Merge tag 'u-boot-stm32-20210409' of https://source.denx.de/u-boot/custodians/u-boot-stm

Add rt-thread art-pi board support based on STM32H750 SoC
Add Engicam i.Core STM32MP1 SoM
Add FIP header support for STM32programmer
Update uart number when no serial device found for STM32MP1
Remove board_check_usb_power function when ADC flag is not set
Update SPL size limitation for STM32MP1
Set soc_type, soc_pkg, soc_rev env variables for STM32MP1
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index a7e27fa..79a0562 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -148,7 +148,7 @@
           export UBOOT_TRAVIS_BUILD_DIR=/tmp/sandbox_spl
           export PYTHONPATH=${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc/pylibfdt
           export PATH=${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc:${PATH}
-          ./tools/buildman/buildman -T0 -o ${UBOOT_TRAVIS_BUILD_DIR} -w sandbox_spl
+          ./tools/buildman/buildman -T0 -o ${UBOOT_TRAVIS_BUILD_DIR} -w --board sandbox_spl
           ./tools/binman/binman --toolpath ${UBOOT_TRAVIS_BUILD_DIR}/tools test
           ./tools/buildman/buildman -t
           ./tools/dtoc/dtoc -t
@@ -187,6 +187,9 @@
         sandbox_spl:
           TEST_PY_BD: "sandbox_spl"
           TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
+        sandbox_noinst:
+          TEST_PY_BD: "sandbox_noinst"
+          TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
         sandbox_flattree:
           TEST_PY_BD: "sandbox_flattree"
         evb_ast2500:
@@ -301,12 +304,12 @@
           grub-mkimage --prefix=\"\" -o ~/grub_x86.efi -O i386-efi normal  echo lsefimmap lsefi lsefisystab efinet tftp minicmd
           grub-mkimage --prefix=\"\" -o ~/grub_x64.efi -O x86_64-efi normal  echo lsefimmap lsefi lsefisystab efinet tftp minicmd
           if [[ "${TEST_PY_BD}" == "qemu-riscv32_spl" ]]; then
-              wget -O - https://github.com/riscv/opensbi/releases/download/v0.8/opensbi-0.8-rv-bin.tar.xz | tar -C /tmp -xJ;
-              export OPENSBI=/tmp/opensbi-0.8-rv-bin/share/opensbi/ilp32/generic/firmware/fw_dynamic.bin;
+              wget -O - https://github.com/riscv/opensbi/releases/download/v0.9/opensbi-0.9-rv-bin.tar.xz | tar -C /tmp -xJ;
+              export OPENSBI=/tmp/opensbi-0.9-rv-bin/share/opensbi/ilp32/generic/firmware/fw_dynamic.bin;
           fi
           if [[ "${TEST_PY_BD}" == "qemu-riscv64_spl" ]]; then
-              wget -O - https://github.com/riscv/opensbi/releases/download/v0.8/opensbi-0.8-rv-bin.tar.xz | tar -C /tmp -xJ;
-              export OPENSBI=/tmp/opensbi-0.8-rv-bin/share/opensbi/lp64/generic/firmware/fw_dynamic.bin;
+              wget -O - https://github.com/riscv/opensbi/releases/download/v0.9/opensbi-0.9-rv-bin.tar.xz | tar -C /tmp -xJ;
+              export OPENSBI=/tmp/opensbi-0.9-rv-bin/share/opensbi/lp64/generic/firmware/fw_dynamic.bin;
           fi
           # the below corresponds to .gitlab-ci.yml "script"
           cd ${WORK_DIR}
@@ -398,7 +401,7 @@
         sun50i:
           BUILDMAN: "sun50i"
         arm_catch_all:
-          BUILDMAN: "arm -x arm11,arm7,arm9,aarch64,at91,bcm,freescale,kirkwood,mvebu,siemens,tegra,uniphier,mx,samsung,sunxi,am33xx,omap,rk,toradex,socfpga,k2,k3,zynq"
+          BUILDMAN: "arm -x arm11,arm7,arm9,aarch64,at91,bcm,freescale,kirkwood,mvebu,renesas,siemens,tegra,uniphier,mx,samsung,sunxi,am33xx,omap,rk,toradex,socfpga,k2,k3,zynq"
         sandbox_x86:
           BUILDMAN: "sandbox x86"
         technexion:
@@ -436,11 +439,11 @@
         uniphier:
           BUILDMAN: "uniphier"
         aarch64_catch_all:
-          BUILDMAN: "aarch64 -x bcm,k3,tegra,ls1,ls2,lx216,mvebu,uniphier,sunxi,samsung,socfpga,rk,versal,zynq"
+          BUILDMAN: "aarch64 -x bcm,k3,tegra,ls1,ls2,lx216,mvebu,uniphier,renesas,sunxi,samsung,socfpga,rk,versal,zynq"
         rockchip:
           BUILDMAN: "rk"
-        sh:
-          BUILDMAN: "sh -x arm"
+        renesas:
+          BUILDMAN: "renesas"
         zynq:
           BUILDMAN: "zynq&armv7"
         zynqmp_versal:
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 4fb9aa1..28f72ab 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -11,7 +11,6 @@
   - world build
 
 .buildman_and_testpy_template: &buildman_and_testpy_dfn
-  tags: [ 'all' ]
   stage: test.py
   before_script:
     # Clone uboot-test-hooks
@@ -21,12 +20,12 @@
     - grub-mkimage --prefix="" -o ~/grub_x86.efi -O i386-efi normal  echo lsefimmap lsefi lsefisystab efinet tftp minicmd
     - grub-mkimage --prefix="" -o ~/grub_x64.efi -O x86_64-efi normal  echo lsefimmap lsefi lsefisystab efinet tftp minicmd
     - if [[ "${TEST_PY_BD}" == "qemu-riscv32_spl" ]]; then
-        wget -O - https://github.com/riscv/opensbi/releases/download/v0.8/opensbi-0.8-rv-bin.tar.xz | tar -C /tmp -xJ;
-        export OPENSBI=/tmp/opensbi-0.8-rv-bin/share/opensbi/ilp32/generic/firmware/fw_dynamic.bin;
+        wget -O - https://github.com/riscv/opensbi/releases/download/v0.9/opensbi-0.9-rv-bin.tar.xz | tar -C /tmp -xJ;
+        export OPENSBI=/tmp/opensbi-0.9-rv-bin/share/opensbi/ilp32/generic/firmware/fw_dynamic.bin;
       fi
     - if [[ "${TEST_PY_BD}" == "qemu-riscv64_spl" ]]; then
-        wget -O - https://github.com/riscv/opensbi/releases/download/v0.8/opensbi-0.8-rv-bin.tar.xz | tar -C /tmp -xJ;
-        export OPENSBI=/tmp/opensbi-0.8-rv-bin/share/opensbi/lp64/generic/firmware/fw_dynamic.bin;
+        wget -O - https://github.com/riscv/opensbi/releases/download/v0.9/opensbi-0.9-rv-bin.tar.xz | tar -C /tmp -xJ;
+        export OPENSBI=/tmp/opensbi-0.9-rv-bin/share/opensbi/lp64/generic/firmware/fw_dynamic.bin;
       fi
 
   after_script:
@@ -53,7 +52,6 @@
         --build-dir "$UBOOT_TRAVIS_BUILD_DIR"
 
 build all 32bit ARM platforms:
-  tags: [ 'all' ]
   stage: world build
   script:
     - ret=0;
@@ -64,7 +62,6 @@
       fi;
 
 build all 64bit ARM platforms:
-  tags: [ 'all' ]
   stage: world build
   script:
     - virtualenv -p /usr/bin/python3 /tmp/venv
@@ -78,7 +75,6 @@
       fi;
 
 build all PowerPC platforms:
-  tags: [ 'all' ]
   stage: world build
   script:
     - ret=0;
@@ -89,7 +85,6 @@
       fi;
 
 build all other platforms:
-  tags: [ 'all' ]
   stage: world build
   script:
     - ret=0;
@@ -102,14 +97,12 @@
 # QA jobs for code analytics
 # static code analysis with cppcheck (we can add --enable=all later)
 cppcheck:
-  tags: [ 'all' ]
   stage: testsuites
   script:
     - cppcheck -j$(nproc) --force --quiet --inline-suppr .
 
 # search for TODO within source tree
 grep TODO/FIXME/HACK:
-  tags: [ 'all' ]
   stage: testsuites
   script:
     - grep -r TODO .
@@ -119,7 +112,6 @@
 
 # build HTML documentation
 htmldocs:
-  tags: [ 'all' ]
   stage: testsuites
   script:
     - virtualenv -p /usr/bin/python3 /tmp/venvhtml
@@ -129,34 +121,29 @@
 
 # some statistics about the code base
 sloccount:
-  tags: [ 'all' ]
   stage: testsuites
   script:
     - sloccount .
 
 # ensure all configs have MAINTAINERS entries
 Check for configs without MAINTAINERS entry:
-  tags: [ 'all' ]
   stage: testsuites
   script:
     - if [ `./tools/genboardscfg.py -f 2>&1 | wc -l` -ne 0 ]; then exit 1; fi
 
 # Ensure host tools build
 Build tools-only:
-  tags: [ 'all' ]
   stage: testsuites
   script:
     - make tools-only_config tools-only -j$(nproc)
 
 # Ensure env tools build
 Build envtools:
-  tags: [ 'all' ]
   stage: testsuites
   script:
     - make tools-only_config envtools -j$(nproc)
 
 Run binman, buildman, dtoc, Kconfig and patman testsuites:
-  tags: [ 'all' ]
   stage: testsuites
   script:
     - git config --global user.name "GitLab CI Runner";
@@ -168,7 +155,8 @@
       export UBOOT_TRAVIS_BUILD_DIR=/tmp/sandbox_spl;
       export PYTHONPATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc/pylibfdt";
       export PATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc:${PATH}";
-      ./tools/buildman/buildman -T0 -o ${UBOOT_TRAVIS_BUILD_DIR} -w sandbox_spl;
+      ./tools/buildman/buildman -T0 -o ${UBOOT_TRAVIS_BUILD_DIR} -w
+        --board sandbox_spl;
       ./tools/binman/binman --toolpath ${UBOOT_TRAVIS_BUILD_DIR}/tools test;
       ./tools/buildman/buildman -t;
       ./tools/dtoc/dtoc -t;
@@ -176,7 +164,6 @@
       make testconfig
 
 Run tests for Nokia RX-51 (aka N900):
-  tags: [ 'all' ]
   stage: testsuites
   script:
     - ./tools/buildman/buildman --fetch-arch arm;
@@ -185,54 +172,53 @@
 
 # Test sandbox with test.py
 sandbox test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "sandbox"
   <<: *buildman_and_testpy_dfn
 
 sandbox with clang test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "sandbox"
     OVERRIDE: "-O clang-10"
   <<: *buildman_and_testpy_dfn
 
 sandbox_spl test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "sandbox_spl"
     TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
   <<: *buildman_and_testpy_dfn
 
-evb-ast2500 test.py:
+sandbox_noinst_test.py:
   tags: [ 'all' ]
   variables:
+    TEST_PY_BD: "sandbox_noinst"
+    TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
+  <<: *buildman_and_testpy_dfn
+
+evb-ast2500 test.py:
+  variables:
     TEST_PY_BD: "evb-ast2500"
     TEST_PY_ID: "--id qemu"
   <<: *buildman_and_testpy_dfn
 
 sandbox_flattree test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "sandbox_flattree"
   <<: *buildman_and_testpy_dfn
 
 vexpress_ca15_tc2 test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "vexpress_ca15_tc2"
     TEST_PY_ID: "--id qemu"
   <<: *buildman_and_testpy_dfn
 
 vexpress_ca9x4 test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "vexpress_ca9x4"
     TEST_PY_ID: "--id qemu"
   <<: *buildman_and_testpy_dfn
 
 integratorcp_cm926ejs test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "integratorcp_cm926ejs"
     TEST_PY_TEST_SPEC: "not sleep"
@@ -240,49 +226,42 @@
   <<: *buildman_and_testpy_dfn
 
 qemu_arm test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "qemu_arm"
     TEST_PY_TEST_SPEC: "not sleep"
   <<: *buildman_and_testpy_dfn
 
 qemu_arm64 test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "qemu_arm64"
     TEST_PY_TEST_SPEC: "not sleep"
   <<: *buildman_and_testpy_dfn
 
 qemu_mips test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "qemu_mips"
     TEST_PY_TEST_SPEC: "not sleep"
   <<: *buildman_and_testpy_dfn
 
 qemu_mipsel test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "qemu_mipsel"
     TEST_PY_TEST_SPEC: "not sleep"
   <<: *buildman_and_testpy_dfn
 
 qemu_mips64 test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "qemu_mips64"
     TEST_PY_TEST_SPEC: "not sleep"
   <<: *buildman_and_testpy_dfn
 
 qemu_mips64el test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "qemu_mips64el"
     TEST_PY_TEST_SPEC: "not sleep"
   <<: *buildman_and_testpy_dfn
 
 qemu_malta test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "malta"
     TEST_PY_TEST_SPEC: "not sleep and not efi"
@@ -290,7 +269,6 @@
   <<: *buildman_and_testpy_dfn
 
 qemu_maltael test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "maltael"
     TEST_PY_TEST_SPEC: "not sleep and not efi"
@@ -298,7 +276,6 @@
   <<: *buildman_and_testpy_dfn
 
 qemu_malta64 test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "malta64"
     TEST_PY_TEST_SPEC: "not sleep and not efi"
@@ -306,7 +283,6 @@
   <<: *buildman_and_testpy_dfn
 
 qemu_malta64el test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "malta64el"
     TEST_PY_TEST_SPEC: "not sleep and not efi"
@@ -314,84 +290,72 @@
   <<: *buildman_and_testpy_dfn
 
 qemu-ppce500 test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "qemu-ppce500"
     TEST_PY_TEST_SPEC: "not sleep"
   <<: *buildman_and_testpy_dfn
 
 qemu-riscv32 test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "qemu-riscv32"
     TEST_PY_TEST_SPEC: "not sleep"
   <<: *buildman_and_testpy_dfn
 
 qemu-riscv64 test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "qemu-riscv64"
     TEST_PY_TEST_SPEC: "not sleep"
   <<: *buildman_and_testpy_dfn
 
 qemu-riscv32_spl test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "qemu-riscv32_spl"
     TEST_PY_TEST_SPEC: "not sleep"
   <<: *buildman_and_testpy_dfn
 
 qemu-riscv64_spl test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "qemu-riscv64_spl"
     TEST_PY_TEST_SPEC: "not sleep"
   <<: *buildman_and_testpy_dfn
 
 qemu-x86 test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "qemu-x86"
     TEST_PY_TEST_SPEC: "not sleep"
   <<: *buildman_and_testpy_dfn
 
 qemu-x86_64 test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "qemu-x86_64"
     TEST_PY_TEST_SPEC: "not sleep"
   <<: *buildman_and_testpy_dfn
 
 r2dplus_i82557c test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "r2dplus"
     TEST_PY_ID: "--id i82557c_qemu"
   <<: *buildman_and_testpy_dfn
 
 r2dplus_pcnet test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "r2dplus"
     TEST_PY_ID: "--id pcnet_qemu"
   <<: *buildman_and_testpy_dfn
 
 r2dplus_rtl8139 test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "r2dplus"
     TEST_PY_ID: "--id rtl8139_qemu"
   <<: *buildman_and_testpy_dfn
 
 r2dplus_tulip test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "r2dplus"
     TEST_PY_ID: "--id tulip_qemu"
   <<: *buildman_and_testpy_dfn
 
 xilinx_zynq_virt test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "xilinx_zynq_virt"
     TEST_PY_TEST_SPEC: "not sleep"
@@ -399,7 +363,6 @@
   <<: *buildman_and_testpy_dfn
 
 xilinx_versal_virt test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "xilinx_versal_virt"
     TEST_PY_TEST_SPEC: "not sleep"
@@ -407,7 +370,6 @@
   <<: *buildman_and_testpy_dfn
 
 xtfpga test.py:
-  tags: [ 'all' ]
   variables:
     TEST_PY_BD: "xtfpga"
     TEST_PY_TEST_SPEC: "not sleep"
diff --git a/Makefile b/Makefile
index 7b526f4..193aa4d 100644
--- a/Makefile
+++ b/Makefile
@@ -17,9 +17,13 @@
 # o Look for make include files relative to root of kernel src
 MAKEFLAGS += -rR --include-dir=$(CURDIR)
 
-# Determine host architecture
+# Determine target architecture for the sandbox
 include include/host_arch.h
-MK_ARCH="${shell uname -m}"
+ifeq ("", "$(CROSS_COMPILE)")
+  MK_ARCH="${shell uname -m}"
+else
+  MK_ARCH="${shell echo $(CROSS_COMPILE) | sed -n 's/^\s*\([^\/]*\/\)*\([^-]*\)-\S*/\2/p'}"
+endif
 unexport HOST_ARCH
 ifeq ("x86_64", $(MK_ARCH))
   export HOST_ARCH=$(HOST_ARCH_X86_64)
@@ -27,7 +31,7 @@
   export HOST_ARCH=$(HOST_ARCH_X86)
 else ifneq (,$(findstring $(MK_ARCH), "aarch64" "armv8l"))
   export HOST_ARCH=$(HOST_ARCH_AARCH64)
-else ifeq ("armv7l", $(MK_ARCH))
+else ifneq (,$(findstring $(MK_ARCH), "arm" "armv7" "armv7l"))
   export HOST_ARCH=$(HOST_ARCH_ARM)
 else ifeq ("riscv32", $(MK_ARCH))
   export HOST_ARCH=$(HOST_ARCH_RISCV32)
@@ -1265,7 +1269,13 @@
 # binman
 # ---------------------------------------------------------------------------
 # Use 'make BINMAN_DEBUG=1' to enable debugging
+# Use 'make BINMAN_VERBOSE=3' to set vebosity level
 default_dt := $(if $(DEVICE_TREE),$(DEVICE_TREE),$(CONFIG_DEFAULT_DEVICE_TREE))
+
+# Tell binman whether we have a devicetree for SPL and TPL
+have_spl_dt := $(if $(CONFIG_SPL_OF_PLATDATA),,$(CONFIG_SPL_OF_CONTROL))
+have_tpl_dt := $(if $(CONFIG_TPL_OF_PLATDATA),,$(CONFIG_TPL_OF_CONTROL))
+
 quiet_cmd_binman = BINMAN  $@
 cmd_binman = $(srctree)/tools/binman/binman $(if $(BINMAN_DEBUG),-D) \
                 --toolpath $(objtree)/tools \
@@ -1276,6 +1286,9 @@
 		-a atf-bl31-path=${BL31} \
 		-a default-dt=$(default_dt) \
 		-a scp-path=$(SCP) \
+		-a spl-bss-pad=$(if $(CONFIG_SPL_SEPARATE_BSS),,1) \
+		-a tpl-bss-pad=$(if $(CONFIG_TPL_SEPARATE_BSS),,1) \
+		-a spl-dtb=$(have_spl_dt) -a tpl-dtb=$(have_tpl_dt) \
 		$(BINMAN_$(@F))
 
 OBJCOPYFLAGS_u-boot.ldr.hex := -I binary -O ihex
@@ -1666,6 +1679,9 @@
 
 ifeq ($(CONFIG_SPL),y)
 spl/u-boot-spl-mtk.bin: spl/u-boot-spl
+
+u-boot-mtk.bin: u-boot-with-spl.bin
+	$(call if_changed,copy)
 else
 MKIMAGEFLAGS_u-boot-mtk.bin = -T mtk_image \
 	-a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE) \
diff --git a/arch/Kconfig b/arch/Kconfig
index 27843cd..7023223 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -142,6 +142,8 @@
 	imply AVB_VERIFY
 	imply LIBAVB
 	imply CMD_AVB
+	imply SCP03
+	imply CMD_SCP03
 	imply UDP_FUNCTION_FASTBOOT
 	imply VIRTIO_MMIO
 	imply VIRTIO_PCI
diff --git a/arch/arc/lib/reset.c b/arch/arc/lib/reset.c
index fbb56ec..b8589d0 100644
--- a/arch/arc/lib/reset.c
+++ b/arch/arc/lib/reset.c
@@ -7,7 +7,7 @@
 #include <common.h>
 #include <cpu_func.h>
 
-__weak void reset_cpu(ulong addr)
+__weak void reset_cpu(void)
 {
 	/* Stop debug session here */
 	__builtin_arc_brk();
@@ -17,7 +17,7 @@
 {
 	printf("Resetting the board...\n");
 
-	reset_cpu(0);
+	reset_cpu();
 
 	return 0;
 }
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 3307f2b..76adf7f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -839,6 +839,9 @@
 config ARCH_IMX8M
 	bool "NXP i.MX8M platform"
 	select ARM64
+	select SYS_FSL_HAS_SEC if IMX_HAB
+	select SYS_FSL_SEC_COMPAT_4
+	select SYS_FSL_SEC_LE
 	select DM
 	select SUPPORT_SPL
 	imply CMD_DM
@@ -875,6 +878,9 @@
 config ARCH_MX7ULP
 	bool "NXP MX7ULP"
 	select CPU_V7A
+	select SYS_FSL_HAS_SEC if IMX_HAB
+	select SYS_FSL_SEC_COMPAT_4
+	select SYS_FSL_SEC_LE
 	select ROM_UNIFIED_SECTIONS
 	imply MXC_GPIO
 	imply SYS_THUMB_BUILD
diff --git a/arch/arm/cpu/arm920t/ep93xx/cpu.c b/arch/arm/cpu/arm920t/ep93xx/cpu.c
index c9ea4e4..3435bdc 100644
--- a/arch/arm/cpu/arm920t/ep93xx/cpu.c
+++ b/arch/arm/cpu/arm920t/ep93xx/cpu.c
@@ -14,7 +14,7 @@
 #include <asm/io.h>
 
 /* We reset the CPU by generating a 1-->0 transition on DeviceCfg bit 31. */
-extern void reset_cpu(ulong addr)
+extern void reset_cpu(void)
 {
 	struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
 	uint32_t value;
diff --git a/arch/arm/cpu/arm920t/imx/timer.c b/arch/arm/cpu/arm920t/imx/timer.c
index e9d5577..0cd3a03 100644
--- a/arch/arm/cpu/arm920t/imx/timer.c
+++ b/arch/arm/cpu/arm920t/imx/timer.c
@@ -81,7 +81,7 @@
 /*
  * Reset the cpu by setting up the watchdog timer and let him time out
  */
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 	/* Disable watchdog and set Time-Out field to 0 */
 	WCR = 0x00000000;
diff --git a/arch/arm/cpu/arm926ejs/armada100/timer.c b/arch/arm/cpu/arm926ejs/armada100/timer.c
index ec73393..6d77ad3 100644
--- a/arch/arm/cpu/arm926ejs/armada100/timer.c
+++ b/arch/arm/cpu/arm926ejs/armada100/timer.c
@@ -142,7 +142,7 @@
  * 2. Write key value to TMP_WSAR reg.
  * 3. Perform write operation.
  */
-void reset_cpu(unsigned long ignored)
+void reset_cpu(void)
 {
 	struct armd1mpmu_registers *mpmu =
 		(struct armd1mpmu_registers *) ARMD1_MPMU_BASE;
diff --git a/arch/arm/cpu/arm926ejs/mx25/reset.c b/arch/arm/cpu/arm926ejs/mx25/reset.c
index 38df1c9..7844a99 100644
--- a/arch/arm/cpu/arm926ejs/mx25/reset.c
+++ b/arch/arm/cpu/arm926ejs/mx25/reset.c
@@ -23,7 +23,7 @@
 /*
  * Reset the cpu by setting up the watchdog timer and let it time out
  */
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 	struct wdog_regs *regs = (struct wdog_regs *)IMX_WDT_BASE;
 	/* Disable watchdog and set Time-Out field to 0 */
diff --git a/arch/arm/cpu/arm926ejs/mx27/reset.c b/arch/arm/cpu/arm926ejs/mx27/reset.c
index 320b0a6..496fb30 100644
--- a/arch/arm/cpu/arm926ejs/mx27/reset.c
+++ b/arch/arm/cpu/arm926ejs/mx27/reset.c
@@ -23,7 +23,7 @@
 /*
  * Reset the cpu by setting up the watchdog timer and let it time out
  */
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 	struct wdog_regs *regs = (struct wdog_regs *)IMX_WDT_BASE;
 	/* Disable watchdog and set Time-Out field to 0 */
diff --git a/arch/arm/cpu/arm926ejs/mxs/mxs.c b/arch/arm/cpu/arm926ejs/mxs/mxs.c
index c936213..344b9b4 100644
--- a/arch/arm/cpu/arm926ejs/mxs/mxs.c
+++ b/arch/arm/cpu/arm926ejs/mxs/mxs.c
@@ -32,9 +32,9 @@
 /* Lowlevel init isn't used on i.MX28, so just have a dummy here */
 __weak void lowlevel_init(void) {}
 
-void reset_cpu(ulong ignored) __attribute__((noreturn));
+void reset_cpu(void) __attribute__((noreturn));
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 	struct mxs_rtc_regs *rtc_regs =
 		(struct mxs_rtc_regs *)MXS_RTC_BASE;
diff --git a/arch/arm/cpu/arm926ejs/spear/reset.c b/arch/arm/cpu/arm926ejs/spear/reset.c
index a316540..97a624e 100644
--- a/arch/arm/cpu/arm926ejs/spear/reset.c
+++ b/arch/arm/cpu/arm926ejs/spear/reset.c
@@ -11,7 +11,7 @@
 #include <asm/arch/spr_syscntl.h>
 #include <linux/delay.h>
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 	struct syscntl_regs *syscntl_regs_p =
 	    (struct syscntl_regs *)CONFIG_SPEAR_SYSCNTLBASE;
diff --git a/arch/arm/cpu/arm946es/cpu.c b/arch/arm/cpu/arm946es/cpu.c
index fb0ea5e..334bb54 100644
--- a/arch/arm/cpu/arm946es/cpu.c
+++ b/arch/arm/cpu/arm946es/cpu.c
@@ -56,7 +56,7 @@
 
 #ifndef CONFIG_ARCH_INTEGRATOR
 
-__attribute__((noreturn)) void reset_cpu(ulong addr __attribute__((unused)))
+__attribute__((noreturn)) void reset_cpu(void)
 {
 	writew(0x0, 0xfffece10);
 	writew(0x8, 0xfffece10);
diff --git a/arch/arm/cpu/armv7/bcm281xx/reset.c b/arch/arm/cpu/armv7/bcm281xx/reset.c
index fda5a95..1491e5c 100644
--- a/arch/arm/cpu/armv7/bcm281xx/reset.c
+++ b/arch/arm/cpu/armv7/bcm281xx/reset.c
@@ -13,7 +13,7 @@
 #define CLKS_SHIFT	20		/* Clock period shift */
 #define LD_SHIFT	0		/* Reload value shift */
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 	/*
 	 * Set WD enable, RST enable,
diff --git a/arch/arm/cpu/armv7/bcmcygnus/reset.c b/arch/arm/cpu/armv7/bcmcygnus/reset.c
index 3bfed34..63992fd 100644
--- a/arch/arm/cpu/armv7/bcmcygnus/reset.c
+++ b/arch/arm/cpu/armv7/bcmcygnus/reset.c
@@ -10,7 +10,7 @@
 #define CRMU_MAIL_BOX1		0x03024028
 #define CRMU_SOFT_RESET_CMD	0xFFFFFFFF
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 	/* Send soft reset command via Mailbox. */
 	writel(CRMU_SOFT_RESET_CMD, CRMU_MAIL_BOX1);
diff --git a/arch/arm/cpu/armv7/bcmnsp/reset.c b/arch/arm/cpu/armv7/bcmnsp/reset.c
index 675f99f..a313775 100644
--- a/arch/arm/cpu/armv7/bcmnsp/reset.c
+++ b/arch/arm/cpu/armv7/bcmnsp/reset.c
@@ -9,7 +9,7 @@
 
 #define CRU_RESET_OFFSET	0x1803F184
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 	/* Reset the cpu by setting software reset request bit */
 	writel(0x1, CRU_RESET_OFFSET);
diff --git a/arch/arm/cpu/armv7/cache_v7.c b/arch/arm/cpu/armv7/cache_v7.c
index 146cf52..19ff432 100644
--- a/arch/arm/cpu/armv7/cache_v7.c
+++ b/arch/arm/cpu/armv7/cache_v7.c
@@ -176,9 +176,6 @@
 {
 }
 
-void arm_init_domains(void)
-{
-}
 #endif /* #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) */
 
 #if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
diff --git a/arch/arm/cpu/armv7/ls102xa/cpu.c b/arch/arm/cpu/armv7/ls102xa/cpu.c
index f26a5b2..d863c96 100644
--- a/arch/arm/cpu/armv7/ls102xa/cpu.c
+++ b/arch/arm/cpu/armv7/ls102xa/cpu.c
@@ -375,7 +375,7 @@
 }
 #endif
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
 
diff --git a/arch/arm/cpu/armv7/s5p4418/cpu.c b/arch/arm/cpu/armv7/s5p4418/cpu.c
index 3c71a37..3baa761 100644
--- a/arch/arm/cpu/armv7/s5p4418/cpu.c
+++ b/arch/arm/cpu/armv7/s5p4418/cpu.c
@@ -88,7 +88,7 @@
 }
 #endif
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 	void *clkpwr_reg = (void *)PHY_BASEADDR_CLKPWR;
 	const u32 sw_rst_enb_bitpos = 3;
diff --git a/arch/arm/cpu/armv7/stv0991/reset.c b/arch/arm/cpu/armv7/stv0991/reset.c
index fb67de1..77d4477 100644
--- a/arch/arm/cpu/armv7/stv0991/reset.c
+++ b/arch/arm/cpu/armv7/stv0991/reset.c
@@ -9,7 +9,7 @@
 #include <asm/io.h>
 #include <asm/arch/stv0991_wdru.h>
 #include <linux/delay.h>
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 	puts("System is going to reboot ...\n");
 	/*
diff --git a/arch/arm/cpu/armv7m/cpu.c b/arch/arm/cpu/armv7m/cpu.c
index 7f827da..6372101 100644
--- a/arch/arm/cpu/armv7m/cpu.c
+++ b/arch/arm/cpu/armv7m/cpu.c
@@ -47,7 +47,7 @@
 /*
  * Perform the low-level reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	/*
 	 * Perform reset but keep priority group unchanged.
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
index ae0b7b2..9d1ba4c 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
@@ -47,6 +47,8 @@
 	select SYS_FSL_ERRATUM_A009663 if !TFABOOT
 	select SYS_FSL_ERRATUM_A009942 if !TFABOOT
 	select SYS_FSL_ERRATUM_A050382
+	select SYS_FSL_ERRATUM_A011334
+	select SYS_FSL_ESDHC_UNRELIABLE_PULSE_DETECTION_WORKAROUND
 	select RESV_RAM if GIC_V3_ITS
 	imply PANIC_HANG
 
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
index 3a5bf77..270a72e 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
@@ -1231,7 +1231,7 @@
 
 __efi_runtime_data u32 __iomem *rstcr = (u32 *)CONFIG_SYS_FSL_RST_ADDR;
 
-void __efi_runtime reset_cpu(ulong addr)
+void __efi_runtime reset_cpu(void)
 {
 #if defined(CONFIG_ARCH_LX2160A) || defined(CONFIG_ARCH_LX2162A)
 	/* clear the RST_REQ_MSK and SW_RST_REQ */
@@ -1260,7 +1260,7 @@
 	case EFI_RESET_COLD:
 	case EFI_RESET_WARM:
 	case EFI_RESET_PLATFORM_SPECIFIC:
-		reset_cpu(0);
+		reset_cpu();
 		break;
 	case EFI_RESET_SHUTDOWN:
 		/* Nothing we can do */
diff --git a/arch/arm/cpu/armv8/s32v234/generic.c b/arch/arm/cpu/armv8/s32v234/generic.c
index 0fc9885..d1ae10b 100644
--- a/arch/arm/cpu/armv8/s32v234/generic.c
+++ b/arch/arm/cpu/armv8/s32v234/generic.c
@@ -319,7 +319,7 @@
 
 #define SRC_SCR_SW_RST					(1<<12)
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	printf("Feature not supported.\n");
 };
diff --git a/arch/arm/cpu/pxa/pxa2xx.c b/arch/arm/cpu/pxa/pxa2xx.c
index ea91d8a..c7efb67 100644
--- a/arch/arm/cpu/pxa/pxa2xx.c
+++ b/arch/arm/cpu/pxa/pxa2xx.c
@@ -267,9 +267,9 @@
 	writel(readl(CKEN) | CKEN14_I2C, CKEN);
 }
 
-void __attribute__((weak)) reset_cpu(ulong ignored) __attribute__((noreturn));
+void __attribute__((weak)) reset_cpu(void) __attribute__((noreturn));
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 	uint32_t tmp;
 
diff --git a/arch/arm/cpu/sa1100/cpu.c b/arch/arm/cpu/sa1100/cpu.c
index 91e100a..6f67f7f 100644
--- a/arch/arm/cpu/sa1100/cpu.c
+++ b/arch/arm/cpu/sa1100/cpu.c
@@ -55,7 +55,7 @@
 #define RSRR	0x00
 #define RCSR	0x04
 
-__attribute__((noreturn)) void reset_cpu(ulong addr __attribute__((unused)))
+__attribute__((noreturn)) void reset_cpu(void)
 {
 	/* repeat endlessly */
 	while (1) {
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 5543ab7..c09ce8f 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -114,7 +114,7 @@
 	rk3328-rock-pi-e.dtb
 
 dtb-$(CONFIG_ROCKCHIP_RK3368) += \
-	rk3368-lion.dtb \
+	rk3368-lion-haikou.dtb \
 	rk3368-sheep.dtb \
 	rk3368-geekbox.dtb \
 	rk3368-px5-evb.dtb \
@@ -131,7 +131,9 @@
 	rk3399-nanopc-t4.dtb \
 	rk3399-nanopi-m4.dtb \
 	rk3399-nanopi-m4-2gb.dtb \
+	rk3399-nanopi-m4b.dtb \
 	rk3399-nanopi-neo4.dtb \
+	rk3399-nanopi-r4s.dtb \
 	rk3399-orangepi.dtb \
 	rk3399-pinebook-pro.dtb \
 	rk3399-puma-haikou.dtb \
@@ -652,6 +654,9 @@
 dtb-$(CONFIG_MX23) += \
 	imx23-evk.dtb
 
+dtb-$(CONFIG_TARGET_MX23_OLINUXINO) += \
+	imx23-olinuxino.dtb
+
 dtb-$(CONFIG_MX28) += \
 	imx28-xea.dtb
 
@@ -661,7 +666,8 @@
 dtb-$(CONFIG_MX53) += imx53-cx9020.dtb \
 	imx53-qsb.dtb \
 	imx53-kp.dtb \
-	imx53-m53menlo.dtb
+	imx53-m53menlo.dtb \
+	imx53-usbarmory.dtb
 
 ifneq ($(CONFIG_MX6DL)$(CONFIG_MX6QDL)$(CONFIG_MX6S),)
 dtb-y += \
@@ -672,6 +678,20 @@
 	imx6dl-cubox-i-emmc-som-v15.dtb \
 	imx6dl-cubox-i-som-v15.dtb \
 	imx6dl-dhcom-pdk2.dtb \
+	imx6dl-gw51xx.dtb \
+	imx6dl-gw52xx.dtb \
+	imx6dl-gw53xx.dtb \
+	imx6dl-gw54xx.dtb \
+	imx6dl-gw551x.dtb \
+	imx6dl-gw552x.dtb \
+	imx6dl-gw553x.dtb \
+	imx6dl-gw560x.dtb \
+	imx6dl-gw5903.dtb \
+	imx6dl-gw5904.dtb \
+	imx6dl-gw5907.dtb \
+	imx6dl-gw5910.dtb \
+	imx6dl-gw5912.dtb \
+	imx6dl-gw5913.dtb \
 	imx6dl-hummingboard2.dtb \
 	imx6dl-hummingboard2-emmc-som-v15.dtb \
 	imx6dl-hummingboard2-som-v15.dtb \
@@ -686,6 +706,8 @@
 	imx6dl-mamoj.dtb \
 	imx6dl-nitrogen6x.dtb \
 	imx6dl-pico.dtb \
+	imx6dl-udoo.dtb \
+	imx6dl-riotboard.dtb \
 	imx6dl-sabreauto.dtb \
 	imx6dl-sabresd.dtb \
 	imx6dl-wandboard-revd1.dtb \
@@ -701,6 +723,20 @@
 	imx6q-cubox-i-som-v15.dtb \
 	imx6q-dhcom-pdk2.dtb \
 	imx6q-display5.dtb \
+	imx6q-gw51xx.dtb \
+	imx6q-gw52xx.dtb \
+	imx6q-gw53xx.dtb \
+	imx6q-gw54xx.dtb \
+	imx6q-gw551x.dtb \
+	imx6q-gw552x.dtb \
+	imx6q-gw553x.dtb \
+	imx6q-gw560x.dtb \
+	imx6q-gw5903.dtb \
+	imx6q-gw5904.dtb \
+	imx6q-gw5907.dtb \
+	imx6q-gw5910.dtb \
+	imx6q-gw5912.dtb \
+	imx6q-gw5913.dtb \
 	imx6q-hummingboard2.dtb \
 	imx6q-hummingboard2-emmc-som-v15.dtb \
 	imx6q-hummingboard2-som-v15.dtb \
@@ -712,6 +748,7 @@
 	imx6q-icore-rqs.dtb \
 	imx6q-kp.dtb \
 	imx6q-logicpd.dtb \
+	imx6q-marsboard.dtb \
 	imx6q-mba6a.dtb \
 	imx6q-mba6b.dtb \
 	imx6q-mccmon6.dtb\
@@ -719,6 +756,7 @@
 	imx6q-novena.dtb \
 	imx6q-pico.dtb \
 	imx6q-phytec-mira-rdk-nand.dtb \
+	imx6q-udoo.dtb \
 	imx6q-sabreauto.dtb \
 	imx6q-sabrelite.dtb \
 	imx6q-sabresd.dtb \
@@ -798,6 +836,7 @@
 	imx8mm-verdin.dtb \
 	phycore-imx8mm.dtb \
 	imx8mn-ddr4-evk.dtb \
+	imx8mn-evk.dtb \
 	imx8mq-evk.dtb \
 	imx8mm-beacon-kit.dtb \
 	imx8mn-beacon-kit.dtb \
@@ -823,6 +862,10 @@
 	r8a774a1-beacon-rzg2m-kit.dtb \
 	r8a774b1-beacon-rzg2n-kit.dtb \
 	r8a774e1-beacon-rzg2h-kit.dtb \
+	r8a774a1-hihope-rzg2m-u-boot.dtb \
+	r8a774b1-hihope-rzg2n-u-boot.dtb \
+	r8a774c0-ek874-u-boot.dtb \
+	r8a774e1-hihope-rzg2h-u-boot.dtb \
 	r8a77950-ulcb-u-boot.dtb \
 	r8a77950-salvator-x-u-boot.dtb \
 	r8a77960-ulcb-u-boot.dtb \
@@ -1014,6 +1057,7 @@
 	mt7622-bananapi-bpi-r64.dtb \
 	mt7623n-bananapi-bpi-r2.dtb \
 	mt7629-rfb.dtb \
+	mt8183-pumpkin.dtb \
 	mt8512-bm1-emmc.dtb \
 	mt8516-pumpkin.dtb \
 	mt8518-ap1-emmc.dtb
diff --git a/arch/arm/dts/bitmain-antminer-s9.dts b/arch/arm/dts/bitmain-antminer-s9.dts
index 7362ad4..0694350 100644
--- a/arch/arm/dts/bitmain-antminer-s9.dts
+++ b/arch/arm/dts/bitmain-antminer-s9.dts
@@ -50,6 +50,14 @@
 	ps-clk-frequency = <33333333>;
 };
 
+&nand0 {
+	status = "okay";
+};
+
+&smcc {
+	status = "okay";
+};
+
 &gem0 {
 	status = "okay";
 	phy-mode = "rgmii-id";
diff --git a/arch/arm/dts/cat875.dtsi b/arch/arm/dts/cat875.dtsi
new file mode 100644
index 0000000..4a2f6fa
--- /dev/null
+++ b/arch/arm/dts/cat875.dtsi
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the Silicon Linux sub board for CAT874 (CAT875)
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+/ {
+	model = "Silicon Linux sub board for CAT874 (CAT875)";
+
+	aliases {
+		ethernet0 = &avb;
+	};
+};
+
+&avb {
+	pinctrl-0 = <&avb_pins>;
+	pinctrl-names = "default";
+	renesas,no-ether-link;
+	phy-handle = <&phy0>;
+	status = "okay";
+
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+		interrupt-parent = <&gpio2>;
+		interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
+		reset-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&can0 {
+	pinctrl-0 = <&can0_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&can1 {
+	pinctrl-0 = <&can1_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&pciec0 {
+	status = "okay";
+};
+
+&pfc {
+	avb_pins: avb {
+		mux {
+			groups = "avb_mii";
+			function = "avb";
+		};
+	};
+
+	can0_pins: can0 {
+		groups = "can0_data";
+		function = "can0";
+	};
+
+	can1_pins: can1 {
+		groups = "can1_data";
+		function = "can1";
+	};
+};
diff --git a/arch/arm/dts/imx23-olinuxino-u-boot.dtsi b/arch/arm/dts/imx23-olinuxino-u-boot.dtsi
new file mode 100644
index 0000000..dee8433
--- /dev/null
+++ b/arch/arm/dts/imx23-olinuxino-u-boot.dtsi
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+&ssp0 {
+	non-removable;
+};
diff --git a/arch/arm/dts/imx23-olinuxino.dts b/arch/arm/dts/imx23-olinuxino.dts
new file mode 100644
index 0000000..0729e72
--- /dev/null
+++ b/arch/arm/dts/imx23-olinuxino.dts
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include "imx23.dtsi"
+
+/ {
+	model = "i.MX23 Olinuxino Low Cost Board";
+	compatible = "olimex,imx23-olinuxino", "fsl,imx23";
+
+	memory@40000000 {
+		device_type = "memory";
+		reg = <0x40000000 0x04000000>;
+	};
+
+	apb@80000000 {
+		apbh@80000000 {
+			ssp0: spi@80010000 {
+				compatible = "fsl,imx23-mmc";
+				pinctrl-names = "default";
+				pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_sck_cfg>;
+				bus-width = <4>;
+				broken-cd;
+				status = "okay";
+			};
+
+			pinctrl@80018000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&hog_pins_a>;
+
+				hog_pins_a: hog@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX23_PAD_GPMI_ALE__GPIO_0_17
+					>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+				};
+
+				led_pin_gpio2_1: led_gpio2_1@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX23_PAD_SSP1_DETECT__GPIO_2_1
+					>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+				};
+			};
+
+			ssp1: spi@80034000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx23-spi";
+				pinctrl-names = "default";
+				pinctrl-0 = <&spi2_pins_a>;
+				status = "okay";
+			};
+		};
+
+		apbx@80040000 {
+			lradc@80050000 {
+				status = "okay";
+			};
+
+			i2c: i2c@80058000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&i2c_pins_b>;
+				status = "okay";
+			};
+
+			duart: serial@80070000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&duart_pins_a>;
+				status = "okay";
+			};
+
+			auart0: serial@8006c000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&auart0_2pins_a>;
+				status = "okay";
+			};
+
+			usbphy0: usbphy@8007c000 {
+				status = "okay";
+			};
+		};
+	};
+
+	ahb@80080000 {
+		usb0: usb@80080000 {
+			dr_mode = "host";
+			vbus-supply = <&reg_usb0_vbus>;
+			status = "okay";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_usb0_vbus: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "usb0_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			startup-delay-us = <300>; /* LAN9215 requires a POR of 200us minimum */
+			gpio = <&gpio0 17 0>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pin_gpio2_1>;
+
+		user {
+			label = "green";
+			gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
+		};
+	};
+};
diff --git a/arch/arm/dts/imx53-usbarmory.dts b/arch/arm/dts/imx53-usbarmory.dts
new file mode 100644
index 0000000..f34993a
--- /dev/null
+++ b/arch/arm/dts/imx53-usbarmory.dts
@@ -0,0 +1,225 @@
+/*
+ * USB armory MkI device tree file
+ * https://inversepath.com/usbarmory
+ *
+ * Copyright (C) 2015, Inverse Path
+ * Andrej Rosano <andrej@inversepath.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx53.dtsi"
+
+/ {
+	model = "Inverse Path USB armory";
+	compatible = "inversepath,imx53-usbarmory", "fsl,imx53";
+};
+
+/ {
+	chosen {
+		stdout-path = &uart1;
+	};
+
+	memory@70000000 {
+		device_type = "memory";
+		reg = <0x70000000 0x20000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_led>;
+
+		user {
+			label = "LED";
+			gpios = <&gpio4 27 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
+
+/*
+ * Not every i.MX53 P/N supports clock > 800MHz.
+ * As USB armory does not mount a specific P/N set a safe clock upper limit.
+ */
+&cpu0 {
+	operating-points = <
+		/* kHz */
+		166666  850000
+		400000  900000
+		800000 1050000
+	>;
+};
+
+&esdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc1>;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl_esdhc1: esdhc1grp {
+		fsl,pins = <
+			MX53_PAD_SD1_DATA0__ESDHC1_DAT0		0x1d5
+			MX53_PAD_SD1_DATA1__ESDHC1_DAT1		0x1d5
+			MX53_PAD_SD1_DATA2__ESDHC1_DAT2		0x1d5
+			MX53_PAD_SD1_DATA3__ESDHC1_DAT3		0x1d5
+			MX53_PAD_SD1_CMD__ESDHC1_CMD		0x1d5
+			MX53_PAD_SD1_CLK__ESDHC1_CLK		0x1d5
+		>;
+	};
+
+	pinctrl_i2c1_pmic: i2c1grp {
+		fsl,pins = <
+			MX53_PAD_EIM_D21__I2C1_SCL	0x80
+			MX53_PAD_EIM_D28__I2C1_SDA	0x80
+		>;
+	};
+
+	pinctrl_led: ledgrp {
+		fsl,pins = <
+			MX53_PAD_DISP0_DAT6__GPIO4_27 0x1e4
+		>;
+	};
+
+	/*
+	 * UART mode pin header configuration
+	 * 3 - GPIO5[26], pull-down 100K
+	 * 4 - GPIO5[27], pull-down 100K
+	 * 5 - TX, pull-up 100K
+	 * 6 - RX, pull-up 100K
+	 * 7 - GPIO5[30], pull-down 100K
+	 */
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX53_PAD_CSI0_DAT8__GPIO5_26		0xc0
+			MX53_PAD_CSI0_DAT9__GPIO5_27		0xc0
+			MX53_PAD_CSI0_DAT10__UART1_TXD_MUX	0x1e4
+			MX53_PAD_CSI0_DAT11__UART1_RXD_MUX	0x1e4
+			MX53_PAD_CSI0_DAT12__GPIO5_30		0xc0
+		>;
+	};
+};
+
+&i2c1 {
+	pinctrl-0 = <&pinctrl_i2c1_pmic>;
+	status = "okay";
+
+	ltc3589: pmic@34 {
+		compatible = "lltc,ltc3589-2";
+		reg = <0x34>;
+
+		regulators {
+			sw1_reg: sw1 {
+				regulator-min-microvolt = <591930>;
+				regulator-max-microvolt = <1224671>;
+				lltc,fb-voltage-divider = <100000 158000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <704123>;
+				regulator-max-microvolt = <1456803>;
+				lltc,fb-voltage-divider = <180000 191000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3_reg: sw3 {
+				regulator-min-microvolt = <1341250>;
+				regulator-max-microvolt = <2775000>;
+				lltc,fb-voltage-divider = <270000 100000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			bb_out_reg: bb-out {
+				regulator-min-microvolt = <3387341>;
+				regulator-max-microvolt = <3387341>;
+				lltc,fb-voltage-divider = <511000 158000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo1_reg: ldo1 {
+				regulator-min-microvolt = <1306329>;
+				regulator-max-microvolt = <1306329>;
+				lltc,fb-voltage-divider = <100000 158000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo2_reg: ldo2 {
+				regulator-min-microvolt = <704123>;
+				regulator-max-microvolt = <1456806>;
+				lltc,fb-voltage-divider = <180000 191000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo3_reg: ldo3 {
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+				regulator-boot-on;
+			};
+
+			ldo4_reg: ldo4 {
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <3200000>;
+			};
+		};
+	};
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&usbotg {
+	dr_mode = "peripheral";
+	status = "okay";
+};
diff --git a/arch/arm/dts/imx6dl-gw51xx.dts b/arch/arm/dts/imx6dl-gw51xx.dts
new file mode 100644
index 0000000..9956d12
--- /dev/null
+++ b/arch/arm/dts/imx6dl-gw51xx.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2013 Gateworks Corporation
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw51xx.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 DualLite/Solo GW51XX";
+	compatible = "gw,imx6dl-gw51xx", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/dts/imx6dl-gw52xx.dts b/arch/arm/dts/imx6dl-gw52xx.dts
new file mode 100644
index 0000000..9ea23dd
--- /dev/null
+++ b/arch/arm/dts/imx6dl-gw52xx.dts
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2013 Gateworks Corporation
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw52xx.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 DualLite/Solo GW52XX";
+	compatible = "gw,imx6dl-gw52xx", "gw,ventana", "fsl,imx6dl";
+};
+
+&i2c3 {
+	adv7180: camera@20 {
+		compatible = "adi,adv7180";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_adv7180>;
+		reg = <0x20>;
+		powerdown-gpios = <&gpio3 31 GPIO_ACTIVE_LOW>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <30 IRQ_TYPE_LEVEL_LOW>;
+
+		port {
+			adv7180_to_ipu1_csi1_mux: endpoint {
+				remote-endpoint = <&ipu1_csi1_mux_from_parallel_sensor>;
+				bus-width = <8>;
+			};
+		};
+	};
+};
+
+&ipu1_csi1_from_ipu1_csi1_mux {
+	bus-width = <8>;
+};
+
+&ipu1_csi1_mux_from_parallel_sensor {
+	remote-endpoint = <&adv7180_to_ipu1_csi1_mux>;
+	bus-width = <8>;
+};
+
+&ipu1_csi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ipu1_csi1>;
+};
+
+&iomuxc {
+	pinctrl_adv7180: adv7180grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D30__GPIO3_IO30          0x0001b0b0
+			MX6QDL_PAD_EIM_D31__GPIO3_IO31          0x4001b0b0
+		>;
+	};
+
+	pinctrl_ipu1_csi1: ipu1_csi1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_EB2__IPU1_CSI1_DATA19    0x1b0b0
+			MX6QDL_PAD_EIM_D16__IPU1_CSI1_DATA18    0x1b0b0
+			MX6QDL_PAD_EIM_D18__IPU1_CSI1_DATA17    0x1b0b0
+			MX6QDL_PAD_EIM_D19__IPU1_CSI1_DATA16    0x1b0b0
+			MX6QDL_PAD_EIM_D20__IPU1_CSI1_DATA15    0x1b0b0
+			MX6QDL_PAD_EIM_D26__IPU1_CSI1_DATA14    0x1b0b0
+			MX6QDL_PAD_EIM_D27__IPU1_CSI1_DATA13    0x1b0b0
+			MX6QDL_PAD_EIM_A17__IPU1_CSI1_DATA12    0x1b0b0
+			MX6QDL_PAD_EIM_D29__IPU1_CSI1_VSYNC     0x1b0b0
+			MX6QDL_PAD_EIM_EB3__IPU1_CSI1_HSYNC     0x1b0b0
+			MX6QDL_PAD_EIM_A16__IPU1_CSI1_PIXCLK    0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6dl-gw53xx.dts b/arch/arm/dts/imx6dl-gw53xx.dts
new file mode 100644
index 0000000..182e819
--- /dev/null
+++ b/arch/arm/dts/imx6dl-gw53xx.dts
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2013 Gateworks Corporation
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw53xx.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 DualLite/Solo GW53XX";
+	compatible = "gw,imx6dl-gw53xx", "gw,ventana", "fsl,imx6dl";
+};
+
+&i2c3 {
+	adv7180: camera@20 {
+		compatible = "adi,adv7180";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_adv7180>;
+		reg = <0x20>;
+		powerdown-gpios = <&gpio3 31 GPIO_ACTIVE_LOW>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <30 IRQ_TYPE_LEVEL_LOW>;
+
+		port {
+			adv7180_to_ipu1_csi1_mux: endpoint {
+				remote-endpoint = <&ipu1_csi1_mux_from_parallel_sensor>;
+				bus-width = <8>;
+			};
+		};
+	};
+};
+
+&ipu1_csi1_from_ipu1_csi1_mux {
+	bus-width = <8>;
+};
+
+&ipu1_csi1_mux_from_parallel_sensor {
+	remote-endpoint = <&adv7180_to_ipu1_csi1_mux>;
+	bus-width = <8>;
+};
+
+&ipu1_csi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ipu1_csi1>;
+};
+
+&iomuxc {
+	pinctrl_adv7180: adv7180grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D30__GPIO3_IO30          0x0001b0b0
+			MX6QDL_PAD_EIM_D31__GPIO3_IO31          0x4001b0b0
+		>;
+	};
+
+	pinctrl_ipu1_csi1: ipu1_csi1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_EB2__IPU1_CSI1_DATA19    0x1b0b0
+			MX6QDL_PAD_EIM_D16__IPU1_CSI1_DATA18    0x1b0b0
+			MX6QDL_PAD_EIM_D18__IPU1_CSI1_DATA17    0x1b0b0
+			MX6QDL_PAD_EIM_D19__IPU1_CSI1_DATA16    0x1b0b0
+			MX6QDL_PAD_EIM_D20__IPU1_CSI1_DATA15    0x1b0b0
+			MX6QDL_PAD_EIM_D26__IPU1_CSI1_DATA14    0x1b0b0
+			MX6QDL_PAD_EIM_D27__IPU1_CSI1_DATA13    0x1b0b0
+			MX6QDL_PAD_EIM_A17__IPU1_CSI1_DATA12    0x1b0b0
+			MX6QDL_PAD_EIM_D29__IPU1_CSI1_VSYNC     0x1b0b0
+			MX6QDL_PAD_EIM_EB3__IPU1_CSI1_HSYNC     0x1b0b0
+			MX6QDL_PAD_EIM_A16__IPU1_CSI1_PIXCLK    0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6dl-gw54xx.dts b/arch/arm/dts/imx6dl-gw54xx.dts
new file mode 100644
index 0000000..a106c4e
--- /dev/null
+++ b/arch/arm/dts/imx6dl-gw54xx.dts
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2013 Gateworks Corporation
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw54xx.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 DualLite/Solo GW54XX";
+	compatible = "gw,imx6dl-gw54xx", "gw,ventana", "fsl,imx6dl";
+};
+
+&i2c3 {
+	adv7180: camera@20 {
+		compatible = "adi,adv7180";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_adv7180>;
+		reg = <0x20>;
+		powerdown-gpios = <&gpio3 31 GPIO_ACTIVE_LOW>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <30 IRQ_TYPE_LEVEL_LOW>;
+
+		port {
+			adv7180_to_ipu1_csi1_mux: endpoint {
+				remote-endpoint = <&ipu1_csi1_mux_from_parallel_sensor>;
+				bus-width = <8>;
+			};
+		};
+	};
+};
+
+&ipu1_csi1_from_ipu1_csi1_mux {
+	bus-width = <8>;
+};
+
+&ipu1_csi1_mux_from_parallel_sensor {
+	remote-endpoint = <&adv7180_to_ipu1_csi1_mux>;
+	bus-width = <8>;
+};
+
+&ipu1_csi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ipu1_csi1>;
+};
+
+&iomuxc {
+	pinctrl_adv7180: adv7180grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D30__GPIO3_IO30          0x0001b0b0
+			MX6QDL_PAD_EIM_D31__GPIO3_IO31          0x4001b0b0
+		>;
+	};
+
+	pinctrl_ipu1_csi1: ipu1_csi1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_EB2__IPU1_CSI1_DATA19    0x1b0b0
+			MX6QDL_PAD_EIM_D16__IPU1_CSI1_DATA18    0x1b0b0
+			MX6QDL_PAD_EIM_D18__IPU1_CSI1_DATA17    0x1b0b0
+			MX6QDL_PAD_EIM_D19__IPU1_CSI1_DATA16    0x1b0b0
+			MX6QDL_PAD_EIM_D20__IPU1_CSI1_DATA15    0x1b0b0
+			MX6QDL_PAD_EIM_D26__IPU1_CSI1_DATA14    0x1b0b0
+			MX6QDL_PAD_EIM_D27__IPU1_CSI1_DATA13    0x1b0b0
+			MX6QDL_PAD_EIM_A17__IPU1_CSI1_DATA12    0x1b0b0
+			MX6QDL_PAD_EIM_D29__IPU1_CSI1_VSYNC     0x1b0b0
+			MX6QDL_PAD_EIM_EB3__IPU1_CSI1_HSYNC     0x1b0b0
+			MX6QDL_PAD_EIM_A16__IPU1_CSI1_PIXCLK    0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6dl-gw551x.dts b/arch/arm/dts/imx6dl-gw551x.dts
new file mode 100644
index 0000000..82d5f85
--- /dev/null
+++ b/arch/arm/dts/imx6dl-gw551x.dts
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2014 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw551x.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 DualLite/Solo GW551X";
+	compatible = "gw,imx6dl-gw551x", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/dts/imx6dl-gw552x.dts b/arch/arm/dts/imx6dl-gw552x.dts
new file mode 100644
index 0000000..4864a36
--- /dev/null
+++ b/arch/arm/dts/imx6dl-gw552x.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2014 Gateworks Corporation
+ */
+
+/dts-v1/;
+
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw552x.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 DualLite/Solo GW552X";
+	compatible = "gw,imx6dl-gw552x", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/dts/imx6dl-gw553x.dts b/arch/arm/dts/imx6dl-gw553x.dts
new file mode 100644
index 0000000..59b8afc
--- /dev/null
+++ b/arch/arm/dts/imx6dl-gw553x.dts
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw553x.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 DualLite/Solo GW553X";
+	compatible = "gw,imx6dl-gw553x", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/dts/imx6dl-gw560x.dts b/arch/arm/dts/imx6dl-gw560x.dts
new file mode 100644
index 0000000..21bdfaf
--- /dev/null
+++ b/arch/arm/dts/imx6dl-gw560x.dts
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw560x.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 DualLite/Solo GW560X";
+	compatible = "gw,imx6dl-gw560x", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/dts/imx6dl-gw5903.dts b/arch/arm/dts/imx6dl-gw5903.dts
new file mode 100644
index 0000000..103261e
--- /dev/null
+++ b/arch/arm/dts/imx6dl-gw5903.dts
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw5903.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Duallite/Solo GW5903";
+	compatible = "gw,imx6dl-gw5903", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/dts/imx6dl-gw5904.dts b/arch/arm/dts/imx6dl-gw5904.dts
new file mode 100644
index 0000000..9c6d3cd
--- /dev/null
+++ b/arch/arm/dts/imx6dl-gw5904.dts
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw5904.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 DualLite/Solo GW5904";
+	compatible = "gw,imx6dl-gw5904", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/dts/imx6dl-gw5907.dts b/arch/arm/dts/imx6dl-gw5907.dts
new file mode 100644
index 0000000..3fa2822
--- /dev/null
+++ b/arch/arm/dts/imx6dl-gw5907.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Gateworks Corporation
+ */
+
+/dts-v1/;
+
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw5907.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 DualLite/Solo GW5907";
+	compatible = "gw,imx6dl-gw5907", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/dts/imx6dl-gw5910.dts b/arch/arm/dts/imx6dl-gw5910.dts
new file mode 100644
index 0000000..0d5e7e5
--- /dev/null
+++ b/arch/arm/dts/imx6dl-gw5910.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Gateworks Corporation
+ */
+
+/dts-v1/;
+
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw5910.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 DualLite/Solo GW5910";
+	compatible = "gw,imx6dl-gw5910", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/dts/imx6dl-gw5912.dts b/arch/arm/dts/imx6dl-gw5912.dts
new file mode 100644
index 0000000..5260e01
--- /dev/null
+++ b/arch/arm/dts/imx6dl-gw5912.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Gateworks Corporation
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw5912.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 DualLite/Solo GW5912";
+	compatible = "gw,imx6dl-gw5912", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/dts/imx6dl-gw5913.dts b/arch/arm/dts/imx6dl-gw5913.dts
new file mode 100644
index 0000000..b74e533
--- /dev/null
+++ b/arch/arm/dts/imx6dl-gw5913.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Gateworks Corporation
+ */
+
+/dts-v1/;
+
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw5913.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 DualLite/Solo GW5913";
+	compatible = "gw,imx6dl-gw5913", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/dts/imx6dl-riotboard-u-boot.dtsi b/arch/arm/dts/imx6dl-riotboard-u-boot.dtsi
new file mode 100644
index 0000000..e51cd24
--- /dev/null
+++ b/arch/arm/dts/imx6dl-riotboard-u-boot.dtsi
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/ {
+	aliases {
+		mmc0 = &usdhc2;
+		mmc1 = &usdhc3;
+	};
+};
diff --git a/arch/arm/dts/imx6dl-riotboard.dts b/arch/arm/dts/imx6dl-riotboard.dts
new file mode 100644
index 0000000..065d3ab
--- /dev/null
+++ b/arch/arm/dts/imx6dl-riotboard.dts
@@ -0,0 +1,594 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2014 Iain Paton <ipaton0@gmail.com>
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "RIoTboard i.MX6S";
+	compatible = "riot,imx6s-riotboard", "fsl,imx6dl";
+
+	memory@10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x40000000>;
+	};
+
+	chosen {
+		stdout-path = "serial1:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_led>;
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio5 2 GPIO_ACTIVE_LOW>;
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio3 28 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx-audio-sgtl5000";
+		model = "imx6-riotboard-sgtl5000";
+		ssi-controller = <&ssi1>;
+		audio-codec = <&codec>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+			mux-int-port = <1>;
+			mux-ext-port = <3>;
+	};
+
+	reg_2p5v: regulator-2p5v {
+		compatible = "regulator-fixed";
+		regulator-name = "2P5V";
+		regulator-min-microvolt = <2500000>;
+		regulator-max-microvolt = <2500000>;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	reg_usb_otg_vbus: regulator-usbotgvbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio3 22 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&clks {
+	fsl,pmic-stby-poweroff;
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii-id";
+	phy-handle = <&rgmii_phy>;
+	interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
+			      <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
+	fsl,err006687-workaround-present;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		/* Atheros AR8035 PHY */
+		rgmii_phy: ethernet-phy@4 {
+			reg = <4>;
+			interrupts-extended = <&gpio1 28 IRQ_TYPE_LEVEL_LOW>;
+			reset-gpios = <&gpio3 31 GPIO_ACTIVE_LOW>;
+			reset-assert-us = <10000>;
+			reset-deassert-us = <1000>;
+		};
+	};
+};
+
+&gpio1 {
+	gpio-line-names =
+		"", "", "SD2_WP", "", "SD2_CD", "I2C3_SCL",
+			"I2C3_SDA", "I2C4_SCL",
+		"I2C4_SDA", "", "", "", "", "", "", "",
+		"", "PWM3", "", "", "", "", "", "",
+		"", "", "", "", "", "", "", "";
+};
+
+&gpio3 {
+	gpio-line-names =
+		"", "", "", "", "", "", "", "",
+		"", "", "", "", "", "", "", "",
+		"", "", "", "", "", "", "USB_OTG_VBUS", "",
+		"UART3_TXD", "UART3_RXD", "", "", "EIM_D28", "", "", "";
+};
+
+&gpio4 {
+	gpio-line-names =
+		"", "", "", "", "", "", "UART4_TXD", "UART4_RXD",
+		"UART5_TXD", "UART5_RXD", "", "", "", "", "", "",
+		"GPIO4_16", "GPIO4_17", "GPIO4_18", "GPIO4_19", "",
+			"CSPI3_CLK", "CSPI3_MOSI", "CSPI3_MISO",
+		"CSPI3_CS0", "CSPI3_CS1", "GPIO4_26", "GPIO4_27",
+			"CSPI3_RDY", "PWM1", "PWM2", "GPIO4_31";
+};
+
+&gpio5 {
+	gpio-line-names =
+		"", "", "EIM_A25", "", "", "GPIO5_05", "GPIO5_06",
+			"GPIO5_07",
+		"GPIO5_08", "CSPI2_CS1", "CSPI2_MOSI", "CSPI2_MISO",
+			"CSPI2_CS0", "CSPI2_CLK", "", "",
+		"", "", "", "", "", "", "", "",
+		"", "", "", "", "", "", "", "";
+};
+
+&gpio7 {
+	gpio-line-names =
+		"SD3_CD", "SD3_WP", "", "", "", "", "", "",
+		"", "", "", "", "", "", "", "",
+		"", "", "", "", "", "", "", "",
+		"", "", "", "", "", "", "", "";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c2>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	codec: sgtl5000@a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		VDDA-supply = <&reg_2p5v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+
+	pmic: pf0100@8 {
+		compatible = "fsl,pfuze100";
+		reg = <0x08>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <16 8>;
+		fsl,pmic-stby-poweroff;
+
+		regulators {
+			reg_vddcore: sw1ab {				/* VDDARM_IN */
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-always-on;
+			};
+
+			reg_vddsoc: sw1c {				/* VDDSOC_IN */
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-always-on;
+			};
+
+			reg_gen_3v3: sw2 {				/* VDDHIGH_IN */
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			reg_ddr_1v5a: sw3a {				/* NVCC_DRAM, NVCC_RGMII */
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-always-on;
+			};
+
+			reg_ddr_1v5b: sw3b {				/* NVCC_DRAM, NVCC_RGMII */
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-always-on;
+			};
+
+			reg_ddr_vtt: sw4 {				/* MIPI conn */
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-always-on;
+			};
+
+			reg_5v_600mA: swbst {				/* not used */
+				regulator-min-microvolt = <5000000>;
+				regulator-max-microvolt = <5150000>;
+			};
+
+			reg_snvs_3v: vsnvs {				/* VDD_SNVS_IN */
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-always-on;
+			};
+
+			vref_reg: vrefddr {				/* VREF_DDR */
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			reg_vgen1_1v5: vgen1 {				/* not used */
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			reg_vgen2_1v2_eth: vgen2 {			/* pcie ? */
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+				regulator-always-on;
+			};
+
+			reg_vgen3_2v8: vgen3 {				/* not used */
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+			reg_vgen4_1v8: vgen4 {				/* NVCC_SD3 */
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			reg_vgen5_2v5_sgtl: vgen5 {			/* Pwr LED & 5V0_delayed enable */
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			reg_vgen6_3v3: vgen6 {				/* #V#_DELAYED enable, MIPI */
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&i2c4 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c4>;
+	clocks = <&clks 116>;
+	status = "okay";
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>;
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>;
+	status = "okay";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>;
+	status = "okay";
+};
+
+&pwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>;
+	status = "okay";
+};
+
+&ssi1 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbh1 {
+	dr_mode = "host";
+	disable-over-current;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
+	wp-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
+	wp-gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
+
+&usdhc4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4>;
+	vmmc-supply = <&reg_3p3v>;
+	non-removable;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+
+	imx6-riotboard {
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT7__AUD3_RXD		0x130b0
+				MX6QDL_PAD_CSI0_DAT4__AUD3_TXC		0x130b0
+				MX6QDL_PAD_CSI0_DAT5__AUD3_TXD		0x110b0
+				MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS		0x130b0
+				MX6QDL_PAD_GPIO_0__CCM_CLKO1		0x130b0		/* CAM_MCLK */
+			>;
+		};
+
+		pinctrl_ecspi1: ecspi1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x100b1
+				MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
+				MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x100b1
+				MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17	0x000b1		/* CS0 */
+			>;
+		};
+
+		pinctrl_ecspi2: ecspi2grp {
+			fsl,pins = <
+				MX6QDL_PAD_DISP0_DAT15__GPIO5_IO09	0x000b1		/* CS1 */
+				MX6QDL_PAD_DISP0_DAT16__ECSPI2_MOSI	0x100b1
+				MX6QDL_PAD_DISP0_DAT17__ECSPI2_MISO	0x100b1
+				MX6QDL_PAD_DISP0_DAT18__GPIO5_IO12	0x000b1		/* CS0 */
+				MX6QDL_PAD_DISP0_DAT19__ECSPI2_SCLK	0x100b1
+			>;
+		};
+
+		pinctrl_ecspi3: ecspi3grp {
+			fsl,pins = <
+				MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK	0x100b1
+				MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI	0x100b1
+				MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO	0x100b1
+				MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24	0x000b1		/* CS0 */
+				MX6QDL_PAD_DISP0_DAT4__GPIO4_IO25	0x000b1		/* CS1 */
+			>;
+		};
+
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b030
+				MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b030
+				MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b030
+				MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b030
+				MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b030
+				MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b030
+				MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x0a0b1		/* AR8035 CLK_25M --> ENET_REF_CLK (V22) */
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b030		/* AR8035 pin strapping: IO voltage: pull up */
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x13030		/* AR8035 pin strapping: PHYADDR#0: pull down */
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x13030		/* AR8035 pin strapping: PHYADDR#1: pull down */
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030		/* AR8035 pin strapping: MODE#1: pull up */
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030		/* AR8035 pin strapping: MODE#3: pull up */
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x130b0		/* AR8035 pin strapping: MODE#0: pull down */
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8	/* GPIO16 -> AR8035 25MHz */
+				MX6QDL_PAD_EIM_D31__GPIO3_IO31		0x130b0		/* RGMII_nRST */
+				MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28	0x180b0		/* AR8035 interrupt */
+				MX6QDL_PAD_GPIO_6__ENET_IRQ		0x000b1
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT8__I2C1_SDA		0x4001b8b1
+				MX6QDL_PAD_CSI0_DAT9__I2C1_SCL		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_5__I2C3_SCL		0x4001b8b1
+				MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c4: i2c4grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_7__I2C4_SCL             0x4001b8b1
+				MX6QDL_PAD_GPIO_8__I2C4_SDA             0x4001b8b1
+			>;
+		};
+
+		pinctrl_led: ledgrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_A25__GPIO5_IO02		0x1b0b1	/* user led0 */
+				MX6QDL_PAD_EIM_D28__GPIO3_IO28		0x1b0b1	/* user led1 */
+			>;
+		};
+
+		pinctrl_pwm1: pwm1grp {
+			fsl,pins = <
+				MX6QDL_PAD_DISP0_DAT8__PWM1_OUT		0x1b0b1
+			>;
+		};
+
+		pinctrl_pwm2: pwm2grp {
+			fsl,pins = <
+				MX6QDL_PAD_DISP0_DAT9__PWM2_OUT		0x1b0b1
+			>;
+		};
+
+		pinctrl_pwm3: pwm3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD1_DAT1__PWM3_OUT		0x1b0b1
+			>;
+		};
+
+		pinctrl_pwm4: pwm4grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD1_CMD__PWM4_OUT		0x1b0b1
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
+				MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D26__UART2_TX_DATA	0x1b0b1
+				MX6QDL_PAD_EIM_D27__UART2_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart3: uart3grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
+				MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart4: uart4grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL0__UART4_TX_DATA	0x1b0b1
+				MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart5: uart5grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+				MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID	0x17059
+				MX6QDL_PAD_EIM_D22__GPIO3_IO22		0x000b0	/* MX6QDL_PAD_EIM_D22__USB_OTG_PWR */
+				MX6QDL_PAD_EIM_D21__USB_OTG_OC		0x1b0b0
+			>;
+		};
+
+		pinctrl_usdhc2: usdhc2grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_CMD__SD2_CMD		0x17059
+				MX6QDL_PAD_SD2_CLK__SD2_CLK		0x10059
+				MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x17059
+				MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x17059
+				MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x17059
+				MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x17059
+				MX6QDL_PAD_GPIO_4__GPIO1_IO04		0x1b0b0	/* SD2 CD */
+				MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x1f0b0	/* SD2 WP */
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+				MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x1b0b0	/* SD3 CD */
+				MX6QDL_PAD_SD3_DAT4__GPIO7_IO01		0x1f0b0	/* SD3 WP */
+			>;
+		};
+
+		pinctrl_usdhc4: usdhc4grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_CMD__SD4_CMD		0x17059
+				MX6QDL_PAD_SD4_CLK__SD4_CLK		0x10059
+				MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x17059
+				MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x17059
+				MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x17059
+				MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x17059
+				MX6QDL_PAD_NANDF_ALE__GPIO6_IO08	0x17059	/* SD4 RST (eMMC) */
+			>;
+		};
+	};
+};
diff --git a/arch/arm/dts/imx6dl-udoo.dts b/arch/arm/dts/imx6dl-udoo.dts
new file mode 100644
index 0000000..d871cac
--- /dev/null
+++ b/arch/arm/dts/imx6dl-udoo.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ */
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-udoo.dtsi"
+
+/ {
+	model = "Udoo i.MX6 Dual-lite Board";
+	compatible = "udoo,imx6dl-udoo", "fsl,imx6dl";
+};
diff --git a/arch/arm/dts/imx6q-gw51xx.dts b/arch/arm/dts/imx6q-gw51xx.dts
new file mode 100644
index 0000000..f801734
--- /dev/null
+++ b/arch/arm/dts/imx6q-gw51xx.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2013 Gateworks Corporation
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-gw51xx.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW51XX";
+	compatible = "gw,imx6q-gw51xx", "gw,ventana", "fsl,imx6q";
+};
diff --git a/arch/arm/dts/imx6q-gw52xx.dts b/arch/arm/dts/imx6q-gw52xx.dts
new file mode 100644
index 0000000..6e1c493
--- /dev/null
+++ b/arch/arm/dts/imx6q-gw52xx.dts
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2013 Gateworks Corporation
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-gw52xx.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW52XX";
+	compatible = "gw,imx6q-gw52xx", "gw,ventana", "fsl,imx6q";
+};
+
+&i2c3 {
+	adv7180: camera@20 {
+		compatible = "adi,adv7180";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_adv7180>;
+		reg = <0x20>;
+		powerdown-gpios = <&gpio3 31 GPIO_ACTIVE_LOW>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <30 IRQ_TYPE_LEVEL_LOW>;
+
+		port {
+			adv7180_to_ipu2_csi1_mux: endpoint {
+				remote-endpoint = <&ipu2_csi1_mux_from_parallel_sensor>;
+				bus-width = <8>;
+			};
+		};
+	};
+};
+
+&ipu2_csi1_from_ipu2_csi1_mux {
+	bus-width = <8>;
+};
+
+&ipu2_csi1_mux_from_parallel_sensor {
+	remote-endpoint = <&adv7180_to_ipu2_csi1_mux>;
+	bus-width = <8>;
+};
+
+&ipu2_csi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ipu2_csi1>;
+};
+
+&iomuxc {
+	pinctrl_adv7180: adv7180grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D30__GPIO3_IO30          0x0001b0b0
+			MX6QDL_PAD_EIM_D31__GPIO3_IO31          0x4001b0b0
+		>;
+	};
+
+	pinctrl_ipu2_csi1: ipu2_csi1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_EB2__IPU2_CSI1_DATA19    0x1b0b0
+			MX6QDL_PAD_EIM_D16__IPU2_CSI1_DATA18    0x1b0b0
+			MX6QDL_PAD_EIM_D18__IPU2_CSI1_DATA17    0x1b0b0
+			MX6QDL_PAD_EIM_D19__IPU2_CSI1_DATA16    0x1b0b0
+			MX6QDL_PAD_EIM_D20__IPU2_CSI1_DATA15    0x1b0b0
+			MX6QDL_PAD_EIM_D26__IPU2_CSI1_DATA14    0x1b0b0
+			MX6QDL_PAD_EIM_D27__IPU2_CSI1_DATA13    0x1b0b0
+			MX6QDL_PAD_EIM_A17__IPU2_CSI1_DATA12    0x1b0b0
+			MX6QDL_PAD_EIM_D29__IPU2_CSI1_VSYNC     0x1b0b0
+			MX6QDL_PAD_EIM_EB3__IPU2_CSI1_HSYNC     0x1b0b0
+			MX6QDL_PAD_EIM_A16__IPU2_CSI1_PIXCLK    0x1b0b0
+		>;
+	};
+};
+
+&sata {
+	status = "okay";
+};
diff --git a/arch/arm/dts/imx6q-gw53xx.dts b/arch/arm/dts/imx6q-gw53xx.dts
new file mode 100644
index 0000000..f13df8e
--- /dev/null
+++ b/arch/arm/dts/imx6q-gw53xx.dts
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2013 Gateworks Corporation
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-gw53xx.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW53XX";
+	compatible = "gw,imx6q-gw53xx", "gw,ventana", "fsl,imx6q";
+};
+
+&i2c3 {
+	adv7180: camera@20 {
+		compatible = "adi,adv7180";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_adv7180>;
+		reg = <0x20>;
+		powerdown-gpios = <&gpio3 31 GPIO_ACTIVE_LOW>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <30 IRQ_TYPE_LEVEL_LOW>;
+
+		port {
+			adv7180_to_ipu2_csi1_mux: endpoint {
+				remote-endpoint = <&ipu2_csi1_mux_from_parallel_sensor>;
+				bus-width = <8>;
+			};
+		};
+	};
+};
+
+&ipu2_csi1_from_ipu2_csi1_mux {
+	bus-width = <8>;
+};
+
+&ipu2_csi1_mux_from_parallel_sensor {
+	remote-endpoint = <&adv7180_to_ipu2_csi1_mux>;
+	bus-width = <8>;
+};
+
+&ipu2_csi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ipu2_csi1>;
+};
+
+&sata {
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl_adv7180: adv7180grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D30__GPIO3_IO30          0x0001b0b0
+			MX6QDL_PAD_EIM_D31__GPIO3_IO31          0x4001b0b0
+		>;
+	};
+
+	pinctrl_ipu2_csi1: ipu2_csi1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_EB2__IPU2_CSI1_DATA19    0x1b0b0
+			MX6QDL_PAD_EIM_D16__IPU2_CSI1_DATA18    0x1b0b0
+			MX6QDL_PAD_EIM_D18__IPU2_CSI1_DATA17    0x1b0b0
+			MX6QDL_PAD_EIM_D19__IPU2_CSI1_DATA16    0x1b0b0
+			MX6QDL_PAD_EIM_D20__IPU2_CSI1_DATA15    0x1b0b0
+			MX6QDL_PAD_EIM_D26__IPU2_CSI1_DATA14    0x1b0b0
+			MX6QDL_PAD_EIM_D27__IPU2_CSI1_DATA13    0x1b0b0
+			MX6QDL_PAD_EIM_A17__IPU2_CSI1_DATA12    0x1b0b0
+			MX6QDL_PAD_EIM_D29__IPU2_CSI1_VSYNC     0x1b0b0
+			MX6QDL_PAD_EIM_EB3__IPU2_CSI1_HSYNC     0x1b0b0
+			MX6QDL_PAD_EIM_A16__IPU2_CSI1_PIXCLK    0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6q-gw54xx.dts b/arch/arm/dts/imx6q-gw54xx.dts
new file mode 100644
index 0000000..d5d4690
--- /dev/null
+++ b/arch/arm/dts/imx6q-gw54xx.dts
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2013 Gateworks Corporation
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-gw54xx.dtsi"
+#include <dt-bindings/media/tda1997x.h>
+
+/ {
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW54XX";
+	compatible = "gw,imx6q-gw54xx", "gw,ventana", "fsl,imx6q";
+
+	sound-digital {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "tda1997x-audio";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&sound_codec>;
+		simple-audio-card,frame-master = <&sound_codec>;
+
+		sound_cpu: simple-audio-card,cpu {
+			sound-dai = <&ssi2>;
+		};
+
+		sound_codec: simple-audio-card,codec {
+			sound-dai = <&hdmi_receiver>;
+		};
+	};
+};
+
+&i2c3 {
+	adv7180: camera@20 {
+		compatible = "adi,adv7180";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_adv7180>;
+		reg = <0x20>;
+		powerdown-gpios = <&gpio3 31 GPIO_ACTIVE_LOW>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <30 IRQ_TYPE_LEVEL_LOW>;
+
+		port {
+			adv7180_to_ipu2_csi1_mux: endpoint {
+				remote-endpoint = <&ipu2_csi1_mux_from_parallel_sensor>;
+				bus-width = <8>;
+			};
+		};
+	};
+
+	hdmi_receiver: hdmi-receiver@48 {
+		compatible = "nxp,tda19971";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_tda1997x>;
+		reg = <0x48>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+		DOVDD-supply = <&reg_3p3v>;
+		AVDD-supply = <&sw4_reg>;
+		DVDD-supply = <&sw4_reg>;
+		#sound-dai-cells = <0>;
+		nxp,audout-format = "i2s";
+		nxp,audout-layout = <0>;
+		nxp,audout-width = <16>;
+		nxp,audout-mclk-fs = <128>;
+		/*
+		 * The 8bpp YUV422 semi-planar mode outputs CbCr[11:4]
+		 * and Y[11:4] across 16bits in the same cycle
+		 * which we map to VP[15:08]<->CSI_DATA[19:12]
+		 */
+		nxp,vidout-portcfg =
+			/*G_Y_11_8<->VP[15:12]<->CSI_DATA[19:16]*/
+			< TDA1997X_VP24_V15_12 TDA1997X_G_Y_11_8 >,
+			/*G_Y_7_4<->VP[11:08]<->CSI_DATA[15:12]*/
+			< TDA1997X_VP24_V11_08 TDA1997X_G_Y_7_4 >,
+			/*R_CR_CBCR_11_8<->VP[07:04]<->CSI_DATA[11:08]*/
+			< TDA1997X_VP24_V07_04 TDA1997X_R_CR_CBCR_11_8 >,
+			/*R_CR_CBCR_7_4<->VP[03:00]<->CSI_DATA[07:04]*/
+			< TDA1997X_VP24_V03_00 TDA1997X_R_CR_CBCR_7_4 >;
+
+		port {
+			tda1997x_to_ipu1_csi0_mux: endpoint {
+				remote-endpoint = <&ipu1_csi0_mux_from_parallel_sensor>;
+				bus-width = <16>;
+				hsync-active = <1>;
+				vsync-active = <1>;
+				data-active = <1>;
+			};
+		};
+	};
+};
+
+&ipu1_csi0_from_ipu1_csi0_mux {
+	bus-width = <16>;
+};
+
+&ipu1_csi0_mux_from_parallel_sensor {
+	remote-endpoint = <&tda1997x_to_ipu1_csi0_mux>;
+	bus-width = <16>;
+};
+
+&ipu1_csi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ipu1_csi0>;
+};
+
+&ipu2_csi1_from_ipu2_csi1_mux {
+	bus-width = <8>;
+};
+
+&ipu2_csi1_mux_from_parallel_sensor {
+	remote-endpoint = <&adv7180_to_ipu2_csi1_mux>;
+	bus-width = <8>;
+};
+
+&ipu2_csi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ipu2_csi1>;
+};
+
+&sata {
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl_adv7180: adv7180grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D30__GPIO3_IO30          0x0001b0b0
+			MX6QDL_PAD_EIM_D31__GPIO3_IO31          0x4001b0b0
+		>;
+	};
+
+	pinctrl_ipu1_csi0: ipu1_csi0grp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT4__IPU1_CSI0_DATA04		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT5__IPU1_CSI0_DATA05		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT6__IPU1_CSI0_DATA06		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT7__IPU1_CSI0_DATA07		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT8__IPU1_CSI0_DATA08		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT9__IPU1_CSI0_DATA09		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT10__IPU1_CSI0_DATA10		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT11__IPU1_CSI0_DATA11		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19		0x1b0b0
+			MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC		0x1b0b0
+			MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK	0x1b0b0
+			MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC		0x1b0b0
+		>;
+	};
+
+	pinctrl_ipu2_csi1: ipu2_csi1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_EB2__IPU2_CSI1_DATA19    0x1b0b0
+			MX6QDL_PAD_EIM_D16__IPU2_CSI1_DATA18    0x1b0b0
+			MX6QDL_PAD_EIM_D18__IPU2_CSI1_DATA17    0x1b0b0
+			MX6QDL_PAD_EIM_D19__IPU2_CSI1_DATA16    0x1b0b0
+			MX6QDL_PAD_EIM_D20__IPU2_CSI1_DATA15    0x1b0b0
+			MX6QDL_PAD_EIM_D26__IPU2_CSI1_DATA14    0x1b0b0
+			MX6QDL_PAD_EIM_D27__IPU2_CSI1_DATA13    0x1b0b0
+			MX6QDL_PAD_EIM_A17__IPU2_CSI1_DATA12    0x1b0b0
+			MX6QDL_PAD_EIM_D29__IPU2_CSI1_VSYNC     0x1b0b0
+			MX6QDL_PAD_EIM_EB3__IPU2_CSI1_HSYNC     0x1b0b0
+			MX6QDL_PAD_EIM_A16__IPU2_CSI1_PIXCLK    0x1b0b0
+		>;
+	};
+
+	pinctrl_tda1997x: tda1997xgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_7__GPIO1_IO07	0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6q-gw551x.dts b/arch/arm/dts/imx6q-gw551x.dts
new file mode 100644
index 0000000..2c7feee
--- /dev/null
+++ b/arch/arm/dts/imx6q-gw551x.dts
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2014 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-gw551x.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW551X";
+	compatible = "gw,imx6q-gw551x", "gw,ventana", "fsl,imx6q";
+};
diff --git a/arch/arm/dts/imx6q-gw552x.dts b/arch/arm/dts/imx6q-gw552x.dts
new file mode 100644
index 0000000..c973b73
--- /dev/null
+++ b/arch/arm/dts/imx6q-gw552x.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2014 Gateworks Corporation
+ */
+
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include "imx6qdl-gw552x.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW552X";
+	compatible = "gw,imx6q-gw552x", "gw,ventana", "fsl,imx6q";
+};
+
+&sata {
+	status = "okay";
+};
diff --git a/arch/arm/dts/imx6q-gw553x.dts b/arch/arm/dts/imx6q-gw553x.dts
new file mode 100644
index 0000000..e9c224c
--- /dev/null
+++ b/arch/arm/dts/imx6q-gw553x.dts
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-gw553x.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW553X";
+	compatible = "gw,imx6q-gw553x", "gw,ventana", "fsl,imx6q";
+};
diff --git a/arch/arm/dts/imx6q-gw560x.dts b/arch/arm/dts/imx6q-gw560x.dts
new file mode 100644
index 0000000..735f2bb
--- /dev/null
+++ b/arch/arm/dts/imx6q-gw560x.dts
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2017 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-gw560x.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW560X";
+	compatible = "gw,imx6q-gw560x", "gw,ventana", "fsl,imx6q";
+};
+
+&sata {
+	status = "okay";
+};
diff --git a/arch/arm/dts/imx6q-gw5903.dts b/arch/arm/dts/imx6q-gw5903.dts
new file mode 100644
index 0000000..a182e4c
--- /dev/null
+++ b/arch/arm/dts/imx6q-gw5903.dts
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-gw5903.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW5903";
+	compatible = "gw,imx6q-gw5903", "gw,ventana", "fsl,imx6q";
+};
diff --git a/arch/arm/dts/imx6q-gw5904.dts b/arch/arm/dts/imx6q-gw5904.dts
new file mode 100644
index 0000000..ca1e2ae
--- /dev/null
+++ b/arch/arm/dts/imx6q-gw5904.dts
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2017 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-gw5904.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW5904";
+	compatible = "gw,imx6q-gw5904", "gw,ventana", "fsl,imx6q";
+};
+
+&sata {
+	status = "okay";
+};
diff --git a/arch/arm/dts/imx6q-gw5907.dts b/arch/arm/dts/imx6q-gw5907.dts
new file mode 100644
index 0000000..b25526e
--- /dev/null
+++ b/arch/arm/dts/imx6q-gw5907.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Gateworks Corporation
+ */
+
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include "imx6qdl-gw5907.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW5907";
+	compatible = "gw,imx6q-gw5907", "gw,ventana", "fsl,imx6q";
+};
diff --git a/arch/arm/dts/imx6q-gw5910.dts b/arch/arm/dts/imx6q-gw5910.dts
new file mode 100644
index 0000000..6aafa2f
--- /dev/null
+++ b/arch/arm/dts/imx6q-gw5910.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Gateworks Corporation
+ */
+
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include "imx6qdl-gw5910.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW5910";
+	compatible = "gw,imx6q-gw5910", "gw,ventana", "fsl,imx6q";
+};
diff --git a/arch/arm/dts/imx6q-gw5912.dts b/arch/arm/dts/imx6q-gw5912.dts
new file mode 100644
index 0000000..4dcbd94
--- /dev/null
+++ b/arch/arm/dts/imx6q-gw5912.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Gateworks Corporation
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-gw5912.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW5912";
+	compatible = "gw,imx6q-gw5912", "gw,ventana", "fsl,imx6q";
+};
diff --git a/arch/arm/dts/imx6q-gw5913.dts b/arch/arm/dts/imx6q-gw5913.dts
new file mode 100644
index 0000000..6f511f1
--- /dev/null
+++ b/arch/arm/dts/imx6q-gw5913.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Gateworks Corporation
+ */
+
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include "imx6qdl-gw5913.dtsi"
+
+/ {
+	model = "Gateworks Ventana i.MX6 Dual/Quad GW5913";
+	compatible = "gw,imx6q-gw5913", "gw,ventana", "fsl,imx6q";
+};
diff --git a/arch/arm/dts/imx6q-marsboard-u-boot.dtsi b/arch/arm/dts/imx6q-marsboard-u-boot.dtsi
new file mode 100644
index 0000000..e51cd24
--- /dev/null
+++ b/arch/arm/dts/imx6q-marsboard-u-boot.dtsi
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/ {
+	aliases {
+		mmc0 = &usdhc2;
+		mmc1 = &usdhc3;
+	};
+};
diff --git a/arch/arm/dts/imx6q-marsboard.dts b/arch/arm/dts/imx6q-marsboard.dts
new file mode 100644
index 0000000..05ee283
--- /dev/null
+++ b/arch/arm/dts/imx6q-marsboard.dts
@@ -0,0 +1,417 @@
+/*
+ * Copyright (C) 2016 Sergio Prado (sergio.prado@e-labworks.com)
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file 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.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Embest MarS Board i.MX6Dual";
+	compatible = "embest,imx6q-marsboard", "fsl,imx6q";
+
+	memory@10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x40000000>;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	reg_usb_otg_vbus: regulator-usb-otg-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_led>;
+
+		user1 {
+			label = "imx6:green:user1";
+			gpios = <&gpio5 2 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+			linux,default-trigger = "heartbeat";
+		};
+
+		user2 {
+			label = "imx6:green:user2";
+			gpios = <&gpio3 28 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&ecspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	cs-gpios = <&gpio2 30 GPIO_ACTIVE_LOW>;
+	status = "okay";
+
+	m25p80@0 {
+		compatible = "microchip,sst25vf016b";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii-id";
+	phy-handle = <&rgmii_phy>;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		/* Atheros AR8035 PHY */
+		rgmii_phy: ethernet-phy@4 {
+			reg = <4>;
+			interrupts-extended = <&gpio1 28 IRQ_TYPE_LEVEL_LOW>;
+			reset-gpios = <&gpio3 31 GPIO_ACTIVE_LOW>;
+			reset-assert-us = <10000>;
+			reset-deassert-us = <1000>;
+		};
+	};
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c2>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>;
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>;
+	status = "okay";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>;
+	status = "okay";
+};
+
+&pwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbh1 {
+	dr_mode = "host";
+	disable-over-current;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	dr_mode = "otg";
+	disable-over-current;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	vmmc-supply = <&reg_3p3v>;
+	cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
+	wp-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	vmmc-supply = <&reg_3p3v>;
+	non-removable;
+	status = "okay";
+};
+
+&iomuxc {
+
+	pinctrl_audmux: audmuxgrp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT7__AUD3_RXD		0x130b0
+			MX6QDL_PAD_CSI0_DAT4__AUD3_TXC		0x130b0
+			MX6QDL_PAD_CSI0_DAT5__AUD3_TXD		0x110b0
+			MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS		0x130b0
+			MX6QDL_PAD_GPIO_0__CCM_CLKO1		0x130b0	/* CAM_MCLK */
+		>;
+	};
+
+	pinctrl_ecspi1: ecspi1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x100b1
+			MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
+			MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x100b1
+			MX6QDL_PAD_EIM_EB2__GPIO2_IO30		0x000b1	/* CS0 */
+		>;
+	};
+
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b030
+			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b030
+			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b030
+			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b030
+			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b030
+			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b030
+			/* AR8035 CLK_25M --> ENET_REF_CLK (V22) */
+			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x0a0b1
+			/* AR8035 pin strapping: IO voltage: pull up */
+			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b030
+			/* AR8035 pin strapping: PHYADDR#0: pull down */
+			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x13030
+			/* AR8035 pin strapping: PHYADDR#1: pull down */
+			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x13030
+			/* AR8035 pin strapping: MODE#1: pull up */
+			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030
+			/* AR8035 pin strapping: MODE#3: pull up */
+			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030
+			/* AR8035 pin strapping: MODE#0: pull down */
+			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x13030
+			/* GPIO16 -> AR8035 25MHz */
+			MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			/* RGMII_nRST */
+			MX6QDL_PAD_EIM_D31__GPIO3_IO31		0x130b0
+			/* AR8035 interrupt */
+			MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28	0x180b0
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT8__I2C1_SDA		0x4001b8b1
+			MX6QDL_PAD_CSI0_DAT9__I2C1_SCL		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_5__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_led: ledgrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_A25__GPIO5_IO02		0x1b0b1	/* LED1 */
+			MX6QDL_PAD_EIM_D28__GPIO3_IO28		0x1b0b1	/* LED2 */
+		>;
+	};
+
+	pinctrl_pwm1: pwm1grp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT8__PWM1_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT9__PWM2_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT1__PWM3_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm4: pwm4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_CMD__PWM4_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
+			MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D26__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D27__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart4: uart4grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL0__UART4_TX_DATA	0x1b0b1
+			MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+			MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID	0x17059
+			MX6QDL_PAD_EIM_D21__USB_OTG_OC		0x1b0b0
+			MX6QDL_PAD_EIM_D22__GPIO3_IO22		0x000b0	/* USB OTG POWER ENABLE */
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD2_CMD__SD2_CMD		0x17059
+			MX6QDL_PAD_SD2_CLK__SD2_CLK		0x10059
+			MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x17059
+			MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x17059
+			MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x17059
+			MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x17059
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0x1b0b0	/* CD */
+			MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x1f0b0	/* WP */
+		>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17009
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10009
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17009
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17009
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17009
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17009
+			MX6QDL_PAD_SD3_RST__SD3_RESET		0x17009
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6q-phytec-mira-rdk-nand-u-boot.dtsi b/arch/arm/dts/imx6q-phytec-mira-rdk-nand-u-boot.dtsi
index 8555be1..5a64f86 100644
--- a/arch/arm/dts/imx6q-phytec-mira-rdk-nand-u-boot.dtsi
+++ b/arch/arm/dts/imx6q-phytec-mira-rdk-nand-u-boot.dtsi
@@ -40,3 +40,7 @@
 &m25p80 {
 	u-boot,dm-spl;
 };
+
+&gpmi {
+	fsl,legacy-bch-geometry;
+};
diff --git a/arch/arm/dts/imx6q-udoo.dts b/arch/arm/dts/imx6q-udoo.dts
new file mode 100644
index 0000000..52e9f4a
--- /dev/null
+++ b/arch/arm/dts/imx6q-udoo.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ */
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-udoo.dtsi"
+
+/ {
+	model = "Udoo i.MX6 Quad Board";
+	compatible = "udoo,imx6q-udoo", "fsl,imx6q";
+};
+
+&sata {
+	status = "okay";
+};
diff --git a/arch/arm/dts/imx6qdl-gw51xx.dtsi b/arch/arm/dts/imx6qdl-gw51xx.dtsi
new file mode 100644
index 0000000..2a21c67
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-gw51xx.dtsi
@@ -0,0 +1,638 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2013 Gateworks Corporation
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		led0 = &led0;
+		led1 = &led1;
+		nand = &gpmi;
+		usb0 = &usbh1;
+		usb1 = &usbotg;
+	};
+
+	chosen {
+		bootargs = "console=ttymxc1,115200";
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		user-pb {
+			label = "user_pb";
+			gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+		};
+
+		user-pb1x {
+			label = "user_pb1x";
+			linux,code = <BTN_1>;
+			interrupt-parent = <&gsc>;
+			interrupts = <0>;
+		};
+
+		key-erased {
+			label = "key-erased";
+			linux,code = <BTN_2>;
+			interrupt-parent = <&gsc>;
+			interrupts = <1>;
+		};
+
+		eeprom-wp {
+			label = "eeprom_wp";
+			linux,code = <BTN_3>;
+			interrupt-parent = <&gsc>;
+			interrupts = <2>;
+		};
+
+		tamper {
+			label = "tamper";
+			linux,code = <BTN_4>;
+			interrupt-parent = <&gsc>;
+			interrupts = <5>;
+		};
+
+		switch-hold {
+			label = "switch_hold";
+			linux,code = <BTN_5>;
+			interrupt-parent = <&gsc>;
+			interrupts = <7>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDG */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDR */
+			default-state = "off";
+		};
+	};
+
+	memory@10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x20000000>;
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pps>;
+		gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+		status = "okay";
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_5p0v: regulator-5p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "5P0V";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	reg_usb_otg_vbus: regulator-usb-otg-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii-id";
+	phy-reset-gpios = <&gpio1 30 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c3>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	gsc: gsc@20 {
+		compatible = "gw,gsc";
+		reg = <0x20>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		#size-cells = <0>;
+
+		adc {
+			compatible = "gw,gsc-adc";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			channel@0 {
+				gw,mode = <0>;
+				reg = <0x00>;
+				label = "temp";
+			};
+
+			channel@2 {
+				gw,mode = <1>;
+				reg = <0x02>;
+				label = "vdd_vin";
+			};
+
+			channel@5 {
+				gw,mode = <1>;
+				reg = <0x05>;
+				label = "vdd_3p3";
+			};
+
+			channel@8 {
+				gw,mode = <1>;
+				reg = <0x08>;
+				label = "vdd_bat";
+			};
+
+			channel@b {
+				gw,mode = <1>;
+				reg = <0x0b>;
+				label = "vdd_5p0";
+			};
+
+			channel@e {
+				gw,mode = <1>;
+				reg = <0xe>;
+				label = "vdd_arm";
+			};
+
+			channel@11 {
+				gw,mode = <1>;
+				reg = <0x11>;
+				label = "vdd_soc";
+			};
+
+			channel@14 {
+				gw,mode = <1>;
+				reg = <0x14>;
+				label = "vdd_3p0";
+			};
+
+			channel@17 {
+				gw,mode = <1>;
+				reg = <0x17>;
+				label = "vdd_1p5";
+			};
+
+			channel@1d {
+				gw,mode = <1>;
+				reg = <0x1d>;
+				label = "vdd_1p8";
+			};
+
+			channel@20 {
+				gw,mode = <1>;
+				reg = <0x20>;
+				label = "vdd_an1";
+			};
+
+			channel@23 {
+				gw,mode = <1>;
+				reg = <0x23>;
+				label = "vdd_2p5";
+			};
+		};
+	};
+
+	gsc_gpio: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gsc>;
+		interrupts = <4>;
+	};
+
+	eeprom1: eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom2: eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom3: eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom4: eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	rtc: ds1672@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	ltc3676: pmic@3c {
+		compatible = "lltc,ltc3676";
+		reg = <0x3c>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pmic>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+
+		regulators {
+			/* VDD_SOC (1+R1/R2 = 1.635) */
+			reg_vdd_soc: sw1 {
+				regulator-name = "vddsoc";
+				regulator-min-microvolt = <674400>;
+				regulator-max-microvolt = <1308000>;
+				lltc,fb-voltage-divider = <127000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_1P8 (1+R1/R2 = 2.505): GPS/VideoIn/ENET-PHY */
+			reg_1p8v: sw2 {
+				regulator-name = "vdd1p8";
+				regulator-min-microvolt = <1033310>;
+				regulator-max-microvolt = <2004000>;
+				lltc,fb-voltage-divider = <301000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_ARM (1+R1/R2 = 1.635) */
+			reg_vdd_arm: sw3 {
+				regulator-name = "vddarm";
+				regulator-min-microvolt = <674400>;
+				regulator-max-microvolt = <1308000>;
+				lltc,fb-voltage-divider = <127000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_DDR (1+R1/R2 = 2.105) */
+			reg_vdd_ddr: sw4 {
+				regulator-name = "vddddr";
+				regulator-min-microvolt = <868310>;
+				regulator-max-microvolt = <1684000>;
+				lltc,fb-voltage-divider = <221000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_2P5 (1+R1/R2 = 3.435): PCIe/ENET-PHY */
+			reg_2p5v: ldo2 {
+				regulator-name = "vdd2p5";
+				regulator-min-microvolt = <2490375>;
+				regulator-max-microvolt = <2490375>;
+				lltc,fb-voltage-divider = <487000 200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_HIGH (1+R1/R2 = 4.17) */
+			reg_3p0v: ldo4 {
+				regulator-name = "vdd3p0";
+				regulator-min-microvolt = <3023250>;
+				regulator-max-microvolt = <3023250>;
+				lltc,fb-voltage-divider = <634000 200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	adv7180: camera@20 {
+		compatible = "adi,adv7180";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_adv7180>;
+		reg = <0x20>;
+		powerdown-gpios = <&gpio5 20 GPIO_ACTIVE_LOW>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <23 IRQ_TYPE_LEVEL_LOW>;
+
+		port {
+			adv7180_to_ipu1_csi0_mux: endpoint {
+				remote-endpoint = <&ipu1_csi0_mux_from_parallel_sensor>;
+				bus-width = <8>;
+			};
+		};
+	};
+};
+
+&ipu1_csi0_from_ipu1_csi0_mux {
+	bus-width = <8>;
+};
+
+&ipu1_csi0_mux_from_parallel_sensor {
+	remote-endpoint = <&adv7180_to_ipu1_csi0_mux>;
+	bus-width = <8>;
+};
+
+&ipu1_csi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ipu1_csi0>;
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio1 0 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>; /* MX6_DIO1 */
+	status = "disabled";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>; /* MX6_DIO2 */
+	status = "disabled";
+};
+
+&pwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>; /* MX6_DIO3 */
+	status = "disabled";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+};
+
+&iomuxc {
+	pinctrl_adv7180: adv7180grp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT5__GPIO5_IO23        0x0001b0b0
+			MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20     0x4001b0b0
+		>;
+	};
+
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b030
+			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b030
+			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b030
+			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030
+			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030
+			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b030
+			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b030
+			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b030
+			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b030
+			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b030
+			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b030
+			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b030
+			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			MX6QDL_PAD_ENET_TXD0__GPIO1_IO30	0x1b0b0 /* PHY Reset */
+		>;
+	};
+
+	pinctrl_gpio_leds: gpioledsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL0__GPIO4_IO06		0x1b0b0
+			MX6QDL_PAD_KEY_ROW0__GPIO4_IO07		0x1b0b0
+		>;
+	};
+
+	pinctrl_gpmi_nand: gpminandgrp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+			MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+			MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+			MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+			MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+			MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+			MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+			MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+			MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+			MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+			MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+			MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+			MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+			MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0x0001b0b0 /* GSC_IRQ# */
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_ipu1_csi0: ipu1csi0grp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12    0x1b0b0
+			MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13    0x1b0b0
+			MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14    0x1b0b0
+			MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15    0x1b0b0
+			MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16    0x1b0b0
+			MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17    0x1b0b0
+			MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18    0x1b0b0
+			MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19    0x1b0b0
+			MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC      0x1b0b0
+			MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC     0x1b0b0
+			MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK   0x1b0b0
+		>;
+	};
+
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_0__GPIO1_IO00		0x1b0b0
+		>;
+	};
+
+	pinctrl_pmic: pmicgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_8__GPIO1_IO08		0x0001b0b0 /* PMIC_IRQ# */
+		>;
+	};
+
+	pinctrl_pps: ppsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_RXD1__GPIO1_IO26	0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT2__PWM2_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT1__PWM3_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm4: pwm4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_CMD__PWM4_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+			MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			MX6QDL_PAD_EIM_D22__GPIO3_IO22		0x1b0b0 /* OTG_PWR_EN */
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT8__WDOG1_B		0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6qdl-gw52xx.dtsi b/arch/arm/dts/imx6qdl-gw52xx.dtsi
new file mode 100644
index 0000000..6eedf8d
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-gw52xx.dtsi
@@ -0,0 +1,782 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2013 Gateworks Corporation
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		led0 = &led0;
+		led1 = &led1;
+		led2 = &led2;
+		mmc0 = &usdhc3;
+		nand = &gpmi;
+		ssi0 = &ssi1;
+		usb0 = &usbh1;
+		usb1 = &usbotg;
+	};
+
+	chosen {
+		bootargs = "console=ttymxc1,115200";
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm4 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		user-pb {
+			label = "user_pb";
+			gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+		};
+
+		user-pb1x {
+			label = "user_pb1x";
+			linux,code = <BTN_1>;
+			interrupt-parent = <&gsc>;
+			interrupts = <0>;
+		};
+
+		key-erased {
+			label = "key-erased";
+			linux,code = <BTN_2>;
+			interrupt-parent = <&gsc>;
+			interrupts = <1>;
+		};
+
+		eeprom-wp {
+			label = "eeprom_wp";
+			linux,code = <BTN_3>;
+			interrupt-parent = <&gsc>;
+			interrupts = <2>;
+		};
+
+		tamper {
+			label = "tamper";
+			linux,code = <BTN_4>;
+			interrupt-parent = <&gsc>;
+			interrupts = <5>;
+		};
+
+		switch-hold {
+			label = "switch_hold";
+			linux,code = <BTN_5>;
+			interrupt-parent = <&gsc>;
+			interrupts = <7>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDG */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDR */
+			default-state = "off";
+		};
+
+		led2: user3 {
+			label = "user3";
+			gpios = <&gpio4 15 GPIO_ACTIVE_LOW>; /* MX6_LOCLED# */
+			default-state = "off";
+		};
+	};
+
+	memory@10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x20000000>;
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pps>;
+		gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+		status = "okay";
+	};
+
+	reg_1p0v: regulator-1p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "1P0V";
+		regulator-min-microvolt = <1000000>;
+		regulator-max-microvolt = <1000000>;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_5p0v: regulator-5p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "5P0V";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	reg_usb_otg_vbus: regulator-usb-otg-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	sound {
+		compatible = "fsl,imx6q-ventana-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "sgtl5000-audio";
+		ssi-controller = <&ssi1>;
+		audio-codec = <&codec>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+		mux-int-port = <1>;
+		mux-ext-port = <4>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	status = "okay";
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
+			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
+				 <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
+};
+
+&ecspi3 {
+	cs-gpios = <&gpio4 24 GPIO_ACTIVE_LOW>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi3>;
+	status = "okay";
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii-id";
+	phy-reset-gpios = <&gpio1 30 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c3>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	gsc: gsc@20 {
+		compatible = "gw,gsc";
+		reg = <0x20>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		#size-cells = <0>;
+
+		adc {
+			compatible = "gw,gsc-adc";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			channel@0 {
+				gw,mode = <0>;
+				reg = <0x00>;
+				label = "temp";
+			};
+
+			channel@2 {
+				gw,mode = <1>;
+				reg = <0x02>;
+				label = "vdd_vin";
+			};
+
+			channel@5 {
+				gw,mode = <1>;
+				reg = <0x05>;
+				label = "vdd_3p3";
+			};
+
+			channel@8 {
+				gw,mode = <1>;
+				reg = <0x08>;
+				label = "vdd_bat";
+			};
+
+			channel@b {
+				gw,mode = <1>;
+				reg = <0x0b>;
+				label = "vdd_5p0";
+			};
+
+			channel@e {
+				gw,mode = <1>;
+				reg = <0xe>;
+				label = "vdd_arm";
+			};
+
+			channel@11 {
+				gw,mode = <1>;
+				reg = <0x11>;
+				label = "vdd_soc";
+			};
+
+			channel@14 {
+				gw,mode = <1>;
+				reg = <0x14>;
+				label = "vdd_3p0";
+			};
+
+			channel@17 {
+				gw,mode = <1>;
+				reg = <0x17>;
+				label = "vdd_1p5";
+			};
+
+			channel@1d {
+				gw,mode = <1>;
+				reg = <0x1d>;
+				label = "vdd_1p8";
+			};
+
+			channel@20 {
+				gw,mode = <1>;
+				reg = <0x20>;
+				label = "vdd_1p0";
+			};
+
+			channel@23 {
+				gw,mode = <1>;
+				reg = <0x23>;
+				label = "vdd_2p5";
+			};
+
+			channel@29 {
+				gw,mode = <1>;
+				reg = <0x29>;
+				label = "vdd_an1";
+			};
+		};
+	};
+
+	gsc_gpio: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gsc>;
+		interrupts = <4>;
+	};
+
+	eeprom1: eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom2: eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom3: eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom4: eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	rtc: ds1672@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	ltc3676: pmic@3c {
+		compatible = "lltc,ltc3676";
+		reg = <0x3c>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pmic>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+
+		regulators {
+			/* VDD_SOC (1+R1/R2 = 1.635) */
+			reg_vdd_soc: sw1 {
+				regulator-name = "vddsoc";
+				regulator-min-microvolt = <674400>;
+				regulator-max-microvolt = <1308000>;
+				lltc,fb-voltage-divider = <127000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_1P8 (1+R1/R2 = 2.505): GPS/VideoIn/ENET-PHY */
+			reg_1p8v: sw2 {
+				regulator-name = "vdd1p8";
+				regulator-min-microvolt = <1033310>;
+				regulator-max-microvolt = <2004000>;
+				lltc,fb-voltage-divider = <301000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_ARM (1+R1/R2 = 1.635) */
+			reg_vdd_arm: sw3 {
+				regulator-name = "vddarm";
+				regulator-min-microvolt = <674400>;
+				regulator-max-microvolt = <1308000>;
+				lltc,fb-voltage-divider = <127000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_DDR (1+R1/R2 = 2.105) */
+			reg_vdd_ddr: sw4 {
+				regulator-name = "vddddr";
+				regulator-min-microvolt = <868310>;
+				regulator-max-microvolt = <1684000>;
+				lltc,fb-voltage-divider = <221000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_2P5 (1+R1/R2 = 3.435): PCIe/ENET-PHY */
+			reg_2p5v: ldo2 {
+				regulator-name = "vdd2p5";
+				regulator-min-microvolt = <2490375>;
+				regulator-max-microvolt = <2490375>;
+				lltc,fb-voltage-divider = <487000 200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_AUD_1P8: Audio codec */
+			reg_aud_1p8v: ldo3 {
+				regulator-name = "vdd1p8a";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+			};
+
+			/* VDD_HIGH (1+R1/R2 = 4.17) */
+			reg_3p0v: ldo4 {
+				regulator-name = "vdd3p0";
+				regulator-min-microvolt = <3023250>;
+				regulator-max-microvolt = <3023250>;
+				lltc,fb-voltage-divider = <634000 200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	codec: sgtl5000@a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		VDDA-supply = <&reg_1p8v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+
+	touchscreen: egalax_ts@4 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		interrupt-parent = <&gpio7>;
+		interrupts = <12 2>;
+		wakeup-gpios = <&gpio7 12 GPIO_ACTIVE_LOW>;
+	};
+
+	accel@1e {
+		compatible = "nxp,fxos8700";
+		reg = <0x1e>;
+	};
+};
+
+&ldb {
+	status = "okay";
+
+	lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+			};
+		};
+	};
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio1 29 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>; /* MX6_DIO1 */
+	status = "disabled";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>; /* MX6_DIO2 */
+	status = "disabled";
+};
+
+&pwm4 {
+	#pwm-cells = <2>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>;
+	status = "okay";
+};
+
+&ssi1 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	rts-gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+	cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
+	vmmc-supply = <&reg_3p3v>;
+	no-1-8-v; /* firmware will remove if board revision supports */
+	status = "okay";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+};
+
+&iomuxc {
+	pinctrl_audmux: audmuxgrp {
+		fsl,pins = <
+			MX6QDL_PAD_SD2_DAT0__AUD4_RXD		0x130b0
+			MX6QDL_PAD_SD2_DAT3__AUD4_TXC		0x130b0
+			MX6QDL_PAD_SD2_DAT2__AUD4_TXD		0x110b0
+			MX6QDL_PAD_SD2_DAT1__AUD4_TXFS		0x130b0
+			MX6QDL_PAD_GPIO_0__CCM_CLKO1	0x130b0 /* AUD4_MCK */
+		>;
+	};
+
+	pinctrl_ecspi3: escpi3grp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK	0x100b1
+			MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI	0x100b1
+			MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO	0x100b1
+			MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24	0x100b1
+		>;
+	};
+
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b030
+			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b030
+			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b030
+			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030
+			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030
+			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b030
+			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b030
+			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b030
+			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b030
+			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b030
+			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b030
+			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b030
+			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			MX6QDL_PAD_ENET_TXD0__GPIO1_IO30	0x1b0b0 /* PHY Reset */
+		>;
+	};
+
+	pinctrl_flexcan1: flexcan1grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX	0x1b0b1
+			MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX	0x1b0b1
+			MX6QDL_PAD_GPIO_9__GPIO1_IO09		0x4001b0b0 /* CAN_STBY */
+		>;
+	};
+
+	pinctrl_gpio_leds: gpioledsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL0__GPIO4_IO06  0x1b0b0
+			MX6QDL_PAD_KEY_ROW0__GPIO4_IO07  0x1b0b0
+			MX6QDL_PAD_KEY_ROW4__GPIO4_IO15  0x1b0b0
+		>;
+	};
+
+	pinctrl_gpmi_nand: gpminandgrp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+			MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+			MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+			MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+			MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+			MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+			MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+			MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+			MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+			MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+			MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+			MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+			MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+			MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0xb0b1
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_TXD1__GPIO1_IO29	0x1b0b0 /* PCIE_RST# */
+		>;
+	};
+
+	pinctrl_pmic: pmicgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_8__GPIO1_IO08		0x0001b0b0 /* PMIC_IRQ# */
+		>;
+	};
+
+	pinctrl_pps: ppsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_RXD1__GPIO1_IO26	0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT2__PWM2_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT1__PWM3_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm4: pwm4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_CMD__PWM4_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+			MX6QDL_PAD_SD3_DAT4__GPIO7_IO01		0x4001b0b1 /* TEN */
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+			MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			MX6QDL_PAD_EIM_D22__GPIO3_IO22	0x1b0b0 /* OTG_PWR_EN */
+		>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x17059 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x17059
+		>;
+	};
+
+	pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170b9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x170b9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170b9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170b9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170b9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170b9
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x170b9 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x170b9
+		>;
+	};
+
+	pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170f9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100f9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170f9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170f9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170f9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170f9
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x170f9 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x170f9
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT8__WDOG1_B		0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6qdl-gw53xx.dtsi b/arch/arm/dts/imx6qdl-gw53xx.dtsi
new file mode 100644
index 0000000..9deec7e
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-gw53xx.dtsi
@@ -0,0 +1,772 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2013 Gateworks Corporation
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		led0 = &led0;
+		led1 = &led1;
+		led2 = &led2;
+		mmc0 = &usdhc3;
+		nand = &gpmi;
+		ssi0 = &ssi1;
+		usb0 = &usbh1;
+		usb1 = &usbotg;
+	};
+
+	chosen {
+		bootargs = "console=ttymxc1,115200";
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm4 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		user-pb {
+			label = "user_pb";
+			gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+		};
+
+		user-pb1x {
+			label = "user_pb1x";
+			linux,code = <BTN_1>;
+			interrupt-parent = <&gsc>;
+			interrupts = <0>;
+		};
+
+		key-erased {
+			label = "key-erased";
+			linux,code = <BTN_2>;
+			interrupt-parent = <&gsc>;
+			interrupts = <1>;
+		};
+
+		eeprom-wp {
+			label = "eeprom_wp";
+			linux,code = <BTN_3>;
+			interrupt-parent = <&gsc>;
+			interrupts = <2>;
+		};
+
+		tamper {
+			label = "tamper";
+			linux,code = <BTN_4>;
+			interrupt-parent = <&gsc>;
+			interrupts = <5>;
+		};
+
+		switch-hold {
+			label = "switch_hold";
+			linux,code = <BTN_5>;
+			interrupt-parent = <&gsc>;
+			interrupts = <7>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDG */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDR */
+			default-state = "off";
+		};
+
+		led2: user3 {
+			label = "user3";
+			gpios = <&gpio4 15 GPIO_ACTIVE_LOW>; /* MX6_LOCLED# */
+			default-state = "off";
+		};
+	};
+
+	memory@10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x40000000>;
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pps>;
+		gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+		status = "okay";
+	};
+
+	reg_1p0v: regulator-1p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "1P0V";
+		regulator-min-microvolt = <1000000>;
+		regulator-max-microvolt = <1000000>;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_usb_h1_vbus: regulator-usb-h1-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_h1_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	reg_usb_otg_vbus: regulator-usb-otg-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	sound {
+		compatible = "fsl,imx6q-ventana-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "sgtl5000-audio";
+		ssi-controller = <&ssi1>;
+		audio-codec = <&codec>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+		mux-int-port = <1>;
+		mux-ext-port = <4>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	status = "okay";
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
+			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
+				 <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii-id";
+	phy-reset-gpios = <&gpio1 30 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c3>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	gsc: gsc@20 {
+		compatible = "gw,gsc";
+		reg = <0x20>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		#size-cells = <0>;
+
+		adc {
+			compatible = "gw,gsc-adc";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			channel@0 {
+				gw,mode = <0>;
+				reg = <0x00>;
+				label = "temp";
+			};
+
+			channel@2 {
+				gw,mode = <1>;
+				reg = <0x02>;
+				label = "vdd_vin";
+			};
+
+			channel@5 {
+				gw,mode = <1>;
+				reg = <0x05>;
+				label = "vdd_3p3";
+			};
+
+			channel@8 {
+				gw,mode = <1>;
+				reg = <0x08>;
+				label = "vdd_bat";
+			};
+
+			channel@b {
+				gw,mode = <1>;
+				reg = <0x0b>;
+				label = "vdd_5p0";
+			};
+
+			channel@e {
+				gw,mode = <1>;
+				reg = <0xe>;
+				label = "vdd_arm";
+			};
+
+			channel@11 {
+				gw,mode = <1>;
+				reg = <0x11>;
+				label = "vdd_soc";
+			};
+
+			channel@14 {
+				gw,mode = <1>;
+				reg = <0x14>;
+				label = "vdd_3p0";
+			};
+
+			channel@17 {
+				gw,mode = <1>;
+				reg = <0x17>;
+				label = "vdd_1p5";
+			};
+
+			channel@1d {
+				gw,mode = <1>;
+				reg = <0x1d>;
+				label = "vdd_1p8";
+			};
+
+			channel@20 {
+				gw,mode = <1>;
+				reg = <0x20>;
+				label = "vdd_1p0";
+			};
+
+			channel@23 {
+				gw,mode = <1>;
+				reg = <0x23>;
+				label = "vdd_2p5";
+			};
+
+			channel@26 {
+				gw,mode = <1>;
+				reg = <0x26>;
+				label = "vdd_gps";
+			};
+
+			channel@29 {
+				gw,mode = <1>;
+				reg = <0x29>;
+				label = "vdd_an1";
+			};
+		};
+	};
+
+	gsc_gpio: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gsc>;
+		interrupts = <4>;
+	};
+
+	eeprom1: eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom2: eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom3: eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom4: eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	rtc: ds1672@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	ltc3676: pmic@3c {
+		compatible = "lltc,ltc3676";
+		reg = <0x3c>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+
+		regulators {
+			/* VDD_SOC (1+R1/R2 = 1.635) */
+			reg_vdd_soc: sw1 {
+				regulator-name = "vddsoc";
+				regulator-min-microvolt = <674400>;
+				regulator-max-microvolt = <1308000>;
+				lltc,fb-voltage-divider = <127000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_1P8 (1+R1/R2 = 2.505): GPS/VideoIn/ENET-PHY */
+			reg_1p8v: sw2 {
+				regulator-name = "vdd1p8";
+				regulator-min-microvolt = <1033310>;
+				regulator-max-microvolt = <2004000>;
+				lltc,fb-voltage-divider = <301000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_ARM (1+R1/R2 = 1.635) */
+			reg_vdd_arm: sw3 {
+				regulator-name = "vddarm";
+				regulator-min-microvolt = <674400>;
+				regulator-max-microvolt = <1308000>;
+				lltc,fb-voltage-divider = <127000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_DDR (1+R1/R2 = 2.105) */
+			reg_vdd_ddr: sw4 {
+				regulator-name = "vddddr";
+				regulator-min-microvolt = <868310>;
+				regulator-max-microvolt = <1684000>;
+				lltc,fb-voltage-divider = <221000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_2P5 (1+R1/R2 = 3.435): PCIe/ENET-PHY */
+			reg_2p5v: ldo2 {
+				regulator-name = "vdd2p5";
+				regulator-min-microvolt = <2490375>;
+				regulator-max-microvolt = <2490375>;
+				lltc,fb-voltage-divider = <487000 200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_AUD_1P8: Audio codec */
+			reg_aud_1p8v: ldo3 {
+				regulator-name = "vdd1p8a";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+			};
+
+			/* VDD_HIGH (1+R1/R2 = 4.17) */
+			reg_3p0v: ldo4 {
+				regulator-name = "vdd3p0";
+				regulator-min-microvolt = <3023250>;
+				regulator-max-microvolt = <3023250>;
+				lltc,fb-voltage-divider = <634000 200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	codec: sgtl5000@a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		VDDA-supply = <&reg_1p8v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+
+	touchscreen: egalax_ts@4 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <11 2>;
+		wakeup-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
+	};
+
+	accel@1e {
+		compatible = "nxp,fxos8700";
+		reg = <0x1e>;
+	};
+};
+
+&ldb {
+	status = "okay";
+
+	lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+			};
+		};
+	};
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio1 29 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>; /* MX6_DIO1 */
+	status = "disabled";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>; /* MX6_DIO2 */
+	status = "disabled";
+};
+
+&pwm4 {
+	#pwm-cells = <2>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>;
+	status = "okay";
+};
+
+&ssi1 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	rts-gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_h1_vbus>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+	cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
+	vmmc-supply = <&reg_3p3v>;
+	no-1-8-v; /* firmware will remove if board revision supports */
+	status = "okay";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+};
+
+&iomuxc {
+	pinctrl_audmux: audmuxgrp {
+		fsl,pins = <
+			MX6QDL_PAD_SD2_DAT0__AUD4_RXD		0x130b0
+			MX6QDL_PAD_SD2_DAT3__AUD4_TXC		0x130b0
+			MX6QDL_PAD_SD2_DAT2__AUD4_TXD		0x110b0
+			MX6QDL_PAD_SD2_DAT1__AUD4_TXFS		0x130b0
+			MX6QDL_PAD_GPIO_0__CCM_CLKO1		0x130b0 /* AUD4_MCK */
+		>;
+	};
+
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b030
+			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b030
+			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b030
+			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030
+			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030
+			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b030
+			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b030
+			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b030
+			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b030
+			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b030
+			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b030
+			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b030
+			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+		>;
+	};
+
+	pinctrl_flexcan1: flexcan1grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX	0x1b0b1
+			MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX	0x1b0b1
+			MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x4001b0b0 /* CAN_STBY */
+		>;
+	};
+
+	pinctrl_gpio_leds: gpioledsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL0__GPIO4_IO06   0x1b0b0
+			MX6QDL_PAD_KEY_ROW0__GPIO4_IO07   0x1b0b0
+			MX6QDL_PAD_KEY_ROW4__GPIO4_IO15   0x1b0b0
+		>;
+	};
+
+	pinctrl_gpmi_nand: gpminandgrp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+			MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+			MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+			MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+			MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+			MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+			MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+			MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+			MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+			MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+			MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+			MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+			MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+			MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0xb0b1
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x1b0b0 /* PCIE IRQ */
+			MX6QDL_PAD_ENET_TXD1__GPIO1_IO29  0x1b0b0 /* PCIE RST */
+		>;
+	};
+
+	pinctrl_pmic: pmicgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_8__GPIO1_IO08		0x0001b0b0 /* PMIC_IRQ# */
+		>;
+	};
+
+	pinctrl_pps: ppsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_RXD1__GPIO1_IO26	0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT2__PWM2_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT1__PWM3_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm4: pwm4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_CMD__PWM4_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+			MX6QDL_PAD_SD3_DAT4__GPIO7_IO01		0x4001b0b1 /* TEN */
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+			MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			MX6QDL_PAD_EIM_D22__GPIO3_IO22		0x1b0b0 /* PWR_EN */
+			MX6QDL_PAD_KEY_COL4__GPIO4_IO14		0x1b0b0 /* OC */
+		>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x17059 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x17059
+		>;
+	};
+
+	pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170b9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100b9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170b9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170b9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170b9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170b9
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x170b9 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x170b9
+		>;
+	};
+
+	pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170f9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100f9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170f9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170f9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170f9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170f9
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x170f9 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x170f9
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT8__WDOG1_B		0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6qdl-gw54xx.dtsi b/arch/arm/dts/imx6qdl-gw54xx.dtsi
new file mode 100644
index 0000000..a30ba48
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-gw54xx.dtsi
@@ -0,0 +1,866 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2013 Gateworks Corporation
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/sound/fsl-imx-audmux.h>
+
+/ {
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		led0 = &led0;
+		led1 = &led1;
+		led2 = &led2;
+		mmc0 = &usdhc3;
+		nand = &gpmi;
+		ssi0 = &ssi1;
+		usb0 = &usbh1;
+		usb1 = &usbotg;
+	};
+
+	chosen {
+		bootargs = "console=ttymxc1,115200";
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm4 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		user-pb {
+			label = "user_pb";
+			gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+		};
+
+		user-pb1x {
+			label = "user_pb1x";
+			linux,code = <BTN_1>;
+			interrupt-parent = <&gsc>;
+			interrupts = <0>;
+		};
+
+		key-erased {
+			label = "key-erased";
+			linux,code = <BTN_2>;
+			interrupt-parent = <&gsc>;
+			interrupts = <1>;
+		};
+
+		eeprom-wp {
+			label = "eeprom_wp";
+			linux,code = <BTN_3>;
+			interrupt-parent = <&gsc>;
+			interrupts = <2>;
+		};
+
+		tamper {
+			label = "tamper";
+			linux,code = <BTN_4>;
+			interrupt-parent = <&gsc>;
+			interrupts = <5>;
+		};
+
+		switch-hold {
+			label = "switch_hold";
+			linux,code = <BTN_5>;
+			interrupt-parent = <&gsc>;
+			interrupts = <7>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDG */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDR */
+			default-state = "off";
+		};
+
+		led2: user3 {
+			label = "user3";
+			gpios = <&gpio4 15 GPIO_ACTIVE_LOW>; /* MX6_LOCLED# */
+			default-state = "off";
+		};
+	};
+
+	memory@10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x40000000>;
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pps>;
+		gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+		status = "okay";
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_1p0v: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "1P0V";
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+			regulator-always-on;
+		};
+
+		reg_3p3v: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_usb_h1_vbus: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "usb_h1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		reg_usb_otg_vbus: regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+	};
+
+	sound-analog {
+		compatible = "fsl,imx6q-ventana-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "sgtl5000-audio";
+		ssi-controller = <&ssi1>;
+		audio-codec = <&sgtl5000>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+		mux-int-port = <1>;
+		mux-ext-port = <4>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>; /* AUD4<->sgtl5000 */
+	status = "okay";
+
+	ssi2 {
+		fsl,audmux-port = <1>;
+		fsl,port-config = <
+			(IMX_AUDMUX_V2_PTCR_TFSDIR |
+			IMX_AUDMUX_V2_PTCR_TFSEL(4+8) | /* RXFS */
+			IMX_AUDMUX_V2_PTCR_TCLKDIR |
+			IMX_AUDMUX_V2_PTCR_TCSEL(4+8) | /* RXC */
+			IMX_AUDMUX_V2_PTCR_SYN)
+			IMX_AUDMUX_V2_PDCR_RXDSEL(4)
+		>;
+	};
+
+	aud5 {
+		fsl,audmux-port = <4>;
+		fsl,port-config = <
+			IMX_AUDMUX_V2_PTCR_SYN
+			IMX_AUDMUX_V2_PDCR_RXDSEL(1)>;
+	};
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	status = "okay";
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
+			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
+				 <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
+};
+
+&ecspi2 {
+	cs-gpios = <&gpio2 26 GPIO_ACTIVE_LOW>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi2>;
+	status = "okay";
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii-id";
+	phy-reset-gpios = <&gpio1 30 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c3>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	gsc: gsc@20 {
+		compatible = "gw,gsc";
+		reg = <0x20>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		adc {
+			compatible = "gw,gsc-adc";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			channel@0 {
+				gw,mode = <0>;
+				reg = <0x00>;
+				label = "temp";
+			};
+
+			channel@2 {
+				gw,mode = <1>;
+				reg = <0x02>;
+				label = "vdd_vin";
+			};
+
+			channel@5 {
+				gw,mode = <1>;
+				reg = <0x05>;
+				label = "vdd_3p3";
+			};
+
+			channel@8 {
+				gw,mode = <1>;
+				reg = <0x08>;
+				label = "vdd_bat";
+			};
+
+			channel@b {
+				gw,mode = <1>;
+				reg = <0x0b>;
+				label = "vdd_5p0";
+			};
+
+			channel@e {
+				gw,mode = <1>;
+				reg = <0xe>;
+				label = "vdd_arm";
+			};
+
+			channel@11 {
+				gw,mode = <1>;
+				reg = <0x11>;
+				label = "vdd_soc";
+			};
+
+			channel@14 {
+				gw,mode = <1>;
+				reg = <0x14>;
+				label = "vdd_3p0";
+			};
+
+			channel@17 {
+				gw,mode = <1>;
+				reg = <0x17>;
+				label = "vdd_1p5";
+			};
+
+			channel@1d {
+				gw,mode = <1>;
+				reg = <0x1d>;
+				label = "vdd_1p8";
+			};
+
+			channel@20 {
+				gw,mode = <1>;
+				reg = <0x20>;
+				label = "vdd_1p0";
+			};
+
+			channel@23 {
+				gw,mode = <1>;
+				reg = <0x23>;
+				label = "vdd_2p5";
+			};
+
+			channel@26 {
+				gw,mode = <1>;
+				reg = <0x26>;
+				label = "vdd_gps";
+			};
+		};
+
+		fan-controller@2c {
+			compatible = "gw,gsc-fan";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x2c>;
+		};
+	};
+
+	gsc_gpio: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gsc>;
+		interrupts = <4>;
+	};
+
+	eeprom1: eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom2: eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom3: eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom4: eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	rtc: ds1672@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	pmic: pfuze100@8 {
+		compatible = "fsl,pfuze100";
+		reg = <0x08>;
+
+		regulators {
+			sw1a_reg: sw1ab {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw1c_reg: sw1c {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3950000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3a_reg: sw3a {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3b_reg: sw3b {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw4_reg: sw4 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			swbst_reg: swbst {
+				regulator-min-microvolt = <5000000>;
+				regulator-max-microvolt = <5150000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			snvs_reg: vsnvs {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vref_reg: vrefddr {
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen1_reg: vgen1 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen2_reg: vgen2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen3_reg: vgen3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vgen4_reg: vgen4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen5_reg: vgen5 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen6_reg: vgen6 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	sgtl5000: audio-codec@a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		VDDA-supply = <&sw4_reg>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+
+	touchscreen: egalax_ts@4 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		interrupt-parent = <&gpio7>;
+		interrupts = <12 2>;
+		wakeup-gpios = <&gpio7 12 GPIO_ACTIVE_LOW>;
+	};
+
+	accel@1e {
+		compatible = "nxp,fxos8700";
+		reg = <0x1e>;
+	};
+};
+
+&ldb {
+	status = "okay";
+
+	lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+			};
+		};
+	};
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio1 29 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>; /* MX6_DIO0 */
+	status = "disabled";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>; /* MX6_DIO1 */
+	status = "disabled";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>; /* MX6_DIO2 */
+	status = "disabled";
+};
+
+&pwm4 {
+	#pwm-cells = <2>;
+	pinctrl-names = "default", "state_dio";
+	pinctrl-0 = <&pinctrl_pwm4_backlight>;
+	pinctrl-1 = <&pinctrl_pwm4_dio>;
+	status = "okay";
+};
+
+&ssi1 {
+	status = "okay";
+};
+
+&ssi2 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	rts-gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_h1_vbus>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+	cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
+	vmmc-supply = <&reg_3p3v>;
+	no-1-8-v; /* firmware will remove if board revision supports */
+	status = "okay";
+};
+
+&wdog1 {
+	status = "disabled";
+};
+
+&wdog2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl_audmux: audmuxgrp {
+		fsl,pins = <
+			MX6QDL_PAD_SD2_DAT0__AUD4_RXD		0x130b0
+			MX6QDL_PAD_SD2_DAT3__AUD4_TXC		0x130b0
+			MX6QDL_PAD_SD2_DAT2__AUD4_TXD		0x110b0
+			MX6QDL_PAD_SD2_DAT1__AUD4_TXFS		0x130b0
+			MX6QDL_PAD_GPIO_0__CCM_CLKO1		0x130b0 /* AUD4_MCK */
+			MX6QDL_PAD_EIM_D25__AUD5_RXC            0x130b0
+			MX6QDL_PAD_DISP0_DAT19__AUD5_RXD        0x130b0
+			MX6QDL_PAD_EIM_D24__AUD5_RXFS           0x130b0
+		>;
+	};
+
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b030
+			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b030
+			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b030
+			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030
+			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030
+			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b030
+			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b030
+			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b030
+			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b030
+			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b030
+			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b030
+			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b030
+			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+		>;
+	};
+
+	pinctrl_ecspi2: escpi2grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_CS0__ECSPI2_SCLK	0x100b1
+			MX6QDL_PAD_EIM_CS1__ECSPI2_MOSI	0x100b1
+			MX6QDL_PAD_EIM_OE__ECSPI2_MISO	0x100b1
+			MX6QDL_PAD_EIM_RW__GPIO2_IO26	0x100b1
+		>;
+	};
+
+	pinctrl_flexcan1: flexcan1grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX	0x1b0b1
+			MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX	0x1b0b1
+			MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x4001b0b0 /* CAN_STBY */
+		>;
+	};
+
+	pinctrl_gpio_leds: gpioledsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL0__GPIO4_IO06		0x1b0b0
+			MX6QDL_PAD_KEY_ROW0__GPIO4_IO07		0x1b0b0
+			MX6QDL_PAD_KEY_ROW4__GPIO4_IO15		0x1b0b0
+		>;
+	};
+
+	pinctrl_gpmi_nand: gpminandgrp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+			MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+			MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+			MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+			MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+			MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+			MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+			MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+			MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+			MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+			MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+			MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+			MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+			MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0xb0b1
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28	0x1b0b0 /* PCIE IRQ */
+			MX6QDL_PAD_ENET_TXD1__GPIO1_IO29	0x1b0b0 /* PCIE RST */
+		>;
+	};
+
+	pinctrl_pps: ppsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_RXD1__GPIO1_IO26	0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm1: pwm1grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_9__PWM1_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT2__PWM2_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT1__PWM3_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm4_backlight: pwm4grpbacklight {
+		fsl,pins = <
+			/* LVDS_PWM J6.5 */
+			MX6QDL_PAD_SD1_CMD__PWM4_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm4_dio: pwm4grpdio {
+		fsl,pins = <
+			/* DIO3 J16.4 */
+			MX6QDL_PAD_SD4_DAT2__PWM4_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+			MX6QDL_PAD_SD3_DAT4__GPIO7_IO01		0x4001b0b1 /* TEN */
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+			MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			MX6QDL_PAD_EIM_D22__GPIO3_IO22		0x1b0b0 /* PWR_EN */
+		>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x17059 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x17059
+		>;
+	};
+
+	pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170b9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100b9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170b9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170b9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170b9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170b9
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x170b9 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x170b9
+		>;
+	};
+
+	pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170f9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100f9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170f9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170f9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170f9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170f9
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x170f9 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x170f9
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT3__WDOG2_B		0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6qdl-gw551x.dtsi b/arch/arm/dts/imx6qdl-gw551x.dtsi
new file mode 100644
index 0000000..1bb586c
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-gw551x.dtsi
@@ -0,0 +1,698 @@
+/*
+ * Copyright 2014 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/media/tda1997x.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/sound/fsl-imx-audmux.h>
+
+/ {
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		led0 = &led0;
+		nand = &gpmi;
+		ssi0 = &ssi1;
+		usb0 = &usbh1;
+		usb1 = &usbotg;
+	};
+
+	chosen {
+		bootargs = "console=ttymxc1,115200";
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		user-pb {
+			label = "user_pb";
+			gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+		};
+
+		user-pb1x {
+			label = "user_pb1x";
+			linux,code = <BTN_1>;
+			interrupt-parent = <&gsc>;
+			interrupts = <0>;
+		};
+
+		key-erased {
+			label = "key-erased";
+			linux,code = <BTN_2>;
+			interrupt-parent = <&gsc>;
+			interrupts = <1>;
+		};
+
+		eeprom-wp {
+			label = "eeprom_wp";
+			linux,code = <BTN_3>;
+			interrupt-parent = <&gsc>;
+			interrupts = <2>;
+		};
+
+		tamper {
+			label = "tamper";
+			linux,code = <BTN_4>;
+			interrupt-parent = <&gsc>;
+			interrupts = <5>;
+		};
+
+		switch-hold {
+			label = "switch_hold";
+			linux,code = <BTN_5>;
+			interrupt-parent = <&gsc>;
+			interrupts = <7>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 7 GPIO_ACTIVE_LOW>;
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	memory@10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x20000000>;
+	};
+
+	reg_5p0v: regulator-5p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "5P0V";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
+
+	reg_usb_h1_vbus: regulator-usb-h1-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_h1_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
+
+	reg_usb_otg_vbus: regulator-usb-otg-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
+
+	sound-digital {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "tda1997x-audio";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&sound_codec>;
+		simple-audio-card,frame-master = <&sound_codec>;
+
+		sound_cpu: simple-audio-card,cpu {
+			sound-dai = <&ssi1>;
+		};
+
+		sound_codec: simple-audio-card,codec {
+			sound-dai = <&hdmi_receiver>;
+		};
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>; /* AUD5<->tda1997x */
+	status = "okay";
+
+	ssi1 {
+		fsl,audmux-port = <0>;
+		fsl,port-config = <
+			(IMX_AUDMUX_V2_PTCR_TFSDIR |
+			IMX_AUDMUX_V2_PTCR_TFSEL(4+8) | /* RXFS */
+			IMX_AUDMUX_V2_PTCR_TCLKDIR |
+			IMX_AUDMUX_V2_PTCR_TCSEL(4+8) | /* RXC */
+			IMX_AUDMUX_V2_PTCR_SYN)
+			IMX_AUDMUX_V2_PDCR_RXDSEL(4)
+		>;
+	};
+
+	aud5 {
+		fsl,audmux-port = <4>;
+		fsl,port-config = <
+			IMX_AUDMUX_V2_PTCR_SYN
+			IMX_AUDMUX_V2_PDCR_RXDSEL(0)>;
+	};
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c3>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	gsc: gsc@20 {
+		compatible = "gw,gsc";
+		reg = <0x20>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		#size-cells = <0>;
+
+		adc {
+			compatible = "gw,gsc-adc";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			channel@0 {
+				gw,mode = <0>;
+				reg = <0x00>;
+				label = "temp";
+			};
+
+			channel@2 {
+				gw,mode = <1>;
+				reg = <0x02>;
+				label = "vdd_vin";
+			};
+
+			channel@5 {
+				gw,mode = <1>;
+				reg = <0x05>;
+				label = "vdd_3p3";
+			};
+
+			channel@8 {
+				gw,mode = <1>;
+				reg = <0x08>;
+				label = "vdd_bat";
+			};
+
+			channel@b {
+				gw,mode = <1>;
+				reg = <0x0b>;
+				label = "vdd_5p0";
+			};
+
+			channel@e {
+				gw,mode = <1>;
+				reg = <0xe>;
+				label = "vdd_arm";
+			};
+
+			channel@11 {
+				gw,mode = <1>;
+				reg = <0x11>;
+				label = "vdd_soc";
+			};
+
+			channel@14 {
+				gw,mode = <1>;
+				reg = <0x14>;
+				label = "vdd_3p0";
+			};
+
+			channel@17 {
+				gw,mode = <1>;
+				reg = <0x17>;
+				label = "vdd_1p5";
+			};
+
+			channel@1d {
+				gw,mode = <1>;
+				reg = <0x1d>;
+				label = "vdd_1p8a";
+			};
+
+			channel@20 {
+				gw,mode = <1>;
+				reg = <0x20>;
+				label = "vdd_1p0b";
+			};
+		};
+	};
+
+	gsc_gpio: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gsc>;
+		interrupts = <4>;
+	};
+
+	eeprom1: eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom2: eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom3: eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom4: eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	rtc: ds1672@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	ltc3676: pmic@3c {
+		compatible = "lltc,ltc3676";
+		reg = <0x3c>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pmic>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+
+		regulators {
+			/* VDD_SOC (1+R1/R2 = 1.635) */
+			reg_vdd_soc: sw1 {
+				regulator-name = "vddsoc";
+				regulator-min-microvolt = <674400>;
+				regulator-max-microvolt = <1308000>;
+				lltc,fb-voltage-divider = <127000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_DDR (1+R1/R2 = 2.105) */
+			reg_vdd_ddr: sw2 {
+				regulator-name = "vddddr";
+				regulator-min-microvolt = <868310>;
+				regulator-max-microvolt = <1684000>;
+				lltc,fb-voltage-divider = <221000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_ARM (1+R1/R2 = 1.635) */
+			reg_vdd_arm: sw3 {
+				regulator-name = "vddarm";
+				regulator-min-microvolt = <674400>;
+				regulator-max-microvolt = <1308000>;
+				lltc,fb-voltage-divider = <127000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_3P3 (1+R1/R2 = 1.281) */
+			reg_3p3: sw4 {
+				regulator-name = "vdd3p3";
+				regulator-min-microvolt = <1880000>;
+				regulator-max-microvolt = <3647000>;
+				lltc,fb-voltage-divider = <200000 56200>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_1P8a (1+R1/R2 = 2.505): HDMI In core */
+			reg_1p8a: ldo2 {
+				regulator-name = "vdd1p8a";
+				regulator-min-microvolt = <1816125>;
+				regulator-max-microvolt = <1816125>;
+				lltc,fb-voltage-divider = <301000 200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_1P8b: HDMI In analog */
+			reg_1p8b: ldo3 {
+				regulator-name = "vdd1p8b";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+			};
+
+			/* VDD_HIGH (1+R1/R2 = 4.17) */
+			reg_3p0: ldo4 {
+				regulator-name = "vdd3p0";
+				regulator-min-microvolt = <3023250>;
+				regulator-max-microvolt = <3023250>;
+				lltc,fb-voltage-divider = <634000 200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	gpio_exp: pca9555@24 {
+		compatible = "nxp,pca9555";
+		reg = <0x24>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	hdmi_receiver: hdmi-receiver@48 {
+		compatible = "nxp,tda19971";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_tda1997x>;
+		reg = <0x48>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+		DOVDD-supply = <&reg_3p3>;
+		AVDD-supply = <&reg_1p8b>;
+		DVDD-supply = <&reg_1p8a>;
+		#sound-dai-cells = <0>;
+		nxp,audout-format = "i2s";
+		nxp,audout-layout = <0>;
+		nxp,audout-width = <16>;
+		nxp,audout-mclk-fs = <128>;
+		/*
+		 * The 8bpp YUV422 semi-planar mode outputs CbCr[11:4]
+		 * and Y[11:4] across 16bits in the same cycle
+		 * which we map to VP[15:08]<->CSI_DATA[19:12]
+		 */
+		nxp,vidout-portcfg =
+			/*G_Y_11_8<->VP[15:12]<->CSI_DATA[19:16]*/
+			< TDA1997X_VP24_V15_12 TDA1997X_G_Y_11_8 >,
+			/*G_Y_7_4<->VP[11:08]<->CSI_DATA[15:12]*/
+			< TDA1997X_VP24_V11_08 TDA1997X_G_Y_7_4 >,
+			/*R_CR_CBCR_11_8<->VP[07:04]<->CSI_DATA[11:08]*/
+			< TDA1997X_VP24_V07_04 TDA1997X_R_CR_CBCR_11_8 >,
+			/*R_CR_CBCR_7_4<->VP[03:00]<->CSI_DATA[07:04]*/
+			< TDA1997X_VP24_V03_00 TDA1997X_R_CR_CBCR_7_4 >;
+
+		port {
+			tda1997x_to_ipu1_csi0_mux: endpoint {
+				remote-endpoint = <&ipu1_csi0_mux_from_parallel_sensor>;
+				bus-width = <16>;
+				hsync-active = <1>;
+				vsync-active = <1>;
+				data-active = <1>;
+			};
+		};
+	};
+};
+
+&ipu1_csi0_from_ipu1_csi0_mux {
+	bus-width = <16>;
+};
+
+&ipu1_csi0_mux_from_parallel_sensor {
+	remote-endpoint = <&tda1997x_to_ipu1_csi0_mux>;
+	bus-width = <16>;
+};
+
+&ipu1_csi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ipu1_csi0>;
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio1 0 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>; /* MX6_DIO1 */
+	status = "disabled";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>; /* MX6_DIO2 */
+	status = "disabled";
+};
+
+&ssi1 {
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_h1_vbus>;
+	status = "okay";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+};
+
+&iomuxc {
+	pinctrl_audmux: audmuxgrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT19__AUD5_RXD	0x130b0
+			MX6QDL_PAD_DISP0_DAT14__AUD5_RXC	0x130b0
+			MX6QDL_PAD_DISP0_DAT13__AUD5_RXFS	0x130b0
+		>;
+	};
+
+	pinctrl_flexcan1: flexcan1grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX	0x1b0b1
+			MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX	0x1b0b1
+			MX6QDL_PAD_GPIO_9__GPIO1_IO09		0x4001b0b0 /* CAN_STBY */
+		>;
+	};
+
+	pinctrl_gpio_leds: gpioledsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_ROW0__GPIO4_IO07   0x1b0b0
+		>;
+	};
+
+	pinctrl_gpmi_nand: gpminandgrp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+			MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+			MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+			MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+			MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+			MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+			MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+			MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+			MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+			MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+			MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+			MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+			MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+			MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0xb0b1
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_ipu1_csi0: ipu1_csi0grp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT4__IPU1_CSI0_DATA04		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT5__IPU1_CSI0_DATA05		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT6__IPU1_CSI0_DATA06		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT7__IPU1_CSI0_DATA07		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT8__IPU1_CSI0_DATA08		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT9__IPU1_CSI0_DATA09		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT10__IPU1_CSI0_DATA10		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT11__IPU1_CSI0_DATA11		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18		0x1b0b0
+			MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19		0x1b0b0
+			MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC		0x1b0b0
+			MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK	0x1b0b0
+			MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC		0x1b0b0
+		>;
+	};
+
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_0__GPIO1_IO00		0x1b0b0 /* PCIE RST */
+		>;
+	};
+
+	pinctrl_pmic: pmicgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_8__GPIO1_IO08		0x0001b0b0 /* PMIC_IRQ# */
+		>;
+	};
+
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT2__PWM2_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT1__PWM3_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_tda1997x: tda1997xgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_7__GPIO1_IO07		0x1b0b0
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT8__WDOG1_B		0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6qdl-gw552x.dtsi b/arch/arm/dts/imx6qdl-gw552x.dtsi
new file mode 100644
index 0000000..5462907
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-gw552x.dtsi
@@ -0,0 +1,522 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2014 Gateworks Corporation
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		led0 = &led0;
+		led1 = &led1;
+		led2 = &led2;
+		nand = &gpmi;
+		usb0 = &usbh1;
+		usb1 = &usbotg;
+	};
+
+	chosen {
+		bootargs = "console=ttymxc1,115200";
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		user-pb {
+			label = "user_pb";
+			gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+		};
+
+		user-pb1x {
+			label = "user_pb1x";
+			linux,code = <BTN_1>;
+			interrupt-parent = <&gsc>;
+			interrupts = <0>;
+		};
+
+		key-erased {
+			label = "key-erased";
+			linux,code = <BTN_2>;
+			interrupt-parent = <&gsc>;
+			interrupts = <1>;
+		};
+
+		eeprom-wp {
+			label = "eeprom_wp";
+			linux,code = <BTN_3>;
+			interrupt-parent = <&gsc>;
+			interrupts = <2>;
+		};
+
+		tamper {
+			label = "tamper";
+			linux,code = <BTN_4>;
+			interrupt-parent = <&gsc>;
+			interrupts = <5>;
+		};
+
+		switch-hold {
+			label = "switch_hold";
+			linux,code = <BTN_5>;
+			interrupt-parent = <&gsc>;
+			interrupts = <7>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDG */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDR */
+			default-state = "off";
+		};
+
+		led2: user3 {
+			label = "user3";
+			gpios = <&gpio4 15 GPIO_ACTIVE_LOW>; /* MX6_LOCLED# */
+			default-state = "off";
+		};
+	};
+
+	memory@10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x20000000>;
+	};
+
+	reg_1p0v: regulator-1p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "1P0V";
+		regulator-min-microvolt = <1000000>;
+		regulator-max-microvolt = <1000000>;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_5p0v: regulator-5p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "5P0V";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c3>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	gsc: gsc@20 {
+		compatible = "gw,gsc";
+		reg = <0x20>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		#size-cells = <0>;
+
+		adc {
+			compatible = "gw,gsc-adc";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			channel@0 {
+				gw,mode = <0>;
+				reg = <0x00>;
+				label = "temp";
+			};
+
+			channel@2 {
+				gw,mode = <1>;
+				reg = <0x02>;
+				label = "vdd_vin";
+			};
+
+			channel@5 {
+				gw,mode = <1>;
+				reg = <0x05>;
+				label = "vdd_3p3";
+			};
+
+			channel@8 {
+				gw,mode = <1>;
+				reg = <0x08>;
+				label = "vdd_bat";
+			};
+
+			channel@b {
+				gw,mode = <1>;
+				reg = <0x0b>;
+				label = "vdd_5p0";
+			};
+
+			channel@e {
+				gw,mode = <1>;
+				reg = <0xe>;
+				label = "vdd_arm";
+			};
+
+			channel@11 {
+				gw,mode = <1>;
+				reg = <0x11>;
+				label = "vdd_soc";
+			};
+
+			channel@14 {
+				gw,mode = <1>;
+				reg = <0x14>;
+				label = "vdd_3p0";
+			};
+
+			channel@17 {
+				gw,mode = <1>;
+				reg = <0x17>;
+				label = "vdd_1p5";
+			};
+
+			channel@1d {
+				gw,mode = <1>;
+				reg = <0x1d>;
+				label = "vdd_1p8";
+			};
+
+			channel@20 {
+				gw,mode = <1>;
+				reg = <0x20>;
+				label = "vdd_1p0";
+			};
+
+			channel@23 {
+				gw,mode = <1>;
+				reg = <0x23>;
+				label = "vdd_2p5";
+			};
+		};
+	};
+
+	gsc_gpio: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gsc>;
+		interrupts = <4>;
+	};
+
+	eeprom1: eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom2: eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom3: eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom4: eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	rtc: ds1672@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	ltc3676: pmic@3c {
+		compatible = "lltc,ltc3676";
+		reg = <0x3c>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pmic>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+
+		regulators {
+			/* VDD_SOC (1+R1/R2 = 1.635) */
+			reg_vdd_soc: sw1 {
+				regulator-name = "vddsoc";
+				regulator-min-microvolt = <674400>;
+				regulator-max-microvolt = <1308000>;
+				lltc,fb-voltage-divider = <127000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_1P8 (1+R1/R2 = 2.505): ENET-PHY */
+			reg_1p8v: sw2 {
+				regulator-name = "vdd1p8";
+				regulator-min-microvolt = <1033310>;
+				regulator-max-microvolt = <2004000>;
+				lltc,fb-voltage-divider = <301000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_ARM (1+R1/R2 = 1.635) */
+			reg_vdd_arm: sw3 {
+				regulator-name = "vddarm";
+				regulator-min-microvolt = <674400>;
+				regulator-max-microvolt = <1308000>;
+				lltc,fb-voltage-divider = <127000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_DDR (1+R1/R2 = 2.105) */
+			reg_vdd_ddr: sw4 {
+				regulator-name = "vddddr";
+				regulator-min-microvolt = <868310>;
+				regulator-max-microvolt = <1684000>;
+				lltc,fb-voltage-divider = <221000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_2P5 (1+R1/R2 = 3.435): PCIe/ENET-PHY */
+			reg_2p5v: ldo2 {
+				regulator-name = "vdd2p5";
+				regulator-min-microvolt = <2490375>;
+				regulator-max-microvolt = <2490375>;
+				lltc,fb-voltage-divider = <487000 200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_HIGH (1+R1/R2 = 4.17) */
+			reg_3p0v: ldo4 {
+				regulator-name = "vdd3p0";
+				regulator-min-microvolt = <3023250>;
+				regulator-max-microvolt = <3023250>;
+				lltc,fb-voltage-divider = <634000 200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio1 29 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>; /* MX6_DIO1 */
+	status = "disabled";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>; /* MX6_DIO2 */
+	status = "disabled";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay"; };
+
+&usbh1 {
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_5p0v>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+};
+
+&iomuxc {
+	pinctrl_gpio_leds: gpioledsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL0__GPIO4_IO06		0x1b0b0
+			MX6QDL_PAD_KEY_ROW0__GPIO4_IO07		0x1b0b0
+			MX6QDL_PAD_KEY_ROW4__GPIO4_IO15		0x1b0b0
+		>;
+	};
+
+	pinctrl_gpmi_nand: gpminandgrp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+			MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+			MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+			MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+			MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+			MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+			MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+			MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+			MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+			MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+			MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+			MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+			MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+			MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0xb0b1
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_TXD1__GPIO1_IO29	0x1b0b0
+		>;
+	};
+
+	pinctrl_pmic: pmicgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_8__GPIO1_IO08		0x0001b0b0 /* PMIC_IRQ# */
+		>;
+	};
+
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT2__PWM2_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT1__PWM3_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+			MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID	0x13059
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT8__WDOG1_B		0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6qdl-gw553x.dtsi b/arch/arm/dts/imx6qdl-gw553x.dtsi
new file mode 100644
index 0000000..b6965f2
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-gw553x.dtsi
@@ -0,0 +1,738 @@
+/*
+ * Copyright 2016 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		led0 = &led0;
+		led1 = &led1;
+		nand = &gpmi;
+		usb0 = &usbh1;
+		usb1 = &usbotg;
+	};
+
+	chosen {
+		stdout-path = &uart2;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		user-pb {
+			label = "user_pb";
+			gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+		};
+
+		user-pb1x {
+			label = "user_pb1x";
+			linux,code = <BTN_1>;
+			interrupt-parent = <&gsc>;
+			interrupts = <0>;
+		};
+
+		key-erased {
+			label = "key-erased";
+			linux,code = <BTN_2>;
+			interrupt-parent = <&gsc>;
+			interrupts = <1>;
+		};
+
+		eeprom-wp {
+			label = "eeprom_wp";
+			linux,code = <BTN_3>;
+			interrupt-parent = <&gsc>;
+			interrupts = <2>;
+		};
+
+		tamper {
+			label = "tamper";
+			linux,code = <BTN_4>;
+			interrupt-parent = <&gsc>;
+			interrupts = <5>;
+		};
+
+		switch-hold {
+			label = "switch_hold";
+			linux,code = <BTN_5>;
+			interrupt-parent = <&gsc>;
+			interrupts = <7>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 10 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDG */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio4 11 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDR */
+			default-state = "off";
+		};
+	};
+
+	memory@10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x20000000>;
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pps>;
+		gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+		status = "okay";
+	};
+
+	reg_5p0v: regulator-5p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "5P0V";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	reg_usb_otg_vbus: regulator-usb-otg-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&hdmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hdmi>;
+	ddc-i2c-bus = <&i2c3>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	gsc: gsc@20 {
+		compatible = "gw,gsc";
+		reg = <0x20>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		#size-cells = <0>;
+
+		adc {
+			compatible = "gw,gsc-adc";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			channel@0 {
+				gw,mode = <0>;
+				reg = <0x00>;
+				label = "temp";
+			};
+
+			channel@2 {
+				gw,mode = <1>;
+				reg = <0x02>;
+				label = "vdd_vin";
+			};
+
+			channel@5 {
+				gw,mode = <1>;
+				reg = <0x05>;
+				label = "vdd_3p3";
+			};
+
+			channel@8 {
+				gw,mode = <1>;
+				reg = <0x08>;
+				label = "vdd_bat";
+			};
+
+			channel@b {
+				gw,mode = <1>;
+				reg = <0x0b>;
+				label = "vdd_5p0";
+			};
+
+			channel@e {
+				gw,mode = <1>;
+				reg = <0xe>;
+				label = "vdd_arm";
+			};
+
+			channel@11 {
+				gw,mode = <1>;
+				reg = <0x11>;
+				label = "vdd_soc";
+			};
+
+			channel@14 {
+				gw,mode = <1>;
+				reg = <0x14>;
+				label = "vdd_3p0";
+			};
+
+			channel@17 {
+				gw,mode = <1>;
+				reg = <0x17>;
+				label = "vdd_1p5";
+			};
+
+			channel@1d {
+				gw,mode = <1>;
+				reg = <0x1d>;
+				label = "vdd_1p8a";
+			};
+
+			channel@20 {
+				gw,mode = <1>;
+				reg = <0x20>;
+				label = "vdd_1p0b";
+			};
+
+			channel@26 {
+				gw,mode = <1>;
+				reg = <0x26>;
+				label = "vdd_an1";
+			};
+		};
+	};
+
+	gsc_gpio: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gsc>;
+		interrupts = <4>;
+	};
+
+	eeprom1: eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom2: eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom3: eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom4: eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	rtc: ds1672@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	magn@1c {
+		compatible = "st,lsm9ds1-magn";
+		reg = <0x1c>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_mag>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <2 IRQ_TYPE_EDGE_RISING>;
+	};
+
+	imu@6a {
+		compatible = "st,lsm9ds1-imu";
+		reg = <0x6a>;
+		st,drdy-int-pin = <1>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_imu>;
+		interrupt-parent = <&gpio7>;
+		interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	ltc3676: pmic@3c {
+		compatible = "lltc,ltc3676";
+		reg = <0x3c>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pmic>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+
+		regulators {
+			/* VDD_SOC (1+R1/R2 = 1.635) */
+			reg_vdd_soc: sw1 {
+				regulator-name = "vddsoc";
+				regulator-min-microvolt = <674400>;
+				regulator-max-microvolt = <1308000>;
+				lltc,fb-voltage-divider = <127000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_DDR (1+R1/R2 = 2.105) */
+			reg_vdd_ddr: sw2 {
+				regulator-name = "vddddr";
+				regulator-min-microvolt = <868310>;
+				regulator-max-microvolt = <1684000>;
+				lltc,fb-voltage-divider = <221000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_ARM (1+R1/R2 = 1.635) */
+			reg_vdd_arm: sw3 {
+				regulator-name = "vddarm";
+				regulator-min-microvolt = <674400>;
+				regulator-max-microvolt = <1308000>;
+				lltc,fb-voltage-divider = <127000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_3P3 (1+R1/R2 = 1.281) */
+			reg_3p3v: sw4 {
+				regulator-name = "vdd3p3";
+				regulator-min-microvolt = <1880000>;
+				regulator-max-microvolt = <3647000>;
+				lltc,fb-voltage-divider = <200000 56200>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_1P8a (1+R1/R2 = 2.505): Analog Video Decoder */
+			reg_1p8a: ldo2 {
+				regulator-name = "vdd1p8a";
+				regulator-min-microvolt = <1816125>;
+				regulator-max-microvolt = <1816125>;
+				lltc,fb-voltage-divider = <301000 200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_1P8b: microSD VDD_1P8 */
+			reg_1p8b: ldo3 {
+				regulator-name = "vdd1p8b";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+			};
+
+			/* VDD_HIGH (1+R1/R2 = 4.17) */
+			reg_3p0v: ldo4 {
+				regulator-name = "vdd3p0";
+				regulator-min-microvolt = <3023250>;
+				regulator-max-microvolt = <3023250>;
+				lltc,fb-voltage-divider = <634000 200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	adv7180: camera@20 {
+		compatible = "adi,adv7180";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_adv7180>;
+		reg = <0x20>;
+		powerdown-gpios = <&gpio5 20 GPIO_ACTIVE_LOW>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <23 IRQ_TYPE_LEVEL_LOW>;
+
+		port {
+			adv7180_to_ipu1_csi0_mux: endpoint {
+				remote-endpoint = <&ipu1_csi0_mux_from_parallel_sensor>;
+				bus-width = <8>;
+			};
+		};
+	};
+};
+
+&ipu1_csi0_from_ipu1_csi0_mux {
+	bus-width = <8>;
+};
+
+&ipu1_csi0_mux_from_parallel_sensor {
+	remote-endpoint = <&adv7180_to_ipu1_csi0_mux>;
+	bus-width = <8>;
+};
+
+&ipu1_csi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ipu1_csi0>;
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio1 0 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>; /* MX6_DIO1 */
+	status = "disabled";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>; /* MX6_DIO2 */
+	status = "disabled";
+};
+
+&pwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>; /* MX6_DIO3 */
+	status = "disabled";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+	cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+};
+
+&iomuxc {
+	pinctrl_adv7180: adv7180grp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT5__GPIO5_IO23        0x0001b0b0
+			MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20     0x4001b0b0
+		>;
+	};
+
+	pinctrl_gpmi_nand: gpminandgrp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+			MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+			MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+			MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+			MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+			MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+			MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+			MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+			MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+			MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+			MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+			MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+			MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+			MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+		>;
+	};
+
+	pinctrl_hdmi: hdmigrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_A25__HDMI_TX_CEC_LINE	0x1f8b0
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0xb0b1
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_imu: imugrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_18__GPIO7_IO13		0x1b0b0
+		>;
+	};
+
+	pinctrl_ipu1_csi0: ipu1csi0grp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12    0x1b0b0
+			MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13    0x1b0b0
+			MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14    0x1b0b0
+			MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15    0x1b0b0
+			MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16    0x1b0b0
+			MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17    0x1b0b0
+			MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18    0x1b0b0
+			MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19    0x1b0b0
+			MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC      0x1b0b0
+			MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC     0x1b0b0
+			MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK   0x1b0b0
+		>;
+	};
+
+	pinctrl_gpio_leds: gpioledsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL2__GPIO4_IO10		0x1b0b0
+			MX6QDL_PAD_KEY_ROW2__GPIO4_IO11		0x1b0b0
+		>;
+	};
+
+	pinctrl_mag: maggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x1b0b0
+		>;
+	};
+
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_0__GPIO1_IO00		0x1b0b0
+			MX6QDL_PAD_GPIO_17__GPIO7_IO12		0x4001b0b0 /* PCIESKT_WDIS# */
+		>;
+	};
+
+	pinctrl_pmic: pmicgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_8__GPIO1_IO08		0x0001b0b0 /* PMIC_IRQ# */
+		>;
+	};
+
+	pinctrl_pps: ppsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_RXD1__GPIO1_IO26	0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT2__PWM2_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT1__PWM3_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm4: pwm4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_CMD__PWM4_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart4: uart4grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL0__UART4_TX_DATA	0x1b0b1
+			MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+			MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			MX6QDL_PAD_EIM_D22__GPIO3_IO22		0x1b0b0 /* OTG_PWR_EN */
+		>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x17059 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x17059
+		>;
+	};
+
+	pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170b9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100b9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170b9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170b9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170b9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170b9
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x170b9 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x170b9
+		>;
+	};
+
+	pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170f9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100f9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170f9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170f9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170f9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170f9
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x170f9 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x170f9
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT8__WDOG1_B		0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6qdl-gw560x.dtsi b/arch/arm/dts/imx6qdl-gw560x.dtsi
new file mode 100644
index 0000000..0786b0d
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-gw560x.dtsi
@@ -0,0 +1,937 @@
+/*
+ * Copyright 2017 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		led0 = &led0;
+		led1 = &led1;
+		led2 = &led2;
+		mmc0 = &usdhc2;
+		mmc1 = &usdhc3;
+		ssi0 = &ssi1;
+		usb0 = &usbh1;
+		usb1 = &usbotg;
+	};
+
+	chosen {
+		stdout-path = &uart2;
+	};
+
+	backlight-display {
+		compatible = "pwm-backlight";
+		pwms = <&pwm4 0 5000000>;
+		brightness-levels = <
+			0  1  2  3  4  5  6  7  8  9
+			10 11 12 13 14 15 16 17 18 19
+			20 21 22 23 24 25 26 27 28 29
+			30 31 32 33 34 35 36 37 38 39
+			40 41 42 43 44 45 46 47 48 49
+			50 51 52 53 54 55 56 57 58 59
+			60 61 62 63 64 65 66 67 68 69
+			70 71 72 73 74 75 76 77 78 79
+			80 81 82 83 84 85 86 87 88 89
+			90 91 92 93 94 95 96 97 98 99
+			100
+			>;
+		default-brightness-level = <100>;
+	};
+
+	backlight-keypad {
+		compatible = "gpio-backlight";
+		gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>;
+		default-on;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		user-pb {
+			label = "user_pb";
+			gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+		};
+
+		user-pb1x {
+			label = "user_pb1x";
+			linux,code = <BTN_1>;
+			interrupt-parent = <&gsc>;
+			interrupts = <0>;
+		};
+
+		key-erased {
+			label = "key-erased";
+			linux,code = <BTN_2>;
+			interrupt-parent = <&gsc>;
+			interrupts = <1>;
+		};
+
+		eeprom-wp {
+			label = "eeprom_wp";
+			linux,code = <BTN_3>;
+			interrupt-parent = <&gsc>;
+			interrupts = <2>;
+		};
+
+		tamper {
+			label = "tamper";
+			linux,code = <BTN_4>;
+			interrupt-parent = <&gsc>;
+			interrupts = <5>;
+		};
+
+		switch-hold {
+			label = "switch_hold";
+			linux,code = <BTN_5>;
+			interrupt-parent = <&gsc>;
+			interrupts = <7>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDG */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDR */
+			default-state = "off";
+		};
+
+		led2: user3 {
+			label = "user3";
+			gpios = <&gpio4 15 GPIO_ACTIVE_LOW>; /* MX6_LOCLED# */
+			default-state = "off";
+		};
+	};
+
+	memory@10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x40000000>;
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pps>;
+		gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+	};
+
+	reg_2p5v: regulator-2p5v {
+		compatible = "regulator-fixed";
+		regulator-name = "2P5V";
+		regulator-min-microvolt = <2500000>;
+		regulator-max-microvolt = <2500000>;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_5p0v: regulator-5p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "5P0V";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	reg_12p0v: regulator-12p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "12P0V";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		gpio = <&gpio4 25 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_1p4v: regulator-vddsoc {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_soc";
+		regulator-min-microvolt = <1400000>;
+		regulator-max-microvolt = <1400000>;
+		regulator-always-on;
+	};
+
+	reg_usb_h1_vbus: regulator-usb-h1-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_h1_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	reg_usb_otg_vbus: regulator-usb-otg-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	sound {
+		compatible = "fsl,imx6q-ventana-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "sgtl5000-audio";
+		ssi-controller = <&ssi1>;
+		audio-codec = <&sgtl5000>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+		mux-int-port = <1>;
+		mux-ext-port = <4>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&ecspi3 {
+	cs-gpios = <&gpio4 24 GPIO_ACTIVE_LOW>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi3>;
+	status = "okay";
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan>;
+	status = "okay";
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
+			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
+				 <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii-id";
+	phy-reset-gpios = <&gpio1 30 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c3>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	gsc: gsc@20 {
+		compatible = "gw,gsc";
+		reg = <0x20>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		#size-cells = <0>;
+
+		adc {
+			compatible = "gw,gsc-adc";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			channel@0 {
+				gw,mode = <0>;
+				reg = <0x00>;
+				label = "temp";
+			};
+
+			channel@2 {
+				gw,mode = <1>;
+				reg = <0x02>;
+				label = "vdd_vin";
+			};
+
+			channel@5 {
+				gw,mode = <1>;
+				reg = <0x05>;
+				label = "vdd_3p3";
+			};
+
+			channel@8 {
+				gw,mode = <1>;
+				reg = <0x08>;
+				label = "vdd_bat";
+			};
+
+			channel@b {
+				gw,mode = <1>;
+				reg = <0x0b>;
+				label = "vdd_5p0";
+			};
+
+			channel@e {
+				gw,mode = <1>;
+				reg = <0xe>;
+				label = "vdd_arm";
+			};
+
+			channel@11 {
+				gw,mode = <1>;
+				reg = <0x11>;
+				label = "vdd_soc";
+			};
+
+			channel@14 {
+				gw,mode = <1>;
+				reg = <0x14>;
+				label = "vdd_3p0";
+			};
+
+			channel@17 {
+				gw,mode = <1>;
+				reg = <0x17>;
+				label = "vdd_1p5";
+			};
+
+			channel@1d {
+				gw,mode = <1>;
+				reg = <0x1d>;
+				label = "vdd_1p8";
+			};
+
+			channel@20 {
+				gw,mode = <1>;
+				reg = <0x20>;
+				label = "vdd_an1";
+			};
+
+			channel@23 {
+				gw,mode = <1>;
+				reg = <0x23>;
+				label = "vdd_2p5";
+			};
+
+			channel@26 {
+				gw,mode = <1>;
+				reg = <0x26>;
+				label = "vdd_gps";
+			};
+
+			channel@29 {
+				gw,mode = <1>;
+				reg = <0x29>;
+				label = "vdd_an2";
+			};
+		};
+	};
+
+	gsc_gpio: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gsc>;
+		interrupts = <4>;
+	};
+
+	eeprom1: eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom2: eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom3: eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom4: eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	ds1672: rtc@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	sgtl5000: codec@a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		#sound-dai-cells = <0>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		VDDA-supply = <&reg_1p8v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+
+	magn@1c {
+		compatible = "st,lsm9ds1-magn";
+		reg = <0x1c>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_mag>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+	};
+
+	tca8418: keypad@34 {
+		compatible = "ti,tca8418";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_keypad>;
+		reg = <0x34>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
+		linux,keymap = < MATRIX_KEY(0x00, 0x01, BTN_0)
+			         MATRIX_KEY(0x00, 0x00, BTN_1)
+			         MATRIX_KEY(0x01, 0x01, BTN_2)
+			         MATRIX_KEY(0x01, 0x00, BTN_3)
+			         MATRIX_KEY(0x02, 0x00, BTN_4)
+			         MATRIX_KEY(0x00, 0x03, BTN_5)
+			         MATRIX_KEY(0x00, 0x02, BTN_6)
+			         MATRIX_KEY(0x01, 0x03, BTN_7)
+			         MATRIX_KEY(0x01, 0x02, BTN_8)
+			         MATRIX_KEY(0x02, 0x02, BTN_9)
+		>;
+		keypad,num-rows = <4>;
+		keypad,num-columns = <4>;
+	};
+
+	ltc3676: pmic@3c {
+		compatible = "lltc,ltc3676";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pmic>;
+		reg = <0x3c>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+
+		regulators {
+			/* VDD_DDR (1+R1/R2 = 2.105) */
+			reg_vdd_ddr: sw2 {
+				regulator-name = "vddddr";
+				regulator-min-microvolt = <868310>;
+				regulator-max-microvolt = <1684000>;
+				lltc,fb-voltage-divider = <221000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_ARM (1+R1/R2 = 1.931) */
+			reg_vdd_arm: sw3 {
+				regulator-name = "vddarm";
+				regulator-min-microvolt = <796551>;
+				regulator-max-microvolt = <1544827>;
+				lltc,fb-voltage-divider = <243000 261000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+				linux,phandle = <&reg_vdd_arm>;
+			};
+
+			/* VDD_1P8 (1+R1/R2 = 2.505): GPS/VideoIn/ENET-PHY */
+			reg_1p8v: sw4 {
+				regulator-name = "vdd1p8";
+				regulator-min-microvolt = <1033310>;
+				regulator-max-microvolt = <2004000>;
+				lltc,fb-voltage-divider = <301000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_1P0 (1+R1/R2 = 1.39): PCIe/ENET-PHY */
+			reg_1p0v: ldo2 {
+				regulator-name = "vdd1p0";
+				regulator-min-microvolt = <950000>;
+				regulator-max-microvolt = <1050000>;
+				lltc,fb-voltage-divider = <78700 200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_AUD_1P8: Audio codec */
+			reg_aud_1p8v: ldo3 {
+				regulator-name = "vdd1p8a";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+			};
+
+			/* VDD_HIGH (1+R1/R2 = 4.17) */
+			reg_3p0v: ldo4 {
+				regulator-name = "vdd3p0";
+				regulator-min-microvolt = <3023250>;
+				regulator-max-microvolt = <3023250>;
+				lltc,fb-voltage-divider = <634000 200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+
+	imu@6a {
+		compatible = "st,lsm9ds1-imu";
+		reg = <0x6a>;
+		st,drdy-int-pin = <1>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_imu>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <6 IRQ_TYPE_LEVEL_HIGH>;
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	egalax_ts: touchscreen@4 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <12 IRQ_TYPE_EDGE_FALLING>;
+		wakeup-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&ldb {
+	fsl,dual-channel;
+	status = "okay";
+
+	lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+			};
+		};
+	};
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio4 31 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>; /* MX6_DIO1 */
+	status = "disabled";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>; /* MX6_DIO2 */
+	status = "disabled";
+};
+
+&pwm4 {
+	#pwm-cells = <2>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>;
+	status = "okay";
+};
+
+&ssi1 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	uart-has-rtscts;
+	rts-gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_h1_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbh1>;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	bus-width = <8>;
+	vmmc-supply = <&reg_3p3v>;
+	non-removable;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+	cd-gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+};
+
+&iomuxc {
+	pinctrl_audmux: audmuxgrp {
+		fsl,pins = <
+			/* AUD4 */
+			MX6QDL_PAD_DISP0_DAT20__AUD4_TXC	0x130b0
+			MX6QDL_PAD_DISP0_DAT21__AUD4_TXD	0x110b0
+			MX6QDL_PAD_DISP0_DAT22__AUD4_TXFS	0x130b0
+			MX6QDL_PAD_DISP0_DAT23__AUD4_RXD	0x130b0
+			MX6QDL_PAD_GPIO_0__CCM_CLKO1		0x130b0 /* AUD4_MCK */
+			/* AUD6 */
+			MX6QDL_PAD_DI0_PIN2__AUD6_TXD		0x130b0
+			MX6QDL_PAD_DI0_PIN3__AUD6_TXFS		0x130b0
+			MX6QDL_PAD_DI0_PIN4__AUD6_RXD		0x130b0
+			MX6QDL_PAD_DI0_PIN15__AUD6_TXC		0x130b0
+		>;
+	};
+
+	pinctrl_ecspi3: escpi3grp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK	0x100b1
+			MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI	0x100b1
+			MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO	0x100b1
+			MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24	0x100b1
+		>;
+	};
+
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b030
+			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b030
+			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b030
+			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030
+			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030
+			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b030
+			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b030
+			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b030
+			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b030
+			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b030
+			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b030
+			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b030
+			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			MX6QDL_PAD_ENET_TXD0__GPIO1_IO30	0x4001b0b0 /* PHY_RST# */
+		>;
+	};
+
+	pinctrl_flexcan: flexcangrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX	0x1b0b1
+			MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX	0x1b0b1
+			MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x4001b0b0 /* CAN_STBY */
+		>;
+	};
+
+	pinctrl_gpio_leds: gpioledsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL0__GPIO4_IO06		0x1b0b0
+			MX6QDL_PAD_KEY_ROW0__GPIO4_IO07		0x1b0b0
+			MX6QDL_PAD_KEY_ROW4__GPIO4_IO15		0x1b0b0
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0xb0b1
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_19__GPIO4_IO05		0x4001b0b0 /* DIOI2C_DIS# */
+			MX6QDL_PAD_DISP0_DAT18__GPIO5_IO12	0x0001b0b0 /* LVDS_TOUCH_IRQ# */
+			MX6QDL_PAD_DISP0_DAT19__GPIO5_IO13	0x0001b0b0 /* LVDS_BACKEN */
+		>;
+	};
+
+	pinctrl_imu: imugrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT12__GPIO5_IO06	0x1b0b0
+		>;
+	};
+
+	pinctrl_keypad: keypadgrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT17__GPIO5_IO11	0x0001b0b0 /* KEYPAD_IRQ# */
+			MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30	0x0001b0b0 /* KEYPAD_LED_EN */
+		>;
+	};
+
+	pinctrl_mag: maggrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT15__GPIO5_IO09	0x1b0b0
+		>;
+	};
+
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT10__GPIO4_IO31	0x1b0b0    /* PCI_RST# */
+			MX6QDL_PAD_GPIO_17__GPIO7_IO12		0x4001b0b0 /* PCIESKT_WDIS# */
+		>;
+	};
+
+	pinctrl_pmic: pmicgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_8__GPIO1_IO08		0x0001b0b0 /* PMIC_IRQ# */
+		>;
+	};
+
+	pinctrl_pps: ppsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_RXD1__GPIO1_IO26	0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT2__PWM2_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT1__PWM3_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm4: pwm4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_CMD__PWM4_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+			MX6QDL_PAD_SD3_DAT4__GPIO7_IO01		0x4001b0b1 /* TEN */
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+			MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbh1: usbh1grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_9__GPIO1_IO09		0x4001b0b0 /* USBHUB_RST# */
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			MX6QDL_PAD_EIM_D22__GPIO3_IO22		0x1b0b0 /* PWR_EN */
+			MX6QDL_PAD_KEY_COL4__GPIO4_IO14		0x1b0b0 /* OC */
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD2_CMD__SD2_CMD		0x170f9
+			MX6QDL_PAD_SD2_CLK__SD2_CLK		0x100f9
+			MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x170f9
+			MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x170f9
+			MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x170f9
+			MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x170f9
+			MX6QDL_PAD_NANDF_D4__SD2_DATA4		0x170f9
+			MX6QDL_PAD_NANDF_D5__SD2_DATA5		0x170f9
+			MX6QDL_PAD_NANDF_D6__SD2_DATA6		0x170f9
+			MX6QDL_PAD_NANDF_D7__SD2_DATA7		0x170f9
+		>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x17059 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x17059
+		>;
+	};
+
+	pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170b9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100b9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170b9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170b9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170b9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170b9
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x170b9 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x170b9
+		>;
+	};
+
+	pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170f9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100f9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170f9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170f9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170f9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170f9
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x170f9 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x170f9
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT8__WDOG1_B		0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6qdl-gw5903.dtsi b/arch/arm/dts/imx6qdl-gw5903.dtsi
new file mode 100644
index 0000000..78f9ec9
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-gw5903.dtsi
@@ -0,0 +1,796 @@
+/*
+ * Copyright 2017 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	chosen {
+		stdout-path = &uart2;
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 5000000>;
+		brightness-levels = <
+			0  1  2  3  4  5  6  7  8  9
+			10 11 12 13 14 15 16 17 18 19
+			20 21 22 23 24 25 26 27 28 29
+			30 31 32 33 34 35 36 37 38 39
+			40 41 42 43 44 45 46 47 48 49
+			50 51 52 53 54 55 56 57 58 59
+			60 61 62 63 64 65 66 67 68 69
+			70 71 72 73 74 75 76 77 78 79
+			80 81 82 83 84 85 86 87 88 89
+			90 91 92 93 94 95 96 97 98 99
+			100
+			>;
+		default-brightness-level = <100>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		user-pb {
+			label = "user_pb";
+			gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+		};
+
+		user-pb1x {
+			label = "user_pb1x";
+			linux,code = <BTN_1>;
+			interrupt-parent = <&gsc>;
+			interrupts = <0>;
+		};
+
+		key-erased {
+			label = "key-erased";
+			linux,code = <BTN_2>;
+			interrupt-parent = <&gsc>;
+			interrupts = <1>;
+		};
+
+		eeprom-wp {
+			label = "eeprom_wp";
+			linux,code = <BTN_3>;
+			interrupt-parent = <&gsc>;
+			interrupts = <2>;
+		};
+
+		tamper {
+			label = "tamper";
+			linux,code = <BTN_4>;
+			interrupt-parent = <&gsc>;
+			interrupts = <5>;
+		};
+
+		switch-hold {
+			label = "switch_hold";
+			linux,code = <BTN_5>;
+			interrupt-parent = <&gsc>;
+			interrupts = <7>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio6 14 GPIO_ACTIVE_LOW>; /* MX6_LOCLED# */
+			default-state = "off";
+		};
+	};
+
+	memory@10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x40000000>;
+	};
+
+	reg_5p0v: regulator-5p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "5P0V";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_2p5v: regulator-2p5v {
+		compatible = "regulator-fixed";
+		regulator-name = "2P5V";
+		regulator-min-microvolt = <2500000>;
+		regulator-max-microvolt = <2500000>;
+		regulator-always-on;
+	};
+
+	reg_usb_h1_vbus: regulator-usb-h1-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_h1_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio3 30 0>;
+		enable-active-high;
+	};
+
+	reg_usb_otg_vbus: regulator-usb-otg-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio4 15 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_12p0: regulator-12p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "12P0V";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		gpio = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	sound {
+		compatible = "fsl,imx-audio-tlv320";
+		model = "imx-tlv320";
+		ssi-controller = <&ssi1>;
+		audio-codec = <&tlv320aic3105>;
+		/* routing of sink, source */
+		audio-routing =
+			/* TLV320 LINE1L pin <-> Mic Jack connector */
+			"LINE1L", "Mic Jack",
+			/* board Headphone Jack <-> HPOUT */
+			"Headphone Jack", "HPLOUT",
+			"Headphone Jack", "HPROUT",
+			"Mic Jack", "Mic Bias";
+		mux-int-port = <1>;
+		mux-ext-port = <6>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
+			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
+				 <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii-id";
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	gsc: gsc@20 {
+		compatible = "gw,gsc";
+		reg = <0x20>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		#size-cells = <0>;
+
+		adc {
+			compatible = "gw,gsc-adc";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			channel@0 {
+				gw,mode = <0>;
+				reg = <0x00>;
+				label = "temp";
+			};
+
+			channel@2 {
+				gw,mode = <1>;
+				reg = <0x02>;
+				label = "vdd_vin";
+			};
+
+			channel@5 {
+				gw,mode = <1>;
+				reg = <0x05>;
+				label = "vdd_3p3";
+			};
+
+			channel@8 {
+				gw,mode = <1>;
+				reg = <0x08>;
+				label = "vdd_bat";
+			};
+
+			channel@b {
+				gw,mode = <1>;
+				reg = <0x0b>;
+				label = "vdd_5p0";
+			};
+
+			channel@e {
+				gw,mode = <1>;
+				reg = <0xe>;
+				label = "vdd_arm";
+			};
+
+			channel@11 {
+				gw,mode = <1>;
+				reg = <0x11>;
+				label = "vdd_soc";
+			};
+
+			channel@14 {
+				gw,mode = <1>;
+				reg = <0x14>;
+				label = "vdd_3p0";
+			};
+
+			channel@17 {
+				gw,mode = <1>;
+				reg = <0x17>;
+				label = "vdd_1p5";
+			};
+
+			channel@1d {
+				gw,mode = <1>;
+				reg = <0x1d>;
+				label = "vdd_1p8";
+			};
+
+			channel@20 {
+				gw,mode = <1>;
+				reg = <0x20>;
+				label = "vdd_an1";
+			};
+
+			channel@23 {
+				gw,mode = <1>;
+				reg = <0x23>;
+				label = "vdd_2p5";
+			};
+		};
+	};
+
+	gsc_gpio: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gsc>;
+		interrupts = <4>;
+	};
+
+	eeprom1: eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom2: eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom3: eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom4: eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	dts1672: rtc@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <400000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	ltc3676: pmic@3c {
+		compatible = "lltc,ltc3676";
+		reg = <0x3c>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+
+		regulators {
+			/* VDD_1P8 (1+R1/R2 = 2.505): Aud/eMMC/microSD/Touch */
+			reg_1p8v: sw1 {
+				regulator-name = "vdd1p8";
+				regulator-min-microvolt = <1033310>;
+				regulator-max-microvolt = <2004000>;
+				lltc,fb-voltage-divider = <301000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_DDR (1+R1/R2 = 2.105) */
+			reg_vdd_ddr: sw2 {
+				regulator-name = "vddddr";
+				regulator-min-microvolt = <868310>;
+				regulator-max-microvolt = <1684000>;
+				lltc,fb-voltage-divider = <221000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_ARM (1+R1/R2 = 1.635) */
+			reg_vdd_arm: sw3 {
+				regulator-name = "vddarm";
+				regulator-min-microvolt = <674400>;
+				regulator-max-microvolt = <1308000>;
+				lltc,fb-voltage-divider = <127000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+				linux,phandle = <&reg_vdd_arm>;
+			};
+
+			/* VDD_SOC (1+R1/R2 = 1.635) */
+			reg_vdd_soc: sw4 {
+				regulator-name = "vddsoc";
+				regulator-min-microvolt = <674400>;
+				regulator-max-microvolt = <1308000>;
+				lltc,fb-voltage-divider = <127000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+				linux,phandle = <&reg_vdd_soc>;
+			};
+
+			/* VDD_1P0 (1+R1/R2 = 1.38): */
+			reg_1p0v: ldo2 {
+				regulator-name = "vdd1p0";
+				regulator-min-microvolt = <1002777>;
+				regulator-max-microvolt = <1002777>;
+				lltc,fb-voltage-divider = <100000 261000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_HIGH (1+R1/R2 = 4.17) */
+			reg_3p0v: ldo4 {
+				regulator-name = "vdd3p0";
+				regulator-min-microvolt = <3023250>;
+				regulator-max-microvolt = <3023250>;
+				lltc,fb-voltage-divider = <634000 200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c3 {
+	clock-frequency = <400000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	tlv320aic3105: codec@18 {
+		compatible = "ti,tlv320aic3x";
+		reg = <0x18>;
+		reset-gpios = <&gpio5 17 GPIO_ACTIVE_LOW>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		ai3x-micbias-vg = <2>; /* MICBIAS_2_5V */
+		/* Regulators */
+		DRVDD-supply = <&reg_3p3v>;
+		AVDD-supply = <&reg_3p3v>;
+		IOVDD-supply = <&reg_3p3v>;
+		DVDD-supply = <&reg_1p8v>;
+	};
+
+	accelerometer@1d {
+		compatible = "fsl,mma8451";
+		reg = <0x1d>;
+		interrupt-parent = <&gpio7>;
+		interrupts = <11 IRQ_TYPE_EDGE_RISING>;
+		interrupt-names = "INT2";
+	};
+
+	/* headphone detect */
+	ts3a227e@3b {
+		compatible = "ti,ts3a227e";
+		reg = <0x3b>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
+		ti,micbias = <4>; /* 2.5V micbias */
+	};
+};
+
+&ldb {
+	status = "okay";
+
+	lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: g101evn010 {
+				clock-frequency = <68930000>;
+				hactive = <1280>;
+				vactive = <800>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+			};
+		};
+	};
+};
+
+&pwm1 {
+	#pwm-cells = <2>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>;
+	status = "okay";
+};
+
+&ssi1 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_h1_vbus>;
+	status = "okay";
+};
+
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1_200mhz>;
+	vmmc-supply = <&reg_3p3v>;
+	non-removable;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+	cd-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>;
+	vmmc-supply = <&reg_3p3v>;
+	max-frequency = <100000000>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+	non-removable;
+	vmmc-supply = <&reg_3p3v>;
+	keep-power-in-suspend;
+	status = "okay";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+};
+
+&iomuxc {
+	pinctrl_audmux: audmuxgrp {
+		fsl,pins = <
+			MX6QDL_PAD_DI0_PIN2__AUD6_TXD		0x130b0
+			MX6QDL_PAD_DI0_PIN3__AUD6_TXFS		0x130b0
+			MX6QDL_PAD_DI0_PIN4__AUD6_RXD		0x130b0
+			MX6QDL_PAD_DI0_PIN15__AUD6_TXC		0x130b0
+			MX6QDL_PAD_GPIO_0__CCM_CLKO1		0x130b0 /* MCK */
+		>;
+	};
+
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b030
+			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b030
+			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b030
+			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030
+			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030
+			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b030
+			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b030
+			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b030
+			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b030
+			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b030
+			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b030
+			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b030
+			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_ENET_TXD0__GPIO1_IO30	0x4001b0b0 /* PHY_RST# */
+			MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25	0x4001b0b0 /* PHY_EN */
+		>;
+	};
+
+	pinctrl_gpio_leds: gpioledsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CS1__GPIO6_IO14	0x1b0b0
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0x0001b0b0 /* GSC_IRQ# */
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_8__GPIO1_IO08		0x0001b0b0 /* PMIC_IRQ# */
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			/* I2C3 */
+			MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+
+			/* Headphone Detect */
+			MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15	0x0001b0b0 /* HPDET_IRQ# */
+			MX6QDL_PAD_DISP0_DAT22__GPIO5_IO16	0x0001b0b0 /* HPDET_MIC# */
+
+			/* Codec */
+			MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17	0x0001b0b0 /* CODEC_RST# */
+
+			/* Touch Controller */
+			MX6QDL_PAD_KEY_COL0__GPIO4_IO06		0x0001b0b0 /* TOUCH_IRQ# */
+			MX6QDL_PAD_KEY_COL1__GPIO4_IO08		0x0001b0b0 /* TOUCH_RST */
+
+			/* Stow Sensor */
+			MX6QDL_PAD_GPIO_16__GPIO7_IO11		0x0001b0b0 /* ACCEL_IRQ2 */
+			MX6QDL_PAD_GPIO_18__GPIO7_IO13		0x0001b0b0 /* ACCEL_IRQ1 */
+		>;
+	};
+
+	pinctrl_pwm1: pwm1grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_9__PWM1_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
+			MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA	0x1b0b1
+			MX6QDL_PAD_CSI0_DAT12__GPIO5_IO30	0x1b0b1 /* TXEN */
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x13059
+			MX6QDL_PAD_KEY_ROW4__GPIO4_IO15		0x4001b0b0 /* PWR_EN */
+			MX6QDL_PAD_KEY_COL4__GPIO4_IO14		0x1b0b0 /* OC */
+		>;
+	};
+
+	pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_D3__GPIO2_IO03		0x4001b0b0 /* EMMY_EN */
+			MX6QDL_PAD_NANDF_D4__GPIO2_IO04		0x4001b0b0 /* EMMY_CFG1# */
+			MX6QDL_PAD_NANDF_D5__GPIO2_IO05		0x4001b0b0 /* EMMY_CFG2# */
+			MX6QDL_PAD_NANDF_D6__GPIO2_IO06		0x0001b0b0 /* EMMY_BTWAKE# */
+			MX6QDL_PAD_NANDF_D7__GPIO2_IO07		0x0001b0b0 /* EMMY_WFWAKE# */
+
+			MX6QDL_PAD_SD1_CLK__SD1_CLK		0x100f9
+			MX6QDL_PAD_SD1_CMD__SD1_CMD		0x100f9
+			MX6QDL_PAD_SD1_DAT0__SD1_DATA0		0x170f9
+			MX6QDL_PAD_SD1_DAT1__SD1_DATA1		0x170f9
+			MX6QDL_PAD_SD1_DAT2__SD1_DATA2		0x170f9
+			MX6QDL_PAD_SD1_DAT3__SD1_DATA3		0x170f9
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD2_CMD__SD2_CMD		0x17059
+			MX6QDL_PAD_SD2_CLK__SD2_CLK		0x10059
+			MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x17059
+			MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x17059
+			MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x17059
+			MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x17059
+			MX6QDL_PAD_NANDF_CS0__GPIO6_IO11	0x17059 /* CD */
+			MX6QDL_PAD_KEY_ROW1__SD2_VSELECT	0x17059
+		>;
+	};
+
+	pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD2_CMD__SD2_CMD		0x170b9
+			MX6QDL_PAD_SD2_CLK__SD2_CLK		0x100b9
+			MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x170b9
+			MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x170b9
+			MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x170b9
+			MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x170b9
+			MX6QDL_PAD_NANDF_CS0__GPIO6_IO11	0x170b9 /* CD */
+			MX6QDL_PAD_KEY_ROW1__SD2_VSELECT	0x170b9
+		>;
+	};
+
+	pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD2_CMD__SD2_CMD		0x170f9
+			MX6QDL_PAD_SD2_CLK__SD2_CLK		0x100f9
+			MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x170f9
+			MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x170f9
+			MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x170f9
+			MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x170f9
+			MX6QDL_PAD_NANDF_CS0__GPIO6_IO11	0x170f9 /* CD */
+			MX6QDL_PAD_KEY_ROW1__SD2_VSELECT	0x170f9
+		>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+			MX6QDL_PAD_SD3_RST__SD3_RESET		0x10059
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			MX6QDL_PAD_SD3_DAT4__SD3_DATA4		0x17059
+			MX6QDL_PAD_SD3_DAT5__SD3_DATA5		0x17059
+			MX6QDL_PAD_SD3_DAT6__SD3_DATA6		0x17059
+			MX6QDL_PAD_SD3_DAT7__SD3_DATA7		0x17059
+		>;
+	};
+
+	pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170b9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100b9
+			MX6QDL_PAD_SD3_RST__SD3_RESET		0x100b9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170b9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170b9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170b9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170b9
+			MX6QDL_PAD_SD3_DAT4__SD3_DATA4		0x170b9
+			MX6QDL_PAD_SD3_DAT5__SD3_DATA5		0x170b9
+			MX6QDL_PAD_SD3_DAT6__SD3_DATA6		0x170b9
+			MX6QDL_PAD_SD3_DAT7__SD3_DATA7		0x170b9
+		>;
+	};
+
+	pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170f9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100f9
+			MX6QDL_PAD_SD3_RST__SD3_RESET		0x100f9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170f9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170f9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170f9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170f9
+			MX6QDL_PAD_SD3_DAT4__SD3_DATA4		0x170f9
+			MX6QDL_PAD_SD3_DAT5__SD3_DATA5		0x170f9
+			MX6QDL_PAD_SD3_DAT6__SD3_DATA6		0x170f9
+			MX6QDL_PAD_SD3_DAT7__SD3_DATA7		0x170f9
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT8__WDOG1_B		0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6qdl-gw5904.dtsi b/arch/arm/dts/imx6qdl-gw5904.dtsi
new file mode 100644
index 0000000..5b7bd56
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-gw5904.dtsi
@@ -0,0 +1,814 @@
+/*
+ * Copyright 2017 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		led0 = &led0;
+		led1 = &led1;
+		led2 = &led2;
+		mmc0 = &usdhc3;
+		usb0 = &usbh1;
+		usb1 = &usbotg;
+	};
+
+	chosen {
+		stdout-path = &uart2;
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm4 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		user-pb {
+			label = "user_pb";
+			gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+		};
+
+		user-pb1x {
+			label = "user_pb1x";
+			linux,code = <BTN_1>;
+			interrupt-parent = <&gsc>;
+			interrupts = <0>;
+		};
+
+		key-erased {
+			label = "key-erased";
+			linux,code = <BTN_2>;
+			interrupt-parent = <&gsc>;
+			interrupts = <1>;
+		};
+
+		eeprom-wp {
+			label = "eeprom_wp";
+			linux,code = <BTN_3>;
+			interrupt-parent = <&gsc>;
+			interrupts = <2>;
+		};
+
+		tamper {
+			label = "tamper";
+			linux,code = <BTN_4>;
+			interrupt-parent = <&gsc>;
+			interrupts = <5>;
+		};
+
+		switch-hold {
+			label = "switch_hold";
+			linux,code = <BTN_5>;
+			interrupt-parent = <&gsc>;
+			interrupts = <7>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDG */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDR */
+			default-state = "off";
+		};
+
+		led2: user3 {
+			label = "user3";
+			gpios = <&gpio4 15 GPIO_ACTIVE_LOW>; /* MX6_LOCLED# */
+			default-state = "off";
+		};
+	};
+
+	memory@10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x40000000>;
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pps>;
+		gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+	};
+
+	reg_1p0v: regulator-1p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "1P0V";
+		regulator-min-microvolt = <1000000>;
+		regulator-max-microvolt = <1000000>;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_usb_h1_vbus: regulator-usb-h1-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_h1_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	reg_usb_otg_vbus: regulator-usb-otg-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
+			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
+				 <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii-id";
+	status = "okay";
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		switch@0 {
+			compatible = "marvell,mv88e6085";
+			reg = <0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					label = "lan4";
+				};
+
+				port@1 {
+					reg = <1>;
+					label = "lan3";
+				};
+
+				port@2 {
+					reg = <2>;
+					label = "lan2";
+				};
+
+				port@3 {
+					reg = <3>;
+					label = "lan1";
+				};
+
+				port@5 {
+					reg = <5>;
+					label = "cpu";
+					ethernet = <&fec>;
+				};
+			};
+		};
+	};
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	gsc: gsc@20 {
+		compatible = "gw,gsc";
+		reg = <0x20>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		#size-cells = <0>;
+
+		adc {
+			compatible = "gw,gsc-adc";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			channel@0 {
+				gw,mode = <0>;
+				reg = <0x00>;
+				label = "temp";
+			};
+
+			channel@2 {
+				gw,mode = <1>;
+				reg = <0x02>;
+				label = "vdd_vin";
+			};
+
+			channel@5 {
+				gw,mode = <1>;
+				reg = <0x05>;
+				label = "vdd_3p3";
+			};
+
+			channel@8 {
+				gw,mode = <1>;
+				reg = <0x08>;
+				label = "vdd_bat";
+			};
+
+			channel@b {
+				gw,mode = <1>;
+				reg = <0x0b>;
+				label = "vdd_5p0";
+			};
+
+			channel@e {
+				gw,mode = <1>;
+				reg = <0xe>;
+				label = "vdd_arm";
+			};
+
+			channel@11 {
+				gw,mode = <1>;
+				reg = <0x11>;
+				label = "vdd_soc";
+			};
+
+			channel@14 {
+				gw,mode = <1>;
+				reg = <0x14>;
+				label = "vdd_3p0";
+			};
+
+			channel@17 {
+				gw,mode = <1>;
+				reg = <0x17>;
+				label = "vdd_1p5";
+			};
+
+			channel@1d {
+				gw,mode = <1>;
+				reg = <0x1d>;
+				label = "vdd_1p8";
+			};
+
+			channel@20 {
+				gw,mode = <1>;
+				reg = <0x20>;
+				label = "vdd_an1";
+			};
+
+			channel@23 {
+				gw,mode = <1>;
+				reg = <0x23>;
+				label = "vdd_2p5";
+			};
+		};
+	};
+
+	gsc_gpio: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gsc>;
+		interrupts = <4>;
+	};
+
+	eeprom1: eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom2: eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom3: eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom4: eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	dts1672: rtc@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	magn@1c {
+		compatible = "st,lsm9ds1-magn";
+		reg = <0x1c>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_mag>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <17 IRQ_TYPE_EDGE_RISING>;
+	};
+
+	ltc3676: pmic@3c {
+		compatible = "lltc,ltc3676";
+		reg = <0x3c>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+
+		regulators {
+			/* VDD_SOC (1+R1/R2 = 1.635) */
+			reg_vdd_soc: sw1 {
+				regulator-name = "vddsoc";
+				regulator-min-microvolt = <674400>;
+				regulator-max-microvolt = <1308000>;
+				lltc,fb-voltage-divider = <127000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_1P8 (1+R1/R2 = 2.505): GbE switch */
+			reg_1p8v: sw2 {
+				regulator-name = "vdd1p8";
+				regulator-min-microvolt = <1033310>;
+				regulator-max-microvolt = <2004000>;
+				lltc,fb-voltage-divider = <301000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_ARM (1+R1/R2 = 1.635) */
+			reg_vdd_arm: sw3 {
+				regulator-name = "vddarm";
+				regulator-min-microvolt = <674400>;
+				regulator-max-microvolt = <1308000>;
+				lltc,fb-voltage-divider = <127000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_DDR (1+R1/R2 = 2.105) */
+			reg_vdd_ddr: sw4 {
+				regulator-name = "vddddr";
+				regulator-min-microvolt = <868310>;
+				regulator-max-microvolt = <1684000>;
+				lltc,fb-voltage-divider = <221000 200000>;
+				regulator-ramp-delay = <7000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_2P5 (1+R1/R2 = 3.435): PCIe/ENET-PHY */
+			reg_2p5v: ldo2 {
+				regulator-name = "vdd2p5";
+				regulator-min-microvolt = <2490375>;
+				regulator-max-microvolt = <2490375>;
+				lltc,fb-voltage-divider = <487000 200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* VDD_HIGH (1+R1/R2 = 4.17) */
+			reg_3p0v: ldo4 {
+				regulator-name = "vdd3p0";
+				regulator-min-microvolt = <3023250>;
+				regulator-max-microvolt = <3023250>;
+				lltc,fb-voltage-divider = <634000 200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+
+	imu@6a {
+		compatible = "st,lsm9ds1-imu";
+		reg = <0x6a>;
+		st,drdy-int-pin = <1>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_imu>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <18 IRQ_TYPE_LEVEL_HIGH>;
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	egalax_ts: touchscreen@4 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
+		wakeup-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&ldb {
+	status = "okay";
+
+	lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+			};
+		};
+	};
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio1 0 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>; /* MX6_DIO1 */
+	status = "disabled";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>; /* MX6_DIO2 */
+	status = "disabled";
+};
+
+&pwm4 {
+	#pwm-cells = <2>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	uart-has-rtscts;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>;
+	uart-has-rtscts;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_h1_vbus>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+	non-removable;
+	vmmc-supply = <&reg_3p3v>;
+	keep-power-in-suspend;
+	status = "okay";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+};
+
+&iomuxc {
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b030
+			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b030
+			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b030
+			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030
+			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030
+			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b030
+			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b030
+			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b030
+			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b030
+			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b030
+			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b030
+			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b030
+			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			MX6QDL_PAD_ENET_TXD0__GPIO1_IO30	0x4001b0b0 /* PHY_RST# */
+		>;
+	};
+
+	pinctrl_gpio_leds: gpioledsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL0__GPIO4_IO06		0x1b0b0
+			MX6QDL_PAD_KEY_ROW0__GPIO4_IO07		0x1b0b0
+			MX6QDL_PAD_KEY_ROW4__GPIO4_IO15		0x1b0b0
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0x0001b0b0 /* GSC_IRQ# */
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_imu: imugrp {
+		fsl,pins = <
+			MX6QDL_PAD_DI0_PIN2__GPIO4_IO18		0x1b0b0
+		>;
+	};
+
+	pinctrl_mag: maggrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17	0x1b0b0
+		>;
+	};
+
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_0__GPIO1_IO00	0x1b0b0 /* PCIE RST */
+		>;
+	};
+
+	pinctrl_pmic: pmicgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_8__GPIO1_IO08	0x1b0b0 /* PMIC_IRQ# */
+		>;
+	};
+
+	pinctrl_pps: ppsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_RXD1__GPIO1_IO26	0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT2__PWM2_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT1__PWM3_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm4: pwm4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_CMD__PWM4_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
+			MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D23__UART3_CTS_B         0x1b0b1
+			MX6QDL_PAD_EIM_D24__UART3_TX_DATA       0x1b0b1
+			MX6QDL_PAD_EIM_D25__UART3_RX_DATA       0x1b0b1
+			MX6QDL_PAD_EIM_D31__UART3_RTS_B         0x1b0b1
+		>;
+	};
+
+	pinctrl_uart4: uart4grp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA    0x1b0b1
+			MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA    0x1b0b1
+			MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B      0x1b0b1
+			MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B      0x1b0b1
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+			MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			MX6QDL_PAD_EIM_D22__GPIO3_IO22		0x1b0b0 /* PWR_EN */
+			MX6QDL_PAD_KEY_COL4__GPIO4_IO14		0x1b0b0 /* OC */
+		>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+			MX6QDL_PAD_SD3_RST__SD3_RESET		0x10059
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			MX6QDL_PAD_SD3_DAT4__SD3_DATA4		0x17059
+			MX6QDL_PAD_SD3_DAT5__SD3_DATA5		0x17059
+			MX6QDL_PAD_SD3_DAT6__SD3_DATA6		0x17059
+			MX6QDL_PAD_SD3_DAT7__SD3_DATA7		0x17059
+		>;
+	};
+
+	pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170b9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100b9
+			MX6QDL_PAD_SD3_RST__SD3_RESET		0x100b9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170b9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170b9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170b9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170b9
+			MX6QDL_PAD_SD3_DAT4__SD3_DATA4		0x170b9
+			MX6QDL_PAD_SD3_DAT5__SD3_DATA5		0x170b9
+			MX6QDL_PAD_SD3_DAT6__SD3_DATA6		0x170b9
+			MX6QDL_PAD_SD3_DAT7__SD3_DATA7		0x170b9
+		>;
+	};
+
+	pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170f9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100f9
+			MX6QDL_PAD_SD3_RST__SD3_RESET		0x100f9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170f9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170f9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170f9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170f9
+			MX6QDL_PAD_SD3_DAT4__SD3_DATA4		0x170f9
+			MX6QDL_PAD_SD3_DAT5__SD3_DATA5		0x170f9
+			MX6QDL_PAD_SD3_DAT6__SD3_DATA6		0x170f9
+			MX6QDL_PAD_SD3_DAT7__SD3_DATA7		0x170f9
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT8__WDOG1_B		0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6qdl-gw5907.dtsi b/arch/arm/dts/imx6qdl-gw5907.dtsi
new file mode 100644
index 0000000..c8b2924
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-gw5907.dtsi
@@ -0,0 +1,539 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Gateworks Corporation
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		led0 = &led0;
+		led1 = &led1;
+		nand = &gpmi;
+		usb0 = &usbh1;
+		usb1 = &usbotg;
+	};
+
+	chosen {
+		stdout-path = &uart2;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		user-pb {
+			label = "user_pb";
+			gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+		};
+
+		user-pb1x {
+			label = "user_pb1x";
+			linux,code = <BTN_1>;
+			interrupt-parent = <&gsc>;
+			interrupts = <0>;
+		};
+
+		key-erased {
+			label = "key-erased";
+			linux,code = <BTN_2>;
+			interrupt-parent = <&gsc>;
+			interrupts = <1>;
+		};
+
+		eeprom-wp {
+			label = "eeprom_wp";
+			linux,code = <BTN_3>;
+			interrupt-parent = <&gsc>;
+			interrupts = <2>;
+		};
+
+		tamper {
+			label = "tamper";
+			linux,code = <BTN_4>;
+			interrupt-parent = <&gsc>;
+			interrupts = <5>;
+		};
+
+		switch-hold {
+			label = "switch_hold";
+			linux,code = <BTN_5>;
+			interrupt-parent = <&gsc>;
+			interrupts = <7>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDG */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDR */
+			default-state = "off";
+		};
+	};
+
+	memory@10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x20000000>;
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pps>;
+		gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+		status = "okay";
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_5p0v: regulator-5p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "5P0V";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	reg_usb_otg_vbus: regulator-usb-otg-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii-id";
+	phy-reset-gpios = <&gpio1 30 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c3>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	gsc: gsc@20 {
+		compatible = "gw,gsc";
+		reg = <0x20>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		#size-cells = <0>;
+
+		adc {
+			compatible = "gw,gsc-adc";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			channel@0 {
+				gw,mode = <0>;
+				reg = <0x00>;
+				label = "temp";
+			};
+
+			channel@2 {
+				gw,mode = <1>;
+				reg = <0x02>;
+				label = "vdd_vin";
+			};
+
+			channel@5 {
+				gw,mode = <1>;
+				reg = <0x05>;
+				label = "vdd_3p3";
+			};
+
+			channel@8 {
+				gw,mode = <1>;
+				reg = <0x08>;
+				label = "vdd_bat";
+			};
+
+			channel@b {
+				gw,mode = <1>;
+				reg = <0x0b>;
+				label = "vdd_5p0";
+			};
+
+			channel@e {
+				gw,mode = <1>;
+				reg = <0xe>;
+				label = "vdd_arm";
+			};
+
+			channel@11 {
+				gw,mode = <1>;
+				reg = <0x11>;
+				label = "vdd_soc";
+			};
+
+			channel@14 {
+				gw,mode = <1>;
+				reg = <0x14>;
+				label = "vdd_3p0";
+			};
+
+			channel@17 {
+				gw,mode = <1>;
+				reg = <0x17>;
+				label = "vdd_1p5";
+			};
+
+			channel@1d {
+				gw,mode = <1>;
+				reg = <0x1d>;
+				label = "vdd_1p8";
+			};
+
+			channel@20 {
+				gw,mode = <1>;
+				reg = <0x20>;
+				label = "vdd_an1";
+			};
+
+			channel@23 {
+				gw,mode = <1>;
+				reg = <0x23>;
+				label = "vdd_2p5";
+			};
+		};
+	};
+
+	gsc_gpio: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gsc>;
+		interrupts = <4>;
+	};
+
+	eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	ds1672@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	gpio@20 {
+		compatible = "nxp,pca9555";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	adc@48 {
+		compatible = "ti,ads1015";
+		reg = <0x48>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		channel@4 {
+			reg = <4>;
+			ti,gain = <0>;
+			ti,datarate = <5>;
+		};
+
+		channel@5 {
+			reg = <5>;
+			ti,gain = <0>;
+			ti,datarate = <5>;
+		};
+
+		channel@6 {
+			reg = <6>;
+			ti,gain = <0>;
+			ti,datarate = <5>;
+		};
+	};
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio1 0 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>; /* MX6_DIO1 */
+	status = "disabled";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>; /* MX6_DIO2 */
+	status = "disabled";
+};
+
+&pwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>; /* MX6_DIO3 */
+	status = "disabled";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+};
+
+&iomuxc {
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b0b0
+			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b0b0
+			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b0b0
+			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b0b0
+			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b0b0
+			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			MX6QDL_PAD_ENET_TXD0__GPIO1_IO30	0x1b0b0
+		>;
+	};
+
+	pinctrl_gpio_leds: gpioledsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL0__GPIO4_IO06		0x1b0b0
+			MX6QDL_PAD_KEY_ROW0__GPIO4_IO07		0x1b0b0
+		>;
+	};
+
+	pinctrl_gpmi_nand: gpminandgrp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+			MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+			MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+			MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+			MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+			MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+			MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+			MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+			MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+			MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+			MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+			MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+			MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+			MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0x0001b0b0
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x1b0b0
+			MX6QDL_PAD_GPIO_19__GPIO4_IO05		0x1b0b0
+		>;
+	};
+
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_0__GPIO1_IO00		0x1b0b0
+		>;
+	};
+
+	pinctrl_pps: ppsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_RXD1__GPIO1_IO26	0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT2__PWM2_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT1__PWM3_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm4: pwm4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_CMD__PWM4_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+			MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			MX6QDL_PAD_EIM_D22__GPIO3_IO22		0x1b0b0
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT8__WDOG1_B		0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6qdl-gw5910.dtsi b/arch/arm/dts/imx6qdl-gw5910.dtsi
new file mode 100644
index 0000000..248e077
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-gw5910.dtsi
@@ -0,0 +1,668 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Gateworks Corporation
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		led0 = &led0;
+		led1 = &led1;
+		led2 = &led2;
+		mmc0 = &usdhc3;
+	};
+
+	chosen {
+		stdout-path = &uart2;
+	};
+
+	memory@10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x20000000>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		user-pb {
+			label = "user_pb";
+			gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+		};
+
+		user-pb1x {
+			label = "user_pb1x";
+			linux,code = <BTN_1>;
+			interrupt-parent = <&gsc>;
+			interrupts = <0>;
+		};
+
+		key-erased {
+			label = "key-erased";
+			linux,code = <BTN_2>;
+			interrupt-parent = <&gsc>;
+			interrupts = <1>;
+		};
+
+		eeprom-wp {
+			label = "eeprom_wp";
+			linux,code = <BTN_3>;
+			interrupt-parent = <&gsc>;
+			interrupts = <2>;
+		};
+
+		tamper {
+			label = "tamper";
+			linux,code = <BTN_4>;
+			interrupt-parent = <&gsc>;
+			interrupts = <5>;
+		};
+
+		switch-hold {
+			label = "switch_hold";
+			linux,code = <BTN_5>;
+			interrupt-parent = <&gsc>;
+			interrupts = <7>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDG */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDR */
+			default-state = "off";
+		};
+
+		led2: user3 {
+			label = "user3";
+			gpios = <&gpio4 15 GPIO_ACTIVE_LOW>; /* MX6_LOCLED# */
+			default-state = "off";
+		};
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pps>;
+		gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>;
+		status = "okay";
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_5p0v: regulator-5p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "5P0V";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	reg_wl: regulator-wl {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_reg_wl>;
+		compatible = "regulator-fixed";
+		regulator-name = "wl";
+		gpio = <&gpio1 5 GPIO_ACTIVE_HIGH>;
+		startup-delay-us = <100>;
+		enable-active-high;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+};
+
+
+&ecspi3 {
+	cs-gpios = <&gpio4 24 GPIO_ACTIVE_LOW>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi3>;
+	status = "okay";
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii-id";
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	gsc: gsc@20 {
+		compatible = "gw,gsc";
+		reg = <0x20>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		#size-cells = <0>;
+
+		adc {
+			compatible = "gw,gsc-adc";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			channel@6 {
+				gw,mode = <0>;
+				reg = <0x06>;
+				label = "temp";
+			};
+
+			channel@8 {
+				gw,mode = <3>;
+				reg = <0x08>;
+				label = "vdd_bat";
+			};
+
+			channel@82 {
+				gw,mode = <2>;
+				reg = <0x82>;
+				label = "vdd_vin";
+				gw,voltage-divider-ohms = <22100 1000>;
+				gw,voltage-offset-microvolt = <800000>;
+			};
+
+			channel@84 {
+				gw,mode = <2>;
+				reg = <0x84>;
+				label = "vdd_5p0";
+				gw,voltage-divider-ohms = <22100 10000>;
+			};
+
+			channel@86 {
+				gw,mode = <2>;
+				reg = <0x86>;
+				label = "vdd_3p3";
+				gw,voltage-divider-ohms = <10000 10000>;
+			};
+
+			channel@88 {
+				gw,mode = <2>;
+				reg = <0x88>;
+				label = "vdd_2p5";
+				gw,voltage-divider-ohms = <10000 10000>;
+			};
+
+			channel@8c {
+				gw,mode = <2>;
+				reg = <0x8c>;
+				label = "vdd_3p0";
+			};
+
+			channel@8e {
+				gw,mode = <2>;
+				reg = <0x8e>;
+				label = "vdd_arm";
+			};
+
+			channel@90 {
+				gw,mode = <2>;
+				reg = <0x90>;
+				label = "vdd_soc";
+			};
+
+			channel@92 {
+				gw,mode = <2>;
+				reg = <0x92>;
+				label = "vdd_1p5";
+			};
+
+			channel@98 {
+				gw,mode = <2>;
+				reg = <0x98>;
+				label = "vdd_1p8";
+			};
+
+			channel@9a {
+				gw,mode = <2>;
+				reg = <0x9a>;
+				label = "vdd_1p0";
+				gw,voltage-divider-ohms = <10000 10000>;
+			};
+
+			channel@9c {
+				gw,mode = <2>;
+				reg = <0x9c>;
+				label = "vdd_an1";
+				gw,voltage-divider-ohms = <10000 10000>;
+			};
+
+			channel@a2 {
+				gw,mode = <2>;
+				reg = <0xa2>;
+				label = "vdd_gsc";
+				gw,voltage-divider-ohms = <10000 10000>;
+			};
+		};
+	};
+
+	gsc_gpio: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gsc>;
+		interrupts = <4>;
+	};
+
+	eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	rtc@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	accel@19 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_accel>;
+		compatible = "st,lis2de12";
+		reg = <0x19>;
+		st,drdy-int-pin = <1>;
+		interrupt-parent = <&gpio7>;
+		interrupts = <13 0>;
+		interrupt-names = "INT1";
+	};
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio3 20 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>; /* MX6_DIO1 */
+	status = "disabled";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>; /* MX6_DIO2 */
+	status = "disabled";
+};
+
+/* off-board RS232 */
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+/* serial console */
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+/* cc1352 */
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	uart-has-rtscts;
+	status = "okay";
+};
+
+/* Sterling-LWB Bluetooth */
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>,<&pinctrl_bten>;
+	uart-has-rtscts;
+	status = "okay";
+
+	bluetooth {
+		compatible = "brcm,bcm4330-bt";
+		shutdown-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+/* GPS */
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_5p0v>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+/* Sterling-LWB SDIO WiFi */
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	vmmc-supply = <&reg_wl>;
+	non-removable;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+	cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+};
+
+&iomuxc {
+	pinctrl_accel: accelmuxgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_18__GPIO7_IO13		0x1b0b1
+		>;
+	};
+
+	pinctrl_bten: btengrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x1b0b1
+		>;
+	};
+
+	pinctrl_ecspi3: escpi3grp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK	0x100b1
+			MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI	0x100b1
+			MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO	0x100b1
+			MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24	0x100b1
+		>;
+	};
+
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b030
+			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b030
+			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b030
+			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030
+			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030
+			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b030
+			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b030
+			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b030
+			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b030
+			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b030
+			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b030
+			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b030
+			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			MX6QDL_PAD_ENET_TXD0__GPIO1_IO30	0x1b0b0
+		>;
+	};
+
+	pinctrl_gpio_leds: gpioledsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL0__GPIO4_IO06  0x1b0b0
+			MX6QDL_PAD_KEY_ROW0__GPIO4_IO07  0x1b0b0
+			MX6QDL_PAD_KEY_ROW4__GPIO4_IO15  0x1b0b0
+		>;
+	};
+
+	pinctrl_gpmi_nand: gpminandgrp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+			MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+			MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+			MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+			MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+			MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+			MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+			MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+			MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+			MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+			MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+			MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+			MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+			MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0x0001b0b0
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D20__GPIO3_IO20		0x1b0b0
+		>;
+	};
+
+	pinctrl_pps: ppsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_DI0_DISP_CLK__GPIO4_IO16	0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT2__PWM2_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT1__PWM3_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_reg_wl: regwlgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_5__GPIO1_IO05		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
+			MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D23__UART3_RTS_B		0x1b0b1
+			MX6QDL_PAD_EIM_D31__UART3_CTS_B		0x1b0b1
+			MX6QDL_PAD_EIM_A25__GPIO5_IO02		0x4001b0b1 /* DIO20 */
+			MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05	0x4001b0b1 /* DIO14 */
+			MX6QDL_PAD_DISP0_DAT12__GPIO5_IO06	0x4001b0b1 /* DIO15 */
+			MX6QDL_PAD_DISP0_DAT14__GPIO5_IO08	0x1b0b1 /* TMS */
+			MX6QDL_PAD_DISP0_DAT15__GPIO5_IO09	0x1b0b1 /* TCK */
+			MX6QDL_PAD_DISP0_DAT16__GPIO5_IO10	0x1b0b1 /* TDO */
+			MX6QDL_PAD_DISP0_DAT17__GPIO5_IO11	0x1b0b1 /* TDI */
+			MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17	0x4001b0b1 /* RST# */
+		>;
+	};
+
+	pinctrl_uart4: uart4grp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA	0x1b0b1
+			MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA	0x1b0b1
+			MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B	0x1b0b1
+			MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+			MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x13059
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD2_CMD__SD2_CMD		0x17059
+			MX6QDL_PAD_SD2_CLK__SD2_CLK		0x10059
+			MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x17059
+			MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x17059
+			MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x17059
+			MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x17059
+		>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x17059 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x17059
+		>;
+	};
+
+	pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170b9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x170b9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170b9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170b9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170b9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170b9
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x170b9 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x170b9
+		>;
+	};
+
+	pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170f9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100f9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170f9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170f9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170f9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170f9
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x170f9 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x170f9
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT8__WDOG1_B		0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6qdl-gw5912.dtsi b/arch/arm/dts/imx6qdl-gw5912.dtsi
new file mode 100644
index 0000000..7593872
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-gw5912.dtsi
@@ -0,0 +1,609 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Gateworks Corporation
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		led0 = &led0;
+		led1 = &led1;
+		led2 = &led2;
+		mmc0 = &usdhc3;
+		nand = &gpmi;
+		usb0 = &usbh1;
+		usb1 = &usbotg;
+	};
+
+	chosen {
+		stdout-path = &uart2;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		user-pb {
+			label = "user_pb";
+			gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+		};
+
+		user-pb1x {
+			label = "user_pb1x";
+			linux,code = <BTN_1>;
+			interrupt-parent = <&gsc>;
+			interrupts = <0>;
+		};
+
+		key-erased {
+			label = "key-erased";
+			linux,code = <BTN_2>;
+			interrupt-parent = <&gsc>;
+			interrupts = <1>;
+		};
+
+		eeprom-wp {
+			label = "eeprom_wp";
+			linux,code = <BTN_3>;
+			interrupt-parent = <&gsc>;
+			interrupts = <2>;
+		};
+
+		tamper {
+			label = "tamper";
+			linux,code = <BTN_4>;
+			interrupt-parent = <&gsc>;
+			interrupts = <5>;
+		};
+
+		switch-hold {
+			label = "switch_hold";
+			linux,code = <BTN_5>;
+			interrupt-parent = <&gsc>;
+			interrupts = <7>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDG */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDR */
+			default-state = "off";
+		};
+
+		led2: user3 {
+			label = "user3";
+			gpios = <&gpio4 15 GPIO_ACTIVE_LOW>; /* MX6_LOCLED# */
+			default-state = "off";
+		};
+	};
+
+	memory@10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x40000000>;
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pps>;
+		gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_usb_vbus: regulator-5p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	status = "okay";
+};
+
+&ecspi2 {
+	cs-gpios = <&gpio2 26 GPIO_ACTIVE_LOW>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi2>;
+	status = "okay";
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii-id";
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	gsc: gsc@20 {
+		compatible = "gw,gsc";
+		reg = <0x20>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		adc {
+			compatible = "gw,gsc-adc";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			channel@0 {
+				gw,mode = <0>;
+				reg = <0x00>;
+				label = "temp";
+			};
+
+			channel@2 {
+				gw,mode = <1>;
+				reg = <0x02>;
+				label = "vdd_vin";
+			};
+
+			channel@5 {
+				gw,mode = <1>;
+				reg = <0x05>;
+				label = "vdd_3p3";
+			};
+
+			channel@8 {
+				gw,mode = <1>;
+				reg = <0x08>;
+				label = "vdd_bat";
+			};
+
+			channel@b {
+				gw,mode = <1>;
+				reg = <0x0b>;
+				label = "vdd_5p0";
+			};
+
+			channel@e {
+				gw,mode = <1>;
+				reg = <0xe>;
+				label = "vdd_arm";
+			};
+
+			channel@11 {
+				gw,mode = <1>;
+				reg = <0x11>;
+				label = "vdd_soc";
+			};
+
+			channel@14 {
+				gw,mode = <1>;
+				reg = <0x14>;
+				label = "vdd_3p0";
+			};
+
+			channel@17 {
+				gw,mode = <1>;
+				reg = <0x17>;
+				label = "vdd_1p5";
+			};
+
+			channel@1d {
+				gw,mode = <1>;
+				reg = <0x1d>;
+				label = "vdd_1p8";
+			};
+
+			channel@20 {
+				gw,mode = <1>;
+				reg = <0x20>;
+				label = "vdd_1p0";
+			};
+
+			channel@23 {
+				gw,mode = <1>;
+				reg = <0x23>;
+				label = "vdd_2p5";
+			};
+		};
+
+		fan-controller@a {
+			compatible = "gw,gsc-fan";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0a>;
+		};
+	};
+
+	gsc_gpio: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gsc>;
+		interrupts = <4>;
+	};
+
+	eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	rtc@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	accel@19 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_accel>;
+		compatible = "st,lis2de12";
+		reg = <0x19>;
+		st,drdy-int-pin = <1>;
+		interrupt-parent = <&gpio7>;
+		interrupts = <13 0>;
+		interrupt-names = "INT1";
+	};
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio1 29 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>; /* MX6_DIO0 */
+	status = "disabled";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>; /* MX6_DIO1 */
+	status = "disabled";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>; /* MX6_DIO2 */
+	status = "disabled";
+};
+
+&pwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>; /* MX6_DIO3 */
+	status = "disabled";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	rts-gpios = <&gpio7 12 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_vbus>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+	cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
+	vmmc-supply = <&reg_3p3v>;
+	no-1-8-v; /* firmware will remove if board revision supports */
+	status = "okay";
+};
+
+&wdog1 {
+	status = "disabled";
+};
+
+&wdog2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl_accel: accelmuxgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_18__GPIO7_IO13		0x1b0b1
+		>;
+	};
+
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b030
+			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b030
+			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b030
+			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030
+			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030
+			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b030
+			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b030
+			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b030
+			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b030
+			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b030
+			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b030
+			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b030
+			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+		>;
+	};
+
+	pinctrl_ecspi2: escpi2grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_CS0__ECSPI2_SCLK	0x100b1
+			MX6QDL_PAD_EIM_CS1__ECSPI2_MOSI	0x100b1
+			MX6QDL_PAD_EIM_OE__ECSPI2_MISO	0x100b1
+			MX6QDL_PAD_EIM_RW__GPIO2_IO26	0x100b1
+		>;
+	};
+
+	pinctrl_flexcan1: flexcan1grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX	0x1b0b1
+			MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX	0x1b0b1
+			MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x4001b0b0
+		>;
+	};
+
+	pinctrl_gpio_leds: gpioledsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL0__GPIO4_IO06		0x1b0b0
+			MX6QDL_PAD_KEY_ROW0__GPIO4_IO07		0x1b0b0
+			MX6QDL_PAD_KEY_ROW4__GPIO4_IO15		0x1b0b0
+		>;
+	};
+
+	pinctrl_gpmi_nand: gpminandgrp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+			MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+			MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+			MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+			MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+			MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+			MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+			MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+			MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+			MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+			MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+			MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+			MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+			MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0x0001b0b0
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28	0x1b0b0
+			MX6QDL_PAD_ENET_TXD1__GPIO1_IO29	0x1b0b0
+		>;
+	};
+
+	pinctrl_pps: ppsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_5__GPIO1_IO05		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm1: pwm1grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_9__PWM1_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT2__PWM2_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT1__PWM3_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm4: pwm4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT2__PWM4_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+			MX6QDL_PAD_GPIO_17__GPIO7_IO12		0x4001b0b1
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT3__GPIO2_IO11		0x4001b0b1
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+			MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x13059
+		>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x17059 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x17059
+		>;
+	};
+
+	pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170b9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100b9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170b9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170b9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170b9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170b9
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x170b9 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x170b9
+		>;
+	};
+
+	pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x170f9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x100f9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x170f9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x170f9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x170f9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x170f9
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x170f9 /* CD */
+			MX6QDL_PAD_NANDF_CS1__SD3_VSELECT	0x170f9
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT3__WDOG2_B		0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6qdl-gw5913.dtsi b/arch/arm/dts/imx6qdl-gw5913.dtsi
new file mode 100644
index 0000000..9fae4cc
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-gw5913.dtsi
@@ -0,0 +1,501 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Gateworks Corporation
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	/* these are used by bootloader for disabling nodes */
+	aliases {
+		led0 = &led0;
+		led1 = &led1;
+		nand = &gpmi;
+		usb0 = &usbh1;
+		usb1 = &usbotg;
+	};
+
+	chosen {
+		stdout-path = &uart2;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		user-pb {
+			label = "user_pb";
+			gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+		};
+
+		user-pb1x {
+			label = "user_pb1x";
+			linux,code = <BTN_1>;
+			interrupt-parent = <&gsc>;
+			interrupts = <0>;
+		};
+
+		key-erased {
+			label = "key-erased";
+			linux,code = <BTN_2>;
+			interrupt-parent = <&gsc>;
+			interrupts = <1>;
+		};
+
+		eeprom-wp {
+			label = "eeprom_wp";
+			linux,code = <BTN_3>;
+			interrupt-parent = <&gsc>;
+			interrupts = <2>;
+		};
+
+		tamper {
+			label = "tamper";
+			linux,code = <BTN_4>;
+			interrupt-parent = <&gsc>;
+			interrupts = <5>;
+		};
+
+		switch-hold {
+			label = "switch_hold";
+			linux,code = <BTN_5>;
+			interrupt-parent = <&gsc>;
+			interrupts = <7>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		led0: user1 {
+			label = "user1";
+			gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDG */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1: user2 {
+			label = "user2";
+			gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDR */
+			default-state = "off";
+		};
+	};
+
+	memory@10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x20000000>;
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pps>;
+		gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>;
+		status = "okay";
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_5p0v: regulator-5p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "5P0V";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii-id";
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	gsc: gsc@20 {
+		compatible = "gw,gsc";
+		reg = <0x20>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		#size-cells = <0>;
+
+		adc {
+			compatible = "gw,gsc-adc";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			channel@6 {
+				gw,mode = <0>;
+				reg = <0x06>;
+				label = "temp";
+			};
+
+			channel@8 {
+				gw,mode = <3>;
+				reg = <0x08>;
+				label = "vdd_bat";
+			};
+
+			channel@82 {
+				gw,mode = <2>;
+				reg = <0x82>;
+				label = "vdd_vin";
+				gw,voltage-divider-ohms = <22100 1000>;
+				gw,voltage-offset-microvolt = <800000>;
+			};
+
+			channel@84 {
+				gw,mode = <2>;
+				reg = <0x84>;
+				label = "vdd_5p0";
+				gw,voltage-divider-ohms = <22100 10000>;
+			};
+
+			channel@86 {
+				gw,mode = <2>;
+				reg = <0x86>;
+				label = "vdd_3p3";
+				gw,voltage-divider-ohms = <10000 10000>;
+			};
+
+			channel@88 {
+				gw,mode = <2>;
+				reg = <0x88>;
+				label = "vdd_2p5";
+				gw,voltage-divider-ohms = <10000 10000>;
+			};
+
+			channel@8c {
+				gw,mode = <2>;
+				reg = <0x8c>;
+				label = "vdd_arm";
+			};
+
+			channel@8e {
+				gw,mode = <2>;
+				reg = <0x8e>;
+				label = "vdd_soc";
+			};
+
+			channel@90 {
+				gw,mode = <2>;
+				reg = <0x90>;
+				label = "vdd_1p5";
+			};
+
+			channel@92 {
+				gw,mode = <2>;
+				reg = <0x92>;
+				label = "vdd_1p0";
+			};
+
+			channel@98 {
+				gw,mode = <2>;
+				reg = <0x98>;
+				label = "vdd_3p0";
+			};
+
+			channel@9a {
+				gw,mode = <2>;
+				reg = <0x9a>;
+				label = "vdd_an1";
+				gw,voltage-divider-ohms = <10000 10000>;
+			};
+
+			channel@a2 {
+				gw,mode = <2>;
+				reg = <0xa2>;
+				label = "vdd_gsc";
+				gw,voltage-divider-ohms = <10000 10000>;
+			};
+		};
+	};
+
+	gsc_gpio: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gsc>;
+		interrupts = <4>;
+	};
+
+	eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	rtc@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio1 0 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>; /* MX6_DIO1 */
+	status = "disabled";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>; /* MX6_DIO2 */
+	status = "disabled";
+};
+
+&pwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>; /* MX6_DIO3 */
+	status = "disabled";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbotg {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+};
+
+&iomuxc {
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b030
+			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b030
+			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b030
+			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030
+			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030
+			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b030
+			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b030
+			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b030
+			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b030
+			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b030
+			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b030
+			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b030
+			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			MX6QDL_PAD_ENET_TXD0__GPIO1_IO30	0x1b0b0
+		>;
+	};
+
+	pinctrl_gpio_leds: gpioledsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL0__GPIO4_IO06		0x1b0b0
+			MX6QDL_PAD_KEY_ROW0__GPIO4_IO07		0x1b0b0
+		>;
+	};
+
+	pinctrl_gpmi_nand: gpminandgrp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+			MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+			MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+			MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+			MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+			MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+			MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+			MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+			MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+			MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+			MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+			MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+			MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+			MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0x0001b0b0
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_0__GPIO1_IO00		0x1b0b0
+		>;
+	};
+
+	pinctrl_pps: ppsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT2__PWM2_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT1__PWM3_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm4: pwm4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_CMD__PWM4_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+			MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT8__WDOG1_B		0x1b0b0
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx6qdl-udoo-u-boot.dtsi b/arch/arm/dts/imx6qdl-udoo-u-boot.dtsi
new file mode 100644
index 0000000..749791a
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-udoo-u-boot.dtsi
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/ {
+	aliases {
+		mmc0 = &usdhc3;
+	};
+};
diff --git a/arch/arm/dts/imx6qdl-udoo.dtsi b/arch/arm/dts/imx6qdl-udoo.dtsi
new file mode 100644
index 0000000..d07d8f8
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-udoo.dtsi
@@ -0,0 +1,324 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ */
+
+/ {
+	aliases {
+		backlight = &backlight;
+		panelchan = &panelchan;
+		panel7 = &panel7;
+		touchscreenp7 = &touchscreenp7;
+	};
+
+	chosen {
+		stdout-path = &uart2;
+	};
+
+	backlight: backlight {
+		compatible = "gpio-backlight";
+		gpios = <&gpio1 4 0>;
+		default-on;
+		status = "disabled";
+	};
+
+	gpio-poweroff {
+		compatible = "gpio-poweroff";
+		gpios = <&gpio2 4 0>;
+		pinctrl-0 = <&pinctrl_power_off>;
+		pinctrl-names = "default";
+	};
+
+	memory@10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x40000000>;
+	};
+
+	panel7: panel7 {
+		/*
+		 * in reality it is a -20t (parallel) model,
+		 * but with LVDS bridge chip attached,
+		 * so it is equivalent to -19t model in drive
+		 * characteristics
+		 */
+		compatible = "urt,umsh-8596md-19t";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_panel>;
+		power-supply = <&reg_panel>;
+		backlight = <&backlight>;
+		status = "disabled";
+
+		port {
+			panel_in: endpoint {
+				remote-endpoint = <&lvds0_out>;
+			};
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_usb_h1_vbus: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "usb_h1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			startup-delay-us = <2>; /* USB2415 requires a POR of 1 us minimum */
+			gpio = <&gpio7 12 0>;
+		};
+
+		reg_panel: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "lcd_panel";
+			enable-active-high;
+			gpio = <&gpio1 2 0>;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx6q-udoo-ac97",
+			     "fsl,imx-audio-ac97";
+		model = "fsl,imx6q-udoo-ac97";
+		audio-cpu = <&ssi1>;
+		audio-routing =
+			"RX", "Mic Jack",
+			"Headphone Jack", "TX";
+		mux-int-port = <1>;
+		mux-ext-port = <6>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii-id";
+	status = "okay";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c2>;
+	status = "okay";
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	touchscreenp7: touchscreenp7@55 {
+		compatible = "sitronix,st1232";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_touchscreenp7>;
+		reg = <0x55>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <13 8>;
+		gpios = <&gpio1 15 0>;
+		status = "disabled";
+	};
+};
+
+&iomuxc {
+	imx6q-udoo {
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b030
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b030
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b030
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b030
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b030
+				MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b030
+				MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b030
+				MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b030
+				MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b030
+				MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b030
+				MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_5__I2C3_SCL		0x4001f8b1
+				MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001f8b1
+			>;
+		};
+
+		pinctrl_panel: panelgrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x70
+				MX6QDL_PAD_GPIO_4__GPIO1_IO04		0x70
+			>;
+		};
+
+		pinctrl_power_off: poweroffgrp {
+			fsl,pins = <
+				MX6QDL_PAD_NANDF_D4__GPIO2_IO04		0x30
+			>;
+		};
+
+		pinctrl_touchscreenp7: touchscreenp7grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_DAT0__GPIO1_IO15		0x70
+				MX6QDL_PAD_SD2_DAT2__GPIO1_IO13		0x1b0b0
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D26__UART2_TX_DATA	0x1b0b1
+				MX6QDL_PAD_EIM_D27__UART2_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_uart4: uart4grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL0__UART4_TX_DATA	0x1b0b1
+				MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA	0x1b0b1
+			>;
+		};
+
+		pinctrl_usbh: usbhgrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000
+				MX6QDL_PAD_NANDF_CS2__CCM_CLKO2 0x130b0
+			>;
+		};
+
+		pinctrl_usbotg: usbotg {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+				MX6QDL_PAD_EIM_D22__USB_OTG_PWR 0x17059
+				MX6QDL_PAD_EIM_D21__USB_OTG_OC 0x17059
+			>;
+		};
+
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+			>;
+		};
+
+		pinctrl_ac97_running: ac97running {
+			fsl,pins = <
+				MX6QDL_PAD_DI0_PIN2__AUD6_TXD		0x1b0b0
+				MX6QDL_PAD_DI0_PIN3__AUD6_TXFS		0x1b0b0
+				MX6QDL_PAD_DI0_PIN4__AUD6_RXD		0x13080
+				MX6QDL_PAD_DI0_PIN15__AUD6_TXC		0x13080
+				MX6QDL_PAD_EIM_EB2__GPIO2_IO30		0x1b0b0
+			>;
+		};
+
+		pinctrl_ac97_warm_reset: ac97warmreset {
+			fsl,pins = <
+				MX6QDL_PAD_DI0_PIN2__AUD6_TXD		0x1b0b0
+				MX6QDL_PAD_DI0_PIN3__GPIO4_IO19		0x1b0b0
+				MX6QDL_PAD_DI0_PIN4__AUD6_RXD		0x13080
+				MX6QDL_PAD_DI0_PIN15__AUD6_TXC		0x13080
+				MX6QDL_PAD_EIM_EB2__GPIO2_IO30		0x1b0b0
+			>;
+		};
+
+		pinctrl_ac97_reset: ac97reset {
+			fsl,pins = <
+				MX6QDL_PAD_DI0_PIN2__GPIO4_IO18		0x1b0b0
+				MX6QDL_PAD_DI0_PIN3__GPIO4_IO19		0x1b0b0
+				MX6QDL_PAD_DI0_PIN4__AUD6_RXD		0x13080
+				MX6QDL_PAD_DI0_PIN15__AUD6_TXC		0x13080
+				MX6QDL_PAD_EIM_EB2__GPIO2_IO30		0x1b0b0
+			>;
+		};
+	};
+};
+
+&ldb {
+	status = "okay";
+
+	panelchan: lvds-channel@0 {
+		port@4 {
+			reg = <4>;
+
+			lvds0_out: endpoint {
+				remote-endpoint = <&panel_in>;
+			};
+		};
+	};
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>;
+	status = "okay";
+};
+
+&usbh1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbh>;
+	vbus-supply = <&reg_usb_h1_vbus>;
+	clocks = <&clks IMX6QDL_CLK_CKO>;
+	status = "okay";
+};
+
+&usbotg {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	non-removable;
+	status = "okay";
+};
+
+&audmux {
+	status = "okay";
+};
+
+&ssi1 {
+	cell-index = <0>;
+	fsl,mode = "ac97-slave";
+	pinctrl-names = "ac97-running", "ac97-reset", "ac97-warm-reset";
+	pinctrl-0 = <&pinctrl_ac97_running>;
+	pinctrl-1 = <&pinctrl_ac97_reset>;
+	pinctrl-2 = <&pinctrl_ac97_warm_reset>;
+	ac97-gpios = <&gpio4 19 0 &gpio4 18 0 &gpio2 30 0>;
+	status = "okay";
+};
diff --git a/arch/arm/dts/imx8mm-evk-u-boot.dtsi b/arch/arm/dts/imx8mm-evk-u-boot.dtsi
index e843a56..3701557 100644
--- a/arch/arm/dts/imx8mm-evk-u-boot.dtsi
+++ b/arch/arm/dts/imx8mm-evk-u-boot.dtsi
@@ -4,11 +4,22 @@
  */
 
 / {
+	binman: binman {
+		multiple-images;
+	};
+
 	wdt-reboot {
 		compatible = "wdt-reboot";
 		wdt = <&wdog1>;
 		u-boot,dm-spl;
 	};
+
+	firmware {
+		optee {
+			compatible = "linaro,optee-tz";
+			method = "smc";
+		};
+	};
 };
 
 &{/soc@0} {
@@ -102,6 +113,7 @@
 	u-boot,dm-spl;
 	sd-uhs-sdr104;
 	sd-uhs-ddr50;
+	fsl,signal-voltage-switch-extra-delay-ms = <8>;
 };
 
 &usdhc3 {
@@ -114,11 +126,11 @@
 	u-boot,dm-spl;
 };
 
-&{/soc@0/bus@30800000/i2c@30a20000/pmic@4b} {
+&{/soc@0/bus@30800000/i2c@30a20000/pca9450@25} {
 	u-boot,dm-spl;
 };
 
-&{/soc@0/bus@30800000/i2c@30a20000/pmic@4b/regulators} {
+&{/soc@0/bus@30800000/i2c@30a20000/pca9450@25/regulators} {
 	u-boot,dm-spl;
 };
 
@@ -137,3 +149,105 @@
 &wdog1 {
 	u-boot,dm-spl;
 };
+
+&binman {
+	 u-boot-spl-ddr {
+		filename = "u-boot-spl-ddr.bin";
+		pad-byte = <0xff>;
+		align-size = <4>;
+		align = <4>;
+
+		u-boot-spl {
+			align-end = <4>;
+		};
+
+		blob_1: blob-ext@1 {
+			filename = "lpddr4_pmu_train_1d_imem.bin";
+			size = <0x8000>;
+		};
+
+		blob_2: blob-ext@2 {
+			filename = "lpddr4_pmu_train_1d_dmem.bin";
+			size = <0x4000>;
+		};
+
+		blob_3: blob-ext@3 {
+			filename = "lpddr4_pmu_train_2d_imem.bin";
+			size = <0x8000>;
+		};
+
+		blob_4: blob-ext@4 {
+			filename = "lpddr4_pmu_train_2d_dmem.bin";
+			size = <0x4000>;
+		};
+	};
+
+
+       flash {
+		mkimage {
+			args = "-n spl/u-boot-spl.cfgout -T imx8mimage -e 0x7e1000";
+
+			blob {
+				filename = "u-boot-spl-ddr.bin";
+			};
+		};
+	};
+
+	itb {
+		filename = "u-boot.itb";
+
+		fit {
+			description = "Configuration to load ATF before U-Boot";
+			#address-cells = <1>;
+			fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
+
+			images {
+				uboot {
+					description = "U-Boot (64-bit)";
+					type = "standalone";
+					arch = "arm64";
+					compression = "none";
+					load = <CONFIG_SYS_TEXT_BASE>;
+
+					uboot_blob: blob-ext {
+						filename = "u-boot-nodtb.bin";
+					};
+				};
+
+				atf {
+					description = "ARM Trusted Firmware";
+					type = "firmware";
+					arch = "arm64";
+					compression = "none";
+					load = <0x920000>;
+					entry = <0x920000>;
+
+					atf_blob: blob-ext {
+						filename = "bl31.bin";
+					};
+				};
+
+				fdt {
+					description = "NAME";
+					type = "flat_dt";
+					compression = "none";
+
+					uboot_fdt_blob: blob-ext {
+						filename = "u-boot.dtb";
+					};
+				};
+			};
+
+			configurations {
+				default = "conf";
+
+				conf {
+					description = "NAME";
+					firmware = "uboot";
+					loadables = "atf";
+					fdt = "fdt";
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/imx8mm-evk.dtsi b/arch/arm/dts/imx8mm-evk.dtsi
index 6518f08..60179e0 100644
--- a/arch/arm/dts/imx8mm-evk.dtsi
+++ b/arch/arm/dts/imx8mm-evk.dtsi
@@ -126,115 +126,120 @@
 	pinctrl-0 = <&pinctrl_i2c1>;
 	status = "okay";
 
-	pmic@4b {
-		compatible = "rohm,bd71847";
-		reg = <0x4b>;
-		pinctrl-names = "default";
+	pmic: pca9450@25 {
+		reg = <0x25>;
+		compatible = "nxp,pca9450a";
+		/* PMIC PCA9450 PMIC_nINT GPIO1_IO3 */
 		pinctrl-0 = <&pinctrl_pmic>;
-		interrupt-parent = <&gpio1>;
-		interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
-		rohm,reset-snvs-powered;
-
-		#clock-cells = <0>;
-		clocks = <&osc_32k 0>;
-		clock-output-names = "clk-32k-out";
+		gpio_intr = <&gpio1 3 GPIO_ACTIVE_LOW>;
 
 		regulators {
-			buck1_reg: BUCK1 {
-				regulator-name = "buck1";
-				regulator-min-microvolt = <700000>;
-				regulator-max-microvolt = <1300000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			pca9450,pmic-buck2-uses-i2c-dvs;
+			/* Run/Standby voltage */
+			pca9450,pmic-buck2-dvs-voltage = <950000>, <850000>;
+
+			buck1_reg: regulator@0 {
+				reg = <0>;
+				regulator-compatible = "buck1";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <2187500>;
 				regulator-boot-on;
 				regulator-always-on;
-				regulator-ramp-delay = <1250>;
+				regulator-ramp-delay = <3125>;
 			};
 
-			buck2_reg: BUCK2 {
-				regulator-name = "buck2";
-				regulator-min-microvolt = <700000>;
-				regulator-max-microvolt = <1300000>;
+			buck2_reg: regulator@1 {
+				reg = <1>;
+				regulator-compatible = "buck2";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <2187500>;
 				regulator-boot-on;
 				regulator-always-on;
-				regulator-ramp-delay = <1250>;
-				rohm,dvs-run-voltage = <1000000>;
-				rohm,dvs-idle-voltage = <900000>;
+				regulator-ramp-delay = <3125>;
 			};
 
-			buck3_reg: BUCK3 {
-				// BUCK5 in datasheet
-				regulator-name = "buck3";
-				regulator-min-microvolt = <700000>;
-				regulator-max-microvolt = <1350000>;
+			buck3_reg: regulator@2 {
+				reg = <2>;
+				regulator-compatible = "buck3";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <2187500>;
 				regulator-boot-on;
 				regulator-always-on;
 			};
 
-			buck4_reg: BUCK4 {
-				// BUCK6 in datasheet
-				regulator-name = "buck4";
-				regulator-min-microvolt = <3000000>;
-				regulator-max-microvolt = <3300000>;
+			buck4_reg: regulator@3 {
+				reg = <3>;
+				regulator-compatible = "buck4";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <3400000>;
 				regulator-boot-on;
 				regulator-always-on;
 			};
 
-			buck5_reg: BUCK5 {
-				// BUCK7 in datasheet
-				regulator-name = "buck5";
-				regulator-min-microvolt = <1605000>;
-				regulator-max-microvolt = <1995000>;
+			buck5_reg: regulator@4 {
+				reg = <4>;
+				regulator-compatible = "buck5";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <3400000>;
 				regulator-boot-on;
 				regulator-always-on;
 			};
 
-			buck6_reg: BUCK6 {
-				// BUCK8 in datasheet
-				regulator-name = "buck6";
-				regulator-min-microvolt = <800000>;
-				regulator-max-microvolt = <1400000>;
+			buck6_reg: regulator@5 {
+				reg = <5>;
+				regulator-compatible = "buck6";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <3400000>;
 				regulator-boot-on;
 				regulator-always-on;
 			};
 
-			ldo1_reg: LDO1 {
-				regulator-name = "ldo1";
+			ldo1_reg: regulator@6 {
+				reg = <6>;
+				regulator-compatible = "ldo1";
 				regulator-min-microvolt = <1600000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-boot-on;
 				regulator-always-on;
 			};
 
-			ldo2_reg: LDO2 {
-				regulator-name = "ldo2";
+			ldo2_reg: regulator@7 {
+				reg = <7>;
+				regulator-compatible = "ldo2";
 				regulator-min-microvolt = <800000>;
-				regulator-max-microvolt = <900000>;
+				regulator-max-microvolt = <1150000>;
 				regulator-boot-on;
 				regulator-always-on;
 			};
 
-			ldo3_reg: LDO3 {
-				regulator-name = "ldo3";
-				regulator-min-microvolt = <1800000>;
+			ldo3_reg: regulator@8 {
+				reg = <8>;
+				regulator-compatible = "ldo3";
+				regulator-min-microvolt = <800000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-boot-on;
 				regulator-always-on;
 			};
 
-			ldo4_reg: LDO4 {
-				regulator-name = "ldo4";
-				regulator-min-microvolt = <900000>;
-				regulator-max-microvolt = <1800000>;
+			ldo4_reg: regulator@9 {
+				reg = <9>;
+				regulator-compatible = "ldo4";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
 				regulator-boot-on;
 				regulator-always-on;
 			};
 
-			ldo6_reg: LDO6 {
-				regulator-name = "ldo6";
-				regulator-min-microvolt = <900000>;
-				regulator-max-microvolt = <1800000>;
-				regulator-boot-on;
-				regulator-always-on;
+			ldo5_reg: regulator@10 {
+				reg = <10>;
+				regulator-compatible = "ldo5";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
 			};
+
 		};
 	};
 };
diff --git a/arch/arm/dts/imx8mn-beacon-baseboard.dtsi b/arch/arm/dts/imx8mn-beacon-baseboard.dtsi
index 49bff19..376ca8f 100644
--- a/arch/arm/dts/imx8mn-beacon-baseboard.dtsi
+++ b/arch/arm/dts/imx8mn-beacon-baseboard.dtsi
@@ -34,6 +34,15 @@
 		};
 	};
 
+	reg_audio: regulator-audio {
+		compatible = "regulator-fixed";
+		regulator-name = "3v3_aud";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&pca6416_1 11 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
 	reg_usdhc2_vmmc: regulator-usdhc2 {
 		compatible = "regulator-fixed";
 		regulator-name = "vsd_3v3";
@@ -53,6 +62,20 @@
 		gpio = <&gpio4 29 GPIO_ACTIVE_HIGH>;
 		enable-active-high;
 	};
+
+	sound {
+		compatible = "fsl,imx-audio-wm8962";
+		model = "wm8962-audio";
+		audio-cpu = <&sai3>;
+		audio-codec = <&wm8962>;
+		audio-routing =
+			"Headphone Jack", "HPOUTL",
+			"Headphone Jack", "HPOUTR",
+			"Ext Spk", "SPKOUTL",
+			"Ext Spk", "SPKOUTR",
+			"AMIC", "MICBIAS",
+			"IN3R", "AMIC";
+	};
 };
 
 &ecspi2 {
@@ -98,6 +121,44 @@
 		interrupt-parent = <&gpio4>;
 		interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
 	};
+
+	wm8962: audio-codec@1a {
+		compatible = "wlf,wm8962";
+		reg = <0x1a>;
+		clocks = <&clk IMX8MN_CLK_SAI3_ROOT>;
+		clock-names = "xclk";
+		DCVDD-supply = <&reg_audio>;
+		DBVDD-supply = <&reg_audio>;
+		AVDD-supply = <&reg_audio>;
+		CPVDD-supply = <&reg_audio>;
+		MICVDD-supply = <&reg_audio>;
+		PLLVDD-supply = <&reg_audio>;
+		SPKVDD1-supply = <&reg_audio>;
+		SPKVDD2-supply = <&reg_audio>;
+		gpio-cfg = <
+			0x0000 /* 0:Default */
+			0x0000 /* 1:Default */
+			0x0000 /* 2:FN_DMICCLK */
+			0x0000 /* 3:Default */
+			0x0000 /* 4:FN_DMICCDAT */
+			0x0000 /* 5:Default */
+		>;
+	};
+};
+
+&easrc {
+	fsl,asrc-rate  = <48000>;
+	status = "okay";
+};
+
+&sai3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sai3>;
+	assigned-clocks = <&clk IMX8MN_CLK_SAI3>;
+	assigned-clock-parents = <&clk IMX8MN_AUDIO_PLL1_OUT>;
+	assigned-clock-rates = <24576000>;
+	fsl,sai-mclk-direction-output;
+	status = "okay";
 };
 
 &snvs_pwrkey {
@@ -177,6 +238,16 @@
 		>;
 	};
 
+	pinctrl_sai3: sai3grp {
+		fsl,pins = <
+			MX8MN_IOMUXC_SAI3_TXFS_SAI3_TX_SYNC     0xd6
+			MX8MN_IOMUXC_SAI3_TXC_SAI3_TX_BCLK      0xd6
+			MX8MN_IOMUXC_SAI3_MCLK_SAI3_MCLK        0xd6
+			MX8MN_IOMUXC_SAI3_TXD_SAI3_TX_DATA0     0xd6
+			MX8MN_IOMUXC_SAI3_RXD_SAI3_RX_DATA0	0xd6
+		>;
+	};
+
 	pinctrl_uart2: uart2grp {
 		fsl,pins = <
 			MX8MN_IOMUXC_UART2_RXD_UART2_DCE_RX	0x140
diff --git a/arch/arm/dts/imx8mn-beacon-som.dtsi b/arch/arm/dts/imx8mn-beacon-som.dtsi
index 52a50d9..de2cd0e 100644
--- a/arch/arm/dts/imx8mn-beacon-som.dtsi
+++ b/arch/arm/dts/imx8mn-beacon-som.dtsi
@@ -4,6 +4,12 @@
  */
 
 / {
+	aliases {
+		rtc0 = &rtc;
+		rtc1 = &snvs_rtc;
+		spi0 = &flexspi;
+	};
+
 	usdhc1_pwrseq: usdhc1_pwrseq {
 		compatible = "mmc-pwrseq-simple";
 		pinctrl-names = "default";
@@ -36,11 +42,39 @@
 	cpu-supply = <&buck2_reg>;
 };
 
+/* DDR controller is running LPDDR at 800MHz which requires 0.95V */
+&a53_opp_table {
+	opp-1200000000 {
+		opp-microvolt = <950000>;
+	};
+};
+
+&ddrc {
+	operating-points-v2 = <&ddrc_opp_table>;
+
+	ddrc_opp_table: opp-table {
+		compatible = "operating-points-v2";
+
+		opp-25M {
+			opp-hz = /bits/ 64 <25000000>;
+		};
+
+		opp-100M {
+			opp-hz = /bits/ 64 <100000000>;
+		};
+
+		opp-800M {
+			opp-hz = /bits/ 64 <800000000>;
+		};
+	};
+};
+
 &fec1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_fec1>;
 	phy-mode = "rgmii-id";
 	phy-handle = <&ethphy0>;
+	phy-supply = <&buck6_reg>;
 	phy-reset-gpios = <&gpio4 22 GPIO_ACTIVE_LOW>;
 	fsl,magic-packet;
 	status = "okay";
@@ -56,6 +90,22 @@
 	};
 };
 
+&flexspi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexspi>;
+	status = "okay";
+
+	flash@0 {
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "jedec,spi-nor";
+		spi-max-frequency = <80000000>;
+		spi-tx-bus-width = <4>;
+		spi-rx-bus-width = <4>;
+	};
+};
+
 &i2c1 {
 	clock-frequency = <400000>;
 	pinctrl-names = "default";
@@ -184,7 +234,7 @@
 		reg = <0x50>;
 	};
 
-	rtc@51 {
+	rtc: rtc@51 {
 		compatible = "nxp,pcf85263";
 		reg = <0x51>;
 	};
@@ -285,6 +335,17 @@
 		>;
 	};
 
+	pinctrl_flexspi: flexspigrp {
+		fsl,pins = <
+			MX8MN_IOMUXC_NAND_ALE_QSPI_A_SCLK               0x1c2
+			MX8MN_IOMUXC_NAND_CE0_B_QSPI_A_SS0_B            0x82
+			MX8MN_IOMUXC_NAND_DATA00_QSPI_A_DATA0           0x82
+			MX8MN_IOMUXC_NAND_DATA01_QSPI_A_DATA1           0x82
+			MX8MN_IOMUXC_NAND_DATA02_QSPI_A_DATA2           0x82
+			MX8MN_IOMUXC_NAND_DATA03_QSPI_A_DATA3           0x82
+		>;
+	};
+
 	pinctrl_pmic: pmicirqgrp {
 		fsl,pins = <
 			MX8MN_IOMUXC_GPIO1_IO03_GPIO1_IO3		0x141
diff --git a/arch/arm/dts/imx8mn-ddr4-evk-u-boot.dtsi b/arch/arm/dts/imx8mn-ddr4-evk-u-boot.dtsi
index 025090f..1d38444 100644
--- a/arch/arm/dts/imx8mn-ddr4-evk-u-boot.dtsi
+++ b/arch/arm/dts/imx8mn-ddr4-evk-u-boot.dtsi
@@ -4,11 +4,21 @@
  */
 
 / {
+	binman: binman {
+		multiple-images;
+	};
+
 	wdt-reboot {
 		compatible = "wdt-reboot";
 		wdt = <&wdog1>;
 		u-boot,dm-spl;
 	};
+	firmware {
+		optee {
+			compatible = "linaro,optee-tz";
+			method = "smc";
+		};
+	};
 };
 
 &{/soc@0} {
@@ -19,6 +29,9 @@
 &clk {
 	u-boot,dm-spl;
 	u-boot,dm-pre-reloc;
+	/delete-property/ assigned-clocks;
+	/delete-property/ assigned-clock-parents;
+	/delete-property/ assigned-clock-rates;
 };
 
 &osc_24m {
@@ -110,3 +123,105 @@
 &wdog1 {
 	u-boot,dm-spl;
 };
+
+&binman {
+	 u-boot-spl-ddr {
+		filename = "u-boot-spl-ddr.bin";
+		pad-byte = <0xff>;
+		align-size = <4>;
+		align = <4>;
+
+		u-boot-spl {
+			align-end = <4>;
+		};
+
+		blob_1: blob-ext@1 {
+			filename = "ddr4_imem_1d_201810.bin";
+			size = <0x8000>;
+		};
+
+		blob_2: blob-ext@2 {
+			filename = "ddr4_dmem_1d_201810.bin";
+			size = <0x4000>;
+		};
+
+		blob_3: blob-ext@3 {
+			filename = "ddr4_imem_2d_201810.bin";
+			size = <0x8000>;
+		};
+
+		blob_4: blob-ext@4 {
+			filename = "ddr4_dmem_2d_201810.bin";
+			size = <0x4000>;
+		};
+	};
+
+
+	flash {
+		mkimage {
+			args = "-n spl/u-boot-spl.cfgout -T imx8mimage -e 0x912000";
+
+			blob {
+				filename = "u-boot-spl-ddr.bin";
+			};
+		};
+	};
+
+	itb {
+		filename = "u-boot.itb";
+
+		fit {
+			description = "Configuration to load ATF before U-Boot";
+			#address-cells = <1>;
+			fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
+
+			images {
+				uboot {
+					description = "U-Boot (64-bit)";
+					type = "standalone";
+					arch = "arm64";
+					compression = "none";
+					load = <CONFIG_SYS_TEXT_BASE>;
+
+					uboot_blob: blob-ext {
+						filename = "u-boot-nodtb.bin";
+					};
+				};
+
+				atf {
+					description = "ARM Trusted Firmware";
+					type = "firmware";
+					arch = "arm64";
+					compression = "none";
+					load = <0x960000>;
+					entry = <0x960000>;
+
+					atf_blob: blob-ext {
+						filename = "bl31.bin";
+					};
+				};
+
+				fdt {
+					description = "NAME";
+					type = "flat_dt";
+					compression = "none";
+
+					uboot_fdt_blob: blob-ext {
+						filename = "u-boot.dtb";
+					};
+				};
+			};
+
+			configurations {
+				default = "conf";
+
+				conf {
+					description = "NAME";
+					firmware = "uboot";
+					loadables = "atf";
+					fdt = "fdt";
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/imx8mn-evk-u-boot.dtsi b/arch/arm/dts/imx8mn-evk-u-boot.dtsi
new file mode 100644
index 0000000..3db46d4
--- /dev/null
+++ b/arch/arm/dts/imx8mn-evk-u-boot.dtsi
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#include "imx8mn-ddr4-evk-u-boot.dtsi"
+
+&i2c1 {
+	u-boot,dm-spl;
+};
+
+&{/soc@0/bus@30800000/i2c@30a20000/pca9450@25} {
+	u-boot,dm-spl;
+};
+
+&{/soc@0/bus@30800000/i2c@30a20000/pca9450@25/regulators} {
+	u-boot,dm-spl;
+};
+
+&pinctrl_i2c1 {
+	u-boot,dm-spl;
+};
+
+&pinctrl_pmic {
+	u-boot,dm-spl;
+};
+
+&binman {
+	 u-boot-spl-ddr {
+		filename = "u-boot-spl-ddr.bin";
+		pad-byte = <0xff>;
+		align-size = <4>;
+		align = <4>;
+
+		u-boot-spl {
+			align-end = <4>;
+		};
+
+		blob_1: blob-ext@1 {
+			filename = "lpddr4_pmu_train_1d_imem.bin";
+			size = <0x8000>;
+		};
+
+		blob_2: blob-ext@2 {
+			filename = "lpddr4_pmu_train_1d_dmem.bin";
+			size = <0x4000>;
+		};
+
+		blob_3: blob-ext@3 {
+			filename = "lpddr4_pmu_train_2d_imem.bin";
+			size = <0x8000>;
+		};
+
+		blob_4: blob-ext@4 {
+			filename = "lpddr4_pmu_train_2d_dmem.bin";
+			size = <0x4000>;
+		};
+	};
+
+
+	flash {
+		mkimage {
+			args = "-n spl/u-boot-spl.cfgout -T imx8mimage -e 0x912000";
+
+			blob {
+				filename = "u-boot-spl-ddr.bin";
+			};
+		};
+	};
+
+	itb {
+		filename = "u-boot.itb";
+
+		fit {
+			description = "Configuration to load ATF before U-Boot";
+			#address-cells = <1>;
+			fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
+
+			images {
+				uboot {
+					description = "U-Boot (64-bit)";
+					type = "standalone";
+					arch = "arm64";
+					compression = "none";
+					load = <CONFIG_SYS_TEXT_BASE>;
+
+					uboot_blob: blob-ext {
+						filename = "u-boot-nodtb.bin";
+					};
+				};
+
+				atf {
+					description = "ARM Trusted Firmware";
+					type = "firmware";
+					arch = "arm64";
+					compression = "none";
+					load = <0x960000>;
+					entry = <0x960000>;
+
+					atf_blob: blob-ext {
+						filename = "bl31.bin";
+					};
+				};
+
+				fdt {
+					description = "NAME";
+					type = "flat_dt";
+					compression = "none";
+
+					uboot_fdt_blob: blob-ext {
+						filename = "u-boot.dtb";
+					};
+				};
+			};
+
+			configurations {
+				default = "conf";
+
+				conf {
+					description = "NAME";
+					firmware = "uboot";
+					loadables = "atf";
+					fdt = "fdt";
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/imx8mn-evk.dts b/arch/arm/dts/imx8mn-evk.dts
new file mode 100644
index 0000000..cd11fb2
--- /dev/null
+++ b/arch/arm/dts/imx8mn-evk.dts
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2019 NXP
+ */
+
+/dts-v1/;
+
+#include "imx8mn.dtsi"
+#include "imx8mn-evk.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	model = "NXP i.MX8MNano EVK board";
+	compatible = "fsl,imx8mn-evk", "fsl,imx8mn";
+};
+
+&A53_0 {
+	cpu-supply = <&buck2>;
+};
+
+&A53_1 {
+	cpu-supply = <&buck2>;
+};
+
+&A53_2 {
+	cpu-supply = <&buck2>;
+};
+
+&A53_3 {
+	cpu-supply = <&buck2>;
+};
+
+&i2c1 {
+	pmic: pca9450@25 {
+		compatible = "nxp,pca9450b";
+		reg = <0x25>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pmic>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+
+		regulators {
+			buck1: BUCK1{
+				regulator-name = "BUCK1";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <2187500>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <3125>;
+			};
+
+			buck2: BUCK2 {
+				regulator-name = "BUCK2";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <2187500>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <3125>;
+				nxp,dvs-run-voltage = <950000>;
+				nxp,dvs-standby-voltage = <850000>;
+			};
+
+			buck4: BUCK4{
+				regulator-name = "BUCK4";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <3400000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck5: BUCK5{
+				regulator-name = "BUCK5";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <3400000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck6: BUCK6 {
+				regulator-name = "BUCK6";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <3400000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo1: LDO1 {
+				regulator-name = "LDO1";
+				regulator-min-microvolt = <1600000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo2: LDO2 {
+				regulator-name = "LDO2";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1150000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo3: LDO3 {
+				regulator-name = "LDO3";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo4: LDO4 {
+				regulator-name = "LDO4";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo5: LDO5 {
+				regulator-name = "LDO5";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/imx8mn.dtsi b/arch/arm/dts/imx8mn.dtsi
index ee17902..16ea500 100644
--- a/arch/arm/dts/imx8mn.dtsi
+++ b/arch/arm/dts/imx8mn.dtsi
@@ -241,10 +241,12 @@
 	};
 
 	soc@0 {
-		compatible = "simple-bus";
+		compatible = "fsl,imx8mn-soc", "simple-bus";
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges = <0x0 0x0 0x0 0x3e000000>;
+		nvmem-cells = <&imx8mn_uid>;
+		nvmem-cell-names = "soc_unique_id";
 
 		aips1: bus@30000000 {
 			compatible = "fsl,aips-bus", "simple-bus";
@@ -253,7 +255,7 @@
 			#size-cells = <1>;
 			ranges;
 
-			spba: bus@30000000 {
+			spba: spba-bus@30000000 {
 				compatible = "fsl,spba-bus", "simple-bus";
 				#address-cells = <1>;
 				#size-cells = <1>;
@@ -531,9 +533,17 @@
 				#address-cells = <1>;
 				#size-cells = <1>;
 
+				imx8mn_uid: unique-id@410 {
+					reg = <0x4 0x8>;
+				};
+
 				cpu_speed_grade: speed-grade@10 {
 					reg = <0x10 4>;
 				};
+
+				fec_mac_address: mac-address@90 {
+					reg = <0x90 6>;
+				};
 			};
 
 			anatop: anatop@30360000 {
@@ -581,7 +591,9 @@
 						<&clk IMX8MN_CLK_NOC>,
 						<&clk IMX8MN_CLK_AUDIO_AHB>,
 						<&clk IMX8MN_CLK_IPG_AUDIO_ROOT>,
-						<&clk IMX8MN_SYS_PLL3>;
+						<&clk IMX8MN_SYS_PLL3>,
+						<&clk IMX8MN_AUDIO_PLL1>,
+						<&clk IMX8MN_AUDIO_PLL2>;
 				assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_800M>,
 							 <&clk IMX8MN_ARM_PLL_OUT>,
 							 <&clk IMX8MN_SYS_PLL3_OUT>,
@@ -589,7 +601,9 @@
 				assigned-clock-rates = <0>, <0>, <0>,
 							<400000000>,
 							<400000000>,
-							<600000000>;
+							<600000000>,
+							<393216000>,
+							<361267200>;
 			};
 
 			src: reset-controller@30390000 {
@@ -875,6 +889,19 @@
 				status = "disabled";
 			};
 
+			flexspi: spi@30bb0000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "nxp,imx8mm-fspi";
+				reg = <0x30bb0000 0x10000>, <0x8000000 0x10000000>;
+				reg-names = "fspi_base", "fspi_mmap";
+				interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clk IMX8MN_CLK_QSPI_ROOT>,
+					 <&clk IMX8MN_CLK_QSPI_ROOT>;
+				clock-names = "fspi", "fspi_en";
+				status = "disabled";
+			};
+
 			sdma1: dma-controller@30bd0000 {
 				compatible = "fsl,imx8mn-sdma", "fsl,imx8mq-sdma";
 				reg = <0x30bd0000 0x10000>;
@@ -903,13 +930,18 @@
 				assigned-clocks = <&clk IMX8MN_CLK_ENET_AXI>,
 						  <&clk IMX8MN_CLK_ENET_TIMER>,
 						  <&clk IMX8MN_CLK_ENET_REF>,
-						  <&clk IMX8MN_CLK_ENET_TIMER>;
+						  <&clk IMX8MN_CLK_ENET_PHY_REF>;
 				assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_266M>,
 							 <&clk IMX8MN_SYS_PLL2_100M>,
-							 <&clk IMX8MN_SYS_PLL2_125M>;
-				assigned-clock-rates = <0>, <0>, <125000000>, <100000000>;
+							 <&clk IMX8MN_SYS_PLL2_125M>,
+							 <&clk IMX8MN_SYS_PLL2_50M>;
+				assigned-clock-rates = <0>, <100000000>, <125000000>, <0>;
 				fsl,num-tx-queues = <3>;
 				fsl,num-rx-queues = <3>;
+				nvmem-cells = <&fec_mac_address>;
+				nvmem-cell-names = "mac-address";
+				nvmem_macaddr_swap;
+				fsl,stop-mode = <&gpr 0x10 3>;
 				status = "disabled";
 			};
 
diff --git a/arch/arm/dts/imx8mp-evk-u-boot.dtsi b/arch/arm/dts/imx8mp-evk-u-boot.dtsi
index 6a91404..4162f41 100644
--- a/arch/arm/dts/imx8mp-evk-u-boot.dtsi
+++ b/arch/arm/dts/imx8mp-evk-u-boot.dtsi
@@ -4,11 +4,21 @@
  */
 
 / {
+	binman: binman {
+		multiple-images;
+	};
+
 	wdt-reboot {
 		compatible = "wdt-reboot";
 		wdt = <&wdog1>;
 		u-boot,dm-spl;
 	};
+	firmware {
+		optee {
+			compatible = "linaro,optee-tz";
+			method = "smc";
+		};
+	};
 };
 
 &{/soc@0} {
@@ -145,3 +155,105 @@
 	phy-reset-duration = <15>;
 	phy-reset-post-delay = <100>;
 };
+
+&binman {
+	 u-boot-spl-ddr {
+		filename = "u-boot-spl-ddr.bin";
+		pad-byte = <0xff>;
+		align-size = <4>;
+		align = <4>;
+
+		u-boot-spl {
+			align-end = <4>;
+		};
+
+		blob_1: blob-ext@1 {
+			filename = "lpddr4_pmu_train_1d_imem_202006.bin";
+			size = <0x8000>;
+		};
+
+		blob_2: blob-ext@2 {
+			filename = "lpddr4_pmu_train_1d_dmem_202006.bin";
+			size = <0x4000>;
+		};
+
+		blob_3: blob-ext@3 {
+			filename = "lpddr4_pmu_train_2d_imem_202006.bin";
+			size = <0x8000>;
+		};
+
+		blob_4: blob-ext@4 {
+			filename = "lpddr4_pmu_train_2d_dmem_202006.bin";
+			size = <0x4000>;
+		};
+	};
+
+
+       flash {
+		mkimage {
+			args = "-n spl/u-boot-spl.cfgout -T imx8mimage -e 0x920000";
+
+			blob {
+				filename = "u-boot-spl-ddr.bin";
+			};
+		};
+	};
+
+	itb {
+		filename = "u-boot.itb";
+
+		fit {
+			description = "Configuration to load ATF before U-Boot";
+			#address-cells = <1>;
+			fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
+
+			images {
+				uboot {
+					description = "U-Boot (64-bit)";
+					type = "standalone";
+					arch = "arm64";
+					compression = "none";
+					load = <CONFIG_SYS_TEXT_BASE>;
+
+					uboot_blob: blob-ext {
+						filename = "u-boot-nodtb.bin";
+					};
+				};
+
+				atf {
+					description = "ARM Trusted Firmware";
+					type = "firmware";
+					arch = "arm64";
+					compression = "none";
+					load = <0x970000>;
+					entry = <0x970000>;
+
+					atf_blob: blob-ext {
+						filename = "bl31.bin";
+					};
+				};
+
+				fdt {
+					description = "NAME";
+					type = "flat_dt";
+					compression = "none";
+
+					uboot_fdt_blob: blob-ext {
+						filename = "u-boot.dtb";
+					};
+				};
+			};
+
+			configurations {
+				default = "conf";
+
+				conf {
+					description = "NAME";
+					firmware = "uboot";
+					loadables = "atf";
+					fdt = "fdt";
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/mt7629-rfb-u-boot.dtsi b/arch/arm/dts/mt7629-rfb-u-boot.dtsi
index 164afd6..c17e82a 100644
--- a/arch/arm/dts/mt7629-rfb-u-boot.dtsi
+++ b/arch/arm/dts/mt7629-rfb-u-boot.dtsi
@@ -5,24 +5,6 @@
  * Author: Weijie Gao <weijie.gao@mediatek.com>
  */
 
-#include <config.h>
-/ {
-	binman {
-		filename = "u-boot-mtk.bin";
-		pad-byte = <0xff>;
-
-#ifdef CONFIG_SPL
-		blob {
-			filename = "spl/u-boot-spl-mtk.bin";
-			size = <CONFIG_SPL_PAD_TO>;
-		};
-
-		u-boot-img {
-		};
-#endif
-	};
-};
-
 &infracfg {
 	u-boot,dm-pre-reloc;
 };
diff --git a/arch/arm/dts/mt7629-rfb.dts b/arch/arm/dts/mt7629-rfb.dts
index df43cc4..f2e4e95 100644
--- a/arch/arm/dts/mt7629-rfb.dts
+++ b/arch/arm/dts/mt7629-rfb.dts
@@ -36,6 +36,16 @@
 };
 
 &pinctrl {
+	state_default: pinmux_conf {
+		u-boot,dm-pre-reloc;
+
+		mux {
+			function = "jtag";
+			groups = "ephy_leds_jtag";
+			u-boot,dm-pre-reloc;
+		};
+	};
+
 	snfi_pins: snfi-pins {
 		mux {
 			function = "flash";
diff --git a/arch/arm/dts/mt7629.dtsi b/arch/arm/dts/mt7629.dtsi
index 0539426..7dea780 100644
--- a/arch/arm/dts/mt7629.dtsi
+++ b/arch/arm/dts/mt7629.dtsi
@@ -152,6 +152,12 @@
 		compatible = "mediatek,mt7629-pinctrl";
 		reg = <0x10217000 0x8000>;
 
+		pinctrl-names = "default";
+		pinctrl-0 = <&state_default>;
+
+		state_default: pinmux_conf {
+		};
+
 		gpio: gpio-controller {
 			gpio-controller;
 			#gpio-cells = <2>;
diff --git a/arch/arm/dts/mt8183-pumpkin.dts b/arch/arm/dts/mt8183-pumpkin.dts
new file mode 100644
index 0000000..470a769
--- /dev/null
+++ b/arch/arm/dts/mt8183-pumpkin.dts
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2021 BayLibre SAS.
+ * Author: Fabien Parent <fparent@baylibre.com>
+ */
+
+/dts-v1/;
+
+#include <config.h>
+#include "mt8183.dtsi"
+
+/ {
+	model = "MediaTek MT8183 pumpkin board";
+	compatible = "mediatek,mt8183-pumpkin", "mediatek,mt8183";
+
+	memory@40000000 {
+		device_type = "memory";
+		reg = <0 0x40000000 0 0x80000000>;
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		/* 192 KiB reserved for ARM Trusted Firmware (BL31) */
+		bl31_secmon_reserved: secmon@54600000 {
+			no-map;
+			reg = <0 0x54600000 0x0 0x30000>;
+		};
+
+		/* 12 MiB reserved for OP-TEE (BL32)
+		 * +-----------------------+ 0x43e0_0000
+		 * |      SHMEM 2MiB       |
+		 * +-----------------------+ 0x43c0_0000
+		 * |        | TA_RAM  8MiB |
+		 * + TZDRAM +--------------+ 0x4340_0000
+		 * |        | TEE_RAM 2MiB |
+		 * +-----------------------+ 0x4320_0000
+		 */
+		optee_reserved: optee@43200000 {
+			no-map;
+			reg = <0 0x43200000 0 0x00c00000>;
+		};
+	};
+
+	chosen {
+		stdout-path = &uart0;
+	};
+
+	reg_1p8v: regulator-1p8v {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-1.8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+};
+
+&watchdog {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&mmc0 {
+	bus-width = <4>;
+	max-frequency = <200000000>;
+	cap-mmc-highspeed;
+	mmc-hs200-1_8v;
+	cap-mmc-hw-reset;
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&reg_1p8v>;
+	non-removable;
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+};
+
+&ssusb {
+	mediatek,force-vbus;
+	maximum-speed = "high-speed";
+	dr_mode = "peripheral";
+	status = "okay";
+};
diff --git a/arch/arm/dts/mt8183.dtsi b/arch/arm/dts/mt8183.dtsi
new file mode 100644
index 0000000..294aa2b
--- /dev/null
+++ b/arch/arm/dts/mt8183.dtsi
@@ -0,0 +1,274 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Copyright (C) 2021 BayLibre, SAS
+ * Author: Ben Ho <ben.ho@mediatek.com>
+ *         Erin Lo <erin.lo@mediatek.com>
+ *         Fabien Parent <fparent@baylibre.com>
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/mt8183-clk.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/phy/phy.h>
+
+/ {
+	compatible = "mediatek,mt8183";
+	interrupt-parent = <&sysirq>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&cpu0>;
+				};
+				core1 {
+					cpu = <&cpu1>;
+				};
+				core2 {
+					cpu = <&cpu2>;
+				};
+				core3 {
+					cpu = <&cpu3>;
+				};
+			};
+
+			cluster1 {
+				core0 {
+					cpu = <&cpu4>;
+				};
+				core1 {
+					cpu = <&cpu5>;
+				};
+				core2 {
+					cpu = <&cpu6>;
+				};
+				core3 {
+					cpu = <&cpu7>;
+				};
+			};
+		};
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x000>;
+			enable-method = "psci";
+			capacity-dmips-mhz = <741>;
+		};
+
+		cpu1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x001>;
+			enable-method = "psci";
+			capacity-dmips-mhz = <741>;
+		};
+
+		cpu2: cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x002>;
+			enable-method = "psci";
+			capacity-dmips-mhz = <741>;
+		};
+
+		cpu3: cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x003>;
+			enable-method = "psci";
+			capacity-dmips-mhz = <741>;
+		};
+
+		cpu4: cpu@100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a73";
+			reg = <0x100>;
+			enable-method = "psci";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu5: cpu@101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a73";
+			reg = <0x101>;
+			enable-method = "psci";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu6: cpu@102 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a73";
+			reg = <0x102>;
+			enable-method = "psci";
+			capacity-dmips-mhz = <1024>;
+		};
+
+		cpu7: cpu@103 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a73";
+			reg = <0x103>;
+			enable-method = "psci";
+			capacity-dmips-mhz = <1024>;
+		};
+	};
+
+	clk26m: oscillator {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+		clock-output-names = "clk26m";
+	};
+
+	soc {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		compatible = "simple-bus";
+		ranges;
+
+		watchdog: watchdog@10007000 {
+			compatible = "mediatek,mt8183-wdt",
+				      "mediatek,wdt";
+			reg = <0 0x10007000 0 0x100>;
+			status = "disabled";
+		};
+
+		gic: interrupt-controller@c000000 {
+			compatible = "arm,gic-v3";
+			#interrupt-cells = <4>;
+			interrupt-parent = <&gic>;
+			interrupt-controller;
+			reg = <0 0x0c000000 0 0x40000>,  /* GICD */
+			      <0 0x0c100000 0 0x200000>, /* GICR */
+			      <0 0x0c400000 0 0x2000>,   /* GICC */
+			      <0 0x0c410000 0 0x1000>,   /* GICH */
+			      <0 0x0c420000 0 0x2000>;   /* GICV */
+
+			interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH 0>;
+			ppi-partitions {
+				ppi_cluster0: interrupt-partition-0 {
+					affinity = <&cpu0 &cpu1 &cpu2 &cpu3>;
+				};
+				ppi_cluster1: interrupt-partition-1 {
+					affinity = <&cpu4 &cpu5 &cpu6 &cpu7>;
+				};
+			};
+		};
+
+		sysirq: interrupt-controller@c530a80 {
+			compatible = "mediatek,mt8183-sysirq",
+				     "mediatek,mt6577-sysirq";
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			interrupt-parent = <&gic>;
+			reg = <0 0x0c530a80 0 0x50>;
+		};
+
+		topckgen: syscon@10000000 {
+			compatible = "mediatek,mt8183-topckgen", "syscon";
+			reg = <0 0x10000000 0 0x1000>;
+			#clock-cells = <1>;
+		};
+
+		infracfg: syscon@10001000 {
+			compatible = "mediatek,mt8183-infracfg", "syscon";
+			reg = <0 0x10001000 0 0x1000>;
+			#clock-cells = <1>;
+		};
+
+		apmixedsys: syscon@1000c000 {
+			compatible = "mediatek,mt8183-apmixedsys", "syscon";
+			reg = <0 0x1000c000 0 0x1000>;
+			#clock-cells = <1>;
+		};
+
+		uart0: serial@11002000 {
+			compatible = "mediatek,mt8183-uart",
+				     "mediatek,hsuart";
+			reg = <0 0x11002000 0 0x1000>;
+			interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>;
+			clock-frequency = <26000000>;
+			clocks = <&clk26m>, <&infracfg CLK_INFRA_UART0>;
+			clock-names = "baud", "bus";
+			status = "disabled";
+		};
+
+		mmc0: mmc@11230000 {
+			compatible = "mediatek,mt8183-mmc";
+			reg = <0 0x11230000 0 0x1000>,
+			      <0 0x11f50000 0 0x1000>;
+			interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_LOW>;
+			clocks = <&topckgen CLK_TOP_MUX_MSDC50_0>,
+				 <&infracfg CLK_INFRA_MSDC0>,
+				 <&infracfg CLK_INFRA_MSDC0_SCK>;
+			clock-names = "source", "hclk", "source_cg";
+			status = "disabled";
+		};
+
+		u3phy: usb-phy@11f40000 {
+			compatible = "mediatek,generic-tphy-v2";
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges;
+			status = "okay";
+
+			u2port0: usb-phy2@11f40000 {
+				reg = <0 0x11f40000 0 0x700>;
+				clocks = <&clk26m>;
+				clock-names = "ref";
+				#phy-cells = <1>;
+				status = "okay";
+			};
+
+			u3port0: usb-phy3@11f40700 {
+				reg = <0 0x11f40700 0 0x900>;
+				clocks = <&clk26m>;
+				clock-names = "ref";
+				#phy-cells = <1>;
+				status = "okay";
+			};
+		};
+
+		usb: usb@11200000 {
+			compatible ="mediatek,mt8183-mtu3", "mediatek,mtu3";
+			reg = <0 0x11200000 0 0x3e00>,
+			      <0 0x11203e00 0 0x0100>;
+			reg-names = "mac", "ippc";
+			interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_LOW>;
+			phys = <&u2port0 PHY_TYPE_USB2>;
+			clocks = <&infracfg CLK_INFRA_UNIPRO_SCK>,
+				 <&infracfg CLK_INFRA_USB>;
+			clock-names = "sys_ck", "ref_ck";
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges;
+			status = "disabled";
+
+			ssusb: ssusb@11200000 {
+				compatible = "mediatek,ssusb";
+				reg = <0 0x11200000 0 0x3e00>;
+				reg-names = "mac";
+				interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_LOW>;
+				status = "disabled";
+			};
+
+			usb_host: xhci@11200000 {
+				compatible = "mediatek,mtk-xhci";
+				reg = <0 0x11200000 0 0x1000>;
+				reg-names = "mac";
+				interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_LOW>;
+				clocks = <&infracfg CLK_INFRA_UNIPRO_SCK>,
+					 <&infracfg CLK_INFRA_USB>;
+				clock-names = "sys_ck", "ref_ck";
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/r8a774b1-hihope-rzg2n-ex.dts b/arch/arm/dts/r8a774b1-hihope-rzg2n-ex.dts
new file mode 100644
index 0000000..60d7c8a
--- /dev/null
+++ b/arch/arm/dts/r8a774b1-hihope-rzg2n-ex.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the HiHope RZ/G2N Rev.3.0/4.0 connected to
+ * sub board
+ *
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ */
+
+#include "r8a774b1-hihope-rzg2n.dts"
+#include "hihope-rzg2-ex.dtsi"
+
+/ {
+	model = "HopeRun HiHope RZ/G2N with sub board";
+	compatible = "hoperun,hihope-rzg2-ex", "hoperun,hihope-rzg2n",
+		     "renesas,r8a774b1";
+};
+
+/* Set SW43 = ON and SW1001[7] = OFF for SATA port to be activated */
+&sata {
+	status = "okay";
+};
diff --git a/arch/arm/dts/r8a774b1-hihope-rzg2n-u-boot.dts b/arch/arm/dts/r8a774b1-hihope-rzg2n-u-boot.dts
new file mode 100644
index 0000000..0bdc690
--- /dev/null
+++ b/arch/arm/dts/r8a774b1-hihope-rzg2n-u-boot.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source extras for U-Boot for the Hihope RZ/G2N board
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+#include "r8a774b1-hihope-rzg2n-ex.dts"
+#include "r8a774b1-u-boot.dtsi"
+
+&gpio3 {
+	bt_reg_on{
+		gpio-hog;
+		gpios = <13 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "bt-reg-on";
+	};
+};
+
+&gpio4 {
+	wlan_reg_on{
+		gpio-hog;
+		gpios = <6 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "wlan-reg-on";
+	};
+};
diff --git a/arch/arm/dts/r8a774b1-hihope-rzg2n.dts b/arch/arm/dts/r8a774b1-hihope-rzg2n.dts
new file mode 100644
index 0000000..f1883cb
--- /dev/null
+++ b/arch/arm/dts/r8a774b1-hihope-rzg2n.dts
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the HiHope RZ/G2N main board Rev.3.0/4.0
+ *
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ */
+
+/dts-v1/;
+#include "r8a774b1.dtsi"
+#include "hihope-rev4.dtsi"
+
+/ {
+	model = "HopeRun HiHope RZ/G2N main board based on r8a774b1";
+	compatible = "hoperun,hihope-rzg2n", "renesas,r8a774b1";
+
+	memory@48000000 {
+		device_type = "memory";
+		/* first 128MB is reserved for secure area. */
+		reg = <0x0 0x48000000 0x0 0x78000000>;
+	};
+
+	memory@480000000 {
+		device_type = "memory";
+		reg = <0x4 0x80000000 0x0 0x80000000>;
+	};
+};
+
+&du {
+	clocks = <&cpg CPG_MOD 724>,
+		 <&cpg CPG_MOD 723>,
+		 <&cpg CPG_MOD 721>,
+		 <&versaclock5 1>,
+		 <&x302_clk>,
+		 <&versaclock5 2>;
+	clock-names = "du.0", "du.1", "du.3",
+		      "dclkin.0", "dclkin.1", "dclkin.3";
+};
+
+&sdhi3 {
+	mmc-hs400-1_8v;
+};
diff --git a/arch/arm/dts/r8a774b1-u-boot.dtsi b/arch/arm/dts/r8a774b1-u-boot.dtsi
new file mode 100644
index 0000000..6fab78e
--- /dev/null
+++ b/arch/arm/dts/r8a774b1-u-boot.dtsi
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source extras for U-Boot on RZ/G2 R8A774B1 SoC
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+#include "r8a779x-u-boot.dtsi"
+
+&extalr_clk {
+	u-boot,dm-pre-reloc;
+};
+
+/delete-node/ &audma0;
+/delete-node/ &audma1;
+/delete-node/ &can0;
+/delete-node/ &can1;
+/delete-node/ &canfd;
+/delete-node/ &csi20;
+/delete-node/ &csi40;
+/delete-node/ &du;
+/delete-node/ &fcpf0;
+/delete-node/ &fcpvb0;
+/delete-node/ &fcpvd0;
+/delete-node/ &fcpvd1;
+/delete-node/ &fcpvi0;
+/delete-node/ &hdmi0;
+/delete-node/ &lvds0;
+/delete-node/ &rcar_sound;
+/delete-node/ &sdhi2;
+/delete-node/ &sound_card;
+/delete-node/ &vin0;
+/delete-node/ &vin1;
+/delete-node/ &vin2;
+/delete-node/ &vin3;
+/delete-node/ &vin4;
+/delete-node/ &vin5;
+/delete-node/ &vin6;
+/delete-node/ &vin7;
+/delete-node/ &vspb;
+/delete-node/ &vspd0;
+/delete-node/ &vspd1;
+/delete-node/ &vspi0;
+
+/ {
+	/delete-node/ hdmi0-out;
+};
+
+/ {
+	soc {
+		/delete-node/ fdp1@fe940000;
+	};
+};
diff --git a/arch/arm/dts/r8a774c0-cat874.dts b/arch/arm/dts/r8a774c0-cat874.dts
new file mode 100644
index 0000000..676fdef
--- /dev/null
+++ b/arch/arm/dts/r8a774c0-cat874.dts
@@ -0,0 +1,453 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the Silicon Linux RZ/G2E 96board platform (CAT874)
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+/dts-v1/;
+#include "r8a774c0.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/display/tda998x.h>
+
+/ {
+	model = "Silicon Linux RZ/G2E 96board platform (CAT874)";
+	compatible = "si-linux,cat874", "renesas,r8a774c0";
+
+	aliases {
+		serial0 = &scif2;
+		serial1 = &hscif2;
+	};
+
+	chosen {
+		bootargs = "ignore_loglevel rw root=/dev/nfs ip=on";
+		stdout-path = "serial0:115200n8";
+	};
+
+	hdmi-out {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_con_out: endpoint {
+				remote-endpoint = <&tda19988_out>;
+			};
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led0 {
+			gpios = <&gpio5 19 GPIO_ACTIVE_HIGH>;
+			label = "LED0";
+		};
+
+		led1 {
+			gpios = <&gpio3 14 GPIO_ACTIVE_HIGH>;
+			label = "LED1";
+		};
+
+		led2 {
+			gpios = <&gpio4 10 GPIO_ACTIVE_HIGH>;
+			label = "LED2";
+		};
+
+		led3 {
+			gpios = <&gpio6 4 GPIO_ACTIVE_HIGH>;
+			label = "LED3";
+		};
+	};
+
+	memory@48000000 {
+		device_type = "memory";
+		/* first 128MB is reserved for secure area. */
+		reg = <0x0 0x48000000 0x0 0x78000000>;
+	};
+
+	reg_12p0v: regulator-12p0v {
+		compatible = "regulator-fixed";
+		regulator-name = "D12.0V";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	sound: sound {
+		compatible = "simple-audio-card";
+
+		simple-audio-card,name = "CAT874 HDMI sound";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&sndcpu>;
+		simple-audio-card,frame-master = <&sndcpu>;
+
+		sndcodec: simple-audio-card,codec {
+			sound-dai = <&tda19988>;
+		};
+
+		sndcpu: simple-audio-card,cpu {
+			sound-dai = <&rcar_sound>;
+		};
+	};
+
+	vcc_sdhi0: regulator-vcc-sdhi0 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "SDHI0 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vccq_sdhi0: regulator-vccq-sdhi0 {
+		compatible = "regulator-gpio";
+
+		regulator-name = "SDHI0 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <3300000 1>, <1800000 0>;
+	};
+
+	wlan_en_reg: fixedregulator {
+		compatible = "regulator-fixed";
+		regulator-name = "wlan-en-regulator";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		startup-delay-us = <70000>;
+
+		gpio = <&gpio2 25 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	x13_clk: x13 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <74250000>;
+	};
+
+	connector {
+		compatible = "usb-c-connector";
+		label = "USB-C";
+		data-role = "dual";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+				hs_ep: endpoint {
+					remote-endpoint = <&usb3_hs_ep>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+				ss_ep: endpoint {
+					remote-endpoint = <&hd3ss3220_in_ep>;
+				};
+			};
+		};
+	};
+};
+
+&audio_clk_a {
+	clock-frequency = <22579200>;
+};
+
+&du {
+	pinctrl-0 = <&du_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	clocks = <&cpg CPG_MOD 724>,
+		 <&cpg CPG_MOD 723>,
+		 <&x13_clk>;
+	clock-names = "du.0", "du.1", "dclkin.0";
+
+	ports {
+		port@0 {
+			endpoint {
+				remote-endpoint = <&tda19988_in>;
+			};
+		};
+	};
+};
+
+&ehci0 {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&extal_clk {
+	clock-frequency = <48000000>;
+};
+
+&hscif2 {
+	pinctrl-0 = <&hscif2_pins>;
+	pinctrl-names = "default";
+
+	uart-has-rtscts;
+	status = "okay";
+
+	bluetooth {
+		compatible = "ti,wl1837-st";
+		enable-gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+	clock-frequency = <100000>;
+
+	hd3ss3220@47 {
+		compatible = "ti,hd3ss3220";
+		reg = <0x47>;
+		interrupt-parent = <&gpio6>;
+		interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+				hd3ss3220_in_ep: endpoint {
+					remote-endpoint = <&ss_ep>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+				hd3ss3220_out_ep: endpoint {
+					remote-endpoint = <&usb3_role_switch>;
+				};
+			};
+		};
+	};
+
+	tda19988: tda19988@70 {
+		compatible = "nxp,tda998x";
+		reg = <0x70>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+
+		video-ports = <0x234501>;
+
+		#sound-dai-cells = <0>;
+		audio-ports = <TDA998x_I2S 0x03>;
+		clocks = <&rcar_sound 1>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				tda19988_in: endpoint {
+					remote-endpoint = <&du_out_rgb>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				tda19988_out: endpoint {
+					remote-endpoint = <&hdmi_con_out>;
+				};
+			};
+		};
+	};
+};
+
+&i2c1 {
+	pinctrl-0 = <&i2c1_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+	clock-frequency = <400000>;
+
+	rtc@32 {
+		compatible = "epson,rx8571";
+		reg = <0x32>;
+	};
+};
+
+&lvds0 {
+	status = "okay";
+
+	clocks = <&cpg CPG_MOD 727>, <&x13_clk>, <&extal_clk>;
+	clock-names = "fck", "dclkin.0", "extal";
+};
+
+&ohci0 {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&pcie_bus_clk {
+	clock-frequency = <100000000>;
+};
+
+&pciec0 {
+	/* Map all possible DDR as inbound ranges */
+	dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>;
+};
+
+&pfc {
+	du_pins: du {
+		groups = "du_rgb888", "du_clk_out_0", "du_sync", "du_disp",
+			 "du_clk_in_0";
+		function = "du";
+	};
+
+	hscif2_pins: hscif2 {
+		groups = "hscif2_data_a", "hscif2_ctrl_a";
+		function = "hscif2";
+	};
+
+	i2c1_pins: i2c1 {
+		groups = "i2c1_b";
+		function = "i2c1";
+	};
+
+	scif2_pins: scif2 {
+		groups = "scif2_data_a";
+		function = "scif2";
+	};
+
+	sdhi0_pins: sd0 {
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
+		power-source = <3300>;
+	};
+
+	sdhi0_pins_uhs: sd0_uhs {
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
+		power-source = <1800>;
+	};
+
+	sdhi3_pins: sd3 {
+		groups = "sdhi3_data4", "sdhi3_ctrl";
+		function = "sdhi3";
+		power-source = <1800>;
+	};
+
+	sound_clk_pins: sound_clk {
+		groups = "audio_clkout1_a";
+		function = "audio_clk";
+	};
+
+	sound_pins: sound {
+		groups = "ssi01239_ctrl", "ssi0_data";
+		function = "ssi";
+	};
+
+	usb30_pins: usb30 {
+		groups = "usb30", "usb30_id";
+		function = "usb30";
+	};
+};
+
+&rcar_sound {
+	pinctrl-0 = <&sound_pins &sound_clk_pins>;
+	pinctrl-names = "default";
+
+	/* Single DAI */
+	#sound-dai-cells = <0>;
+
+	/* audio_clkout0/1/2/3 */
+	#clock-cells = <1>;
+	clock-frequency = <11289600>;
+
+	status = "okay";
+
+	rcar_sound,dai {
+		dai0 {
+			playback = <&ssi0 &src0 &dvc0>;
+		};
+	};
+};
+
+&rwdt {
+	timeout-sec = <60>;
+	status = "okay";
+};
+
+&scif2 {
+	pinctrl-0 = <&scif2_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
+
+&sdhi0 {
+	pinctrl-0 = <&sdhi0_pins>;
+	pinctrl-1 = <&sdhi0_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
+
+	vmmc-supply = <&vcc_sdhi0>;
+	vqmmc-supply = <&vccq_sdhi0>;
+	cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
+	bus-width = <4>;
+	sd-uhs-sdr50;
+	sd-uhs-sdr104;
+	status = "okay";
+};
+
+&sdhi3 {
+	status = "okay";
+	pinctrl-0 = <&sdhi3_pins>;
+	pinctrl-names = "default";
+
+	vmmc-supply = <&wlan_en_reg>;
+	bus-width = <4>;
+	non-removable;
+	cap-power-off-card;
+	keep-power-in-suspend;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	wlcore: wlcore@2 {
+		compatible = "ti,wl1837";
+		reg = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+	};
+};
+
+&usb2_phy0 {
+	renesas,no-otg-pins;
+	status = "okay";
+};
+
+&usb3_peri0 {
+	companion = <&xhci0>;
+	status = "okay";
+	usb-role-switch;
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		port@0 {
+			reg = <0>;
+			usb3_hs_ep: endpoint {
+				remote-endpoint = <&hs_ep>;
+			};
+		};
+		port@1 {
+			reg = <1>;
+			usb3_role_switch: endpoint {
+				remote-endpoint = <&hd3ss3220_out_ep>;
+			};
+		};
+	};
+};
+
+&xhci0 {
+	pinctrl-0 = <&usb30_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
diff --git a/arch/arm/dts/r8a774c0-ek874-u-boot.dts b/arch/arm/dts/r8a774c0-ek874-u-boot.dts
new file mode 100644
index 0000000..8fa6d80
--- /dev/null
+++ b/arch/arm/dts/r8a774c0-ek874-u-boot.dts
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source extras for U-Boot for the Hihope board
+ *
+ * Copyright (C) 2021 Renesas Electronisc Corporation
+ */
+
+#include "r8a774c0-ek874.dts"
+#include "r8a774c0-u-boot.dtsi"
+
+/ {
+	aliases {
+		spi0 = &rpc;
+	};
+};
+
+&rpc {
+	num-cs = <1>;
+	status = "okay";
+	spi-max-frequency = <50000000>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	flash0: spi-flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "w25m512jv", "spi-flash", "jedec,spi-nor";
+		spi-max-frequency = <50000000>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <1>;
+		reg = <0>;
+	};
+};
diff --git a/arch/arm/dts/r8a774c0-ek874.dts b/arch/arm/dts/r8a774c0-ek874.dts
new file mode 100644
index 0000000..d3ab28b
--- /dev/null
+++ b/arch/arm/dts/r8a774c0-ek874.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the Silicon Linux RZ/G2E evaluation kit (EK874)
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+#include "r8a774c0-cat874.dts"
+#include "cat875.dtsi"
+
+/ {
+	model = "Silicon Linux RZ/G2E evaluation kit EK874 (CAT874 + CAT875)";
+	compatible = "si-linux,cat875", "si-linux,cat874", "renesas,r8a774c0";
+};
diff --git a/arch/arm/dts/r8a774c0-u-boot.dtsi b/arch/arm/dts/r8a774c0-u-boot.dtsi
new file mode 100644
index 0000000..af1c861
--- /dev/null
+++ b/arch/arm/dts/r8a774c0-u-boot.dtsi
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source extras for U-Boot on R8A774C0 SoC
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ *
+ */
+
+#include "r8a779x-u-boot.dtsi"
+
+/ {
+	soc {
+		rpc: rpc@ee200000 {
+			compatible = "renesas,rcar-gen3-rpc", "renesas,rpc-r8a774c0";
+			reg = <0 0xee200000 0 0x100>, <0 0x08000000 0 0x04000000>;
+			clocks = <&cpg CPG_MOD 917>;
+			bank-width = <2>;
+			status = "disabled";
+		};
+	};
+};
+
+/delete-node/ &can0;
+/delete-node/ &can1;
+/delete-node/ &canfd;
+/delete-node/ &pwm0;
+/delete-node/ &pwm1;
+/delete-node/ &pwm2;
+/delete-node/ &pwm3;
+/delete-node/ &pwm4;
+/delete-node/ &pwm5;
+/delete-node/ &pwm6;
+/delete-node/ &vin4;
+/delete-node/ &vin5;
+/delete-node/ &rcar_sound;
+/delete-node/ &audma0;
+/delete-node/ &sdhi1;
+/delete-node/ &sdhi3;
+/delete-node/ &vspb0;
+/delete-node/ &vspd0;
+/delete-node/ &vspd1;
+/delete-node/ &vspi0;
+/delete-node/ &fcpvb0;
+/delete-node/ &fcpvd0;
+/delete-node/ &fcpvd1;
+/delete-node/ &fcpvi0;
+/delete-node/ &csi40;
+/delete-node/ &du;
+/delete-node/ &lvds0;
+/delete-node/ &lvds1;
+/delete-node/ &hdmi_con_out;
+/delete-node/ &sound;
+/delete-node/ &tda19988;
diff --git a/arch/arm/dts/r8a774c0.dtsi b/arch/arm/dts/r8a774c0.dtsi
index e14db4d..2bdd571 100644
--- a/arch/arm/dts/r8a774c0.dtsi
+++ b/arch/arm/dts/r8a774c0.dtsi
@@ -256,7 +256,7 @@
 			resets = <&cpg 906>;
 		};
 
-		pfc: pin-controller@e6060000 {
+		pfc: pinctrl@e6060000 {
 			compatible = "renesas,pfc-r8a774c0";
 			reg = <0 0xe6060000 0 0x508>;
 		};
@@ -960,6 +960,7 @@
 			power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
 			resets = <&cpg 812>;
 			phy-mode = "rgmii";
+			rx-internal-delay-ps = <0>;
 			iommus = <&ipmmu_ds0 16>;
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -1214,9 +1215,8 @@
 			reg = <0 0xe6ea0000 0 0x0064>;
 			interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 210>;
-			dmas = <&dmac1 0x43>, <&dmac1 0x42>,
-			       <&dmac2 0x43>, <&dmac2 0x42>;
-			dma-names = "tx", "rx", "tx", "rx";
+			dmas = <&dmac0 0x43>, <&dmac0 0x42>;
+			dma-names = "tx", "rx";
 			power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
 			resets = <&cpg 210>;
 			#address-cells = <1>;
@@ -1698,6 +1698,25 @@
 			status = "disabled";
 		};
 
+		pciec0_ep: pcie-ep@fe000000 {
+			compatible = "renesas,r8a774c0-pcie-ep",
+				     "renesas,rcar-gen3-pcie-ep";
+			reg = <0x0 0xfe000000 0 0x80000>,
+			      <0x0 0xfe100000 0 0x100000>,
+			      <0x0 0xfe200000 0 0x200000>,
+			      <0x0 0x30000000 0 0x8000000>,
+			      <0x0 0x38000000 0 0x8000000>;
+			reg-names = "apb-base", "memory0", "memory1", "memory2", "memory3";
+			interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 319>;
+			clock-names = "pcie";
+			resets = <&cpg 319>;
+			power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
 		vspb0: vsp@fe960000 {
 			compatible = "renesas,vsp2";
 			reg = <0 0xfe960000 0 0x8000>;
diff --git a/arch/arm/dts/r8a774e1-hihope-rzg2h-ex.dts b/arch/arm/dts/r8a774e1-hihope-rzg2h-ex.dts
new file mode 100644
index 0000000..8129959
--- /dev/null
+++ b/arch/arm/dts/r8a774e1-hihope-rzg2h-ex.dts
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the HiHope RZ/G2H sub board
+ *
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ */
+
+#include "r8a774e1-hihope-rzg2h.dts"
+#include "hihope-rzg2-ex.dtsi"
+
+/ {
+	model = "HopeRun HiHope RZ/G2H with sub board";
+	compatible = "hoperun,hihope-rzg2-ex", "hoperun,hihope-rzg2h",
+		     "renesas,r8a774e1";
+};
+
+/* Set SW43 = ON and SW1001[7] = OFF for SATA port to be activated */
+&sata {
+	status = "okay";
+};
diff --git a/arch/arm/dts/r8a774e1-hihope-rzg2h-u-boot.dts b/arch/arm/dts/r8a774e1-hihope-rzg2h-u-boot.dts
new file mode 100644
index 0000000..03a17ba
--- /dev/null
+++ b/arch/arm/dts/r8a774e1-hihope-rzg2h-u-boot.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source extras for U-Boot for the Hihope RZ/G2H board
+ *
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ */
+
+#include "r8a774e1-hihope-rzg2h-ex.dts"
+#include "r8a774e1-u-boot.dtsi"
+
+&gpio3 {
+	bt_reg_on{
+		gpio-hog;
+		gpios = <13 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "bt-reg-on";
+	};
+};
+
+&gpio4 {
+	wlan_reg_on{
+		gpio-hog;
+		gpios = <6 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "wlan-reg-on";
+	};
+};
diff --git a/arch/arm/dts/r8a774e1-hihope-rzg2h.dts b/arch/arm/dts/r8a774e1-hihope-rzg2h.dts
new file mode 100644
index 0000000..9525d5e
--- /dev/null
+++ b/arch/arm/dts/r8a774e1-hihope-rzg2h.dts
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the HiHope RZ/G2H main board
+ *
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ */
+
+/dts-v1/;
+#include "r8a774e1.dtsi"
+#include "hihope-rev4.dtsi"
+
+/ {
+	model = "HopeRun HiHope RZ/G2H main board based on r8a774e1";
+	compatible = "hoperun,hihope-rzg2h", "renesas,r8a774e1";
+
+	memory@48000000 {
+		device_type = "memory";
+		/* first 128MB is reserved for secure area. */
+		reg = <0x0 0x48000000 0x0 0x78000000>;
+	};
+
+	memory@500000000 {
+		device_type = "memory";
+		reg = <0x5 0x00000000 0x0 0x80000000>;
+	};
+};
+
+&du {
+	clocks = <&cpg CPG_MOD 724>,
+		 <&cpg CPG_MOD 723>,
+		 <&cpg CPG_MOD 721>,
+		 <&versaclock5 1>,
+		 <&x302_clk>,
+		 <&versaclock5 2>;
+	clock-names = "du.0", "du.1", "du.3",
+		      "dclkin.0", "dclkin.1", "dclkin.3";
+};
+
+&sdhi3 {
+	mmc-hs400-1_8v;
+};
diff --git a/arch/arm/dts/r8a774e1-u-boot.dtsi b/arch/arm/dts/r8a774e1-u-boot.dtsi
new file mode 100644
index 0000000..74758df
--- /dev/null
+++ b/arch/arm/dts/r8a774e1-u-boot.dtsi
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source extras for U-Boot on RZ/G2 R8A774E1 SoC
+ *
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ */
+
+#include "r8a779x-u-boot.dtsi"
+
+&extalr_clk {
+	u-boot,dm-pre-reloc;
+};
+
+/delete-node/ &audma0;
+/delete-node/ &audma1;
+/delete-node/ &can0;
+/delete-node/ &can1;
+/delete-node/ &canfd;
+/delete-node/ &csi20;
+/delete-node/ &csi40;
+/delete-node/ &du;
+/delete-node/ &fcpf0;
+/delete-node/ &fcpf1;
+/delete-node/ &fcpvb0;
+/delete-node/ &fcpvb1;
+/delete-node/ &fcpvd0;
+/delete-node/ &fcpvd1;
+/delete-node/ &fcpvi0;
+/delete-node/ &fcpvi1;
+/delete-node/ &hdmi0;
+/delete-node/ &lvds0;
+/delete-node/ &rcar_sound;
+/delete-node/ &sdhi2;
+/delete-node/ &sound_card;
+/delete-node/ &vin0;
+/delete-node/ &vin1;
+/delete-node/ &vin2;
+/delete-node/ &vin3;
+/delete-node/ &vin4;
+/delete-node/ &vin5;
+/delete-node/ &vin6;
+/delete-node/ &vin7;
+/delete-node/ &vspbc;
+/delete-node/ &vspbd;
+/delete-node/ &vspd0;
+/delete-node/ &vspd1;
+/delete-node/ &vspi0;
+/delete-node/ &vspi1;
+
+/ {
+	/delete-node/ hdmi0-out;
+};
+
+/ {
+	soc {
+		/delete-node/ fdp1@fe940000;
+		/delete-node/ fdp1@fe944000;
+	};
+};
diff --git a/arch/arm/dts/rk3368-geekbox-u-boot.dtsi b/arch/arm/dts/rk3368-geekbox-u-boot.dtsi
index 30ea9e4..0b724fa 100644
--- a/arch/arm/dts/rk3368-geekbox-u-boot.dtsi
+++ b/arch/arm/dts/rk3368-geekbox-u-boot.dtsi
@@ -3,6 +3,8 @@
  * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
  */
 
+#include "rk3368-u-boot.dtsi"
+
 &pinctrl {
 	u-boot,dm-pre-reloc;
 };
diff --git a/arch/arm/dts/rk3368-lion-u-boot.dtsi b/arch/arm/dts/rk3368-lion-haikou-u-boot.dtsi
similarity index 96%
rename from arch/arm/dts/rk3368-lion-u-boot.dtsi
rename to arch/arm/dts/rk3368-lion-haikou-u-boot.dtsi
index 6d54214d..7826d1e 100644
--- a/arch/arm/dts/rk3368-lion-u-boot.dtsi
+++ b/arch/arm/dts/rk3368-lion-haikou-u-boot.dtsi
@@ -3,6 +3,8 @@
  * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
  */
 
+#include "rk3368-u-boot.dtsi"
+
 / {
 	config {
 		u-boot,spl-payload-offset = <0x40000>; /* @ 256KB */
@@ -36,6 +38,10 @@
 	};
 };
 
+&gpio2 {
+	u-boot,dm-pre-reloc;
+};
+
 &pinctrl {
 	u-boot,dm-pre-reloc;
 };
diff --git a/arch/arm/dts/rk3368-lion-haikou.dts b/arch/arm/dts/rk3368-lion-haikou.dts
new file mode 100644
index 0000000..7fcb1ea
--- /dev/null
+++ b/arch/arm/dts/rk3368-lion-haikou.dts
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Theobroma Systems Design und Consulting GmbH
+ */
+
+/dts-v1/;
+#include "rk3368-lion.dtsi"
+
+/ {
+	model = "Theobroma Systems RK3368-uQ7 Baseboard";
+	compatible = "tsd,rk3368-lion-haikou", "rockchip,rk3368";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	i2cmux2 {
+		i2c@0 {
+			eeprom: eeprom@50 {
+				compatible = "atmel,24c01";
+				pagesize = <8>;
+				reg = <0x50>;
+			};
+		};
+	};
+
+	leds {
+		pinctrl-0 = <&module_led_pins>, <&sd_card_led_pin>;
+
+		sd_card_led: led-3 {
+			label = "sd_card_led";
+			gpios = <&gpio0 RK_PD2 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc0";
+		};
+	};
+
+	dc_12v: dc-12v {
+		compatible = "regulator-fixed";
+		regulator-name = "dc_12v";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+	};
+
+	vcc3v3_baseboard: vcc3v3-baseboard {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc3v3_baseboard";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&dc_12v>;
+	};
+
+	vcc5v0_otg: vcc5v0-otg-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&otg_vbus_drv>;
+		regulator-name = "vcc5v0_otg";
+		regulator-always-on;
+	};
+};
+
+&sdmmc {
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	cd-gpios = <&gpio2 RK_PB3 GPIO_ACTIVE_LOW>;
+	disable-wp;
+	max-frequency = <25000000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4>;
+	rockchip,default-sample-phase = <90>;
+	vmmc-supply = <&vcc3v3_baseboard>;
+	status = "okay";
+};
+
+&spi2 {
+	cs-gpios = <0>, <&gpio2 RK_PC3 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&usb_otg {
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
+	status = "okay";
+};
+
+&uart1 {
+	/* alternate function of GPIO5/6 */
+	status = "disabled";
+};
+
+&pinctrl {
+	pinctrl-names = "default";
+	pinctrl-0 = <&haikou_pin_hog>;
+
+	hog {
+		haikou_pin_hog: haikou-pin-hog {
+			rockchip,pins =
+				/* LID_BTN */
+				<3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>,
+				/* BATLOW# */
+				<0 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up>,
+				/* SLP_BTN# */
+				<3 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>,
+				/* BIOS_DISABLE# */
+				<3 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	leds {
+		sd_card_led_pin: sd-card-led-pin {
+			rockchip,pins =
+				<0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	sdmmc {
+		sdmmc_cd_pin: sdmmc-cd-pin {
+			rockchip,pins =
+				<2 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	usb_otg {
+		otg_vbus_drv: otg-vbus-drv {
+			rockchip,pins =
+				<0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
diff --git a/arch/arm/dts/rk3368-lion.dts b/arch/arm/dts/rk3368-lion.dts
deleted file mode 100644
index 2814542..0000000
--- a/arch/arm/dts/rk3368-lion.dts
+++ /dev/null
@@ -1,194 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+ OR X11
-/*
- * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
- */
-
-/dts-v1/;
-#include "rk3368.dtsi"
-#include "rk3368-lion-u-boot.dtsi"
-#include <dt-bindings/input/input.h>
-
-/ {
-	model = "Theobroma Systems RK3368-uQ7 SoM";
-	compatible = "tsd,rk3368-uq7", "tsd,lion", "rockchip,rk3368";
-
-	aliases {
-		mmc0 = &emmc;
-		mmc1 = &sdmmc;
-	};
-
-	memory@0 {
-		device_type = "memory";
-		reg = <0x0 0x0 0x0 0x80000000>;
-	};
-
-	ext_gmac: gmac-clk {
-		compatible = "fixed-clock";
-		clock-frequency = <125000000>;
-		clock-output-names = "ext_gmac";
-		#clock-cells = <0>;
-	};
-
-	vcc_sys: vcc-sys-regulator {
-		compatible = "regulator-fixed";
-		regulator-name = "vcc_sys";
-		regulator-min-microvolt = <5000000>;
-		regulator-max-microvolt = <5000000>;
-		regulator-always-on;
-		regulator-boot-on;
-	};
-};
-
-&uart0 {
-	status = "okay";
-};
-
-&emmc {
-	status = "okay";
-	bus-width = <8>;
-	cap-mmc-highspeed;
-	clock-frequency = <150000000>;
-	disable-wp;
-	keep-power-in-suspend;
-	non-removable;
-	num-slots = <1>;
-	vmmc-supply = <&vcc33_io>;
-	vqmmc-supply = <&vcc18_io>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&emmc_clk>, <&emmc_cmd>, <&emmc_bus8>;
-};
-
-&sdmmc {
-	status = "okay";
-};
-
-&gmac {
-	status = "okay";
-	phy-supply = <&vcc33_io>;
-	phy-mode = "rgmii";
-	clock_in_out = "input";
-	snps,reset-gpio = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>;
-	snps,reset-active-low;
-	snps,reset-delays-us = <2 10000 50000>;
-	assigned-clocks = <&cru SCLK_MAC>;
-	assigned-clock-parents = <&ext_gmac>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&rgmii_pins>;
-	tx_delay = <0x10>;
-	rx_delay = <0x10>;
-};
-
-&i2c0 {
-	status = "okay";
-
-	rk808: pmic@1b {
-		compatible = "rockchip,rk808";
-		reg = <0x1b>;
-		interrupt-parent = <&gpio0>;
-		interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
-		rockchip,system-power-controller;
-		vcc1-supply = <&vcc_sys>;
-		vcc2-supply = <&vcc_sys>;
-		vcc3-supply = <&vcc_sys>;
-		vcc4-supply = <&vcc_sys>;
-		vcc6-supply = <&vcc_sys>;
-		vcc7-supply = <&vcc_sys>;
-		vcc8-supply = <&vcc_sys>;
-		vcc9-supply = <&vcc_sys>;
-		vcc10-supply = <&vcc_sys>;
-		vcc11-supply = <&vcc_sys>;
-		vcc12-supply = <&vcc_sys>;
-		clock-output-names = "xin32k", "rk808-clkout2";
-		#clock-cells = <1>;
-
-		regulators {
-			vdd_cpu: DCDC_REG1 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <700000>;
-				regulator-max-microvolt = <1500000>;
-				regulator-name = "vdd_cpu";
-			};
-
-			vdd_log: DCDC_REG2 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <700000>;
-				regulator-max-microvolt = <1500000>;
-				regulator-name = "vdd_log";
-			};
-
-			vcc_ddr: DCDC_REG3 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-name = "vcc_ddr";
-			};
-
-			vcc33_io: DCDC_REG4 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <3300000>;
-				regulator-max-microvolt = <3300000>;
-				regulator-name = "vcc33_io";
-			};
-
-			vcc33_video: LDO_REG2 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <3300000>;
-				regulator-max-microvolt = <3300000>;
-				regulator-name = "vcc33_video";
-			};
-
-			vdd10_pll: LDO_REG3 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <1000000>;
-				regulator-max-microvolt = <1000000>;
-				regulator-name = "vdd10_pll";
-			};
-
-			vcc18_io: LDO_REG4 {
-				regulator-boot-on;
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <1800000>;
-				regulator-name = "vcc18_io";
-			};
-
-			vdd10_video: LDO_REG6 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <1000000>;
-				regulator-max-microvolt = <1000000>;
-				regulator-name = "vdd10_video";
-			};
-
-			vcc18_video: LDO_REG8 {
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <1800000>;
-				regulator-name = "vcc18_video";
-			};
-		};
-	};
-};
-
-&uart0 {
-	status = "okay";
-};
-
-&spi1 {
-	status = "okay";
-
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	spiflash: w25q32dw@0 {
-		compatible = "jedec,spi-nor";
-		reg = <0>;
-		spi-max-frequency = <49500000>;
-		spi-cpol;
-		spi-cpha;
-	};
-};
diff --git a/arch/arm/dts/rk3368-lion.dtsi b/arch/arm/dts/rk3368-lion.dtsi
new file mode 100644
index 0000000..532e6a6
--- /dev/null
+++ b/arch/arm/dts/rk3368-lion.dtsi
@@ -0,0 +1,331 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Theobroma Systems Design und Consulting GmbH
+ */
+
+/dts-v1/;
+#include "rk3368.dtsi"
+
+/ {
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	ext_gmac: gmac-clk {
+		compatible = "fixed-clock";
+		clock-frequency = <125000000>;
+		clock-output-names = "ext_gmac";
+		#clock-cells = <0>;
+	};
+
+	i2cmux1 {
+		compatible = "i2c-mux-gpio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		i2c-parent = <&i2c1>;
+		mux-gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>;
+
+		/* Q7_GPO_I2C */
+		i2c@0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		/* Q7_SMB */
+		i2c@1 {
+			reg = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	i2cmux2 {
+		compatible = "i2c-mux-gpio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		i2c-parent = <&i2c2>;
+		mux-gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_HIGH>;
+
+		/* Q7_LVDS_BLC_I2C */
+		i2c@0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			fan: fan@18 {
+				compatible = "ti,amc6821";
+				reg = <0x18>;
+				#cooling-cells = <2>;
+			};
+
+			rtc_twi: rtc@6f {
+				compatible = "isil,isl1208";
+				reg = <0x6f>;
+			};
+		};
+
+		/* Q7_GP2_I2C */
+		i2c@1 {
+			reg = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&module_led_pins>;
+
+		module_led1: led-1 {
+			label = "module_led1";
+			gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+			panic-indicator;
+		};
+
+		module_led2: led-2 {
+			label = "module_led2";
+			gpios = <&gpio3 RK_PA3 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
+
+	vcc_sys: vcc-sys-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_sys";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+};
+
+&cpu_l0 {
+	cpu-supply = <&vdd_cpu>;
+};
+
+&cpu_l1 {
+	cpu-supply = <&vdd_cpu>;
+};
+
+&cpu_l2 {
+	cpu-supply = <&vdd_cpu>;
+};
+
+&cpu_l3 {
+	cpu-supply = <&vdd_cpu>;
+};
+
+&cpu_b0 {
+	cpu-supply = <&vdd_cpu>;
+};
+
+&cpu_b1 {
+	cpu-supply = <&vdd_cpu>;
+};
+
+&cpu_b2 {
+	cpu-supply = <&vdd_cpu>;
+};
+
+&cpu_b3 {
+	cpu-supply = <&vdd_cpu>;
+};
+
+&emmc {
+	bus-width = <8>;
+	clock-frequency = <150000000>;
+	mmc-hs200-1_8v;
+	non-removable;
+	vmmc-supply = <&vcc33_io>;
+	vqmmc-supply = <&vcc18_io>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_clk>, <&emmc_cmd>, <&emmc_bus8>;
+	status = "okay";
+};
+
+&gmac {
+	assigned-clocks = <&cru SCLK_MAC>;
+	assigned-clock-parents = <&ext_gmac>;
+	clock_in_out = "input";
+	phy-handle = <&phy0>;
+	phy-supply = <&vcc33_io>;
+	phy-mode = "rgmii";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>;
+	snps,reset-active-low;
+	snps,reset-delays-us = <0 10000 50000>;
+	snps,reset-gpio = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>;
+	tx_delay = <0x10>;
+	rx_delay = <0x10>;
+	status = "okay";
+
+	mdio {
+		compatible = "snps,dwmac-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		/* Microsemi VSC8531-02 */
+		phy0: phy@0 {
+		compatible = "ethernet-phy-id0007.0570";
+			reg = <0>;
+			vsc8531,clk-out-frequency = <125000000>;
+			vsc8531,edge-slowdown = <7>;
+			vsc8531,led-0-mode = <1>;
+			vsc8531,led-1-mode = <2>;
+		};
+	};
+};
+
+&i2c0 {
+	status = "okay";
+
+	rk808: pmic@1b {
+		compatible = "rockchip,rk808";
+		reg = <0x1b>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <RK_PA5 IRQ_TYPE_LEVEL_LOW>;
+		clock-output-names = "xin32k", "rk808-clkout2";
+		#clock-cells = <1>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_int_l>, <&pmic_sleep>;
+		rockchip,system-power-controller;
+		vcc1-supply = <&vcc_sys>;
+		vcc2-supply = <&vcc_sys>;
+		vcc3-supply = <&vcc_sys>;
+		vcc4-supply = <&vcc_sys>;
+		vcc6-supply = <&vcc_sys>;
+		vcc7-supply = <&vcc_sys>;
+		vcc8-supply = <&vcc_sys>;
+		vcc9-supply = <&vcc_sys>;
+		vcc10-supply = <&vcc_sys>;
+		vcc11-supply = <&vcc_sys>;
+		vcc12-supply = <&vcc_sys>;
+
+		regulators {
+			vdd_cpu: DCDC_REG1 {
+				regulator-name = "vdd_cpu";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			vdd_log: DCDC_REG2 {
+				regulator-name = "vdd_log";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			vcc_ddr: DCDC_REG3 {
+				regulator-name = "vcc_ddr";
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			vcc33_io: DCDC_REG4 {
+				regulator-name = "vcc33_io";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			vcc33_video: LDO_REG2 {
+				regulator-name = "vcc33_video";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			vdd10_pll: LDO_REG3 {
+				regulator-name = "vdd10_pll";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			vcc18_io: LDO_REG4 {
+				regulator-name = "vcc18_io";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+			};
+
+			vdd10_video: LDO_REG6 {
+				regulator-name = "vdd10_video";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			vcc18_video: LDO_REG8 {
+				regulator-name = "vcc18_video";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+		};
+	};
+};
+
+&i2c1 {
+	status = "okay";
+};
+
+&i2c2 {
+	status = "okay";
+};
+
+&pinctrl {
+	leds {
+		module_led_pins: module-led-pins {
+			rockchip,pins =
+				<2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>,
+				<3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+	pmic {
+		pmic_int_l: pmic-int-l {
+			rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+
+		pmic_sleep: pmic-sleep {
+			rockchip,pins = <0 RK_PA0 2 &pcfg_pull_none>;
+		};
+	};
+};
+
+&spi1 {
+	status = "okay";
+
+	norflash: flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <50000000>;
+	};
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&usb_host0_ehci {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3368-px5-evb-u-boot.dtsi b/arch/arm/dts/rk3368-px5-evb-u-boot.dtsi
index 936ce55..264fb7a 100644
--- a/arch/arm/dts/rk3368-px5-evb-u-boot.dtsi
+++ b/arch/arm/dts/rk3368-px5-evb-u-boot.dtsi
@@ -2,6 +2,9 @@
 /*
  * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
  */
+
+#include "rk3368-u-boot.dtsi"
+
 / {
 	chosen {
 		u-boot,spl-boot-order = &emmc;
diff --git a/arch/arm/dts/rk3368-sheep-u-boot.dtsi b/arch/arm/dts/rk3368-sheep-u-boot.dtsi
index 30ea9e4..0b724fa 100644
--- a/arch/arm/dts/rk3368-sheep-u-boot.dtsi
+++ b/arch/arm/dts/rk3368-sheep-u-boot.dtsi
@@ -3,6 +3,8 @@
  * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
  */
 
+#include "rk3368-u-boot.dtsi"
+
 &pinctrl {
 	u-boot,dm-pre-reloc;
 };
diff --git a/arch/arm/dts/rk3368-u-boot.dtsi b/arch/arm/dts/rk3368-u-boot.dtsi
new file mode 100644
index 0000000..2767c26
--- /dev/null
+++ b/arch/arm/dts/rk3368-u-boot.dtsi
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH
+ */
+
+#include <dt-bindings/memory/rk3368-dmc.h>
+
+/ {
+	dmc: dmc@ff610000 {
+		compatible = "rockchip,rk3368-dmc", "syscon";
+		rockchip,cru = <&cru>;
+		rockchip,grf = <&grf>;
+		rockchip,msch = <&service_msch>;
+		reg = <0 0xff610000 0 0x400
+		       0 0xff620000 0 0x400>;
+	};
+
+	service_msch: syscon@ffac0000 {
+		compatible = "rockchip,rk3368-msch", "syscon";
+		reg = <0x0 0xffac0000 0x0 0x2000>;
+	};
+
+	sgrf: syscon@ff740000 {
+		compatible = "rockchip,rk3368-sgrf", "syscon";
+		reg = <0x0 0xff740000 0x0 0x1000>;
+	};
+};
diff --git a/arch/arm/dts/rk3368.dtsi b/arch/arm/dts/rk3368.dtsi
index b4f4f61..cd2c322 100644
--- a/arch/arm/dts/rk3368.dtsi
+++ b/arch/arm/dts/rk3368.dtsi
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2015 Heiko Stuebner <heiko@sntech.de>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 #include <dt-bindings/clock/rk3368-cru.h>
@@ -45,8 +8,8 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,boot-mode.h>
 #include <dt-bindings/thermal/thermal.h>
-#include <dt-bindings/memory/rk3368-dmc.h>
 
 / {
 	compatible = "rockchip,rk3368";
@@ -108,84 +71,99 @@
 			};
 		};
 
-		idle-states {
-			entry-method = "psci";
-
-			cpu_sleep: cpu-sleep-0 {
-				compatible = "arm,idle-state";
-				arm,psci-suspend-param = <0x1010000>;
-				entry-latency-us = <0x3fffffff>;
-				exit-latency-us = <0x40000000>;
-				min-residency-us = <0xffffffff>;
-			};
-		};
-
 		cpu_l0: cpu@0 {
 			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
+			compatible = "arm,cortex-a53";
 			reg = <0x0 0x0>;
-			cpu-idle-states = <&cpu_sleep>;
 			enable-method = "psci";
-
 			#cooling-cells = <2>; /* min followed by max */
 		};
 
 		cpu_l1: cpu@1 {
 			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
+			compatible = "arm,cortex-a53";
 			reg = <0x0 0x1>;
-			cpu-idle-states = <&cpu_sleep>;
 			enable-method = "psci";
+			#cooling-cells = <2>; /* min followed by max */
 		};
 
 		cpu_l2: cpu@2 {
 			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
+			compatible = "arm,cortex-a53";
 			reg = <0x0 0x2>;
-			cpu-idle-states = <&cpu_sleep>;
 			enable-method = "psci";
+			#cooling-cells = <2>; /* min followed by max */
 		};
 
 		cpu_l3: cpu@3 {
 			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
+			compatible = "arm,cortex-a53";
 			reg = <0x0 0x3>;
-			cpu-idle-states = <&cpu_sleep>;
 			enable-method = "psci";
+			#cooling-cells = <2>; /* min followed by max */
 		};
 
 		cpu_b0: cpu@100 {
 			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
+			compatible = "arm,cortex-a53";
 			reg = <0x0 0x100>;
-			cpu-idle-states = <&cpu_sleep>;
 			enable-method = "psci";
-
 			#cooling-cells = <2>; /* min followed by max */
 		};
 
 		cpu_b1: cpu@101 {
 			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
+			compatible = "arm,cortex-a53";
 			reg = <0x0 0x101>;
-			cpu-idle-states = <&cpu_sleep>;
 			enable-method = "psci";
+			#cooling-cells = <2>; /* min followed by max */
 		};
 
 		cpu_b2: cpu@102 {
 			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
+			compatible = "arm,cortex-a53";
 			reg = <0x0 0x102>;
-			cpu-idle-states = <&cpu_sleep>;
 			enable-method = "psci";
+			#cooling-cells = <2>; /* min followed by max */
 		};
 
 		cpu_b3: cpu@103 {
 			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
+			compatible = "arm,cortex-a53";
 			reg = <0x0 0x103>;
-			cpu-idle-states = <&cpu_sleep>;
 			enable-method = "psci";
+			#cooling-cells = <2>; /* min followed by max */
+		};
+	};
+
+	amba: bus {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		dmac_peri: dma-controller@ff250000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x0 0xff250000 0x0 0x4000>;
+			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			arm,pl330-broken-no-flushp;
+			arm,pl330-periph-burst;
+			clocks = <&cru ACLK_DMAC_PERI>;
+			clock-names = "apb_pclk";
+		};
+
+		dmac_bus: dma-controller@ff600000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x0 0xff600000 0x0 0x4000>;
+			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			arm,pl330-broken-no-flushp;
+			arm,pl330-periph-burst;
+			clocks = <&cru ACLK_DMAC_BUS>;
+			clock-names = "apb_pclk";
 		};
 	};
 
@@ -228,54 +206,45 @@
 		#clock-cells = <0>;
 	};
 
-	dmc: dmc@ff610000 {
-		compatible = "rockchip,rk3368-dmc", "syscon";
-		rockchip,cru = <&cru>;
-		rockchip,grf = <&grf>;
-		rockchip,msch = <&service_msch>;
-		reg = <0 0xff610000 0 0x400
-		       0 0xff620000 0 0x400>;
-	};
-
-	service_msch: syscon@ffac0000 {
-		compatible = "rockchip,rk3368-msch", "syscon";
-		reg = <0x0 0xffac0000 0x0 0x2000>;
-		status = "okay";
-	};
-
-	sdmmc: dwmmc@ff0c0000 {
+	sdmmc: mmc@ff0c0000 {
 		compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc";
 		reg = <0x0 0xff0c0000 0x0 0x4000>;
-		clock-freq-min-max = <400000 150000000>;
+		max-frequency = <150000000>;
 		clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
 			 <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
 		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
 		fifo-depth = <0x100>;
 		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+		resets = <&cru SRST_MMC0>;
+		reset-names = "reset";
 		status = "disabled";
 	};
 
-	sdio0: dwmmc@ff0d0000 {
+	sdio0: mmc@ff0d0000 {
 		compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc";
 		reg = <0x0 0xff0d0000 0x0 0x4000>;
-		clock-freq-min-max = <400000 150000000>;
+		max-frequency = <150000000>;
 		clocks = <&cru HCLK_SDIO0>, <&cru SCLK_SDIO0>,
 			 <&cru SCLK_SDIO0_DRV>, <&cru SCLK_SDIO0_SAMPLE>;
-		clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
 		fifo-depth = <0x100>;
 		interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+		resets = <&cru SRST_SDIO0>;
+		reset-names = "reset";
 		status = "disabled";
 	};
 
-	emmc: dwmmc@ff0f0000 {
+	emmc: mmc@ff0f0000 {
 		compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc";
 		reg = <0x0 0xff0f0000 0x0 0x4000>;
-		clock-freq-min-max = <400000 150000000>;
+		max-frequency = <150000000>;
 		clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
 			 <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
 		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
 		fifo-depth = <0x100>;
 		interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+		resets = <&cru SRST_EMMC>;
+		reset-names = "reset";
 		status = "disabled";
 	};
 
@@ -286,6 +255,8 @@
 		#io-channel-cells = <1>;
 		clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
 		clock-names = "saradc", "apb_pclk";
+		resets = <&cru SRST_SARADC>;
+		reset-names = "saradc-apb";
 		status = "disabled";
 	};
 
@@ -328,16 +299,16 @@
 		status = "disabled";
 	};
 
-	i2c1: i2c@ff140000 {
+	i2c2: i2c@ff140000 {
 		compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c";
 		reg = <0x0 0xff140000 0x0 0x1000>;
 		interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		clock-names = "i2c";
-		clocks = <&cru PCLK_I2C1>;
+		clocks = <&cru PCLK_I2C2>;
 		pinctrl-names = "default";
-		pinctrl-0 = <&i2c1_xfer>;
+		pinctrl-0 = <&i2c2_xfer>;
 		status = "disabled";
 	};
 
@@ -389,8 +360,6 @@
 		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
 		reg-shift = <2>;
 		reg-io-width = <4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&uart0_xfer>;
 		status = "disabled";
 	};
 
@@ -403,8 +372,6 @@
 		interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
 		reg-shift = <2>;
 		reg-io-width = <4>;
-		pinctrl-names = "default";
-		pinctrl-1 = <&uart0_xfer>;
 		status = "disabled";
 	};
 
@@ -417,8 +384,6 @@
 		interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
 		reg-shift = <2>;
 		reg-io-width = <4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&uart3_xfer>;
 		status = "disabled";
 	};
 
@@ -431,8 +396,6 @@
 		interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
 		reg-shift = <2>;
 		reg-io-width = <4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&uart4_xfer>;
 		status = "disabled";
 	};
 
@@ -465,12 +428,18 @@
 				map0 {
 					trip = <&cpu_alert0>;
 					cooling-device =
-					<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+					<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+					<&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+					<&cpu_b2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+					<&cpu_b3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
 				};
 				map1 {
 					trip = <&cpu_alert1>;
 					cooling-device =
-					<&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+					<&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+					<&cpu_l1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+					<&cpu_l2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+					<&cpu_l3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
 				};
 			};
 		};
@@ -498,7 +467,10 @@
 				map0 {
 					trip = <&gpu_alert0>;
 					cooling-device =
-					<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+					<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+					<&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+					<&cpu_b2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+					<&cpu_b3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
 				};
 			};
 		};
@@ -513,9 +485,9 @@
 		resets = <&cru SRST_TSADC>;
 		reset-names = "tsadc-apb";
 		pinctrl-names = "init", "default", "sleep";
-		pinctrl-0 = <&otp_gpio>;
+		pinctrl-0 = <&otp_pin>;
 		pinctrl-1 = <&otp_out>;
-		pinctrl-2 = <&otp_gpio>;
+		pinctrl-2 = <&otp_pin>;
 		#thermal-sensor-cells = <1>;
 		rockchip,hw-tshut-temp = <95000>;
 		status = "disabled";
@@ -543,7 +515,6 @@
 		reg = <0x0 0xff500000 0x0 0x100>;
 		interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&cru HCLK_HOST0>;
-		clock-names = "usbhost";
 		status = "disabled";
 	};
 
@@ -558,7 +529,6 @@
 		g-np-tx-fifo-size = <16>;
 		g-rx-fifo-size = <275>;
 		g-tx-fifo-size = <256 128 128 64 64 32>;
-		g-use-dma;
 		status = "disabled";
 	};
 
@@ -575,16 +545,16 @@
 		status = "disabled";
 	};
 
-	i2c2: i2c@ff660000 {
+	i2c1: i2c@ff660000 {
 		compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c";
 		reg = <0x0 0xff660000 0x0 0x1000>;
 		interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		clock-names = "i2c";
-		clocks = <&cru PCLK_I2C2>;
+		clocks = <&cru PCLK_I2C1>;
 		pinctrl-names = "default";
-		pinctrl-0 = <&i2c2_xfer>;
+		pinctrl-0 = <&i2c1_xfer>;
 		status = "disabled";
 	};
 
@@ -633,7 +603,6 @@
 	uart2: serial@ff690000 {
 		compatible = "rockchip,rk3368-uart", "snps,dw-apb-uart";
 		reg = <0x0 0xff690000 0x0 0x100>;
-		clock-frequency = <24000000>;
 		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
 		clock-names = "baudclk", "apb_pclk";
 		interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
@@ -654,16 +623,26 @@
 		clocks = <&cru PCLK_MAILBOX>;
 		clock-names = "pclk_mailbox";
 		#mbox-cells = <1>;
+		status = "disabled";
 	};
 
 	pmugrf: syscon@ff738000 {
-		compatible = "rockchip,rk3368-pmugrf", "syscon";
+		compatible = "rockchip,rk3368-pmugrf", "syscon", "simple-mfd";
 		reg = <0x0 0xff738000 0x0 0x1000>;
-	};
 
-	sgrf: syscon@ff740000 {
-	        compatible = "rockchip,rk3368-sgrf", "syscon";
-		reg = <0x0 0xff740000 0x0 0x1000>;
+		pmu_io_domains: io-domains {
+			compatible = "rockchip,rk3368-pmu-io-voltage-domain";
+			status = "disabled";
+		};
+
+		reboot-mode {
+			compatible = "syscon-reboot-mode";
+			offset = <0x200>;
+			mode-normal = <BOOT_NORMAL>;
+			mode-recovery = <BOOT_RECOVERY>;
+			mode-bootloader = <BOOT_FASTBOOT>;
+			mode-loader = <BOOT_BL_DOWNLOAD>;
+		};
 	};
 
 	cru: clock-controller@ff760000 {
@@ -675,8 +654,13 @@
 	};
 
 	grf: syscon@ff770000 {
-		compatible = "rockchip,rk3368-grf", "syscon";
+		compatible = "rockchip,rk3368-grf", "syscon", "simple-mfd";
 		reg = <0x0 0xff770000 0x0 0x1000>;
+
+		io_domains: io-domains {
+			compatible = "rockchip,rk3368-io-voltage-domain";
+			status = "disabled";
+		};
 	};
 
 	wdt: watchdog@ff800000 {
@@ -693,6 +677,118 @@
 		interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
+	spdif: spdif@ff880000 {
+		compatible = "rockchip,rk3368-spdif";
+		reg = <0x0 0xff880000 0x0 0x1000>;
+		interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_SPDIF_8CH>, <&cru HCLK_SPDIF>;
+		clock-names = "mclk", "hclk";
+		dmas = <&dmac_bus 3>;
+		dma-names = "tx";
+		pinctrl-names = "default";
+		pinctrl-0 = <&spdif_tx>;
+		status = "disabled";
+	};
+
+	i2s_2ch: i2s-2ch@ff890000 {
+		compatible = "rockchip,rk3368-i2s", "rockchip,rk3066-i2s";
+		reg = <0x0 0xff890000 0x0 0x1000>;
+		interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+		clock-names = "i2s_clk", "i2s_hclk";
+		clocks = <&cru SCLK_I2S_2CH>, <&cru HCLK_I2S_2CH>;
+		dmas = <&dmac_bus 6>, <&dmac_bus 7>;
+		dma-names = "tx", "rx";
+		status = "disabled";
+	};
+
+	i2s_8ch: i2s-8ch@ff898000 {
+		compatible = "rockchip,rk3368-i2s", "rockchip,rk3066-i2s";
+		reg = <0x0 0xff898000 0x0 0x1000>;
+		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+		clock-names = "i2s_clk", "i2s_hclk";
+		clocks = <&cru SCLK_I2S_8CH>, <&cru HCLK_I2S_8CH>;
+		dmas = <&dmac_bus 0>, <&dmac_bus 1>;
+		dma-names = "tx", "rx";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s_8ch_bus>;
+		status = "disabled";
+	};
+
+	iep_mmu: iommu@ff900800 {
+		compatible = "rockchip,iommu";
+		reg = <0x0 0xff900800 0x0 0x100>;
+		interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "iep_mmu";
+		clocks = <&cru ACLK_IEP>, <&cru HCLK_IEP>;
+		clock-names = "aclk", "iface";
+		#iommu-cells = <0>;
+		status = "disabled";
+	};
+
+	isp_mmu: iommu@ff914000 {
+		compatible = "rockchip,iommu";
+		reg = <0x0 0xff914000 0x0 0x100>,
+		      <0x0 0xff915000 0x0 0x100>;
+		interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "isp_mmu";
+		clocks = <&cru ACLK_ISP>, <&cru HCLK_ISP>;
+		clock-names = "aclk", "iface";
+		#iommu-cells = <0>;
+		rockchip,disable-mmu-reset;
+		status = "disabled";
+	};
+
+	vop_mmu: iommu@ff930300 {
+		compatible = "rockchip,iommu";
+		reg = <0x0 0xff930300 0x0 0x100>;
+		interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "vop_mmu";
+		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
+		clock-names = "aclk", "iface";
+		#iommu-cells = <0>;
+		status = "disabled";
+	};
+
+	hevc_mmu: iommu@ff9a0440 {
+		compatible = "rockchip,iommu";
+		reg = <0x0 0xff9a0440 0x0 0x40>,
+		      <0x0 0xff9a0480 0x0 0x40>;
+		interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "hevc_mmu";
+		clocks = <&cru ACLK_VIDEO>, <&cru HCLK_VIDEO>;
+		clock-names = "aclk", "iface";
+		#iommu-cells = <0>;
+		status = "disabled";
+	};
+
+	vpu_mmu: iommu@ff9a0800 {
+		compatible = "rockchip,iommu";
+		reg = <0x0 0xff9a0800 0x0 0x100>;
+		interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "vepu_mmu", "vdpu_mmu";
+		clocks = <&cru ACLK_VIDEO>, <&cru HCLK_VIDEO>;
+		clock-names = "aclk", "iface";
+		#iommu-cells = <0>;
+		status = "disabled";
+	};
+
+	efuse256: efuse@ffb00000 {
+		compatible = "rockchip,rk3368-efuse";
+		reg = <0x0 0xffb00000 0x0 0x20>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		clocks = <&cru PCLK_EFUSE256>;
+		clock-names = "pclk_efuse";
+
+		cpu_leakage: cpu-leakage@17 {
+			reg = <0x17 0x1>;
+		};
+		temp_adjust: temp-adjust@1f {
+			reg = <0x1f 0x1>;
+		};
+	};
+
 	gic: interrupt-controller@ffb71000 {
 		compatible = "arm,gic-400";
 		interrupt-controller;
@@ -700,7 +796,7 @@
 		#address-cells = <0>;
 
 		reg = <0x0 0xffb71000 0x0 0x1000>,
-		      <0x0 0xffb72000 0x0 0x1000>,
+		      <0x0 0xffb72000 0x0 0x2000>,
 		      <0x0 0xffb74000 0x0 0x2000>,
 		      <0x0 0xffb76000 0x0 0x2000>;
 		interrupts = <GIC_PPI 9
@@ -786,325 +882,345 @@
 
 		emmc {
 			emmc_clk: emmc-clk {
-				rockchip,pins = <2 4 RK_FUNC_2 &pcfg_pull_none>;
+				rockchip,pins = <2 RK_PA4 2 &pcfg_pull_none>;
 			};
 
 			emmc_cmd: emmc-cmd {
-				rockchip,pins = <1 26 RK_FUNC_2 &pcfg_pull_up>;
+				rockchip,pins = <1 RK_PD2 2 &pcfg_pull_up>;
 			};
 
 			emmc_pwr: emmc-pwr {
-				rockchip,pins = <1 27 RK_FUNC_2 &pcfg_pull_up>;
+				rockchip,pins = <1 RK_PD3 2 &pcfg_pull_up>;
 			};
 
 			emmc_bus1: emmc-bus1 {
-				rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up>;
+				rockchip,pins = <1 RK_PC2 2 &pcfg_pull_up>;
 			};
 
 			emmc_bus4: emmc-bus4 {
-				rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up>,
-						<1 19 RK_FUNC_2 &pcfg_pull_up>,
-						<1 20 RK_FUNC_2 &pcfg_pull_up>,
-						<1 21 RK_FUNC_2 &pcfg_pull_up>;
+				rockchip,pins = <1 RK_PC2 2 &pcfg_pull_up>,
+						<1 RK_PC3 2 &pcfg_pull_up>,
+						<1 RK_PC4 2 &pcfg_pull_up>,
+						<1 RK_PC5 2 &pcfg_pull_up>;
 			};
 
 			emmc_bus8: emmc-bus8 {
-				rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up>,
-						<1 19 RK_FUNC_2 &pcfg_pull_up>,
-						<1 20 RK_FUNC_2 &pcfg_pull_up>,
-						<1 21 RK_FUNC_2 &pcfg_pull_up>,
-						<1 22 RK_FUNC_2 &pcfg_pull_up>,
-						<1 23 RK_FUNC_2 &pcfg_pull_up>,
-						<1 24 RK_FUNC_2 &pcfg_pull_up>,
-						<1 25 RK_FUNC_2 &pcfg_pull_up>;
+				rockchip,pins = <1 RK_PC2 2 &pcfg_pull_up>,
+						<1 RK_PC3 2 &pcfg_pull_up>,
+						<1 RK_PC4 2 &pcfg_pull_up>,
+						<1 RK_PC5 2 &pcfg_pull_up>,
+						<1 RK_PC6 2 &pcfg_pull_up>,
+						<1 RK_PC7 2 &pcfg_pull_up>,
+						<1 RK_PD0 2 &pcfg_pull_up>,
+						<1 RK_PD1 2 &pcfg_pull_up>;
 			};
 		};
 
 		gmac {
 			rgmii_pins: rgmii-pins {
-				rockchip,pins =	<3 22 RK_FUNC_1 &pcfg_pull_none>,
-						<3 24 RK_FUNC_1 &pcfg_pull_none>,
-						<3 19 RK_FUNC_1 &pcfg_pull_none>,
-						<3 8 RK_FUNC_1 &pcfg_pull_none_12ma>,
-						<3 9 RK_FUNC_1 &pcfg_pull_none_12ma>,
-						<3 10 RK_FUNC_1 &pcfg_pull_none_12ma>,
-						<3 14 RK_FUNC_1 &pcfg_pull_none_12ma>,
-						<3 28 RK_FUNC_1 &pcfg_pull_none_12ma>,
-						<3 13 RK_FUNC_1 &pcfg_pull_none_12ma>,
-						<3 15 RK_FUNC_1 &pcfg_pull_none>,
-						<3 16 RK_FUNC_1 &pcfg_pull_none>,
-						<3 17 RK_FUNC_1 &pcfg_pull_none>,
-						<3 18 RK_FUNC_1 &pcfg_pull_none>,
-						<3 25 RK_FUNC_1 &pcfg_pull_none>,
-						<3 20 RK_FUNC_1 &pcfg_pull_none>;
+				rockchip,pins =	<3 RK_PC6 1 &pcfg_pull_none>,
+						<3 RK_PD0 1 &pcfg_pull_none>,
+						<3 RK_PC3 1 &pcfg_pull_none>,
+						<3 RK_PB0 1 &pcfg_pull_none_12ma>,
+						<3 RK_PB1 1 &pcfg_pull_none_12ma>,
+						<3 RK_PB2 1 &pcfg_pull_none_12ma>,
+						<3 RK_PB6 1 &pcfg_pull_none_12ma>,
+						<3 RK_PD4 1 &pcfg_pull_none_12ma>,
+						<3 RK_PB5 1 &pcfg_pull_none_12ma>,
+						<3 RK_PB7 1 &pcfg_pull_none>,
+						<3 RK_PC0 1 &pcfg_pull_none>,
+						<3 RK_PC1 1 &pcfg_pull_none>,
+						<3 RK_PC2 1 &pcfg_pull_none>,
+						<3 RK_PD1 1 &pcfg_pull_none>,
+						<3 RK_PC4 1 &pcfg_pull_none>;
 			};
 
 			rmii_pins: rmii-pins {
-				rockchip,pins =	<3 22 RK_FUNC_1 &pcfg_pull_none>,
-						<3 24 RK_FUNC_1 &pcfg_pull_none>,
-						<3 19 RK_FUNC_1 &pcfg_pull_none>,
-						<3 8 RK_FUNC_1 &pcfg_pull_none_12ma>,
-						<3 9 RK_FUNC_1 &pcfg_pull_none_12ma>,
-						<3 13 RK_FUNC_1 &pcfg_pull_none_12ma>,
-						<3 15 RK_FUNC_1 &pcfg_pull_none>,
-						<3 16 RK_FUNC_1 &pcfg_pull_none>,
-						<3 20 RK_FUNC_1 &pcfg_pull_none>,
-						<3 21 RK_FUNC_1 &pcfg_pull_none>;
+				rockchip,pins =	<3 RK_PC6 1 &pcfg_pull_none>,
+						<3 RK_PD0 1 &pcfg_pull_none>,
+						<3 RK_PC3 1 &pcfg_pull_none>,
+						<3 RK_PB0 1 &pcfg_pull_none_12ma>,
+						<3 RK_PB1 1 &pcfg_pull_none_12ma>,
+						<3 RK_PB5 1 &pcfg_pull_none_12ma>,
+						<3 RK_PB7 1 &pcfg_pull_none>,
+						<3 RK_PC0 1 &pcfg_pull_none>,
+						<3 RK_PC4 1 &pcfg_pull_none>,
+						<3 RK_PC5 1 &pcfg_pull_none>;
 			};
 		};
 
 		i2c0 {
 			i2c0_xfer: i2c0-xfer {
-				rockchip,pins = <0 6 RK_FUNC_1 &pcfg_pull_none>,
-						<0 7 RK_FUNC_1 &pcfg_pull_none>;
+				rockchip,pins = <0 RK_PA6 1 &pcfg_pull_none>,
+						<0 RK_PA7 1 &pcfg_pull_none>;
 			};
 		};
 
 		i2c1 {
 			i2c1_xfer: i2c1-xfer {
-				rockchip,pins = <2 21 RK_FUNC_1 &pcfg_pull_none>,
-						<2 22 RK_FUNC_1 &pcfg_pull_none>;
+				rockchip,pins = <2 RK_PC5 1 &pcfg_pull_none>,
+						<2 RK_PC6 1 &pcfg_pull_none>;
 			};
 		};
 
 		i2c2 {
 			i2c2_xfer: i2c2-xfer {
-				rockchip,pins = <0 9 RK_FUNC_2 &pcfg_pull_none>,
-						<3 31 RK_FUNC_2 &pcfg_pull_none>;
+				rockchip,pins = <0 RK_PB1 2 &pcfg_pull_none>,
+						<3 RK_PD7 2 &pcfg_pull_none>;
 			};
 		};
 
 		i2c3 {
 			i2c3_xfer: i2c3-xfer {
-				rockchip,pins = <1 16 RK_FUNC_1 &pcfg_pull_none>,
-						<1 17 RK_FUNC_1 &pcfg_pull_none>;
+				rockchip,pins = <1 RK_PC0 1 &pcfg_pull_none>,
+						<1 RK_PC1 1 &pcfg_pull_none>;
 			};
 		};
 
 		i2c4 {
 			i2c4_xfer: i2c4-xfer {
-				rockchip,pins = <3 24 RK_FUNC_2 &pcfg_pull_none>,
-						<3 25 RK_FUNC_2 &pcfg_pull_none>;
+				rockchip,pins = <3 RK_PD0 2 &pcfg_pull_none>,
+						<3 RK_PD1 2 &pcfg_pull_none>;
 			};
 		};
 
 		i2c5 {
 			i2c5_xfer: i2c5-xfer {
-				rockchip,pins = <3 26 RK_FUNC_2 &pcfg_pull_none>,
-						<3 27 RK_FUNC_2 &pcfg_pull_none>;
+				rockchip,pins = <3 RK_PD2 2 &pcfg_pull_none>,
+						<3 RK_PD3 2 &pcfg_pull_none>;
+			};
+		};
+
+		i2s {
+			i2s_8ch_bus: i2s-8ch-bus {
+				rockchip,pins = <2 RK_PB4 1 &pcfg_pull_none>,
+						<2 RK_PB5 1 &pcfg_pull_none>,
+						<2 RK_PB6 1 &pcfg_pull_none>,
+						<2 RK_PB7 1 &pcfg_pull_none>,
+						<2 RK_PC0 1 &pcfg_pull_none>,
+						<2 RK_PC1 1 &pcfg_pull_none>,
+						<2 RK_PC2 1 &pcfg_pull_none>,
+						<2 RK_PC3 1 &pcfg_pull_none>,
+						<2 RK_PC4 1 &pcfg_pull_none>;
 			};
 		};
 
 		pwm0 {
 			pwm0_pin: pwm0-pin {
-				rockchip,pins = <3 8 RK_FUNC_2 &pcfg_pull_none>;
+				rockchip,pins = <3 RK_PB0 2 &pcfg_pull_none>;
 			};
 		};
 
 		pwm1 {
 			pwm1_pin: pwm1-pin {
-				rockchip,pins = <0 8 RK_FUNC_2 &pcfg_pull_none>;
+				rockchip,pins = <0 RK_PB0 2 &pcfg_pull_none>;
 			};
 		};
 
 		pwm3 {
 			pwm3_pin: pwm3-pin {
-				rockchip,pins = <3 29 RK_FUNC_3 &pcfg_pull_none>;
+				rockchip,pins = <3 RK_PD5 3 &pcfg_pull_none>;
 			};
 		};
 
 		sdio0 {
 			sdio0_bus1: sdio0-bus1 {
-				rockchip,pins = <2 28 RK_FUNC_1 &pcfg_pull_up>;
+				rockchip,pins = <2 RK_PD4 1 &pcfg_pull_up>;
 			};
 
 			sdio0_bus4: sdio0-bus4 {
-				rockchip,pins = <2 28 RK_FUNC_1 &pcfg_pull_up>,
-						<2 29 RK_FUNC_1 &pcfg_pull_up>,
-						<2 30 RK_FUNC_1 &pcfg_pull_up>,
-						<2 31 RK_FUNC_1 &pcfg_pull_up>;
+				rockchip,pins = <2 RK_PD4 1 &pcfg_pull_up>,
+						<2 RK_PD5 1 &pcfg_pull_up>,
+						<2 RK_PD6 1 &pcfg_pull_up>,
+						<2 RK_PD7 1 &pcfg_pull_up>;
 			};
 
 			sdio0_cmd: sdio0-cmd {
-				rockchip,pins = <3 0 RK_FUNC_1 &pcfg_pull_up>;
+				rockchip,pins = <3 RK_PA0 1 &pcfg_pull_up>;
 			};
 
 			sdio0_clk: sdio0-clk {
-				rockchip,pins = <3 1 RK_FUNC_1 &pcfg_pull_none>;
+				rockchip,pins = <3 RK_PA1 1 &pcfg_pull_none>;
 			};
 
 			sdio0_cd: sdio0-cd {
-				rockchip,pins = <3 2 RK_FUNC_1 &pcfg_pull_up>;
+				rockchip,pins = <3 RK_PA2 1 &pcfg_pull_up>;
 			};
 
 			sdio0_wp: sdio0-wp {
-				rockchip,pins = <3 3 RK_FUNC_1 &pcfg_pull_up>;
+				rockchip,pins = <3 RK_PA3 1 &pcfg_pull_up>;
 			};
 
 			sdio0_pwr: sdio0-pwr {
-				rockchip,pins = <3 4 RK_FUNC_1 &pcfg_pull_up>;
+				rockchip,pins = <3 RK_PA4 1 &pcfg_pull_up>;
 			};
 
 			sdio0_bkpwr: sdio0-bkpwr {
-				rockchip,pins = <3 5 RK_FUNC_1 &pcfg_pull_up>;
+				rockchip,pins = <3 RK_PA5 1 &pcfg_pull_up>;
 			};
 
 			sdio0_int: sdio0-int {
-				rockchip,pins = <3 6 RK_FUNC_1 &pcfg_pull_up>;
+				rockchip,pins = <3 RK_PA6 1 &pcfg_pull_up>;
 			};
 		};
 
 		sdmmc {
 			sdmmc_clk: sdmmc-clk {
-				rockchip,pins = <2 9 RK_FUNC_1 &pcfg_pull_none>;
+				rockchip,pins = <2 RK_PB1 1 &pcfg_pull_none>;
 			};
 
 			sdmmc_cmd: sdmmc-cmd {
-				rockchip,pins = <2 10 RK_FUNC_1 &pcfg_pull_up>;
+				rockchip,pins = <2 RK_PB2 1 &pcfg_pull_up>;
 			};
 
 			sdmmc_cd: sdmmc-cd {
-				rockchip,pins = <2 11 RK_FUNC_1 &pcfg_pull_up>;
+				rockchip,pins = <2 RK_PB3 1 &pcfg_pull_up>;
 			};
 
 			sdmmc_bus1: sdmmc-bus1 {
-				rockchip,pins = <2 5 RK_FUNC_1 &pcfg_pull_up>;
+				rockchip,pins = <2 RK_PA5 1 &pcfg_pull_up>;
 			};
 
 			sdmmc_bus4: sdmmc-bus4 {
-				rockchip,pins = <2 5 RK_FUNC_1 &pcfg_pull_up>,
-						<2 6 RK_FUNC_1 &pcfg_pull_up>,
-						<2 7 RK_FUNC_1 &pcfg_pull_up>,
-						<2 8 RK_FUNC_1 &pcfg_pull_up>;
+				rockchip,pins = <2 RK_PA5 1 &pcfg_pull_up>,
+						<2 RK_PA6 1 &pcfg_pull_up>,
+						<2 RK_PA7 1 &pcfg_pull_up>,
+						<2 RK_PB0 1 &pcfg_pull_up>;
+			};
+		};
+
+		spdif {
+			spdif_tx: spdif-tx {
+				rockchip,pins =	<2 RK_PC7 1 &pcfg_pull_none>;
 			};
 		};
 
 		spi0 {
 			spi0_clk: spi0-clk {
-				rockchip,pins = <1 29 RK_FUNC_2 &pcfg_pull_up>;
+				rockchip,pins = <1 RK_PD5 2 &pcfg_pull_up>;
 			};
 			spi0_cs0: spi0-cs0 {
-				rockchip,pins = <1 24 RK_FUNC_3 &pcfg_pull_up>;
+				rockchip,pins = <1 RK_PD0 3 &pcfg_pull_up>;
 			};
 			spi0_cs1: spi0-cs1 {
-				rockchip,pins = <1 25 RK_FUNC_3 &pcfg_pull_up>;
+				rockchip,pins = <1 RK_PD1 3 &pcfg_pull_up>;
 			};
 			spi0_tx: spi0-tx {
-				rockchip,pins = <1 23 RK_FUNC_3 &pcfg_pull_up>;
+				rockchip,pins = <1 RK_PC7 3 &pcfg_pull_up>;
 			};
 			spi0_rx: spi0-rx {
-				rockchip,pins = <1 22 RK_FUNC_3 &pcfg_pull_up>;
+				rockchip,pins = <1 RK_PC6 3 &pcfg_pull_up>;
 			};
 		};
 
 		spi1 {
 			spi1_clk: spi1-clk {
-				rockchip,pins = <1 14 RK_FUNC_2 &pcfg_pull_up>;
+				rockchip,pins = <1 RK_PB6 2 &pcfg_pull_up>;
 			};
 			spi1_cs0: spi1-cs0 {
-				rockchip,pins = <1 15 RK_FUNC_2 &pcfg_pull_up>;
+				rockchip,pins = <1 RK_PB7 2 &pcfg_pull_up>;
 			};
 			spi1_cs1: spi1-cs1 {
-				rockchip,pins = <3 28 RK_FUNC_2 &pcfg_pull_up>;
+				rockchip,pins = <3 RK_PD4 2 &pcfg_pull_up>;
 			};
 			spi1_rx: spi1-rx {
-				rockchip,pins = <1 16 RK_FUNC_2 &pcfg_pull_up>;
+				rockchip,pins = <1 RK_PC0 2 &pcfg_pull_up>;
 			};
 			spi1_tx: spi1-tx {
-				rockchip,pins = <1 17 RK_FUNC_2 &pcfg_pull_up>;
+				rockchip,pins = <1 RK_PC1 2 &pcfg_pull_up>;
 			};
 		};
 
 		spi2 {
 			spi2_clk: spi2-clk {
-				rockchip,pins = <0 12 RK_FUNC_2 &pcfg_pull_up>;
+				rockchip,pins = <0 RK_PB4 2 &pcfg_pull_up>;
 			};
 			spi2_cs0: spi2-cs0 {
-				rockchip,pins = <0 13 RK_FUNC_2 &pcfg_pull_up>;
+				rockchip,pins = <0 RK_PB5 2 &pcfg_pull_up>;
 			};
 			spi2_rx: spi2-rx {
-				rockchip,pins = <0 10 RK_FUNC_2 &pcfg_pull_up>;
+				rockchip,pins = <0 RK_PB2 2 &pcfg_pull_up>;
 			};
 			spi2_tx: spi2-tx {
-				rockchip,pins = <0 11 RK_FUNC_2 &pcfg_pull_up>;
+				rockchip,pins = <0 RK_PB3 2 &pcfg_pull_up>;
 			};
 		};
 
 		tsadc {
-			otp_gpio: otp-gpio {
-				rockchip,pins = <0 3 RK_FUNC_GPIO &pcfg_pull_none>;
+			otp_pin: otp-pin {
+				rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
 			};
 
 			otp_out: otp-out {
-				rockchip,pins = <0 3 RK_FUNC_1 &pcfg_pull_none>;
+				rockchip,pins = <0 RK_PA3 1 &pcfg_pull_none>;
 			};
 		};
 
 		uart0 {
 			uart0_xfer: uart0-xfer {
-				rockchip,pins = <2 24 RK_FUNC_1 &pcfg_pull_up>,
-						<2 25 RK_FUNC_1 &pcfg_pull_none>;
+				rockchip,pins = <2 RK_PD0 1 &pcfg_pull_up>,
+						<2 RK_PD1 1 &pcfg_pull_none>;
 			};
 
 			uart0_cts: uart0-cts {
-				rockchip,pins = <2 26 RK_FUNC_1 &pcfg_pull_none>;
+				rockchip,pins = <2 RK_PD2 1 &pcfg_pull_none>;
 			};
 
 			uart0_rts: uart0-rts {
-				rockchip,pins = <2 27 RK_FUNC_1 &pcfg_pull_none>;
+				rockchip,pins = <2 RK_PD3 1 &pcfg_pull_none>;
 			};
 		};
 
 		uart1 {
 			uart1_xfer: uart1-xfer {
-				rockchip,pins = <0 20 RK_FUNC_3 &pcfg_pull_up>,
-						<0 21 RK_FUNC_3 &pcfg_pull_none>;
+				rockchip,pins = <0 RK_PC4 3 &pcfg_pull_up>,
+						<0 RK_PC5 3 &pcfg_pull_none>;
 			};
 
 			uart1_cts: uart1-cts {
-				rockchip,pins = <0 22 RK_FUNC_3 &pcfg_pull_none>;
+				rockchip,pins = <0 RK_PC6 3 &pcfg_pull_none>;
 			};
 
 			uart1_rts: uart1-rts {
-				rockchip,pins = <0 23 RK_FUNC_3 &pcfg_pull_none>;
+				rockchip,pins = <0 RK_PC7 3 &pcfg_pull_none>;
 			};
 		};
 
 		uart2 {
 			uart2_xfer: uart2-xfer {
-				rockchip,pins = <2 6 RK_FUNC_2 &pcfg_pull_up>,
-						<2 5 RK_FUNC_2 &pcfg_pull_none>;
+				rockchip,pins = <2 RK_PA6 2 &pcfg_pull_up>,
+						<2 RK_PA5 2 &pcfg_pull_none>;
 			};
 			/* no rts / cts for uart2 */
 		};
 
 		uart3 {
 			uart3_xfer: uart3-xfer {
-				rockchip,pins = <3 29 RK_FUNC_2 &pcfg_pull_up>,
-						<3 30 RK_FUNC_3 &pcfg_pull_none>;
+				rockchip,pins = <3 RK_PD5 2 &pcfg_pull_up>,
+						<3 RK_PD6 3 &pcfg_pull_none>;
 			};
 
 			uart3_cts: uart3-cts {
-				rockchip,pins = <3 16 RK_FUNC_2 &pcfg_pull_none>;
+				rockchip,pins = <3 RK_PC0 2 &pcfg_pull_none>;
 			};
 
 			uart3_rts: uart3-rts {
-				rockchip,pins = <3 17 RK_FUNC_2 &pcfg_pull_none>;
+				rockchip,pins = <3 RK_PC1 2 &pcfg_pull_none>;
 			};
 		};
 
 		uart4 {
 			uart4_xfer: uart4-xfer {
-				rockchip,pins = <0 27 RK_FUNC_3 &pcfg_pull_up>,
-						<0 26 RK_FUNC_3 &pcfg_pull_none>;
+				rockchip,pins = <0 RK_PD3 3 &pcfg_pull_up>,
+						<0 RK_PD2 3 &pcfg_pull_none>;
 			};
 
 			uart4_cts: uart4-cts {
-				rockchip,pins = <0 24 RK_FUNC_3 &pcfg_pull_none>;
+				rockchip,pins = <0 RK_PD0 3 &pcfg_pull_none>;
 			};
 
 			uart4_rts: uart4-rts {
-				rockchip,pins = <0 25 RK_FUNC_3 &pcfg_pull_none>;
+				rockchip,pins = <0 RK_PD1 3 &pcfg_pull_none>;
 			};
 		};
 	};
diff --git a/arch/arm/dts/rk3399-nanopi-m4b-u-boot.dtsi b/arch/arm/dts/rk3399-nanopi-m4b-u-boot.dtsi
new file mode 100644
index 0000000..9c3c1ef
--- /dev/null
+++ b/arch/arm/dts/rk3399-nanopi-m4b-u-boot.dtsi
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021 Alexandre Vicenzi <linux@alxd.me>
+ */
+
+#include "rk3399-nanopi4-u-boot.dtsi"
+#include "rk3399-sdram-ddr3-1866.dtsi"
diff --git a/arch/arm/dts/rk3399-nanopi-m4b.dts b/arch/arm/dts/rk3399-nanopi-m4b.dts
new file mode 100644
index 0000000..72182c5
--- /dev/null
+++ b/arch/arm/dts/rk3399-nanopi-m4b.dts
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * FriendlyElec NanoPi M4B board device tree source
+ *
+ * Copyright (c) 2020 Chen-Yu Tsai <wens@csie.org>
+ */
+
+/dts-v1/;
+#include "rk3399-nanopi-m4.dts"
+
+/ {
+	model = "FriendlyElec NanoPi M4B";
+	compatible = "friendlyarm,nanopi-m4b", "rockchip,rk3399";
+
+	adc-keys {
+		compatible = "adc-keys";
+		io-channels = <&saradc 1>;
+		io-channel-names = "buttons";
+		keyup-threshold-microvolt = <1500000>;
+		poll-interval = <100>;
+
+		recovery {
+			label = "Recovery";
+			linux,code = <KEY_VENDOR>;
+			press-threshold-microvolt = <18000>;
+		};
+	};
+};
+
+/* No USB type-C PD power manager */
+/delete-node/ &fusb0;
+
+&i2c4 {
+	status = "disabled";
+};
+
+&u2phy0_host {
+	phy-supply = <&vcc5v0_usb2>;
+};
+
+&u2phy0_otg {
+	phy-supply = <&vbus_typec>;
+};
+
+&u2phy1_otg {
+	phy-supply = <&vcc5v0_usb1>;
+};
+
+&vbus_typec {
+	enable-active-high;
+	gpios = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>;
+};
diff --git a/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi b/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi
new file mode 100644
index 0000000..cd16425
--- /dev/null
+++ b/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * RK3399-based FriendlyElec boards device tree source
+ *
+ * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * Copyright (c) 2018 FriendlyElec Computer Tech. Co., Ltd.
+ * (http://www.friendlyarm.com)
+ *
+ * Copyright (c) 2018 Collabora Ltd.
+ * Copyright (c) 2019 Arm Ltd.
+ * Copyright (C) 2020 Xiaobo <peterwillcn@gmail.com>
+ */
+
+#include "rk3399-nanopi4-u-boot.dtsi"
+#include "rk3399-sdram-lpddr4-100.dtsi"
diff --git a/arch/arm/dts/rk3399-nanopi-r4s.dts b/arch/arm/dts/rk3399-nanopi-r4s.dts
new file mode 100644
index 0000000..6f2cf17
--- /dev/null
+++ b/arch/arm/dts/rk3399-nanopi-r4s.dts
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * Copyright (c) 2018 FriendlyElec Computer Tech. Co., Ltd.
+ * (http://www.friendlyarm.com)
+ *
+ * Copyright (c) 2018 Collabora Ltd.
+ * Copyright (c) 2019 Arm Ltd.
+ * Copyright (C) 2020 Xiaobo <peterwillcn@gmail.com>
+ */
+
+/dts-v1/;
+#include "rk3399-nanopi4.dtsi"
+
+/ {
+	model = "FriendlyElec NanoPi R4S";
+	compatible = "friendlyarm,nanopi-r4s", "rockchip,rk3399";
+
+	aliases {
+		ethernet1 = &r8169;
+	};
+
+	vdd_5v: vdd-5v {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_5v";
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	fan: pwm-fan {
+		compatible = "pwm-fan";
+		cooling-levels = <0 12 18 255>;
+		#cooling-cells = <2>;
+		fan-supply = <&vdd_5v>;
+		pwms = <&pwm1 0 50000 0>;
+	};
+};
+
+&cpu_thermal {
+	trips {
+		cpu_warm: cpu_warm {
+			temperature = <55000>;
+			hysteresis = <2000>;
+			type = "active";
+		};
+
+		cpu_hot: cpu_hot {
+			temperature = <65000>;
+			hysteresis = <2000>;
+			type = "active";
+		};
+	};
+
+	cooling-maps {
+		map2 {
+			trip = <&cpu_warm>;
+			cooling-device = <&fan THERMAL_NO_LIMIT 1>;
+		};
+
+		map3 {
+			trip = <&cpu_hot>;
+			cooling-device = <&fan 2 THERMAL_NO_LIMIT>;
+		};
+	};
+};
+
+&emmc_phy {
+	status = "disabled";
+};
+
+&fusb0 {
+	status = "disabled";
+};
+
+&leds {
+	lan_led: led-1 {
+		gpios = <&gpio1 RK_PA1 GPIO_ACTIVE_HIGH>;
+		label = "nanopi-r4s:green:lan";
+	};
+
+	wan_led: led-2 {
+		gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>;
+		label = "nanopi-r4s:green:wan";
+	};
+};
+
+&leds_gpio {
+	rockchip,pins =
+		<0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>,
+		<1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>,
+		<1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>;
+};
+
+&pcie0 {
+	max-link-speed = <1>;
+	num-lanes = <1>;
+	vpcie3v3-supply = <&vcc3v3_sys>;
+
+	pcie@0 {
+		reg = <0x00000000 0 0 0 0>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+
+		r8169: pcie@0,0 {
+			reg = <0x000000 0 0 0 0>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+		};
+	};
+};
+
+&sdhci {
+	status = "disabled";
+};
+
+&sdio0 {
+	status = "disabled";
+};
+
+&sdmmc {
+	host-index-min = <1>;
+};
+
+&u2phy0_host {
+	phy-supply = <&vdd_5v>;
+};
+
+&u2phy1_host {
+	status = "disabled";
+};
+
+&usbdrd_dwc3_0 {
+	dr_mode = "host";
+};
+
+&vcc3v3_sys {
+	vin-supply = <&vcc5v0_sys>;
+};
diff --git a/arch/arm/dts/rk3399-puma-haikou-u-boot.dtsi b/arch/arm/dts/rk3399-puma-haikou-u-boot.dtsi
index e7a1aea..e0476ab 100644
--- a/arch/arm/dts/rk3399-puma-haikou-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-puma-haikou-u-boot.dtsi
@@ -48,6 +48,18 @@
 		regulator-min-microvolt = <1800000>;
 		regulator-max-microvolt = <1800000>;
 	};
+
+	vdd_log: vdd-log {
+		compatible = "pwm-regulator";
+		pwms = <&pwm2 0 25000 1>;
+		regulator-name = "vdd_log";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <800000>;
+		regulator-max-microvolt = <1400000>;
+		regulator-init-microvolt = <950000>;
+		vin-supply = <&vcc5v0_sys>;
+	};
 };
 
 &gpio1 {
diff --git a/arch/arm/dts/socfpga_soc64_fit-u-boot.dtsi b/arch/arm/dts/socfpga_soc64_fit-u-boot.dtsi
index 4b30473..84b91e8 100644
--- a/arch/arm/dts/socfpga_soc64_fit-u-boot.dtsi
+++ b/arch/arm/dts/socfpga_soc64_fit-u-boot.dtsi
@@ -29,10 +29,12 @@
 					arch = "arm64";
 					compression = "none";
 					load = <0x00200000>;
-
 					uboot_blob: blob-ext {
 						filename = "u-boot-nodtb.bin";
 					};
+					hash {
+						algo = "crc32";
+					};
 				};
 
 				atf {
@@ -43,20 +45,24 @@
 					compression = "none";
 					load = <0x00001000>;
 					entry = <0x00001000>;
-
 					atf_blob: blob-ext {
 						filename = "bl31.bin";
 					};
+					hash {
+						algo = "crc32";
+					};
 				};
 
 				fdt {
 					description = "U-Boot SoC64 flat device-tree";
 					type = "flat_dt";
 					compression = "none";
-
 					uboot_fdt_blob: blob-ext {
 						filename = "u-boot.dtb";
 					};
+					hash {
+						algo = "crc32";
+					};
 				};
 			};
 
@@ -67,6 +73,11 @@
 					firmware = "atf";
 					loadables = "uboot";
 					fdt = "fdt";
+					signature {
+						algo = "crc32";
+						key-name-hint = "dev";
+						sign-images = "atf", "fdt", "uboot";
+					};
 				};
 			};
 		};
@@ -87,10 +98,12 @@
 					compression = "none";
 					load = <0x4080000>;
 					entry = <0x4080000>;
-
 					kernel_blob: blob-ext {
 						filename = "Image";
 					};
+					hash {
+						algo = "crc32";
+					};
 				};
 
 				fdt {
@@ -98,10 +111,12 @@
 					type = "flat_dt";
 					arch = "arm64";
 					compression = "none";
-
 					kernel_fdt_blob: blob-ext {
 						filename = "linux.dtb";
 					};
+					hash {
+						algo = "crc32";
+					};
 				};
 			};
 
@@ -111,6 +126,11 @@
 					description = "Intel SoC64 FPGA";
 					kernel = "kernel";
 					fdt = "fdt";
+					signature {
+						algo = "crc32";
+						key-name-hint = "dev";
+						sign-images = "fdt", "kernel";
+					};
 				};
 			};
 		};
diff --git a/arch/arm/dts/zynq-zc702.dts b/arch/arm/dts/zynq-zc702.dts
index b043d34..e45eba3 100644
--- a/arch/arm/dts/zynq-zc702.dts
+++ b/arch/arm/dts/zynq-zc702.dts
@@ -51,7 +51,7 @@
 	leds {
 		compatible = "gpio-leds";
 
-		ds23 {
+		led-ds23 {
 			label = "ds23";
 			gpios = <&gpio0 10 0>;
 			linux,default-trigger = "heartbeat";
diff --git a/arch/arm/dts/zynq-zturn-common.dtsi b/arch/arm/dts/zynq-zturn-common.dtsi
index 1d7af02..486b6fa 100644
--- a/arch/arm/dts/zynq-zturn-common.dtsi
+++ b/arch/arm/dts/zynq-zturn-common.dtsi
@@ -112,7 +112,7 @@
 	};
 
 	accelerometer@53 {
-		compatible = "adi,adxl345", "adxl345", "adi,adxl34x", "adxl34x";
+		compatible = "adi,adxl345";
 		reg = <0x53>;
 		interrupt-parent = <&intc>;
 		interrupts = <0x0 0x1e 0x4>;
diff --git a/arch/arm/dts/zynq-zybo-z7.dts b/arch/arm/dts/zynq-zybo-z7.dts
index 3f8a3bf..116958e 100644
--- a/arch/arm/dts/zynq-zybo-z7.dts
+++ b/arch/arm/dts/zynq-zybo-z7.dts
@@ -31,7 +31,7 @@
 	gpio-leds {
 		compatible = "gpio-leds";
 
-		ld4 {
+		led-ld4 {
 			label = "zynq-zybo-z7:green:ld4";
 			gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
 		};
diff --git a/arch/arm/dts/zynqmp-clk-ccf.dtsi b/arch/arm/dts/zynqmp-clk-ccf.dtsi
index b02ef22..987792e 100644
--- a/arch/arm/dts/zynqmp-clk-ccf.dtsi
+++ b/arch/arm/dts/zynqmp-clk-ccf.dtsi
@@ -284,18 +284,16 @@
 	clocks = <&zynqmp_clk AMS_REF>;
 };
 
-&zynqmp_dpsub {
-	clocks = <&dp_aclk>, <&zynqmp_clk DP_AUDIO_REF>, <&zynqmp_clk DP_VIDEO_REF>;
+&zynqmp_pcap {
+	clocks = <&zynqmp_clk PCAP>;
 };
 
-&xlnx_dpdma {
+&zynqmp_dpdma {
 	clocks = <&zynqmp_clk DPDMA_REF>;
 };
 
-&zynqmp_dp_snd_codec0 {
-	clocks = <&zynqmp_clk DP_AUDIO_REF>;
-};
-
-&zynqmp_pcap {
-	clocks = <&zynqmp_clk PCAP>;
+&zynqmp_dpsub {
+	clocks = <&zynqmp_clk TOPSW_LSBUS>,
+		 <&zynqmp_clk DP_AUDIO_REF>,
+		 <&zynqmp_clk DP_VIDEO_REF>;
 };
diff --git a/arch/arm/dts/zynqmp-g-a2197-00-revA.dts b/arch/arm/dts/zynqmp-g-a2197-00-revA.dts
index 9468dc5..f94b797 100644
--- a/arch/arm/dts/zynqmp-g-a2197-00-revA.dts
+++ b/arch/arm/dts/zynqmp-g-a2197-00-revA.dts
@@ -88,9 +88,6 @@
 		reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
 /*		xlnx,phy-type = <PHY_TYPE_SGMII>; */
 	};
-/*	phy-names = "...";
-	phys = <&lane0 PHY_TYPE_SGMII ... >
-	Note: lane0 sgmii/lane1 usb3 */
 };
 
 &gpio {
diff --git a/arch/arm/dts/zynqmp-m-a2197-01-revA.dts b/arch/arm/dts/zynqmp-m-a2197-01-revA.dts
index 66ea02e..19e1ebd 100644
--- a/arch/arm/dts/zynqmp-m-a2197-01-revA.dts
+++ b/arch/arm/dts/zynqmp-m-a2197-01-revA.dts
@@ -118,9 +118,6 @@
 		reg = <0>;
 /*		xlnx,phy-type = <PHY_TYPE_SGMII>; */
 	};
-/*	phy-names = "...";
-	phys = <&lane0 PHY_TYPE_SGMII ... >
-	Note: lane0 sgmii/lane1 usb3 */
 };
 
 &gpio {
diff --git a/arch/arm/dts/zynqmp-mini-emmc0.dts b/arch/arm/dts/zynqmp-mini-emmc0.dts
index 2213bb2..8467dd8 100644
--- a/arch/arm/dts/zynqmp-mini-emmc0.dts
+++ b/arch/arm/dts/zynqmp-mini-emmc0.dts
@@ -51,6 +51,8 @@
 			u-boot,dm-pre-reloc;
 			compatible = "xlnx,zynqmp-8.9a", "arasan,sdhci-8.9a";
 			status = "disabled";
+			non-removable;
+			bus-width = <8>;
 			reg = <0x0 0xff160000 0x0 0x1000>;
 			clock-names = "clk_xin", "clk_ahb";
 			clocks = <&clk_xin &clk_xin>;
diff --git a/arch/arm/dts/zynqmp-mini-emmc1.dts b/arch/arm/dts/zynqmp-mini-emmc1.dts
index 0538da4..2afcc77 100644
--- a/arch/arm/dts/zynqmp-mini-emmc1.dts
+++ b/arch/arm/dts/zynqmp-mini-emmc1.dts
@@ -51,6 +51,8 @@
 			u-boot,dm-pre-reloc;
 			compatible = "xlnx,zynqmp-8.9a", "arasan,sdhci-8.9a";
 			status = "disabled";
+			non-removable;
+			bus-width = <8>;
 			reg = <0x0 0xff170000 0x0 0x1000>;
 			clock-names = "clk_xin", "clk_ahb";
 			clocks = <&clk_xin &clk_xin>;
diff --git a/arch/arm/dts/zynqmp-zc1232-revA.dts b/arch/arm/dts/zynqmp-zc1232-revA.dts
index afb3e96..ef7cf0a 100644
--- a/arch/arm/dts/zynqmp-zc1232-revA.dts
+++ b/arch/arm/dts/zynqmp-zc1232-revA.dts
@@ -78,8 +78,6 @@
 	ceva,p1-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
 	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
 	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
-	phy-names = "sata-phy";
-	phys = <&lane0 PHY_TYPE_SATA 0 0 125000000>, <&lane1 PHY_TYPE_SATA 1 1 125000000>;
 };
 
 &uart0 {
diff --git a/arch/arm/dts/zynqmp-zc1751-xm015-dc1.dts b/arch/arm/dts/zynqmp-zc1751-xm015-dc1.dts
index e2428ec..b8c5efb 100644
--- a/arch/arm/dts/zynqmp-zc1751-xm015-dc1.dts
+++ b/arch/arm/dts/zynqmp-zc1751-xm015-dc1.dts
@@ -175,26 +175,11 @@
 	dr_mode = "host";
 };
 
+&zynqmp_dpdma {
+	status = "okay";
+};
+
 &zynqmp_dpsub {
 	status = "okay";
 };
 
-&zynqmp_dp_snd_pcm0 {
-	status = "okay";
-};
-
-&zynqmp_dp_snd_pcm1 {
-	status = "okay";
-};
-
-&zynqmp_dp_snd_card0 {
-	status = "okay";
-};
-
-&zynqmp_dp_snd_codec0 {
-	status = "okay";
-};
-
-&xlnx_dpdma {
-	status = "okay";
-};
diff --git a/arch/arm/dts/zynqmp-zc1751-xm016-dc2.dts b/arch/arm/dts/zynqmp-zc1751-xm016-dc2.dts
index 92d938d..3204456 100644
--- a/arch/arm/dts/zynqmp-zc1751-xm016-dc2.dts
+++ b/arch/arm/dts/zynqmp-zc1751-xm016-dc2.dts
@@ -124,6 +124,10 @@
 		reg = <0x0>;
 		#address-cells = <0x2>;
 		#size-cells = <0x1>;
+		nand-ecc-mode = "soft";
+		nand-ecc-algo = "bch";
+		nand-rb = <0>;
+		label = "main-storage-0";
 
 		partition@0 {	/* for testing purpose */
 			label = "nand-fsbl-uboot";
@@ -154,6 +158,10 @@
 		reg = <0x1>;
 		#address-cells = <0x2>;
 		#size-cells = <0x1>;
+		nand-ecc-mode = "soft";
+		nand-ecc-algo = "bch";
+		nand-rb = <0>;
+		label = "main-storage-1";
 
 		partition@0 {	/* for testing purpose */
 			label = "nand1-fsbl-uboot";
diff --git a/arch/arm/dts/zynqmp-zc1751-xm018-dc4.dts b/arch/arm/dts/zynqmp-zc1751-xm018-dc4.dts
index 9b38b8b..aadda17 100644
--- a/arch/arm/dts/zynqmp-zc1751-xm018-dc4.dts
+++ b/arch/arm/dts/zynqmp-zc1751-xm018-dc4.dts
@@ -119,7 +119,7 @@
 	status = "okay";
 };
 
-&xlnx_dpdma {
+&zynqmp_dpdma {
 	status = "okay";
 };
 
diff --git a/arch/arm/dts/zynqmp-zcu100-revC.dts b/arch/arm/dts/zynqmp-zcu100-revC.dts
index d6c914c..bbcc69c 100644
--- a/arch/arm/dts/zynqmp-zcu100-revC.dts
+++ b/arch/arm/dts/zynqmp-zcu100-revC.dts
@@ -69,27 +69,27 @@
 
 	leds {
 		compatible = "gpio-leds";
-		ds2 {
+		led-ds2 {
 			label = "ds2";
 			gpios = <&gpio 20 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "heartbeat";
 		};
 
-		ds3 {
+		led-ds3 {
 			label = "ds3";
 			gpios = <&gpio 19 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "phy0tx"; /* WLAN tx */
 			default-state = "off";
 		};
 
-		ds4 {
+		led-ds4 {
 			label = "ds4";
 			gpios = <&gpio 18 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "phy0rx"; /* WLAN rx */
 			default-state = "off";
 		};
 
-		ds5 {
+		led-ds5 {
 			label = "ds5";
 			gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "bluetooth-power";
@@ -130,6 +130,18 @@
 		compatible = "iio-hwmon";
 		io-channels = <&u35 0>, <&u35 1>, <&u35 2>, <&u35 3>;
 	};
+
+	si5335a_0: clk26 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+	};
+
+	si5335a_1: clk27 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <27000000>;
+	};
 };
 
 &dcc {
@@ -212,7 +224,7 @@
 				compatible = "ti,tps65086";
 				reg = <0x5e>;
 				interrupt-parent = <&gpio>;
-				interrupts = <77 GPIO_ACTIVE_LOW>;
+				interrupts = <77 IRQ_TYPE_LEVEL_LOW>;
 				#gpio-cells = <2>;
 				gpio-controller;
 			};
@@ -250,6 +262,13 @@
 	};
 };
 
+&psgtr {
+	status = "okay";
+	/* usb3, dps */
+	clocks = <&si5335a_0>, <&si5335a_1>;
+	clock-names = "ref0", "ref1";
+};
+
 &rtc {
 	status = "okay";
 };
@@ -281,10 +300,6 @@
 	};
 };
 
-&serdes {
-	status = "okay";
-};
-
 &spi0 { /* Low Speed connector */
 	status = "okay";
 	label = "LS-SPI0";
@@ -318,8 +333,6 @@
 &dwc3_0 {
 	status = "okay";
 	dr_mode = "peripheral";
-	phy-names = "usb3-phy";
-	phys = <&lane2 PHY_TYPE_USB3 0 0 26000000>;
 	maximum-speed = "super-speed";
 };
 
@@ -331,8 +344,6 @@
 &dwc3_1 {
 	status = "okay";
 	dr_mode = "host";
-	phy-names = "usb3-phy";
-	phys = <&lane3 PHY_TYPE_USB3 1 0 26000000>;
 	maximum-speed = "super-speed";
 };
 
@@ -347,3 +358,14 @@
 &ams_ps {
 	status = "okay";
 };
+
+&zynqmp_dpdma {
+	status = "okay";
+};
+
+&zynqmp_dpsub {
+	status = "okay";
+	phy-names = "dp-phy0", "dp-phy1";
+	phys = <&psgtr 1 PHY_TYPE_DP 0 1>,
+	       <&psgtr 0 PHY_TYPE_DP 1 1>;
+};
diff --git a/arch/arm/dts/zynqmp-zcu102-revA.dts b/arch/arm/dts/zynqmp-zcu102-revA.dts
index ed036e6..9323b8d 100644
--- a/arch/arm/dts/zynqmp-zcu102-revA.dts
+++ b/arch/arm/dts/zynqmp-zcu102-revA.dts
@@ -137,6 +137,19 @@
 		compatible = "iio-hwmon";
 		io-channels = <&u75 0>, <&u75 1>, <&u75 2>, <&u75 3>;
 	};
+
+	/* 48MHz reference crystal */
+	ref48: ref48M {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <48000000>;
+	};
+
+	refhdmi: refhdmi {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <114285000>;
+	};
 };
 
 &can1 {
@@ -213,25 +226,25 @@
 		gpio-line-names = "PS_GTR_LAN_SEL0", "PS_GTR_LAN_SEL1", "PS_GTR_LAN_SEL2", "PS_GTR_LAN_SEL3",
 				"PCI_CLK_DIR_SEL", "IIC_MUX_RESET_B", "GEM3_EXP_RESET_B",
 				"", "", "", "", "", "", "", "", "";
-		gtr-sel0 {
+		gtr-sel0-hog {
 			gpio-hog;
 			gpios = <0 0>;
 			output-low; /* PCIE = 0, DP = 1 */
 			line-name = "sel0";
 		};
-		gtr-sel1 {
+		gtr-sel1-hog {
 			gpio-hog;
 			gpios = <1 0>;
 			output-high; /* PCIE = 0, DP = 1 */
 			line-name = "sel1";
 		};
-		gtr-sel2 {
+		gtr-sel2-hog {
 			gpio-hog;
 			gpios = <2 0>;
 			output-high; /* PCIE = 0, USB0 = 1 */
 			line-name = "sel2";
 		};
-		gtr-sel3 {
+		gtr-sel3-hog {
 			gpio-hog;
 			gpios = <3 0>;
 			output-high; /* PCIE = 0, SATA = 1 */
@@ -494,8 +507,54 @@
 			si5341: clock-generator@36 { /* SI5341 - u69 */
 				compatible = "silabs,si5341";
 				reg = <0x36>;
-			};
+				#clock-cells = <2>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&ref48>;
+				clock-names = "xtal";
+				clock-output-names = "si5341";
 
+				si5341_0: out@0 {
+					/* refclk0 for PS-GT, used for DP */
+					reg = <0>;
+					always-on;
+				};
+				si5341_2: out@2 {
+					/* refclk2 for PS-GT, used for USB3 */
+					reg = <2>;
+					always-on;
+				};
+				si5341_3: out@3 {
+					/* refclk3 for PS-GT, used for SATA */
+					reg = <3>;
+					always-on;
+				};
+				si5341_4: out@4 {
+					/* refclk4 for PS-GT, used for PCIE slot */
+					reg = <4>;
+					always-on;
+				};
+				si5341_5: out@5 {
+					/* refclk5 for PS-GT, used for PCIE */
+					reg = <5>;
+					always-on;
+				};
+				si5341_6: out@6 {
+					/* refclk6 PL CLK125 */
+					reg = <6>;
+					always-on;
+				};
+				si5341_7: out@7 {
+					/* refclk7 PL CLK74 */
+					reg = <7>;
+					always-on;
+				};
+				si5341_9: out@9 {
+					/* refclk9 used for PS_REF_CLK 33.3 MHz */
+					reg = <9>;
+					always-on;
+				};
+			};
 		};
 		i2c@2 {
 			#address-cells = <1>;
@@ -603,6 +662,13 @@
 	status = "okay";
 };
 
+&psgtr {
+	status = "okay";
+	/* pcie, sata, usb3, dp */
+	clocks = <&si5341 0 5>, <&si5341 0 3>, <&si5341 0 2>, <&si5341 0 0>;
+	clock-names = "ref0", "ref1", "ref2", "ref3";
+};
+
 &qspi {
 	status = "okay";
 	is-dual = <1>;
@@ -649,7 +715,7 @@
 	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
 	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
 	phy-names = "sata-phy";
-	phys = <&lane3 PHY_TYPE_SATA 1 1 125000000>;
+	phys = <&psgtr 3 PHY_TYPE_SATA 1 1>;
 };
 
 /* SD1 with level shifter */
@@ -663,10 +729,6 @@
 	xlnx,mio-bank = <1>;
 };
 
-&serdes {
-	status = "okay";
-};
-
 &uart0 {
 	status = "okay";
 };
@@ -684,8 +746,6 @@
 	status = "okay";
 	dr_mode = "host";
 	snps,usb3_lpm_capable;
-	phy-names = "usb3-phy";
-	phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
 	maximum-speed = "super-speed";
 };
 
@@ -705,26 +765,12 @@
 	status = "okay";
 };
 
+&zynqmp_dpdma {
+	status = "okay";
+};
+
 &zynqmp_dpsub {
 	status = "okay";
-};
-
-&zynqmp_dp_snd_codec0 {
-	status = "okay";
-};
-
-&zynqmp_dp_snd_pcm0 {
-	status = "okay";
-};
-
-&zynqmp_dp_snd_pcm1 {
-	status = "okay";
-};
-
-&zynqmp_dp_snd_card0 {
-	status = "okay";
-};
-
-&xlnx_dpdma {
-	status = "okay";
+	phy-names = "dp-phy0";
+	phys = <&psgtr 1 PHY_TYPE_DP 0 3>;
 };
diff --git a/arch/arm/dts/zynqmp-zcu104-revA.dts b/arch/arm/dts/zynqmp-zcu104-revA.dts
index cb8ffdf..a95bd49 100644
--- a/arch/arm/dts/zynqmp-zcu104-revA.dts
+++ b/arch/arm/dts/zynqmp-zcu104-revA.dts
@@ -40,6 +40,24 @@
 		device_type = "memory";
 		reg = <0x0 0x0 0x0 0x80000000>;
 	};
+
+	clock_8t49n287_5: clk125 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <125000000>;
+	};
+
+	clock_8t49n287_2: clk26 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+	};
+
+	clock_8t49n287_3: clk27 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <27000000>;
+	};
 };
 
 &can1 {
@@ -226,6 +244,13 @@
 	};
 };
 
+&psgtr {
+	status = "okay";
+	/* nc, sata, usb3, dp */
+	clocks = <&clock_8t49n287_5>, <&clock_8t49n287_2>, <&clock_8t49n287_3>;
+	clock-names = "ref1", "ref2", "ref3";
+};
+
 &rtc {
 	status = "okay";
 };
@@ -242,7 +267,7 @@
 	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
 	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
 	phy-names = "sata-phy";
-	phys = <&lane3 PHY_TYPE_SATA 1 1 125000000>;
+	phys = <&psgtr 3 PHY_TYPE_SATA 1 1>;
 };
 
 /* SD1 with level shifter */
@@ -253,10 +278,6 @@
 	disable-wp;
 };
 
-&serdes {
-	status = "okay";
-};
-
 &uart0 {
 	status = "okay";
 };
@@ -274,8 +295,6 @@
 	status = "okay";
 	dr_mode = "host";
 	snps,usb3_lpm_capable;
-	phy-names = "usb3-phy";
-	phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
 	maximum-speed = "super-speed";
 };
 
@@ -294,3 +313,14 @@
 &ams_pl {
 	status = "okay";
 };
+
+&zynqmp_dpdma {
+	status = "okay";
+};
+
+&zynqmp_dpsub {
+	status = "okay";
+	phy-names = "dp-phy0", "dp-phy1";
+	phys = <&psgtr 1 PHY_TYPE_DP 0 3>,
+	       <&psgtr 0 PHY_TYPE_DP 1 3>;
+};
diff --git a/arch/arm/dts/zynqmp-zcu104-revC.dts b/arch/arm/dts/zynqmp-zcu104-revC.dts
index e203280..8f30a28 100644
--- a/arch/arm/dts/zynqmp-zcu104-revC.dts
+++ b/arch/arm/dts/zynqmp-zcu104-revC.dts
@@ -46,6 +46,24 @@
 		compatible = "iio-hwmon";
 		io-channels = <&u183 0>, <&u183 1>, <&u183 2>, <&u183 3>;
 	};
+
+	clock_8t49n287_5: clk125 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <125000000>;
+	};
+
+	clock_8t49n287_2: clk26 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+	};
+
+	clock_8t49n287_3: clk27 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <27000000>;
+	};
 };
 
 &can1 {
@@ -243,6 +261,13 @@
 	status = "okay";
 };
 
+&psgtr {
+	status = "okay";
+	/* nc, sata, usb3, dp */
+	clocks = <&clock_8t49n287_5>, <&clock_8t49n287_2>, <&clock_8t49n287_3>;
+	clock-names = "ref1", "ref2", "ref3";
+};
+
 &sata {
 	status = "okay";
 	/* SATA OOB timing settings */
@@ -255,7 +280,7 @@
 	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
 	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
 	phy-names = "sata-phy";
-	phys = <&lane3 PHY_TYPE_SATA 1 1 125000000>;
+	phys = <&psgtr 3 PHY_TYPE_SATA 1 1>;
 };
 
 /* SD1 with level shifter */
@@ -266,10 +291,6 @@
 	disable-wp;
 };
 
-&serdes {
-	status = "okay";
-};
-
 &uart0 {
 	status = "okay";
 };
@@ -287,8 +308,6 @@
 	status = "okay";
 	dr_mode = "host";
 	snps,usb3_lpm_capable;
-	phy-names = "usb3-phy";
-	phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
 	maximum-speed = "super-speed";
 };
 
@@ -307,3 +326,14 @@
 &ams_pl {
 	status = "okay";
 };
+
+&zynqmp_dpdma {
+	status = "okay";
+};
+
+&zynqmp_dpsub {
+	status = "okay";
+	phy-names = "dp-phy0", "dp-phy1";
+	phys = <&psgtr 1 PHY_TYPE_DP 0 3>,
+	       <&psgtr 0 PHY_TYPE_DP 1 3>;
+};
diff --git a/arch/arm/dts/zynqmp-zcu106-revA.dts b/arch/arm/dts/zynqmp-zcu106-revA.dts
index 1dff845..971f76f 100644
--- a/arch/arm/dts/zynqmp-zcu106-revA.dts
+++ b/arch/arm/dts/zynqmp-zcu106-revA.dts
@@ -137,6 +137,19 @@
 		compatible = "iio-hwmon";
 		io-channels = <&u75 0>, <&u75 1>, <&u75 2>, <&u75 3>;
 	};
+
+	/* 48MHz reference crystal */
+	ref48: ref48M {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <48000000>;
+	};
+
+	refhdmi: refhdmi {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <114285000>;
+	};
 };
 
 &can1 {
@@ -147,6 +160,18 @@
 	status = "okay";
 };
 
+&zynqmp_dpdma {
+	status = "okay";
+};
+
+&zynqmp_dpsub {
+	status = "okay";
+	phy-names = "dp-phy0", "dp-phy1";
+	phys = <&psgtr 1 PHY_TYPE_DP 0 3>,
+	       <&psgtr 0 PHY_TYPE_DP 1 3>;
+};
+
+/* fpd_dma clk 667MHz, lpd_dma 500MHz */
 &fpd_dma_chan1 {
 	status = "okay";
 };
@@ -490,8 +515,45 @@
 			#size-cells = <0>;
 			reg = <1>;
 			si5341: clock-generator@36 { /* SI5341 - u69 */
-				compatible = "si5341";
+				compatible = "silabs,si5341";
 				reg = <0x36>;
+				#clock-cells = <2>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&ref48>;
+				clock-names = "xtal";
+				clock-output-names = "si5341";
+
+				si5341_0: out@0 {
+					/* refclk0 for PS-GT, used for DP */
+					reg = <0>;
+					always-on;
+				};
+				si5341_2: out@2 {
+					/* refclk2 for PS-GT, used for USB3 */
+					reg = <2>;
+					always-on;
+				};
+				si5341_3: out@3 {
+					/* refclk3 for PS-GT, used for SATA */
+					reg = <3>;
+					always-on;
+				};
+				si5341_6: out@6 {
+					/* refclk6 PL CLK125 */
+					reg = <6>;
+					always-on;
+				};
+				si5341_7: out@7 {
+					/* refclk7 PL CLK74 */
+					reg = <7>;
+					always-on;
+				};
+				si5341_9: out@9 {
+					/* refclk9 used for PS_REF_CLK 33.3 MHz */
+					reg = <9>;
+					always-on;
+				};
 			};
 
 		};
@@ -528,8 +590,23 @@
 			#size-cells = <0>;
 			reg = <4>;
 			si5328: clock-generator@69 {/* SI5328 - u20 */
-				compatible = "silabs,si5328";
 				reg = <0x69>;
+				/*
+				 * Chip has interrupt present connected to PL
+				 * interrupt-parent = <&>;
+				 * interrupts = <>;
+				 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				#clock-cells = <1>;
+				clocks = <&refhdmi>;
+				clock-names = "xtal";
+				clock-output-names = "si5328";
+
+				si5328_clk: clk0@0 {
+					reg = <0>;
+					clock-frequency = <27000000>;
+				};
 			};
 		};
 		i2c@5 {
@@ -601,6 +678,13 @@
 	};
 };
 
+&psgtr {
+	status = "okay";
+	/* nc, sata, usb3, dp */
+	clocks = <&si5341 0 3>, <&si5341 0 2>, <&si5341 0 0>;
+	clock-names = "ref1", "ref2", "ref3";
+};
+
 &qspi {
 	status = "okay";
 	is-dual = <1>;
@@ -647,7 +731,7 @@
 	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
 	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
 	phy-names = "sata-phy";
-	phys = <&lane3 PHY_TYPE_SATA 1 1 125000000>;
+	phys = <&psgtr 3 PHY_TYPE_SATA 1 1>;
 };
 
 /* SD1 with level shifter */
@@ -660,10 +744,6 @@
 	xlnx,mio-bank = <1>;
 };
 
-&serdes {
-	status = "okay";
-};
-
 &uart0 {
 	status = "okay";
 };
@@ -681,8 +761,6 @@
 	status = "okay";
 	dr_mode = "host";
 	snps,usb3_lpm_capable;
-	phy-names = "usb3-phy";
-	phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
 };
 
 &watchdog0 {
diff --git a/arch/arm/dts/zynqmp-zcu111-revA.dts b/arch/arm/dts/zynqmp-zcu111-revA.dts
index 82e6c8d..9e47008 100644
--- a/arch/arm/dts/zynqmp-zcu111-revA.dts
+++ b/arch/arm/dts/zynqmp-zcu111-revA.dts
@@ -121,6 +121,13 @@
 		compatible = "iio-hwmon";
 		io-channels = <&u79 0>, <&u79 1>, <&u79 2>, <&u79 3>;
 	};
+
+	/* 48MHz reference crystal */
+	ref48: ref48M {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <48000000>;
+	};
 };
 
 &dcc {
@@ -386,10 +393,46 @@
 			#size-cells = <0>;
 			reg = <1>;
 			si5341: clock-generator@36 { /* SI5341 - u46 */
-				compatible = "si5341";
+				compatible = "silabs,si5341";
 				reg = <0x36>;
-			};
+				#clock-cells = <2>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&ref48>;
+				clock-names = "xtal";
+				clock-output-names = "si5341";
 
+				si5341_0: out@0 {
+					/* refclk0 for PS-GT, used for DP */
+					reg = <0>;
+					always-on;
+				};
+				si5341_2: out@2 {
+					/* refclk2 for PS-GT, used for USB3 */
+					reg = <2>;
+					always-on;
+				};
+				si5341_3: out@3 {
+					/* refclk3 for PS-GT, used for SATA */
+					reg = <3>;
+					always-on;
+				};
+				si5341_5: out@5 {
+					/* refclk5 PL CLK100 */
+					reg = <5>;
+					always-on;
+				};
+				si5341_6: out@6 {
+					/* refclk6 PL CLK125 */
+					reg = <6>;
+					always-on;
+				};
+				si5341_9: out@9 {
+					/* refclk9 used for PS_REF_CLK 33.3 MHz */
+					reg = <9>;
+					always-on;
+				};
+			};
 		};
 		i2c@2 {
 			#address-cells = <1>;
@@ -423,8 +466,8 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <4>;
-			si5328: clock-generator@69 { /* SI5328 - u48 */
-				compatible = "silabs,si5328";
+			si5382: clock-generator@69 { /* SI5382 - u48 */
+				compatible = "silabs,si5382";
 				reg = <0x69>;
 			};
 		};
@@ -511,6 +554,13 @@
 	};
 };
 
+&psgtr {
+	status = "okay";
+	/* nc, sata, usb3, dp */
+	clocks = <&si5341 0 3>, <&si5341 0 2>, <&si5341 0 0>;
+	clock-names = "ref1", "ref2", "ref3";
+};
+
 &qspi {
 	status = "okay";
 	is-dual = <1>;
@@ -557,7 +607,7 @@
 	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
 	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
 	phy-names = "sata-phy";
-	phys = <&lane3 PHY_TYPE_SATA 1 3 125000000>;
+	phys = <&psgtr 3 PHY_TYPE_SATA 1 1>;
 };
 
 /* SD1 with level shifter */
@@ -571,10 +621,6 @@
 	xlnx,mio-bank = <1>;
 };
 
-&serdes {
-	status = "okay";
-};
-
 &uart0 {
 	status = "okay";
 };
@@ -582,12 +628,16 @@
 /* ULPI SMSC USB3320 */
 &usb0 {
 	status = "okay";
+	dr_mode = "host";
 };
 
-&dwc3_0 {
+&zynqmp_dpdma {
 	status = "okay";
-	dr_mode = "host";
-	snps,usb3_lpm_capable;
-	phy-names = "usb3-phy";
-	phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
+};
+
+&zynqmp_dpsub {
+	status = "okay";
+	phy-names = "dp-phy0", "dp-phy1";
+	phys = <&psgtr 1 PHY_TYPE_DP 0 1>,
+	       <&psgtr 0 PHY_TYPE_DP 1 1>;
 };
diff --git a/arch/arm/dts/zynqmp-zcu208-revA.dts b/arch/arm/dts/zynqmp-zcu208-revA.dts
index 1242193..0e114cd 100644
--- a/arch/arm/dts/zynqmp-zcu208-revA.dts
+++ b/arch/arm/dts/zynqmp-zcu208-revA.dts
@@ -120,6 +120,13 @@
 		compatible = "iio-hwmon";
 		io-channels = <&dac_avcc 0>, <&dac_avcc 1>, <&dac_avcc 2>, <&dac_avcc 3>;
 	};
+
+	/* 48MHz reference crystal */
+	ref48: ref48M {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <48000000>;
+	};
 };
 
 &dcc {
@@ -404,10 +411,41 @@
 			#size-cells = <0>;
 			reg = <1>;
 			si5341: clock-generator@36 { /* SI5341 - u43 */
-				compatible = "si5341";
+				compatible = "silabs,si5341";
 				reg = <0x36>;
-			};
+				#clock-cells = <2>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&ref48>;
+				clock-names = "xtal";
+				clock-output-names = "si5341";
 
+				si5341_2: out@2 {
+					/* refclk2 for PS-GT, used for USB3 */
+					reg = <2>;
+					always-on; /* assigned-clocks does not enable, so do it here */
+				};
+				si5341_3: out@3 {
+					/* refclk3 for PS-GT, used for SATA */
+					reg = <3>;
+					always-on; /* assigned-clocks does not enable, so do it here */
+				};
+				si5341_5: out@5 {
+					/* refclk5 PL CLK100 */
+					reg = <5>;
+					always-on; /* assigned-clocks does not enable, so do it here */
+				};
+				si5341_6: out@6 {
+					/* refclk6 PL CLK125 */
+					reg = <6>;
+					always-on; /* assigned-clocks does not enable, so do it here */
+				};
+				si5341_9: out@9 {
+					/* refclk9 used for PS_REF_CLK 33.3 MHz */
+					reg = <9>;
+					always-on; /* assigned-clocks does not enable, so do it here */
+				};
+			};
 		};
 		i2c_si570_user_c0: i2c@2 {
 			#address-cells = <1>;
@@ -441,7 +479,10 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <4>;
-			/* U409B - 8a34001 */
+			idt_8a34001: phc@5b {
+				compatible = "idt,8a34001"; /* u409B */
+				reg = <0x5b>;
+			};
 		};
 		i2c_clk104: i2c@5 {
 			#address-cells = <1>;
@@ -538,6 +579,13 @@
 	};
 };
 
+&psgtr {
+	status = "okay";
+	/* pcie, sata, usb3, dp */
+	clocks = <&si5341 0 5>, <&si5341 0 3>, <&si5341 0 2>, <&si5341 0 0>;
+	clock-names = "ref0", "ref1", "ref2", "ref3";
+};
+
 &rtc {
 	status = "okay";
 };
@@ -553,8 +601,7 @@
 	ceva,p1-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
 	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
 	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
-	phy-names = "sata-phy";
-	phys = <&lane3 PHY_TYPE_SATA 1 3 125000000>;
+	phys = <&psgtr 3 PHY_TYPE_SATA 1 3>;
 };
 
 /* SD1 with level shifter */
@@ -568,10 +615,6 @@
 	xlnx,mio-bank = <1>;
 };
 
-&serdes {
-	status = "okay";
-};
-
 &uart0 {
 	status = "okay";
 };
@@ -585,6 +628,4 @@
 	status = "okay";
 	dr_mode = "host";
 	snps,usb3_lpm_capable;
-	phy-names = "usb3-phy";
-	phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
 };
diff --git a/arch/arm/dts/zynqmp-zcu216-revA.dts b/arch/arm/dts/zynqmp-zcu216-revA.dts
index 511727f..2302b07 100644
--- a/arch/arm/dts/zynqmp-zcu216-revA.dts
+++ b/arch/arm/dts/zynqmp-zcu216-revA.dts
@@ -120,6 +120,20 @@
 		compatible = "iio-hwmon";
 		io-channels = <&dac_avcc 0>, <&dac_avcc 1>, <&dac_avcc 2>, <&dac_avcc 3>;
 	};
+
+	/* 48MHz reference crystal */
+	ref48: ref48M {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <48000000>;
+	};
+};
+
+&psgtr {
+	status = "okay";
+	/* pcie, sata, usb3, dp */
+	clocks = <&si5341 0 5>, <&si5341 0 3>, <&si5341 0 2>, <&si5341 0 0>;
+	clock-names = "ref0", "ref1", "ref2", "ref3";
 };
 
 &dcc {
@@ -408,10 +422,41 @@
 			#size-cells = <0>;
 			reg = <1>;
 			si5341: clock-generator@36 { /* SI5341 - u43 */
-				compatible = "si5341";
+				compatible = "silabs,si5341";
 				reg = <0x36>;
-			};
+				#clock-cells = <2>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&ref48>;
+				clock-names = "xtal";
+				clock-output-names = "si5341";
 
+				si5341_2: out@2 {
+					/* refclk2 for PS-GT, used for USB3 */
+					reg = <2>;
+					always-on; /* assigned-clocks does not enable, so do it here */
+				};
+				si5341_3: out@3 {
+					/* refclk3 for PS-GT, used for SATA */
+					reg = <3>;
+					always-on; /* assigned-clocks does not enable, so do it here */
+				};
+				si5341_5: out@5 {
+					/* refclk5 PL CLK100 */
+					reg = <5>;
+					always-on; /* assigned-clocks does not enable, so do it here */
+				};
+				si5341_6: out@6 {
+					/* refclk6 PL CLK125 */
+					reg = <6>;
+					always-on; /* assigned-clocks does not enable, so do it here */
+				};
+				si5341_9: out@9 {
+					/* refclk9 used for PS_REF_CLK 33.3 MHz */
+					reg = <9>;
+					always-on; /* assigned-clocks does not enable, so do it here */
+				};
+			};
 		};
 		i2c_si570_user_c0: i2c@2 {
 			#address-cells = <1>;
@@ -445,7 +490,10 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <4>;
-			/* U409B - 8a34001 */
+			idt_8a34001: phc@5b {
+				compatible = "idt,8a34001"; /* u409B */
+				reg = <0x5b>;
+			};
 		};
 		i2c_clk104: i2c@5 {
 			#address-cells = <1>;
@@ -557,8 +605,7 @@
 	ceva,p1-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
 	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
 	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
-	phy-names = "sata-phy";
-	phys = <&lane3 PHY_TYPE_SATA 1 3 125000000>;
+	phys = <&psgtr 3 PHY_TYPE_SATA 1 3>;
 };
 
 /* SD1 with level shifter */
@@ -572,10 +619,6 @@
 	xlnx,mio-bank = <1>;
 };
 
-&serdes {
-	status = "okay";
-};
-
 &uart0 {
 	status = "okay";
 };
@@ -589,6 +632,4 @@
 	status = "okay";
 	dr_mode = "host";
 	snps,usb3_lpm_capable;
-	phy-names = "usb3-phy";
-	phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
 };
diff --git a/arch/arm/dts/zynqmp.dtsi b/arch/arm/dts/zynqmp.dtsi
index aa0ac95..84d9770 100644
--- a/arch/arm/dts/zynqmp.dtsi
+++ b/arch/arm/dts/zynqmp.dtsi
@@ -12,6 +12,7 @@
  * the License, or (at your option) any later version.
  */
 
+#include <dt-bindings/dma/xlnx-zynqmp-dpdma.h>
 #include <dt-bindings/power/xlnx-zynqmp-power.h>
 #include <dt-bindings/reset/xlnx-zynqmp-resets.h>
 
@@ -160,11 +161,25 @@
 				mbox-names = "tx", "rx";
 			};
 
+			nvmem_firmware {
+				compatible = "xlnx,zynqmp-nvmem-fw";
+				#address-cells = <1>;
+				#size-cells = <1>;
+
+				soc_revision: soc_revision@0 {
+					reg = <0x0 0x4>;
+				};
+			};
+
 			zynqmp_pcap: pcap {
 				compatible = "xlnx,zynqmp-pcap-fpga";
 				clock-names = "ref_clk";
 			};
 
+			xlnx_aes: zynqmp-aes {
+				compatible = "xlnx,zynqmp-aes";
+			};
+
 			zynqmp_reset: reset-controller {
 				compatible = "xlnx,zynqmp-reset";
 				#reset-cells = <1>;
@@ -198,16 +213,6 @@
 		ranges;
 	};
 
-	nvmem_firmware {
-		compatible = "xlnx,zynqmp-nvmem-fw";
-		#address-cells = <1>;
-		#size-cells = <1>;
-
-		soc_revision: soc_revision@0 {
-			reg = <0x0 0x4>;
-		};
-	};
-
 	amba: axi {
 		compatible = "simple-bus";
 		u-boot,dm-pre-reloc;
@@ -501,11 +506,11 @@
 			interrupts = <0 112 4>;
 		};
 
-		nand0: nand@ff100000 {
-			compatible = "arasan,nfc-v3p10";
+		nand0: nand-controller@ff100000 {
+			compatible = "xlnx,zynqmp-nand-controller", "arasan,nfc-v3p10";
 			status = "disabled";
 			reg = <0x0 0xff100000 0x0 0x1000>;
-			clock-names = "clk_sys", "clk_flash";
+			clock-names = "controller", "bus";
 			interrupt-parent = <&gic>;
 			interrupts = <0 14 4>;
 			#address-cells = <1>;
@@ -667,6 +672,15 @@
 			power-domains = <&zynqmp_firmware PD_QSPI>;
 		};
 
+		psgtr: phy@fd400000 {
+			compatible = "xlnx,zynqmp-psgtr-v1.1";
+			status = "disabled";
+			reg = <0x0 0xfd400000 0x0 0x40000>,
+			      <0x0 0xfd3d0000 0x0 0x1000>;
+			reg-names = "serdes", "siou";
+			#phy-cells = <4>;
+		};
+
 		rtc: rtc@ffa60000 {
 			compatible = "xlnx,zynqmp-rtc";
 			status = "disabled";
@@ -677,45 +691,6 @@
 			calibration = <0x8000>;
 		};
 
-		serdes: zynqmp_phy@fd400000 {
-			compatible = "xlnx,zynqmp-psgtr";
-			status = "disabled";
-			reg = <0x0 0xfd400000 0x0 0x40000>,
-			      <0x0 0xfd3d0000 0x0 0x1000>,
-			      <0x0 0xff5e0000 0x0 0x1000>;
-			reg-names = "serdes", "siou", "lpd";
-			nvmem-cells = <&soc_revision>;
-			nvmem-cell-names = "soc_revision";
-			resets = <&zynqmp_reset ZYNQMP_RESET_SATA>,
-				 <&zynqmp_reset ZYNQMP_RESET_USB0_CORERESET>,
-				 <&zynqmp_reset ZYNQMP_RESET_USB1_CORERESET>,
-				 <&zynqmp_reset ZYNQMP_RESET_USB0_HIBERRESET>,
-				 <&zynqmp_reset ZYNQMP_RESET_USB1_HIBERRESET>,
-				 <&zynqmp_reset ZYNQMP_RESET_USB0_APB>,
-				 <&zynqmp_reset ZYNQMP_RESET_USB1_APB>,
-				 <&zynqmp_reset ZYNQMP_RESET_DP>,
-				 <&zynqmp_reset ZYNQMP_RESET_GEM0>,
-				 <&zynqmp_reset ZYNQMP_RESET_GEM1>,
-				 <&zynqmp_reset ZYNQMP_RESET_GEM2>,
-				 <&zynqmp_reset ZYNQMP_RESET_GEM3>;
-			reset-names = "sata_rst", "usb0_crst", "usb1_crst",
-				      "usb0_hibrst", "usb1_hibrst", "usb0_apbrst",
-				      "usb1_apbrst", "dp_rst", "gem0_rst",
-				      "gem1_rst", "gem2_rst", "gem3_rst";
-			lane0: lane0 {
-				#phy-cells = <4>;
-			};
-			lane1: lane1 {
-				#phy-cells = <4>;
-			};
-			lane2: lane2 {
-				#phy-cells = <4>;
-			};
-			lane3: lane3 {
-				#phy-cells = <4>;
-			};
-		};
-
 		sata: ahci@fd0c0000 {
 			compatible = "ceva,ahci-1v84";
 			status = "disabled";
@@ -740,11 +715,11 @@
 			xlnx,device_id = <0>;
 			#stream-id-cells = <1>;
 			iommus = <&smmu 0x870>;
-			power-domains = <&zynqmp_firmware PD_SD_0>;
 			nvmem-cells = <&soc_revision>;
 			nvmem-cell-names = "soc_revision";
 			#clock-cells = <1>;
 			clock-output-names = "clk_out_sd0", "clk_in_sd0";
+			power-domains = <&zynqmp_firmware PD_SD_0>;
 		};
 
 		sdhci1: mmc@ff170000 {
@@ -758,11 +733,11 @@
 			xlnx,device_id = <1>;
 			#stream-id-cells = <1>;
 			iommus = <&smmu 0x871>;
-			power-domains = <&zynqmp_firmware PD_SD_1>;
 			nvmem-cells = <&soc_revision>;
 			nvmem-cell-names = "soc_revision";
 			#clock-cells = <1>;
 			clock-output-names = "clk_out_sd1", "clk_in_sd1";
+			power-domains = <&zynqmp_firmware PD_SD_1>;
 		};
 
 		smmu: iommu@fd800000 {
@@ -962,37 +937,18 @@
 			};
 		};
 
-		xlnx_dpdma: dma@fd4c0000 {
-			compatible = "xlnx,dpdma";
+		zynqmp_dpdma: dma-controller@fd4c0000 {
+			compatible = "xlnx,zynqmp-dpdma";
 			status = "disabled";
 			reg = <0x0 0xfd4c0000 0x0 0x1000>;
 			interrupts = <0 122 4>;
 			interrupt-parent = <&gic>;
 			clock-names = "axi_clk";
 			power-domains = <&zynqmp_firmware PD_DP>;
-			dma-channels = <6>;
 			#dma-cells = <1>;
-			dma-video0channel {
-				compatible = "xlnx,video0";
-			};
-			dma-video1channel {
-				compatible = "xlnx,video1";
-			};
-			dma-video2channel {
-				compatible = "xlnx,video2";
-			};
-			dma-graphicschannel {
-				compatible = "xlnx,graphics";
-			};
-			dma-audio0channel {
-				compatible = "xlnx,audio0";
-			};
-			dma-audio1channel {
-				compatible = "xlnx,audio1";
-			};
 		};
 
-		zynqmp_dpsub: zynqmp-display@fd4a0000 {
+		zynqmp_dpsub: display@fd4a0000 {
 			compatible = "xlnx,zynqmp-dpsub-1.7";
 			status = "disabled";
 			reg = <0x0 0xfd4a0000 0x0 0x1000>,
@@ -1002,51 +958,15 @@
 			reg-names = "dp", "blend", "av_buf", "aud";
 			interrupts = <0 119 4>;
 			interrupt-parent = <&gic>;
-
 			clock-names = "dp_apb_clk", "dp_aud_clk",
 				      "dp_vtc_pixel_clk_in";
-
 			power-domains = <&zynqmp_firmware PD_DP>;
-
-			vid-layer {
-				dma-names = "vid0", "vid1", "vid2";
-				dmas = <&xlnx_dpdma 0>,
-				       <&xlnx_dpdma 1>,
-				       <&xlnx_dpdma 2>;
-			};
-
-			gfx-layer {
-				dma-names = "gfx0";
-				dmas = <&xlnx_dpdma 3>;
-			};
-
-			/* dummy node to indicate there's no child i2c device */
-			i2c-bus {
-			};
-
-			zynqmp_dp_snd_codec0: zynqmp_dp_snd_codec0 {
-				compatible = "xlnx,dp-snd-codec";
-				clock-names = "aud_clk";
-			};
-
-			zynqmp_dp_snd_pcm0: zynqmp_dp_snd_pcm0 {
-				compatible = "xlnx,dp-snd-pcm";
-				dmas = <&xlnx_dpdma 4>;
-				dma-names = "tx";
-			};
-
-			zynqmp_dp_snd_pcm1: zynqmp_dp_snd_pcm1 {
-				compatible = "xlnx,dp-snd-pcm";
-				dmas = <&xlnx_dpdma 5>;
-				dma-names = "tx";
-			};
-
-			zynqmp_dp_snd_card0: zynqmp_dp_snd_card {
-				compatible = "xlnx,dp-snd-card";
-				xlnx,dp-snd-pcm = <&zynqmp_dp_snd_pcm0>,
-						  <&zynqmp_dp_snd_pcm1>;
-				xlnx,dp-snd-codec = <&zynqmp_dp_snd_codec0>;
-			};
+			resets = <&zynqmp_reset ZYNQMP_RESET_DP>;
+			dma-names = "vid0", "vid1", "vid2", "gfx0";
+			dmas = <&zynqmp_dpdma ZYNQMP_DPDMA_VIDEO0>,
+			       <&zynqmp_dpdma ZYNQMP_DPDMA_VIDEO1>,
+			       <&zynqmp_dpdma ZYNQMP_DPDMA_VIDEO2>,
+			       <&zynqmp_dpdma ZYNQMP_DPDMA_GRAPHICS>;
 		};
 	};
 };
diff --git a/arch/arm/include/asm/arch-imx/cpu.h b/arch/arm/include/asm/arch-imx/cpu.h
index f37fe21..bb13e07 100644
--- a/arch/arm/include/asm/arch-imx/cpu.h
+++ b/arch/arm/include/asm/arch-imx/cpu.h
@@ -40,10 +40,13 @@
 #define MXC_CPU_IMX8MNL		0x8e /* dummy ID */
 #define MXC_CPU_IMX8MNDL		0x8f /* dummy ID */
 #define MXC_CPU_IMX8MNSL		0x181 /* dummy ID */
-#define MXC_CPU_IMX8MP		0x182/* dummy ID */
-#define MXC_CPU_IMX8MP6		0x184 /* dummy ID */
-#define MXC_CPU_IMX8MPL		0x186 /* dummy ID */
-#define MXC_CPU_IMX8MPD		0x187 /* dummy ID */
+#define MXC_CPU_IMX8MNUQ		0x182 /* dummy ID */
+#define MXC_CPU_IMX8MNUD		0x183 /* dummy ID */
+#define MXC_CPU_IMX8MNUS		0x184 /* dummy ID */
+#define MXC_CPU_IMX8MP		0x185/* dummy ID */
+#define MXC_CPU_IMX8MP6		0x186 /* dummy ID */
+#define MXC_CPU_IMX8MPL		0x187 /* dummy ID */
+#define MXC_CPU_IMX8MPD		0x188 /* dummy ID */
 #define MXC_CPU_IMX8QXP_A0	0x90 /* dummy ID */
 #define MXC_CPU_IMX8QM		0x91 /* dummy ID */
 #define MXC_CPU_IMX8QXP		0x92 /* dummy ID */
@@ -59,9 +62,11 @@
 #define CHIP_REV_1_0            0x10
 #define CHIP_REV_1_1            0x11
 #define CHIP_REV_1_2            0x12
+#define CHIP_REV_1_3            0x13
 #define CHIP_REV_1_5            0x15
 #define CHIP_REV_2_0            0x20
 #define CHIP_REV_2_1            0x21
+#define CHIP_REV_2_2            0x22
 #define CHIP_REV_2_5            0x25
 #define CHIP_REV_3_0            0x30
 
diff --git a/arch/arm/include/asm/arch-imx8/image.h b/arch/arm/include/asm/arch-imx8/image.h
index c1e5700..547beeb 100644
--- a/arch/arm/include/asm/arch-imx8/image.h
+++ b/arch/arm/include/asm/arch-imx8/image.h
@@ -53,4 +53,15 @@
 	u16 signature_offset;
 	u32 reserved;
 } __packed;
+
+struct generate_key_blob_hdr {
+	u8 version;
+	u8 length_lsb;
+	u8 length_msb;
+	u8 tag;
+	u8 flags;
+	u8 size;
+	u8 algorithm;
+	u8 mode;
+} __packed;
 #endif
diff --git a/arch/arm/include/asm/arch-imx8m/clock.h b/arch/arm/include/asm/arch-imx8m/clock.h
index c545eb8..77d9428 100644
--- a/arch/arm/include/asm/arch-imx8m/clock.h
+++ b/arch/arm/include/asm/arch-imx8m/clock.h
@@ -275,3 +275,4 @@
 int enable_i2c_clk(unsigned char enable, unsigned int i2c_num);
 int set_clk_enet(enum enet_freq type);
 int set_clk_eqos(enum enet_freq type);
+void hab_caam_clock_enable(unsigned char enable);
diff --git a/arch/arm/include/asm/arch-imx8m/imx-regs.h b/arch/arm/include/asm/arch-imx8m/imx-regs.h
index 3f50014..b800da1 100644
--- a/arch/arm/include/asm/arch-imx8m/imx-regs.h
+++ b/arch/arm/include/asm/arch-imx8m/imx-regs.h
@@ -65,6 +65,16 @@
 #define IOMUXC_GPR_GPR1_GPR_ENET_QOS_INTF_SEL_MASK 0x70000
 #define FEC_QUIRK_ENET_MAC
 
+#define CAAM_ARB_BASE_ADDR              (0x00100000)
+#define CAAM_ARB_END_ADDR               (0x00107FFF)
+#define CAAM_IPS_BASE_ADDR              (0x30900000)
+#define CONFIG_SYS_FSL_SEC_OFFSET       (0)
+#define CONFIG_SYS_FSL_SEC_ADDR         (CAAM_IPS_BASE_ADDR + \
+					 CONFIG_SYS_FSL_SEC_OFFSET)
+#define CONFIG_SYS_FSL_JR0_OFFSET       (0x1000)
+#define CONFIG_SYS_FSL_JR0_ADDR         (CONFIG_SYS_FSL_SEC_ADDR + \
+					 CONFIG_SYS_FSL_JR0_OFFSET)
+#define CONFIG_SYS_FSL_MAX_NUM_OF_SEC   1
 #if !defined(__ASSEMBLY__)
 #include <asm/types.h>
 #include <linux/bitops.h>
@@ -120,6 +130,16 @@
 	} bank[0];
 };
 
+#ifdef CONFIG_IMX8MP
+struct fuse_bank0_regs {
+	u32 lock;
+	u32 rsvd0[7];
+	u32 uid_low;
+	u32 rsvd1[3];
+	u32 uid_high;
+	u32 rsvd2[3];
+};
+#else
 struct fuse_bank0_regs {
 	u32 lock;
 	u32 rsvd0[3];
@@ -128,6 +148,7 @@
 	u32 uid_high;
 	u32 rsvd2[7];
 };
+#endif
 
 struct fuse_bank1_regs {
 	u32 tester3;
diff --git a/arch/arm/include/asm/arch-meson/axg.h b/arch/arm/include/asm/arch-meson/axg.h
index 91c8769..12042de 100644
--- a/arch/arm/include/asm/arch-meson/axg.h
+++ b/arch/arm/include/asm/arch-meson/axg.h
@@ -31,26 +31,4 @@
 #define AXG_AO_BL31_RSVMEM_SIZE_SHIFT	16
 #define AXG_AO_BL32_RSVMEM_SIZE_MASK	0xFFFF
 
-/* Peripherals registers */
-#define AXG_PERIPHS_ADDR(off)	(AXG_PERIPHS_BASE + ((off) << 2))
-
-#define AXG_ETH_REG_0		AXG_PERIPHS_ADDR(0x50)
-#define AXG_ETH_REG_1		AXG_PERIPHS_ADDR(0x51)
-
-#define AXG_ETH_REG_0_PHY_INTF_RGMII	BIT(0)
-#define AXG_ETH_REG_0_PHY_INTF_RMII	BIT(2)
-#define AXG_ETH_REG_0_TX_PHASE(x)	(((x) & 3) << 5)
-#define AXG_ETH_REG_0_TX_RATIO(x)	(((x) & 7) << 7)
-#define AXG_ETH_REG_0_PHY_CLK_EN	BIT(10)
-#define AXG_ETH_REG_0_INVERT_RMII_CLK	BIT(11)
-#define AXG_ETH_REG_0_CLK_EN		BIT(12)
-
-/* HIU registers */
-#define AXG_HIU_ADDR(off)	(AXG_HIU_BASE + ((off) << 2))
-
-#define AXG_MEM_PD_REG_0	AXG_HIU_ADDR(0x40)
-
-/* Ethernet memory power domain */
-#define AXG_MEM_PD_REG_0_ETH_MASK	(BIT(2) | BIT(3))
-
 #endif /* __AXG_H__ */
diff --git a/arch/arm/include/asm/arch-meson/eth.h b/arch/arm/include/asm/arch-meson/eth.h
index f765cd7..c007061 100644
--- a/arch/arm/include/asm/arch-meson/eth.h
+++ b/arch/arm/include/asm/arch-meson/eth.h
@@ -7,18 +7,6 @@
 #ifndef __MESON_ETH_H__
 #define __MESON_ETH_H__
 
-#include <phy.h>
-
-enum {
-	/* Use Internal RMII PHY */
-	MESON_USE_INTERNAL_RMII_PHY = 1,
-};
-
-/* Configure the Ethernet MAC with the requested interface mode
- * with some optional flags.
- */
-void meson_eth_init(phy_interface_t mode, unsigned int flags);
-
 /* Generate an unique MAC address based on the HW serial */
 int meson_generate_serial_ethaddr(void);
 
diff --git a/arch/arm/include/asm/arch-meson/g12a.h b/arch/arm/include/asm/arch-meson/g12a.h
index db29cc3..ef4f301 100644
--- a/arch/arm/include/asm/arch-meson/g12a.h
+++ b/arch/arm/include/asm/arch-meson/g12a.h
@@ -32,39 +32,4 @@
 #define G12A_AO_BL31_RSVMEM_SIZE_SHIFT	16
 #define G12A_AO_BL32_RSVMEM_SIZE_MASK	0xFFFF
 
-/* Peripherals registers */
-#define G12A_PERIPHS_ADDR(off)	(G12A_PERIPHS_BASE + ((off) << 2))
-
-#define G12A_ETH_REG_0			G12A_PERIPHS_ADDR(0x50)
-#define G12A_ETH_REG_1			G12A_PERIPHS_ADDR(0x51)
-
-#define G12A_ETH_REG_0_PHY_INTF_RGMII	BIT(0)
-#define G12A_ETH_REG_0_PHY_INTF_RMII	BIT(2)
-#define G12A_ETH_REG_0_TX_PHASE(x)	(((x) & 3) << 5)
-#define G12A_ETH_REG_0_TX_RATIO(x)	(((x) & 7) << 7)
-#define G12A_ETH_REG_0_PHY_CLK_EN	BIT(10)
-#define G12A_ETH_REG_0_INVERT_RMII_CLK	BIT(11)
-#define G12A_ETH_REG_0_CLK_EN		BIT(12)
-
-#define G12A_ETH_PHY_ADDR(off)	(G12A_ETH_PHY_BASE + ((off) << 2))
-#define ETH_PLL_CNTL0			G12A_ETH_PHY_ADDR(0x11)
-#define ETH_PLL_CNTL1			G12A_ETH_PHY_ADDR(0x12)
-#define ETH_PLL_CNTL2			G12A_ETH_PHY_ADDR(0x13)
-#define ETH_PLL_CNTL3			G12A_ETH_PHY_ADDR(0x14)
-#define ETH_PLL_CNTL4			G12A_ETH_PHY_ADDR(0x15)
-#define ETH_PLL_CNTL5			G12A_ETH_PHY_ADDR(0x16)
-#define ETH_PLL_CNTL6			G12A_ETH_PHY_ADDR(0x17)
-#define ETH_PLL_CNTL7			G12A_ETH_PHY_ADDR(0x18)
-#define ETH_PHY_CNTL0			G12A_ETH_PHY_ADDR(0x20)
-#define ETH_PHY_CNTL1			G12A_ETH_PHY_ADDR(0x21)
-#define ETH_PHY_CNTL2			G12A_ETH_PHY_ADDR(0x22)
-
-/* HIU registers */
-#define G12A_HIU_ADDR(off)	(G12A_HIU_BASE + ((off) << 2))
-
-#define G12A_MEM_PD_REG_0		G12A_HIU_ADDR(0x40)
-
-/* Ethernet memory power domain */
-#define G12A_MEM_PD_REG_0_ETH_MASK	(BIT(2) | BIT(3))
-
 #endif /* __G12A_H__ */
diff --git a/arch/arm/include/asm/arch-meson/gx.h b/arch/arm/include/asm/arch-meson/gx.h
index 743d2e8..26ec5d0 100644
--- a/arch/arm/include/asm/arch-meson/gx.h
+++ b/arch/arm/include/asm/arch-meson/gx.h
@@ -41,24 +41,4 @@
 #define GX_GPIO_IN(n)		GX_PERIPHS_ADDR(_GX_GPIO_OFF(n) + 1)
 #define GX_GPIO_OUT(n)	GX_PERIPHS_ADDR(_GX_GPIO_OFF(n) + 2)
 
-#define GX_ETH_REG_0		GX_PERIPHS_ADDR(0x50)
-#define GX_ETH_REG_1		GX_PERIPHS_ADDR(0x51)
-#define GX_ETH_REG_2		GX_PERIPHS_ADDR(0x56)
-#define GX_ETH_REG_3		GX_PERIPHS_ADDR(0x57)
-
-#define GX_ETH_REG_0_PHY_INTF		BIT(0)
-#define GX_ETH_REG_0_TX_PHASE(x)	(((x) & 3) << 5)
-#define GX_ETH_REG_0_TX_RATIO(x)	(((x) & 7) << 7)
-#define GX_ETH_REG_0_PHY_CLK_EN	BIT(10)
-#define GX_ETH_REG_0_INVERT_RMII_CLK	BIT(11)
-#define GX_ETH_REG_0_CLK_EN		BIT(12)
-
-/* HIU registers */
-#define GX_HIU_ADDR(off)	(GX_HIU_BASE + ((off) << 2))
-
-#define GX_MEM_PD_REG_0	GX_HIU_ADDR(0x40)
-
-/* Ethernet memory power domain */
-#define GX_MEM_PD_REG_0_ETH_MASK	(BIT(2) | BIT(3))
-
 #endif /* __GX_H__ */
diff --git a/arch/arm/include/asm/arch-mx6/mx6ull_pins.h b/arch/arm/include/asm/arch-mx6/mx6ull_pins.h
index de4a1ab..842d0ca 100644
--- a/arch/arm/include/asm/arch-mx6/mx6ull_pins.h
+++ b/arch/arm/include/asm/arch-mx6/mx6ull_pins.h
@@ -326,7 +326,7 @@
 
 	MX6_PAD_UART5_TX_DATA__UART5_DCE_TX                   = IOMUX_PAD(0x0348, 0x00BC, 0, 0x0000, 0, 0),
 
-	MX6_PAD_UART5_TX_DATA__UART5_DTE_RX                   = IOMUX_PAD(0x0348, 0x00BC, 0, 0x0644, 4, 0),
+	MX6_PAD_UART5_TX_DATA__UART5_DTE_RX                   = IOMUX_PAD(0x0348, 0x00BC, 0, 0x0644, 6, 0),
 	MX6_PAD_UART5_TX_DATA__ENET2_CRS                      = IOMUX_PAD(0x0348, 0x00BC, 1, 0x0000, 0, 0),
 	MX6_PAD_UART5_TX_DATA__I2C2_SCL                       = IOMUX_PAD(0x0348, 0x00BC, IOMUX_CONFIG_SION | 2, 0x05AC, 2, 0),
 	MX6_PAD_UART5_TX_DATA__CSI_DATA14                     = IOMUX_PAD(0x0348, 0x00BC, 3, 0x04FC, 0, 0),
@@ -363,7 +363,7 @@
 	MX6_PAD_ENET1_RX_DATA1__USDHC2_LCTL                   = IOMUX_PAD(0x0354, 0x00C8, 8, 0x0000, 0, 0),
 
 	MX6_PAD_ENET1_RX_EN__ENET1_RX_EN                      = IOMUX_PAD(0x0358, 0x00CC, 0, 0x0000, 0, 0),
-	MX6_PAD_ENET1_RX_EN__UART5_DCE_RTS                    = IOMUX_PAD(0x0358, 0x00CC, 1, 0x0640, 3, 0),
+	MX6_PAD_ENET1_RX_EN__UART5_DCE_RTS                    = IOMUX_PAD(0x0358, 0x00CC, 1, 0x0640, 5, 0),
 	MX6_PAD_ENET1_RX_EN__UART5_DTE_CTS                    = IOMUX_PAD(0x0358, 0x00CC, 1, 0x0000, 0, 0),
 	MX6_PAD_ENET1_RX_EN__CSI_DATA18                       = IOMUX_PAD(0x0358, 0x00CC, 3, 0x050C, 0, 0),
 	MX6_PAD_ENET1_RX_EN__FLEXCAN2_TX                      = IOMUX_PAD(0x0358, 0x00CC, 4, 0x0000, 0, 0),
@@ -373,7 +373,7 @@
 
 	MX6_PAD_ENET1_TX_DATA0__ENET1_TDATA00                 = IOMUX_PAD(0x035C, 0x00D0, 0, 0x0000, 0, 0),
 	MX6_PAD_ENET1_TX_DATA0__UART5_DCE_CTS                 = IOMUX_PAD(0x035C, 0x00D0, 1, 0x0000, 0, 0),
-	MX6_PAD_ENET1_TX_DATA0__UART5_DTE_RTS                 = IOMUX_PAD(0x035C, 0x00D0, 1, 0x0640, 4, 0),
+	MX6_PAD_ENET1_TX_DATA0__UART5_DTE_RTS                 = IOMUX_PAD(0x035C, 0x00D0, 1, 0x0640, 6, 0),
 	MX6_PAD_ENET1_TX_DATA0__CSI_DATA19                    = IOMUX_PAD(0x035C, 0x00D0, 3, 0x0510, 0, 0),
 	MX6_PAD_ENET1_TX_DATA0__FLEXCAN2_RX                   = IOMUX_PAD(0x035C, 0x00D0, 4, 0x0588, 1, 0),
 	MX6_PAD_ENET1_TX_DATA0__GPIO2_IO03                    = IOMUX_PAD(0x035C, 0x00D0, 5, 0x0000, 0, 0),
@@ -1012,7 +1012,7 @@
 	MX6_PAD_CSI_DATA02__EIM_AD02                          = IOMUX_PAD(0x0478, 0x01EC, 4, 0x0000, 0, 0),
 	MX6_PAD_CSI_DATA02__GPIO4_IO23                        = IOMUX_PAD(0x0478, 0x01EC, 5, 0x0000, 0, 0),
 	MX6_PAD_CSI_DATA02__SAI1_RX_SYNC                      = IOMUX_PAD(0x0478, 0x01EC, 6, 0x0000, 0, 0),
-	MX6_PAD_CSI_DATA02__UART5_DCE_RTS                     = IOMUX_PAD(0x0478, 0x01EC, 8, 0x0640, 5, 0),
+	MX6_PAD_CSI_DATA02__UART5_DCE_RTS                     = IOMUX_PAD(0x0478, 0x01EC, 8, 0x0640, 7, 0),
 	MX6_PAD_CSI_DATA02__UART5_DTE_CTS                     = IOMUX_PAD(0x0478, 0x01EC, 8, 0x0000, 0, 0),
 
 	MX6_PAD_CSI_DATA03__CSI_DATA05                        = IOMUX_PAD(0x047C, 0x01F0, 0, 0x04CC, 0, 0),
diff --git a/arch/arm/include/asm/arch-mx7ulp/imx-regs.h b/arch/arm/include/asm/arch-mx7ulp/imx-regs.h
index 9a420dc..cb0c2c1 100644
--- a/arch/arm/include/asm/arch-mx7ulp/imx-regs.h
+++ b/arch/arm/include/asm/arch-mx7ulp/imx-regs.h
@@ -16,6 +16,8 @@
 #define CAAM_SEC_SRAM_SIZE      (SZ_32K)
 #define CAAM_SEC_SRAM_END       (CAAM_SEC_SRAM_BASE + CAAM_SEC_SRAM_SIZE - 1)
 
+#define CAAM_ARB_BASE_ADDR      CAAM_SEC_SRAM_BASE
+
 #define OCRAM_0_BASE            (0x2F000000)
 #define OCRAM_0_SIZE            (SZ_128K)
 #define OCRAM_0_END             (OCRAM_0_BASE + OCRAM_0_SIZE - 1)
@@ -224,6 +226,16 @@
 #define IOMUXC_DDR_RBASE	((AIPS3_BASE + (AIPS3_SLOT_SIZE * IOMUXC_DDR_AIPS3_SLOT)))
 #define MMDC0_PCC_REG		(PCC3_RBASE + (4 * MMDC0_PCC3_SLOT))
 
+#define CAAM_IPS_BASE_ADDR              (AIPS2_BASE + 0x240000) /* 40240000 */
+
+#define CONFIG_SYS_FSL_SEC_OFFSET       0
+#define CONFIG_SYS_FSL_SEC_ADDR         (CAAM_IPS_BASE_ADDR + \
+					 CONFIG_SYS_FSL_SEC_OFFSET)
+#define CONFIG_SYS_FSL_JR0_OFFSET       0x1000
+#define CONFIG_SYS_FSL_JR0_ADDR         (CONFIG_SYS_FSL_SEC_ADDR + \
+					 CONFIG_SYS_FSL_JR0_OFFSET)
+#define CONFIG_SYS_FSL_MAX_NUM_OF_SEC   1
+
 #define IOMUXC_DPCR_DDR_DQS0	((IOMUXC_DDR_RBASE + (4 * 32)))
 #define IOMUXC_DPCR_DDR_DQS1	((IOMUXC_DDR_RBASE + (4 * 33)))
 #define IOMUXC_DPCR_DDR_DQS2	((IOMUXC_DDR_RBASE + (4 * 34)))
diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h
index c20e05e..b10edf8 100644
--- a/arch/arm/include/asm/cache.h
+++ b/arch/arm/include/asm/cache.h
@@ -35,7 +35,6 @@
 void set_section_dcache(int section, enum dcache_option option);
 
 void arm_init_before_mmu(void);
-void arm_init_domains(void);
 void cpu_cache_initialization(void);
 void dram_bank_mmu_setup(int bank);
 
diff --git a/arch/arm/include/asm/mach-imx/hab.h b/arch/arm/include/asm/mach-imx/hab.h
index d8bd770..2abf28e 100644
--- a/arch/arm/include/asm/mach-imx/hab.h
+++ b/arch/arm/include/asm/mach-imx/hab.h
@@ -18,8 +18,6 @@
  */
 #define IVT_HEADER_MAGIC	0xD1
 #define IVT_TOTAL_LENGTH	0x20
-#define IVT_HEADER_V1		0x40
-#define IVT_HEADER_V2		0x41
 
 struct __packed ivt_header {
 	uint8_t		magic;
@@ -44,6 +42,15 @@
 	u8 par;              /* Parameters field */
 };
 
+/* Default event structure */
+struct __packed evt_def {
+	struct hab_hdr hdr;		/* Header */
+	uint32_t sts;			/* Status */
+	uint32_t ctx;			/* Default context */
+	uint8_t *data;			/* Default data location */
+	size_t bytes;			/* Size of default data */
+};
+
 /* -------- start of HAB API updates ------------*/
 /* The following are taken from HAB4 SIS */
 
@@ -165,6 +172,22 @@
 #define HAB_ENG_RTL		0x77   /* RTL simulation engine */
 #define HAB_ENG_SW		0xff   /* Software engine */
 
+#ifdef CONFIG_ARM64
+#ifdef CONFIG_IMX8MQ
+#define HAB_RVT_BASE                   0x00000880
+#else
+#define HAB_RVT_BASE                   0x00000900
+#endif
+
+#define HAB_RVT_ENTRY			(*(ulong *)(HAB_RVT_BASE + 0x08))
+#define HAB_RVT_EXIT			(*(ulong *)(HAB_RVT_BASE + 0x10))
+#define HAB_RVT_CHECK_TARGET		(*(ulong *)(HAB_RVT_BASE + 0x18))
+#define HAB_RVT_AUTHENTICATE_IMAGE	(*(ulong *)(HAB_RVT_BASE + 0x20))
+#define HAB_RVT_REPORT_EVENT		(*(ulong *)(HAB_RVT_BASE + 0x40))
+#define HAB_RVT_REPORT_STATUS		(*(ulong *)(HAB_RVT_BASE + 0x48))
+#define HAB_RVT_FAILSAFE		(*(ulong *)(HAB_RVT_BASE + 0x50))
+#else
+
 #ifdef CONFIG_ROM_UNIFIED_SECTIONS
 #define HAB_RVT_BASE			0x00000100
 #else
@@ -172,7 +195,7 @@
 #define HAB_RVT_BASE_OLD		0x00000094
 #define HAB_RVT_BASE ((is_mx6dqp()) ?					\
 			HAB_RVT_BASE_NEW :				\
-			(is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ?	\
+			(is_mx6dq() && (soc_rev() >= CHIP_REV_1_3)) ?	\
 			HAB_RVT_BASE_NEW :				\
 			(is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ?	\
 			HAB_RVT_BASE_NEW : HAB_RVT_BASE_OLD)
@@ -186,6 +209,8 @@
 #define HAB_RVT_REPORT_STATUS		(*(uint32_t *)(HAB_RVT_BASE + 0x24))
 #define HAB_RVT_FAILSAFE		(*(uint32_t *)(HAB_RVT_BASE + 0x28))
 
+#endif /*CONFIG_ARM64*/
+
 #define HAB_CID_ROM 0 /**< ROM Caller ID */
 #define HAB_CID_UBOOT 1 /**< UBOOT Caller ID*/
 
@@ -199,6 +224,12 @@
 #define IVT_SIZE			0x20
 #define CSF_PAD_SIZE			0x2000
 
+#define HAB_TAG_EVT		0xDB
+#define HAB_TAG_EVT_DEF		0x0C
+
+#define HAB_MAJ_VER		0x40
+#define HAB_MAJ_MASK		0xF0
+
 /* ----------- end of HAB API updates ------------*/
 
 int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
diff --git a/arch/arm/include/asm/mach-imx/sys_proto.h b/arch/arm/include/asm/mach-imx/sys_proto.h
index 43eae6d..c7668ff 100644
--- a/arch/arm/include/asm/mach-imx/sys_proto.h
+++ b/arch/arm/include/asm/mach-imx/sys_proto.h
@@ -60,12 +60,16 @@
 #define is_imx8mmsl() (is_cpu_type(MXC_CPU_IMX8MMSL))
 #define is_imx8mn() (is_cpu_type(MXC_CPU_IMX8MN) || is_cpu_type(MXC_CPU_IMX8MND) || \
 	is_cpu_type(MXC_CPU_IMX8MNS) || is_cpu_type(MXC_CPU_IMX8MNL) || \
-	is_cpu_type(MXC_CPU_IMX8MNDL) || is_cpu_type(MXC_CPU_IMX8MNSL))
+	is_cpu_type(MXC_CPU_IMX8MNDL) || is_cpu_type(MXC_CPU_IMX8MNSL) || \
+	is_cpu_type(MXC_CPU_IMX8MNUD) || is_cpu_type(MXC_CPU_IMX8MNUS) || is_cpu_type(MXC_CPU_IMX8MNUQ))
 #define is_imx8mnd() (is_cpu_type(MXC_CPU_IMX8MND))
 #define is_imx8mns() (is_cpu_type(MXC_CPU_IMX8MNS))
 #define is_imx8mnl() (is_cpu_type(MXC_CPU_IMX8MNL))
 #define is_imx8mndl() (is_cpu_type(MXC_CPU_IMX8MNDL))
 #define is_imx8mnsl() (is_cpu_type(MXC_CPU_IMX8MNSL))
+#define is_imx8mnuq() (is_cpu_type(MXC_CPU_IMX8MNUQ))
+#define is_imx8mnud() (is_cpu_type(MXC_CPU_IMX8MNUD))
+#define is_imx8mnus() (is_cpu_type(MXC_CPU_IMX8MNUS))
 #define is_imx8mp() (is_cpu_type(MXC_CPU_IMX8MP)  || is_cpu_type(MXC_CPU_IMX8MPD) || \
 	is_cpu_type(MXC_CPU_IMX8MPL) || is_cpu_type(MXC_CPU_IMX8MP6))
 #define is_imx8mpd() (is_cpu_type(MXC_CPU_IMX8MPD))
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 5fe8369..11fceec 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -397,20 +397,6 @@
 	isb();
 }
 
-static inline unsigned int get_dacr(void)
-{
-	unsigned int val;
-	asm("mrc p15, 0, %0, c3, c0, 0	@ get DACR" : "=r" (val) : : "cc");
-	return val;
-}
-
-static inline void set_dacr(unsigned int val)
-{
-	asm volatile("mcr p15, 0, %0, c3, c0, 0	@ set DACR"
-	  : : "r" (val) : "cc");
-	isb();
-}
-
 #ifdef CONFIG_ARMV7_LPAE
 /* Long-Descriptor Translation Table Level 1/2 Bits */
 #define TTB_SECT_XN_MASK	(1ULL << 54)
@@ -475,7 +461,7 @@
 #define TTB_SECT_XN_MASK	(1 << 4)
 #define TTB_SECT_C_MASK		(1 << 3)
 #define TTB_SECT_B_MASK		(1 << 2)
-#define TTB_SECT			(2 << 0)
+#define TTB_SECT		(2 << 0)
 
 /*
  * Short-descriptor format memory region attributes, without TEX remap
@@ -489,7 +475,7 @@
  */
 enum dcache_option {
 	DCACHE_OFF = TTB_SECT_DOMAIN(0) | TTB_SECT_XN_MASK | TTB_SECT,
-	DCACHE_WRITETHROUGH = DCACHE_OFF | TTB_SECT_C_MASK,
+	DCACHE_WRITETHROUGH = TTB_SECT_DOMAIN(0) | TTB_SECT | TTB_SECT_C_MASK,
 	DCACHE_WRITEBACK = DCACHE_WRITETHROUGH | TTB_SECT_B_MASK,
 	DCACHE_WRITEALLOC = DCACHE_WRITEBACK | TTB_SECT_TEX(1),
 };
diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c
index 24050e5..aab1bf4 100644
--- a/arch/arm/lib/cache-cp15.c
+++ b/arch/arm/lib/cache-cp15.c
@@ -22,10 +22,6 @@
 {
 }
 
-__weak void arm_init_domains(void)
-{
-}
-
 static void set_section_phys(int section, phys_addr_t phys,
 			     enum dcache_option option)
 {
@@ -203,11 +199,12 @@
 	asm volatile("mcr p15, 0, %0, c2, c0, 0"
 		     : : "r" (gd->arch.tlb_addr) : "memory");
 #endif
-	/* Set the access control to all-supervisor */
+	/*
+	 * initial value of Domain Access Control Register (DACR)
+	 * Set the access control to client (1U) for each of the 16 domains
+	 */
 	asm volatile("mcr p15, 0, %0, c3, c0, 0"
-		     : : "r" (~0));
-
-	arm_init_domains();
+		     : : "r" (0x55555555));
 
 	/* and enable the mmu */
 	reg = get_cr();	/* get control reg. */
diff --git a/arch/arm/lib/interrupts.c b/arch/arm/lib/interrupts.c
index 05bb1a3..6dc27d1 100644
--- a/arch/arm/lib/interrupts.c
+++ b/arch/arm/lib/interrupts.c
@@ -53,7 +53,7 @@
 void bad_mode (void)
 {
 	panic ("Resetting CPU ...\n");
-	reset_cpu(0);
+	reset_cpu();
 }
 
 static void show_efi_loaded_images(struct pt_regs *regs)
diff --git a/arch/arm/lib/interrupts_m.c b/arch/arm/lib/interrupts_m.c
index 2ae1c5b..277854a 100644
--- a/arch/arm/lib/interrupts_m.c
+++ b/arch/arm/lib/interrupts_m.c
@@ -59,7 +59,7 @@
 void bad_mode(void)
 {
 	panic("Resetting CPU ...\n");
-	reset_cpu(0);
+	reset_cpu();
 }
 
 void do_hard_fault(struct autosave_regs *autosave_regs)
diff --git a/arch/arm/lib/reset.c b/arch/arm/lib/reset.c
index 4f1a768..95169ba 100644
--- a/arch/arm/lib/reset.c
+++ b/arch/arm/lib/reset.c
@@ -39,7 +39,7 @@
 	disable_interrupts();
 
 	reset_misc();
-	reset_cpu(0);
+	reset_cpu();
 
 	/*NOTREACHED*/
 	return 0;
diff --git a/arch/arm/mach-at91/arm920t/reset.c b/arch/arm/mach-at91/arm920t/reset.c
index d92bc57..91e3751 100644
--- a/arch/arm/mach-at91/arm920t/reset.c
+++ b/arch/arm/mach-at91/arm920t/reset.c
@@ -24,7 +24,7 @@
 	/* true empty function for defining weak symbol */
 }
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 	at91_st_t *st = (at91_st_t *) ATMEL_BASE_ST;
 
diff --git a/arch/arm/mach-at91/arm926ejs/lowlevel_init.S b/arch/arm/mach-at91/arm926ejs/lowlevel_init.S
index 71d7582..994f42e 100644
--- a/arch/arm/mach-at91/arm926ejs/lowlevel_init.S
+++ b/arch/arm/mach-at91/arm926ejs/lowlevel_init.S
@@ -71,10 +71,10 @@
 	str	r0, [r1]
 
 	/* Reading the PMC Status to detect when the Main Oscillator is enabled */
-	mov	r4, #AT91_PMC_IXR_MOSCS
+	mov	r6, #AT91_PMC_IXR_MOSCS
 MOSCS_Loop:
 	ldr	r3, [r2]
-	and	r3, r4, r3
+	and	r3, r6, r3
 	cmp	r3, #AT91_PMC_IXR_MOSCS
 	bne	MOSCS_Loop
 
@@ -89,10 +89,10 @@
 	str	r0, [r1]
 
 	/* Reading the PMC Status register to detect when the PLLA is locked */
-	mov	r4, #AT91_PMC_IXR_LOCKA
+	mov	r6, #AT91_PMC_IXR_LOCKA
 MOSCS_Loop1:
 	ldr	r3, [r2]
-	and	r3, r4, r3
+	and	r3, r6, r3
 	cmp	r3, #AT91_PMC_IXR_LOCKA
 	bne	MOSCS_Loop1
 
@@ -109,10 +109,10 @@
 	str	r0, [r1]
 
 	/* Reading the PMC Status to detect when the Master clock is ready */
-	mov	r4, #AT91_PMC_IXR_MCKRDY
+	mov	r6, #AT91_PMC_IXR_MCKRDY
 MCKRDY_Loop:
 	ldr	r3, [r2]
-	and	r3, r4, r3
+	and	r3, r6, r3
 	cmp	r3, #AT91_PMC_IXR_MCKRDY
 	bne	MCKRDY_Loop
 
@@ -120,10 +120,10 @@
 	str	r0, [r1]
 
 	/* Reading the PMC Status to detect when the Master clock is ready */
-	mov	r4, #AT91_PMC_IXR_MCKRDY
+	mov	r6, #AT91_PMC_IXR_MCKRDY
 MCKRDY_Loop1:
 	ldr	r3, [r2]
-	and	r3, r4, r3
+	and	r3, r6, r3
 	cmp	r3, #AT91_PMC_IXR_MCKRDY
 	bne	MCKRDY_Loop1
 PLL_setup_end:
diff --git a/arch/arm/mach-at91/arm926ejs/reset.c b/arch/arm/mach-at91/arm926ejs/reset.c
index 56fbbd9..6acbfa3 100644
--- a/arch/arm/mach-at91/arm926ejs/reset.c
+++ b/arch/arm/mach-at91/arm926ejs/reset.c
@@ -12,7 +12,7 @@
 #include <asm/arch/at91_rstc.h>
 
 /* Reset the cpu by telling the reset controller to do so */
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 	at91_rstc_t *rstc = (at91_rstc_t *) ATMEL_BASE_RSTC;
 
diff --git a/arch/arm/mach-at91/armv7/reset.c b/arch/arm/mach-at91/armv7/reset.c
index 8f4c81d..1ea415e 100644
--- a/arch/arm/mach-at91/armv7/reset.c
+++ b/arch/arm/mach-at91/armv7/reset.c
@@ -15,7 +15,7 @@
 #include <asm/arch/at91_rstc.h>
 
 /* Reset the cpu by telling the reset controller to do so */
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 	at91_rstc_t *rstc = (at91_rstc_t *)ATMEL_BASE_RSTC;
 
diff --git a/arch/arm/mach-at91/include/mach/atmel_pio4.h b/arch/arm/mach-at91/include/mach/atmel_pio4.h
index 35ac7b2..c3bd914 100644
--- a/arch/arm/mach-at91/include/mach/atmel_pio4.h
+++ b/arch/arm/mach-at91/include/mach/atmel_pio4.h
@@ -44,6 +44,7 @@
 #define ATMEL_PIO_DIR_MASK		BIT(8)
 #define ATMEL_PIO_PUEN_MASK		BIT(9)
 #define ATMEL_PIO_PDEN_MASK		BIT(10)
+#define ATMEL_PIO_SR			BIT(11)
 #define ATMEL_PIO_IFEN_MASK		BIT(12)
 #define ATMEL_PIO_IFSCEN_MASK		BIT(13)
 #define ATMEL_PIO_OPD_MASK		BIT(14)
diff --git a/arch/arm/mach-bcm283x/reset.c b/arch/arm/mach-bcm283x/reset.c
index 2b4ccd4..f13ac0c 100644
--- a/arch/arm/mach-bcm283x/reset.c
+++ b/arch/arm/mach-bcm283x/reset.c
@@ -48,7 +48,7 @@
 	writel(BCM2835_WDOG_PASSWORD | rstc, &wdog_regs->rstc);
 }
 
-void reset_cpu(ulong ticks)
+void reset_cpu(void)
 {
 	struct bcm2835_wdog_regs *regs =
 		(struct bcm2835_wdog_regs *)BCM2835_WDOG_PHYSADDR;
diff --git a/arch/arm/mach-davinci/reset.c b/arch/arm/mach-davinci/reset.c
index 4e6031a..0d59eb6 100644
--- a/arch/arm/mach-davinci/reset.c
+++ b/arch/arm/mach-davinci/reset.c
@@ -12,7 +12,7 @@
 #include <asm/arch/timer_defs.h>
 #include <asm/arch/hardware.h>
 
-void reset_cpu(unsigned long a)
+void reset_cpu(void)
 {
 	struct davinci_timer *const wdttimer =
 		(struct davinci_timer *)DAVINCI_WDOG_BASE;
diff --git a/arch/arm/mach-exynos/soc.c b/arch/arm/mach-exynos/soc.c
index 810fa34..a07c87a 100644
--- a/arch/arm/mach-exynos/soc.c
+++ b/arch/arm/mach-exynos/soc.c
@@ -20,7 +20,7 @@
 void *secondary_boot_addr = (void *)_main;
 #endif /* CONFIG_TARGET_ESPRESSO7420 */
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 #ifdef CONFIG_CPU_V7A
 	writel(0x1, samsung_get_base_swreset());
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 8f64e23..26bfc5c 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -43,9 +43,9 @@
 
 config IMX_HAB
 	bool "Support i.MX HAB features"
-	depends on ARCH_MX7 || ARCH_MX6 || ARCH_MX5
+	depends on ARCH_MX7 || ARCH_MX6 || ARCH_MX5 || ARCH_IMX8M
 	select FSL_CAAM if HAS_CAAM
-	imply CMD_DEKBLOB
+	imply CMD_DEKBLOB if HAS_CAAM
 	help
 	  This option enables the support for secure boot (HAB).
 	  See doc/imx/habv4/* for more details.
@@ -75,12 +75,43 @@
 
 config CMD_DEKBLOB
 	bool "Support the 'dek_blob' command"
+	select IMX_CAAM_DEK_ENCAP if ARCH_MX6 || ARCH_MX7 || ARCH_MX7ULP
+	select IMX_OPTEE_DEK_ENCAP if ARCH_IMX8M
+	select IMX_SECO_DEK_ENCAP if ARCH_IMX8
 	help
 	  This enables the 'dek_blob' command which is used with the
 	  Freescale secure boot mechanism. This command encapsulates and
 	  creates a blob of data. See also CMD_BLOB and doc/imx/habv4/* for
 	  more information.
 
+config IMX_CAAM_DEK_ENCAP
+	bool "Support the DEK blob encapsulation with CAAM U-Boot driver"
+	help
+	  This enables the DEK blob encapsulation with the U-Boot CAAM driver.
+	  This option is only available on imx6, imx7 and imx7ulp.
+
+config IMX_OPTEE_DEK_ENCAP
+	select TEE
+	select OPTEE
+	bool "Support the DEK blob encapsulation with OP-TEE"
+	help
+	  This enabled the DEK blob encapsulation with OP-TEE. The communication
+	  with OP-TEE is done through a SMC call and OP-TEE shared memory. This
+	  option is available on imx8mm.
+
+config IMX_SECO_DEK_ENCAP
+	bool "Support the DEK blob encapsulation with SECO"
+	help
+	  This enabled the DEK blob encapsulation with the SECO API. This option
+	  is only available on imx8.
+
+config CMD_PRIBLOB
+	bool "Support the set_priblob_bitfield command"
+	depends on HAS_CAAM && IMX_HAB
+	help
+	  This option enables the priblob command which can be used
+		to set the priblob setting to 0x3.
+
 config CMD_HDMIDETECT
 	bool "Support the 'hdmidet' command"
 	help
@@ -99,6 +130,15 @@
 	  This is similar to kobs-ng, which is used in Linux as separate
 	  rootfs package.
 
+config FSL_MFGPROT
+	bool "Support the 'mfgprot' command"
+	depends on IMX_HAB && ARCH_MX7
+	help
+	  This option enables the manufacturing protection command
+	  which can be used has a protection feature for Manufacturing
+	  process. With this tool is possible to authenticate the
+	  chip to the OEM's server.
+
 config NXP_BOARD_REVISION
 	bool "Read NXP board revision from fuses"
 	depends on ARCH_MX6 || ARCH_MX7
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index e6b4654..82aa39d 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -16,6 +16,7 @@
 obj-$(CONFIG_ENV_IS_IN_MMC) += mmc_env.o
 obj-$(CONFIG_FEC_MXC) += mac.o
 obj-$(CONFIG_SYS_I2C_MXC) += i2c-mxv7.o
+obj-$(CONFIG_IMX_HAB) += hab.o
 obj-y += cpu.o
 endif
 
@@ -29,12 +30,14 @@
 endif
 ifeq ($(SOC),$(filter $(SOC),mx7 mx6 mxs imx8m imx8 imxrt))
 obj-y	+= misc.o
+obj-$(CONFIG_CMD_PRIBLOB) += priblob.o
 obj-$(CONFIG_SPL_BUILD)	+= spl.o
 endif
 ifeq ($(SOC),$(filter $(SOC),mx7))
 obj-y 	+= cpu.o
 obj-$(CONFIG_SYS_I2C_MXC) += i2c-mxv7.o
 obj-$(CONFIG_ENV_IS_IN_MMC) += mmc_env.o
+obj-$(CONFIG_FSL_MFGPROT) += cmd_mfgprot.o
 endif
 ifeq ($(SOC),$(filter $(SOC),mx5 mx6 mx7))
 obj-$(CONFIG_IMX_VIDEO_SKIP) += video.o
diff --git a/arch/arm/mach-imx/cmd_dek.c b/arch/arm/mach-imx/cmd_dek.c
index 49dd473..b10ead1 100644
--- a/arch/arm/mach-imx/cmd_dek.c
+++ b/arch/arm/mach-imx/cmd_dek.c
@@ -14,6 +14,12 @@
 #include <fsl_sec.h>
 #include <asm/arch/clock.h>
 #include <mapmem.h>
+#include <tee.h>
+#ifdef CONFIG_IMX_SECO_DEK_ENCAP
+#include <asm/arch/sci/sci.h>
+#include <asm/arch/image.h>
+#endif
+#include <cpu_func.h>
 
 /**
 * blob_dek() - Encapsulate the DEK as a blob using CAM's Key
@@ -23,16 +29,20 @@
 *
 * Returns zero on success,and negative on error.
 */
-static int blob_encap_dek(const u8 *src, u8 *dst, u32 len)
+#ifdef CONFIG_IMX_CAAM_DEK_ENCAP
+static int blob_encap_dek(u32 src_addr, u32 dst_addr, u32 len)
 {
-	int ret = 0;
-	u32 jr_size = 4;
+	u8 *src_ptr, *dst_ptr;
 
-	u32 out_jr_size = sec_in32(CONFIG_SYS_FSL_JR0_ADDR + 0x102c);
-	if (out_jr_size != jr_size) {
-		hab_caam_clock_enable(1);
+	src_ptr = map_sysmem(src_addr, len / 8);
+	dst_ptr = map_sysmem(dst_addr, BLOB_SIZE(len / 8));
+
+	hab_caam_clock_enable(1);
+
+	u32 out_jr_size = sec_in32(CONFIG_SYS_FSL_JR0_ADDR +
+				   FSL_CAAM_ORSR_JRa_OFFSET);
+	if (out_jr_size != FSL_CAAM_MAX_JR_SIZE)
 		sec_init();
-	}
 
 	if (!((len == 128) | (len == 192) | (len == 256))) {
 		debug("Invalid DEK size. Valid sizes are 128, 192 and 256b\n");
@@ -40,10 +50,237 @@
 	}
 
 	len /= 8;
-	ret = blob_dek(src, dst, len);
+	return blob_dek(src_ptr, dst_ptr, len);
+}
+#endif /* CONFIG_IMX_CAAM_DEK_ENCAP */
+
+#ifdef CONFIG_IMX_OPTEE_DEK_ENCAP
+
+#define PTA_DEK_BLOB_PTA_UUID {0xef477737, 0x0db1, 0x4a9d, \
+	{0x84, 0x37, 0xf2, 0xf5, 0x35, 0xc0, 0xbd, 0x92} }
+
+#define OPTEE_BLOB_HDR_SIZE		8
+
+static int blob_encap_dek(u32 src_addr, u32 dst_addr, u32 len)
+{
+	struct udevice *dev = NULL;
+	struct tee_shm *shm_input, *shm_output;
+	struct tee_open_session_arg arg = {0};
+	struct tee_invoke_arg arg_func = {0};
+	const struct tee_optee_ta_uuid uuid = PTA_DEK_BLOB_PTA_UUID;
+	struct tee_param param[4] = {0};
+	int ret;
+
+	/* Get tee device */
+	dev = tee_find_device(NULL, NULL, NULL, NULL);
+	if (!dev) {
+		printf("Cannot get OP-TEE device\n");
+		return -1;
+	}
+
+	/* Set TA UUID */
+	tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
+
+	/* Open TA session */
+	ret = tee_open_session(dev, &arg, 0, NULL);
+	if (ret < 0) {
+		printf("Cannot open session with PTA Blob 0x%X\n", ret);
+		return -1;
+	}
+
+	/* Allocate shared input and output buffers for TA */
+	ret = tee_shm_register(dev, (void *)(ulong)src_addr, len / 8, 0x0, &shm_input);
+	if (ret < 0) {
+		printf("Cannot register input shared memory 0x%X\n", ret);
+		goto error;
+	}
+
+	ret = tee_shm_register(dev, (void *)(ulong)dst_addr,
+			       BLOB_SIZE(len / 8) + OPTEE_BLOB_HDR_SIZE,
+			       0x0, &shm_output);
+	if (ret < 0) {
+		printf("Cannot register output shared memory 0x%X\n", ret);
+		goto error;
+	}
+
+	param[0].u.memref.shm	= shm_input;
+	param[0].u.memref.size	= shm_input->size;
+	param[0].attr		= TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
+	param[1].u.memref.shm	= shm_output;
+	param[1].u.memref.size	= shm_output->size;
+	param[1].attr		= TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+	param[2].attr		= TEE_PARAM_ATTR_TYPE_NONE;
+	param[3].attr		= TEE_PARAM_ATTR_TYPE_NONE;
+
+	arg_func.func = 0;
+	arg_func.session = arg.session;
+
+	/* Generate DEK blob */
+	arg_func.session = arg.session;
+	ret = tee_invoke_func(dev, &arg_func, 4, param);
+	if (ret < 0)
+		printf("Cannot generate Blob with PTA DEK Blob 0x%X\n", ret);
+
+error:
+	/* Free shared memory */
+	tee_shm_free(shm_input);
+	tee_shm_free(shm_output);
+
+	/* Close session */
+	ret = tee_close_session(dev, arg.session);
+	if (ret < 0)
+		printf("Cannot close session with PTA DEK Blob 0x%X\n", ret);
 
 	return ret;
 }
+#endif /* CONFIG_IMX_OPTEE_DEK_ENCAP */
+#ifdef CONFIG_IMX_SECO_DEK_ENCAP
+
+#define DEK_BLOB_KEY_ID				0x0
+
+#define AHAB_PRIVATE_KEY			0x81
+#define AHAB_VERSION				0x00
+#define AHAB_MODE_CBC				0x67
+#define AHAB_ALG_AES				0x55
+#define AHAB_128_AES_KEY			0x10
+#define AHAB_192_AES_KEY			0x18
+#define AHAB_256_AES_KEY			0x20
+#define AHAB_FLAG_KEK				0x80
+#define AHAB_DEK_BLOB				0x01
+
+#define DEK_BLOB_HDR_SIZE			8
+#define SECO_PT					2U
+
+static int blob_encap_dek(u32 src_addr, u32 dst_addr, u32 len)
+{
+	sc_err_t err;
+	sc_rm_mr_t mr_input, mr_output;
+	struct generate_key_blob_hdr hdr;
+	u8 in_size, out_size;
+	u8 *src_ptr, *dst_ptr;
+	int ret = 0;
+	int i;
+
+	/* Set sizes */
+	in_size = sizeof(struct generate_key_blob_hdr) + len / 8;
+	out_size = BLOB_SIZE(len / 8) + DEK_BLOB_HDR_SIZE;
+
+	/* Get src and dst virtual addresses */
+	src_ptr = map_sysmem(src_addr, in_size);
+	dst_ptr = map_sysmem(dst_addr, out_size);
+
+	/* Check addr input */
+	if (!(src_ptr && dst_ptr)) {
+		debug("src_addr or dst_addr invalid\n");
+		return -1;
+	}
+
+	/* Build key header */
+	hdr.version = AHAB_VERSION;
+	hdr.length_lsb = sizeof(struct generate_key_blob_hdr) + len / 8;
+	hdr.length_msb = 0x00;
+	hdr.tag = AHAB_PRIVATE_KEY;
+	hdr.flags = AHAB_DEK_BLOB;
+	hdr.algorithm = AHAB_ALG_AES;
+	hdr.mode = AHAB_MODE_CBC;
+
+	switch (len) {
+	case 128:
+		hdr.size = AHAB_128_AES_KEY;
+		break;
+	case 192:
+		hdr.size = AHAB_192_AES_KEY;
+		break;
+	case 256:
+		hdr.size = AHAB_256_AES_KEY;
+		break;
+	default:
+		/* Not supported */
+		debug("Invalid DEK size. Valid sizes are 128, 192 and 256b\n");
+		return -1;
+	}
+
+	/* Build input message */
+	memmove((void *)(src_ptr + sizeof(struct generate_key_blob_hdr)),
+		(void *)src_ptr, len / 8);
+	memcpy((void *)src_ptr, (void *)&hdr,
+	       sizeof(struct generate_key_blob_hdr));
+
+	/* Flush the cache before triggering the CAAM DMA */
+	flush_dcache_range(src_addr, src_addr + in_size);
+
+	/* Find input memory region */
+	err = sc_rm_find_memreg((-1), &mr_input, src_addr & ~(CONFIG_SYS_CACHELINE_SIZE - 1),
+				ALIGN(src_addr + in_size, CONFIG_SYS_CACHELINE_SIZE));
+	if (err) {
+		printf("Error: find memory region 0x%X\n", src_addr);
+		return -ENOMEM;
+	}
+
+	/* Find output memory region */
+	err = sc_rm_find_memreg((-1), &mr_output, dst_addr & ~(CONFIG_SYS_CACHELINE_SIZE - 1),
+				ALIGN(dst_addr + out_size, CONFIG_SYS_CACHELINE_SIZE));
+	if (err) {
+		printf("Error: find memory region 0x%X\n", dst_addr);
+		return -ENOMEM;
+	}
+
+	/* Set memory region permissions for SECO */
+	err = sc_rm_set_memreg_permissions(-1, mr_input, SECO_PT,
+					   SC_RM_PERM_FULL);
+	if (err) {
+		printf("Set permission failed for input memory region\n");
+		ret = -EPERM;
+		goto error;
+	}
+
+	err = sc_rm_set_memreg_permissions(-1, mr_output, SECO_PT,
+					   SC_RM_PERM_FULL);
+	if (err) {
+		printf("Set permission failed for output memory region\n");
+		ret = -EPERM;
+		goto error;
+	}
+
+	/* Flush output data before SECO operation */
+	flush_dcache_range((ulong)dst_ptr, (ulong)(dst_ptr +
+			roundup(out_size, ARCH_DMA_MINALIGN)));
+
+	/* Generate DEK blob */
+	err = sc_seco_gen_key_blob((-1), 0x0, src_addr, dst_addr, out_size);
+	if (err) {
+		ret = -EPERM;
+		goto error;
+	}
+
+	/* Invalidate output buffer */
+	invalidate_dcache_range((ulong)dst_ptr, (ulong)(dst_ptr +
+			roundup(out_size, ARCH_DMA_MINALIGN)));
+
+	printf("DEK Blob\n");
+	for (i = 0; i < DEK_BLOB_HDR_SIZE + BLOB_SIZE(len / 8); i++)
+		printf("%02X", dst_ptr[i]);
+	printf("\n");
+
+error:
+	/* Remove memory region permission to SECO */
+	err = sc_rm_set_memreg_permissions(-1, mr_input, SECO_PT,
+					   SC_RM_PERM_NONE);
+	if (err) {
+		printf("Error: remove permission failed for input\n");
+		ret = -EPERM;
+	}
+
+	err = sc_rm_set_memreg_permissions(-1, mr_output, SECO_PT,
+					   SC_RM_PERM_NONE);
+	if (err) {
+		printf("Error: remove permission failed for output\n");
+		ret = -EPERM;
+	}
+
+	return ret;
+}
+#endif /* CONFIG_IMX_SECO_DEK_ENCAP */
 
 /**
  * do_dek_blob() - Handle the "dek_blob" command-line command
@@ -59,8 +296,6 @@
 		       char *const argv[])
 {
 	uint32_t src_addr, dst_addr, len;
-	uint8_t *src_ptr, *dst_ptr;
-	int ret = 0;
 
 	if (argc != 4)
 		return CMD_RET_USAGE;
@@ -69,12 +304,7 @@
 	dst_addr = simple_strtoul(argv[2], NULL, 16);
 	len = simple_strtoul(argv[3], NULL, 10);
 
-	src_ptr = map_sysmem(src_addr, len/8);
-	dst_ptr = map_sysmem(dst_addr, BLOB_SIZE(len/8));
-
-	ret = blob_encap_dek(src_ptr, dst_ptr, len);
-
-	return ret;
+	return blob_encap_dek(src_addr, dst_addr, len);
 }
 
 /***************************************************/
diff --git a/arch/arm/mach-imx/cmd_mfgprot.c b/arch/arm/mach-imx/cmd_mfgprot.c
new file mode 100644
index 0000000..1430f61
--- /dev/null
+++ b/arch/arm/mach-imx/cmd_mfgprot.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ *
+ * These commands enable the use of the CAAM MPPubK-generation and MPSign
+ * functions in supported i.MX devices.
+ */
+
+#include <asm/byteorder.h>
+#include <asm/arch/clock.h>
+#include <linux/compiler.h>
+#include <command.h>
+#include <common.h>
+#include <environment.h>
+#include <fsl_sec.h>
+#include <mapmem.h>
+#include <memalign.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * do_mfgprot() - Handle the "mfgprot" command-line command
+ * @cmdtp:  Command data struct pointer
+ * @flag:   Command flag
+ * @argc:   Command-line argument count
+ * @argv:   Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
+static int do_mfgprot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	u8 *m_ptr, *dgst_ptr, *c_ptr, *d_ptr, *dst_ptr;
+	char *pubk, *sign, *sel;
+	int m_size, i, ret;
+	u32 m_addr;
+
+	pubk = "pubk";
+	sign = "sign";
+	sel = argv[1];
+
+	/* Enable HAB clock */
+	hab_caam_clock_enable(1);
+
+	u32 out_jr_size = sec_in32(CONFIG_SYS_FSL_JR0_ADDR +
+				   FSL_CAAM_ORSR_JRa_OFFSET);
+
+	if (out_jr_size != FSL_CAAM_MAX_JR_SIZE)
+		sec_init();
+
+	if (strcmp(sel, pubk) == 0) {
+		dst_ptr = malloc_cache_aligned(FSL_CAAM_MP_PUBK_BYTES);
+		if (!dst_ptr)
+			return -ENOMEM;
+
+		ret = gen_mppubk(dst_ptr);
+		if (ret) {
+			free(dst_ptr);
+			return ret;
+		}
+
+		/* Output results */
+		puts("Public key:\n");
+		for (i = 0; i < FSL_CAAM_MP_PUBK_BYTES; i++)
+			printf("%02X", (dst_ptr)[i]);
+		puts("\n");
+		free(dst_ptr);
+
+	} else if (strcmp(sel, sign) == 0) {
+		if (argc != 4)
+			return CMD_RET_USAGE;
+
+		m_addr = simple_strtoul(argv[2], NULL, 16);
+		m_size = simple_strtoul(argv[3], NULL, 10);
+		m_ptr = map_physmem(m_addr, m_size, MAP_NOCACHE);
+		if (!m_ptr)
+			return -ENOMEM;
+
+		dgst_ptr = malloc_cache_aligned(FSL_CAAM_MP_MES_DGST_BYTES);
+		if (!dgst_ptr) {
+			ret = -ENOMEM;
+			goto free_m;
+		}
+
+		c_ptr = malloc_cache_aligned(FSL_CAAM_MP_PRVK_BYTES);
+		if (!c_ptr) {
+			ret = -ENOMEM;
+			goto free_dgst;
+		}
+
+		d_ptr = malloc_cache_aligned(FSL_CAAM_MP_PRVK_BYTES);
+		if (!d_ptr) {
+			ret = -ENOMEM;
+			goto free_c;
+		}
+
+		ret = sign_mppubk(m_ptr, m_size, dgst_ptr, c_ptr, d_ptr);
+		if (ret)
+			goto free_d;
+
+		/* Output results */
+		puts("Message: ");
+		for (i = 0; i < m_size; i++)
+			printf("%02X ", (m_ptr)[i]);
+		puts("\n");
+
+		puts("Message Representative Digest(SHA-256):\n");
+		for (i = 0; i < FSL_CAAM_MP_MES_DGST_BYTES; i++)
+			printf("%02X", (dgst_ptr)[i]);
+		puts("\n");
+
+		puts("Signature:\n");
+		puts("C:\n");
+		for (i = 0; i < FSL_CAAM_MP_PRVK_BYTES; i++)
+			printf("%02X", (c_ptr)[i]);
+		puts("\n");
+
+		puts("d:\n");
+		for (i = 0; i < FSL_CAAM_MP_PRVK_BYTES; i++)
+			printf("%02X", (d_ptr)[i]);
+		puts("\n");
+free_d:
+	free(d_ptr);
+free_c:
+	free(c_ptr);
+free_dgst:
+	free(dgst_ptr);
+free_m:
+	unmap_sysmem(m_ptr);
+
+	} else {
+		return CMD_RET_USAGE;
+	}
+	return ret;
+}
+
+/***************************************************/
+static char mfgprot_help_text[] =
+	"Usage:\n"
+	 "Print the public key for Manufacturing Protection\n"
+	 "\tmfgprot pubk\n"
+	 "Generates a Manufacturing Protection signature\n"
+	 "\tmfgprot sign <data_addr> <size>";
+
+U_BOOT_CMD(
+	mfgprot, 4, 1, do_mfgprot,
+	"Manufacturing Protection\n",
+	mfgprot_help_text
+);
diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c
index 38b87ed..423b715 100644
--- a/arch/arm/mach-imx/cpu.c
+++ b/arch/arm/mach-imx/cpu.c
@@ -117,7 +117,13 @@
 	case MXC_CPU_IMX8MNDL:
 		return "8MNano DualLite"; /* Dual-core Lite version */
 	case MXC_CPU_IMX8MNSL:
-		return "8MNano SoloLite"; /* Single-core Lite version */
+		return "8MNano SoloLite";/* Single-core Lite version of the imx8mn */
+	case MXC_CPU_IMX8MNUQ:
+		return "8MNano UltraLite Quad";/* Quad-core UltraLite version of the imx8mn */
+	case MXC_CPU_IMX8MNUD:
+		return "8MNano UltraLite Dual";/* Dual-core UltraLite version of the imx8mn */
+	case MXC_CPU_IMX8MNUS:
+		return "8MNano UltraLite Solo";/* Single-core UltraLite version of the imx8mn */
 	case MXC_CPU_IMX8MM:
 		return "8MMQ";	/* Quad-core version of the imx8mm */
 	case MXC_CPU_IMX8MML:
diff --git a/arch/arm/mach-imx/hab.c b/arch/arm/mach-imx/hab.c
index d0757d8..00bd157 100644
--- a/arch/arm/mach-imx/hab.c
+++ b/arch/arm/mach-imx/hab.c
@@ -10,10 +10,14 @@
 #include <mapmem.h>
 #include <image.h>
 #include <asm/io.h>
+#include <asm/global_data.h>
 #include <asm/system.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/mach-imx/hab.h>
+#include <linux/arm-smccc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
 
 #define ALIGN_SIZE		0x1000
 #define MX6DQ_PU_IROM_MMU_EN_VAR	0x009024a8
@@ -21,7 +25,13 @@
 #define MX6SL_PU_IROM_MMU_EN_VAR	0x00901c60
 #define IS_HAB_ENABLED_BIT \
 	(is_soc_type(MXC_SOC_MX7ULP) ? 0x80000000 :	\
-	 (is_soc_type(MXC_SOC_MX7) ? 0x2000000 : 0x2))
+	 ((is_soc_type(MXC_SOC_MX7) || is_soc_type(MXC_SOC_IMX8M)) ? 0x2000000 : 0x2))
+
+#ifdef CONFIG_MX7ULP
+#define HAB_M4_PERSISTENT_START	((soc_rev() >= CHIP_REV_2_0) ? 0x20008040 : \
+				  0x20008180)
+#define HAB_M4_PERSISTENT_BYTES		0xB80
+#endif
 
 static int ivt_header_error(const char *err_str, struct ivt_header *ivt_hdr)
 {
@@ -41,13 +51,200 @@
 	if (be16_to_cpu(ivt_hdr->length) != IVT_TOTAL_LENGTH)
 		result = ivt_header_error("bad length", ivt_hdr);
 
-	if (ivt_hdr->version != IVT_HEADER_V1 &&
-	    ivt_hdr->version != IVT_HEADER_V2)
+	if ((ivt_hdr->version & HAB_MAJ_MASK) != HAB_MAJ_VER)
 		result = ivt_header_error("bad version", ivt_hdr);
 
 	return result;
 }
 
+#ifdef CONFIG_ARM64
+#define FSL_SIP_HAB		0xC2000007
+#define FSL_SIP_HAB_AUTHENTICATE	0x00
+#define FSL_SIP_HAB_ENTRY		0x01
+#define FSL_SIP_HAB_EXIT		0x02
+#define FSL_SIP_HAB_REPORT_EVENT	0x03
+#define FSL_SIP_HAB_REPORT_STATUS	0x04
+#define FSL_SIP_HAB_FAILSAFE		0x05
+#define FSL_SIP_HAB_CHECK_TARGET	0x06
+static volatile gd_t *gd_save;
+#endif
+
+static inline void save_gd(void)
+{
+#ifdef CONFIG_ARM64
+	gd_save = gd;
+#endif
+}
+
+static inline void restore_gd(void)
+{
+#ifdef CONFIG_ARM64
+	/*
+	 * Make will already error that reserving x18 is not supported at the
+	 * time of writing, clang: error: unknown argument: '-ffixed-x18'
+	 */
+	__asm__ volatile("mov x18, %0\n" : : "r" (gd_save));
+#endif
+}
+
+enum hab_status hab_rvt_report_event(enum hab_status status, u32 index,
+				     u8 *event, size_t *bytes)
+{
+	enum hab_status ret;
+	hab_rvt_report_event_t *hab_rvt_report_event_func;
+	struct arm_smccc_res res __maybe_unused;
+
+	hab_rvt_report_event_func =  (hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT;
+#if defined(CONFIG_ARM64)
+	if (current_el() != 3) {
+		/* call sip */
+		arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_REPORT_EVENT, (unsigned long)index,
+			      (unsigned long)event, (unsigned long)bytes, 0, 0, 0, &res);
+		return (enum hab_status)res.a0;
+	}
+#endif
+
+	save_gd();
+	ret = hab_rvt_report_event_func(status, index, event, bytes);
+	restore_gd();
+
+	return ret;
+
+}
+
+enum hab_status hab_rvt_report_status(enum hab_config *config, enum hab_state *state)
+{
+	enum hab_status ret;
+	hab_rvt_report_status_t *hab_rvt_report_status_func;
+	struct arm_smccc_res res __maybe_unused;
+
+	hab_rvt_report_status_func = (hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS;
+#if defined(CONFIG_ARM64)
+	if (current_el() != 3) {
+		/* call sip */
+		arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_REPORT_STATUS, (unsigned long)config,
+			      (unsigned long)state, 0, 0, 0, 0, &res);
+		return (enum hab_status)res.a0;
+	}
+#endif
+
+	save_gd();
+	ret = hab_rvt_report_status_func(config, state);
+	restore_gd();
+
+	return ret;
+}
+
+enum hab_status hab_rvt_entry(void)
+{
+	enum hab_status ret;
+	hab_rvt_entry_t *hab_rvt_entry_func;
+	struct arm_smccc_res res __maybe_unused;
+
+	hab_rvt_entry_func = (hab_rvt_entry_t *)HAB_RVT_ENTRY;
+#if defined(CONFIG_ARM64)
+	if (current_el() != 3) {
+		/* call sip */
+		arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_ENTRY, 0, 0, 0, 0, 0, 0, &res);
+		return (enum hab_status)res.a0;
+	}
+#endif
+
+	save_gd();
+	ret = hab_rvt_entry_func();
+	restore_gd();
+
+	return ret;
+}
+
+enum hab_status hab_rvt_exit(void)
+{
+	enum hab_status ret;
+	hab_rvt_exit_t *hab_rvt_exit_func;
+	struct arm_smccc_res res __maybe_unused;
+
+	hab_rvt_exit_func =  (hab_rvt_exit_t *)HAB_RVT_EXIT;
+#if defined(CONFIG_ARM64)
+	if (current_el() != 3) {
+		/* call sip */
+		arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_EXIT, 0, 0, 0, 0, 0, 0, &res);
+		return (enum hab_status)res.a0;
+	}
+#endif
+
+	save_gd();
+	ret = hab_rvt_exit_func();
+	restore_gd();
+
+	return ret;
+}
+
+void hab_rvt_failsafe(void)
+{
+	hab_rvt_failsafe_t *hab_rvt_failsafe_func;
+
+	hab_rvt_failsafe_func = (hab_rvt_failsafe_t *)HAB_RVT_FAILSAFE;
+#if defined(CONFIG_ARM64)
+	if (current_el() != 3) {
+		/* call sip */
+		arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_FAILSAFE, 0, 0, 0, 0, 0, 0, NULL);
+		return;
+	}
+#endif
+
+	save_gd();
+	hab_rvt_failsafe_func();
+	restore_gd();
+}
+
+enum hab_status hab_rvt_check_target(enum hab_target type, const void *start,
+					       size_t bytes)
+{
+	enum hab_status ret;
+	hab_rvt_check_target_t *hab_rvt_check_target_func;
+	struct arm_smccc_res res __maybe_unused;
+
+	hab_rvt_check_target_func =  (hab_rvt_check_target_t *)HAB_RVT_CHECK_TARGET;
+#if defined(CONFIG_ARM64)
+	if (current_el() != 3) {
+		/* call sip */
+		arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_CHECK_TARGET, (unsigned long)type,
+			      (unsigned long)start, (unsigned long)bytes, 0, 0, 0, &res);
+		return (enum hab_status)res.a0;
+	}
+#endif
+
+	save_gd();
+	ret = hab_rvt_check_target_func(type, start, bytes);
+	restore_gd();
+
+	return ret;
+}
+
+void *hab_rvt_authenticate_image(uint8_t cid, ptrdiff_t ivt_offset,
+				 void **start, size_t *bytes, hab_loader_callback_f_t loader)
+{
+	void *ret;
+	hab_rvt_authenticate_image_t *hab_rvt_authenticate_image_func;
+	struct arm_smccc_res res __maybe_unused;
+
+	hab_rvt_authenticate_image_func = (hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE;
+#if defined(CONFIG_ARM64)
+	if (current_el() != 3) {
+		/* call sip */
+		arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_AUTHENTICATE, (unsigned long)ivt_offset,
+			      (unsigned long)start, (unsigned long)bytes, 0, 0, 0, &res);
+		return (void *)res.a0;
+	}
+#endif
+
+	save_gd();
+	ret = hab_rvt_authenticate_image_func(cid, ivt_offset, start, bytes, loader);
+	restore_gd();
+
+	return ret;
+}
+
 #if !defined(CONFIG_SPL_BUILD)
 
 #define MAX_RECORD_BYTES     (8*1024) /* 4 kbytes */
@@ -253,12 +450,6 @@
 	size_t bytes = sizeof(event_data); /* Event size in bytes */
 	enum hab_config config = 0;
 	enum hab_state state = 0;
-	hab_rvt_report_event_t *hab_rvt_report_event;
-	hab_rvt_report_status_t *hab_rvt_report_status;
-
-	hab_rvt_report_event = (hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT;
-	hab_rvt_report_status =
-			(hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS;
 
 	if (imx_hab_is_enabled())
 		puts("\nSecure boot enabled\n");
@@ -270,8 +461,8 @@
 		printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
 		       config, state);
 
-		/* Display HAB Error events */
-		while (hab_rvt_report_event(HAB_FAILURE, index, event_data,
+		/* Display HAB events */
+		while (hab_rvt_report_event(HAB_STS_ANY, index, event_data,
 					&bytes) == HAB_SUCCESS) {
 			puts("\n");
 			printf("--------- HAB Event %d -----------------\n",
@@ -292,15 +483,99 @@
 	return 0;
 }
 
+#ifdef CONFIG_MX7ULP
+
+static int get_record_len(struct record *rec)
+{
+	return (size_t)((rec->len[0] << 8) + (rec->len[1]));
+}
+
+static int get_hab_status_m4(void)
+{
+	unsigned int index = 0;
+	uint8_t event_data[128];
+	size_t record_len, offset = 0;
+	enum hab_config config = 0;
+	enum hab_state state = 0;
+
+	if (imx_hab_is_enabled())
+		puts("\nSecure boot enabled\n");
+	else
+		puts("\nSecure boot disabled\n");
+
+	/*
+	 * HAB in both A7 and M4 gather the security state
+	 * and configuration of the chip from
+	 * shared SNVS module
+	 */
+	hab_rvt_report_status(&config, &state);
+	printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
+	       config, state);
+
+	struct record *rec = (struct record *)(HAB_M4_PERSISTENT_START);
+
+	record_len = get_record_len(rec);
+
+	/* Check if HAB persistent memory is valid */
+	if (rec->tag != HAB_TAG_EVT_DEF ||
+	    record_len != sizeof(struct evt_def) ||
+	    (rec->par & HAB_MAJ_MASK) != HAB_MAJ_VER) {
+		puts("\nERROR: Invalid HAB persistent memory\n");
+		return 1;
+	}
+
+	/* Parse events in HAB M4 persistent memory region */
+	while (offset < HAB_M4_PERSISTENT_BYTES) {
+		rec = (struct record *)(HAB_M4_PERSISTENT_START + offset);
+
+		record_len = get_record_len(rec);
+
+		if (rec->tag == HAB_TAG_EVT) {
+			memcpy(&event_data, rec, record_len);
+			puts("\n");
+			printf("--------- HAB Event %d -----------------\n",
+			       index + 1);
+			puts("event data:\n");
+			display_event(event_data, record_len);
+			puts("\n");
+			index++;
+		}
+
+		offset += record_len;
+
+		/* Ensure all records start on a word boundary */
+		if ((offset % 4) != 0)
+			offset =  offset + (4 - (offset % 4));
+	}
+
+	if (!index)
+		puts("No HAB Events Found!\n\n");
+
+	return 0;
+}
+#endif
+
 static int do_hab_status(struct cmd_tbl *cmdtp, int flag, int argc,
 			 char *const argv[])
 {
+#ifdef CONFIG_MX7ULP
+	if ((argc > 2)) {
+		cmd_usage(cmdtp);
+		return 1;
+	}
+
+	if (strcmp("m4", argv[1]) == 0)
+		get_hab_status_m4();
+	else
+		get_hab_status();
+#else
 	if ((argc != 1)) {
 		cmd_usage(cmdtp);
 		return 1;
 	}
 
 	get_hab_status();
+#endif
 
 	return 0;
 }
@@ -353,14 +628,11 @@
 static int do_hab_failsafe(struct cmd_tbl *cmdtp, int flag, int argc,
 			   char *const argv[])
 {
-	hab_rvt_failsafe_t *hab_rvt_failsafe;
-
 	if (argc != 1) {
 		cmd_usage(cmdtp);
 		return 1;
 	}
 
-	hab_rvt_failsafe = (hab_rvt_failsafe_t *)HAB_RVT_FAILSAFE;
 	hab_rvt_failsafe();
 
 	return 0;
@@ -406,11 +678,20 @@
 	return ret;
 }
 
+#ifdef CONFIG_MX7ULP
+U_BOOT_CMD(
+		hab_status, CONFIG_SYS_MAXARGS, 2, do_hab_status,
+		"display HAB status and events",
+		"hab_status - A7 HAB event and status\n"
+		"hab_status m4 - M4 HAB event and status"
+	  );
+#else
 U_BOOT_CMD(
 		hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
 		"display HAB status",
 		""
 	  );
+#endif
 
 U_BOOT_CMD(
 		hab_auth_img, 4, 0, do_authenticate_image,
@@ -493,7 +774,7 @@
 		return false;
 	}
 
-	csf_hdr = (u8 *)ivt->csf;
+	csf_hdr = (u8 *)(ulong)ivt->csf;
 
 	/* Verify if CSF Header exist */
 	if (*csf_hdr != HAB_CMD_HDR) {
@@ -542,6 +823,48 @@
 	return true;
 }
 
+/*
+ * Validate IVT structure of the image being authenticated
+ */
+static int validate_ivt(struct ivt *ivt_initial)
+{
+	struct ivt_header *ivt_hdr = &ivt_initial->hdr;
+
+	if ((ulong)ivt_initial & 0x3) {
+		puts("Error: Image's start address is not 4 byte aligned\n");
+		return 0;
+	}
+
+	/* Check IVT fields before allowing authentication */
+	if ((!verify_ivt_header(ivt_hdr)) && \
+	    (ivt_initial->entry != 0x0) && \
+	    (ivt_initial->reserved1 == 0x0) && \
+	    (ivt_initial->self == \
+		   (uint32_t)((ulong)ivt_initial & 0xffffffff)) && \
+	    (ivt_initial->csf != 0x0) && \
+	    (ivt_initial->reserved2 == 0x0)) {
+		/* Report boot failure if DCD pointer is found in IVT */
+		if (ivt_initial->dcd != 0x0)
+			puts("Error: DCD pointer must be 0\n");
+		else
+			return 1;
+	}
+
+	puts("Error: Invalid IVT structure\n");
+	debug("\nAllowed IVT structure:\n");
+	debug("IVT HDR       = 0x4X2000D1\n");
+	debug("IVT ENTRY     = 0xXXXXXXXX\n");
+	debug("IVT RSV1      = 0x0\n");
+	debug("IVT DCD       = 0x0\n");		/* Recommended */
+	debug("IVT BOOT_DATA = 0xXXXXXXXX\n");	/* Commonly 0x0 */
+	debug("IVT SELF      = 0xXXXXXXXX\n");	/* = ddr_start + ivt_offset */
+	debug("IVT CSF       = 0xXXXXXXXX\n");
+	debug("IVT RSV2      = 0x0\n");
+
+	/* Invalid IVT structure */
+	return 0;
+}
+
 bool imx_hab_is_enabled(void)
 {
 	struct imx_sec_config_fuse_t *fuse =
@@ -561,29 +884,16 @@
 int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
 			       uint32_t ivt_offset)
 {
-	uint32_t load_addr = 0;
+	ulong load_addr = 0;
 	size_t bytes;
-	uint32_t ivt_addr = 0;
+	ulong ivt_addr = 0;
 	int result = 1;
 	ulong start;
-	hab_rvt_authenticate_image_t *hab_rvt_authenticate_image;
-	hab_rvt_entry_t *hab_rvt_entry;
-	hab_rvt_exit_t *hab_rvt_exit;
-	hab_rvt_check_target_t *hab_rvt_check_target;
 	struct ivt *ivt;
-	struct ivt_header *ivt_hdr;
 	enum hab_status status;
 
-	hab_rvt_authenticate_image =
-		(hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE;
-	hab_rvt_entry = (hab_rvt_entry_t *)HAB_RVT_ENTRY;
-	hab_rvt_exit = (hab_rvt_exit_t *)HAB_RVT_EXIT;
-	hab_rvt_check_target = (hab_rvt_check_target_t *)HAB_RVT_CHECK_TARGET;
-
-	if (!imx_hab_is_enabled()) {
+	if (!imx_hab_is_enabled())
 		puts("hab fuse not enabled\n");
-		return 0;
-	}
 
 	printf("\nAuthenticate image from DDR location 0x%x...\n",
 	       ddr_start);
@@ -591,27 +901,13 @@
 	hab_caam_clock_enable(1);
 
 	/* Calculate IVT address header */
-	ivt_addr = ddr_start + ivt_offset;
+	ivt_addr = (ulong) (ddr_start + ivt_offset);
 	ivt = (struct ivt *)ivt_addr;
-	ivt_hdr = &ivt->hdr;
 
 	/* Verify IVT header bugging out on error */
-	if (verify_ivt_header(ivt_hdr))
+	if (!validate_ivt(ivt))
 		goto hab_authentication_exit;
 
-	/* Verify IVT body */
-	if (ivt->self != ivt_addr) {
-		printf("ivt->self 0x%08x pointer is 0x%08x\n",
-		       ivt->self, ivt_addr);
-		goto hab_authentication_exit;
-	}
-
-	/* Verify if IVT DCD pointer is NULL */
-	if (ivt->dcd) {
-		puts("Error: DCD pointer must be NULL\n");
-		goto hab_authentication_exit;
-	}
-
 	start = ddr_start;
 	bytes = image_size;
 
@@ -624,14 +920,14 @@
 		goto hab_exit_failure_print_status;
 	}
 
-	status = hab_rvt_check_target(HAB_TGT_MEMORY, (void *)ddr_start, bytes);
+	status = hab_rvt_check_target(HAB_TGT_MEMORY, (void *)(ulong)ddr_start, bytes);
 	if (status != HAB_SUCCESS) {
-		printf("HAB check target 0x%08x-0x%08x fail\n",
-		       ddr_start, ddr_start + bytes);
+		printf("HAB check target 0x%08x-0x%08lx fail\n",
+		       ddr_start, ddr_start + (ulong)bytes);
 		goto hab_exit_failure_print_status;
 	}
 #ifdef DEBUG
-	printf("\nivt_offset = 0x%x, ivt addr = 0x%x\n", ivt_offset, ivt_addr);
+	printf("\nivt_offset = 0x%x, ivt addr = 0x%lx\n", ivt_offset, ivt_addr);
 	printf("ivt entry = 0x%08x, dcd = 0x%08x, csf = 0x%08x\n", ivt->entry,
 	       ivt->dcd, ivt->csf);
 	puts("Dumping IVT\n");
@@ -649,6 +945,8 @@
 	printf("\tstart = 0x%08lx\n", start);
 	printf("\tbytes = 0x%x\n", bytes);
 #endif
+
+#ifndef CONFIG_ARM64
 	/*
 	 * If the MMU is enabled, we have to notify the ROM
 	 * code, or it won't flush the caches when needed.
@@ -676,8 +974,9 @@
 			writel(1, MX6SL_PU_IROM_MMU_EN_VAR);
 		}
 	}
+#endif
 
-	load_addr = (uint32_t)hab_rvt_authenticate_image(
+	load_addr = (ulong)hab_rvt_authenticate_image(
 			HAB_CID_UBOOT,
 			ivt_offset, (void **)&start,
 			(size_t *)&bytes, NULL);
@@ -693,8 +992,20 @@
 
 hab_authentication_exit:
 
-	if (load_addr != 0)
+	if (load_addr != 0 || !imx_hab_is_enabled())
 		result = 0;
 
 	return result;
 }
+
+int authenticate_image(u32 ddr_start, u32 raw_image_size)
+{
+	u32 ivt_offset;
+	size_t bytes;
+
+	ivt_offset = (raw_image_size + ALIGN_SIZE - 1) &
+					~(ALIGN_SIZE - 1);
+	bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE;
+
+	return imx_hab_authenticate_image(ddr_start, bytes, ivt_offset);
+}
diff --git a/arch/arm/mach-imx/imx8/Kconfig b/arch/arm/mach-imx/imx8/Kconfig
index 04b9729..4e76612 100644
--- a/arch/arm/mach-imx/imx8/Kconfig
+++ b/arch/arm/mach-imx/imx8/Kconfig
@@ -2,6 +2,7 @@
 
 config AHAB_BOOT
 	bool "Support i.MX8 AHAB features"
+	imply CMD_DEKBLOB
 	help
 	  This option enables the support for AHAB secure boot.
 
diff --git a/arch/arm/mach-imx/imx8m/Kconfig b/arch/arm/mach-imx/imx8m/Kconfig
index 12b8d0d..c27fb24 100644
--- a/arch/arm/mach-imx/imx8m/Kconfig
+++ b/arch/arm/mach-imx/imx8m/Kconfig
@@ -2,6 +2,7 @@
 
 config IMX8M
 	bool
+	select HAS_CAAM
 	select ROM_UNIFIED_SECTIONS
 
 config IMX8MQ
@@ -39,6 +40,7 @@
 
 config TARGET_IMX8MM_EVK
 	bool "imx8mm LPDDR4 EVK board"
+	select BINMAN
 	select IMX8MM
 	select SUPPORT_SPL
 	select IMX8M_LPDDR4
@@ -49,14 +51,23 @@
 	select SUPPORT_SPL
 	select IMX8M_LPDDR4
 
+config TARGET_IMX8MN_EVK
+	bool "imx8mn LPDDR4 EVK board"
+	select BINMAN
+	select IMX8MN
+	select SUPPORT_SPL
+	select IMX8M_LPDDR4
+
 config TARGET_IMX8MN_DDR4_EVK
 	bool "imx8mn DDR4 EVK board"
+	select BINMAN
 	select IMX8MN
 	select SUPPORT_SPL
 	select IMX8M_DDR4
 
 config TARGET_IMX8MP_EVK
 	bool "imx8mp LPDDR4 EVK board"
+	select BINMAN
 	select IMX8MP
 	select SUPPORT_SPL
 	select IMX8M_LPDDR4
diff --git a/arch/arm/mach-imx/imx8m/clock_imx8mm.c b/arch/arm/mach-imx/imx8m/clock_imx8mm.c
index 4024daf..029d06f 100644
--- a/arch/arm/mach-imx/imx8m/clock_imx8mm.c
+++ b/arch/arm/mach-imx/imx8m/clock_imx8mm.c
@@ -21,6 +21,14 @@
 static struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR;
 
 static u32 get_root_clk(enum clk_root_index clock_id);
+
+#ifdef CONFIG_IMX_HAB
+void hab_caam_clock_enable(unsigned char enable)
+{
+	/* The CAAM clock is always on for iMX8M */
+}
+#endif
+
 void enable_ocotp_clk(unsigned char enable)
 {
 	clock_enable(CCGR_OCOTP, !!enable);
diff --git a/arch/arm/mach-imx/imx8m/clock_imx8mq.c b/arch/arm/mach-imx/imx8m/clock_imx8mq.c
index 759ec6d..8fecc60 100644
--- a/arch/arm/mach-imx/imx8m/clock_imx8mq.c
+++ b/arch/arm/mach-imx/imx8m/clock_imx8mq.c
@@ -310,6 +310,13 @@
 	return root_src_clk / (post_podf + 1) / (pre_podf + 1);
 }
 
+#ifdef CONFIG_IMX_HAB
+void hab_caam_clock_enable(unsigned char enable)
+{
+	/* The CAAM clock is always on for iMX8M */
+}
+#endif
+
 #ifdef CONFIG_MXC_OCOTP
 void enable_ocotp_clk(unsigned char enable)
 {
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c
index 5f37282..36abb2e 100644
--- a/arch/arm/mach-imx/imx8m/soc.c
+++ b/arch/arm/mach-imx/imx8m/soc.c
@@ -105,6 +105,13 @@
 			 PTE_BLOCK_NON_SHARE |
 			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
 	}, {
+		/* OCRAM_S */
+		.virt = 0x180000UL,
+		.phys = 0x180000UL,
+		.size = 0x8000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_OUTER_SHARE
+	}, {
 		/* TCM */
 		.virt = 0x7C0000UL,
 		.phys = 0x7C0000UL,
@@ -324,18 +331,30 @@
 	} else if (type == MXC_CPU_IMX8MN) {
 		switch (value & 0x3) {
 		case 2:
-			if (value & 0x1000000)
-				return MXC_CPU_IMX8MNDL;
-			else
+			if (value & 0x1000000) {
+				if (value & 0x10000000)	 /* MIPI DSI */
+					return MXC_CPU_IMX8MNUD;
+				else
+					return MXC_CPU_IMX8MNDL;
+			} else {
 				return MXC_CPU_IMX8MND;
+			}
 		case 3:
-			if (value & 0x1000000)
-				return MXC_CPU_IMX8MNSL;
-			else
+			if (value & 0x1000000) {
+				if (value & 0x10000000)	 /* MIPI DSI */
+					return MXC_CPU_IMX8MNUS;
+				else
+					return MXC_CPU_IMX8MNSL;
+			} else {
 				return MXC_CPU_IMX8MNS;
+			}
 		default:
-			if (value & 0x1000000)
-				return MXC_CPU_IMX8MNL;
+			if (value & 0x1000000) {
+				if (value & 0x10000000)	 /* MIPI DSI */
+					return MXC_CPU_IMX8MNUQ;
+				else
+					return MXC_CPU_IMX8MNL;
+			}
 			break;
 		}
 	} else if (type == MXC_CPU_IMX8MP) {
@@ -398,7 +417,16 @@
 			 * 0xff0055aa is magic number for B1.
 			 */
 			if (readl((void __iomem *)(OCOTP_BASE_ADDR + 0x40)) == 0xff0055aa) {
-				reg = CHIP_REV_2_1;
+				/*
+				 * B2 uses same DIGPROG and OCOTP_READ_FUSE_DATA value with B1,
+				 * so have to check ROM to distinguish them
+				 */
+				rom_version = readl((void __iomem *)ROM_VERSION_B0);
+				rom_version &= 0xff;
+				if (rom_version == CHIP_REV_2_2)
+					reg = CHIP_REV_2_2;
+				else
+					reg = CHIP_REV_2_1;
 			} else {
 				rom_version =
 					readl((void __iomem *)ROM_VERSION_A0);
@@ -468,7 +496,7 @@
 
 		if (is_imx8md() || is_imx8mmd() || is_imx8mmdl() || is_imx8mms() ||
 		    is_imx8mmsl() || is_imx8mnd() || is_imx8mndl() || is_imx8mns() ||
-		    is_imx8mnsl() || is_imx8mpd()) {
+		    is_imx8mnsl() || is_imx8mpd() || is_imx8mnud() || is_imx8mnus()) {
 			/* Power down cpu core 1, 2 and 3 for iMX8M Dual core or Single core */
 			struct pgc_reg *pgc_core1 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x840);
 			struct pgc_reg *pgc_core2 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x880);
@@ -477,7 +505,7 @@
 
 			writel(0x1, &pgc_core2->pgcr);
 			writel(0x1, &pgc_core3->pgcr);
-			if (is_imx8mms() || is_imx8mmsl() || is_imx8mns() || is_imx8mnsl()) {
+			if (is_imx8mms() || is_imx8mmsl() || is_imx8mns() || is_imx8mnsl() || is_imx8mnus()) {
 				writel(0x1, &pgc_core1->pgcr);
 				writel(0xE, &gpc->cpu_pgc_dn_trg);
 			} else {
@@ -616,7 +644,8 @@
 		"/mipi_dsi_bridge@30A00000",
 		"/dsi_phy@30A00300",
 		"/soc@0/bus@30800000/mipi_dsi@30a00000",
-		"/soc@0/bus@30800000/dphy@30a00300"
+		"/soc@0/bus@30800000/dphy@30a00300",
+		"/soc@0/bus@30800000/mipi-dsi@30a00000",
 	};
 
 	return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
@@ -644,7 +673,8 @@
 {
 	static const char * const lcdif_path[] = {
 		"/lcdif@30320000",
-		"/soc@0/bus@30000000/lcdif@30320000"
+		"/soc@0/bus@30000000/lcdif@30320000",
+		"/soc@0/bus@30000000/lcd-controller@30320000"
 	};
 	static const char * const mipi_dsi_path[] = {
 		"/mipi_dsi@30A00000",
@@ -652,11 +682,13 @@
 	};
 	static const char * const lcdif_ep_path[] = {
 		"/lcdif@30320000/port@0/mipi-dsi-endpoint",
-		"/soc@0/bus@30000000/lcdif@30320000/port@0/endpoint"
+		"/soc@0/bus@30000000/lcdif@30320000/port@0/endpoint",
+		"/soc@0/bus@30000000/lcd-controller@30320000/port@0/endpoint"
 	};
 	static const char * const mipi_dsi_ep_path[] = {
 		"/mipi_dsi@30A00000/port@1/endpoint",
-		"/soc@0/bus@30800000/mipi_dsi@30a00000/ports/port@0/endpoint"
+		"/soc@0/bus@30800000/mipi_dsi@30a00000/ports/port@0/endpoint",
+		"/soc@0/bus@30800000/mipi-dsi@30a00000/ports/port@0/endpoint@0"
 	};
 
 	int lookup_node;
@@ -726,10 +758,46 @@
 		return -EPERM;
 }
 
+#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
+static int low_drive_gpu_freq(void *blob)
+{
+	static const char *nodes_path_8mn[] = {
+		"/gpu@38000000",
+		"/soc@0/gpu@38000000"
+	};
+
+	int nodeoff, cnt, i;
+	u32 assignedclks[7];
+
+	nodeoff = fdt_path_offset(blob, nodes_path_8mn[0]);
+	if (nodeoff < 0)
+		return nodeoff;
+
+	cnt = fdtdec_get_int_array_count(blob, nodeoff, "assigned-clock-rates", assignedclks, 7);
+	if (cnt < 0)
+		return cnt;
+
+	if (cnt != 7)
+		printf("Warning: %s, assigned-clock-rates count %d\n", nodes_path_8mn[0], cnt);
+
+	assignedclks[cnt - 1] = 200000000;
+	assignedclks[cnt - 2] = 200000000;
+
+	for (i = 0; i < cnt; i++) {
+		debug("<%u>, ", assignedclks[i]);
+		assignedclks[i] = cpu_to_fdt32(assignedclks[i]);
+	}
+	debug("\n");
+
+	return fdt_setprop(blob, nodeoff, "assigned-clock-rates", &assignedclks, sizeof(assignedclks));
+}
+#endif
+
 int disable_gpu_nodes(void *blob)
 {
 	static const char * const nodes_path_8mn[] = {
-		"/gpu@38000000"
+		"/gpu@38000000",
+		"/soc@/gpu@38000000"
 	};
 
 	return disable_fdt_nodes(blob, nodes_path_8mn, ARRAY_SIZE(nodes_path_8mn));
@@ -763,6 +831,79 @@
 	return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
 }
 
+static void disable_thermal_cpu_nodes(void *blob, u32 disabled_cores)
+{
+	static const char * const thermal_path[] = {
+		"/thermal-zones/cpu-thermal/cooling-maps/map0"
+	};
+
+	int nodeoff, cnt, i, ret, j;
+	u32 cooling_dev[12];
+
+	for (i = 0; i < ARRAY_SIZE(thermal_path); i++) {
+		nodeoff = fdt_path_offset(blob, thermal_path[i]);
+		if (nodeoff < 0)
+			continue; /* Not found, skip it */
+
+		cnt = fdtdec_get_int_array_count(blob, nodeoff, "cooling-device", cooling_dev, 12);
+		if (cnt < 0)
+			continue;
+
+		if (cnt != 12)
+			printf("Warning: %s, cooling-device count %d\n", thermal_path[i], cnt);
+
+		for (j = 0; j < cnt; j++)
+			cooling_dev[j] = cpu_to_fdt32(cooling_dev[j]);
+
+		ret = fdt_setprop(blob, nodeoff, "cooling-device", &cooling_dev,
+				  sizeof(u32) * (12 - disabled_cores * 3));
+		if (ret < 0) {
+			printf("Warning: %s, cooling-device setprop failed %d\n",
+			       thermal_path[i], ret);
+			continue;
+		}
+
+		printf("Update node %s, cooling-device prop\n", thermal_path[i]);
+	}
+}
+
+static void disable_pmu_cpu_nodes(void *blob, u32 disabled_cores)
+{
+	static const char * const pmu_path[] = {
+		"/pmu"
+	};
+
+	int nodeoff, cnt, i, ret, j;
+	u32 irq_affinity[4];
+
+	for (i = 0; i < ARRAY_SIZE(pmu_path); i++) {
+		nodeoff = fdt_path_offset(blob, pmu_path[i]);
+		if (nodeoff < 0)
+			continue; /* Not found, skip it */
+
+		cnt = fdtdec_get_int_array_count(blob, nodeoff, "interrupt-affinity",
+						 irq_affinity, 4);
+		if (cnt < 0)
+			continue;
+
+		if (cnt != 4)
+			printf("Warning: %s, interrupt-affinity count %d\n", pmu_path[i], cnt);
+
+		for (j = 0; j < cnt; j++)
+			irq_affinity[j] = cpu_to_fdt32(irq_affinity[j]);
+
+		ret = fdt_setprop(blob, nodeoff, "interrupt-affinity", &irq_affinity,
+				 sizeof(u32) * (4 - disabled_cores));
+		if (ret < 0) {
+			printf("Warning: %s, interrupt-affinity setprop failed %d\n",
+			       pmu_path[i], ret);
+			continue;
+		}
+
+		printf("Update node %s, interrupt-affinity prop\n", pmu_path[i]);
+	}
+}
+
 static int disable_cpu_nodes(void *blob, u32 disabled_cores)
 {
 	static const char * const nodes_path[] = {
@@ -795,6 +936,9 @@
 		}
 	}
 
+	disable_thermal_cpu_nodes(blob, disabled_cores);
+	disable_pmu_cpu_nodes(blob, disabled_cores);
+
 	return 0;
 }
 
@@ -895,10 +1039,20 @@
 #elif defined(CONFIG_IMX8MN)
 	if (is_imx8mnl() || is_imx8mndl() ||  is_imx8mnsl())
 		disable_gpu_nodes(blob);
+#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
+	else {
+		int ldm_gpu = low_drive_gpu_freq(blob);
 
-	if (is_imx8mnd() || is_imx8mndl())
+		if (ldm_gpu < 0)
+			printf("Update GPU node assigned-clock-rates failed\n");
+		else
+			printf("Update GPU node assigned-clock-rates ok\n");
+	}
+#endif
+
+	if (is_imx8mnd() || is_imx8mndl() || is_imx8mnud())
 		disable_cpu_nodes(blob, 2);
-	else if (is_imx8mns() || is_imx8mnsl())
+	else if (is_imx8mns() || is_imx8mnsl() || is_imx8mnus())
 		disable_cpu_nodes(blob, 3);
 
 #elif defined(CONFIG_IMX8MP)
@@ -923,7 +1077,7 @@
 #endif
 
 #if !CONFIG_IS_ENABLED(SYSRESET)
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
 
diff --git a/arch/arm/mach-imx/imx_bootaux.c b/arch/arm/mach-imx/imx_bootaux.c
index e1fc4b3..30fb45d 100644
--- a/arch/arm/mach-imx/imx_bootaux.c
+++ b/arch/arm/mach-imx/imx_bootaux.c
@@ -14,6 +14,71 @@
 #include <linux/compiler.h>
 #include <cpu_func.h>
 
+#ifndef CONFIG_IMX8M
+const __weak struct rproc_att hostmap[] = { };
+
+static const struct rproc_att *get_host_mapping(unsigned long auxcore)
+{
+	const struct rproc_att *mmap = hostmap;
+
+	while (mmap && mmap->size) {
+		if (mmap->da <= auxcore &&
+		    mmap->da + mmap->size > auxcore)
+			return mmap;
+		mmap++;
+	}
+
+	return NULL;
+}
+
+/*
+ * A very simple elf loader for the auxilary core, assumes the image
+ * is valid, returns the entry point address.
+ * Translates load addresses in the elf file to the U-Boot address space.
+ */
+static unsigned long load_elf_image_m_core_phdr(unsigned long addr)
+{
+	Elf32_Ehdr *ehdr; /* ELF header structure pointer */
+	Elf32_Phdr *phdr; /* Program header structure pointer */
+	int i;
+
+	ehdr = (Elf32_Ehdr *)addr;
+	phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
+
+	/* Load each program header */
+	for (i = 0; i < ehdr->e_phnum; ++i, ++phdr) {
+		const struct rproc_att *mmap = get_host_mapping(phdr->p_paddr);
+		void *dst, *src;
+
+		if (phdr->p_type != PT_LOAD)
+			continue;
+
+		if (!mmap) {
+			printf("Invalid aux core address: %08x",
+			       phdr->p_paddr);
+			return 0;
+		}
+
+		dst = (void *)(phdr->p_paddr - mmap->da) + mmap->sa;
+		src = (void *)addr + phdr->p_offset;
+
+		debug("Loading phdr %i to 0x%p (%i bytes)\n",
+		      i, dst, phdr->p_filesz);
+
+		if (phdr->p_filesz)
+			memcpy(dst, src, phdr->p_filesz);
+		if (phdr->p_filesz != phdr->p_memsz)
+			memset(dst + phdr->p_filesz, 0x00,
+			       phdr->p_memsz - phdr->p_filesz);
+		flush_cache((unsigned long)dst &
+			    ~(CONFIG_SYS_CACHELINE_SIZE - 1),
+			    ALIGN(phdr->p_filesz, CONFIG_SYS_CACHELINE_SIZE));
+	}
+
+	return ehdr->e_entry;
+}
+#endif
+
 int arch_auxiliary_core_up(u32 core_id, ulong addr)
 {
 	ulong stack, pc;
@@ -31,7 +96,7 @@
 	 */
 	if (valid_elf_image(addr)) {
 		stack = 0x0;
-		pc = load_elf_image_phdr(addr);
+		pc = load_elf_image_m_core_phdr(addr);
 		if (!pc)
 			return CMD_RET_FAILURE;
 
diff --git a/arch/arm/mach-imx/mx7ulp/Kconfig b/arch/arm/mach-imx/mx7ulp/Kconfig
index 6680f85..2ffac9c 100644
--- a/arch/arm/mach-imx/mx7ulp/Kconfig
+++ b/arch/arm/mach-imx/mx7ulp/Kconfig
@@ -9,6 +9,7 @@
 	  Select this option to enable the PMC1 LDO.
 
 config MX7ULP
+	select HAS_CAAM
 	bool
 
 choice
diff --git a/arch/arm/mach-imx/mx7ulp/soc.c b/arch/arm/mach-imx/mx7ulp/soc.c
index 8dd6b4d..320f24d 100644
--- a/arch/arm/mach-imx/mx7ulp/soc.c
+++ b/arch/arm/mach-imx/mx7ulp/soc.c
@@ -197,7 +197,7 @@
 #endif
 
 #ifndef CONFIG_ULP_WATCHDOG
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	setbits_le32(SIM0_RBASE, SIM_SOPT1_A7_SW_RESET);
 	while (1)
diff --git a/arch/arm/mach-imx/priblob.c b/arch/arm/mach-imx/priblob.c
new file mode 100644
index 0000000..e253edd
--- /dev/null
+++ b/arch/arm/mach-imx/priblob.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+
+/*
+ * Boot command to get and set the PRIBLOB bitfield form the SCFGR register
+ * of the CAAM IP. It is recommended to set this bitfield to 3 once your
+ * encrypted boot image is ready, to prevent the generation of blobs usable
+ * to decrypt an encrypted boot image.
+ */
+
+#include <asm/io.h>
+#include <common.h>
+#include <command.h>
+#include "../drivers/crypto/fsl_caam_internal.h"
+
+int do_priblob_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	writel((readl(CAAM_SCFGR) & 0xFFFFFFFC) | 3, CAAM_SCFGR);
+	printf("New priblob setting = 0x%x\n", readl(CAAM_SCFGR) & 0x3);
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	set_priblob_bitfield, 1, 0, do_priblob_write,
+	"Set the PRIBLOB bitfield to 3",
+	"<value>\n"
+	"    - Write 3 in PRIBLOB bitfield of SCFGR regiter of CAAM IP.\n"
+	"    Prevent the generation of blobs usable to decrypt an\n"
+	"    encrypted boot image."
+);
diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c
index 4fbf148..9191f68 100644
--- a/arch/arm/mach-k3/common.c
+++ b/arch/arm/mach-k3/common.c
@@ -320,7 +320,7 @@
 #endif
 
 #ifndef CONFIG_SYSRESET
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 }
 #endif
diff --git a/arch/arm/mach-keystone/ddr3.c b/arch/arm/mach-keystone/ddr3.c
index 7dea600..9ee3284 100644
--- a/arch/arm/mach-keystone/ddr3.c
+++ b/arch/arm/mach-keystone/ddr3.c
@@ -345,7 +345,7 @@
 
 		if (!ecc_test) {
 			puts("Reseting the device ...\n");
-			reset_cpu(0);
+			reset_cpu();
 		}
 	}
 
@@ -445,7 +445,7 @@
 		tmp &= ~KS2_RSTYPE_PLL_SOFT;
 		__raw_writel(tmp, KS2_RSTCTRL_RSCFG);
 
-		reset_cpu(0);
+		reset_cpu();
 	}
 }
 #endif
diff --git a/arch/arm/mach-keystone/init.c b/arch/arm/mach-keystone/init.c
index 4950f14..5b95f60 100644
--- a/arch/arm/mach-keystone/init.c
+++ b/arch/arm/mach-keystone/init.c
@@ -192,7 +192,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	volatile u32 *rstctrl = (volatile u32 *)(KS2_RSTCTRL);
 	u32 tmp;
diff --git a/arch/arm/mach-kirkwood/cpu.c b/arch/arm/mach-kirkwood/cpu.c
index 551c22a..339ae7f 100644
--- a/arch/arm/mach-kirkwood/cpu.c
+++ b/arch/arm/mach-kirkwood/cpu.c
@@ -19,7 +19,7 @@
 #include <asm/arch/soc.h>
 #include <mvebu_mmc.h>
 
-void reset_cpu(unsigned long ignored)
+void reset_cpu(void)
 {
 	struct kwcpu_registers *cpureg =
 	    (struct kwcpu_registers *)KW_CPU_REG_BASE;
@@ -279,10 +279,3 @@
 }
 #endif
 
-#ifdef CONFIG_MVEBU_MMC
-int board_mmc_init(struct bd_info *bis)
-{
-	mvebu_mmc_init(bis);
-	return 0;
-}
-#endif /* CONFIG_MVEBU_MMC */
diff --git a/arch/arm/mach-lpc32xx/cpu.c b/arch/arm/mach-lpc32xx/cpu.c
index 32af620..c2586d0 100644
--- a/arch/arm/mach-lpc32xx/cpu.c
+++ b/arch/arm/mach-lpc32xx/cpu.c
@@ -17,28 +17,17 @@
 static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE;
 static struct wdt_regs  *wdt = (struct wdt_regs *)WDT_BASE;
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	/* Enable watchdog clock */
 	setbits_le32(&clk->timclk_ctrl, CLK_TIMCLK_WATCHDOG);
 
-	/* To be compatible with the original U-Boot code:
-	 * addr: - 0: perform hard reset.
-	 *       - !=0: perform a soft reset; i.e. "RESOUT_N" not asserted). */
-	if (addr == 0) {
-		/* Reset pulse length is 13005 peripheral clock frames */
-		writel(13000, &wdt->pulse);
+	/* Reset pulse length is 13005 peripheral clock frames */
+	writel(13000, &wdt->pulse);
 
-		/* Force WDOG_RESET2 and RESOUT_N signal active */
-		writel(WDTIM_MCTRL_RESFRC2 | WDTIM_MCTRL_RESFRC1
-		       | WDTIM_MCTRL_M_RES2, &wdt->mctrl);
-	} else {
-		/* Force match output active */
-		writel(0x01, &wdt->emr);
-
-		/* Internal reset on match output (no pulse on "RESOUT_N") */
-		writel(WDTIM_MCTRL_M_RES1, &wdt->mctrl);
-	}
+	/* Force WDOG_RESET2 and RESOUT_N signal active */
+	writel(WDTIM_MCTRL_RESFRC2 | WDTIM_MCTRL_RESFRC1 | WDTIM_MCTRL_M_RES2,
+	       &wdt->mctrl);
 
 	while (1)
 		/* NOP */;
diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
index 7f40ba9..e067604 100644
--- a/arch/arm/mach-mediatek/Kconfig
+++ b/arch/arm/mach-mediatek/Kconfig
@@ -36,12 +36,20 @@
 	bool "MediaTek MT7629 SoC"
 	select CPU_V7A
 	select SPL
-	select BINMAN
 	help
 	  The MediaTek MT7629 is a ARM-based SoC with a dual-core Cortex-A7
 	  including DDR3, crypto engine, 3x3 11n/ac Wi-Fi, Gigabit Ethernet,
 	  switch, USB3.0, PCIe, UART, SPI, I2C and PWM.
 
+config TARGET_MT8183
+	bool "MediaTek MT8183 SoC"
+	select ARM64
+	help
+	  The MediaTek MT8183 is a ARM64-based SoC with a quad-core Cortex-A73 and
+	  a quad-core Cortex-A53. It is including UART, SPI, USB3.0 dual role,
+	  SD and MMC cards, UFS, PWM, I2C, I2S, S/PDIF, and several LPDDR3
+	  and LPDDR4 options.
+
 config TARGET_MT8512
         bool "MediaTek MT8512 M1 Board"
         select ARM64
@@ -75,8 +83,9 @@
 source "board/mediatek/mt7622/Kconfig"
 source "board/mediatek/mt7623/Kconfig"
 source "board/mediatek/mt7629/Kconfig"
+source "board/mediatek/mt8183/Kconfig"
 source "board/mediatek/mt8512/Kconfig"
+source "board/mediatek/mt8516/Kconfig"
 source "board/mediatek/mt8518/Kconfig"
-source "board/mediatek/pumpkin/Kconfig"
 
 endif
diff --git a/arch/arm/mach-mediatek/Makefile b/arch/arm/mach-mediatek/Makefile
index 290d2c7..0f5b0c1 100644
--- a/arch/arm/mach-mediatek/Makefile
+++ b/arch/arm/mach-mediatek/Makefile
@@ -7,5 +7,6 @@
 obj-$(CONFIG_TARGET_MT7622) += mt7622/
 obj-$(CONFIG_TARGET_MT7623) += mt7623/
 obj-$(CONFIG_TARGET_MT7629) += mt7629/
+obj-$(CONFIG_TARGET_MT8183) += mt8183/
 obj-$(CONFIG_TARGET_MT8516) += mt8516/
 obj-$(CONFIG_TARGET_MT8518) += mt8518/
diff --git a/arch/arm/mach-mediatek/mt7622/init.c b/arch/arm/mach-mediatek/mt7622/init.c
index 7f6ce80..e501907 100644
--- a/arch/arm/mach-mediatek/mt7622/init.c
+++ b/arch/arm/mach-mediatek/mt7622/init.c
@@ -27,7 +27,7 @@
 
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	psci_system_reset();
 }
diff --git a/board/mediatek/pumpkin/Makefile b/arch/arm/mach-mediatek/mt8183/Makefile
similarity index 65%
rename from board/mediatek/pumpkin/Makefile
rename to arch/arm/mach-mediatek/mt8183/Makefile
index 75fce4a..886ab7e 100644
--- a/board/mediatek/pumpkin/Makefile
+++ b/arch/arm/mach-mediatek/mt8183/Makefile
@@ -1,3 +1,3 @@
 # SPDX-License-Identifier:	GPL-2.0
 
-obj-y += pumpkin.o
+obj-y += init.o
diff --git a/arch/arm/mach-mediatek/mt8183/init.c b/arch/arm/mach-mediatek/mt8183/init.c
new file mode 100644
index 0000000..877f387
--- /dev/null
+++ b/arch/arm/mach-mediatek/mt8183/init.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Copyright (C) 2021 BayLibre, SAS
+ * Author: Fabien Parent <fparent@baylibre.com>
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <ram.h>
+#include <asm/arch/misc.h>
+#include <asm/armv8/mmu.h>
+#include <asm/sections.h>
+#include <asm/system.h>
+#include <dm/uclass.h>
+#include <dt-bindings/clock/mt8516-clk.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+	int ret;
+
+	ret = fdtdec_setup_memory_banksize();
+	if (ret)
+		return ret;
+
+	return fdtdec_setup_mem_size_base();
+}
+
+int dram_init_banksize(void)
+{
+	gd->bd->bi_dram[0].start = gd->ram_base;
+	gd->bd->bi_dram[0].size = gd->ram_size;
+
+	return 0;
+}
+
+int mtk_pll_early_init(void)
+{
+	return 0;
+}
+
+int mtk_soc_early_init(void)
+{
+	return 0;
+}
+
+void reset_cpu(ulong addr)
+{
+	psci_system_reset();
+}
+
+int print_cpuinfo(void)
+{
+	printf("CPU:   MediaTek MT8183\n");
+	return 0;
+}
+
+static struct mm_region mt8183_mem_map[] = {
+	{
+		/* DDR */
+		.virt = 0x40000000UL,
+		.phys = 0x40000000UL,
+		.size = 0x80000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE,
+	}, {
+		.virt = 0x00000000UL,
+		.phys = 0x00000000UL,
+		.size = 0x20000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		0,
+	}
+};
+struct mm_region *mem_map = mt8183_mem_map;
diff --git a/arch/arm/mach-mediatek/mt8512/init.c b/arch/arm/mach-mediatek/mt8512/init.c
index c14e7d2..b7050df 100644
--- a/arch/arm/mach-mediatek/mt8512/init.c
+++ b/arch/arm/mach-mediatek/mt8512/init.c
@@ -43,7 +43,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	struct udevice *watchdog_dev = NULL;
 
diff --git a/arch/arm/mach-mediatek/mt8516/init.c b/arch/arm/mach-mediatek/mt8516/init.c
index 3771152..3460dcc 100644
--- a/arch/arm/mach-mediatek/mt8516/init.c
+++ b/arch/arm/mach-mediatek/mt8516/init.c
@@ -85,7 +85,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	psci_system_reset();
 }
diff --git a/arch/arm/mach-mediatek/mt8518/init.c b/arch/arm/mach-mediatek/mt8518/init.c
index 28b00c3..f7e03de 100644
--- a/arch/arm/mach-mediatek/mt8518/init.c
+++ b/arch/arm/mach-mediatek/mt8518/init.c
@@ -42,7 +42,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	psci_system_reset();
 }
diff --git a/arch/arm/mach-meson/board-axg.c b/arch/arm/mach-meson/board-axg.c
index 3b14bc9..71ac65c 100644
--- a/arch/arm/mach-meson/board-axg.c
+++ b/arch/arm/mach-meson/board-axg.c
@@ -91,40 +91,6 @@
 
 struct mm_region *mem_map = axg_mem_map;
 
-/* Configure the Ethernet MAC with the requested interface mode
- * with some optional flags.
- */
-void meson_eth_init(phy_interface_t mode, unsigned int flags)
-{
-	switch (mode) {
-	case PHY_INTERFACE_MODE_RGMII:
-	case PHY_INTERFACE_MODE_RGMII_ID:
-	case PHY_INTERFACE_MODE_RGMII_RXID:
-	case PHY_INTERFACE_MODE_RGMII_TXID:
-		/* Set RGMII mode */
-		setbits_le32(AXG_ETH_REG_0, AXG_ETH_REG_0_PHY_INTF_RGMII |
-			     AXG_ETH_REG_0_TX_PHASE(1) |
-			     AXG_ETH_REG_0_TX_RATIO(4) |
-			     AXG_ETH_REG_0_PHY_CLK_EN |
-			     AXG_ETH_REG_0_CLK_EN);
-		break;
-
-	case PHY_INTERFACE_MODE_RMII:
-		/* Set RMII mode */
-		out_le32(AXG_ETH_REG_0, AXG_ETH_REG_0_PHY_INTF_RMII |
-					AXG_ETH_REG_0_INVERT_RMII_CLK |
-					AXG_ETH_REG_0_CLK_EN);
-		break;
-
-	default:
-		printf("Invalid Ethernet interface mode\n");
-		return;
-	}
-
-	/* Enable power gate */
-	clrbits_le32(AXG_MEM_PD_REG_0, AXG_MEM_PD_REG_0_ETH_MASK);
-}
-
 #if CONFIG_IS_ENABLED(USB_DWC3_MESON_GXL) && \
 	CONFIG_IS_ENABLED(USB_GADGET_DWC2_OTG)
 static struct dwc2_plat_otg_data meson_gx_dwc2_data;
diff --git a/arch/arm/mach-meson/board-common.c b/arch/arm/mach-meson/board-common.c
index 34b3c8f..1690b6b 100644
--- a/arch/arm/mach-meson/board-common.c
+++ b/arch/arm/mach-meson/board-common.c
@@ -167,7 +167,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	struct pt_regs regs;
 
@@ -182,7 +182,7 @@
 		;
 }
 #else
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	psci_system_reset();
 }
diff --git a/arch/arm/mach-meson/board-g12a.c b/arch/arm/mach-meson/board-g12a.c
index bb75d4f..2e59eee 100644
--- a/arch/arm/mach-meson/board-g12a.c
+++ b/arch/arm/mach-meson/board-g12a.c
@@ -97,73 +97,6 @@
 
 struct mm_region *mem_map = g12a_mem_map;
 
-static void g12a_enable_external_mdio(void)
-{
-	writel(0x0, ETH_PHY_CNTL2);
-}
-
-static void g12a_enable_internal_mdio(void)
-{
-	/* Fire up the PHY PLL */
-	writel(0x29c0040a, ETH_PLL_CNTL0);
-	writel(0x927e0000, ETH_PLL_CNTL1);
-	writel(0xac5f49e5, ETH_PLL_CNTL2);
-	writel(0x00000000, ETH_PLL_CNTL3);
-	writel(0x00000000, ETH_PLL_CNTL4);
-	writel(0x20200000, ETH_PLL_CNTL5);
-	writel(0x0000c002, ETH_PLL_CNTL6);
-	writel(0x00000023, ETH_PLL_CNTL7);
-	writel(0x39c0040a, ETH_PLL_CNTL0);
-	writel(0x19c0040a, ETH_PLL_CNTL0);
-
-	/* Select the internal MDIO */
-	writel(0x33000180, ETH_PHY_CNTL0);
-	writel(0x00074043, ETH_PHY_CNTL1);
-	writel(0x00000260, ETH_PHY_CNTL2);
-}
-
-/* Configure the Ethernet MAC with the requested interface mode
- * with some optional flags.
- */
-void meson_eth_init(phy_interface_t mode, unsigned int flags)
-{
-	switch (mode) {
-	case PHY_INTERFACE_MODE_RGMII:
-	case PHY_INTERFACE_MODE_RGMII_ID:
-	case PHY_INTERFACE_MODE_RGMII_RXID:
-	case PHY_INTERFACE_MODE_RGMII_TXID:
-		/* Set RGMII mode */
-		setbits_le32(G12A_ETH_REG_0, G12A_ETH_REG_0_PHY_INTF_RGMII |
-			     G12A_ETH_REG_0_TX_PHASE(1) |
-			     G12A_ETH_REG_0_TX_RATIO(4) |
-			     G12A_ETH_REG_0_PHY_CLK_EN |
-			     G12A_ETH_REG_0_CLK_EN);
-		g12a_enable_external_mdio();
-		break;
-
-	case PHY_INTERFACE_MODE_RMII:
-		/* Set RMII mode */
-		out_le32(G12A_ETH_REG_0, G12A_ETH_REG_0_PHY_INTF_RMII |
-					G12A_ETH_REG_0_INVERT_RMII_CLK |
-					G12A_ETH_REG_0_CLK_EN);
-
-		/* Use G12A RMII Internal PHY */
-		if (flags & MESON_USE_INTERNAL_RMII_PHY)
-			g12a_enable_internal_mdio();
-		else
-			g12a_enable_external_mdio();
-
-		break;
-
-	default:
-		printf("Invalid Ethernet interface mode\n");
-		return;
-	}
-
-	/* Enable power gate */
-	clrbits_le32(G12A_MEM_PD_REG_0, G12A_MEM_PD_REG_0_ETH_MASK);
-}
-
 #if CONFIG_IS_ENABLED(USB_DWC3_MESON_G12A) && \
 	CONFIG_IS_ENABLED(USB_GADGET_DWC2_OTG)
 static struct dwc2_plat_otg_data meson_g12a_dwc2_data;
diff --git a/arch/arm/mach-meson/board-gx.c b/arch/arm/mach-meson/board-gx.c
index f5273f4..01fafd8 100644
--- a/arch/arm/mach-meson/board-gx.c
+++ b/arch/arm/mach-meson/board-gx.c
@@ -109,54 +109,6 @@
 
 struct mm_region *mem_map = gx_mem_map;
 
-/* Configure the Ethernet MAC with the requested interface mode
- * with some optional flags.
- */
-void meson_eth_init(phy_interface_t mode, unsigned int flags)
-{
-	switch (mode) {
-	case PHY_INTERFACE_MODE_RGMII:
-	case PHY_INTERFACE_MODE_RGMII_ID:
-	case PHY_INTERFACE_MODE_RGMII_RXID:
-	case PHY_INTERFACE_MODE_RGMII_TXID:
-		/* Set RGMII mode */
-		setbits_le32(GX_ETH_REG_0, GX_ETH_REG_0_PHY_INTF |
-			     GX_ETH_REG_0_TX_PHASE(1) |
-			     GX_ETH_REG_0_TX_RATIO(4) |
-			     GX_ETH_REG_0_PHY_CLK_EN |
-			     GX_ETH_REG_0_CLK_EN);
-
-		/* Reset to external PHY */
-		if(!IS_ENABLED(CONFIG_MESON_GXBB))
-			writel(0x2009087f, GX_ETH_REG_3);
-
-		break;
-
-	case PHY_INTERFACE_MODE_RMII:
-		/* Set RMII mode */
-		out_le32(GX_ETH_REG_0, GX_ETH_REG_0_INVERT_RMII_CLK |
-					 GX_ETH_REG_0_CLK_EN);
-
-		/* Use GXL RMII Internal PHY (also on GXM) */
-		if (!IS_ENABLED(CONFIG_MESON_GXBB)) {
-			if ((flags & MESON_USE_INTERNAL_RMII_PHY)) {
-				writel(0x10110181, GX_ETH_REG_2);
-				writel(0xe40908ff, GX_ETH_REG_3);
-			} else
-				writel(0x2009087f, GX_ETH_REG_3);
-		}
-
-		break;
-
-	default:
-		printf("Invalid Ethernet interface mode\n");
-		return;
-	}
-
-	/* Enable power gate */
-	clrbits_le32(GX_MEM_PD_REG_0, GX_MEM_PD_REG_0_ETH_MASK);
-}
-
 #if CONFIG_IS_ENABLED(USB_DWC3_MESON_GXL) && \
 	CONFIG_IS_ENABLED(USB_GADGET_DWC2_OTG)
 static struct dwc2_plat_otg_data meson_gx_dwc2_data;
diff --git a/arch/arm/mach-mvebu/armada3700/cpu.c b/arch/arm/mach-mvebu/armada3700/cpu.c
index 70f76c7..0cf60d7 100644
--- a/arch/arm/mach-mvebu/armada3700/cpu.c
+++ b/arch/arm/mach-mvebu/armada3700/cpu.c
@@ -314,7 +314,7 @@
 	return fdt_setprop_inplace(blob, node, "ranges", new_ranges, len);
 }
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 	/*
 	 * Write magic number of 0x1d1e to North Bridge Warm Reset register
diff --git a/arch/arm/mach-mvebu/armada8k/cpu.c b/arch/arm/mach-mvebu/armada8k/cpu.c
index 529dac9..474327a 100644
--- a/arch/arm/mach-mvebu/armada8k/cpu.c
+++ b/arch/arm/mach-mvebu/armada8k/cpu.c
@@ -104,7 +104,7 @@
 	dcache_enable();
 }
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 	u32 reg;
 
diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c
index 7dce11e..0b935c4 100644
--- a/arch/arm/mach-mvebu/cpu.c
+++ b/arch/arm/mach-mvebu/cpu.c
@@ -42,7 +42,7 @@
 	 */
 }
 
-void reset_cpu(unsigned long ignored)
+void reset_cpu(void)
 {
 	struct mvebu_system_registers *reg =
 		(struct mvebu_system_registers *)MVEBU_SYSTEM_REG_BASE;
diff --git a/arch/arm/mach-nexell/Makefile b/arch/arm/mach-nexell/Makefile
index 10b3963..dda16db 100644
--- a/arch/arm/mach-nexell/Makefile
+++ b/arch/arm/mach-nexell/Makefile
@@ -10,4 +10,3 @@
 obj-y				+= tieoff.o
 obj-$(CONFIG_ARCH_S5P4418)	+= reg-call.o
 obj-$(CONFIG_ARCH_S5P4418)	+= nx_sec_reg.o
-obj-$(CONFIG_CMD_BOOTL)		+= cmd_boot_linux.o
diff --git a/arch/arm/mach-nexell/cmd_boot_linux.c b/arch/arm/mach-nexell/cmd_boot_linux.c
deleted file mode 100644
index 9b38d38..0000000
--- a/arch/arm/mach-nexell/cmd_boot_linux.c
+++ /dev/null
@@ -1,145 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2016 nexell
- * jhkim <jhkim@nexell.co.kr>
- */
-
-#include <common.h>
-#include <bootm.h>
-#include <command.h>
-#include <environment.h>
-#include <errno.h>
-#include <image.h>
-#include <fdt_support.h>
-#include <asm/global_data.h>
-
-#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_CLI_FRAMEWORK)
-
-DECLARE_GLOBAL_DATA_PTR;
-
-static bootm_headers_t linux_images;
-
-static void boot_go_set_os(cmd_tbl_t *cmdtp, int flag, int argc,
-			   char * const argv[],
-			   bootm_headers_t *images)
-{
-	char * const img_addr = argv[0];
-
-	images->os.type = IH_TYPE_KERNEL;
-	images->os.comp = IH_COMP_NONE;
-	images->os.os = IH_OS_LINUX;
-	images->os.load = simple_strtoul(img_addr, NULL, 16);
-	images->ep = images->os.load;
-#if defined(CONFIG_ARM)
-	images->os.arch = IH_ARCH_ARM;
-#elif defined(CONFIG_ARM64)
-	images->os.arch = IH_ARCH_ARM64;
-#else
-	#error "Not support architecture ..."
-#endif
-	if (!IS_ENABLED(CONFIG_OF_LIBFDT) && !IS_ENABLED(CONFIG_SPL_BUILD)) {
-		/* set DTB address for linux kernel */
-		if (argc > 2) {
-			unsigned long ft_addr;
-
-			ft_addr = simple_strtol(argv[2], NULL, 16);
-			images->ft_addr = (char *)ft_addr;
-
-			/*
-			 * if not defined IMAGE_ENABLE_OF_LIBFDT,
-			 * must be set to fdt address
-			 */
-			if (!IMAGE_ENABLE_OF_LIBFDT)
-				gd->bd->bi_boot_params = ft_addr;
-
-			debug("## set ft:%08lx and boot params:%08lx [control of:%s]"
-			      "...\n", ft_addr, gd->bd->bi_boot_params,
-			      IMAGE_ENABLE_OF_LIBFDT ? "on" : "off");
-		}
-	}
-}
-
-#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB)
-static void boot_start_lmb(bootm_headers_t *images)
-{
-	ulong		mem_start;
-	phys_size_t	mem_size;
-
-	lmb_init(&images->lmb);
-
-	mem_start = getenv_bootm_low();
-	mem_size = getenv_bootm_size();
-
-	lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
-
-	arch_lmb_reserve(&images->lmb);
-	board_lmb_reserve(&images->lmb);
-}
-#else
-#define lmb_reserve(lmb, base, size)
-static inline void boot_start_lmb(bootm_headers_t *images) { }
-#endif
-
-int do_boot_linux(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-	boot_os_fn *boot_fn;
-	bootm_headers_t *images = &linux_images;
-	int flags;
-	int ret;
-
-	boot_start_lmb(images);
-
-	flags  = BOOTM_STATE_START;
-
-	argc--; argv++;
-	boot_go_set_os(cmdtp, flag, argc, argv, images);
-
-	if (IS_ENABLED(CONFIG_OF_LIBFDT)) {
-		/* find flattened device tree */
-		ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, images,
-				   &images->ft_addr, &images->ft_len);
-		if (ret) {
-			puts("Could not find a valid device tree\n");
-			return 1;
-		}
-		set_working_fdt_addr((ulong)images->ft_addr);
-	}
-
-	if (!IS_ENABLED(CONFIG_OF_LIBFDT))
-		flags |= BOOTM_STATE_OS_GO;
-
-	boot_fn = do_bootm_linux;
-	ret = boot_fn(flags, argc, argv, images);
-
-	if (ret == BOOTM_ERR_UNIMPLEMENTED)
-		show_boot_progress(BOOTSTAGE_ID_DECOMP_UNIMPL);
-	else if (ret == BOOTM_ERR_RESET)
-		do_reset(cmdtp, flag, argc, argv);
-
-	return ret;
-}
-
-U_BOOT_CMD(bootl, CONFIG_SYS_MAXARGS, 1, do_boot_linux,
-	   "boot linux image from memory",
-	   "[addr [arg ...]]\n    - boot linux image stored in memory\n"
-	   "\tuse a '-' for the DTB address\n"
-);
-#endif
-
-#if defined(CONFIG_CMD_BOOTD) && !defined(CONFIG_CMD_BOOTM)
-int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-	return run_command(env_get("bootcmd"), flag);
-}
-
-U_BOOT_CMD(boot, 1, 1, do_bootd,
-	   "boot default, i.e., run 'bootcmd'",
-	   ""
-);
-
-/* keep old command name "bootd" for backward compatibility */
-U_BOOT_CMD(bootd, 1,	1,	do_bootd,
-	   "boot default, i.e., run 'bootcmd'",
-	   ""
-);
-#endif
diff --git a/arch/arm/mach-octeontx/cpu.c b/arch/arm/mach-octeontx/cpu.c
index ce5f2b4..7bd74fe 100644
--- a/arch/arm/mach-octeontx/cpu.c
+++ b/arch/arm/mach-octeontx/cpu.c
@@ -72,6 +72,6 @@
 	return 0x80000;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
diff --git a/arch/arm/mach-octeontx2/cpu.c b/arch/arm/mach-octeontx2/cpu.c
index 8786815..afa458c 100644
--- a/arch/arm/mach-octeontx2/cpu.c
+++ b/arch/arm/mach-octeontx2/cpu.c
@@ -68,6 +68,6 @@
 	return 0x80000;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
diff --git a/arch/arm/mach-omap2/omap-cache.c b/arch/arm/mach-omap2/omap-cache.c
index 1b246f8..36db588 100644
--- a/arch/arm/mach-omap2/omap-cache.c
+++ b/arch/arm/mach-omap2/omap-cache.c
@@ -41,9 +41,6 @@
 #define ARMV7_DCACHE_POLICY	DCACHE_WRITEBACK & ~TTB_SECT_XN_MASK
 #endif
 
-#define ARMV7_DOMAIN_CLIENT	1
-#define ARMV7_DOMAIN_MASK	(0x3 << 0)
-
 void enable_caches(void)
 {
 
@@ -67,17 +64,3 @@
 	for (i = start; i < end; i++)
 		set_section_dcache(i, ARMV7_DCACHE_POLICY);
 }
-
-void arm_init_domains(void)
-{
-	u32 reg;
-
-	reg = get_dacr();
-	/*
-	* Set DOMAIN to client access so that all permissions
-	* set in pagetables are validated by the mmu.
-	*/
-	reg &= ~ARMV7_DOMAIN_MASK;
-	reg |= ARMV7_DOMAIN_CLIENT;
-	set_dacr(reg);
-}
diff --git a/arch/arm/mach-omap2/omap5/hwinit.c b/arch/arm/mach-omap2/omap5/hwinit.c
index 47ac865..edab9a9 100644
--- a/arch/arm/mach-omap2/omap5/hwinit.c
+++ b/arch/arm/mach-omap2/omap5/hwinit.c
@@ -417,7 +417,7 @@
 	die_id[3] = readl((*ctrl)->control_std_fuse_die_id_3);
 }
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 	u32 omap_rev = omap_revision();
 
diff --git a/arch/arm/mach-omap2/reset.c b/arch/arm/mach-omap2/reset.c
index 2bbd5fc..1fd79c2 100644
--- a/arch/arm/mach-omap2/reset.c
+++ b/arch/arm/mach-omap2/reset.c
@@ -14,7 +14,7 @@
 #include <asm/arch/cpu.h>
 #include <linux/compiler.h>
 
-void __weak reset_cpu(unsigned long ignored)
+void __weak reset_cpu(void)
 {
 	writel(PRM_RSTCTRL_RESET, PRM_RSTCTRL);
 }
diff --git a/arch/arm/mach-orion5x/cpu.c b/arch/arm/mach-orion5x/cpu.c
index beae7b8..ffae9a0 100644
--- a/arch/arm/mach-orion5x/cpu.c
+++ b/arch/arm/mach-orion5x/cpu.c
@@ -20,7 +20,7 @@
 
 #define BUFLEN	16
 
-void reset_cpu(unsigned long ignored)
+void reset_cpu(void)
 {
 	struct orion5x_cpu_registers *cpureg =
 	    (struct orion5x_cpu_registers *)ORION5X_CPU_REG_BASE;
diff --git a/arch/arm/mach-owl/soc.c b/arch/arm/mach-owl/soc.c
index 4d2b9d0..4baef2e 100644
--- a/arch/arm/mach-owl/soc.c
+++ b/arch/arm/mach-owl/soc.c
@@ -74,7 +74,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	psci_system_reset();
 }
diff --git a/arch/arm/mach-rmobile/Kconfig.64 b/arch/arm/mach-rmobile/Kconfig.64
index b95c8e8..8127d33 100644
--- a/arch/arm/mach-rmobile/Kconfig.64
+++ b/arch/arm/mach-rmobile/Kconfig.64
@@ -4,6 +4,8 @@
 
 config R8A774A1
 	bool "Renesas SoC R8A774A1"
+	imply CLK_R8A774A1
+	imply PINCTRL_PFC_R8A774A1
 
 config R8A774B1
 	bool "Renesas SoC R8A774B1"
@@ -13,6 +15,7 @@
 config R8A774C0
 	bool "Renesas SoC R8A774C0"
 	imply CLK_R8A774C0
+	imply PINCTRL_PFC_R8A774C0
 
 config R8A774E1
 	bool "Renesas SoC R8A774E1"
@@ -99,6 +102,23 @@
 	help
           Support for Renesas R-Car Gen3 Ebisu platform
 
+config TARGET_HIHOPE_RZG2
+	bool "HiHope RZ/G2 board"
+	imply R8A774A1
+	imply R8A774B1
+	imply R8A774E1
+	imply SYS_MALLOC_F
+	imply MULTI_DTB_FIT
+	imply MULTI_DTB_FIT_USER_DEFINED_AREA
+	help
+          Support for RZG2 HiHope platform
+
+config TARGET_SILINUX_EK874
+	bool "Silicon Linux EK874 board"
+	imply R8A774C0
+	help
+          Support for Silicon Linux EK874 platform
+
 config TARGET_SALVATOR_X
 	bool "Salvator-X board"
 	imply R8A7795
@@ -133,12 +153,16 @@
 source "board/renesas/salvator-x/Kconfig"
 source "board/renesas/ulcb/Kconfig"
 source "board/beacon/beacon-rzg2m/Kconfig"
+source "board/hoperun/hihope-rzg2/Kconfig"
+source "board/silinux/ek874/Kconfig"
 
 config MULTI_DTB_FIT_UNCOMPRESS_SZ
+	default 0x80000 if TARGET_HIHOPE_RZG2
 	default 0x80000 if TARGET_SALVATOR_X
 	default 0x80000 if TARGET_ULCB
 
 config MULTI_DTB_FIT_USER_DEF_ADDR
+	default 0x49000000 if TARGET_HIHOPE_RZG2
 	default 0x49000000 if TARGET_SALVATOR_X
 	default 0x49000000 if TARGET_ULCB
 
diff --git a/arch/arm/mach-rmobile/Makefile b/arch/arm/mach-rmobile/Makefile
index 3206bce..9f56af4 100644
--- a/arch/arm/mach-rmobile/Makefile
+++ b/arch/arm/mach-rmobile/Makefile
@@ -22,7 +22,7 @@
 spl/u-boot-spl.srec: spl/u-boot-spl FORCE
 	$(call if_changed,objcopy)
 
-ifneq ($(CONFIG_R8A77990)$(CONFIG_R8A77995),)
+ifneq ($(CONFIG_R8A774C0)$(CONFIG_R8A77990)$(CONFIG_R8A77995),)
 #
 # The first 6 generate statements generate the R-Car Gen3 SCIF loader header.
 # The subsequent generate statements represent the following chunk of assembler
diff --git a/arch/arm/mach-rockchip/rk3368/Kconfig b/arch/arm/mach-rockchip/rk3368/Kconfig
index d6ca5f1..78eb96d 100644
--- a/arch/arm/mach-rockchip/rk3368/Kconfig
+++ b/arch/arm/mach-rockchip/rk3368/Kconfig
@@ -49,7 +49,7 @@
 	default "rk3368"
 
 config SYS_MALLOC_F_LEN
-	default 0x2000
+	default 0x4000
 
 config SPL_LIBCOMMON_SUPPORT
 	default y
@@ -65,6 +65,9 @@
 config SPL_LDSCRIPT
 	default "arch/arm/cpu/armv8/u-boot-spl.lds"
 
+config SPL_STACK_R_ADDR
+	default 0x04000000
+
 config TPL_MAX_SIZE
         default 28672
 
diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile
index 9e63296..5779c55 100644
--- a/arch/arm/mach-socfpga/Makefile
+++ b/arch/arm/mach-socfpga/Makefile
@@ -35,10 +35,10 @@
 obj-y	+= misc_s10.o
 obj-y	+= mmu-arm64_s10.o
 obj-y	+= reset_manager_s10.o
-obj-y	+= system_manager_s10.o
+obj-y	+= system_manager_soc64.o
 obj-y	+= timer_s10.o
-obj-y	+= wrap_pinmux_config_s10.o
-obj-y	+= wrap_pll_config_s10.o
+obj-y	+= wrap_handoff_soc64.o
+obj-y	+= wrap_pll_config_soc64.o
 endif
 
 ifdef CONFIG_TARGET_SOCFPGA_AGILEX
@@ -49,11 +49,11 @@
 obj-y	+= mmu-arm64_s10.o
 obj-y	+= reset_manager_s10.o
 obj-$(CONFIG_SOCFPGA_SECURE_VAB_AUTH)	+= secure_vab.o
-obj-y	+= system_manager_s10.o
+obj-y	+= system_manager_soc64.o
 obj-y	+= timer_s10.o
 obj-$(CONFIG_SOCFPGA_SECURE_VAB_AUTH)	+= vab.o
-obj-y	+= wrap_pinmux_config_s10.o
-obj-y	+= wrap_pll_config_s10.o
+obj-y	+= wrap_handoff_soc64.o
+obj-y	+= wrap_pll_config_soc64.o
 endif
 
 ifdef CONFIG_SPL_BUILD
@@ -70,10 +70,12 @@
 ifdef CONFIG_TARGET_SOCFPGA_STRATIX10
 obj-y	+= firewall.o
 obj-y	+= spl_s10.o
+obj-y	+= spl_soc64.o
 endif
 ifdef CONFIG_TARGET_SOCFPGA_AGILEX
 obj-y	+= firewall.o
 obj-y	+= spl_agilex.o
+obj-y	+= spl_soc64.o
 endif
 else
 obj-$(CONFIG_SPL_ATF) += secure_reg_helper.o
diff --git a/arch/arm/mach-socfpga/clock_manager.c b/arch/arm/mach-socfpga/clock_manager.c
index f0b15f7..9e645a4 100644
--- a/arch/arm/mach-socfpga/clock_manager.c
+++ b/arch/arm/mach-socfpga/clock_manager.c
@@ -4,12 +4,13 @@
  */
 
 #include <common.h>
+#include <asm/arch/clock_manager.h>
+#include <asm/arch/system_manager.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
 #include <command.h>
 #include <init.h>
 #include <wait_bit.h>
-#include <asm/global_data.h>
-#include <asm/io.h>
-#include <asm/arch/clock_manager.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -63,6 +64,42 @@
 	return 0;
 }
 
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_SOC64)
+int cm_set_qspi_controller_clk_hz(u32 clk_hz)
+{
+	u32 reg;
+	u32 clk_khz;
+
+	/*
+	 * Store QSPI ref clock and set into sysmgr boot register.
+	 * Only clock freq in kHz degree is accepted due to limited bits[27:0]
+	 * is reserved for storing the QSPI clock freq into boot scratch cold0
+	 * register.
+	 */
+	if (clk_hz < 1000)
+		return -EINVAL;
+
+	clk_khz = clk_hz / 1000;
+	printf("QSPI: Reference clock at %d kHz\n", clk_khz);
+
+	reg = (readl(socfpga_get_sysmgr_addr() +
+		     SYSMGR_SOC64_BOOT_SCRATCH_COLD0)) &
+		     ~(SYSMGR_SCRATCH_REG_0_QSPI_REFCLK_MASK);
+
+	writel((clk_khz & SYSMGR_SCRATCH_REG_0_QSPI_REFCLK_MASK) | reg,
+	       socfpga_get_sysmgr_addr() + SYSMGR_SOC64_BOOT_SCRATCH_COLD0);
+
+	return 0;
+}
+
+unsigned int cm_get_qspi_controller_clk_hz(void)
+{
+	return (readl(socfpga_get_sysmgr_addr() +
+		     SYSMGR_SOC64_BOOT_SCRATCH_COLD0) &
+		     SYSMGR_SCRATCH_REG_0_QSPI_REFCLK_MASK) * 1000;
+}
+#endif
+
 #ifndef CONFIG_SPL_BUILD
 static int do_showclocks(struct cmd_tbl *cmdtp, int flag, int argc,
 			 char *const argv[])
diff --git a/arch/arm/mach-socfpga/clock_manager_agilex.c b/arch/arm/mach-socfpga/clock_manager_agilex.c
index 6377f2c..e035c09 100644
--- a/arch/arm/mach-socfpga/clock_manager_agilex.c
+++ b/arch/arm/mach-socfpga/clock_manager_agilex.c
@@ -65,12 +65,6 @@
 	return cm_get_rate_dm(AGILEX_L4_SYS_FREE_CLK);
 }
 
-u32 cm_get_qspi_controller_clk_hz(void)
-{
-	return readl(socfpga_get_sysmgr_addr() +
-		     SYSMGR_SOC64_BOOT_SCRATCH_COLD0);
-}
-
 void cm_print_clock_quick_summary(void)
 {
 	printf("MPU       %10d kHz\n",
diff --git a/arch/arm/mach-socfpga/clock_manager_s10.c b/arch/arm/mach-socfpga/clock_manager_s10.c
index 642dcbb..4b4f074 100644
--- a/arch/arm/mach-socfpga/clock_manager_s10.c
+++ b/arch/arm/mach-socfpga/clock_manager_s10.c
@@ -8,7 +8,7 @@
 #include <asm/global_data.h>
 #include <asm/io.h>
 #include <asm/arch/clock_manager.h>
-#include <asm/arch/handoff_s10.h>
+#include <asm/arch/handoff_soc64.h>
 #include <asm/arch/system_manager.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -384,12 +384,6 @@
 	return clock;
 }
 
-unsigned int cm_get_qspi_controller_clk_hz(void)
-{
-	return readl(socfpga_get_sysmgr_addr() +
-		     SYSMGR_SOC64_BOOT_SCRATCH_COLD0);
-}
-
 unsigned int cm_get_spi_controller_clk_hz(void)
 {
 	u32 clock = cm_get_l3_main_clk_hz();
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager.h b/arch/arm/mach-socfpga/include/mach/clock_manager.h
index 1f734bc..2f9b471 100644
--- a/arch/arm/mach-socfpga/include/mach/clock_manager.h
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager.h
@@ -12,6 +12,11 @@
 void cm_wait_for_lock(u32 mask);
 int cm_wait_for_fsm(void);
 void cm_print_clock_quick_summary(void);
+unsigned int cm_get_qspi_controller_clk_hz(void);
+
+#if defined(CONFIG_TARGET_SOCFPGA_SOC64)
+int cm_set_qspi_controller_clk_hz(u32 clk_hz);
+#endif
 #endif
 
 #if defined(CONFIG_TARGET_SOCFPGA_GEN5)
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h b/arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h
index 11ddee5..798d374 100644
--- a/arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h
@@ -70,8 +70,6 @@
 unsigned int cm_get_l4_sp_clk_hz(void);
 unsigned long cm_get_mpu_clk_hz(void);
 
-unsigned int cm_get_qspi_controller_clk_hz(void);
-
 #endif /* __ASSEMBLY__ */
 
 #define LOCKED_MASK	(CLKMGR_CLKMGR_STAT_MAINPLLLOCKED_SET_MSK | \
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager_gen5.h b/arch/arm/mach-socfpga/include/mach/clock_manager_gen5.h
index 5c9abe6..4cc1268 100644
--- a/arch/arm/mach-socfpga/include/mach/clock_manager_gen5.h
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager_gen5.h
@@ -100,7 +100,6 @@
 unsigned long cm_get_sdram_clk_hz(void);
 unsigned int cm_get_l4_sp_clk_hz(void);
 unsigned int cm_get_mmc_controller_clk_hz(void);
-unsigned int cm_get_qspi_controller_clk_hz(void);
 unsigned int cm_get_spi_controller_clk_hz(void);
 const unsigned int cm_get_osc_clk_hz(const int osc);
 const unsigned int cm_get_f2s_per_ref_clk_hz(void);
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h b/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h
index cb7923b..98c3bf1 100644
--- a/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h
@@ -15,7 +15,6 @@
 unsigned long cm_get_sdram_clk_hz(void);
 unsigned int cm_get_l4_sp_clk_hz(void);
 unsigned int cm_get_mmc_controller_clk_hz(void);
-unsigned int cm_get_qspi_controller_clk_hz(void);
 unsigned int cm_get_spi_controller_clk_hz(void);
 
 struct cm_config {
diff --git a/arch/arm/mach-socfpga/include/mach/handoff_s10.h b/arch/arm/mach-socfpga/include/mach/handoff_s10.h
deleted file mode 100644
index 3e9b606..0000000
--- a/arch/arm/mach-socfpga/include/mach/handoff_s10.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0
- *
- * Copyright (C) 2016-2018 Intel Corporation <www.intel.com>
- *
- */
-
-#ifndef _HANDOFF_S10_H_
-#define _HANDOFF_S10_H_
-
-/*
- * Offset for HW handoff from Quartus tools
- */
-#define S10_HANDOFF_BASE		0xFFE3F000
-#define S10_HANDOFF_MUX		(S10_HANDOFF_BASE + 0x10)
-#define S10_HANDOFF_IOCTL		(S10_HANDOFF_BASE + 0x1A0)
-#define S10_HANDOFF_FPGA		(S10_HANDOFF_BASE + 0x330)
-#define S10_HANODFF_DELAY		(S10_HANDOFF_BASE + 0x3F0)
-#define S10_HANDOFF_CLOCK		(S10_HANDOFF_BASE + 0x580)
-#define S10_HANDOFF_MISC		(S10_HANDOFF_BASE + 0x610)
-#define S10_HANDOFF_MAGIC_MUX	0x504D5558
-#define S10_HANDOFF_MAGIC_IOCTL	0x494F4354
-#define S10_HANDOFF_MAGIC_FPGA	0x46504741
-#define S10_HANDOFF_MAGIC_DELAY	0x444C4159
-#define S10_HANDOFF_MAGIC_CLOCK	0x434C4B53
-#define S10_HANDOFF_MAGIC_MISC	0x4D495343
-#define S10_HANDOFF_OFFSET_LENGTH	0x4
-#define S10_HANDOFF_OFFSET_DATA	0x10
-
-#ifdef CONFIG_TARGET_SOCFPGA_STRATIX10
-#define HANDOFF_CLOCK_OSC	(S10_HANDOFF_BASE + 0x608)
-#define HANDOFF_CLOCK_FPGA	(S10_HANDOFF_BASE + 0x60C)
-#else
-#define HANDOFF_CLOCK_OSC	(S10_HANDOFF_BASE + 0x5fc)
-#define HANDOFF_CLOCK_FPGA	(S10_HANDOFF_BASE + 0x600)
-#endif
-
-#define S10_HANDOFF_SIZE	4096
-
-#endif /* _HANDOFF_S10_H_ */
diff --git a/arch/arm/mach-socfpga/include/mach/handoff_soc64.h b/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
new file mode 100644
index 0000000..3750216
--- /dev/null
+++ b/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2016-2020 Intel Corporation <www.intel.com>
+ *
+ */
+
+#ifndef _HANDOFF_SOC64_H_
+#define _HANDOFF_SOC64_H_
+
+/*
+ * Offset for HW handoff from Quartus tools
+ */
+/* HPS handoff */
+#define SOC64_HANDOFF_MAGIC_BOOT	0x424F4F54
+#define SOC64_HANDOFF_MAGIC_MUX	0x504D5558
+#define SOC64_HANDOFF_MAGIC_IOCTL	0x494F4354
+#define SOC64_HANDOFF_MAGIC_FPGA	0x46504741
+#define SOC64_HANDOFF_MAGIC_DELAY	0x444C4159
+#define SOC64_HANDOFF_MAGIC_CLOCK	0x434C4B53
+#define SOC64_HANDOFF_MAGIC_MISC	0x4D495343
+
+#define SOC64_HANDOFF_OFFSET_LENGTH	0x4
+#define SOC64_HANDOFF_OFFSET_DATA	0x10
+#define SOC64_HANDOFF_SIZE		4096
+
+#define SOC64_HANDOFF_BASE		0xFFE3F000
+#define SOC64_HANDOFF_MISC		(SOC64_HANDOFF_BASE + 0x610)
+#define SOC64_HANDOFF_MUX		(SOC64_HANDOFF_BASE + 0x10)
+#define SOC64_HANDOFF_IOCTL		(SOC64_HANDOFF_BASE + 0x1A0)
+#define SOC64_HANDOFF_FPGA		(SOC64_HANDOFF_BASE + 0x330)
+#define SOC64_HANDOFF_DELAY		(SOC64_HANDOFF_BASE + 0x3F0)
+#define SOC64_HANDOFF_CLOCK		(SOC64_HANDOFF_BASE + 0x580)
+
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_STRATIX10)
+#define SOC64_HANDOFF_CLOCK_OSC	(SOC64_HANDOFF_BASE + 0x608)
+#define SOC64_HANDOFF_CLOCK_FPGA	(SOC64_HANDOFF_BASE + 0x60C)
+#else
+#define SOC64_HANDOFF_CLOCK_OSC	(SOC64_HANDOFF_BASE + 0x5fc)
+#define SOC64_HANDOFF_CLOCK_FPGA	(SOC64_HANDOFF_BASE + 0x600)
+#endif
+
+#define SOC64_HANDOFF_MUX_LEN			96
+#define SOC64_HANDOFF_IOCTL_LEN			96
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_STRATIX10)
+#define SOC64_HANDOFF_FPGA_LEN			42
+#else
+#define SOC64_HANDOFF_FPGA_LEN			40
+#endif
+#define SOC64_HANDOFF_DELAY_LEN			96
+
+#ifndef __ASSEMBLY__
+#include <asm/types.h>
+enum endianness {
+	LITTLE_ENDIAN = 0,
+	BIG_ENDIAN
+};
+
+int socfpga_get_handoff_size(void *handoff_address, enum endianness endian);
+int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len,
+			 enum endianness big_endian);
+#endif
+#endif /* _HANDOFF_SOC64_H_ */
diff --git a/arch/arm/mach-socfpga/include/mach/reset_manager.h b/arch/arm/mach-socfpga/include/mach/reset_manager.h
index 8c25325..1d68034 100644
--- a/arch/arm/mach-socfpga/include/mach/reset_manager.h
+++ b/arch/arm/mach-socfpga/include/mach/reset_manager.h
@@ -8,7 +8,7 @@
 
 phys_addr_t socfpga_get_rstmgr_addr(void);
 
-void reset_cpu(ulong addr);
+void reset_cpu(void);
 
 void socfpga_per_reset(u32 reset, int set);
 void socfpga_per_reset_all(void);
diff --git a/arch/arm/mach-socfpga/include/mach/smc_api.h b/arch/arm/mach-socfpga/include/mach/smc_api.h
index bbefdd8..6b5b7ea 100644
--- a/arch/arm/mach-socfpga/include/mach/smc_api.h
+++ b/arch/arm/mach-socfpga/include/mach/smc_api.h
@@ -9,5 +9,6 @@
 int invoke_smc(u32 func_id, u64 *args, int arg_len, u64 *ret_arg, int ret_len);
 int smc_send_mailbox(u32 cmd, u32 len, u32 *arg, u8 urgent, u32 *resp_buf_len,
 		     u32 *resp_buf);
+int smc_get_usercode(u32 *usercode);
 
 #endif /* _SMC_API_H_ */
diff --git a/arch/arm/mach-socfpga/include/mach/system_manager_soc64.h b/arch/arm/mach-socfpga/include/mach/system_manager_soc64.h
index 4949cae..fc4e178 100644
--- a/arch/arm/mach-socfpga/include/mach/system_manager_soc64.h
+++ b/arch/arm/mach-socfpga/include/mach/system_manager_soc64.h
@@ -10,10 +10,6 @@
 void sysmgr_pinmux_init(void);
 void populate_sysmgr_fpgaintf_module(void);
 void populate_sysmgr_pinmux(void);
-void sysmgr_pinmux_table_sel(const u32 **table, unsigned int *table_len);
-void sysmgr_pinmux_table_ctrl(const u32 **table, unsigned int *table_len);
-void sysmgr_pinmux_table_fpga(const u32 **table, unsigned int *table_len);
-void sysmgr_pinmux_table_delay(const u32 **table, unsigned int *table_len);
 
 #define SYSMGR_SOC64_WDDBG			0x08
 #define SYSMGR_SOC64_DMA			0x20
@@ -46,7 +42,10 @@
 #define SYSMGR_SOC64_GPO			0xe4
 #define SYSMGR_SOC64_GPI			0xe8
 #define SYSMGR_SOC64_MPU			0xf0
-/* store qspi ref clock */
+/*
+ * Bits[31:28] reserved for N5X DDR retention, bits[27:0] reserved for SOC 64-bit
+ * storing qspi ref clock (kHz)
+ */
 #define SYSMGR_SOC64_BOOT_SCRATCH_COLD0		0x200
 /* store osc1 clock freq */
 #define SYSMGR_SOC64_BOOT_SCRATCH_COLD1		0x204
@@ -89,6 +88,17 @@
 #define SYSMGR_SOC64_HPS_OSC_CLK		0x1358
 #define SYSMGR_SOC64_IODELAY0			0x1400
 
+/*
+ * Bits for SYSMGR_SOC64_BOOT_SCRATCH_COLD0
+ * Bits[31:28] reserved for DM DDR retention, bits[27:0] reserved for SOC 64-bit
+ * storing qspi ref clock (kHz)
+ */
+#define SYSMGR_SCRATCH_REG_0_QSPI_REFCLK_MASK		GENMASK(27, 0)
+#define ALT_SYSMGR_SCRATCH_REG_0_DDR_RETENTION_MASK	BIT(31)
+#define ALT_SYSMGR_SCRATCH_REG_0_DDR_SHA_MASK		BIT(30)
+#define ALT_SYSMGR_SCRATCH_REG_0_DDR_RESET_TYPE_MASK	(BIT(29) | BIT(28))
+#define ALT_SYSMGR_SCRATCH_REG_0_DDR_RESET_TYPE_SHIFT	28
+
 #define SYSMGR_SDMMC				SYSMGR_SOC64_SDMMC
 
 #define SYSMGR_ROMCODEGRP_CTRL_WARMRSTCFGPINMUX	BIT(0)
diff --git a/arch/arm/mach-socfpga/mailbox_s10.c b/arch/arm/mach-socfpga/mailbox_s10.c
index 7dcdae8..101af23 100644
--- a/arch/arm/mach-socfpga/mailbox_s10.c
+++ b/arch/arm/mach-socfpga/mailbox_s10.c
@@ -5,14 +5,15 @@
  */
 
 #include <common.h>
-#include <hang.h>
-#include <wait_bit.h>
-#include <asm/global_data.h>
-#include <asm/io.h>
+#include <asm/arch/clock_manager.h>
 #include <asm/arch/mailbox_s10.h>
 #include <asm/arch/system_manager.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
 #include <asm/secure.h>
 #include <asm/system.h>
+#include <hang.h>
+#include <wait_bit.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -384,10 +385,10 @@
 	if (ret)
 		goto error;
 
-	/* We are getting QSPI ref clock and set into sysmgr boot register */
-	printf("QSPI: Reference clock at %d Hz\n", resp_buf[0]);
-	writel(resp_buf[0],
-	       socfpga_get_sysmgr_addr() + SYSMGR_SOC64_BOOT_SCRATCH_COLD0);
+	/* Store QSPI controller ref clock frequency */
+	ret = cm_set_qspi_controller_clk_hz(resp_buf[0]);
+	if (ret)
+		goto error;
 
 	return 0;
 
diff --git a/arch/arm/mach-socfpga/smc_api.c b/arch/arm/mach-socfpga/smc_api.c
index 085daba..8ffc7a4 100644
--- a/arch/arm/mach-socfpga/smc_api.c
+++ b/arch/arm/mach-socfpga/smc_api.c
@@ -54,3 +54,20 @@
 
 	return (int)resp[0];
 }
+
+int smc_get_usercode(u32 *usercode)
+{
+	int ret;
+	u64 resp;
+
+	if (!usercode)
+		return -EINVAL;
+
+	ret = invoke_smc(INTEL_SIP_SMC_GET_USERCODE, NULL, 0,
+			 &resp, 1);
+
+	if (ret == INTEL_SIP_SMC_STATUS_OK)
+		*usercode = (u32)resp;
+
+	return ret;
+}
diff --git a/arch/arm/mach-socfpga/spl_agilex.c b/arch/arm/mach-socfpga/spl_agilex.c
index 71b17ce..ee5a9dc 100644
--- a/arch/arm/mach-socfpga/spl_agilex.c
+++ b/arch/arm/mach-socfpga/spl_agilex.c
@@ -25,22 +25,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-u32 spl_boot_device(void)
-{
-	return BOOT_DEVICE_MMC1;
-}
-
-#ifdef CONFIG_SPL_MMC_SUPPORT
-u32 spl_mmc_boot_mode(const u32 boot_device)
-{
-#if defined(CONFIG_SPL_FS_FAT) || defined(CONFIG_SPL_FS_EXT4)
-	return MMCSD_MODE_FS;
-#else
-	return MMCSD_MODE_RAW;
-#endif
-}
-#endif
-
 void board_init_f(ulong dummy)
 {
 	int ret;
diff --git a/arch/arm/mach-socfpga/spl_s10.c b/arch/arm/mach-socfpga/spl_s10.c
index 955a116..c20e87c 100644
--- a/arch/arm/mach-socfpga/spl_s10.c
+++ b/arch/arm/mach-socfpga/spl_s10.c
@@ -26,23 +26,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-u32 spl_boot_device(void)
-{
-	/* TODO: Get from SDM or handoff */
-	return BOOT_DEVICE_MMC1;
-}
-
-#ifdef CONFIG_SPL_MMC_SUPPORT
-u32 spl_mmc_boot_mode(const u32 boot_device)
-{
-#if defined(CONFIG_SPL_FS_FAT) || defined(CONFIG_SPL_FS_EXT4)
-	return MMCSD_MODE_FS;
-#else
-	return MMCSD_MODE_RAW;
-#endif
-}
-#endif
-
 void board_init_f(ulong dummy)
 {
 	const struct cm_config *cm_default_cfg = cm_get_default_config();
diff --git a/arch/arm/mach-socfpga/spl_soc64.c b/arch/arm/mach-socfpga/spl_soc64.c
new file mode 100644
index 0000000..cb98ab3
--- /dev/null
+++ b/arch/arm/mach-socfpga/spl_soc64.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Copyright (C) 2020 Intel Corporation. All rights reserved
+ *
+ */
+
+#include <common.h>
+#include <spl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+u32 spl_boot_device(void)
+{
+	return BOOT_DEVICE_MMC1;
+}
+
+#if IS_ENABLED(CONFIG_SPL_MMC_SUPPORT)
+u32 spl_boot_mode(const u32 boot_device)
+{
+	if (IS_ENABLED(CONFIG_SPL_FS_FAT) || IS_ENABLED(CONFIG_SPL_FS_EXT4))
+		return MMCSD_MODE_FS;
+	else
+		return MMCSD_MODE_RAW;
+}
+#endif
diff --git a/arch/arm/mach-socfpga/system_manager_s10.c b/arch/arm/mach-socfpga/system_manager_s10.c
deleted file mode 100644
index c123cc9..0000000
--- a/arch/arm/mach-socfpga/system_manager_s10.c
+++ /dev/null
@@ -1,102 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2016-2018 Intel Corporation <www.intel.com>
- *
- */
-
-#include <common.h>
-#include <asm/global_data.h>
-#include <asm/io.h>
-#include <asm/arch/system_manager.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-/*
- * Configure all the pin muxes
- */
-void sysmgr_pinmux_init(void)
-{
-	populate_sysmgr_pinmux();
-	populate_sysmgr_fpgaintf_module();
-}
-
-/*
- * Populate the value for SYSMGR.FPGAINTF.MODULE based on pinmux setting.
- * The value is not wrote to SYSMGR.FPGAINTF.MODULE but
- * CONFIG_SYSMGR_ISWGRP_HANDOFF.
- */
-void populate_sysmgr_fpgaintf_module(void)
-{
-	u32 handoff_val = 0;
-
-	/* Enable the signal for those HPS peripherals that use FPGA. */
-	if (readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_NAND_USEFPGA) ==
-	    SYSMGR_FPGAINTF_USEFPGA)
-		handoff_val |= SYSMGR_FPGAINTF_NAND;
-	if (readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_SDMMC_USEFPGA) ==
-	    SYSMGR_FPGAINTF_USEFPGA)
-		handoff_val |= SYSMGR_FPGAINTF_SDMMC;
-	if (readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_SPIM0_USEFPGA) ==
-	    SYSMGR_FPGAINTF_USEFPGA)
-		handoff_val |= SYSMGR_FPGAINTF_SPIM0;
-	if (readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_SPIM1_USEFPGA) ==
-	    SYSMGR_FPGAINTF_USEFPGA)
-		handoff_val |= SYSMGR_FPGAINTF_SPIM1;
-	writel(handoff_val,
-	       socfpga_get_sysmgr_addr() + SYSMGR_SOC64_FPGAINTF_EN2);
-
-	handoff_val = 0;
-	if (readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC0_USEFPGA) ==
-	    SYSMGR_FPGAINTF_USEFPGA)
-		handoff_val |= SYSMGR_FPGAINTF_EMAC0;
-	if (readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC1_USEFPGA) ==
-	    SYSMGR_FPGAINTF_USEFPGA)
-		handoff_val |= SYSMGR_FPGAINTF_EMAC1;
-	if (readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC2_USEFPGA) ==
-	    SYSMGR_FPGAINTF_USEFPGA)
-		handoff_val |= SYSMGR_FPGAINTF_EMAC2;
-	writel(handoff_val,
-	       socfpga_get_sysmgr_addr() + SYSMGR_SOC64_FPGAINTF_EN3);
-}
-
-/*
- * Configure all the pin muxes
- */
-void populate_sysmgr_pinmux(void)
-{
-	const u32 *sys_mgr_table_u32;
-	unsigned int len, i;
-
-	/* setup the pin sel */
-	sysmgr_pinmux_table_sel(&sys_mgr_table_u32, &len);
-	for (i = 0; i < len; i = i + 2) {
-		writel(sys_mgr_table_u32[i + 1],
-		       sys_mgr_table_u32[i] +
-		       (u8 *)socfpga_get_sysmgr_addr() + SYSMGR_SOC64_PINSEL0);
-	}
-
-	/* setup the pin ctrl */
-	sysmgr_pinmux_table_ctrl(&sys_mgr_table_u32, &len);
-	for (i = 0; i < len; i = i + 2) {
-		writel(sys_mgr_table_u32[i + 1],
-		       sys_mgr_table_u32[i] +
-		       (u8 *)socfpga_get_sysmgr_addr() + SYSMGR_SOC64_IOCTRL0);
-	}
-
-	/* setup the fpga use */
-	sysmgr_pinmux_table_fpga(&sys_mgr_table_u32, &len);
-	for (i = 0; i < len; i = i + 2) {
-		writel(sys_mgr_table_u32[i + 1],
-		       sys_mgr_table_u32[i] +
-		       (u8 *)socfpga_get_sysmgr_addr() +
-		       SYSMGR_SOC64_EMAC0_USEFPGA);
-	}
-
-	/* setup the IO delay */
-	sysmgr_pinmux_table_delay(&sys_mgr_table_u32, &len);
-	for (i = 0; i < len; i = i + 2) {
-		writel(sys_mgr_table_u32[i + 1],
-		       sys_mgr_table_u32[i] +
-		       (u8 *)socfpga_get_sysmgr_addr() + SYSMGR_SOC64_IODELAY0);
-	}
-}
diff --git a/arch/arm/mach-socfpga/system_manager_soc64.c b/arch/arm/mach-socfpga/system_manager_soc64.c
new file mode 100644
index 0000000..3b5e774
--- /dev/null
+++ b/arch/arm/mach-socfpga/system_manager_soc64.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016-2018 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <asm/arch/handoff_soc64.h>
+#include <asm/arch/system_manager.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Configure all the pin muxes
+ */
+void sysmgr_pinmux_init(void)
+{
+	populate_sysmgr_pinmux();
+	populate_sysmgr_fpgaintf_module();
+}
+
+/*
+ * Populate the value for SYSMGR.FPGAINTF.MODULE based on pinmux setting.
+ * The value is not wrote to SYSMGR.FPGAINTF.MODULE but
+ * CONFIG_SYSMGR_ISWGRP_HANDOFF.
+ */
+void populate_sysmgr_fpgaintf_module(void)
+{
+	u32 handoff_val = 0;
+
+	/* Enable the signal for those HPS peripherals that use FPGA. */
+	if (readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_NAND_USEFPGA) ==
+	    SYSMGR_FPGAINTF_USEFPGA)
+		handoff_val |= SYSMGR_FPGAINTF_NAND;
+	if (readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_SDMMC_USEFPGA) ==
+	    SYSMGR_FPGAINTF_USEFPGA)
+		handoff_val |= SYSMGR_FPGAINTF_SDMMC;
+	if (readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_SPIM0_USEFPGA) ==
+	    SYSMGR_FPGAINTF_USEFPGA)
+		handoff_val |= SYSMGR_FPGAINTF_SPIM0;
+	if (readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_SPIM1_USEFPGA) ==
+	    SYSMGR_FPGAINTF_USEFPGA)
+		handoff_val |= SYSMGR_FPGAINTF_SPIM1;
+	writel(handoff_val,
+	       socfpga_get_sysmgr_addr() + SYSMGR_SOC64_FPGAINTF_EN2);
+
+	handoff_val = 0;
+	if (readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC0_USEFPGA) ==
+	    SYSMGR_FPGAINTF_USEFPGA)
+		handoff_val |= SYSMGR_FPGAINTF_EMAC0;
+	if (readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC1_USEFPGA) ==
+	    SYSMGR_FPGAINTF_USEFPGA)
+		handoff_val |= SYSMGR_FPGAINTF_EMAC1;
+	if (readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC2_USEFPGA) ==
+	    SYSMGR_FPGAINTF_USEFPGA)
+		handoff_val |= SYSMGR_FPGAINTF_EMAC2;
+	writel(handoff_val,
+	       socfpga_get_sysmgr_addr() + SYSMGR_SOC64_FPGAINTF_EN3);
+}
+
+/*
+ * Configure all the pin muxes
+ */
+void populate_sysmgr_pinmux(void)
+{
+	u32 len, i;
+	u32 len_mux = socfpga_get_handoff_size((void *)SOC64_HANDOFF_MUX, BIG_ENDIAN);
+	u32 len_ioctl = socfpga_get_handoff_size((void *)SOC64_HANDOFF_IOCTL, BIG_ENDIAN);
+	u32 len_fpga = socfpga_get_handoff_size((void *)SOC64_HANDOFF_FPGA, BIG_ENDIAN);
+	u32 len_delay = socfpga_get_handoff_size((void *)SOC64_HANDOFF_DELAY, BIG_ENDIAN);
+
+	len = (len_mux > len_ioctl) ? len_mux : len_ioctl;
+	len = (len > len_fpga) ? len : len_fpga;
+	len = (len > len_delay) ? len : len_delay;
+
+	u32 handoff_table[len];
+
+	/* setup the pin sel */
+	len = (len_mux < SOC64_HANDOFF_MUX_LEN) ? len_mux : SOC64_HANDOFF_MUX_LEN;
+	socfpga_handoff_read((void *)SOC64_HANDOFF_MUX, handoff_table, len, BIG_ENDIAN);
+	for (i = 0; i < len; i = i + 2) {
+		writel(handoff_table[i + 1],
+		       handoff_table[i] +
+		       (u8 *)socfpga_get_sysmgr_addr() +
+		       SYSMGR_SOC64_PINSEL0);
+	}
+
+	/* setup the pin ctrl */
+	len = (len_ioctl < SOC64_HANDOFF_IOCTL_LEN) ? len_ioctl : SOC64_HANDOFF_IOCTL_LEN;
+	socfpga_handoff_read((void *)SOC64_HANDOFF_IOCTL, handoff_table, len, BIG_ENDIAN);
+	for (i = 0; i < len; i = i + 2) {
+		writel(handoff_table[i + 1],
+		       handoff_table[i] +
+		       (u8 *)socfpga_get_sysmgr_addr() +
+		       SYSMGR_SOC64_IOCTRL0);
+	}
+
+	/* setup the fpga use */
+	len = (len_fpga < SOC64_HANDOFF_FPGA_LEN) ? len_fpga : SOC64_HANDOFF_FPGA_LEN;
+	socfpga_handoff_read((void *)SOC64_HANDOFF_FPGA, handoff_table, len, BIG_ENDIAN);
+	for (i = 0; i < len; i = i + 2) {
+		writel(handoff_table[i + 1],
+		       handoff_table[i] +
+		       (u8 *)socfpga_get_sysmgr_addr() +
+		       SYSMGR_SOC64_EMAC0_USEFPGA);
+	}
+
+	/* setup the IO delay */
+	len = (len_delay < SOC64_HANDOFF_DELAY_LEN) ? len_delay : SOC64_HANDOFF_DELAY_LEN;
+	socfpga_handoff_read((void *)SOC64_HANDOFF_DELAY, handoff_table, len, BIG_ENDIAN);
+	for (i = 0; i < len; i = i + 2) {
+		writel(handoff_table[i + 1],
+		       handoff_table[i] +
+		       (u8 *)socfpga_get_sysmgr_addr() +
+		       SYSMGR_SOC64_IODELAY0);
+	}
+}
diff --git a/arch/arm/mach-socfpga/wrap_handoff_soc64.c b/arch/arm/mach-socfpga/wrap_handoff_soc64.c
new file mode 100644
index 0000000..a7ad7a1
--- /dev/null
+++ b/arch/arm/mach-socfpga/wrap_handoff_soc64.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <asm/arch/handoff_soc64.h>
+#include <asm/io.h>
+#include <common.h>
+#include <errno.h>
+#include "log.h"
+
+int socfpga_get_handoff_size(void *handoff_address, enum endianness endian)
+{
+	u32 size;
+
+	size = readl(handoff_address + SOC64_HANDOFF_OFFSET_LENGTH);
+	if (endian == BIG_ENDIAN)
+		size = swab32(size);
+
+	size = (size - SOC64_HANDOFF_OFFSET_DATA) / sizeof(u32);
+
+	debug("%s: handoff address = 0x%p handoff size = 0x%08x\n", __func__,
+	      (u32 *)handoff_address, size);
+
+	return size;
+}
+
+int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len,
+			 enum endianness big_endian)
+{
+	u32 temp, i;
+	u32 *table_x32 = table;
+
+	debug("%s: handoff addr = 0x%p ", __func__, (u32 *)handoff_address);
+
+	if (big_endian) {
+		if (swab32(readl(SOC64_HANDOFF_BASE)) == SOC64_HANDOFF_MAGIC_BOOT) {
+			debug("Handoff table address = 0x%p ", table_x32);
+			debug("table length = 0x%x\n", table_len);
+			debug("%s: handoff data =\n{\n", __func__);
+
+			for (i = 0; i < table_len; i++) {
+				temp = readl(handoff_address +
+					     SOC64_HANDOFF_OFFSET_DATA +
+					     (i * sizeof(u32)));
+				*table_x32 = swab32(temp);
+
+				if (!(i % 2))
+					debug(" No.%d Addr 0x%08x: ", i,
+					      *table_x32);
+				else
+					debug(" 0x%08x\n", *table_x32);
+
+				table_x32++;
+			}
+			debug("\n}\n");
+		} else {
+			debug("%s: Cannot find SOC64_HANDOFF_MAGIC_BOOT ", __func__);
+			debug("at addr  0x%p\n", (u32 *)handoff_address);
+			return -EPERM;
+		}
+	}
+
+	return 0;
+}
diff --git a/arch/arm/mach-socfpga/wrap_pinmux_config_s10.c b/arch/arm/mach-socfpga/wrap_pinmux_config_s10.c
deleted file mode 100644
index 0b497ec..0000000
--- a/arch/arm/mach-socfpga/wrap_pinmux_config_s10.c
+++ /dev/null
@@ -1,56 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2016-2018 Intel Corporation <www.intel.com>
- *
- */
-
-#include <common.h>
-#include <errno.h>
-#include <asm/io.h>
-#include <asm/arch/handoff_s10.h>
-
-static void sysmgr_pinmux_handoff_read(void *handoff_address,
-				       const u32 **table,
-				       unsigned int *table_len)
-{
-	unsigned int handoff_entry = (swab32(readl(handoff_address +
-					S10_HANDOFF_OFFSET_LENGTH)) -
-					S10_HANDOFF_OFFSET_DATA) /
-					sizeof(unsigned int);
-	unsigned int handoff_chunk[handoff_entry], temp, i;
-
-	if (swab32(readl(S10_HANDOFF_MUX)) == S10_HANDOFF_MAGIC_MUX) {
-		/* using handoff from Quartus tools if exists */
-		for (i = 0; i < handoff_entry; i++) {
-			temp = readl(handoff_address +
-				     S10_HANDOFF_OFFSET_DATA + (i * 4));
-			handoff_chunk[i] = swab32(temp);
-		}
-		*table = handoff_chunk;
-		*table_len = ARRAY_SIZE(handoff_chunk);
-	}
-}
-
-void sysmgr_pinmux_table_sel(const u32 **table, unsigned int *table_len)
-{
-	sysmgr_pinmux_handoff_read((void *)S10_HANDOFF_MUX, table,
-				   table_len);
-}
-
-void sysmgr_pinmux_table_ctrl(const u32 **table, unsigned int *table_len)
-{
-	sysmgr_pinmux_handoff_read((void *)S10_HANDOFF_IOCTL, table,
-				   table_len);
-}
-
-void sysmgr_pinmux_table_fpga(const u32 **table, unsigned int *table_len)
-{
-	sysmgr_pinmux_handoff_read((void *)S10_HANDOFF_FPGA, table,
-				   table_len);
-}
-
-void sysmgr_pinmux_table_delay(const u32 **table, unsigned int *table_len)
-{
-	sysmgr_pinmux_handoff_read((void *)S10_HANODFF_DELAY, table,
-				   table_len);
-}
diff --git a/arch/arm/mach-socfpga/wrap_pll_config_s10.c b/arch/arm/mach-socfpga/wrap_pll_config_soc64.c
similarity index 74%
rename from arch/arm/mach-socfpga/wrap_pll_config_s10.c
rename to arch/arm/mach-socfpga/wrap_pll_config_soc64.c
index 049c571..6a0d6b5 100644
--- a/arch/arm/mach-socfpga/wrap_pll_config_s10.c
+++ b/arch/arm/mach-socfpga/wrap_pll_config_soc64.c
@@ -7,24 +7,24 @@
 #include <common.h>
 #include <asm/arch/clock_manager.h>
 #include <asm/io.h>
-#include <asm/arch/handoff_s10.h>
+#include <asm/arch/handoff_soc64.h>
 #include <asm/arch/system_manager.h>
 
 const struct cm_config * const cm_get_default_config(void)
 {
 #ifdef CONFIG_SPL_BUILD
 	struct cm_config *cm_handoff_cfg = (struct cm_config *)
-		(S10_HANDOFF_CLOCK + S10_HANDOFF_OFFSET_DATA);
+		(SOC64_HANDOFF_CLOCK + SOC64_HANDOFF_OFFSET_DATA);
 	u32 *conversion = (u32 *)cm_handoff_cfg;
 	u32 i;
-	u32 handoff_clk = readl(S10_HANDOFF_CLOCK);
+	u32 handoff_clk = readl(SOC64_HANDOFF_CLOCK);
 
-	if (swab32(handoff_clk) == S10_HANDOFF_MAGIC_CLOCK) {
-		writel(swab32(handoff_clk), S10_HANDOFF_CLOCK);
+	if (swab32(handoff_clk) == SOC64_HANDOFF_MAGIC_CLOCK) {
+		writel(swab32(handoff_clk), SOC64_HANDOFF_CLOCK);
 		for (i = 0; i < (sizeof(*cm_handoff_cfg) / sizeof(u32)); i++)
 			conversion[i] = swab32(conversion[i]);
 		return cm_handoff_cfg;
-	} else if (handoff_clk == S10_HANDOFF_MAGIC_CLOCK) {
+	} else if (handoff_clk == SOC64_HANDOFF_MAGIC_CLOCK) {
 		return cm_handoff_cfg;
 	}
 #endif
@@ -35,7 +35,7 @@
 {
 #ifdef CONFIG_SPL_BUILD
 
-	u32 clock = readl(HANDOFF_CLOCK_OSC);
+	u32 clock = readl(SOC64_HANDOFF_CLOCK_OSC);
 
 	writel(clock,
 	       socfpga_get_sysmgr_addr() + SYSMGR_SOC64_BOOT_SCRATCH_COLD1);
@@ -52,7 +52,7 @@
 const unsigned int cm_get_fpga_clk_hz(void)
 {
 #ifdef CONFIG_SPL_BUILD
-	u32 clock = readl(HANDOFF_CLOCK_FPGA);
+	u32 clock = readl(SOC64_HANDOFF_CLOCK_FPGA);
 
 	writel(clock,
 	       socfpga_get_sysmgr_addr() + SYSMGR_SOC64_BOOT_SCRATCH_COLD2);
diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c
index b8f05ab..8115d58 100644
--- a/arch/arm/mach-stm32mp/cpu.c
+++ b/arch/arm/mach-stm32mp/cpu.c
@@ -212,6 +212,35 @@
 }
 
 /*
+ * weak function overidde: set the DDR/SYSRAM executable before to enable the
+ * MMU and configure DACR, for early early_enable_caches (SPL or pre-reloc)
+ */
+void dram_bank_mmu_setup(int bank)
+{
+	struct bd_info *bd = gd->bd;
+	int	i;
+	phys_addr_t start;
+	phys_size_t size;
+
+	if (IS_ENABLED(CONFIG_SPL_BUILD)) {
+		start = ALIGN_DOWN(STM32_SYSRAM_BASE, MMU_SECTION_SIZE);
+		size = ALIGN(STM32_SYSRAM_SIZE, MMU_SECTION_SIZE);
+	} else if (gd->flags & GD_FLG_RELOC) {
+		/* bd->bi_dram is available only after relocation */
+		start = bd->bi_dram[bank].start;
+		size =  bd->bi_dram[bank].size;
+	} else {
+		/* mark cacheable and executable the beggining of the DDR */
+		start = STM32_DDR_BASE;
+		size = CONFIG_DDR_CACHEABLE_SIZE;
+	}
+
+	for (i = start >> MMU_SECTION_SHIFT;
+	     i < (start >> MMU_SECTION_SHIFT) + (size >> MMU_SECTION_SHIFT);
+	     i++)
+		set_section_dcache(i, DCACHE_DEFAULT_OPTION);
+}
+/*
  * initialize the MMU and activate cache in SPL or in U-Boot pre-reloc stage
  * MMU/TLB is updated in enable_caches() for U-Boot after relocation
  * or is deactivated in U-Boot entry function start.S::cpu_init_cp15
@@ -228,17 +257,8 @@
 		gd->arch.tlb_addr = (unsigned long)&early_tlb;
 	}
 
+	/* enable MMU (default configuration) */
 	dcache_enable();
-
-	if (IS_ENABLED(CONFIG_SPL_BUILD))
-		mmu_set_region_dcache_behaviour(
-			ALIGN_DOWN(STM32_SYSRAM_BASE, MMU_SECTION_SIZE),
-			ALIGN(STM32_SYSRAM_SIZE, MMU_SECTION_SIZE),
-			DCACHE_DEFAULT_OPTION);
-	else
-		mmu_set_region_dcache_behaviour(STM32_DDR_BASE,
-						CONFIG_DDR_CACHEABLE_SIZE,
-						DCACHE_DEFAULT_OPTION);
 }
 
 /*
diff --git a/arch/arm/mach-stm32mp/dram_init.c b/arch/arm/mach-stm32mp/dram_init.c
index ad6977f..66e81ba 100644
--- a/arch/arm/mach-stm32mp/dram_init.c
+++ b/arch/arm/mach-stm32mp/dram_init.c
@@ -13,6 +13,7 @@
 #include <log.h>
 #include <ram.h>
 #include <asm/global_data.h>
+#include <asm/system.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -41,6 +42,7 @@
 
 ulong board_get_usable_ram_top(ulong total_size)
 {
+	phys_size_t size;
 	phys_addr_t reg;
 	struct lmb lmb;
 
@@ -48,10 +50,13 @@
 	lmb_init(&lmb);
 	lmb_add(&lmb, gd->ram_base, gd->ram_size);
 	boot_fdt_add_mem_rsv_regions(&lmb, (void *)gd->fdt_blob);
-	reg = lmb_alloc(&lmb, CONFIG_SYS_MALLOC_LEN + total_size, SZ_4K);
+	size = ALIGN(CONFIG_SYS_MALLOC_LEN + total_size, MMU_SECTION_SIZE),
+	reg = lmb_alloc(&lmb, size, MMU_SECTION_SIZE);
 
-	if (reg)
-		return ALIGN(reg + CONFIG_SYS_MALLOC_LEN + total_size, SZ_4K);
+	if (!reg)
+		reg = gd->ram_top - size;
 
-	return gd->ram_top;
+	mmu_set_region_dcache_behaviour(reg, size, DCACHE_DEFAULT_OPTION);
+
+	return reg + size;
 }
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 0135575..a29d115 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -816,13 +816,14 @@
 	depends on !MACH_SUN9I
 	depends on !MACH_SUN50I
 	depends on !SUN50I_GEN_H6
-	select VIDEO
+	select DM_VIDEO
+	select DISPLAY
 	imply VIDEO_DT_SIMPLEFB
 	default y
 	---help---
-	Say Y here to add support for using a cfb console on the HDMI, LCD
-	or VGA output found on most sunxi devices. See doc/README.video for
-	info on how to select the video output and mode.
+	Say Y here to add support for using a graphical console on the HDMI,
+	LCD or VGA output found on older sunxi devices. This will also provide
+	a simple_framebuffer device for Linux.
 
 config VIDEO_HDMI
 	bool "HDMI output support"
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index fa2b6fc..503538e 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -338,7 +338,7 @@
 }
 #endif
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 #if defined(CONFIG_SUNXI_GEN_SUN4I) || defined(CONFIG_MACH_SUN8I_R40)
 	static const struct sunxi_wdog *wdog =
diff --git a/arch/arm/mach-tegra/cmd_enterrcm.c b/arch/arm/mach-tegra/cmd_enterrcm.c
index 25df31a..92ff6cb 100644
--- a/arch/arm/mach-tegra/cmd_enterrcm.c
+++ b/arch/arm/mach-tegra/cmd_enterrcm.c
@@ -40,7 +40,7 @@
 
 	tegra_pmc_writel(2, PMC_SCRATCH0);
 	disable_interrupts();
-	reset_cpu(0);
+	reset_cpu();
 
 	return 0;
 }
diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
index 93db63e..8d617be 100644
--- a/arch/arm/mach-tegra/pmc.c
+++ b/arch/arm/mach-tegra/pmc.c
@@ -85,7 +85,7 @@
 	writel(value, NV_PA_PMC_BASE + offset);
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	u32 value;
 
diff --git a/arch/arm/mach-uniphier/arm32/psci.c b/arch/arm/mach-uniphier/arm32/psci.c
index a4d260a..fbb6ebc 100644
--- a/arch/arm/mach-uniphier/arm32/psci.c
+++ b/arch/arm/mach-uniphier/arm32/psci.c
@@ -158,5 +158,5 @@
 
 void __secure psci_system_reset(void)
 {
-	reset_cpu(0);
+	reset_cpu();
 }
diff --git a/arch/arm/mach-uniphier/reset.c b/arch/arm/mach-uniphier/reset.c
index 5fffd23..dddb48e 100644
--- a/arch/arm/mach-uniphier/reset.c
+++ b/arch/arm/mach-uniphier/reset.c
@@ -18,7 +18,7 @@
 #define __SECURE
 #endif
 
-void __SECURE reset_cpu(unsigned long ignored)
+void __SECURE reset_cpu(void)
 {
 	u32 tmp;
 
diff --git a/arch/arm/mach-zynq/cpu.c b/arch/arm/mach-zynq/cpu.c
index 3befc12..69b818f 100644
--- a/arch/arm/mach-zynq/cpu.c
+++ b/arch/arm/mach-zynq/cpu.c
@@ -78,7 +78,7 @@
 						>> ZYNQ_SILICON_VER_SHIFT;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	zynq_slcr_cpu_reset();
 	while (1)
diff --git a/arch/arm/mach-zynqmp-r5/cpu.c b/arch/arm/mach-zynqmp-r5/cpu.c
index d841c3a..0d36844 100644
--- a/arch/arm/mach-zynqmp-r5/cpu.c
+++ b/arch/arm/mach-zynqmp-r5/cpu.c
@@ -30,7 +30,7 @@
 /*
  * Perform the low-level reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	while (1)
 		;
diff --git a/arch/nds32/cpu/n1213/ag101/cpu.c b/arch/nds32/cpu/n1213/ag101/cpu.c
index 9d99c83..91c3574 100644
--- a/arch/nds32/cpu/n1213/ag101/cpu.c
+++ b/arch/nds32/cpu/n1213/ag101/cpu.c
@@ -46,7 +46,7 @@
 	/*
 	 * reset to the base addr of andesboot.
 	 * currently no ROM loader at addr 0.
-	 * do not use reset_cpu(0);
+	 * do not use reset_cpu();
 	 */
 #ifdef CONFIG_FTWDT010_WATCHDOG
 	/*
diff --git a/arch/nds32/cpu/n1213/start.S b/arch/nds32/cpu/n1213/start.S
index 386c199..3395721 100644
--- a/arch/nds32/cpu/n1213/start.S
+++ b/arch/nds32/cpu/n1213/start.S
@@ -500,25 +500,3 @@
 	bal	do_interruption
 
 	.align	5
-
-/*
- * void reset_cpu(ulong addr);
- * $r0: input address to jump to
- */
-.globl reset_cpu
-reset_cpu:
-/* No need to disable MMU because we never enable it */
-
-	bal	invalidate_icac
-	bal	invalidate_dcac
-	mfsr	$p0, $MMU_CFG
-	andi	$p0, $p0, 0x3			! MMPS
-	li	$p1, 0x2			! TLB MMU
-	bne	$p0, $p1, 1f
-	tlbop	flushall			! Flush TLB
-1:
-	mfsr	$p0, MR_CAC_CTL			! Get the $CACHE_CTL reg
-	li	$p1, DIS_DCAC
-	and	$p0, $p0, $p1			! Clear the DC_EN bit
-	mtsr	$p0, MR_CAC_CTL			! Write back the $CACHE_CTL reg
-	br	$r0				! Jump to the input address
diff --git a/arch/nds32/lib/interrupts.c b/arch/nds32/lib/interrupts.c
index 1481e05..0ec72d1 100644
--- a/arch/nds32/lib/interrupts.c
+++ b/arch/nds32/lib/interrupts.c
@@ -66,7 +66,7 @@
 void bad_mode(void)
 {
 	panic("Resetting CPU ...\n");
-	reset_cpu(0);
+	reset_cpu();
 }
 
 void show_regs(struct pt_regs *regs)
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 55eaee2..3f221dc 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -17,8 +17,8 @@
 config TARGET_QEMU_VIRT
 	bool "Support QEMU Virt Board"
 
-config TARGET_SIFIVE_FU540
-	bool "Support SiFive FU540 Board"
+config TARGET_SIFIVE_UNLEASHED
+	bool "Support SiFive Unleashed Board"
 
 config TARGET_SIPEED_MAIX
 	bool "Support Sipeed Maix Board"
@@ -55,7 +55,7 @@
 source "board/AndesTech/ax25-ae350/Kconfig"
 source "board/emulation/qemu-riscv/Kconfig"
 source "board/microchip/mpfs_icicle/Kconfig"
-source "board/sifive/fu540/Kconfig"
+source "board/sifive/unleashed/Kconfig"
 source "board/sipeed/maix/Kconfig"
 
 # platform-specific options below
@@ -271,4 +271,82 @@
 config OF_BOARD_FIXUP
 	default y if OF_SEPARATE && RISCV_SMODE
 
+config USE_ARCH_MEMCPY
+	bool "Use an assembly optimized implementation of memcpy"
+	default y
+	help
+	  Enable the generation of an optimized version of memcpy.
+	  Such an implementation may be faster under some conditions
+	  but may increase the binary size.
+
+config SPL_USE_ARCH_MEMCPY
+	bool "Use an assembly optimized implementation of memcpy for SPL"
+	default y if USE_ARCH_MEMCPY
+	depends on SPL
+	help
+	  Enable the generation of an optimized version of memcpy.
+	  Such an implementation may be faster under some conditions
+	  but may increase the binary size.
+
+config TPL_USE_ARCH_MEMCPY
+	bool "Use an assembly optimized implementation of memcpy for TPL"
+	default y if USE_ARCH_MEMCPY
+	depends on TPL
+	help
+	  Enable the generation of an optimized version of memcpy.
+	  Such an implementation may be faster under some conditions
+	  but may increase the binary size.
+
+config USE_ARCH_MEMMOVE
+	bool "Use an assembly optimized implementation of memmove"
+	default y
+	help
+	  Enable the generation of an optimized version of memmove.
+	  Such an implementation may be faster under some conditions
+	  but may increase the binary size.
+
+config SPL_USE_ARCH_MEMMOVE
+	bool "Use an assembly optimized implementation of memmove for SPL"
+	default y if USE_ARCH_MEMCPY
+	depends on SPL
+	help
+	  Enable the generation of an optimized version of memmove.
+	  Such an implementation may be faster under some conditions
+	  but may increase the binary size.
+
+config TPL_USE_ARCH_MEMMOVE
+	bool "Use an assembly optimized implementation of memmove for TPL"
+	default y if USE_ARCH_MEMCPY
+	depends on TPL
+	help
+	  Enable the generation of an optimized version of memmove.
+	  Such an implementation may be faster under some conditions
+	  but may increase the binary size.
+
+config USE_ARCH_MEMSET
+	bool "Use an assembly optimized implementation of memset"
+	default y
+	help
+	  Enable the generation of an optimized version of memset.
+	  Such an implementation may be faster under some conditions
+	  but may increase the binary size.
+
+config SPL_USE_ARCH_MEMSET
+	bool "Use an assembly optimized implementation of memset for SPL"
+	default y if USE_ARCH_MEMSET
+	depends on SPL
+	help
+	  Enable the generation of an optimized version of memset.
+	  Such an implementation may be faster under some conditions
+	  but may increase the binary size.
+
+config TPL_USE_ARCH_MEMSET
+	bool "Use an assembly optimized implementation of memset for TPL"
+	default y if USE_ARCH_MEMSET
+	depends on TPL
+	help
+	  Enable the generation of an optimized version of memset.
+	  Such an implementation may be faster under some conditions
+	  but may increase the binary size.
+
 endmenu
diff --git a/arch/riscv/cpu/ax25/Kconfig b/arch/riscv/cpu/ax25/Kconfig
index 327b74e..941d963 100644
--- a/arch/riscv/cpu/ax25/Kconfig
+++ b/arch/riscv/cpu/ax25/Kconfig
@@ -6,7 +6,7 @@
 	imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE)
 	imply ANDES_PLIC if (RISCV_MMODE || SPL_RISCV_MMODE)
 	imply ANDES_PLMT_TIMER if (RISCV_MMODE || SPL_RISCV_MMODE)
-	imply SPL_CPU_SUPPORT
+	imply SPL_CPU
 	imply SPL_OPENSBI
 	imply SPL_LOAD_FIT
 	help
diff --git a/arch/riscv/cpu/fu540/Kconfig b/arch/riscv/cpu/fu540/Kconfig
index 61bd5c4..616b256 100644
--- a/arch/riscv/cpu/fu540/Kconfig
+++ b/arch/riscv/cpu/fu540/Kconfig
@@ -13,7 +13,7 @@
 	imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE)
 	imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE)
 	imply CMD_CPU
-	imply SPL_CPU_SUPPORT
+	imply SPL_CPU
 	imply SPL_OPENSBI
 	imply SPL_LOAD_FIT
 	imply SMP
diff --git a/arch/riscv/cpu/generic/Kconfig b/arch/riscv/cpu/generic/Kconfig
index f4c2e26..198e36e 100644
--- a/arch/riscv/cpu/generic/Kconfig
+++ b/arch/riscv/cpu/generic/Kconfig
@@ -10,6 +10,6 @@
 	imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE)
 	imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE)
 	imply CMD_CPU
-	imply SPL_CPU_SUPPORT
+	imply SPL_CPU
 	imply SPL_OPENSBI
 	imply SPL_LOAD_FIT
diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile
index 01331b0..8138d89 100644
--- a/arch/riscv/dts/Makefile
+++ b/arch/riscv/dts/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 
 dtb-$(CONFIG_TARGET_AX25_AE350) += ae350_32.dtb ae350_64.dtb
-dtb-$(CONFIG_TARGET_SIFIVE_FU540) += hifive-unleashed-a00.dtb
+dtb-$(CONFIG_TARGET_SIFIVE_UNLEASHED) += hifive-unleashed-a00.dtb
 dtb-$(CONFIG_TARGET_SIPEED_MAIX) += k210-maix-bit.dtb
 dtb-$(CONFIG_TARGET_MICROCHIP_ICICLE) += microchip-mpfs-icicle-kit.dtb
 
diff --git a/arch/riscv/dts/k210.dtsi b/arch/riscv/dts/k210.dtsi
index 81b0401..0b79a29 100644
--- a/arch/riscv/dts/k210.dtsi
+++ b/arch/riscv/dts/k210.dtsi
@@ -439,7 +439,6 @@
 				interrupts = <21>;
 				clocks = <&sysclk K210_CLK_WDT0>;
 				resets = <&sysrst K210_RST_WDT0>;
-				status = "disabled";
 			};
 
 			wdt1: watchdog@50410000 {
diff --git a/arch/riscv/dts/microchip-mpfs-icicle-kit.dts b/arch/riscv/dts/microchip-mpfs-icicle-kit.dts
index e2b9dec..89c4cf5 100644
--- a/arch/riscv/dts/microchip-mpfs-icicle-kit.dts
+++ b/arch/riscv/dts/microchip-mpfs-icicle-kit.dts
@@ -232,7 +232,6 @@
 			reg-shift = <2>;
 			interrupt-parent = <&plic>;
 			interrupts = <90>;
-			clock-frequency = <150000000>;
 			clocks = <&clkcfg CLK_MMUART0>;
 			status = "okay";
 		};
@@ -294,7 +293,6 @@
 			reg-shift = <2>;
 			interrupt-parent = <&plic>;
 			interrupts = <91>;
-			clock-frequency = <150000000>;
 			clocks = <&clkcfg CLK_MMUART1>;
 			status = "okay";
 		};
@@ -305,7 +303,6 @@
 			reg-shift = <2>;
 			interrupt-parent = <&plic>;
 			interrupts = <92>;
-			clock-frequency = <150000000>;
 			clocks = <&clkcfg CLK_MMUART2>;
 			status = "okay";
 		};
@@ -316,7 +313,6 @@
 			reg-shift = <2>;
 			interrupt-parent = <&plic>;
 			interrupts = <93>;
-			clock-frequency = <150000000>;
 			clocks = <&clkcfg CLK_MMUART3>;
 			status = "okay";
 		};
diff --git a/arch/riscv/include/asm/string.h b/arch/riscv/include/asm/string.h
index 0fc3424..7dee3e4 100644
--- a/arch/riscv/include/asm/string.h
+++ b/arch/riscv/include/asm/string.h
@@ -19,31 +19,25 @@
 
 #undef __HAVE_ARCH_STRRCHR
 #undef __HAVE_ARCH_STRCHR
-#undef __HAVE_ARCH_MEMCPY
-#undef __HAVE_ARCH_MEMMOVE
 #undef __HAVE_ARCH_MEMCHR
 #undef __HAVE_ARCH_MEMZERO
-#undef __HAVE_ARCH_MEMSET
 
-#ifdef CONFIG_MARCO_MEMSET
-#define memset(_p, _v, _n)	\
-	(typeof(_p) (p) = (_p); \
-	 typeof(_v) (v) = (_v); \
-	 typeof(_n) (n) = (_n); \
-	 {								\
-		if ((n) != 0) {						\
-			if (__builtin_constant_p((v)) && (v) == 0)	\
-				__memzero((p), (n));			\
-			else						\
-				memset((p), (v), (n));			\
-		}							\
-		(p);							\
-	})
-
-#define memzero(_p, _n) \
-	(typeof(_p) (p) = (_p); \
-	 typeof(_n) (n) = (_n); \
-	 { if ((n) != 0) __memzero((p), (n)); (p); })
+#undef __HAVE_ARCH_MEMCPY
+#if CONFIG_IS_ENABLED(USE_ARCH_MEMCPY)
+#define __HAVE_ARCH_MEMCPY
 #endif
+extern void *memcpy(void *, const void *, __kernel_size_t);
+
+#undef __HAVE_ARCH_MEMMOVE
+#if CONFIG_IS_ENABLED(USE_ARCH_MEMMOVE)
+#define __HAVE_ARCH_MEMMOVE
+#endif
+extern void *memmove(void *, const void *, __kernel_size_t);
+
+#undef __HAVE_ARCH_MEMZERO
+#if CONFIG_IS_ENABLED(USE_ARCH_MEMSET)
+#define __HAVE_ARCH_MEMSET
+#endif
+extern void *memset(void *, int, __kernel_size_t);
 
 #endif /* __ASM_RISCV_STRING_H */
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
index 12c14f2..ff0677a 100644
--- a/arch/riscv/lib/Makefile
+++ b/arch/riscv/lib/Makefile
@@ -36,3 +36,7 @@
 extra-$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE) += $(EFI_CRT0) $(EFI_RELOC)
 extra-$(CONFIG_CMD_BOOTEFI_SELFTEST) += $(EFI_CRT0) $(EFI_RELOC)
 extra-$(CONFIG_EFI) += $(EFI_CRT0) $(EFI_RELOC)
+
+obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMSET) += memset.o
+obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMMOVE) += memmove.o
+obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMCPY) += memcpy.o
diff --git a/arch/riscv/lib/memcpy.S b/arch/riscv/lib/memcpy.S
new file mode 100644
index 0000000..51ab716
--- /dev/null
+++ b/arch/riscv/lib/memcpy.S
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2013 Regents of the University of California
+ */
+
+#include <linux/linkage.h>
+#include <asm/asm.h>
+
+/* void *memcpy(void *, const void *, size_t) */
+ENTRY(__memcpy)
+WEAK(memcpy)
+	move t6, a0  /* Preserve return value */
+
+	/* Defer to byte-oriented copy for small sizes */
+	sltiu a3, a2, 128
+	bnez a3, 4f
+	/* Use word-oriented copy only if low-order bits match */
+	andi a3, t6, SZREG-1
+	andi a4, a1, SZREG-1
+	bne a3, a4, 4f
+
+	beqz a3, 2f  /* Skip if already aligned */
+	/*
+	 * Round to nearest double word-aligned address
+	 * greater than or equal to start address
+	 */
+	andi a3, a1, ~(SZREG-1)
+	addi a3, a3, SZREG
+	/* Handle initial misalignment */
+	sub a4, a3, a1
+1:
+	lb a5, 0(a1)
+	addi a1, a1, 1
+	sb a5, 0(t6)
+	addi t6, t6, 1
+	bltu a1, a3, 1b
+	sub a2, a2, a4  /* Update count */
+
+2:
+	andi a4, a2, ~((16*SZREG)-1)
+	beqz a4, 4f
+	add a3, a1, a4
+3:
+	REG_L a4,       0(a1)
+	REG_L a5,   SZREG(a1)
+	REG_L a6, 2*SZREG(a1)
+	REG_L a7, 3*SZREG(a1)
+	REG_L t0, 4*SZREG(a1)
+	REG_L t1, 5*SZREG(a1)
+	REG_L t2, 6*SZREG(a1)
+	REG_L t3, 7*SZREG(a1)
+	REG_L t4, 8*SZREG(a1)
+	REG_L t5, 9*SZREG(a1)
+	REG_S a4,       0(t6)
+	REG_S a5,   SZREG(t6)
+	REG_S a6, 2*SZREG(t6)
+	REG_S a7, 3*SZREG(t6)
+	REG_S t0, 4*SZREG(t6)
+	REG_S t1, 5*SZREG(t6)
+	REG_S t2, 6*SZREG(t6)
+	REG_S t3, 7*SZREG(t6)
+	REG_S t4, 8*SZREG(t6)
+	REG_S t5, 9*SZREG(t6)
+	REG_L a4, 10*SZREG(a1)
+	REG_L a5, 11*SZREG(a1)
+	REG_L a6, 12*SZREG(a1)
+	REG_L a7, 13*SZREG(a1)
+	REG_L t0, 14*SZREG(a1)
+	REG_L t1, 15*SZREG(a1)
+	addi a1, a1, 16*SZREG
+	REG_S a4, 10*SZREG(t6)
+	REG_S a5, 11*SZREG(t6)
+	REG_S a6, 12*SZREG(t6)
+	REG_S a7, 13*SZREG(t6)
+	REG_S t0, 14*SZREG(t6)
+	REG_S t1, 15*SZREG(t6)
+	addi t6, t6, 16*SZREG
+	bltu a1, a3, 3b
+	andi a2, a2, (16*SZREG)-1  /* Update count */
+
+4:
+	/* Handle trailing misalignment */
+	beqz a2, 6f
+	add a3, a1, a2
+
+	/* Use word-oriented copy if co-aligned to word boundary */
+	or a5, a1, t6
+	or a5, a5, a3
+	andi a5, a5, 3
+	bnez a5, 5f
+7:
+	lw a4, 0(a1)
+	addi a1, a1, 4
+	sw a4, 0(t6)
+	addi t6, t6, 4
+	bltu a1, a3, 7b
+
+	ret
+
+5:
+	lb a4, 0(a1)
+	addi a1, a1, 1
+	sb a4, 0(t6)
+	addi t6, t6, 1
+	bltu a1, a3, 5b
+6:
+	ret
+END(__memcpy)
diff --git a/arch/riscv/lib/memmove.S b/arch/riscv/lib/memmove.S
new file mode 100644
index 0000000..07d1d21
--- /dev/null
+++ b/arch/riscv/lib/memmove.S
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/linkage.h>
+#include <asm/asm.h>
+
+ENTRY(__memmove)
+WEAK(memmove)
+        move    t0, a0
+        move    t1, a1
+
+        beq     a0, a1, exit_memcpy
+        beqz    a2, exit_memcpy
+        srli    t2, a2, 0x2
+
+        slt     t3, a0, a1
+        beqz    t3, do_reverse
+
+        andi    a2, a2, 0x3
+        li      t4, 1
+        beqz    t2, byte_copy
+
+word_copy:
+        lw      t3, 0(a1)
+        addi    t2, t2, -1
+        addi    a1, a1, 4
+        sw      t3, 0(a0)
+        addi    a0, a0, 4
+        bnez    t2, word_copy
+        beqz    a2, exit_memcpy
+        j       byte_copy
+
+do_reverse:
+        add     a0, a0, a2
+        add     a1, a1, a2
+        andi    a2, a2, 0x3
+        li      t4, -1
+        beqz    t2, reverse_byte_copy
+
+reverse_word_copy:
+        addi    a1, a1, -4
+        addi    t2, t2, -1
+        lw      t3, 0(a1)
+        addi    a0, a0, -4
+        sw      t3, 0(a0)
+        bnez    t2, reverse_word_copy
+        beqz    a2, exit_memcpy
+
+reverse_byte_copy:
+        addi    a0, a0, -1
+        addi    a1, a1, -1
+
+byte_copy:
+        lb      t3, 0(a1)
+        addi    a2, a2, -1
+        sb      t3, 0(a0)
+        add     a1, a1, t4
+        add     a0, a0, t4
+        bnez    a2, byte_copy
+
+exit_memcpy:
+        move a0, t0
+        move a1, t1
+        ret
+END(__memmove)
diff --git a/arch/riscv/lib/memset.S b/arch/riscv/lib/memset.S
new file mode 100644
index 0000000..34c5360
--- /dev/null
+++ b/arch/riscv/lib/memset.S
@@ -0,0 +1,113 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2013 Regents of the University of California
+ */
+
+
+#include <linux/linkage.h>
+#include <asm/asm.h>
+
+/* void *memset(void *, int, size_t) */
+ENTRY(__memset)
+WEAK(memset)
+	move t0, a0  /* Preserve return value */
+
+	/* Defer to byte-oriented fill for small sizes */
+	sltiu a3, a2, 16
+	bnez a3, 4f
+
+	/*
+	 * Round to nearest XLEN-aligned address
+	 * greater than or equal to start address
+	 */
+	addi a3, t0, SZREG-1
+	andi a3, a3, ~(SZREG-1)
+	beq a3, t0, 2f  /* Skip if already aligned */
+	/* Handle initial misalignment */
+	sub a4, a3, t0
+1:
+	sb a1, 0(t0)
+	addi t0, t0, 1
+	bltu t0, a3, 1b
+	sub a2, a2, a4  /* Update count */
+
+2: /* Duff's device with 32 XLEN stores per iteration */
+	/* Broadcast value into all bytes */
+	andi a1, a1, 0xff
+	slli a3, a1, 8
+	or a1, a3, a1
+	slli a3, a1, 16
+	or a1, a3, a1
+#ifdef CONFIG_64BIT
+	slli a3, a1, 32
+	or a1, a3, a1
+#endif
+
+	/* Calculate end address */
+	andi a4, a2, ~(SZREG-1)
+	add a3, t0, a4
+
+	andi a4, a4, 31*SZREG  /* Calculate remainder */
+	beqz a4, 3f            /* Shortcut if no remainder */
+	neg a4, a4
+	addi a4, a4, 32*SZREG  /* Calculate initial offset */
+
+	/* Adjust start address with offset */
+	sub t0, t0, a4
+
+	/* Jump into loop body */
+	/* Assumes 32-bit instruction lengths */
+	la a5, 3f
+#ifdef CONFIG_64BIT
+	srli a4, a4, 1
+#endif
+	add a5, a5, a4
+	jr a5
+3:
+	REG_S a1,        0(t0)
+	REG_S a1,    SZREG(t0)
+	REG_S a1,  2*SZREG(t0)
+	REG_S a1,  3*SZREG(t0)
+	REG_S a1,  4*SZREG(t0)
+	REG_S a1,  5*SZREG(t0)
+	REG_S a1,  6*SZREG(t0)
+	REG_S a1,  7*SZREG(t0)
+	REG_S a1,  8*SZREG(t0)
+	REG_S a1,  9*SZREG(t0)
+	REG_S a1, 10*SZREG(t0)
+	REG_S a1, 11*SZREG(t0)
+	REG_S a1, 12*SZREG(t0)
+	REG_S a1, 13*SZREG(t0)
+	REG_S a1, 14*SZREG(t0)
+	REG_S a1, 15*SZREG(t0)
+	REG_S a1, 16*SZREG(t0)
+	REG_S a1, 17*SZREG(t0)
+	REG_S a1, 18*SZREG(t0)
+	REG_S a1, 19*SZREG(t0)
+	REG_S a1, 20*SZREG(t0)
+	REG_S a1, 21*SZREG(t0)
+	REG_S a1, 22*SZREG(t0)
+	REG_S a1, 23*SZREG(t0)
+	REG_S a1, 24*SZREG(t0)
+	REG_S a1, 25*SZREG(t0)
+	REG_S a1, 26*SZREG(t0)
+	REG_S a1, 27*SZREG(t0)
+	REG_S a1, 28*SZREG(t0)
+	REG_S a1, 29*SZREG(t0)
+	REG_S a1, 30*SZREG(t0)
+	REG_S a1, 31*SZREG(t0)
+	addi t0, t0, 32*SZREG
+	bltu t0, a3, 3b
+	andi a2, a2, SZREG-1  /* Update count */
+
+4:
+	/* Handle trailing misalignment */
+	beqz a2, 6f
+	add a3, t0, a2
+5:
+	sb a1, 0(t0)
+	addi t0, t0, 1
+	bltu t0, a3, 5b
+6:
+	ret
+END(__memset)
diff --git a/arch/riscv/lib/setjmp.S b/arch/riscv/lib/setjmp.S
index 72bc924..99d6195 100644
--- a/arch/riscv/lib/setjmp.S
+++ b/arch/riscv/lib/setjmp.S
@@ -54,12 +54,8 @@
 	LOAD_IDX(sp, 13)
 
 	/* Move the return value in place, but return 1 if passed 0. */
-	beq a1, zero, longjmp_1
-	mv a0, a1
-	ret
-
-	longjmp_1:
-	li a0, 1
+	seqz a0, a1
+	add a0, a0, a1
 	ret
 ENDPROC(longjmp)
 .popsection
diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c
index edd48e2..48636ab 100644
--- a/arch/sandbox/cpu/cpu.c
+++ b/arch/sandbox/cpu/cpu.c
@@ -6,7 +6,6 @@
 #include <common.h>
 #include <bootstage.h>
 #include <cpu_func.h>
-#include <dm.h>
 #include <errno.h>
 #include <log.h>
 #include <asm/global_data.h>
@@ -17,7 +16,6 @@
 #include <asm/malloc.h>
 #include <asm/setjmp.h>
 #include <asm/state.h>
-#include <dm/root.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -34,10 +32,8 @@
 {
 	/* Do this here while it still has an effect */
 	os_fd_restore();
-	if (state_uninit())
-		os_exit(2);
 
-	if (dm_uninit())
+	if (state_uninit())
 		os_exit(2);
 
 	/* This is considered normal termination for now */
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 3d8af0a..b9ad341 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -153,7 +153,7 @@
 		printf("Cannot seek to start of file '%s'\n", fname);
 		goto err;
 	}
-	*bufp = malloc(size);
+	*bufp = os_malloc(size);
 	if (!*bufp) {
 		printf("Not enough memory to read file '%s'\n", fname);
 		ret = -ENOMEM;
@@ -267,11 +267,18 @@
 	signal(SIGINT, os_sigint_handler);
 }
 
+/*
+ * Provide our own malloc so we don't use space in the sandbox ram_buf for
+ * allocations that are internal to sandbox, or need to be done before U-Boot's
+ * malloc() is ready.
+ */
 void *os_malloc(size_t length)
 {
 	int page_size = getpagesize();
 	struct os_mem_hdr *hdr;
 
+	if (!length)
+		return NULL;
 	/*
 	 * Use an address that is hopefully available to us so that pointers
 	 * to this memory are fairly obvious. If we end up with a different
@@ -298,6 +305,47 @@
 	}
 }
 
+/* These macros are from kernel.h but not accessible in this file */
+#define ALIGN(x, a)		__ALIGN_MASK((x), (typeof(x))(a) - 1)
+#define __ALIGN_MASK(x, mask)	(((x) + (mask)) & ~(mask))
+
+/*
+ * Provide our own malloc so we don't use space in the sandbox ram_buf for
+ * allocations that are internal to sandbox, or need to be done before U-Boot's
+ * malloc() is ready.
+ */
+void *os_realloc(void *ptr, size_t length)
+{
+	int page_size = getpagesize();
+	struct os_mem_hdr *hdr;
+	void *new_ptr;
+
+	/* Reallocating a NULL pointer is just an alloc */
+	if (!ptr)
+		return os_malloc(length);
+
+	/* Changing a length to 0 is just a free */
+	if (length) {
+		os_free(ptr);
+		return NULL;
+	}
+
+	/*
+	 * If the new size is the same number of pages as the old, nothing to
+	 * do. There isn't much point in shrinking things
+	 */
+	hdr = ptr - page_size;
+	if (ALIGN(length, page_size) <= ALIGN(hdr->length, page_size))
+		return ptr;
+
+	/* We have to grow it, so allocate something new */
+	new_ptr = os_malloc(length);
+	memcpy(new_ptr, ptr, hdr->length);
+	os_free(ptr);
+
+	return new_ptr;
+}
+
 void os_usleep(unsigned long usec)
 {
 	usleep(usec);
@@ -343,8 +391,8 @@
 	state->argv = argv;
 
 	/* dynamically construct the arguments to the system getopt_long */
-	short_opts = malloc(sizeof(*short_opts) * num_options * 2 + 1);
-	long_opts = malloc(sizeof(*long_opts) * (num_options + 1));
+	short_opts = os_malloc(sizeof(*short_opts) * num_options * 2 + 1);
+	long_opts = os_malloc(sizeof(*long_opts) * (num_options + 1));
 	if (!short_opts || !long_opts)
 		return 1;
 
@@ -423,7 +471,7 @@
 
 	while (node) {
 		next = node->next;
-		free(node);
+		os_free(node);
 		node = next;
 	}
 }
@@ -448,7 +496,7 @@
 	/* Create a buffer upfront, with typically sufficient size */
 	dirlen = strlen(dirname) + 2;
 	len = dirlen + 256;
-	fname = malloc(len);
+	fname = os_malloc(len);
 	if (!fname) {
 		ret = -ENOMEM;
 		goto done;
@@ -461,7 +509,7 @@
 			ret = errno;
 			break;
 		}
-		next = malloc(sizeof(*node) + strlen(entry->d_name) + 1);
+		next = os_malloc(sizeof(*node) + strlen(entry->d_name) + 1);
 		if (!next) {
 			os_dirent_free(head);
 			ret = -ENOMEM;
@@ -470,10 +518,10 @@
 		if (dirlen + strlen(entry->d_name) > len) {
 			len = dirlen + strlen(entry->d_name);
 			old_fname = fname;
-			fname = realloc(fname, len);
+			fname = os_realloc(fname, len);
 			if (!fname) {
-				free(old_fname);
-				free(next);
+				os_free(old_fname);
+				os_free(next);
 				os_dirent_free(head);
 				ret = -ENOMEM;
 				goto done;
@@ -507,7 +555,7 @@
 
 done:
 	closedir(dir);
-	free(fname);
+	os_free(fname);
 	return ret;
 }
 
@@ -624,7 +672,7 @@
 	for (argc = 0; (*argvp)[argc]; argc++)
 		;
 
-	argv = malloc((argc + count + 1) * sizeof(char *));
+	argv = os_malloc((argc + count + 1) * sizeof(char *));
 	if (!argv) {
 		printf("Out of memory for %d argv\n", count);
 		return -ENOMEM;
@@ -663,7 +711,7 @@
  * @fname: Filename to exec
  * @return does not return on success, any return value is an error
  */
-static int os_jump_to_file(const char *fname)
+static int os_jump_to_file(const char *fname, bool delete_it)
 {
 	struct sandbox_state *state = state_get_current();
 	char mem_fname[30];
@@ -686,11 +734,13 @@
 
 	os_fd_restore();
 
-	extra_args[0] = "-j";
-	extra_args[1] = (char *)fname;
-	extra_args[2] = "-m";
-	extra_args[3] = mem_fname;
-	argc = 4;
+	argc = 0;
+	if (delete_it) {
+		extra_args[argc++] = "-j";
+		extra_args[argc++] = (char *)fname;
+	}
+	extra_args[argc++] = "-m";
+	extra_args[argc++] = mem_fname;
 	if (state->ram_buf_rm)
 		extra_args[argc++] = "--rm_memory";
 	err = add_args(&argv, extra_args, argc);
@@ -707,14 +757,17 @@
 		os_exit(2);
 
 	err = execv(fname, argv);
-	free(argv);
+	os_free(argv);
 	if (err) {
 		perror("Unable to run image");
 		printf("Image filename '%s'\n", fname);
 		return err;
 	}
 
-	return unlink(fname);
+	if (delete_it)
+		return unlink(fname);
+
+	return -EFAULT;
 }
 
 int os_jump_to_image(const void *dest, int size)
@@ -726,10 +779,10 @@
 	if (err)
 		return err;
 
-	return os_jump_to_file(fname);
+	return os_jump_to_file(fname, true);
 }
 
-int os_find_u_boot(char *fname, int maxlen)
+int os_find_u_boot(char *fname, int maxlen, bool use_img)
 {
 	struct sandbox_state *state = state_get_current();
 	const char *progname = state->argv[0];
@@ -753,8 +806,8 @@
 			return 0;
 		}
 
-		/* Look for 'u-boot-tpl' in the tpl/ directory */
-		p = strstr(fname, "/tpl/");
+		/* Look for 'u-boot-spl' in the spl/ directory */
+		p = strstr(fname, "/spl/");
 		if (p) {
 			p[1] = 's';
 			fd = os_open(fname, O_RDONLY);
@@ -781,6 +834,8 @@
 	if (p) {
 		/* Remove the "spl" characters */
 		memmove(p, p + 4, strlen(p + 4) + 1);
+		if (use_img)
+			strcat(p, ".img");
 		fd = os_open(fname, O_RDONLY);
 		if (fd >= 0) {
 			close(fd);
@@ -795,10 +850,10 @@
 {
 	struct sandbox_state *state = state_get_current();
 
-	printf("%s\n", __func__);
 	/* U-Boot will delete ram buffer after read: "--rm_memory"*/
 	state->ram_buf_rm = true;
-	return os_jump_to_file(fname);
+
+	return os_jump_to_file(fname, false);
 }
 
 long os_get_time_offset(void)
diff --git a/arch/sandbox/cpu/sdl.c b/arch/sandbox/cpu/sdl.c
index d4dab36..8102649 100644
--- a/arch/sandbox/cpu/sdl.c
+++ b/arch/sandbox/cpu/sdl.c
@@ -69,14 +69,14 @@
 	 * We don't want to include common.h in this file since it uses
 	 * system headers. So add a declation here.
 	 */
-	extern void reset_cpu(unsigned long addr);
+	extern void reset_cpu(void);
 	SDL_Event event;
 
 	while (SDL_PollEvent(&event)) {
 		switch (event.type) {
 		case SDL_QUIT:
 			puts("LCD window closed - quitting\n");
-			reset_cpu(1);
+			reset_cpu();
 			break;
 		}
 	}
diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c
index e7b4b50..f82b0d3 100644
--- a/arch/sandbox/cpu/spl.c
+++ b/arch/sandbox/cpu/spl.c
@@ -13,7 +13,7 @@
 #include <asm/global_data.h>
 #include <asm/spl.h>
 #include <asm/state.h>
-#include <test/test.h>
+#include <test/ut.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -37,16 +37,20 @@
 	char fname[256];
 	int ret;
 
-	ret = os_find_u_boot(fname, sizeof(fname));
+	ret = os_find_u_boot(fname, sizeof(fname), false);
 	if (ret) {
 		printf("(%s not found, error %d)\n", fname, ret);
 		return ret;
 	}
 
-	/* Set up spl_image to boot from jump_to_image_no_args() */
-	spl_image->arg = strdup(fname);
+	/*
+	 * Set up spl_image to boot from jump_to_image_no_args(). Allocate this
+	 * outsdide the RAM buffer (i.e. don't use strdup()).
+	 */
+	spl_image->arg = os_malloc(strlen(fname) + 1);
 	if (!spl_image->arg)
-		return log_msg_ret("Setup exec filename", -ENOMEM);
+		return log_msg_ret("exec", -ENOMEM);
+	strcpy(spl_image->arg, fname);
 
 	return 0;
 }
@@ -59,9 +63,12 @@
 	preloader_console_init();
 
 	if (state->run_unittests) {
+		struct unit_test *tests = UNIT_TEST_ALL_START();
+		const int count = UNIT_TEST_ALL_COUNT();
 		int ret;
 
-		ret = dm_test_main(state->select_unittests);
+		ret = ut_run_list("spl", NULL, tests, count,
+				  state->select_unittests);
 		/* continue execution into U-Boot */
 	}
 }
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 483a264..e87365e 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -88,7 +88,7 @@
 
 	/* Sort the options */
 	size = sizeof(*sorted_opt) * num_options;
-	sorted_opt = malloc(size);
+	sorted_opt = os_malloc(size);
 	if (!sorted_opt) {
 		printf("No memory to sort options\n");
 		os_exit(1);
@@ -188,7 +188,7 @@
 	int len;
 
 	len = strlen(state->argv[0]) + strlen(fmt) + 1;
-	fname = malloc(len);
+	fname = os_malloc(len);
 	if (!fname)
 		return -ENOMEM;
 	snprintf(fname, len, fmt, state->argv[0]);
@@ -208,7 +208,7 @@
 	int len;
 
 	len = strlen(state->argv[0]) + strlen(fmt) + 1;
-	fname = malloc(len);
+	fname = os_malloc(len);
 	if (!fname)
 		return -ENOMEM;
 	strcpy(fname, state->argv[0]);
@@ -436,16 +436,18 @@
 {
 	struct sandbox_state *state;
 	gd_t data;
+	int size;
 	int ret;
 
 	/*
 	 * Copy argv[] so that we can pass the arguments in the original
 	 * sequence when resetting the sandbox.
 	 */
-	os_argv = calloc(argc + 1, sizeof(char *));
+	size = sizeof(char *) * (argc + 1);
+	os_argv = os_malloc(size);
 	if (!os_argv)
 		os_exit(1);
-	memcpy(os_argv, argv, sizeof(char *) * (argc + 1));
+	memcpy(os_argv, argv, size);
 
 	memset(&data, '\0', sizeof(data));
 	gd = &data;
@@ -489,7 +491,6 @@
 	gd->reloc_off = (ulong)gd->arch.text_base;
 
 	/* sandbox test: log functions called before log_init in board_init_f */
-	log_info("sandbox: starting...\n");
 	log_debug("debug: %s\n", __func__);
 
 	/* Do pre- and post-relocation init */
diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c
index b2901b7..f63cfd3 100644
--- a/arch/sandbox/cpu/state.c
+++ b/arch/sandbox/cpu/state.c
@@ -4,6 +4,7 @@
  */
 
 #include <common.h>
+#include <bloblist.h>
 #include <errno.h>
 #include <fdtdec.h>
 #include <log.h>
@@ -29,17 +30,17 @@
 		return 0;
 
 	size = used + extra_size;
-	buf = malloc(size);
+	buf = os_malloc(size);
 	if (!buf)
 		return -ENOMEM;
 
 	ret = fdt_open_into(blob, buf, size);
 	if (ret) {
-		free(buf);
+		os_free(buf);
 		return -EIO;
 	}
 
-	free(blob);
+	os_free(blob);
 	state->state_fdt = buf;
 	return 0;
 }
@@ -55,7 +56,7 @@
 		printf("Cannot find sandbox state file '%s'\n", fname);
 		return -ENOENT;
 	}
-	state->state_fdt = malloc(size);
+	state->state_fdt = os_malloc(size);
 	if (!state->state_fdt) {
 		puts("No memory to read sandbox state\n");
 		return -ENOMEM;
@@ -77,7 +78,7 @@
 err_read:
 	os_close(fd);
 err_open:
-	free(state->state_fdt);
+	os_free(state->state_fdt);
 	state->state_fdt = NULL;
 
 	return ret;
@@ -244,7 +245,7 @@
 	/* Create a state FDT if we don't have one */
 	if (!state->state_fdt) {
 		size = 0x4000;
-		state->state_fdt = malloc(size);
+		state->state_fdt = os_malloc(size);
 		if (!state->state_fdt) {
 			puts("No memory to create FDT\n");
 			return -ENOMEM;
@@ -302,7 +303,7 @@
 err_write:
 	os_close(fd);
 err_create:
-	free(state->state_fdt);
+	os_free(state->state_fdt);
 
 	return ret;
 }
@@ -398,8 +399,12 @@
 {
 	int err;
 
+	log_info("Writing sandbox state\n");
 	state = &main_state;
 
+	/* Finish the bloblist, so that it is correct before writing memory */
+	bloblist_finish();
+
 	if (state->write_ram_buf) {
 		err = os_write_ram_buf(state->ram_buf_fname);
 		if (err) {
@@ -419,8 +424,8 @@
 	if (state->jumped_fname)
 		os_unlink(state->jumped_fname);
 
-	if (state->state_fdt)
-		free(state->state_fdt);
+	os_free(state->state_fdt);
+	os_free(state->ram_buf);
 	memset(state, '\0', sizeof(*state));
 
 	return 0;
diff --git a/arch/sandbox/cpu/u-boot-spl.lds b/arch/sandbox/cpu/u-boot-spl.lds
index 649abeb..1816043 100644
--- a/arch/sandbox/cpu/u-boot-spl.lds
+++ b/arch/sandbox/cpu/u-boot-spl.lds
@@ -13,6 +13,14 @@
 		KEEP(*(SORT(.u_boot_list*)));
 	}
 
+	/* Private data for devices with OF_PLATDATA_RT */
+	. = ALIGN(4);
+	.priv_data : {
+		__priv_data_start = .;
+		*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.priv_data*)))
+		__priv_data_end = .;
+	}
+
 	__u_boot_sandbox_option_start = .;
 	_u_boot_sandbox_getopt : { KEEP(*(.u_boot_sandbox_getopt)) }
 	__u_boot_sandbox_option_end = .;
diff --git a/arch/sandbox/cpu/u-boot.lds b/arch/sandbox/cpu/u-boot.lds
index 936da5e..a1f509c 100644
--- a/arch/sandbox/cpu/u-boot.lds
+++ b/arch/sandbox/cpu/u-boot.lds
@@ -44,6 +44,13 @@
 	{
 		*(.__efi_runtime_rel_stop)
 	}
+
+	.dynsym :
+	{
+		__dyn_sym_start = .;
+		*(.dynsym)
+		__dyn_sym_end = .;
+	}
 }
 
 INSERT BEFORE .data;
diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index dc933f3..31db50d 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -31,7 +31,7 @@
 
 	clk_fixed: clk-fixed {
 		u-boot,dm-pre-reloc;
-		compatible = "fixed-clock";
+		compatible = "sandbox,fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <1234>;
 	};
@@ -101,15 +101,19 @@
 		};
 
 		i2c_emul: emul {
+			u-boot,dm-pre-reloc;
 			reg = <0xff>;
 			compatible = "sandbox,i2c-emul-parent";
 			emul_eeprom: emul-eeprom {
 				compatible = "sandbox,i2c-eeprom";
 				sandbox,filename = "i2c.bin";
 				sandbox,size = <256>;
+				#emul-cells = <0>;
 			};
 			emul0: emul0 {
-				compatible = "sandbox,i2c-rtc";
+				u-boot,dm-pre-reloc;
+				compatible = "sandbox,i2c-rtc-emul";
+				#emul-cells = <0>;
 			};
 		};
 	};
@@ -196,6 +200,10 @@
 		compatible = "sandbox,reset";
 	};
 
+	rng {
+		compatible = "sandbox,sandbox-rng";
+	};
+
 	sound {
 		compatible = "sandbox,sound";
 		cpu {
@@ -260,14 +268,10 @@
 		stringarray = "pre-proper";
 	};
 
-	test-bus {
-		compatible = "simple-bus";
+	spl-test7 {
 		u-boot,dm-spl;
-		spl-test7 {
-			u-boot,dm-spl;
-			compatible = "sandbox,spl-test";
-			stringarray = "spl";
-		};
+		compatible = "sandbox,spl-test";
+		stringarray = "spl";
 	};
 
 	square {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 2600360..899e75f 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -604,10 +604,10 @@
 				sandbox,size = <256>;
 			};
 			emul0: emul0 {
-				compatible = "sandbox,i2c-rtc";
+				compatible = "sandbox,i2c-rtc-emul";
 			};
 			emul1: emull {
-				compatible = "sandbox,i2c-rtc";
+				compatible = "sandbox,i2c-rtc-emul";
 			};
 		};
 
@@ -1402,3 +1402,4 @@
 };
 
 #include "sandbox_pmic.dtsi"
+#include "cros-ec-keyboard.dtsi"
diff --git a/arch/sandbox/include/asm/clk.h b/arch/sandbox/include/asm/clk.h
index 68a8687..df7156f 100644
--- a/arch/sandbox/include/asm/clk.h
+++ b/arch/sandbox/include/asm/clk.h
@@ -7,6 +7,9 @@
 #define __SANDBOX_CLK_H
 
 #include <common.h>
+#include <clk.h>
+#include <dt-structs.h>
+#include <linux/clk-provider.h>
 
 struct udevice;
 
@@ -45,6 +48,27 @@
 
 #define SANDBOX_CLK_TEST_NON_DEVM_COUNT SANDBOX_CLK_TEST_ID_DEVM1
 
+struct sandbox_clk_priv {
+	bool probed;
+	ulong rate[SANDBOX_CLK_ID_COUNT];
+	bool enabled[SANDBOX_CLK_ID_COUNT];
+	bool requested[SANDBOX_CLK_ID_COUNT];
+};
+
+struct sandbox_clk_test {
+	struct clk clks[SANDBOX_CLK_TEST_NON_DEVM_COUNT];
+	struct clk *clkps[SANDBOX_CLK_TEST_ID_COUNT];
+	struct clk_bulk bulk;
+};
+
+/* Platform data for the sandbox fixed-rate clock driver */
+struct sandbox_clk_fixed_rate_plat {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_sandbox_fixed_clock dtplat;
+#endif
+	struct clk_fixed_rate fixed;
+};
+
 /**
  * sandbox_clk_query_rate - Query the current rate of a sandbox clock.
  *
diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h
index df4ba4f..9e10052 100644
--- a/arch/sandbox/include/asm/gpio.h
+++ b/arch/sandbox/include/asm/gpio.h
@@ -23,6 +23,15 @@
  */
 #include <asm-generic/gpio.h>
 
+/* Our own private GPIO flags, which musn't conflict with GPIOD_... */
+#define GPIOD_EXT_HIGH		BIT(31)	/* external source is high (else low) */
+#define GPIOD_EXT_DRIVEN	BIT(30)	/* external source is driven */
+#define GPIOD_EXT_PULL_UP	BIT(29)	/* GPIO has external pull-up */
+#define GPIOD_EXT_PULL_DOWN	BIT(28)	/* GPIO has external pull-down */
+
+#define GPIOD_EXT_PULL		(BIT(28) | BIT(29))
+#define GPIOD_SANDBOX_MASK	GENMASK(31, 28)
+
 /**
  * Return the simulated value of a GPIO (used only in sandbox test code)
  *
@@ -69,17 +78,17 @@
  * @param offset	GPIO offset within bank
  * @return dir_flags: bitfield accesses by GPIOD_ defines
  */
-ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset);
+ulong sandbox_gpio_get_flags(struct udevice *dev, unsigned int offset);
 
 /**
  * Set the simulated flags of a GPIO (used only in sandbox test code)
  *
  * @param dev		device to use
  * @param offset	GPIO offset within bank
- * @param flags		dir_flags: bitfield accesses by GPIOD_ defines
+ * @param flags		bitfield accesses by GPIOD_ defines
  * @return -1 on error, 0 if ok
  */
-int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-			       ulong flags);
+int sandbox_gpio_set_flags(struct udevice *dev, unsigned int offset,
+			   ulong flags);
 
 #endif
diff --git a/arch/sandbox/include/asm/i2c.h b/arch/sandbox/include/asm/i2c.h
index b482be4..4fc190b 100644
--- a/arch/sandbox/include/asm/i2c.h
+++ b/arch/sandbox/include/asm/i2c.h
@@ -11,4 +11,19 @@
 	bool test_mode;
 };
 
+/**
+ * struct i2c_emul_uc_plat - information about the emulator for this device
+ *
+ * This is used by devices in UCLASS_I2C_EMUL to record information about the
+ * device being emulated. It is accessible with dev_get_uclass_plat()
+ *
+ * @dev: Device being emulated
+ * @idx: of-platdata index, set up by the device's bind() method if of-platdata
+ *	is in use
+ */
+struct i2c_emul_uc_plat {
+	struct udevice *dev;
+	int idx;
+};
+
 #endif /* __asn_i2c_h */
diff --git a/arch/sandbox/include/asm/rtc.h b/arch/sandbox/include/asm/rtc.h
index 5bb032f..025cd6c 100644
--- a/arch/sandbox/include/asm/rtc.h
+++ b/arch/sandbox/include/asm/rtc.h
@@ -9,6 +9,8 @@
 #ifndef __asm_rtc_h
 #define __asm_rtc_h
 
+#include <dt-structs.h>
+
 /* Register numbers in the sandbox RTC */
 enum {
 	REG_SEC		= 5,
@@ -29,4 +31,26 @@
 	REG_COUNT	= 0x80,
 };
 
+/**
+ * struct sandbox_i2c_rtc_plat_data - platform data for the RTC
+ *
+ * @base_time:		Base system time when RTC device was bound
+ * @offset:		RTC offset from current system time
+ * @use_system_time:	true to use system time, false to use @base_time
+ * @reg:		Register values
+ */
+struct sandbox_i2c_rtc_plat_data {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_sandbox_i2c_rtc_emul dtplat;
+#endif
+	long base_time;
+	long offset;
+	bool use_system_time;
+	u8 reg[REG_COUNT];
+};
+
+struct sandbox_i2c_rtc {
+	unsigned int offset_secs;
+};
+
 #endif
diff --git a/arch/sh/cpu/sh4/cpu.c b/arch/sh/cpu/sh4/cpu.c
index 801102f..1b2f50d 100644
--- a/arch/sh/cpu/sh4/cpu.c
+++ b/arch/sh/cpu/sh4/cpu.c
@@ -32,7 +32,7 @@
 int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
 	disable_interrupts();
-	reset_cpu(0);
+	reset_cpu();
 	return 0;
 }
 
diff --git a/arch/sh/cpu/sh4/watchdog.c b/arch/sh/cpu/sh4/watchdog.c
index 1de32cd..bf403d3 100644
--- a/arch/sh/cpu/sh4/watchdog.c
+++ b/arch/sh/cpu/sh4/watchdog.c
@@ -51,7 +51,7 @@
 }
 #endif
 
-void reset_cpu(unsigned long ignored)
+void reset_cpu(void)
 {
 	/* Address error with SR.BL=1 first. */
 	trigger_address_error();
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 5b089af..970bdff 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1047,4 +1047,25 @@
 
 endif # INTEL_SOC
 
+config COREBOOT_SYSINFO
+	bool "Support reading coreboot sysinfo"
+	default y if SYS_COREBOOT
+	help
+	  Select this option to read the coreboot sysinfo table on start-up,
+	  if present. This is written by coreboot before it exits and provides
+	  various pieces of information about the running system, including
+	  display, memory and build information. It is stored in
+	  struct sysinfo_t after parsing by get_coreboot_info().
+
+config SPL_COREBOOT_SYSINFO
+	bool "Support reading coreboot sysinfo"
+	depends on SPL
+	default y if COREBOOT_SYSINFO
+	help
+	  Select this option to read the coreboot sysinfo table in SPL,
+	  if present. This is written by coreboot before it exits and provides
+	  various pieces of information about the running system, including
+	  display, memory and build information. It is stored in
+	  struct sysinfo_t after parsing by get_coreboot_info().
+
 endmenu
diff --git a/arch/x86/cpu/apollolake/Kconfig b/arch/x86/cpu/apollolake/Kconfig
index 590fe31..b3ce053 100644
--- a/arch/x86/cpu/apollolake/Kconfig
+++ b/arch/x86/cpu/apollolake/Kconfig
@@ -21,6 +21,8 @@
 	select INTEL_GMA_SWSMISCI
 	select ACPI_GNVS_EXTERNAL
 	select TPL_OF_PLATDATA_PARENT
+	select TPL_OF_PLATDATA_INST
+	select TPL_READ_ONLY
 	imply ENABLE_MRC_CACHE
 	imply AHCI_PCI
 	imply SCSI
diff --git a/arch/x86/cpu/apollolake/cpu.c b/arch/x86/cpu/apollolake/cpu.c
index fbc016d..647c9df 100644
--- a/arch/x86/cpu/apollolake/cpu.c
+++ b/arch/x86/cpu/apollolake/cpu.c
@@ -19,6 +19,7 @@
 #include <asm/arch/iomap.h>
 #include <dm/acpi.h>
 
+#ifdef CONFIG_ACPIGEN
 #define CSTATE_RES(address_space, width, offset, address)		\
 	{								\
 	.space_id = address_space,					\
@@ -57,11 +58,6 @@
 	},
 };
 
-static int apl_get_info(const struct udevice *dev, struct cpu_info *info)
-{
-	return cpu_intel_get_info(info, INTEL_BCLK_MHZ);
-}
-
 static int acpi_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx)
 {
 	uint core_id = dev_seq(dev);
@@ -89,6 +85,12 @@
 
 	return 0;
 }
+#endif /* CONFIG_ACPIGEN */
+
+static int apl_get_info(const struct udevice *dev, struct cpu_info *info)
+{
+	return cpu_intel_get_info(info, INTEL_BCLK_MHZ);
+}
 
 static void update_fixed_mtrrs(void)
 {
@@ -170,9 +172,11 @@
 	return 0;
 }
 
+#ifdef CONFIG_ACPIGEN
 struct acpi_ops apl_cpu_acpi_ops = {
 	.fill_ssdt	= acpi_cpu_fill_ssdt,
 };
+#endif
 
 static const struct cpu_ops cpu_x86_apl_ops = {
 	.get_desc	= cpu_x86_get_desc,
diff --git a/arch/x86/cpu/apollolake/cpu_common.c b/arch/x86/cpu/apollolake/cpu_common.c
index 63f6999..5d7d26b 100644
--- a/arch/x86/cpu/apollolake/cpu_common.c
+++ b/arch/x86/cpu/apollolake/cpu_common.c
@@ -7,11 +7,17 @@
 #include <dm.h>
 #include <log.h>
 #include <asm/cpu_common.h>
+#include <asm/io.h>
 #include <asm/msr.h>
+#include <asm/pci.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/iomap.h>
+#include <asm/arch/uart.h>
 #include <power/acpi_pmc.h>
 
+/* Define this here to avoid referencing any drivers for the debug UART 1 */
+#define PCH_DEV_P2SB	PCI_BDF(0, 0x0d, 0)
+
 void cpu_flush_l1d_to_l2(void)
 {
 	struct msr_t msr;
@@ -40,3 +46,57 @@
 	debug("PM timer %x %x\n", msr.hi, msr.lo);
 	msr_write(MSR_EMULATE_PM_TIMER, msr);
 }
+
+static void pch_uart_init(void)
+{
+	/*
+	 * Set up the pinmux so that the UART rx/tx signals are connected
+	 * outside the SoC.
+	 *
+	 * There are about 500 lines of code required to program the GPIO
+	 * configuration for the UARTs. But it boils down to four writes, and
+	 * for the debug UART we want the minimum possible amount of code before
+	 * the UART is running. So just add the magic writes here. See
+	 * apl_hostbridge_early_init_pinctrl() for the full horror.
+	 */
+	if (PCI_FUNC(PCH_DEV_UART) == 1) {
+		writel(0x40000402, 0xd0c50650);
+		writel(0x3c47, 0xd0c50654);
+		writel(0x40000400, 0xd0c50658);
+		writel(0x3c48, 0xd0c5065c);
+	} else { /* UART2 */
+		writel(0x40000402, 0xd0c50670);
+		writel(0x3c4b, 0xd0c50674);
+		writel(0x40000400, 0xd0c50678);
+		writel(0x3c4c, 0xd0c5067c);
+	}
+
+#ifdef CONFIG_DEBUG_UART
+	apl_uart_init(PCH_DEV_UART, CONFIG_DEBUG_UART_BASE);
+#endif
+}
+
+static void p2sb_enable_bar(ulong bar)
+{
+	/* Enable PCR Base address in PCH */
+	pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_0, bar,
+			     PCI_SIZE_32);
+	pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
+
+	/* Enable P2SB MSE */
+	pci_x86_write_config(PCH_DEV_P2SB, PCI_COMMAND,
+			     PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY,
+			     PCI_SIZE_8);
+}
+
+/*
+ * board_debug_uart_init() - Init the debug UART ready for use
+ *
+ * This is the minimum init needed to get the UART running. It avoids any
+ * drivers or complex code, so that the UART is running as soon as possible.
+ */
+void board_debug_uart_init(void)
+{
+	p2sb_enable_bar(IOMAP_P2SB_BAR);
+	pch_uart_init();
+}
diff --git a/arch/x86/cpu/apollolake/cpu_spl.c b/arch/x86/cpu/apollolake/cpu_spl.c
index 9a18476..8f48457 100644
--- a/arch/x86/cpu/apollolake/cpu_spl.c
+++ b/arch/x86/cpu/apollolake/cpu_spl.c
@@ -31,68 +31,10 @@
 #include <asm/arch/lpc.h>
 #include <asm/arch/pch.h>
 #include <asm/arch/systemagent.h>
-#include <asm/arch/uart.h>
 #include <asm/fsp2/fsp_api.h>
 #include <linux/sizes.h>
 #include <power/acpi_pmc.h>
 
-/* Define this here to avoid referencing any drivers for the debug UART 1 */
-#define PCH_DEV_P2SB	PCI_BDF(0, 0x0d, 0)
-
-static void pch_uart_init(void)
-{
-	/*
-	 * Set up the pinmux so that the UART rx/tx signals are connected
-	 * outside the SoC.
-	 *
-	 * There are about 500 lines of code required to program the GPIO
-	 * configuration for the UARTs. But it boils down to four writes, and
-	 * for the debug UART we want the minimum possible amount of code before
-	 * the UART is running. So just add the magic writes here. See
-	 * apl_hostbridge_early_init_pinctrl() for the full horror.
-	 */
-	if (PCI_FUNC(PCH_DEV_UART) == 1) {
-		writel(0x40000402, 0xd0c50650);
-		writel(0x3c47, 0xd0c50654);
-		writel(0x40000400, 0xd0c50658);
-		writel(0x3c48, 0xd0c5065c);
-	} else { /* UART2 */
-		writel(0x40000402, 0xd0c50670);
-		writel(0x3c4b, 0xd0c50674);
-		writel(0x40000400, 0xd0c50678);
-		writel(0x3c4c, 0xd0c5067c);
-	}
-
-#ifdef CONFIG_DEBUG_UART
-	apl_uart_init(PCH_DEV_UART, CONFIG_DEBUG_UART_BASE);
-#endif
-}
-
-static void p2sb_enable_bar(ulong bar)
-{
-	/* Enable PCR Base address in PCH */
-	pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_0, bar,
-			     PCI_SIZE_32);
-	pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
-
-	/* Enable P2SB MSE */
-	pci_x86_write_config(PCH_DEV_P2SB, PCI_COMMAND,
-			     PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY,
-			     PCI_SIZE_8);
-}
-
-/*
- * board_debug_uart_init() - Init the debug UART ready for use
- *
- * This is the minimum init needed to get the UART running. It avoids any
- * drivers or complex code, so that the UART is running as soon as possible.
- */
-void board_debug_uart_init(void)
-{
-	p2sb_enable_bar(IOMAP_P2SB_BAR);
-	pch_uart_init();
-}
-
 static int fast_spi_cache_bios_region(void)
 {
 	uint map_size, offset;
diff --git a/arch/x86/cpu/apollolake/pmc.c b/arch/x86/cpu/apollolake/pmc.c
index e23d38e..1d21187 100644
--- a/arch/x86/cpu/apollolake/pmc.c
+++ b/arch/x86/cpu/apollolake/pmc.c
@@ -9,8 +9,8 @@
 #define LOG_CATEGORY UCLASS_ACPI_PMC
 
 #include <common.h>
-#include <dt-structs.h>
 #include <dm.h>
+#include <dt-structs.h>
 #include <log.h>
 #include <spl.h>
 #include <acpi/acpi_s3.h>
diff --git a/arch/x86/cpu/apollolake/punit.c b/arch/x86/cpu/apollolake/punit.c
index e67c011..5ed7963 100644
--- a/arch/x86/cpu/apollolake/punit.c
+++ b/arch/x86/cpu/apollolake/punit.c
@@ -93,4 +93,5 @@
 	.id		= UCLASS_SYSCON,
 	.of_match	= apl_syscon_ids,
 	.probe		= apl_punit_probe,
+	DM_HEADER(<asm/cpu.h>)    /* for X86_SYSCON_PUNIT */
 };
diff --git a/arch/x86/cpu/coreboot/Makefile b/arch/x86/cpu/coreboot/Makefile
index 605f903..a6cdb9a 100644
--- a/arch/x86/cpu/coreboot/Makefile
+++ b/arch/x86/cpu/coreboot/Makefile
@@ -20,5 +20,4 @@
 obj-y += sdram.o
 endif
 obj-y += coreboot.o
-obj-y += tables.o
 obj-y += timestamp.o
diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c
index 15c3ad8..69cf8f4 100644
--- a/arch/x86/cpu/coreboot/coreboot.c
+++ b/arch/x86/cpu/coreboot/coreboot.c
@@ -14,7 +14,7 @@
 #include <asm/io.h>
 #include <asm/msr.h>
 #include <asm/mtrr.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
 #include <asm/arch/timestamp.h>
 
 DECLARE_GLOBAL_DATA_PTR;
diff --git a/arch/x86/cpu/coreboot/sdram.c b/arch/x86/cpu/coreboot/sdram.c
index a2e47d1..4a256ba 100644
--- a/arch/x86/cpu/coreboot/sdram.c
+++ b/arch/x86/cpu/coreboot/sdram.c
@@ -8,7 +8,7 @@
 #include <common.h>
 #include <init.h>
 #include <asm/e820.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
 #include <asm/global_data.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -16,32 +16,7 @@
 unsigned int install_e820_map(unsigned int max_entries,
 			      struct e820_entry *entries)
 {
-	unsigned int num_entries;
-	int i;
-
-	num_entries = min((unsigned int)lib_sysinfo.n_memranges, max_entries);
-	if (num_entries < lib_sysinfo.n_memranges) {
-		printf("Warning: Limiting e820 map to %d entries.\n",
-			num_entries);
-	}
-	for (i = 0; i < num_entries; i++) {
-		struct memrange *memrange = &lib_sysinfo.memrange[i];
-
-		entries[i].addr = memrange->base;
-		entries[i].size = memrange->size;
-
-		/*
-		 * coreboot has some extensions (type 6 & 16) to the E820 types.
-		 * When we detect this, mark it as E820_RESERVED.
-		 */
-		if (memrange->type == CB_MEM_VENDOR_RSVD ||
-		    memrange->type == CB_MEM_TABLE)
-			entries[i].type = E820_RESERVED;
-		else
-			entries[i].type = memrange->type;
-	}
-
-	return num_entries;
+	return cb_install_e820_map(max_entries, entries);
 }
 
 /*
diff --git a/arch/x86/cpu/coreboot/tables.c b/arch/x86/cpu/coreboot/tables.c
deleted file mode 100644
index c52741a..0000000
--- a/arch/x86/cpu/coreboot/tables.c
+++ /dev/null
@@ -1,255 +0,0 @@
-// SPDX-License-Identifier: BSD-3-Clause
-/*
- * This file is part of the libpayload project.
- *
- * Copyright (C) 2008 Advanced Micro Devices, Inc.
- * Copyright (C) 2009 coresystems GmbH
- */
-
-#include <common.h>
-#include <net.h>
-#include <asm/arch/sysinfo.h>
-#include <asm/global_data.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-/*
- * This needs to be in the .data section so that it's copied over during
- * relocation. By default it's put in the .bss section which is simply filled
- * with zeroes when transitioning from "ROM", which is really RAM, to other
- * RAM.
- */
-struct sysinfo_t lib_sysinfo __attribute__((section(".data")));
-
-/*
- * Some of this is x86 specific, and the rest of it is generic. Right now,
- * since we only support x86, we'll avoid trying to make lots of infrastructure
- * we don't need. If in the future, we want to use coreboot on some other
- * architecture, then take out the generic parsing code and move it elsewhere.
- */
-
-/* === Parsing code === */
-/* This is the generic parsing code. */
-
-static void cb_parse_memory(unsigned char *ptr, struct sysinfo_t *info)
-{
-	struct cb_memory *mem = (struct cb_memory *)ptr;
-	int count = MEM_RANGE_COUNT(mem);
-	int i;
-
-	if (count > SYSINFO_MAX_MEM_RANGES)
-		count = SYSINFO_MAX_MEM_RANGES;
-
-	info->n_memranges = 0;
-
-	for (i = 0; i < count; i++) {
-		struct cb_memory_range *range =
-		    (struct cb_memory_range *)MEM_RANGE_PTR(mem, i);
-
-		info->memrange[info->n_memranges].base =
-		    UNPACK_CB64(range->start);
-
-		info->memrange[info->n_memranges].size =
-		    UNPACK_CB64(range->size);
-
-		info->memrange[info->n_memranges].type = range->type;
-
-		info->n_memranges++;
-	}
-}
-
-static void cb_parse_serial(unsigned char *ptr, struct sysinfo_t *info)
-{
-	struct cb_serial *ser = (struct cb_serial *)ptr;
-	info->serial = ser;
-}
-
-static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info)
-{
-	struct cb_vbnv *vbnv = (struct cb_vbnv *)ptr;
-
-	info->vbnv_start = vbnv->vbnv_start;
-	info->vbnv_size = vbnv->vbnv_size;
-}
-
-static void cb_parse_cbmem_entry(unsigned char *ptr, struct sysinfo_t *info)
-{
-	struct cb_cbmem_entry *entry = (struct cb_cbmem_entry *)ptr;
-
-	if (entry->id != CBMEM_ID_SMBIOS)
-		return;
-
-	info->smbios_start = entry->address;
-	info->smbios_size = entry->entry_size;
-}
-
-static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info)
-{
-	int i;
-	struct cb_gpios *gpios = (struct cb_gpios *)ptr;
-
-	info->num_gpios = (gpios->count < SYSINFO_MAX_GPIOS) ?
-				(gpios->count) : SYSINFO_MAX_GPIOS;
-
-	for (i = 0; i < info->num_gpios; i++)
-		info->gpios[i] = gpios->gpios[i];
-}
-
-static void cb_parse_vdat(unsigned char *ptr, struct sysinfo_t *info)
-{
-	struct cb_vdat *vdat = (struct cb_vdat *) ptr;
-
-	info->vdat_addr = vdat->vdat_addr;
-	info->vdat_size = vdat->vdat_size;
-}
-
-static void cb_parse_tstamp(unsigned char *ptr, struct sysinfo_t *info)
-{
-	info->tstamp_table = ((struct cb_cbmem_tab *)ptr)->cbmem_tab;
-}
-
-static void cb_parse_cbmem_cons(unsigned char *ptr, struct sysinfo_t *info)
-{
-	info->cbmem_cons = ((struct cb_cbmem_tab *)ptr)->cbmem_tab;
-}
-
-static void cb_parse_framebuffer(unsigned char *ptr, struct sysinfo_t *info)
-{
-	info->framebuffer = (struct cb_framebuffer *)ptr;
-}
-
-static void cb_parse_string(unsigned char *ptr, char **info)
-{
-	*info = (char *)((struct cb_string *)ptr)->string;
-}
-
-__weak void cb_parse_unhandled(u32 tag, unsigned char *ptr)
-{
-}
-
-static int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
-{
-	unsigned char *ptr = addr;
-	struct cb_header *header;
-	int i;
-
-	header = (struct cb_header *)ptr;
-	if (!header->table_bytes)
-		return 0;
-
-	/* Make sure the checksums match. */
-	if (!ip_checksum_ok(header, sizeof(*header)))
-		return -1;
-
-	if (compute_ip_checksum(ptr + sizeof(*header), header->table_bytes) !=
-	    header->table_checksum)
-		return -1;
-
-	/* Now, walk the tables. */
-	ptr += header->header_bytes;
-
-	/* Inintialize some fields to sentinel values. */
-	info->vbnv_start = info->vbnv_size = (uint32_t)(-1);
-
-	for (i = 0; i < header->table_entries; i++) {
-		struct cb_record *rec = (struct cb_record *)ptr;
-
-		/* We only care about a few tags here (maybe more later). */
-		switch (rec->tag) {
-		case CB_TAG_FORWARD:
-			return cb_parse_header(
-				(void *)(unsigned long)
-				((struct cb_forward *)rec)->forward,
-				len, info);
-			continue;
-		case CB_TAG_MEMORY:
-			cb_parse_memory(ptr, info);
-			break;
-		case CB_TAG_SERIAL:
-			cb_parse_serial(ptr, info);
-			break;
-		case CB_TAG_VERSION:
-			cb_parse_string(ptr, &info->version);
-			break;
-		case CB_TAG_EXTRA_VERSION:
-			cb_parse_string(ptr, &info->extra_version);
-			break;
-		case CB_TAG_BUILD:
-			cb_parse_string(ptr, &info->build);
-			break;
-		case CB_TAG_COMPILE_TIME:
-			cb_parse_string(ptr, &info->compile_time);
-			break;
-		case CB_TAG_COMPILE_BY:
-			cb_parse_string(ptr, &info->compile_by);
-			break;
-		case CB_TAG_COMPILE_HOST:
-			cb_parse_string(ptr, &info->compile_host);
-			break;
-		case CB_TAG_COMPILE_DOMAIN:
-			cb_parse_string(ptr, &info->compile_domain);
-			break;
-		case CB_TAG_COMPILER:
-			cb_parse_string(ptr, &info->compiler);
-			break;
-		case CB_TAG_LINKER:
-			cb_parse_string(ptr, &info->linker);
-			break;
-		case CB_TAG_ASSEMBLER:
-			cb_parse_string(ptr, &info->assembler);
-			break;
-		/*
-		 * FIXME we should warn on serial if coreboot set up a
-		 * framebuffer buf the payload does not know about it.
-		 */
-		case CB_TAG_FRAMEBUFFER:
-			cb_parse_framebuffer(ptr, info);
-			break;
-		case CB_TAG_GPIO:
-			cb_parse_gpios(ptr, info);
-			break;
-		case CB_TAG_VDAT:
-			cb_parse_vdat(ptr, info);
-			break;
-		case CB_TAG_TIMESTAMPS:
-			cb_parse_tstamp(ptr, info);
-			break;
-		case CB_TAG_CBMEM_CONSOLE:
-			cb_parse_cbmem_cons(ptr, info);
-			break;
-		case CB_TAG_VBNV:
-			cb_parse_vbnv(ptr, info);
-			break;
-		case CB_TAG_CBMEM_ENTRY:
-			cb_parse_cbmem_entry(ptr, info);
-			break;
-		default:
-			cb_parse_unhandled(rec->tag, ptr);
-			break;
-		}
-
-		ptr += rec->size;
-	}
-
-	return 1;
-}
-
-/* == Architecture specific == */
-/* This is the x86 specific stuff. */
-
-int get_coreboot_info(struct sysinfo_t *info)
-{
-	long addr;
-	int ret;
-
-	addr = locate_coreboot_table();
-	if (addr < 0)
-		return addr;
-	ret = cb_parse_header((void *)addr, 0x1000, info);
-	if (!ret)
-		return -ENOENT;
-	gd->arch.coreboot_table = addr;
-	gd->flags |= GD_FLG_SKIP_LL_INIT;
-
-	return 0;
-}
diff --git a/arch/x86/cpu/coreboot/timestamp.c b/arch/x86/cpu/coreboot/timestamp.c
index 0162597..7f133ce 100644
--- a/arch/x86/cpu/coreboot/timestamp.c
+++ b/arch/x86/cpu/coreboot/timestamp.c
@@ -8,21 +8,9 @@
 #include <common.h>
 #include <bootstage.h>
 #include <asm/arch/timestamp.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
 #include <linux/compiler.h>
 
-struct timestamp_entry {
-	uint32_t	entry_id;
-	uint64_t	entry_stamp;
-} __packed;
-
-struct timestamp_table {
-	uint64_t	base_time;
-	uint32_t	max_entries;
-	uint32_t	num_entries;
-	struct timestamp_entry entries[0]; /* Variable number of entries */
-} __packed;
-
 static struct timestamp_table *ts_table  __attribute__((section(".data")));
 
 void timestamp_init(void)
diff --git a/arch/x86/cpu/intel_common/itss.c b/arch/x86/cpu/intel_common/itss.c
index 588a512..1eff030 100644
--- a/arch/x86/cpu/intel_common/itss.c
+++ b/arch/x86/cpu/intel_common/itss.c
@@ -153,8 +153,9 @@
 
 static int itss_bind(struct udevice *dev)
 {
-	/* This is not set with of-platdata, so set it manually */
-	if (CONFIG_IS_ENABLED(OF_PLATDATA))
+	/* This is not set with basic of-platdata, so set it manually */
+	if (CONFIG_IS_ENABLED(OF_PLATDATA) &&
+	    !CONFIG_IS_ENABLED(OF_PLATDATA_INST))
 		dev->driver_data = X86_IRQT_ITSS;
 
 	return 0;
diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c
index bddba3e..a02f4f9 100644
--- a/arch/x86/cpu/ivybridge/cpu.c
+++ b/arch/x86/cpu/ivybridge/cpu.c
@@ -143,7 +143,7 @@
 
 		/* System is not happy after keyboard reset... */
 		debug("Issuing CF9 warm reset\n");
-		reset_cpu(0);
+		reset_cpu();
 	}
 
 	ret = cpu_common_init();
diff --git a/arch/x86/cpu/start_from_spl.S b/arch/x86/cpu/start_from_spl.S
index 905c825..abfd4ab 100644
--- a/arch/x86/cpu/start_from_spl.S
+++ b/arch/x86/cpu/start_from_spl.S
@@ -43,6 +43,10 @@
 
 	call	board_init_f_init_reserve
 
+#ifdef CONFIG_DEBUG_UART
+	call	debug_uart_init
+#endif
+
 	call	x86_cpu_reinit_f
 	xorl	%eax, %eax
 	call	board_init_f
diff --git a/arch/x86/cpu/u-boot-spl.lds b/arch/x86/cpu/u-boot-spl.lds
index b82e53a..4a655bf 100644
--- a/arch/x86/cpu/u-boot-spl.lds
+++ b/arch/x86/cpu/u-boot-spl.lds
@@ -33,6 +33,14 @@
 	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
 
 	. = ALIGN(4);
+
+	.priv_data : {
+		__priv_data_start = .;
+		*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.priv_data*)))
+		__priv_data_end = .;
+	}
+
+	. = ALIGN(4);
 	.data : { *(.data*) }
 
 	. = ALIGN(4);
diff --git a/arch/x86/dts/chromebook_coral.dts b/arch/x86/dts/chromebook_coral.dts
index 2ffe3b4..c8cb4e2 100644
--- a/arch/x86/dts/chromebook_coral.dts
+++ b/arch/x86/dts/chromebook_coral.dts
@@ -47,6 +47,7 @@
 		i2c5 = &i2c_5;
 		i2c6 = &i2c_6;
 		i2c7 = &i2c_7;
+		mmc0 = &emmc;
 		mmc1 = &sdmmc;
 	};
 
@@ -55,6 +56,17 @@
 		recovery-gpios = <&gpio_nw (-1) GPIO_ACTIVE_LOW>;
 		write-protect-gpios = <&gpio_nw GPIO_75 GPIO_ACTIVE_HIGH>;
 		phase-enforce-gpios = <&gpio_n GPIO_10 GPIO_ACTIVE_HIGH>;
+		memconfig-gpios = <&gpio_nw GPIO_101 GPIO_ACTIVE_HIGH
+			&gpio_nw GPIO_102 GPIO_ACTIVE_HIGH
+			&gpio_n GPIO_38 GPIO_ACTIVE_HIGH
+			&gpio_n GPIO_45 GPIO_ACTIVE_HIGH>;
+
+		/*
+		 * This is used for reef only:
+		 *
+		 * skuconfig-gpios = <&gpio_nw GPIO_16 GPIO_ACTIVE_HIGH
+		 *	&gpio_nw GPIO_17 GPIO_ACTIVE_HIGH>;
+		 */
 		smbios {
 			/* Type 1 table */
 			system {
@@ -100,7 +112,7 @@
 	clk: clock {
 		compatible = "intel,apl-clk";
 		#clock-cells = <1>;
-		u-boot,dm-pre-reloc;
+		u-boot,dm-pre-proper;
 	};
 
 	cpus {
@@ -141,13 +153,18 @@
 	};
 
 	acpi_gpe: general-purpose-events {
-		u-boot,dm-pre-reloc;
+		u-boot,dm-pre-proper;
 		reg = <IOMAP_ACPI_BASE IOMAP_ACPI_SIZE>;
 		compatible = "intel,acpi-gpe";
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
 
+	coreboot-video {
+		/* This will only activate when booted from coreboot */
+		compatible = "coreboot-fb";
+	};
+
 	keyboard {
 		intel,duplicate-por;
 	};
@@ -423,7 +440,7 @@
 			compatible = "intel,apl-i2c", "snps,designware-i2c-pci";
 			reg = <0x0200b210 0 0 0 0>;
 			early-regs = <IOMAP_I2C2_BASE 0x1000>;
-			u-boot,dm-pre-reloc;
+			u-boot,dm-pre-proper;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			clock-frequency = <400000>;
@@ -434,7 +451,7 @@
 			tpm: tpm@50 {
 				reg = <0x50>;
 				compatible = "google,cr50";
-				u-boot,dm-pre-reloc;
+				u-boot,dm-pre-proper;
 				u-boot,i2c-offset-len = <0>;
 				ready-gpios = <&gpio_n 28 GPIO_ACTIVE_LOW>;
 				interrupts-extended = <&acpi_gpe GPIO_28_IRQ
@@ -571,7 +588,7 @@
 		sdmmc: sdmmc@1b,0 {
 			reg = <0x0000d800 0 0 0 0>;
 			compatible = "intel,apl-sd";
-			cd-gpios = <&gpio_n GPIO_177 GPIO_ACTIVE_LOW>;
+			cd-gpios = <&gpio_sw GPIO_177 GPIO_ACTIVE_LOW>;
 			acpi,name = "SDCD";
 		};
 
@@ -1233,5 +1250,5 @@
 &rtc {
 	#address-cells = <1>;
 	#size-cells = <0>;
-	u-boot,dm-pre-reloc;
+	u-boot,dm-pre-proper;
 };
diff --git a/arch/x86/dts/reset.dtsi b/arch/x86/dts/reset.dtsi
index 555d0dd..f2ba2fb 100644
--- a/arch/x86/dts/reset.dtsi
+++ b/arch/x86/dts/reset.dtsi
@@ -1,6 +1,6 @@
 / {
 	reset: reset {
 		compatible = "x86,reset";
-		u-boot,dm-pre-reloc;
+		u-boot,dm-pre-proper;
 	};
 };
diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi
index bf92f45..ca84d18 100644
--- a/arch/x86/dts/u-boot.dtsi
+++ b/arch/x86/dts/u-boot.dtsi
@@ -38,20 +38,11 @@
 	};
 #endif
 	spl {
-		type = "section";
+		type = "u-boot-spl";
 		offset = <CONFIG_X86_OFFSET_SPL>;
-		u-boot-spl {
-		};
-		u-boot-spl-dtb {
-		};
 	};
 	u-boot {
-		type = "section";
 		offset = <CONFIG_X86_OFFSET_U_BOOT>;
-		u-boot-nodtb {
-		};
-		u-boot-dtb {
-		};
 	};
 #elif defined(CONFIG_SPL)
 	u-boot-spl-with-ucode-ptr {
@@ -64,11 +55,7 @@
 		offset = <CONFIG_X86_OFFSET_U_BOOT>;
 	};
 #else
-# ifdef CONFIG_SPL
-	u-boot {
-		offset = <CONFIG_SYS_TEXT_BASE>;
-	};
-# elif defined(CONFIG_HAVE_MICROCODE)
+# ifdef CONFIG_HAVE_MICROCODE
 	/* If there is no SPL then we need to put microcode in U-Boot */
 	u-boot-with-ucode-ptr {
 		offset = <CONFIG_X86_OFFSET_U_BOOT>;
diff --git a/arch/x86/include/asm/arch-apollolake/uart.h b/arch/x86/include/asm/arch-apollolake/uart.h
index 38335b0..c3ca171 100644
--- a/arch/x86/include/asm/arch-apollolake/uart.h
+++ b/arch/x86/include/asm/arch-apollolake/uart.h
@@ -6,6 +6,7 @@
 #ifndef _ASM_ARCH_UART_H
 #define _ASM_ARCH_UART_H
 
+#include <dt-structs.h>
 #include <ns16550.h>
 
 /**
diff --git a/arch/x86/include/asm/arch-coreboot/sysinfo.h b/arch/x86/include/asm/arch-coreboot/sysinfo.h
deleted file mode 100644
index 419ec52..0000000
--- a/arch/x86/include/asm/arch-coreboot/sysinfo.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause */
-/*
- * This file is part of the libpayload project.
- *
- * Copyright (C) 2008 Advanced Micro Devices, Inc.
- */
-
-#ifndef _COREBOOT_SYSINFO_H
-#define _COREBOOT_SYSINFO_H
-
-#include <asm/coreboot_tables.h>
-
-/* Maximum number of memory range definitions */
-#define SYSINFO_MAX_MEM_RANGES	32
-/* Allow a maximum of 8 GPIOs */
-#define SYSINFO_MAX_GPIOS	8
-
-struct sysinfo_t {
-	int n_memranges;
-	struct memrange {
-		unsigned long long base;
-		unsigned long long size;
-		unsigned int type;
-	} memrange[SYSINFO_MAX_MEM_RANGES];
-
-	u32 cmos_range_start;
-	u32 cmos_range_end;
-	u32 cmos_checksum_location;
-	u32 vbnv_start;
-	u32 vbnv_size;
-
-	char *version;
-	char *extra_version;
-	char *build;
-	char *compile_time;
-	char *compile_by;
-	char *compile_host;
-	char *compile_domain;
-	char *compiler;
-	char *linker;
-	char *assembler;
-
-	struct cb_framebuffer *framebuffer;
-
-	int num_gpios;
-	struct cb_gpio gpios[SYSINFO_MAX_GPIOS];
-
-	void	*vdat_addr;
-	u32	vdat_size;
-	void	*tstamp_table;
-	void	*cbmem_cons;
-	u64 smbios_start;
-	u32 smbios_size;
-
-	struct cb_serial *serial;
-};
-
-extern struct sysinfo_t lib_sysinfo;
-
-int get_coreboot_info(struct sysinfo_t *info);
-
-#endif
diff --git a/arch/x86/include/asm/arch-coreboot/timestamp.h b/arch/x86/include/asm/arch-coreboot/timestamp.h
index 85d42c0..531526b 100644
--- a/arch/x86/include/asm/arch-coreboot/timestamp.h
+++ b/arch/x86/include/asm/arch-coreboot/timestamp.h
@@ -8,30 +8,7 @@
 #ifndef __COREBOOT_TIMESTAMP_H__
 #define __COREBOOT_TIMESTAMP_H__
 
-enum timestamp_id {
-	/* coreboot specific timestamp IDs */
-	TS_START_ROMSTAGE = 1,
-	TS_BEFORE_INITRAM = 2,
-	TS_AFTER_INITRAM = 3,
-	TS_END_ROMSTAGE = 4,
-	TS_START_COPYRAM = 8,
-	TS_END_COPYRAM = 9,
-	TS_START_RAMSTAGE = 10,
-	TS_DEVICE_ENUMERATE = 30,
-	TS_DEVICE_CONFIGURE = 40,
-	TS_DEVICE_ENABLE = 50,
-	TS_DEVICE_INITIALIZE = 60,
-	TS_DEVICE_DONE = 70,
-	TS_CBMEM_POST = 75,
-	TS_WRITE_TABLES = 80,
-	TS_LOAD_PAYLOAD = 90,
-	TS_ACPI_WAKE_JUMP = 98,
-	TS_SELFBOOT_JUMP = 99,
-
-	/* U-Boot entry IDs start at 1000 */
-	TS_U_BOOT_INITTED = 1000, /* This is where u-boot starts */
-	TS_U_BOOT_START_KERNEL = 1100, /* Right before jumping to kernel. */
-};
+#include <asm/cb_sysinfo.h>
 
 void timestamp_init(void);
 void timestamp_add(enum timestamp_id id, uint64_t ts_time);
diff --git a/arch/x86/include/asm/cb_sysinfo.h b/arch/x86/include/asm/cb_sysinfo.h
new file mode 100644
index 0000000..675eef6
--- /dev/null
+++ b/arch/x86/include/asm/cb_sysinfo.h
@@ -0,0 +1,220 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * This file is part of the libpayload project.
+ *
+ * Copyright (C) 2008 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _COREBOOT_SYSINFO_H
+#define _COREBOOT_SYSINFO_H
+
+#include <asm/coreboot_tables.h>
+
+/* Maximum number of memory range definitions */
+#define SYSINFO_MAX_MEM_RANGES	32
+/* Allow a maximum of 8 GPIOs */
+#define SYSINFO_MAX_GPIOS	8
+/* Up to 10 MAC addresses */
+#define SYSINFO_MAX_MACS 10
+
+/**
+ * struct sysinfo_t - Information passed to U-Boot from coreboot
+ *
+ * Coreboot passes on a lot of information using a list of individual data
+ * structures identified by a numeric tag. These are parsed in U-Boot to produce
+ * this struct. Some of the pointers here point back to the tagged data
+ * structure, since it is assumed to remain around while U-Boot is running.
+ *
+ * The 'cbsysinfo' command can display this information.
+ *
+ * @cpu_khz: CPU frequence in KHz (e.g. 1100000)
+ * @serial: Pointer to the serial information, NULL if none
+ * @ser_ioport: Not actually provided by a tag and not used on modern hardware,
+ *	which typicaally uses a memory-mapped port
+ * @ser_base: Not used at all, but present to match up with the coreboot data
+ *	structure
+ * @n_memranges: Number of memory ranges
+ * @memrange: List of memory ranges:
+ *	@base: Base address of range
+ *	@size: Size of range in bytes
+ *	@type: Type of range (CB_MEM_RAM, etc.)
+ * @option_table: Provides a pointer to the CMOS RAM options table, which
+ *	indicates which options are available. The header is followed by a list
+ *	of struct cb_cmos_entries records, so that an option can be found from
+ *	its name. This is not used in U-Boot. NULL if not present
+ * @cmos_range_start: Start bit of the CMOS checksum range (in fact this must
+ *	be a multiple of 8)
+ * @cmos_range_end: End bit of the CMOS checksum range (multiple of 8). This is
+ *	the inclusive end.
+ * @cmos_checksum_location: Location of checksum, multiplied by 8. This is the
+ *	byte offset into the CMOS RAM of the first checksum byte. The second one
+ *	follows immediately. The checksum is a simple 16-bit sum of all the
+ *	bytes from offset cmos_range_start / 8 to cmos_range_end / 8, inclusive,
+ *	in big-endian format (so sum >> 8 is stored in the first byte).
+ * @vbnv_start: Start offset of CMOS RAM used for Chromium OS verified boot
+ *	(typically 0x34)
+ * @vbnv_size: Number of bytes used by Chromium OS verified boot (typically
+ *	0x10)
+ * @extra_version: Extra version information, typically ""
+ * @build: Build date, e.g. "Wed Nov 18 02:51:58 UTC 2020"
+ * @compile_time: Compilation time, e.g. "02:51:58"
+ * @compile_by: Who compiled coreboot (never set?)
+ * @compile_host: Name of the machine that compiled coreboot (never set?)
+ * @compile_domain: Domain name of the machine that compiled coreboot (never
+ *	set?)
+ * @compiler: Name of the compiler used to build coreboot (never set?)
+ * @linker: Name of the linker used to build coreboot (never set?)
+ * @assembler: Name of the assembler used to build coreboot (never set?)
+ * @cb_version: Coreboot version string, e.g. v1.9308_26_0.0.22-2599-g232f22c75d
+ * @framebuffer: Address of framebuffer tag, or NULL if none. See
+ *	struct cb_framebuffer for the definition
+ * @num_gpios: Number of verified-boot GPIOs
+ * @gpios: List of GPIOs:
+ *	@port: GPIO number, or 0xffffffff if not a GPIO
+ *	@polarity: CB_GPIO_ACTIVE_LOW or CB_GPIO_ACTIVE_HIGH
+ *	@value: Value of GPIO (0 or 1)
+ *	@name: Name of GPIO
+ *
+ *	A typical list is:
+ *	  id: port     polarity val name
+ *	   0:    -  active-high   1 write protect
+ *	   1:    -  active-high   0 recovery
+ *	   2:    -  active-high   1 lid
+ *	   3:    -  active-high   0 power
+ *	   4:    -  active-high   0 oprom
+ *	   5:   29  active-high   0 EC in RW
+ *
+ * @num_macs: Number of MAC addresses
+ * @macs: List of MAC addresses
+ * @serialno: Serial number, or NULL (never set?)
+ * @mbtable: Address of the multiboot table, or NULL. This is a
+ *	struct multiboot_header, not used in U-Boot
+ * @header: Address of header, if there is a CB_TAG_FORWARD, else NULL
+ * @mainboard: Pointer to mainboard info or NULL. Typically the vendor is
+ *	"Google" and the part number is ""
+ * @vboot_handoff: Pointer to Chromium OS verified boot hand-off information.
+ *	This is struct vboot_handoff, providing access to internal information
+ *	generated by coreboot when this is being used
+ * @vboot_handoff_size: Size of hand-off information (typically 0xc0c)
+ * @vdat_addr: Pointer to Chromium OS verified boot data, which uses
+ *	struct chromeos_acpi. It sits in the Intel Global NVS struct, after the
+ *	first 0x100 bytes
+ * @vdat_size: Size of this data, typically 0xf00
+ * @smbios_start: Address of SMBIOS tables
+ * @smbios_size: Size of SMBIOS tables (e.g. 0x800)
+ * @x86_rom_var_mtrr_index: MTRR number used for ROM caching. Not used in U-Boot
+ * @tstamp_table: Pointer to timestamp_table, struct timestamp_table
+ * @cbmem_cons: Pointer to the console dump, struct cbmem_console. This provides
+ *	access to the console output generated by coreboot, typically about 64KB
+ *	and mostly PCI enumeration info
+ * @mrc_cache: Pointer to memory-reference-code cache, typically NULL
+ * acpi_gnvs: @Pointer to Intel Global NVS struct, see struct acpi_global_nvs
+ * @board_id: Board ID indicating the board variant, typically 0xffffffff
+ * @ram_code: RAM code indicating the SDRAM type, typically 0xffffffff
+ * @wifi_calibration: WiFi calibration info, NULL if none
+ * @ramoops_buffer: Address of kernel Ramoops buffer
+ * @ramoops_buffer_size: Sizeof of Ramoops buffer, typically 1MB
+ * @spi_flash: Information about SPI flash:
+ *	@size: Size in bytes, e.g. 16MB
+ *	@sector_size; Sector size of flash device, e.g. 4KB
+ *	@erase_cmd: Command used to erase flash, or 0 if not used
+ * @fmap_offset: SPI-flash offset of the flash map (FMAP) table. This has a
+ *	__FMAP__ header. It provides information about the different top-level
+ *	sections in the SPI flash, e.g. 0x204000
+ * @cbfs_offset: SPI-flash offset of the Coreboot Filesystem (CBFS) used for
+ *	read-only data, e.g. 0x205000. This is typically called 'COREBOOT' in
+ *	the flash map. It holds various coreboot binaries as well as
+ *	video-configuration files and graphics data for the Chromium OS
+ *	verified boot user interface.
+ * @cbfs_size: Size of CBFS, e.g. 0x17b000
+ * @boot_media_size; Size of boot media (i.e. SPI flash), e.g. 16MB
+ * @mtc_start; Start of MTC region (Nvidia private data), 0 if not used. See
+ *	https://chromium.googlesource.com/chromiumos/third_party/coreboot/+/chromeos-2013.04/src/soc/nvidia/tegra210/mtc.c
+ * @mtc_size: Size of MTC region
+ * @chromeos_vpd: Chromium OS Vital Product Data region, typically NULL, meaning
+ *	not used
+ */
+struct sysinfo_t {
+	unsigned int cpu_khz;
+	struct cb_serial *serial;
+	unsigned short ser_ioport;
+	unsigned long ser_base; // for mmapped serial
+
+	int n_memranges;
+
+	struct memrange {
+		unsigned long long base;
+		unsigned long long size;
+		unsigned int type;
+	} memrange[SYSINFO_MAX_MEM_RANGES];
+
+	struct cb_cmos_option_table *option_table;
+	u32 cmos_range_start;
+	u32 cmos_range_end;
+	u32 cmos_checksum_location;
+	u32 vbnv_start;
+	u32 vbnv_size;
+
+	char *version;
+	char *extra_version;
+	char *build;
+	char *compile_time;
+	char *compile_by;
+	char *compile_host;
+	char *compile_domain;
+	char *compiler;
+	char *linker;
+	char *assembler;
+
+	char *cb_version;
+
+	struct cb_framebuffer *framebuffer;
+
+	int num_gpios;
+	struct cb_gpio gpios[SYSINFO_MAX_GPIOS];
+	int num_macs;
+	struct mac_address macs[SYSINFO_MAX_MACS];
+	char *serialno;
+
+	unsigned long *mbtable; /** Pointer to the multiboot table */
+
+	struct cb_header *header;
+	struct cb_mainboard *mainboard;
+
+	void	*vboot_handoff;
+	u32	vboot_handoff_size;
+	void	*vdat_addr;
+	u32	vdat_size;
+	u64 smbios_start;
+	u32 smbios_size;
+
+	int x86_rom_var_mtrr_index;
+
+	void		*tstamp_table;
+	void		*cbmem_cons;
+	void		*mrc_cache;
+	void		*acpi_gnvs;
+	u32		board_id;
+	u32		ram_code;
+	void		*wifi_calibration;
+	u64	ramoops_buffer;
+	u32	ramoops_buffer_size;
+	struct {
+		u32 size;
+		u32 sector_size;
+		u32 erase_cmd;
+	} spi_flash;
+	u64 fmap_offset;
+	u64 cbfs_offset;
+	u64 cbfs_size;
+	u64 boot_media_size;
+	u64 mtc_start;
+	u32 mtc_size;
+	void	*chromeos_vpd;
+};
+
+extern struct sysinfo_t lib_sysinfo;
+
+int get_coreboot_info(struct sysinfo_t *info);
+
+#endif
diff --git a/arch/x86/include/asm/coreboot_tables.h b/arch/x86/include/asm/coreboot_tables.h
index 7e15767..a74654b 100644
--- a/arch/x86/include/asm/coreboot_tables.h
+++ b/arch/x86/include/asm/coreboot_tables.h
@@ -8,6 +8,106 @@
 #ifndef _COREBOOT_TABLES_H
 #define _COREBOOT_TABLES_H
 
+struct timestamp_entry {
+	u32	entry_id;
+	u64	entry_stamp;
+} __packed;
+
+struct timestamp_table {
+	u64	base_time;
+	u16	max_entries;
+	u16	tick_freq_mhz;
+	u32	num_entries;
+	struct timestamp_entry entries[0]; /* Variable number of entries */
+} __packed;
+
+enum timestamp_id {
+	/* coreboot-specific timestamp IDs */
+	TS_START_ROMSTAGE = 1,
+	TS_BEFORE_INITRAM = 2,
+	TS_AFTER_INITRAM = 3,
+	TS_END_ROMSTAGE = 4,
+	TS_START_VBOOT = 5,
+	TS_END_VBOOT = 6,
+	TS_START_COPYRAM = 8,
+	TS_END_COPYRAM = 9,
+	TS_START_RAMSTAGE = 10,
+	TS_START_BOOTBLOCK = 11,
+	TS_END_BOOTBLOCK = 12,
+	TS_START_COPYROM = 13,
+	TS_END_COPYROM = 14,
+	TS_START_ULZMA = 15,
+	TS_END_ULZMA = 16,
+	TS_START_ULZ4F = 17,
+	TS_END_ULZ4F = 18,
+	TS_DEVICE_ENUMERATE = 30,
+	TS_DEVICE_CONFIGURE = 40,
+	TS_DEVICE_ENABLE = 50,
+	TS_DEVICE_INITIALIZE = 60,
+	TS_DEVICE_DONE = 70,
+	TS_CBMEM_POST = 75,
+	TS_WRITE_TABLES = 80,
+	TS_FINALIZE_CHIPS = 85,
+	TS_LOAD_PAYLOAD = 90,
+	TS_ACPI_WAKE_JUMP = 98,
+	TS_SELFBOOT_JUMP = 99,
+
+	/* 500+ reserved for vendorcode extensions (500-600: google/chromeos) */
+	TS_START_COPYVER = 501,
+	TS_END_COPYVER = 502,
+	TS_START_TPMINIT = 503,
+	TS_END_TPMINIT = 504,
+	TS_START_VERIFY_SLOT = 505,
+	TS_END_VERIFY_SLOT = 506,
+	TS_START_HASH_BODY = 507,
+	TS_DONE_LOADING = 508,
+	TS_DONE_HASHING = 509,
+	TS_END_HASH_BODY = 510,
+	TS_START_COPYVPD = 550,
+	TS_END_COPYVPD_RO = 551,
+	TS_END_COPYVPD_RW = 552,
+
+	/* 940-950 reserved for vendorcode extensions (940-950: Intel ME) */
+	TS_ME_INFORM_DRAM_WAIT = 940,
+	TS_ME_INFORM_DRAM_DONE = 941,
+
+	/* 950+ reserved for vendorcode extensions (950-999: intel/fsp) */
+	TS_FSP_MEMORY_INIT_START = 950,
+	TS_FSP_MEMORY_INIT_END = 951,
+	TS_FSP_TEMP_RAM_EXIT_START = 952,
+	TS_FSP_TEMP_RAM_EXIT_END = 953,
+	TS_FSP_SILICON_INIT_START = 954,
+	TS_FSP_SILICON_INIT_END = 955,
+	TS_FSP_BEFORE_ENUMERATE = 956,
+	TS_FSP_AFTER_ENUMERATE = 957,
+	TS_FSP_BEFORE_FINALIZE = 958,
+	TS_FSP_AFTER_FINALIZE = 959,
+	TS_FSP_BEFORE_END_OF_FIRMWARE = 960,
+	TS_FSP_AFTER_END_OF_FIRMWARE = 961,
+
+	/* 1000+ reserved for payloads (1000-1200: ChromeOS depthcharge) */
+
+	/* U-Boot entry IDs start at 1000 */
+	TS_U_BOOT_INITTED = 1000, /* This is where U-Boot starts */
+
+	TS_RO_PARAMS_INIT = 1001,
+	TS_RO_VB_INIT = 1002,
+	TS_RO_VB_SELECT_FIRMWARE = 1003,
+	TS_RO_VB_SELECT_AND_LOAD_KERNEL = 1004,
+
+	TS_RW_VB_SELECT_AND_LOAD_KERNEL = 1010,
+
+	TS_VB_SELECT_AND_LOAD_KERNEL = 1020,
+	TS_VB_EC_VBOOT_DONE = 1030,
+	TS_VB_STORAGE_INIT_DONE = 1040,
+	TS_VB_READ_KERNEL_DONE = 1050,
+	TS_VB_VBOOT_DONE = 1100,
+
+	TS_START_KERNEL = 1101,
+	TS_KERNEL_DECOMPRESSION = 1102,
+	TS_U_BOOT_START_KERNEL = 1100, /* Right before jumping to kernel */
+};
+
 struct memory_area;
 
 struct cbuint64 {
@@ -162,13 +262,14 @@
 };
 
 #define CB_TAG_GPIO			0x0013
-#define GPIO_MAX_NAME_LENGTH		16
-
+#define CB_GPIO_ACTIVE_LOW		0
+#define CB_GPIO_ACTIVE_HIGH		1
+#define CB_GPIO_MAX_NAME_LENGTH		16
 struct cb_gpio {
 	u32 port;
 	u32 polarity;
 	u32 value;
-	u8 name[GPIO_MAX_NAME_LENGTH];
+	u8 name[CB_GPIO_MAX_NAME_LENGTH];
 };
 
 struct cb_gpios {
@@ -181,61 +282,158 @@
 #define CB_TAG_FDT			0x0014
 
 struct cb_fdt {
-	uint32_t tag;
-	uint32_t size;	/* size of the entire entry */
+	u32 tag;
+	u32 size;	/* size of the entire entry */
 	/* the actual FDT gets placed here */
 };
 
 #define CB_TAG_VDAT			0x0015
 
 struct cb_vdat {
-	uint32_t tag;
-	uint32_t size;	/* size of the entire entry */
+	u32 tag;
+	u32 size;	/* size of the entire entry */
 	void *vdat_addr;
-	uint32_t vdat_size;
+	u32 vdat_size;
 };
 
 #define CB_TAG_TIMESTAMPS		0x0016
 #define CB_TAG_CBMEM_CONSOLE		0x0017
+
+struct cbmem_console {
+	u32 size;
+	u32 cursor;
+	char body[0];
+} __packed;
+
 #define CB_TAG_MRC_CACHE		0x0018
 
 struct cb_cbmem_tab {
-	uint32_t tag;
-	uint32_t size;
-	void *cbmem_tab;
+	u32 tag;
+	u32 size;
+	u64 cbmem_tab;
 };
 
 #define CB_TAG_VBNV			0x0019
 
 struct cb_vbnv {
-	uint32_t tag;
-	uint32_t size;
-	uint32_t vbnv_start;
-	uint32_t vbnv_size;
+	u32 tag;
+	u32 size;
+	u32 vbnv_start;
+	u32 vbnv_size;
 };
 
-#define CB_TAG_CBMEM_ENTRY 0x0031
-#define CBMEM_ID_SMBIOS    0x534d4254
+#define CB_TAG_VBOOT_HANDOFF		0x0020
+
+#define CB_TAG_X86_ROM_MTRR		0x0021
+struct cb_x86_rom_mtrr {
+	u32 tag;
+	u32 size;
+	/*
+	 * The variable range MTRR index covering the ROM. If one wants to
+	 * enable caching the ROM, the variable MTRR needs to be set to
+	 * write-protect. To disable the caching after enabling set the
+	 * type to uncacheable
+	 */
+	u32 index;
+};
+
+#define CB_TAG_DMA			0x0022
+#define CB_TAG_RAM_OOPS			0x0023
+#define CB_TAG_ACPI_GNVS		0x0024
+
+#define CB_TAG_BOARD_ID			0x0025
+struct cb_board_id {
+	u32 tag;
+	u32 size;
+	/* Board ID as retrieved from the board revision GPIOs. */
+	u32 board_id;
+};
+
+#define CB_TAG_MAC_ADDRS		0x0026
+struct mac_address {
+	u8 mac_addr[6];
+	u8 pad[2];         /* Pad it to 8 bytes to keep it simple. */
+};
+
+struct cb_macs {
+	u32 tag;
+	u32 size;
+	u32 count;
+	struct mac_address mac_addrs[0];
+};
+
+#define CB_TAG_WIFI_CALIBRATION		0x0027
+
+#define CB_TAG_RAM_CODE			0x0028
+struct cb_ram_code {
+	u32 tag;
+	u32 size;
+	u32 ram_code;
+};
+
+#define CB_TAG_SPI_FLASH		0x0029
+struct cb_spi_flash {
+	u32 tag;
+	u32 size;
+	u32 flash_size;
+	u32 sector_size;
+	u32 erase_cmd;
+};
+
+#define CB_TAG_MTC			0x002b
+#define CB_TAG_VPD			0x002c
+struct lb_range {
+	u32 tag;
+	u32 size;
+	u64 range_start;
+	u32 range_size;
+};
+
+#define CB_TAG_BOOT_MEDIA_PARAMS	0x0030
+struct cb_boot_media_params {
+	u32 tag;
+	u32 size;
+	/* offsets are relative to start of boot media */
+	u64 fmap_offset;
+	u64 cbfs_offset;
+	u64 cbfs_size;
+	u64 boot_media_size;
+};
+
+#define CB_TAG_CBMEM_ENTRY		0x0031
+#define CBMEM_ID_SMBIOS			0x534d4254
 
 struct cb_cbmem_entry {
-	uint32_t tag;
-	uint32_t size;
-	uint64_t address;
-	uint32_t entry_size;
-	uint32_t id;
+	u32 tag;
+	u32 size;
+	u64 address;
+	u32 entry_size;
+	u32 id;
 };
 
+#define CB_TAG_TSC_INFO			0x0032
+struct cb_tsc_info {
+	u32 tag;
+	u32 size;
+
+	u32 freq_khz;
+};
+
+#define CB_TAG_SERIALNO			0x002a
+#define CB_MAX_SERIALNO_LENGTH		32
+
 #define CB_TAG_CMOS_OPTION_TABLE	0x00c8
 
 struct cb_cmos_option_table {
 	u32 tag;
 	u32 size;
 	u32 header_length;
+	/* entries follow after this header */
 };
 
 #define CB_TAG_OPTION			0x00c9
 
-#define CMOS_MAX_NAME_LENGTH		32
+#define CB_CMOS_MAX_NAME_LENGTH		32
 
 struct cb_cmos_entries {
 	u32 tag;
@@ -244,34 +442,33 @@
 	u32 length;
 	u32 config;
 	u32 config_id;
-	u8 name[CMOS_MAX_NAME_LENGTH];
+	u8 name[CB_CMOS_MAX_NAME_LENGTH];
 };
 
 #define CB_TAG_OPTION_ENUM		0x00ca
-#define CMOS_MAX_TEXT_LENGTH		32
-
+#define CB_CMOS_MAX_TEXT_LENGTH		32
 struct cb_cmos_enums {
 	u32 tag;
 	u32 size;
 	u32 config_id;
 	u32 value;
-	u8 text[CMOS_MAX_TEXT_LENGTH];
+	u8 text[CB_CMOS_MAX_TEXT_LENGTH];
 };
 
 #define CB_TAG_OPTION_DEFAULTS		0x00cb
-#define CMOS_IMAGE_BUFFER_SIZE		128
+#define CB_CMOS_IMAGE_BUFFER_SIZE	128
 
 struct cb_cmos_defaults {
 	u32 tag;
 	u32 size;
 	u32 name_length;
-	u8 name[CMOS_MAX_NAME_LENGTH];
-	u8 default_set[CMOS_IMAGE_BUFFER_SIZE];
+	u8 name[CB_CMOS_MAX_NAME_LENGTH];
+	u8 default_set[CB_CMOS_IMAGE_BUFFER_SIZE];
 };
 
 #define CB_TAG_OPTION_CHECKSUM		0x00cc
-#define CHECKSUM_NONE			0
-#define CHECKSUM_PCBIOS			1
+#define CB_CHECKSUM_NONE		0
+#define CB_CHECKSUM_PCBIOS		1
 
 struct	cb_cmos_checksum {
 	u32 tag;
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
index a66c0d2..850a0a7 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -22,9 +22,23 @@
 #define ISA_START_ADDRESS	0xa0000
 #define ISA_END_ADDRESS		0x100000
 
-/* Implementation defined function to install an e820 map */
+/* Implementation-defined function to install an e820 map */
 unsigned int install_e820_map(unsigned int max_entries,
 			      struct e820_entry *);
+
+/**
+ * cb_install_e820_map() - Install e820 map provided by coreboot sysinfo
+ *
+ * This should be used when booting from coreboot, since in that case the
+ * memory areas are provided by coreboot in its sysinfo.
+ *
+ * @max_entries: Maximum number of entries to write
+ * @entries: Place to put entires
+ * @return number of entries written
+ */
+unsigned int cb_install_e820_map(unsigned int max_entries,
+				 struct e820_entry *entries);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_X86_E820_H */
diff --git a/arch/x86/include/asm/intel_pinctrl_defs.h b/arch/x86/include/asm/intel_pinctrl_defs.h
index 1ea141f..5d83d24 100644
--- a/arch/x86/include/asm/intel_pinctrl_defs.h
+++ b/arch/x86/include/asm/intel_pinctrl_defs.h
@@ -11,6 +11,11 @@
 
 /* This file is included by device trees, so avoid BIT() macros */
 
+#define GPIO_DW_SIZE(x)			(sizeof(u32) * (x))
+#define PAD_CFG_OFFSET(x, dw_num)	((x) + GPIO_DW_SIZE(dw_num))
+#define PAD_CFG0_OFFSET(x)		PAD_CFG_OFFSET(x, 0)
+#define PAD_CFG1_OFFSET(x)		PAD_CFG_OFFSET(x, 1)
+
 #define PAD_CFG0_TX_STATE_BIT		0
 #define PAD_CFG0_TX_STATE		(1 << PAD_CFG0_TX_STATE_BIT)
 #define PAD_CFG0_RX_STATE_BIT		1
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 1bcbb49..65d9b3b 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -15,6 +15,7 @@
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
 endif
 obj-y	+= cmd_boot.o
+obj-$(CONFIG_$(SPL_)COREBOOT_SYSINFO)	+= coreboot/
 obj-$(CONFIG_SEABIOS) += coreboot_table.o
 obj-y	+= early_cmos.o
 obj-y	+= e820.o
diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c
index aa5f0bf..733dd71 100644
--- a/arch/x86/lib/bootm.c
+++ b/arch/x86/lib/bootm.c
@@ -36,7 +36,7 @@
 	printf("\nStarting kernel ...\n\n");
 
 #ifdef CONFIG_SYS_COREBOOT
-	timestamp_add_now(TS_U_BOOT_START_KERNEL);
+	timestamp_add_now(TS_START_KERNEL);
 #endif
 	bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
 #if CONFIG_IS_ENABLED(BOOTSTAGE_REPORT)
diff --git a/arch/x86/lib/coreboot/Makefile b/arch/x86/lib/coreboot/Makefile
new file mode 100644
index 0000000..cb0ae1d
--- /dev/null
+++ b/arch/x86/lib/coreboot/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier:	GPL-2.0+
+#
+# Copyright 2021 Google LLC
+#
+
+obj-y += cb_sysinfo.o
+obj-y += cb_support.o
diff --git a/arch/x86/lib/coreboot/cb_support.c b/arch/x86/lib/coreboot/cb_support.c
new file mode 100644
index 0000000..ebb45cd
--- /dev/null
+++ b/arch/x86/lib/coreboot/cb_support.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Support for booting from coreboot
+ *
+ * Copyright 2021 Google LLC
+ */
+
+#include <common.h>
+#include <asm/cb_sysinfo.h>
+#include <asm/e820.h>
+
+unsigned int cb_install_e820_map(unsigned int max_entries,
+				 struct e820_entry *entries)
+{
+	unsigned int num_entries;
+	int i;
+
+	num_entries = min((unsigned int)lib_sysinfo.n_memranges, max_entries);
+	if (num_entries < lib_sysinfo.n_memranges) {
+		printf("Warning: Limiting e820 map to %d entries\n",
+		       num_entries);
+	}
+	for (i = 0; i < num_entries; i++) {
+		struct memrange *memrange = &lib_sysinfo.memrange[i];
+
+		entries[i].addr = memrange->base;
+		entries[i].size = memrange->size;
+
+		/*
+		 * coreboot has some extensions (type 6 & 16) to the E820 types.
+		 * When we detect this, mark it as E820_RESERVED.
+		 */
+		if (memrange->type == CB_MEM_VENDOR_RSVD ||
+		    memrange->type == CB_MEM_TABLE)
+			entries[i].type = E820_RESERVED;
+		else
+			entries[i].type = memrange->type;
+	}
+
+	return num_entries;
+}
diff --git a/arch/x86/lib/coreboot/cb_sysinfo.c b/arch/x86/lib/coreboot/cb_sysinfo.c
new file mode 100644
index 0000000..e2c65bf
--- /dev/null
+++ b/arch/x86/lib/coreboot/cb_sysinfo.c
@@ -0,0 +1,468 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * This file is part of the libpayload project.
+ *
+ * Copyright (C) 2008 Advanced Micro Devices, Inc.
+ * Copyright (C) 2009 coresystems GmbH
+ */
+
+#include <common.h>
+#include <asm/cb_sysinfo.h>
+#include <init.h>
+#include <mapmem.h>
+#include <net.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * This needs to be in the .data section so that it's copied over during
+ * relocation. By default it's put in the .bss section which is simply filled
+ * with zeroes when transitioning from "ROM", which is really RAM, to other
+ * RAM.
+ */
+struct sysinfo_t lib_sysinfo __attribute__((section(".data")));
+
+/*
+ * Some of this is x86 specific, and the rest of it is generic. Right now,
+ * since we only support x86, we'll avoid trying to make lots of infrastructure
+ * we don't need. If in the future, we want to use coreboot on some other
+ * architecture, then take out the generic parsing code and move it elsewhere.
+ */
+
+/* === Parsing code === */
+/* This is the generic parsing code */
+
+static void cb_parse_memory(unsigned char *ptr, struct sysinfo_t *info)
+{
+	struct cb_memory *mem = (struct cb_memory *)ptr;
+	int count = MEM_RANGE_COUNT(mem);
+	int i;
+
+	if (count > SYSINFO_MAX_MEM_RANGES)
+		count = SYSINFO_MAX_MEM_RANGES;
+
+	info->n_memranges = 0;
+
+	for (i = 0; i < count; i++) {
+		struct cb_memory_range *range =
+		    (struct cb_memory_range *)MEM_RANGE_PTR(mem, i);
+
+		info->memrange[info->n_memranges].base =
+		    UNPACK_CB64(range->start);
+
+		info->memrange[info->n_memranges].size =
+		    UNPACK_CB64(range->size);
+
+		info->memrange[info->n_memranges].type = range->type;
+
+		info->n_memranges++;
+	}
+}
+
+static void cb_parse_serial(unsigned char *ptr, struct sysinfo_t *info)
+{
+	struct cb_serial *ser = (struct cb_serial *)ptr;
+
+	info->serial = ser;
+}
+
+static void cb_parse_vboot_handoff(unsigned char *ptr, struct sysinfo_t *info)
+{
+	struct lb_range *vbho = (struct lb_range *)ptr;
+
+	info->vboot_handoff = (void *)(uintptr_t)vbho->range_start;
+	info->vboot_handoff_size = vbho->range_size;
+}
+
+static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info)
+{
+	struct lb_range *vbnv = (struct lb_range *)ptr;
+
+	info->vbnv_start = vbnv->range_start;
+	info->vbnv_size = vbnv->range_size;
+}
+
+static void cb_parse_cbmem_entry(unsigned char *ptr, struct sysinfo_t *info)
+{
+	struct cb_cbmem_entry *entry = (struct cb_cbmem_entry *)ptr;
+
+	if (entry->id != CBMEM_ID_SMBIOS)
+		return;
+
+	info->smbios_start = entry->address;
+	info->smbios_size = entry->entry_size;
+}
+
+static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info)
+{
+	int i;
+	struct cb_gpios *gpios = (struct cb_gpios *)ptr;
+
+	info->num_gpios = (gpios->count < SYSINFO_MAX_GPIOS) ?
+				(gpios->count) : SYSINFO_MAX_GPIOS;
+
+	for (i = 0; i < info->num_gpios; i++)
+		info->gpios[i] = gpios->gpios[i];
+}
+
+static void cb_parse_vdat(unsigned char *ptr, struct sysinfo_t *info)
+{
+	struct lb_range *vdat = (struct lb_range *)ptr;
+
+	info->vdat_addr = map_sysmem(vdat->range_start, vdat->range_size);
+	info->vdat_size = vdat->range_size;
+}
+
+static void cb_parse_mac_addresses(unsigned char *ptr,
+				   struct sysinfo_t *info)
+{
+	struct cb_macs *macs = (struct cb_macs *)ptr;
+	int i;
+
+	info->num_macs = (macs->count < ARRAY_SIZE(info->macs)) ?
+		macs->count : ARRAY_SIZE(info->macs);
+
+	for (i = 0; i < info->num_macs; i++)
+		info->macs[i] = macs->mac_addrs[i];
+}
+
+static void cb_parse_tstamp(void *ptr, struct sysinfo_t *info)
+{
+	struct cb_cbmem_tab *const cbmem = ptr;
+
+	info->tstamp_table = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+static void cb_parse_cbmem_cons(void *ptr, struct sysinfo_t *info)
+{
+	struct cb_cbmem_tab *const cbmem = ptr;
+
+	info->cbmem_cons = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+static void cb_parse_acpi_gnvs(unsigned char *ptr, struct sysinfo_t *info)
+{
+	struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
+
+	info->acpi_gnvs = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+static void cb_parse_board_id(unsigned char *ptr, struct sysinfo_t *info)
+{
+	struct cb_board_id *const cbbid = (struct cb_board_id *)ptr;
+
+	info->board_id = cbbid->board_id;
+}
+
+static void cb_parse_ram_code(unsigned char *ptr, struct sysinfo_t *info)
+{
+	struct cb_ram_code *const ram_code = (struct cb_ram_code *)ptr;
+
+	info->ram_code = ram_code->ram_code;
+}
+
+static void cb_parse_optiontable(void *ptr, struct sysinfo_t *info)
+{
+	/* ptr points to a coreboot table entry and is already virtual */
+	info->option_table = ptr;
+}
+
+static void cb_parse_checksum(void *ptr, struct sysinfo_t *info)
+{
+	struct cb_cmos_checksum *cmos_cksum = ptr;
+
+	info->cmos_range_start = cmos_cksum->range_start;
+	info->cmos_range_end = cmos_cksum->range_end;
+	info->cmos_checksum_location = cmos_cksum->location;
+}
+
+static void cb_parse_framebuffer(void *ptr, struct sysinfo_t *info)
+{
+	/* ptr points to a coreboot table entry and is already virtual */
+	info->framebuffer = ptr;
+}
+
+static void cb_parse_string(unsigned char *ptr, char **info)
+{
+	*info = (char *)((struct cb_string *)ptr)->string;
+}
+
+static void cb_parse_wifi_calibration(void *ptr, struct sysinfo_t *info)
+{
+	struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
+
+	info->wifi_calibration = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+static void cb_parse_ramoops(void *ptr, struct sysinfo_t *info)
+{
+	struct lb_range *ramoops = (struct lb_range *)ptr;
+
+	info->ramoops_buffer = ramoops->range_start;
+	info->ramoops_buffer_size = ramoops->range_size;
+}
+
+static void cb_parse_mtc(void *ptr, struct sysinfo_t *info)
+{
+	struct lb_range *mtc = (struct lb_range *)ptr;
+
+	info->mtc_start = mtc->range_start;
+	info->mtc_size = mtc->range_size;
+}
+
+static void cb_parse_spi_flash(void *ptr, struct sysinfo_t *info)
+{
+	struct cb_spi_flash *flash = (struct cb_spi_flash *)ptr;
+
+	info->spi_flash.size = flash->flash_size;
+	info->spi_flash.sector_size = flash->sector_size;
+	info->spi_flash.erase_cmd = flash->erase_cmd;
+}
+
+static void cb_parse_boot_media_params(unsigned char *ptr,
+				       struct sysinfo_t *info)
+{
+	struct cb_boot_media_params *const bmp =
+			(struct cb_boot_media_params *)ptr;
+
+	info->fmap_offset = bmp->fmap_offset;
+	info->cbfs_offset = bmp->cbfs_offset;
+	info->cbfs_size = bmp->cbfs_size;
+	info->boot_media_size = bmp->boot_media_size;
+}
+
+static void cb_parse_vpd(void *ptr, struct sysinfo_t *info)
+{
+	struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
+
+	info->chromeos_vpd = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+static void cb_parse_tsc_info(void *ptr, struct sysinfo_t *info)
+{
+	const struct cb_tsc_info *tsc_info = ptr;
+
+	if (tsc_info->freq_khz == 0)
+		return;
+
+	/* Honor the TSC frequency passed to the payload */
+	info->cpu_khz = tsc_info->freq_khz;
+}
+
+static void cb_parse_x86_rom_var_mtrr(void *ptr, struct sysinfo_t *info)
+{
+	struct cb_x86_rom_mtrr *rom_mtrr = ptr;
+
+	info->x86_rom_var_mtrr_index = rom_mtrr->index;
+}
+
+static void cb_parse_mrc_cache(void *ptr, struct sysinfo_t *info)
+{
+	struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
+
+	info->mrc_cache = map_sysmem(cbmem->cbmem_tab, 0);
+}
+
+__weak void cb_parse_unhandled(u32 tag, unsigned char *ptr)
+{
+}
+
+static int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
+{
+	unsigned char *ptr = addr;
+	struct cb_header *header;
+	int i;
+
+	header = (struct cb_header *)ptr;
+	if (!header->table_bytes)
+		return 0;
+
+	/* Make sure the checksums match */
+	if (!ip_checksum_ok(header, sizeof(*header)))
+		return -1;
+
+	if (compute_ip_checksum(ptr + sizeof(*header), header->table_bytes) !=
+	    header->table_checksum)
+		return -1;
+
+	info->header = header;
+
+	/*
+	 * Board straps represented by numerical values are small numbers.
+	 * Preset them to an invalid value in case the firmware does not
+	 * supply the info.
+	 */
+	info->board_id = ~0;
+	info->ram_code = ~0;
+
+	/* Now, walk the tables */
+	ptr += header->header_bytes;
+
+	/* Inintialize some fields to sentinel values */
+	info->vbnv_start = info->vbnv_size = (uint32_t)(-1);
+
+	for (i = 0; i < header->table_entries; i++) {
+		struct cb_record *rec = (struct cb_record *)ptr;
+
+		/* We only care about a few tags here (maybe more later) */
+		switch (rec->tag) {
+		case CB_TAG_FORWARD:
+			return cb_parse_header(
+				(void *)(unsigned long)
+				((struct cb_forward *)rec)->forward,
+				len, info);
+			continue;
+		case CB_TAG_MEMORY:
+			cb_parse_memory(ptr, info);
+			break;
+		case CB_TAG_SERIAL:
+			cb_parse_serial(ptr, info);
+			break;
+		case CB_TAG_VERSION:
+			cb_parse_string(ptr, &info->cb_version);
+			break;
+		case CB_TAG_EXTRA_VERSION:
+			cb_parse_string(ptr, &info->extra_version);
+			break;
+		case CB_TAG_BUILD:
+			cb_parse_string(ptr, &info->build);
+			break;
+		case CB_TAG_COMPILE_TIME:
+			cb_parse_string(ptr, &info->compile_time);
+			break;
+		case CB_TAG_COMPILE_BY:
+			cb_parse_string(ptr, &info->compile_by);
+			break;
+		case CB_TAG_COMPILE_HOST:
+			cb_parse_string(ptr, &info->compile_host);
+			break;
+		case CB_TAG_COMPILE_DOMAIN:
+			cb_parse_string(ptr, &info->compile_domain);
+			break;
+		case CB_TAG_COMPILER:
+			cb_parse_string(ptr, &info->compiler);
+			break;
+		case CB_TAG_LINKER:
+			cb_parse_string(ptr, &info->linker);
+			break;
+		case CB_TAG_ASSEMBLER:
+			cb_parse_string(ptr, &info->assembler);
+			break;
+		case CB_TAG_CMOS_OPTION_TABLE:
+			cb_parse_optiontable(ptr, info);
+			break;
+		case CB_TAG_OPTION_CHECKSUM:
+			cb_parse_checksum(ptr, info);
+			break;
+		/*
+		 * FIXME we should warn on serial if coreboot set up a
+		 * framebuffer buf the payload does not know about it.
+		 */
+		case CB_TAG_FRAMEBUFFER:
+			cb_parse_framebuffer(ptr, info);
+			break;
+		case CB_TAG_MAINBOARD:
+			info->mainboard = (struct cb_mainboard *)ptr;
+			break;
+		case CB_TAG_GPIO:
+			cb_parse_gpios(ptr, info);
+			break;
+		case CB_TAG_VDAT:
+			cb_parse_vdat(ptr, info);
+			break;
+		case CB_TAG_VBNV:
+			cb_parse_vbnv(ptr, info);
+			break;
+		case CB_TAG_VBOOT_HANDOFF:
+			cb_parse_vboot_handoff(ptr, info);
+			break;
+		case CB_TAG_MAC_ADDRS:
+			cb_parse_mac_addresses(ptr, info);
+			break;
+		case CB_TAG_SERIALNO:
+			cb_parse_string(ptr, &info->serialno);
+			break;
+		case CB_TAG_TIMESTAMPS:
+			cb_parse_tstamp(ptr, info);
+			break;
+		case CB_TAG_CBMEM_CONSOLE:
+			cb_parse_cbmem_cons(ptr, info);
+			break;
+		case CB_TAG_ACPI_GNVS:
+			cb_parse_acpi_gnvs(ptr, info);
+			break;
+		case CB_TAG_CBMEM_ENTRY:
+			cb_parse_cbmem_entry(ptr, info);
+			break;
+		case CB_TAG_BOARD_ID:
+			cb_parse_board_id(ptr, info);
+			break;
+		case CB_TAG_RAM_CODE:
+			cb_parse_ram_code(ptr, info);
+			break;
+		case CB_TAG_WIFI_CALIBRATION:
+			cb_parse_wifi_calibration(ptr, info);
+			break;
+		case CB_TAG_RAM_OOPS:
+			cb_parse_ramoops(ptr, info);
+			break;
+		case CB_TAG_SPI_FLASH:
+			cb_parse_spi_flash(ptr, info);
+			break;
+		case CB_TAG_MTC:
+			cb_parse_mtc(ptr, info);
+			break;
+		case CB_TAG_BOOT_MEDIA_PARAMS:
+			cb_parse_boot_media_params(ptr, info);
+			break;
+		case CB_TAG_TSC_INFO:
+			cb_parse_tsc_info(ptr, info);
+			break;
+		case CB_TAG_VPD:
+			cb_parse_vpd(ptr, info);
+			break;
+		case CB_TAG_X86_ROM_MTRR:
+			cb_parse_x86_rom_var_mtrr(rec, info);
+			break;
+		case CB_TAG_MRC_CACHE:
+			cb_parse_mrc_cache(rec, info);
+			break;
+		default:
+			cb_parse_unhandled(rec->tag, ptr);
+			break;
+		}
+
+		ptr += rec->size;
+	}
+
+	return 1;
+}
+
+/* == Architecture specific == */
+/* This is the x86 specific stuff */
+
+int get_coreboot_info(struct sysinfo_t *info)
+{
+	long addr;
+	int ret;
+
+	addr = locate_coreboot_table();
+	if (addr < 0)
+		return addr;
+	ret = cb_parse_header((void *)addr, 0x1000, info);
+	if (!ret)
+		return -ENOENT;
+	gd->arch.coreboot_table = addr;
+	gd->flags |= GD_FLG_SKIP_LL_INIT;
+
+	return 0;
+}
+
+const struct sysinfo_t *cb_get_sysinfo(void)
+{
+	if (!ll_boot_init())
+		return &lib_sysinfo;
+
+	return NULL;
+}
diff --git a/arch/x86/lib/fsp/fsp_graphics.c b/arch/x86/lib/fsp/fsp_graphics.c
index cc909e0..02fd05c 100644
--- a/arch/x86/lib/fsp/fsp_graphics.c
+++ b/arch/x86/lib/fsp/fsp_graphics.c
@@ -87,7 +87,7 @@
 	int ret;
 
 	if (!ll_boot_init())
-		return 0;
+		return -ENODEV;
 
 	printf("Video: ");
 
diff --git a/arch/x86/lib/fsp2/fsp_init.c b/arch/x86/lib/fsp2/fsp_init.c
index 85cae54..5afdce1 100644
--- a/arch/x86/lib/fsp2/fsp_init.c
+++ b/arch/x86/lib/fsp2/fsp_init.c
@@ -84,7 +84,8 @@
 	struct cbfs_priv *cbfs;
 	int ret;
 
-	ret = cbfs_init_mem(map_base + cbfs_base, &cbfs);
+	ret = cbfs_init_mem(map_base + cbfs_base, CBFS_SIZE_UNKNOWN, true,
+			    &cbfs);
 	if (ret)
 		return ret;
 	if (!ret) {
diff --git a/arch/x86/lib/fsp2/fsp_support.c b/arch/x86/lib/fsp2/fsp_support.c
index 503f97d..b2c7658 100644
--- a/arch/x86/lib/fsp2/fsp_support.c
+++ b/arch/x86/lib/fsp2/fsp_support.c
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <init.h>
 #include <log.h>
 #include <spi_flash.h>
 #include <asm/fsp/fsp_support.h>
@@ -114,6 +115,9 @@
 	struct fsp_notify_params *params_ptr;
 	u32 status;
 
+	if (!ll_boot_init())
+		return 0;
+
 	if (!fsp_hdr)
 		fsp_hdr = gd->arch.fsp_s_hdr;
 
diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c
index 066dc40..67401b9 100644
--- a/arch/x86/lib/init_helpers.c
+++ b/arch/x86/lib/init_helpers.c
@@ -18,6 +18,9 @@
 		 IS_ENABLED(CONFIG_FSP_VERSION2);
 	int ret;
 
+	if (!ll_boot_init())
+		return 0;
+
 	do_mtrr &= !IS_ENABLED(CONFIG_FSP_VERSION1) &&
 		!IS_ENABLED(CONFIG_SYS_SLIMBOOTLOADER);
 
@@ -31,9 +34,6 @@
 			return ret;
 	}
 
-	if (!ll_boot_init())
-		return 0;
-
 	/* Initialise the CPU cache(s) */
 	return init_cache();
 }
diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c
index 1bae1f4..b18c1cd 100644
--- a/arch/x86/lib/spl.c
+++ b/arch/x86/lib/spl.c
@@ -96,7 +96,7 @@
 	}
 #endif
 	preloader_console_init();
-#ifndef CONFIG_TPL
+#if !defined(CONFIG_TPL) && !CONFIG_IS_ENABLED(CPU)
 	ret = print_cpuinfo();
 	if (ret) {
 		debug("%s: print_cpuinfo() failed\n", __func__);
diff --git a/arch/x86/lib/tpl.c b/arch/x86/lib/tpl.c
index ac6b6ef..b3e5f9c 100644
--- a/arch/x86/lib/tpl.c
+++ b/arch/x86/lib/tpl.c
@@ -150,5 +150,6 @@
 	.name	= "pci_x86",
 	.id	= UCLASS_SIMPLE_BUS,
 	.of_match = of_match_ptr(tpl_fake_pci_ids),
+	DM_PHASE(tpl)
 };
 #endif
diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c
index 602788e..90fc8a4 100644
--- a/arch/x86/lib/zimage.c
+++ b/arch/x86/lib/zimage.c
@@ -18,6 +18,7 @@
 #include <bootm.h>
 #include <command.h>
 #include <env.h>
+#include <init.h>
 #include <irq_func.h>
 #include <log.h>
 #include <malloc.h>
@@ -28,6 +29,7 @@
 #include <asm/byteorder.h>
 #include <asm/bootm.h>
 #include <asm/bootparam.h>
+#include <asm/global_data.h>
 #ifdef CONFIG_SYS_COREBOOT
 #include <asm/arch/timestamp.h>
 #endif
@@ -35,6 +37,8 @@
 #include <linux/ctype.h>
 #include <linux/libfdt.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /*
  * Memory lay-out:
  *
@@ -309,8 +313,13 @@
 	int bootproto = get_boot_protocol(hdr, false);
 
 	log_debug("Setup E820 entries\n");
-	setup_base->e820_entries = install_e820_map(
-		ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map);
+	if (ll_boot_init()) {
+		setup_base->e820_entries = install_e820_map(
+			ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map);
+	} else if (IS_ENABLED(CONFIG_COREBOOT_SYSINFO)) {
+		setup_base->e820_entries = cb_install_e820_map(
+			ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map);
+	}
 
 	if (bootproto == 0x0100) {
 		setup_base->screen_info.cl_magic = COMMAND_LINE_MAGIC;
diff --git a/board/BuR/brppt2/board.c b/board/BuR/brppt2/board.c
index e6eb403..ee006f0 100644
--- a/board/BuR/brppt2/board.c
+++ b/board/BuR/brppt2/board.c
@@ -540,7 +540,7 @@
 	spl_dram_init();
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 #endif /* CONFIG_SPL_BUILD */
diff --git a/board/Synology/common/Makefile b/board/Synology/common/Makefile
new file mode 100644
index 0000000..62354cc
--- /dev/null
+++ b/board/Synology/common/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2021 Phil Sutter <phil@nwl.cc>
+
+obj-y	+= legacy.o
diff --git a/board/Synology/common/legacy.c b/board/Synology/common/legacy.c
new file mode 100644
index 0000000..3c89e92
--- /dev/null
+++ b/board/Synology/common/legacy.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021
+ * Walter Schweizer <swwa@users.sourceforge.net>
+ * Phil Sutter <phil@nwl.cc>
+ */
+
+#include <config.h>
+#include <vsprintf.h>
+#include <env.h>
+#include <net.h>
+#include <asm/setup.h>
+
+#include "legacy.h"
+
+static unsigned int syno_board_id(void)
+{
+	switch (CONFIG_MACH_TYPE) {
+	case 527:
+		return SYNO_DS109_ID;
+	case 3036:
+		return SYNO_AXP_4BAY_2BAY;
+	default:
+		return 0;
+	}
+}
+
+static unsigned int usb_port_modes(void)
+{
+	unsigned int i, ret = 0;
+	char var[32], *val;
+
+	for (i = 0; i < USBPORT_MAX; i++) {
+		snprintf(var, 32, "usb%dMode", i);
+		val = env_get(var);
+
+		if (!val || strcasecmp(val, "host"))
+			continue;
+
+		ret |= 1 << i;
+	}
+	return ret;
+}
+
+/* Support old kernels */
+void setup_board_tags(struct tag **in_params)
+{
+	struct tag_mv_uboot *t;
+	struct tag *params;
+	int i;
+
+	debug("Synology board tags...\n");
+
+	params = *in_params;
+	t = (struct tag_mv_uboot *)&params->u;
+
+	t->uboot_version = VER_NUM | syno_board_id();
+	t->tclk = CONFIG_SYS_TCLK;
+	t->sysclk = CONFIG_SYS_TCLK * 2;
+	t->isusbhost = usb_port_modes();
+
+	for (i = 0; i < ETHADDR_MAX; i++) {
+		char addrvar[16], mtuvar[16];
+
+		sprintf(addrvar, i ? "eth%daddr" : "ethaddr", i);
+		sprintf(mtuvar, i ? "eth%dmtu" : "ethmtu", i);
+
+		eth_env_get_enetaddr(addrvar, t->macaddr[i]);
+		t->mtu[i] = env_get_ulong(mtuvar, 10, 0);
+	}
+
+	params->hdr.tag = ATAG_MV_UBOOT;
+	params->hdr.size = tag_size(tag_mv_uboot);
+	params = tag_next(params);
+	*in_params = params;
+}
diff --git a/board/Synology/common/legacy.h b/board/Synology/common/legacy.h
new file mode 100644
index 0000000..0a81432
--- /dev/null
+++ b/board/Synology/common/legacy.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2021
+ * Walter Schweizer <swwa@users.sourceforge.net>
+ * Phil Sutter <phil@nwl.cc>
+ */
+
+#ifndef __SYNO_LEGACY_H
+#define __SYNO_LEGACY_H
+
+/* Marvell uboot parameters */
+#define ATAG_MV_UBOOT 0x41000403
+#define VER_NUM       0x03040400 /* 3.4.4 */
+
+#define BOARD_ID_BASE 0x0
+#define SYNO_DS109_ID (BOARD_ID_BASE + 0x15)
+#define SYNO_AXP_4BAY_2BAY (0xf + 1)
+
+#define ETHADDR_MAX	4
+#define USBPORT_MAX	3
+
+struct tag_mv_uboot {
+	u32 uboot_version;
+	u32 tclk;
+	u32 sysclk;
+	u32 isusbhost;
+	u8 macaddr[ETHADDR_MAX][ETH_ALEN];
+	u16 mtu[ETHADDR_MAX];
+	u32 fw_image_base;
+	u32 fw_image_size;
+};
+
+#endif /* __SYNO_LEGACY_H */
diff --git a/board/Synology/ds109/ds109.c b/board/Synology/ds109/ds109.c
index eaac954..3914faa 100644
--- a/board/Synology/ds109/ds109.c
+++ b/board/Synology/ds109/ds109.c
@@ -114,38 +114,6 @@
 		     SOFTWARE_REBOOT);
 }
 
-/* Support old kernels */
-void setup_board_tags(struct tag **in_params)
-{
-	unsigned int boardId;
-	struct tag *params;
-	struct tag_mv_uboot *t;
-	int i;
-
-	printf("Synology board tags...");
-	params = *in_params;
-	t = (struct tag_mv_uboot *)&params->u;
-
-	t->uboot_version = VER_NUM;
-
-	boardId = SYNO_DS109_ID;
-	t->uboot_version |= boardId;
-
-	t->tclk = CONFIG_SYS_TCLK;
-	t->sysclk = CONFIG_SYS_TCLK*2;
-
-	t->isusbhost = 1;
-	for (i = 0; i < 4; i++)	{
-		memset(t->macaddr[i], 0, sizeof(t->macaddr[i]));
-		t->mtu[i] = 0;
-	}
-
-	params->hdr.tag = ATAG_MV_UBOOT;
-	params->hdr.size = tag_size(tag_mv_uboot);
-	params = tag_next(params);
-	*in_params = params;
-}
-
 #ifdef CONFIG_RESET_PHY_R
 /* Configure and enable MV88E1116 PHY */
 void reset_phy(void)
diff --git a/board/Synology/ds109/ds109.h b/board/Synology/ds109/ds109.h
index cc6ef99..0cf0525 100644
--- a/board/Synology/ds109/ds109.h
+++ b/board/Synology/ds109/ds109.h
@@ -23,21 +23,4 @@
 #define MV88E1116_RGMII_TXTM_CTRL	(1 << 4)
 #define MV88E1116_RGMII_RXTM_CTRL	(1 << 5)
 
-/* Marvell uboot parameters */
-#define ATAG_MV_UBOOT 0x41000403
-#define VER_NUM       0x03040400 /* 3.4.4 */
-#define BOARD_ID_BASE 0x0
-#define SYNO_DS109_ID (BOARD_ID_BASE+0x15)
-
-struct tag_mv_uboot {
-	u32 uboot_version;
-	u32 tclk;
-	u32 sysclk;
-	u32 isusbhost;
-	char macaddr[4][6];
-	u16 mtu[4];
-	u32 fw_image_base;
-	u32 fw_image_size;
-};
-
 #endif /* __DS109_H */
diff --git a/board/Synology/ds414/Kconfig b/board/Synology/ds414/Kconfig
new file mode 100644
index 0000000..4d30852
--- /dev/null
+++ b/board/Synology/ds414/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_DS414
+
+config SYS_BOARD
+	default "ds414"
+
+config SYS_VENDOR
+	default "Synology"
+
+config SYS_CONFIG_NAME
+	default "ds414"
+
+endif
diff --git a/board/Synology/ds414/cmd_syno.c b/board/Synology/ds414/cmd_syno.c
index a120c31..a62658a 100644
--- a/board/Synology/ds414/cmd_syno.c
+++ b/board/Synology/ds414/cmd_syno.c
@@ -17,12 +17,9 @@
 #include <asm/io.h>
 #include "../drivers/ddr/marvell/axp/ddr3_init.h"
 
-#define ETHADDR_MAX		4
-#define SYNO_SN_TAG		"SN="
-#define SYNO_CHKSUM_TAG		"CHK="
+#include "cmd_syno.h"
 
-
-static int do_syno_populate(int argc, char *const argv[])
+int do_syno_populate(int argc, char *const argv[])
 {
 	unsigned int bus = CONFIG_SF_DEFAULT_BUS;
 	unsigned int cs = CONFIG_SF_DEFAULT_CS;
@@ -57,7 +54,7 @@
 		goto out_unmap;
 	}
 
-	for (n = 0; n < ETHADDR_MAX; n++) {
+	for (n = 0; n < SYNO_ETHADDR_MAX; n++) {
 		char ethaddr[ETH_ALEN];
 		int i, sum = 0;
 		unsigned char csum = 0;
diff --git a/board/Synology/ds414/cmd_syno.h b/board/Synology/ds414/cmd_syno.h
new file mode 100644
index 0000000..42e435c
--- /dev/null
+++ b/board/Synology/ds414/cmd_syno.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Commands to deal with Synology specifics.
+ *
+ * Copyright (C) 2021  Phil Sutter <phil@nwl.cc>
+ */
+
+#ifndef _CMD_SYNO_H
+#define _CMD_SYNO_H
+
+#define SYNO_ETHADDR_MAX	4
+#define SYNO_SN_TAG		"SN="
+#define SYNO_CHKSUM_TAG		"CHK="
+
+int do_syno_populate(int argc, char *const argv[]);
+
+#endif /* _CMD_SYNO_H */
diff --git a/board/Synology/ds414/ds414.c b/board/Synology/ds414/ds414.c
index 9c4ce67..abe6f9e 100644
--- a/board/Synology/ds414/ds414.c
+++ b/board/Synology/ds414/ds414.c
@@ -18,6 +18,8 @@
 #include "../arch/arm/mach-mvebu/serdes/axp/high_speed_env_spec.h"
 #include "../arch/arm/mach-mvebu/serdes/axp/board_env_spec.h"
 
+#include "cmd_syno.h"
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* GPP and MPP settings as found in mvBoardEnvSpec.c of Synology's U-Boot */
@@ -179,6 +181,15 @@
 	return 0;
 }
 
+int misc_init_r(void)
+{
+	if (!env_get("ethaddr")) {
+		puts("Incomplete environment, populating from SPI flash\n");
+		do_syno_populate(0, NULL);
+	}
+	return 0;
+}
+
 int checkboard(void)
 {
 	puts("Board: DS414\n");
diff --git a/board/abilis/tb100/tb100.c b/board/abilis/tb100/tb100.c
index 52dc5b8..89e7322 100644
--- a/board/abilis/tb100/tb100.c
+++ b/board/abilis/tb100/tb100.c
@@ -9,7 +9,7 @@
 #include <netdev.h>
 #include <asm/io.h>
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 #define CRM_SWRESET	0xff101044
 	writel(0x1, (void *)CRM_SWRESET);
diff --git a/board/advantech/imx8qm_rom7720_a1/imx8qm_rom7720_a1.c b/board/advantech/imx8qm_rom7720_a1/imx8qm_rom7720_a1.c
index 8492e76..ace18b2 100644
--- a/board/advantech/imx8qm_rom7720_a1/imx8qm_rom7720_a1.c
+++ b/board/advantech/imx8qm_rom7720_a1/imx8qm_rom7720_a1.c
@@ -115,7 +115,7 @@
 /*
  * Board specific reset that is system reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	/* TODO */
 }
diff --git a/board/amlogic/beelink-s922x/beelink-s922x.c b/board/amlogic/beelink-s922x/beelink-s922x.c
index dc0d933..bb74426 100644
--- a/board/amlogic/beelink-s922x/beelink-s922x.c
+++ b/board/amlogic/beelink-s922x/beelink-s922x.c
@@ -28,8 +28,6 @@
 	    meson_get_soc_rev(tmp, sizeof(tmp)) > 0)
 		env_set("soc_rev", tmp);
 
-	meson_eth_init(PHY_INTERFACE_MODE_RGMII, 0);
-
 	if (!eth_env_get_enetaddr("ethaddr", mac_addr)) {
 		len = meson_sm_read_efuse(EFUSE_MAC_OFFSET,
 					  efuse_mac_addr, EFUSE_MAC_SIZE);
diff --git a/board/amlogic/odroid-n2/odroid-n2.c b/board/amlogic/odroid-n2/odroid-n2.c
index 863975e..88a60f3 100644
--- a/board/amlogic/odroid-n2/odroid-n2.c
+++ b/board/amlogic/odroid-n2/odroid-n2.c
@@ -115,8 +115,6 @@
 	    meson_get_soc_rev(tmp, sizeof(tmp)) > 0)
 		env_set("soc_rev", tmp);
 
-	meson_eth_init(PHY_INTERFACE_MODE_RGMII, 0);
-
 	if (!eth_env_get_enetaddr("ethaddr", mac_addr)) {
 		len = meson_sm_read_efuse(EFUSE_MAC_OFFSET,
 					  efuse_mac_addr, EFUSE_MAC_SIZE);
diff --git a/board/amlogic/p200/p200.c b/board/amlogic/p200/p200.c
index 8f1bf8b..7c432f9 100644
--- a/board/amlogic/p200/p200.c
+++ b/board/amlogic/p200/p200.c
@@ -25,8 +25,6 @@
 	char serial[EFUSE_SN_SIZE];
 	ssize_t len;
 
-	meson_eth_init(PHY_INTERFACE_MODE_RGMII, 0);
-
 	if (!eth_env_get_enetaddr("ethaddr", mac_addr)) {
 		len = meson_sm_read_efuse(EFUSE_MAC_OFFSET,
 					  mac_addr, EFUSE_MAC_SIZE);
diff --git a/board/amlogic/p201/p201.c b/board/amlogic/p201/p201.c
index 597bb71..7c432f9 100644
--- a/board/amlogic/p201/p201.c
+++ b/board/amlogic/p201/p201.c
@@ -25,8 +25,6 @@
 	char serial[EFUSE_SN_SIZE];
 	ssize_t len;
 
-	meson_eth_init(PHY_INTERFACE_MODE_RMII, 0);
-
 	if (!eth_env_get_enetaddr("ethaddr", mac_addr)) {
 		len = meson_sm_read_efuse(EFUSE_MAC_OFFSET,
 					  mac_addr, EFUSE_MAC_SIZE);
diff --git a/board/amlogic/p212/p212.c b/board/amlogic/p212/p212.c
index fbc49e9..fcef90b 100644
--- a/board/amlogic/p212/p212.c
+++ b/board/amlogic/p212/p212.c
@@ -26,9 +26,6 @@
 	char serial[EFUSE_SN_SIZE];
 	ssize_t len;
 
-	meson_eth_init(PHY_INTERFACE_MODE_RMII,
-		       MESON_USE_INTERNAL_RMII_PHY);
-
 	if (!eth_env_get_enetaddr("ethaddr", mac_addr)) {
 		len = meson_sm_read_efuse(EFUSE_MAC_OFFSET,
 					  mac_addr, EFUSE_MAC_SIZE);
diff --git a/board/amlogic/q200/q200.c b/board/amlogic/q200/q200.c
index 62e6fa3..3aa6d8f 100644
--- a/board/amlogic/q200/q200.c
+++ b/board/amlogic/q200/q200.c
@@ -26,8 +26,6 @@
 	char serial[EFUSE_SN_SIZE];
 	ssize_t len;
 
-	meson_eth_init(PHY_INTERFACE_MODE_RGMII, 0);
-
 	if (!eth_env_get_enetaddr("ethaddr", mac_addr)) {
 		len = meson_sm_read_efuse(EFUSE_MAC_OFFSET,
 					  mac_addr, EFUSE_MAC_SIZE);
diff --git a/board/amlogic/s400/s400.c b/board/amlogic/s400/s400.c
index b081942..06a9044 100644
--- a/board/amlogic/s400/s400.c
+++ b/board/amlogic/s400/s400.c
@@ -16,8 +16,6 @@
 
 int misc_init_r(void)
 {
-	meson_eth_init(PHY_INTERFACE_MODE_RGMII, 0);
-
 	meson_generate_serial_ethaddr();
 
 	return 0;
diff --git a/board/amlogic/sei510/sei510.c b/board/amlogic/sei510/sei510.c
index 5a5148e..bb188c2 100644
--- a/board/amlogic/sei510/sei510.c
+++ b/board/amlogic/sei510/sei510.c
@@ -18,9 +18,6 @@
 
 int misc_init_r(void)
 {
-	meson_eth_init(PHY_INTERFACE_MODE_RMII,
-		       MESON_USE_INTERNAL_RMII_PHY);
-
 	meson_generate_serial_ethaddr();
 
 	env_set("serial#", "AMLG12ASEI510");
diff --git a/board/amlogic/sei610/sei610.c b/board/amlogic/sei610/sei610.c
index 27dba93..6490bac 100644
--- a/board/amlogic/sei610/sei610.c
+++ b/board/amlogic/sei610/sei610.c
@@ -18,9 +18,6 @@
 
 int misc_init_r(void)
 {
-	meson_eth_init(PHY_INTERFACE_MODE_RMII,
-		       MESON_USE_INTERNAL_RMII_PHY);
-
 	meson_generate_serial_ethaddr();
 
 	env_set("serial#", "AMLG12ASEI610");
diff --git a/board/amlogic/u200/u200.c b/board/amlogic/u200/u200.c
index 373235d..06a9044 100644
--- a/board/amlogic/u200/u200.c
+++ b/board/amlogic/u200/u200.c
@@ -16,8 +16,7 @@
 
 int misc_init_r(void)
 {
-	meson_eth_init(PHY_INTERFACE_MODE_RMII,
-		       MESON_USE_INTERNAL_RMII_PHY);
+	meson_generate_serial_ethaddr();
 
 	return 0;
 }
diff --git a/board/amlogic/vim3/vim3.c b/board/amlogic/vim3/vim3.c
index 7b09617..6cd5f2e 100644
--- a/board/amlogic/vim3/vim3.c
+++ b/board/amlogic/vim3/vim3.c
@@ -149,8 +149,6 @@
 	char efuse_mac_addr[EFUSE_MAC_SIZE], tmp[3];
 	ssize_t len;
 
-	meson_eth_init(PHY_INTERFACE_MODE_RGMII, 0);
-
 	if (!eth_env_get_enetaddr("ethaddr", mac_addr)) {
 		len = meson_sm_read_efuse(EFUSE_MAC_OFFSET,
 					  efuse_mac_addr, EFUSE_MAC_SIZE);
diff --git a/board/amlogic/w400/w400.c b/board/amlogic/w400/w400.c
index 47a5171..4199198 100644
--- a/board/amlogic/w400/w400.c
+++ b/board/amlogic/w400/w400.c
@@ -14,7 +14,7 @@
 
 int misc_init_r(void)
 {
-	meson_eth_init(PHY_INTERFACE_MODE_RGMII, 0);
+	meson_generate_serial_ethaddr();
 
 	return 0;
 }
diff --git a/board/armltd/total_compute/total_compute.c b/board/armltd/total_compute/total_compute.c
index 01c65e4..b7eaab0 100644
--- a/board/armltd/total_compute/total_compute.c
+++ b/board/armltd/total_compute/total_compute.c
@@ -63,6 +63,6 @@
 }
 
 /* Nothing to be done here as handled by PSCI interface */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
diff --git a/board/armltd/vexpress/vexpress_common.c b/board/armltd/vexpress/vexpress_common.c
index df4cbd3..ba3278a 100644
--- a/board/armltd/vexpress/vexpress_common.c
+++ b/board/armltd/vexpress/vexpress_common.c
@@ -174,7 +174,7 @@
 }
 
 /* Use the ARM Watchdog System to cause reset */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE_MB, 0))
 		printf("Unable to reboot\n");
diff --git a/board/armltd/vexpress64/vexpress64.c b/board/armltd/vexpress64/vexpress64.c
index 9d29490..2e42602 100644
--- a/board/armltd/vexpress64/vexpress64.c
+++ b/board/armltd/vexpress64/vexpress64.c
@@ -143,7 +143,7 @@
 #endif
 
 /* Actual reset is done via PSCI. */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
diff --git a/board/atmark-techno/armadillo-800eva/armadillo-800eva.c b/board/atmark-techno/armadillo-800eva/armadillo-800eva.c
index 1bae283..c1c3dfd 100644
--- a/board/atmark-techno/armadillo-800eva/armadillo-800eva.c
+++ b/board/atmark-techno/armadillo-800eva/armadillo-800eva.c
@@ -322,6 +322,6 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
diff --git a/board/beacon/beacon-rzg2m/beacon-rzg2m.c b/board/beacon/beacon-rzg2m/beacon-rzg2m.c
index c343de5..0c7f8e5 100644
--- a/board/beacon/beacon-rzg2m/beacon-rzg2m.c
+++ b/board/beacon/beacon-rzg2m/beacon-rzg2m.c
@@ -47,7 +47,7 @@
 #define RST_CA57RESCNT	(RST_BASE + 0x40)
 #define RST_CODE	0xA5A5000F
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	writel(RST_CODE, RST_CA57RESCNT);
 }
diff --git a/board/bosch/shc/board.c b/board/bosch/shc/board.c
index bfce291..e893781 100644
--- a/board/bosch/shc/board.c
+++ b/board/bosch/shc/board.c
@@ -486,7 +486,7 @@
 		printf("Resetting ...\n");
 		writel(RESET_MASK, GPIO1_BASE + OMAP_GPIO_IRQSTATUS_SET_0);
 		disable_interrupts();
-		reset_cpu(0);
+		reset_cpu();
 		/*NOTREACHED*/
 	}
 }
diff --git a/board/broadcom/bcmns2/northstar2.c b/board/broadcom/bcmns2/northstar2.c
index 494e457..ee586d5 100644
--- a/board/broadcom/bcmns2/northstar2.c
+++ b/board/broadcom/bcmns2/northstar2.c
@@ -57,7 +57,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	psci_system_reset();
 }
diff --git a/board/broadcom/bcmns3/ns3.c b/board/broadcom/bcmns3/ns3.c
index 9d2df92..758a358 100644
--- a/board/broadcom/bcmns3/ns3.c
+++ b/board/broadcom/bcmns3/ns3.c
@@ -15,9 +15,6 @@
 #include <dt-bindings/memory/bcm-ns3-mc.h>
 #include <broadcom/chimp.h>
 
-/* Default reset-level = 3 and strap-val = 0 */
-#define L3_RESET	30
-
 #define BANK_OFFSET(bank)      ((u64)BCM_NS3_DDR_INFO_BASE + 8 + ((bank) * 16))
 
 /*
@@ -188,25 +185,10 @@
 	return BCM_NS3_MEM_END;
 }
 
-void reset_cpu(ulong level)
+void reset_cpu(void)
 {
-	u32 reset_level, strap_val;
-
-	/* Default reset type is L3 reset */
-	if (!level) {
-		/*
-		 * Encoding: U-Boot reset command expects decimal argument,
-		 * Boot strap val: Bits[3:0]
-		 * reset level: Bits[7:4]
-		 */
-		strap_val = L3_RESET % 10;
-		level = L3_RESET / 10;
-		reset_level = level % 10;
-		psci_system_reset2(reset_level, strap_val);
-	} else {
-		/* U-Boot cmd "reset" with any arg will trigger L1 reset */
-		psci_system_reset();
-	}
+	/* Perform a level 3 reset */
+	psci_system_reset2(3, 0);
 }
 
 #ifdef CONFIG_OF_BOARD_SETUP
diff --git a/board/broadcom/bcmstb/bcmstb.c b/board/broadcom/bcmstb/bcmstb.c
index f6bdf1f..ee0a341 100644
--- a/board/broadcom/bcmstb/bcmstb.c
+++ b/board/broadcom/bcmstb/bcmstb.c
@@ -43,7 +43,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong ignored)
+void reset_cpu(void)
 {
 }
 
diff --git a/board/cavium/thunderx/thunderx.c b/board/cavium/thunderx/thunderx.c
index b09f72c..a7dc5c6 100644
--- a/board/cavium/thunderx/thunderx.c
+++ b/board/cavium/thunderx/thunderx.c
@@ -110,7 +110,7 @@
 /*
  * Board specific reset that is system reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
diff --git a/board/compulab/cm_t335/spl.c b/board/compulab/cm_t335/spl.c
index 8662632..33264df 100644
--- a/board/compulab/cm_t335/spl.c
+++ b/board/compulab/cm_t335/spl.c
@@ -96,7 +96,7 @@
 		break;
 	default:
 		puts("Failed configuring DRAM, resetting...\n\n");
-		reset_cpu(0);
+		reset_cpu();
 	}
 	debug("%s: setting DRAM size to %ldM\n", __func__, size >> 20);
 	config_ddr(303, &ioregs, &ddr3_data,
diff --git a/board/coreboot/coreboot/coreboot.c b/board/coreboot/coreboot/coreboot.c
index 9aafb89..175d3ce 100644
--- a/board/coreboot/coreboot/coreboot.c
+++ b/board/coreboot/coreboot/coreboot.c
@@ -4,7 +4,7 @@
  */
 
 #include <common.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
 #include <asm/global_data.h>
 #include <init.h>
 #include <smbios.h>
diff --git a/board/cortina/presidio-asic/presidio.c b/board/cortina/presidio-asic/presidio.c
index 5c73522..f344622 100644
--- a/board/cortina/presidio-asic/presidio.c
+++ b/board/cortina/presidio-asic/presidio.c
@@ -115,7 +115,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	invoke_psci_fn_smc(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
 }
diff --git a/board/embest/mx6boards/mx6boards.c b/board/embest/mx6boards/mx6boards.c
index 65b3942..dda8502 100644
--- a/board/embest/mx6boards/mx6boards.c
+++ b/board/embest/mx6boards/mx6boards.c
@@ -31,8 +31,6 @@
 #include <asm/mach-imx/video.h>
 #include <i2c.h>
 #include <input.h>
-#include <mmc.h>
-#include <fsl_esdhc_imx.h>
 #include <miiphy.h>
 #include <netdev.h>
 #include <asm/arch/mxc_hdmi.h>
@@ -93,24 +91,6 @@
 }
 
 iomux_v3_cfg_t const enet_pads[] = {
-	MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
-	MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
-	/* GPIO16 -> AR8035 25MHz */
-	MX6_PAD_GPIO_16__ENET_REF_CLK | MUX_PAD_CTRL(NO_PAD_CTRL),
-	MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(NO_PAD_CTRL),
-	MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
-	MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
-	MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
-	MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
-	MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
-	/* AR8035 CLK_25M --> ENET_REF_CLK (V22) */
-	MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL_CLK),
-	MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
-	MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD),
-	MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD),
-	MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
-	MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
-	MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL_PD),
 	/* AR8035 PHY Reset */
 	MX6_PAD_EIM_D31__GPIO3_IO31 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD),
 	/* AR8035 PHY Interrupt */
@@ -150,141 +130,6 @@
 	return 0;
 }
 
-iomux_v3_cfg_t const usdhc2_pads[] = {
-	MX6_PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(USDHC_PAD_CLK_CTRL),
-	MX6_PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
-	MX6_PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
-	MX6_PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
-	MX6_PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
-	MX6_PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
-	MX6_PAD_GPIO_2__GPIO1_IO02 | MUX_PAD_CTRL(NO_PAD_CTRL), /* WP */
-	MX6_PAD_GPIO_4__GPIO1_IO04 | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
-};
-
-iomux_v3_cfg_t const usdhc3_pads[] = {
-	MX6_PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CLK_CTRL),
-	MX6_PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
-	MX6_PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
-	MX6_PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
-	MX6_PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
-	MX6_PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
-};
-
-iomux_v3_cfg_t const riotboard_usdhc3_pads[] = {
-	MX6_PAD_SD3_DAT4__GPIO7_IO01 | MUX_PAD_CTRL(NO_PAD_CTRL), /* WP */
-	MX6_PAD_SD3_DAT5__GPIO7_IO00 | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
-};
-
-iomux_v3_cfg_t const usdhc4_pads[] = {
-	MX6_PAD_SD4_CLK__SD4_CLK | MUX_PAD_CTRL(USDHC_PAD_CLK_CTRL),
-	MX6_PAD_SD4_CMD__SD4_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
-	MX6_PAD_SD4_DAT0__SD4_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
-	MX6_PAD_SD4_DAT1__SD4_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
-	MX6_PAD_SD4_DAT2__SD4_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
-	MX6_PAD_SD4_DAT3__SD4_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
-	/* eMMC RST */
-	MX6_PAD_NANDF_ALE__GPIO6_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),
-};
-
-#ifdef CONFIG_FSL_ESDHC_IMX
-struct fsl_esdhc_cfg usdhc_cfg[3] = {
-	{USDHC2_BASE_ADDR},
-	{USDHC3_BASE_ADDR},
-	{USDHC4_BASE_ADDR},
-};
-
-#define USDHC2_CD_GPIO	IMX_GPIO_NR(1, 4)
-#define USDHC3_CD_GPIO	IMX_GPIO_NR(7, 0)
-
-int board_mmc_getcd(struct mmc *mmc)
-{
-	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
-	int ret = 0;
-
-	switch (cfg->esdhc_base) {
-	case USDHC2_BASE_ADDR:
-		ret = !gpio_get_value(USDHC2_CD_GPIO);
-		break;
-	case USDHC3_BASE_ADDR:
-		if (board_type == BOARD_IS_RIOTBOARD)
-			ret = !gpio_get_value(USDHC3_CD_GPIO);
-		else if (board_type == BOARD_IS_MARSBOARD)
-			ret = 1; /* eMMC/uSDHC3 is always present */
-		break;
-	case USDHC4_BASE_ADDR:
-		ret = 1; /* eMMC/uSDHC4 is always present */
-		break;
-	}
-
-	return ret;
-}
-
-int board_mmc_init(struct bd_info *bis)
-{
-	int ret;
-	int i;
-
-	/*
-	 * According to the board_mmc_init() the following map is done:
-	 * (U-Boot device node)    (Physical Port)
-	 * ** RiOTboard :
-	 * mmc0                    SDCard slot (bottom)
-	 * mmc1                    uSDCard slot (top)
-	 * mmc2                    eMMC
-	 * ** MarSBoard :
-	 * mmc0                    uSDCard slot (bottom)
-	 * mmc1                    eMMC
-	 */
-	for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) {
-		switch (i) {
-		case 0:
-			imx_iomux_v3_setup_multiple_pads(
-				usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
-			gpio_direction_input(USDHC2_CD_GPIO);
-			usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
-			usdhc_cfg[0].max_bus_width = 4;
-			break;
-		case 1:
-			imx_iomux_v3_setup_multiple_pads(
-				usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
-			if (board_type == BOARD_IS_RIOTBOARD) {
-				imx_iomux_v3_setup_multiple_pads(
-					riotboard_usdhc3_pads,
-					ARRAY_SIZE(riotboard_usdhc3_pads));
-				gpio_direction_input(USDHC3_CD_GPIO);
-			} else {
-				gpio_direction_output(IMX_GPIO_NR(7, 8) , 0);
-				udelay(250);
-				gpio_set_value(IMX_GPIO_NR(7, 8), 1);
-			}
-			usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
-			usdhc_cfg[1].max_bus_width = 4;
-			break;
-		case 2:
-			imx_iomux_v3_setup_multiple_pads(
-				usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
-			usdhc_cfg[2].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
-			usdhc_cfg[2].max_bus_width = 4;
-			gpio_direction_output(IMX_GPIO_NR(6, 8) , 0);
-			udelay(250);
-			gpio_set_value(IMX_GPIO_NR(6, 8), 1);
-			break;
-		default:
-			printf("Warning: you configured more USDHC controllers"
-			       "(%d) then supported by the board (%d)\n",
-			       i + 1, CONFIG_SYS_FSL_USDHC_NUM);
-			return -EINVAL;
-		}
-
-		ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-#endif
-
 #ifdef CONFIG_MXC_SPI
 iomux_v3_cfg_t const ecspi1_pads[] = {
 	MX6_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
@@ -513,13 +358,6 @@
 	return 1;
 }
 
-int board_eth_init(struct bd_info *bis)
-{
-	setup_iomux_enet();
-
-	return cpu_eth_init(bis);
-}
-
 int board_early_init_f(void)
 {
 	u32 cputype = cpu_type(get_cpu_rev());
@@ -597,6 +435,7 @@
 	else if (board_type == BOARD_IS_RIOTBOARD)
 		add_board_boot_modes(marsboard_boot_modes);
 #endif
+	setup_iomux_enet();
 
 	return 0;
 }
diff --git a/board/freescale/imx8mm_evk/boot.cmd b/board/freescale/imx8mm_evk/boot.cmd
deleted file mode 100644
index fdfceec..0000000
--- a/board/freescale/imx8mm_evk/boot.cmd
+++ /dev/null
@@ -1,35 +0,0 @@
-setenv bootargs console=${console} root=${mmcroot};
-
-for boot_target in ${boot_targets};
-do
-        if test "${boot_target}" = "mmc1" ; then
-                if fatload mmc 1:${mmcpart} ${kernel_addr_r} ${image}; then
-                        if fatload mmc 1:${mmcpart} ${fdt_addr} ${fdt_file}; then
-                                echo Load image and .dtb from SD card(mmc1);
-                                booti ${kernel_addr_r} - ${fdt_addr};
-                                exit;
-                        fi
-                fi
-        fi
-
-        if test "${boot_target}" = "mmc2" ; then
-                if fatload mmc 2:${mmcpart} ${kernel_addr_r} ${image}; then
-                        if fatload mmc 2:${mmcpart} ${fdt_addr} ${fdt_file}; then
-                                echo Load image and .dtb from eMMC(mmc2);
-                                booti ${kernel_addr_r} - ${fdt_addr};
-                                exit;
-                        fi
-                fi
-        fi
-
-        if test "${boot_target}" = "dhcp" ; then
-                if dhcp ${kernel_addr_r} ${serverip}:${image}; then
-                        if dhcp ${fdt_addr} ${serverip}:${fdt_file}; then
-                                echo Load image and .dtb from net(dhcp);
-                                booti ${kernel_addr_r} - ${fdt_addr};
-                                exit;
-                        fi
-                fi
-        fi
-
-done
diff --git a/board/freescale/imx8mm_evk/imximage-8mm-lpddr4.cfg b/board/freescale/imx8mm_evk/imximage-8mm-lpddr4.cfg
new file mode 100644
index 0000000..b89092a
--- /dev/null
+++ b/board/freescale/imx8mm_evk/imximage-8mm-lpddr4.cfg
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2021 NXP
+ */
+
+#define __ASSEMBLY__
+
+BOOT_FROM	sd
+LOADER		mkimage.flash.mkimage	0x7E1000
diff --git a/board/freescale/imx8mm_evk/lpddr4_timing.c b/board/freescale/imx8mm_evk/lpddr4_timing.c
index 8e48b9d..4373ca6 100644
--- a/board/freescale/imx8mm_evk/lpddr4_timing.c
+++ b/board/freescale/imx8mm_evk/lpddr4_timing.c
@@ -1,129 +1,162 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright 2019 NXP
+ * Copyright 2018-2019 NXP
+ *
+ * Generated code from MX8M_DDR_tool
  */
 
 #include <linux/kernel.h>
-#include <common.h>
 #include <asm/arch/ddr.h>
-#include <asm/arch/lpddr4_define.h>
 
-struct dram_cfg_param lpddr4_ddrc_cfg[] = {
-	/* Start to config, default 3200mbps */
-	{ DDRC_DBG1(0),	0x00000001 },
-	{ DDRC_PWRCTL(0), 0x00000001 },
-	{ DDRC_MSTR(0),	0xa1080020 },
-	{ DDRC_RFSHTMG(0), 0x005b00d2 },
-	{ DDRC_INIT0(0), 0xC003061B },
-	{ DDRC_INIT1(0), 0x009D0000 },
-	{ DDRC_INIT3(0), 0x00D4002D },
-	{ DDRC_INIT4(0), (LPDDR4_MR3 << 16) | 0x0000 },
-	{ DDRC_INIT6(0), 0x0066004a },
-	{ DDRC_INIT7(0), 0x0006004a },
-
-	{ DDRC_DRAMTMG0(0), 0x1A201B22 },
-	{ DDRC_DRAMTMG1(0), 0x00060633 },
-	{ DDRC_DRAMTMG3(0), 0x00C0C000 },
-	{ DDRC_DRAMTMG4(0), 0x0F04080F },
-	{ DDRC_DRAMTMG5(0), 0x02040C0C },
-	{ DDRC_DRAMTMG6(0), 0x01010007 },
-	{ DDRC_DRAMTMG7(0), 0x00000401 },
-	{ DDRC_DRAMTMG12(0), 0x00020600 },
-	{ DDRC_DRAMTMG13(0), 0x0C100002 },
-	{ DDRC_DRAMTMG14(0), 0x000000E6 },
-	{ DDRC_DRAMTMG17(0), 0x00A00050 },
-
-	{ DDRC_ZQCTL0(0), 0x03200018 },
-	{ DDRC_ZQCTL1(0), 0x028061A8 },
-	{ DDRC_ZQCTL2(0), 0x00000000 },
-
-	{ DDRC_DFITMG0(0), 0x0497820A },
-	{ DDRC_DFITMG2(0), 0x0000170A },
-	{ DDRC_DRAMTMG2(0), 0x070E171a },
-	{ DDRC_DBICTL(0), 0x00000001 },
-
-	{ DDRC_DFITMG1(0), 0x00080303 },
-	{ DDRC_DFIUPD0(0), 0xE0400018 },
-	{ DDRC_DFIUPD1(0), 0x00DF00E4 },
-	{ DDRC_DFIUPD2(0), 0x80000000 },
-	{ DDRC_DFIMISC(0), 0x00000011 },
-
-	{ DDRC_DFIPHYMSTR(0), 0x00000000 },
-	{ DDRC_RANKCTL(0), 0x00000c99 },
-
-	/* address mapping */
-	{ DDRC_ADDRMAP0(0), 0x0000001f },
-	{ DDRC_ADDRMAP1(0), 0x00080808 },
-	{ DDRC_ADDRMAP2(0), 0x00000000 },
-	{ DDRC_ADDRMAP3(0), 0x00000000 },
-	{ DDRC_ADDRMAP4(0), 0x00001f1f },
-	{ DDRC_ADDRMAP5(0), 0x07070707 },
-	{ DDRC_ADDRMAP6(0), 0x07070707 },
-	{ DDRC_ADDRMAP7(0), 0x00000f0f },
+struct dram_cfg_param ddr_ddrc_cfg[] = {
+	/* Initialize DDRC registers */
+	{ 0x3d400304, 0x1 },
+	{ 0x3d400030, 0x1 },
+	{ 0x3d400000, 0xa1080020 },
+	{ 0x3d400020, 0x223 },
+	{ 0x3d400024, 0x16e3600 },
+	{ 0x3d400064, 0x5b00d2 },
+	{ 0x3d4000d0, 0xc00305ba },
+	{ 0x3d4000d4, 0x940000 },
+	{ 0x3d4000dc, 0xd4002d },
+	{ 0x3d4000e0, 0x310000 },
+	{ 0x3d4000e8, 0x66004d },
+	{ 0x3d4000ec, 0x16004d },
+	{ 0x3d400100, 0x191e1920 },
+	{ 0x3d400104, 0x60630 },
+	{ 0x3d40010c, 0xb0b000 },
+	{ 0x3d400110, 0xe04080e },
+	{ 0x3d400114, 0x2040c0c },
+	{ 0x3d400118, 0x1010007 },
+	{ 0x3d40011c, 0x401 },
+	{ 0x3d400130, 0x20600 },
+	{ 0x3d400134, 0xc100002 },
+	{ 0x3d400138, 0xd8 },
+	{ 0x3d400144, 0x96004b },
+	{ 0x3d400180, 0x2ee0017 },
+	{ 0x3d400184, 0x2605b8e },
+	{ 0x3d400188, 0x0 },
+	{ 0x3d400190, 0x497820a },
+	{ 0x3d400194, 0x80303 },
+	{ 0x3d4001b4, 0x170a },
+	{ 0x3d4001a0, 0xe0400018 },
+	{ 0x3d4001a4, 0xdf00e4 },
+	{ 0x3d4001a8, 0x80000000 },
+	{ 0x3d4001b0, 0x11 },
+	{ 0x3d4001c0, 0x1 },
+	{ 0x3d4001c4, 0x0 },
+	{ 0x3d4000f4, 0xc99 },
+	{ 0x3d400108, 0x70e1617 },
+	{ 0x3d400200, 0x1f },
+	{ 0x3d40020c, 0x0 },
+	{ 0x3d400210, 0x1f1f },
+	{ 0x3d400204, 0x80808 },
+	{ 0x3d400214, 0x7070707 },
+	{ 0x3d400218, 0x7070707 },
 
 	/* performance setting */
-	{ DDRC_SCHED(0), 0x29001701 },
-	{ DDRC_SCHED1(0), 0x0000002c },
-	{ DDRC_PERFHPR1(0), 0x04000030 },
-	{ DDRC_PERFLPR1(0), 0x900093e7 },
-	{ DDRC_PERFWR1(0), 0x20005574 },
-	{ DDRC_PCCFG(0), 0x00000111 },
-	{ DDRC_PCFGW_0(0), 0x000072ff },
-	{ DDRC_PCFGQOS0_0(0), 0x02100e07 },
-	{ DDRC_PCFGQOS1_0(0), 0x00620096 },
-	{ DDRC_PCFGWQOS0_0(0), 0x01100e07 },
-	{ DDRC_PCFGWQOS1_0(0), 0x00c8012c },
+	{ 0x3d400250, 0x29001701 },
+	{ 0x3d400254, 0x2c },
+	{ 0x3d40025c, 0x4000030 },
+	{ 0x3d400264, 0x900093e7 },
+	{ 0x3d40026c, 0x2005574 },
+	{ 0x3d400400, 0x111 },
+	{ 0x3d400408, 0x72ff },
+	{ 0x3d400494, 0x2100e07 },
+	{ 0x3d400498, 0x620096 },
+	{ 0x3d40049c, 0x1100e07 },
+	{ 0x3d4004a0, 0xc8012c },
 
-	/* frequency P1&P2 */
-	/* Frequency 1: 400mbps */
-	{ DDRC_FREQ1_DRAMTMG0(0), 0x0d0b010c },
-	{ DDRC_FREQ1_DRAMTMG1(0), 0x00030410 },
-	{ DDRC_FREQ1_DRAMTMG2(0), 0x0203090c },
-	{ DDRC_FREQ1_DRAMTMG3(0), 0x00505006 },
-	{ DDRC_FREQ1_DRAMTMG4(0), 0x05040305 },
-	{ DDRC_FREQ1_DRAMTMG5(0), 0x0d0e0504 },
-	{ DDRC_FREQ1_DRAMTMG6(0), 0x0a060004 },
-	{ DDRC_FREQ1_DRAMTMG7(0), 0x0000090e },
-	{ DDRC_FREQ1_DRAMTMG14(0), 0x00000032 },
-	{ DDRC_FREQ1_DRAMTMG15(0), 0x00000000 },
-	{ DDRC_FREQ1_DRAMTMG17(0), 0x0036001b },
-	{ DDRC_FREQ1_DERATEINT(0), 0x7e9fbeb1 },
-	{ DDRC_FREQ1_DFITMG0(0), 0x03818200 },
-	{ DDRC_FREQ1_DFITMG2(0), 0x00000000 },
-	{ DDRC_FREQ1_RFSHTMG(0), 0x000C001c },
-	{ DDRC_FREQ1_INIT3(0), 0x00840000 },
-	{ DDRC_FREQ1_INIT4(0), 0x00310000 },
-	{ DDRC_FREQ1_INIT6(0), 0x0066004a },
-	{ DDRC_FREQ1_INIT7(0), 0x0006004a },
+	/* P1: 400mts */
+	{ 0x3d402020, 0x21 },
+	{ 0x3d402024, 0x30d400 },
+	{ 0x3d402050, 0x20d040 },
+	{ 0x3d402064, 0xc001c },
+	{ 0x3d4020dc, 0x840000 },
+	{ 0x3d4020e0, 0x310000 },
+	{ 0x3d4020e8, 0x66004d },
+	{ 0x3d4020ec, 0x16004d },
+	{ 0x3d402100, 0xa040305 },
+	{ 0x3d402104, 0x30407 },
+	{ 0x3d402108, 0x203060b },
+	{ 0x3d40210c, 0x505000 },
+	{ 0x3d402110, 0x2040202 },
+	{ 0x3d402114, 0x2030202 },
+	{ 0x3d402118, 0x1010004 },
+	{ 0x3d40211c, 0x301 },
+	{ 0x3d402130, 0x20300 },
+	{ 0x3d402134, 0xa100002 },
+	{ 0x3d402138, 0x1d },
+	{ 0x3d402144, 0x14000a },
+	{ 0x3d402180, 0x640004 },
+	{ 0x3d402190, 0x3818200 },
+	{ 0x3d402194, 0x80303 },
+	{ 0x3d4021b4, 0x100 },
 
-	/* Frequency 2: 100mbps */
-	{ DDRC_FREQ2_DRAMTMG0(0), 0x0d0b010c },
-	{ DDRC_FREQ2_DRAMTMG1(0), 0x00030410 },
-	{ DDRC_FREQ2_DRAMTMG2(0), 0x0203090c },
-	{ DDRC_FREQ2_DRAMTMG3(0), 0x00505006 },
-	{ DDRC_FREQ2_DRAMTMG4(0), 0x05040305 },
-	{ DDRC_FREQ2_DRAMTMG5(0), 0x0d0e0504 },
-	{ DDRC_FREQ2_DRAMTMG6(0), 0x0a060004 },
-	{ DDRC_FREQ2_DRAMTMG7(0), 0x0000090e },
-	{ DDRC_FREQ2_DRAMTMG14(0), 0x00000032 },
-	{ DDRC_FREQ2_DRAMTMG17(0), 0x0036001b },
-	{ DDRC_FREQ2_DERATEINT(0), 0x7e9fbeb1 },
-	{ DDRC_FREQ2_DFITMG0(0), 0x03818200 },
-	{ DDRC_FREQ2_DFITMG2(0), 0x00000000 },
-	{ DDRC_FREQ2_RFSHTMG(0), 0x0003800c },
-	{ DDRC_FREQ2_RFSHTMG(0), 0x00030007 },
-	{ DDRC_FREQ2_INIT3(0), 0x00840000 },
-	{ DDRC_FREQ2_INIT4(0), 0x00310008 },
-	{ DDRC_FREQ2_INIT4(0), (LPDDR4_MR3 << 16) | 0x0000 },
-	{ DDRC_FREQ2_INIT6(0), 0x0066004a },
-	{ DDRC_FREQ2_INIT7(0), 0x0006004a },
+	/* p2: 100mts */
+	{ 0x3d403020, 0x21 },
+	{ 0x3d403024, 0xc3500 },
+	{ 0x3d403050, 0x20d040 },
+	{ 0x3d403064, 0x30007 },
+	{ 0x3d4030dc, 0x840000 },
+	{ 0x3d4030e0, 0x310000 },
+	{ 0x3d4030e8, 0x66004d },
+	{ 0x3d4030ec, 0x16004d },
+	{ 0x3d403100, 0xa010102 },
+	{ 0x3d403104, 0x30404 },
+	{ 0x3d403108, 0x203060b },
+	{ 0x3d40310c, 0x505000 },
+	{ 0x3d403110, 0x2040202 },
+	{ 0x3d403114, 0x2030202 },
+	{ 0x3d403118, 0x1010004 },
+	{ 0x3d40311c, 0x301 },
+	{ 0x3d403130, 0x20300 },
+	{ 0x3d403134, 0xa100002 },
+	{ 0x3d403138, 0x8 },
+	{ 0x3d403144, 0x50003 },
+	{ 0x3d403180, 0x190004 },
+	{ 0x3d403190, 0x3818200 },
+	{ 0x3d403194, 0x80303 },
+	{ 0x3d4031b4, 0x100 },
 
-	/* boot start point */
-	{ DDRC_MSTR2(0), 0x2 }, //DDRC_MSTR2
+	/* default boot point */
+	{ 0x3d400028, 0x0 },
 };
 
 /* PHY Initialize Configuration */
-struct dram_cfg_param lpddr4_ddrphy_cfg[] = {
+struct dram_cfg_param ddr_ddrphy_cfg[] = {
+	{ 0x100a0, 0x0 },
+	{ 0x100a1, 0x1 },
+	{ 0x100a2, 0x2 },
+	{ 0x100a3, 0x3 },
+	{ 0x100a4, 0x4 },
+	{ 0x100a5, 0x5 },
+	{ 0x100a6, 0x6 },
+	{ 0x100a7, 0x7 },
+	{ 0x110a0, 0x0 },
+	{ 0x110a1, 0x1 },
+	{ 0x110a2, 0x3 },
+	{ 0x110a3, 0x4 },
+	{ 0x110a4, 0x5 },
+	{ 0x110a5, 0x2 },
+	{ 0x110a6, 0x7 },
+	{ 0x110a7, 0x6 },
+	{ 0x120a0, 0x0 },
+	{ 0x120a1, 0x1 },
+	{ 0x120a2, 0x3 },
+	{ 0x120a3, 0x2 },
+	{ 0x120a4, 0x5 },
+	{ 0x120a5, 0x4 },
+	{ 0x120a6, 0x7 },
+	{ 0x120a7, 0x6 },
+	{ 0x130a0, 0x0 },
+	{ 0x130a1, 0x1 },
+	{ 0x130a2, 0x2 },
+	{ 0x130a3, 0x3 },
+	{ 0x130a4, 0x4 },
+	{ 0x130a5, 0x5 },
+	{ 0x130a6, 0x6 },
+	{ 0x130a7, 0x7 },
 	{ 0x1005f, 0x1ff },
 	{ 0x1015f, 0x1ff },
 	{ 0x1105f, 0x1ff },
@@ -132,7 +165,6 @@
 	{ 0x1215f, 0x1ff },
 	{ 0x1305f, 0x1ff },
 	{ 0x1315f, 0x1ff },
-
 	{ 0x11005f, 0x1ff },
 	{ 0x11015f, 0x1ff },
 	{ 0x11105f, 0x1ff },
@@ -141,7 +173,6 @@
 	{ 0x11215f, 0x1ff },
 	{ 0x11305f, 0x1ff },
 	{ 0x11315f, 0x1ff },
-
 	{ 0x21005f, 0x1ff },
 	{ 0x21015f, 0x1ff },
 	{ 0x21105f, 0x1ff },
@@ -150,7 +181,6 @@
 	{ 0x21215f, 0x1ff },
 	{ 0x21305f, 0x1ff },
 	{ 0x21315f, 0x1ff },
-
 	{ 0x55, 0x1ff },
 	{ 0x1055, 0x1ff },
 	{ 0x2055, 0x1ff },
@@ -161,32 +191,24 @@
 	{ 0x7055, 0x1ff },
 	{ 0x8055, 0x1ff },
 	{ 0x9055, 0x1ff },
-
 	{ 0x200c5, 0x19 },
 	{ 0x1200c5, 0x7 },
 	{ 0x2200c5, 0x7 },
-
 	{ 0x2002e, 0x2 },
 	{ 0x12002e, 0x2 },
 	{ 0x22002e, 0x2 },
-
 	{ 0x90204, 0x0 },
 	{ 0x190204, 0x0 },
 	{ 0x290204, 0x0 },
-
-	{ 0x20024, 0xab },
+	{ 0x20024, 0x1ab },
 	{ 0x2003a, 0x0 },
-
-	{ 0x120024, 0xab },
+	{ 0x120024, 0x1ab },
 	{ 0x2003a, 0x0 },
-
-	{ 0x220024, 0xab },
+	{ 0x220024, 0x1ab },
 	{ 0x2003a, 0x0 },
-
 	{ 0x20056, 0x3 },
 	{ 0x120056, 0xa },
 	{ 0x220056, 0xa },
-
 	{ 0x1004d, 0xe00 },
 	{ 0x1014d, 0xe00 },
 	{ 0x1104d, 0xe00 },
@@ -195,7 +217,6 @@
 	{ 0x1214d, 0xe00 },
 	{ 0x1304d, 0xe00 },
 	{ 0x1314d, 0xe00 },
-
 	{ 0x11004d, 0xe00 },
 	{ 0x11014d, 0xe00 },
 	{ 0x11104d, 0xe00 },
@@ -204,7 +225,6 @@
 	{ 0x11214d, 0xe00 },
 	{ 0x11304d, 0xe00 },
 	{ 0x11314d, 0xe00 },
-
 	{ 0x21004d, 0xe00 },
 	{ 0x21014d, 0xe00 },
 	{ 0x21104d, 0xe00 },
@@ -213,34 +233,30 @@
 	{ 0x21214d, 0xe00 },
 	{ 0x21304d, 0xe00 },
 	{ 0x21314d, 0xe00 },
-
-	{ 0x10049, 0xfbe },
-	{ 0x10149, 0xfbe },
-	{ 0x11049, 0xfbe },
-	{ 0x11149, 0xfbe },
-	{ 0x12049, 0xfbe },
-	{ 0x12149, 0xfbe },
-	{ 0x13049, 0xfbe },
-	{ 0x13149, 0xfbe },
-
-	{ 0x110049, 0xfbe },
-	{ 0x110149, 0xfbe },
-	{ 0x111049, 0xfbe },
-	{ 0x111149, 0xfbe },
-	{ 0x112049, 0xfbe },
-	{ 0x112149, 0xfbe },
-	{ 0x113049, 0xfbe },
-	{ 0x113149, 0xfbe },
-
-	{ 0x210049, 0xfbe },
-	{ 0x210149, 0xfbe },
-	{ 0x211049, 0xfbe },
-	{ 0x211149, 0xfbe },
-	{ 0x212049, 0xfbe },
-	{ 0x212149, 0xfbe },
-	{ 0x213049, 0xfbe },
-	{ 0x213149, 0xfbe },
-
+	{ 0x10049, 0xeba },
+	{ 0x10149, 0xeba },
+	{ 0x11049, 0xeba },
+	{ 0x11149, 0xeba },
+	{ 0x12049, 0xeba },
+	{ 0x12149, 0xeba },
+	{ 0x13049, 0xeba },
+	{ 0x13149, 0xeba },
+	{ 0x110049, 0xeba },
+	{ 0x110149, 0xeba },
+	{ 0x111049, 0xeba },
+	{ 0x111149, 0xeba },
+	{ 0x112049, 0xeba },
+	{ 0x112149, 0xeba },
+	{ 0x113049, 0xeba },
+	{ 0x113149, 0xeba },
+	{ 0x210049, 0xeba },
+	{ 0x210149, 0xeba },
+	{ 0x211049, 0xeba },
+	{ 0x211149, 0xeba },
+	{ 0x212049, 0xeba },
+	{ 0x212149, 0xeba },
+	{ 0x213049, 0xeba },
+	{ 0x213149, 0xeba },
 	{ 0x43, 0x63 },
 	{ 0x1043, 0x63 },
 	{ 0x2043, 0x63 },
@@ -251,7 +267,6 @@
 	{ 0x7043, 0x63 },
 	{ 0x8043, 0x63 },
 	{ 0x9043, 0x63 },
-
 	{ 0x20018, 0x3 },
 	{ 0x20075, 0x4 },
 	{ 0x20050, 0x0 },
@@ -259,8 +274,7 @@
 	{ 0x120008, 0x64 },
 	{ 0x220008, 0x19 },
 	{ 0x20088, 0x9 },
-
-	{ 0x200b2, 0x1d4 },
+	{ 0x200b2, 0xdc },
 	{ 0x10043, 0x5a1 },
 	{ 0x10143, 0x5a1 },
 	{ 0x11043, 0x5a1 },
@@ -269,7 +283,6 @@
 	{ 0x12143, 0x5a1 },
 	{ 0x13043, 0x5a1 },
 	{ 0x13143, 0x5a1 },
-
 	{ 0x1200b2, 0xdc },
 	{ 0x110043, 0x5a1 },
 	{ 0x110143, 0x5a1 },
@@ -279,7 +292,6 @@
 	{ 0x112143, 0x5a1 },
 	{ 0x113043, 0x5a1 },
 	{ 0x113143, 0x5a1 },
-
 	{ 0x2200b2, 0xdc },
 	{ 0x210043, 0x5a1 },
 	{ 0x210143, 0x5a1 },
@@ -289,15 +301,12 @@
 	{ 0x212143, 0x5a1 },
 	{ 0x213043, 0x5a1 },
 	{ 0x213143, 0x5a1 },
-
 	{ 0x200fa, 0x1 },
 	{ 0x1200fa, 0x1 },
 	{ 0x2200fa, 0x1 },
-
 	{ 0x20019, 0x1 },
 	{ 0x120019, 0x1 },
 	{ 0x220019, 0x1 },
-
 	{ 0x200f0, 0x660 },
 	{ 0x200f1, 0x0 },
 	{ 0x200f2, 0x4444 },
@@ -306,21 +315,20 @@
 	{ 0x200f5, 0x0 },
 	{ 0x200f6, 0x0 },
 	{ 0x200f7, 0xf000 },
-
 	{ 0x20025, 0x0 },
-	{ 0x2002d, LPDDR4_PHY_DMIPinPresent },
-	{ 0x12002d, LPDDR4_PHY_DMIPinPresent },
-	{ 0x22002d, LPDDR4_PHY_DMIPinPresent },
+	{ 0x2002d, 0x0 },
+	{ 0x12002d, 0x0 },
+	{ 0x22002d, 0x0 },
 	{ 0x200c7, 0x21 },
-	{ 0x200ca, 0x24 },
 	{ 0x1200c7, 0x21 },
-	{ 0x1200ca, 0x24 },
 	{ 0x2200c7, 0x21 },
+	{ 0x200ca, 0x24 },
+	{ 0x1200ca, 0x24 },
 	{ 0x2200ca, 0x24 },
 };
 
 /* ddr phy trained csr */
-struct dram_cfg_param lpddr4_ddrphy_trained_csr[] = {
+struct dram_cfg_param ddr_ddrphy_trained_csr[] = {
 	{ 0x200b2, 0x0 },
 	{ 0x1200b2, 0x0 },
 	{ 0x2200b2, 0x0 },
@@ -1041,309 +1049,164 @@
 	{ 0x13730, 0x0 },
 	{ 0x13830, 0x0 },
 };
-
 /* P0 message block paremeter for training firmware */
-struct dram_cfg_param lpddr4_fsp0_cfg[] = {
+struct dram_cfg_param ddr_fsp0_cfg[] = {
 	{ 0xd0000, 0x0 },
-	{ 0x54000, 0x0 },
-	{ 0x54001, 0x0 },
-	{ 0x54002, 0x0 },
 	{ 0x54003, 0xbb8 },
 	{ 0x54004, 0x2 },
-	{ 0x54005, ((LPDDR4_PHY_RON << 8) | LPDDR4_PHY_RTT) },//PHY Ron/Rtt
-	{ 0x54006, LPDDR4_PHY_VREF_VALUE },
-	{ 0x54007, 0x0 },
+	{ 0x54005, 0x2228 },
+	{ 0x54006, 0x11 },
 	{ 0x54008, 0x131f },
 	{ 0x54009, 0xc8 },
-	{ 0x5400a, 0x0 },
 	{ 0x5400b, 0x2 },
-	{ 0x5400c, 0x0 },
-	{ 0x5400d, 0x0 },
-	{ 0x5400e, 0x0 },
-	{ 0x5400f, 0x0 },
-	{ 0x54010, 0x0 },
-	{ 0x54011, 0x0 },
-	{ 0x54012, (LPDDR4_CS << 8) | (0x110 & 0xff) },
-	{ 0x54013, 0x0 },
-	{ 0x54014, 0x0 },
-	{ 0x54015, 0x0 },
-	{ 0x54016, 0x0 },
-	{ 0x54017, 0x0 },
-	{ 0x54018, 0x0 },
+	{ 0x54012, 0x110 },
 	{ 0x54019, 0x2dd4 },
-	{ 0x5401a, (0x31 & 0xff00) | LPDDR4_MR3 },
+	{ 0x5401a, 0x31 },
 	{ 0x5401b, 0x4d66 },
-	{ 0x5401c, 0x4d08 },
-	{ 0x5401d, 0x0 },
-	{ 0x5401e, LPDDR4_MR22_RANK0/*0x16*/ },
+	{ 0x5401c, 0x4d00 },
+	{ 0x5401e, 0x16 },
 	{ 0x5401f, 0x2dd4 },
-	{ 0x54020, (0x31 & 0xff00) | LPDDR4_MR3 },
+	{ 0x54020, 0x31 },
 	{ 0x54021, 0x4d66 },
-	{ 0x54022, 0x4d08 },
-	{ 0x54023, 0x0 },
-	{ 0x54024, LPDDR4_MR22_RANK1/*0x16*/ },
-	{ 0x54025, 0x0 },
-	{ 0x54026, 0x0 },
-	{ 0x54027, 0x0 },
-	{ 0x54028, 0x0 },
-	{ 0x54029, 0x0 },
-	{ 0x5402a, 0x0 },
+	{ 0x54022, 0x4d00 },
+	{ 0x54024, 0x16 },
 	{ 0x5402b, 0x1000 },
-	{ 0x5402c, LPDDR4_CS },
-	{ 0x5402d, 0x0 },
-	{ 0x5402e, 0x0 },
-	{ 0x5402f, 0x0 },
-	{ 0x54030, 0x0 },
-	{ 0x54031, 0x0 },
+	{ 0x5402c, 0x1 },
 	{ 0x54032, 0xd400 },
-	{ 0x54033, (LPDDR4_MR3 << 8) | (0x312d & 0xff) },
+	{ 0x54033, 0x312d },
 	{ 0x54034, 0x6600 },
-	{ 0x54035, 0x84d },
+	{ 0x54035, 0x4d },
 	{ 0x54036, 0x4d },
-	{ 0x54037, (LPDDR4_MR22_RANK0 << 8)/*0x1600*/ },
+	{ 0x54037, 0x1600 },
 	{ 0x54038, 0xd400 },
-	{ 0x54039, (LPDDR4_MR3 << 8) | (0x312d & 0xff) },
+	{ 0x54039, 0x312d },
 	{ 0x5403a, 0x6600 },
-	{ 0x5403b, 0x84d },
+	{ 0x5403b, 0x4d },
 	{ 0x5403c, 0x4d },
-	{ 0x5403d, (LPDDR4_MR22_RANK1 << 8)/*0x1600*/ },
-	{ 0x5403e, 0x0 },
-	{ 0x5403f, 0x0 },
-	{ 0x54040, 0x0 },
-	{ 0x54041, 0x0 },
-	{ 0x54042, 0x0 },
-	{ 0x54043, 0x0 },
-	{ 0x54044, 0x0 },
+	{ 0x5403d, 0x1600 },
 	{ 0xd0000, 0x1 },
 };
 
 /* P1 message block paremeter for training firmware */
-struct dram_cfg_param lpddr4_fsp1_cfg[] = {
+struct dram_cfg_param ddr_fsp1_cfg[] = {
 	{ 0xd0000, 0x0 },
-	{ 0x54000, 0x0 },
-	{ 0x54001, 0x0 },
 	{ 0x54002, 0x101 },
 	{ 0x54003, 0x190 },
 	{ 0x54004, 0x2 },
-	{ 0x54005, ((LPDDR4_PHY_RON << 8) | LPDDR4_PHY_RTT) },/* PHY Ron/Rtt */
-	{ 0x54006, LPDDR4_PHY_VREF_VALUE },
-	{ 0x54007, 0x0 },
+	{ 0x54005, 0x2228 },
+	{ 0x54006, 0x11 },
 	{ 0x54008, 0x121f },
 	{ 0x54009, 0xc8 },
-	{ 0x5400a, 0x0 },
 	{ 0x5400b, 0x2 },
-	{ 0x5400c, 0x0 },
-	{ 0x5400d, 0x0 },
-	{ 0x5400e, 0x0 },
-	{ 0x5400f, 0x0 },
-	{ 0x54010, 0x0 },
-	{ 0x54011, 0x0 },
-	{ 0x54012, (LPDDR4_CS << 8) | (0x110 & 0xff) },
-	{ 0x54013, 0x0 },
-	{ 0x54014, 0x0 },
-	{ 0x54015, 0x0 },
-	{ 0x54016, 0x0 },
-	{ 0x54017, 0x0 },
-	{ 0x54018, 0x0 },
+	{ 0x54012, 0x110 },
 	{ 0x54019, 0x84 },
-	{ 0x5401a, (0x31 & 0xff00) | LPDDR4_MR3 },
+	{ 0x5401a, 0x31 },
 	{ 0x5401b, 0x4d66 },
-	{ 0x5401c, 0x4d08 },
-	{ 0x5401d, 0x0 },
-	{ 0x5401e, LPDDR4_MR22_RANK0/*0x16*/ },
+	{ 0x5401c, 0x4d00 },
+	{ 0x5401e, 0x16 },
 	{ 0x5401f, 0x84 },
-	{ 0x54020, (0x31 & 0xff00) | LPDDR4_MR3 },
+	{ 0x54020, 0x31 },
 	{ 0x54021, 0x4d66 },
-	{ 0x54022, 0x4d08 },
-	{ 0x54023, 0x0 },
-	{ 0x54024, LPDDR4_MR22_RANK1/*0x16*/ },
-	{ 0x54025, 0x0 },
-	{ 0x54026, 0x0 },
-	{ 0x54027, 0x0 },
-	{ 0x54028, 0x0 },
-	{ 0x54029, 0x0 },
-	{ 0x5402a, 0x0 },
+	{ 0x54022, 0x4d00 },
+	{ 0x54024, 0x16 },
 	{ 0x5402b, 0x1000 },
-	{ 0x5402c, LPDDR4_CS },
-	{ 0x5402d, 0x0 },
-	{ 0x5402e, 0x0 },
-	{ 0x5402f, 0x0 },
-	{ 0x54030, 0x0 },
-	{ 0x54031, 0x0 },
+	{ 0x5402c, 0x1 },
 	{ 0x54032, 0x8400 },
-	{ 0x54033, (LPDDR4_MR3 << 8) | (0x3100 & 0xff) },
+	{ 0x54033, 0x3100 },
 	{ 0x54034, 0x6600 },
-	{ 0x54035, 0x84d },
+	{ 0x54035, 0x4d },
 	{ 0x54036, 0x4d },
-	{ 0x54037, (LPDDR4_MR22_RANK0 << 8)/*0x1600*/ },
+	{ 0x54037, 0x1600 },
 	{ 0x54038, 0x8400 },
-	{ 0x54039, (LPDDR4_MR3 << 8) | (0x3100 & 0xff) },
+	{ 0x54039, 0x3100 },
 	{ 0x5403a, 0x6600 },
-	{ 0x5403b, 0x84d },
+	{ 0x5403b, 0x4d },
 	{ 0x5403c, 0x4d },
-	{ 0x5403d, (LPDDR4_MR22_RANK1 << 8)/*0x1600*/ },
-	{ 0x5403e, 0x0 },
-	{ 0x5403f, 0x0 },
-	{ 0x54040, 0x0 },
-	{ 0x54041, 0x0 },
-	{ 0x54042, 0x0 },
-	{ 0x54043, 0x0 },
-	{ 0x54044, 0x0 },
+	{ 0x5403d, 0x1600 },
 	{ 0xd0000, 0x1 },
 };
 
-/* P1 message block paremeter for training firmware */
-struct dram_cfg_param lpddr4_fsp2_cfg[] = {
+/* P2 message block paremeter for training firmware */
+struct dram_cfg_param ddr_fsp2_cfg[] = {
 	{ 0xd0000, 0x0 },
-	{ 0x54000, 0x0 },
-	{ 0x54001, 0x0 },
 	{ 0x54002, 0x102 },
 	{ 0x54003, 0x64 },
 	{ 0x54004, 0x2 },
-	{ 0x54005, ((LPDDR4_PHY_RON << 8) | LPDDR4_PHY_RTT) },//PHY Ron/Rtt
-	{ 0x54006, LPDDR4_PHY_VREF_VALUE },
-	{ 0x54007, 0x0 },
+	{ 0x54005, 0x2228 },
+	{ 0x54006, 0x11 },
 	{ 0x54008, 0x121f },
 	{ 0x54009, 0xc8 },
-	{ 0x5400a, 0x0 },
 	{ 0x5400b, 0x2 },
-	{ 0x5400c, 0x0 },
-	{ 0x5400d, 0x0 },
-	{ 0x5400e, 0x0 },
-	{ 0x5400f, 0x0 },
-	{ 0x54010, 0x0 },
-	{ 0x54011, 0x0 },
-	{ 0x54012, (LPDDR4_CS << 8) | (0x110 & 0xff) },
-	{ 0x54013, 0x0 },
-	{ 0x54014, 0x0 },
-	{ 0x54015, 0x0 },
-	{ 0x54016, 0x0 },
-	{ 0x54017, 0x0 },
-	{ 0x54018, 0x0 },
+	{ 0x54012, 0x110 },
 	{ 0x54019, 0x84 },
-	{ 0x5401a, (0x31 & 0xff00) | LPDDR4_MR3 },
+	{ 0x5401a, 0x31 },
 	{ 0x5401b, 0x4d66 },
-	{ 0x5401c, 0x4d08 },
-	{ 0x5401d, 0x0 },
-	{ 0x5401e, LPDDR4_MR22_RANK0/*0x16*/ },
+	{ 0x5401c, 0x4d00 },
+	{ 0x5401e, 0x16 },
 	{ 0x5401f, 0x84 },
-	{ 0x54020, (0x31 & 0xff00) | LPDDR4_MR3 },
+	{ 0x54020, 0x31 },
 	{ 0x54021, 0x4d66 },
-	{ 0x54022, 0x4d08 },
-	{ 0x54023, 0x0 },
-	{ 0x54024, LPDDR4_MR22_RANK1/*0x16*/ },
-	{ 0x54025, 0x0 },
-	{ 0x54026, 0x0 },
-	{ 0x54027, 0x0 },
-	{ 0x54028, 0x0 },
-	{ 0x54029, 0x0 },
-	{ 0x5402a, 0x0 },
+	{ 0x54022, 0x4d00 },
+	{ 0x54024, 0x16 },
 	{ 0x5402b, 0x1000 },
-	{ 0x5402c, LPDDR4_CS },
-	{ 0x5402d, 0x0 },
-	{ 0x5402e, 0x0 },
-	{ 0x5402f, 0x0 },
-	{ 0x54030, 0x0 },
-	{ 0x54031, 0x0 },
+	{ 0x5402c, 0x1 },
 	{ 0x54032, 0x8400 },
-	{ 0x54033, (LPDDR4_MR3 << 8) | (0x3100 & 0xff) },
+	{ 0x54033, 0x3100 },
 	{ 0x54034, 0x6600 },
-	{ 0x54035, 0x84d },
+	{ 0x54035, 0x4d },
 	{ 0x54036, 0x4d },
-	{ 0x54037, (LPDDR4_MR22_RANK0 << 8)/*0x1600*/ },
+	{ 0x54037, 0x1600 },
 	{ 0x54038, 0x8400 },
-	{ 0x54039, (LPDDR4_MR3 << 8) | (0x3100 & 0xff) },
+	{ 0x54039, 0x3100 },
 	{ 0x5403a, 0x6600 },
-	{ 0x5403b, 0x84d },
+	{ 0x5403b, 0x4d },
 	{ 0x5403c, 0x4d },
-	{ 0x5403d, (LPDDR4_MR22_RANK1 << 8)/*0x1600*/ },
-	{ 0x5403e, 0x0 },
-	{ 0x5403f, 0x0 },
-	{ 0x54040, 0x0 },
-	{ 0x54041, 0x0 },
-	{ 0x54042, 0x0 },
-	{ 0x54043, 0x0 },
-	{ 0x54044, 0x0 },
+	{ 0x5403d, 0x1600 },
 	{ 0xd0000, 0x1 },
 };
 
 /* P0 2D message block paremeter for training firmware */
-struct dram_cfg_param lpddr4_fsp0_2d_cfg[] = {
+struct dram_cfg_param ddr_fsp0_2d_cfg[] = {
 	{ 0xd0000, 0x0 },
-	{ 0x54000, 0x0 },
-	{ 0x54001, 0x0 },
-	{ 0x54002, 0x0 },
 	{ 0x54003, 0xbb8 },
 	{ 0x54004, 0x2 },
-	{ 0x54005, ((LPDDR4_PHY_RON << 8) | LPDDR4_PHY_RTT) },//PHY Ron/Rtt
-	{ 0x54006, LPDDR4_PHY_VREF_VALUE },
-	{ 0x54007, 0x0 },
+	{ 0x54005, 0x2228 },
+	{ 0x54006, 0x11 },
 	{ 0x54008, 0x61 },
 	{ 0x54009, 0xc8 },
-	{ 0x5400a, 0x0 },
 	{ 0x5400b, 0x2 },
-	{ 0x5400c, 0x0 },
-	{ 0x5400d, 0x0 },
-	{ 0x5400e, 0x0 },
 	{ 0x5400f, 0x100 },
 	{ 0x54010, 0x1f7f },
-	{ 0x54011, 0x0 },
-	{ 0x54012, (LPDDR4_CS << 8) | (0x110 & 0xff) },
-	{ 0x54013, 0x0 },
-	{ 0x54014, 0x0 },
-	{ 0x54015, 0x0 },
-	{ 0x54016, 0x0 },
-	{ 0x54017, 0x0 },
-	{ 0x54018, 0x0 },
+	{ 0x54012, 0x110 },
 	{ 0x54019, 0x2dd4 },
-	{ 0x5401a, (0x31 & 0xff00) | LPDDR4_MR3 },
+	{ 0x5401a, 0x31 },
 	{ 0x5401b, 0x4d66 },
-	{ 0x5401c, 0x4d08 },
-	{ 0x5401d, 0x0 },
-	{ 0x5401e, LPDDR4_MR22_RANK0/*0x16*/ },
+	{ 0x5401c, 0x4d00 },
+	{ 0x5401e, 0x16 },
 	{ 0x5401f, 0x2dd4 },
-	{ 0x54020, (0x31 & 0xff00) | LPDDR4_MR3 },
+	{ 0x54020, 0x31 },
 	{ 0x54021, 0x4d66 },
-	{ 0x54022, 0x4d08 },
-	{ 0x54023, 0x0 },
-	{ 0x54024, LPDDR4_MR22_RANK1/*0x16*/ },
-	{ 0x54025, 0x0 },
-	{ 0x54026, 0x0 },
-	{ 0x54027, 0x0 },
-	{ 0x54028, 0x0 },
-	{ 0x54029, 0x0 },
-	{ 0x5402a, 0x0 },
+	{ 0x54022, 0x4d00 },
+	{ 0x54024, 0x16 },
 	{ 0x5402b, 0x1000 },
-	{ 0x5402c, LPDDR4_CS },
-	{ 0x5402d, 0x0 },
-	{ 0x5402e, 0x0 },
-	{ 0x5402f, 0x0 },
-	{ 0x54030, 0x0 },
-	{ 0x54031, 0x0 },
+	{ 0x5402c, 0x1 },
 	{ 0x54032, 0xd400 },
-	{ 0x54033, (LPDDR4_MR3 << 8) | (0x312d & 0xff) },
+	{ 0x54033, 0x312d },
 	{ 0x54034, 0x6600 },
-	{ 0x54035, 0x84d },
+	{ 0x54035, 0x4d },
 	{ 0x54036, 0x4d },
-	{ 0x54037, (LPDDR4_MR22_RANK0 << 8)/*0x1600*/ },
+	{ 0x54037, 0x1600 },
 	{ 0x54038, 0xd400 },
-	{ 0x54039, (LPDDR4_MR3 << 8) | (0x312d & 0xff) },
+	{ 0x54039, 0x312d },
 	{ 0x5403a, 0x6600 },
-	{ 0x5403b, 0x84d },
+	{ 0x5403b, 0x4d },
 	{ 0x5403c, 0x4d },
-	{ 0x5403d, (LPDDR4_MR22_RANK1 << 8)/*0x1600*/ },
-	{ 0x5403e, 0x0 },
-	{ 0x5403f, 0x0 },
-	{ 0x54040, 0x0 },
-	{ 0x54041, 0x0 },
-	{ 0x54042, 0x0 },
-	{ 0x54043, 0x0 },
-	{ 0x54044, 0x0 },
+	{ 0x5403d, 0x1600 },
 	{ 0xd0000, 0x1 },
 };
 
 /* DRAM PHY init engine image */
-struct dram_cfg_param lpddr4_phy_pie[] = {
+struct dram_cfg_param ddr_phy_pie[] = {
 	{ 0xd0000, 0x0 },
 	{ 0x90000, 0x10 },
 	{ 0x90001, 0x400 },
@@ -1854,6 +1717,10 @@
 	{ 0x90013, 0x6152 },
 	{ 0x20010, 0x5a },
 	{ 0x20011, 0x3 },
+	{ 0x120010, 0x5a },
+	{ 0x120011, 0x3 },
+	{ 0x220010, 0x5a },
+	{ 0x220011, 0x3 },
 	{ 0x40080, 0xe0 },
 	{ 0x40081, 0x12 },
 	{ 0x40082, 0xe0 },
@@ -1931,50 +1798,51 @@
 	{ 0x138b4, 0x1 },
 	{ 0x2003a, 0x2 },
 	{ 0xc0080, 0x2 },
-	{ 0xd0000, 0x1 },
+	{ 0xd0000, 0x1 }
 };
 
-struct dram_fsp_msg lpddr4_dram_fsp_msg[] = {
+struct dram_fsp_msg ddr_dram_fsp_msg[] = {
 	{
 		/* P0 3000mts 1D */
 		.drate = 3000,
 		.fw_type = FW_1D_IMAGE,
-		.fsp_cfg = lpddr4_fsp0_cfg,
-		.fsp_cfg_num = ARRAY_SIZE(lpddr4_fsp0_cfg),
-	},
-	{
-		/* P0 3000mts 2D */
-		.drate = 3000,
-		.fw_type = FW_2D_IMAGE,
-		.fsp_cfg = lpddr4_fsp0_2d_cfg,
-		.fsp_cfg_num = ARRAY_SIZE(lpddr4_fsp0_2d_cfg),
+		.fsp_cfg = ddr_fsp0_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_cfg),
 	},
 	{
 		/* P1 400mts 1D */
 		.drate = 400,
 		.fw_type = FW_1D_IMAGE,
-		.fsp_cfg = lpddr4_fsp1_cfg,
-		.fsp_cfg_num = ARRAY_SIZE(lpddr4_fsp1_cfg),
+		.fsp_cfg = ddr_fsp1_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp1_cfg),
 	},
 	{
-		/* P1 100mts 1D */
+		/* P2 100mts 1D */
 		.drate = 100,
 		.fw_type = FW_1D_IMAGE,
-		.fsp_cfg = lpddr4_fsp2_cfg,
-		.fsp_cfg_num = ARRAY_SIZE(lpddr4_fsp2_cfg),
+		.fsp_cfg = ddr_fsp2_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp2_cfg),
+	},
+	{
+		/* P0 3000mts 2D */
+		.drate = 3000,
+		.fw_type = FW_2D_IMAGE,
+		.fsp_cfg = ddr_fsp0_2d_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_2d_cfg),
 	},
 };
 
-/* lpddr4 timing config params on EVK board */
+/* ddr timing config params */
 struct dram_timing_info dram_timing = {
-	.ddrc_cfg = lpddr4_ddrc_cfg,
-	.ddrc_cfg_num = ARRAY_SIZE(lpddr4_ddrc_cfg),
-	.ddrphy_cfg = lpddr4_ddrphy_cfg,
-	.ddrphy_cfg_num = ARRAY_SIZE(lpddr4_ddrphy_cfg),
-	.fsp_msg = lpddr4_dram_fsp_msg,
-	.fsp_msg_num = ARRAY_SIZE(lpddr4_dram_fsp_msg),
-	.ddrphy_trained_csr = lpddr4_ddrphy_trained_csr,
-	.ddrphy_trained_csr_num = ARRAY_SIZE(lpddr4_ddrphy_trained_csr),
-	.ddrphy_pie = lpddr4_phy_pie,
-	.ddrphy_pie_num = ARRAY_SIZE(lpddr4_phy_pie),
+	.ddrc_cfg = ddr_ddrc_cfg,
+	.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg),
+	.ddrphy_cfg = ddr_ddrphy_cfg,
+	.ddrphy_cfg_num = ARRAY_SIZE(ddr_ddrphy_cfg),
+	.fsp_msg = ddr_dram_fsp_msg,
+	.fsp_msg_num = ARRAY_SIZE(ddr_dram_fsp_msg),
+	.ddrphy_trained_csr = ddr_ddrphy_trained_csr,
+	.ddrphy_trained_csr_num = ARRAY_SIZE(ddr_ddrphy_trained_csr),
+	.ddrphy_pie = ddr_phy_pie,
+	.ddrphy_pie_num = ARRAY_SIZE(ddr_phy_pie),
+	.fsp_table = { 3000, 400, 100, },
 };
diff --git a/board/freescale/imx8mm_evk/spl.c b/board/freescale/imx8mm_evk/spl.c
index 64bc606..4ef7f6f 100644
--- a/board/freescale/imx8mm_evk/spl.c
+++ b/board/freescale/imx8mm_evk/spl.c
@@ -26,7 +26,7 @@
 #include <dm/device-internal.h>
 
 #include <power/pmic.h>
-#include <power/bd71837.h>
+#include <power/pca9450.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -94,7 +94,7 @@
 	struct udevice *dev;
 	int ret;
 
-	ret = pmic_get("pmic@4b", &dev);
+	ret = pmic_get("pca9450@25", &dev);
 	if (ret == -ENODEV) {
 		puts("No pmic\n");
 		return 0;
@@ -102,25 +102,26 @@
 	if (ret != 0)
 		return ret;
 
-	/* decrease RESET key long push time from the default 10s to 10ms */
-	pmic_reg_write(dev, BD718XX_PWRONCONFIG1, 0x0);
+	/* BUCKxOUT_DVS0/1 control BUCK123 output */
+	pmic_reg_write(dev, PCA9450_BUCK123_DVS, 0x29);
 
-	/* unlock the PMIC regs */
-	pmic_reg_write(dev, BD718XX_REGLOCK, 0x1);
+	/* Buck 1 DVS control through PMIC_STBY_REQ */
+	pmic_reg_write(dev, PCA9450_BUCK1CTRL, 0x59);
 
-	/* increase VDD_SOC to typical value 0.85v before first DRAM access */
-	pmic_reg_write(dev, BD718XX_BUCK1_VOLT_RUN, 0x0f);
+	/* Set DVS1 to 0.8v for suspend */
+	pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS1, 0x10);
 
-	/* increase VDD_DRAM to 0.975v for 3Ghz DDR */
-	pmic_reg_write(dev, BD718XX_1ST_NODVS_BUCK_VOLT, 0x83);
+	/* increase VDD_DRAM to 0.95v for 3Ghz DDR */
+	pmic_reg_write(dev, PCA9450_BUCK3OUT_DVS0, 0x1C);
 
-#ifndef CONFIG_IMX8M_LPDDR4
-	/* increase NVCC_DRAM_1V2 to 1.2v for DDR4 */
-	pmic_reg_write(dev, BD718XX_4TH_NODVS_BUCK_VOLT, 0x28);
-#endif
+	/* VDD_DRAM needs off in suspend, set B1_ENMODE=10 (ON by PMIC_ON_REQ = H && PMIC_STBY_REQ = L) */
+	pmic_reg_write(dev, PCA9450_BUCK3CTRL, 0x4a);
 
-	/* lock the PMIC regs */
-	pmic_reg_write(dev, BD718XX_REGLOCK, 0x11);
+	/* set VDD_SNVS_0V8 from default 0.85V */
+	pmic_reg_write(dev, PCA9450_LDO2CTRL, 0xC0);
+
+	/* set WDOG_B_CFG to cold reset */
+	pmic_reg_write(dev, PCA9450_RESET_CTRL, 0xA1);
 
 	return 0;
 }
diff --git a/board/freescale/imx8mn_evk/Kconfig b/board/freescale/imx8mn_evk/Kconfig
index 048fb7d..478f4ed 100644
--- a/board/freescale/imx8mn_evk/Kconfig
+++ b/board/freescale/imx8mn_evk/Kconfig
@@ -1,4 +1,4 @@
-if TARGET_IMX8MN_DDR4_EVK
+if TARGET_IMX8MN_EVK || TARGET_IMX8MN_DDR4_EVK
 
 config SYS_BOARD
 	default "imx8mn_evk"
@@ -9,6 +9,10 @@
 config SYS_CONFIG_NAME
 	default "imx8mn_evk"
 
+config IMX8MN_LOW_DRIVE_MODE
+	bool "Enable the low drive mode of iMX8MN on EVK board"
+	default n
+
 source "board/freescale/common/Kconfig"
 
 endif
diff --git a/board/freescale/imx8mn_evk/MAINTAINERS b/board/freescale/imx8mn_evk/MAINTAINERS
index 3b0653d..6d110cc 100644
--- a/board/freescale/imx8mn_evk/MAINTAINERS
+++ b/board/freescale/imx8mn_evk/MAINTAINERS
@@ -1,6 +1,7 @@
-i.MX8MM EVK BOARD
+i.MX8MN EVK BOARD
 M:	Peng Fan <peng.fan@nxp.com>
 S:	Maintained
 F:	board/freescale/imx8mn_evk/
 F:	include/configs/imx8mn_evk.h
 F:	configs/imx8mn_ddr4_evk_defconfig
+F:	configs/imx8mn_evk_defconfig
diff --git a/board/freescale/imx8mn_evk/Makefile b/board/freescale/imx8mn_evk/Makefile
index 9511a70..42d1179 100644
--- a/board/freescale/imx8mn_evk/Makefile
+++ b/board/freescale/imx8mn_evk/Makefile
@@ -8,5 +8,11 @@
 
 ifdef CONFIG_SPL_BUILD
 obj-y += spl.o
+ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
+obj-$(CONFIG_IMX8M_LPDDR4) += lpddr4_timing_ld.o
+obj-$(CONFIG_IMX8M_DDR4) += ddr4_timing_ld.o
+else
+obj-$(CONFIG_IMX8M_LPDDR4) += lpddr4_timing.o
 obj-$(CONFIG_IMX8M_DDR4) += ddr4_timing.o
 endif
+endif
diff --git a/board/freescale/imx8mn_evk/ddr4_timing.c b/board/freescale/imx8mn_evk/ddr4_timing.c
index cfd193a..f1509e2 100644
--- a/board/freescale/imx8mn_evk/ddr4_timing.c
+++ b/board/freescale/imx8mn_evk/ddr4_timing.c
@@ -1,121 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2019 NXP
  *
- * SPDX-License-Identifier:	GPL-2.0+
- *
  * Generated code from MX8M_DDR_tool
- * Align with uboot-imx_v2018.03_4.14.78_1.0.0_ga
+ * Align with uboot version:
+ * imx_v2018.03_4.14.78_1.0.0_ga ~ imx_v2018.04_4.19.35_1.0.0_ga
  */
 
 #include <linux/kernel.h>
 #include <asm/arch/ddr.h>
 
 struct dram_cfg_param ddr_ddrc_cfg[] = {
-	{0x3d400000, 0x81040010},
-	{0x3d400030, 0x00000020},
-	{0x3d400034, 0x00221306},
-	{0x3d400050, 0x00210070},
-	{0x3d400054, 0x00010008},
-	{0x3d400060, 0x00000000},
-	{0x3d400064, 0x0092014a},
-	{0x3d4000c0, 0x00000000},
-	{0x3d4000c4, 0x00001000},
-	{0x3d4000d0, 0xc0030126},
-	{0x3d4000d4, 0x00770000},
-	{0x3d4000dc, 0x08340105},
-	{0x3d4000e0, 0x00180200},
-	{0x3d4000e4, 0x00110000},
-	{0x3d4000e8, 0x02000740},
-	{0x3d4000ec, 0x00000850},
-	{0x3d4000f4, 0x00000ec7},
-	{0x3d400100, 0x11122914},
-	{0x3d400104, 0x0004051c},
-	{0x3d400108, 0x0608050d},
-	{0x3d40010c, 0x0000400c},
-	{0x3d400110, 0x08030409},
-	{0x3d400114, 0x06060403},
-	{0x3d40011c, 0x00000606},
-	{0x3d400120, 0x07070d0c},
-	{0x3d400124, 0x0002040a},
-	{0x3d40012c, 0x1809010e},
-	{0x3d400130, 0x00000008},
-	{0x3d40013c, 0x00000000},
-	{0x3d400180, 0x01000040},
-	{0x3d400184, 0x0000493e},
-	{0x3d400190, 0x038b8207},
-	{0x3d400194, 0x02020303},
-	{0x3d400198, 0x07f04011},
-	{0x3d40019c, 0x000000b0},
-	{0x3d4001a0, 0xe0400018},
-	{0x3d4001a4, 0x0048005a},
-	{0x3d4001a8, 0x80000000},
-	{0x3d4001b0, 0x00000001},
-	{0x3d4001b4, 0x00000b07},
-	{0x3d4001b8, 0x00000004},
-	{0x3d4001c0, 0x00000001},
-	{0x3d4001c4, 0x00000000},
-	{0x3d400240, 0x06000610},
-	{0x3d400244, 0x00001323},
-	{0x3d400200, 0x00003f1f},
-	{0x3d400204, 0x003f0909},
-	{0x3d400208, 0x01010100},
-	{0x3d40020c, 0x01010101},
-	{0x3d400210, 0x00001f1f},
-	{0x3d400214, 0x07070707},
-	{0x3d400218, 0x07070707},
-	{0x3d40021c, 0x00000f07},
-	{0x3d400220, 0x00003f01},
-	{0x3d402050, 0x00210070},
-	{0x3d402064, 0x00180037},
-	{0x3d4020dc, 0x00000105},
-	{0x3d4020e0, 0x00000000},
-	{0x3d4020e8, 0x02000740},
-	{0x3d4020ec, 0x00000050},
-	{0x3d402100, 0x08030604},
-	{0x3d402104, 0x00020205},
-	{0x3d402108, 0x05050309},
-	{0x3d40210c, 0x0000400c},
-	{0x3d402110, 0x02030202},
-	{0x3d402114, 0x03030202},
-	{0x3d402118, 0x0a070008},
-	{0x3d40211c, 0x00000d09},
-	{0x3d402120, 0x08084b09},
-	{0x3d402124, 0x00020308},
-	{0x3d402128, 0x000f0d06},
-	{0x3d40212c, 0x12060111},
-	{0x3d402130, 0x00000008},
-	{0x3d40213c, 0x00000000},
-	{0x3d402180, 0x01000040},
-	{0x3d402190, 0x03848204},
-	{0x3d402194, 0x02020303},
-	{0x3d4021b4, 0x00000404},
-	{0x3d4021b8, 0x00000004},
-	{0x3d402240, 0x07000600},
-	{0x3d403050, 0x00210070},
-	{0x3d403064, 0x0006000d},
-	{0x3d4030dc, 0x00000105},
-	{0x3d4030e0, 0x00000000},
-	{0x3d4030e8, 0x02000740},
-	{0x3d4030ec, 0x00000050},
-	{0x3d403100, 0x07010101},
-	{0x3d403104, 0x00020202},
-	{0x3d403108, 0x05050309},
-	{0x3d40310c, 0x0000400c},
-	{0x3d403110, 0x01030201},
-	{0x3d403114, 0x03030202},
-	{0x3d40311c, 0x00000303},
-	{0x3d403120, 0x02020d02},
-	{0x3d403124, 0x00020208},
-	{0x3d403128, 0x000f0d06},
-	{0x3d40312c, 0x0e02010e},
-	{0x3d403130, 0x00000008},
-	{0x3d40313c, 0x00000000},
-	{0x3d403180, 0x01000040},
-	{0x3d403190, 0x03848204},
-	{0x3d403194, 0x02020303},
-	{0x3d4031b4, 0x00000404},
-	{0x3d4031b8, 0x00000004},
-	{0x3d403240, 0x07000600},
+	/** Initialize DDRC registers **/
+	{ 0x3d400000, 0x81040010 },
+	{ 0x3d400030, 0x20 },
+	{ 0x3d400034, 0x221306 },
+	{ 0x3d400050, 0x210070 },
+	{ 0x3d400054, 0x10008 },
+	{ 0x3d400060, 0x0 },
+	{ 0x3d400064, 0x92014a },
+	{ 0x3d4000c0, 0x0 },
+	{ 0x3d4000c4, 0x1000 },
+	{ 0x3d4000d0, 0xc0030126 },
+	{ 0x3d4000d4, 0x770000 },
+	{ 0x3d4000dc, 0x8340105 },
+	{ 0x3d4000e0, 0x180200 },
+	{ 0x3d4000e4, 0x110000 },
+	{ 0x3d4000e8, 0x2000600 },
+	{ 0x3d4000ec, 0x810 },
+	{ 0x3d4000f0, 0x20 },
+	{ 0x3d4000f4, 0xec7 },
+	{ 0x3d400100, 0x11122914 },
+	{ 0x3d400104, 0x4051c },
+	{ 0x3d400108, 0x608050d },
+	{ 0x3d40010c, 0x400c },
+	{ 0x3d400110, 0x8030409 },
+	{ 0x3d400114, 0x6060403 },
+	{ 0x3d40011c, 0x606 },
+	{ 0x3d400120, 0x7070d0c },
+	{ 0x3d400124, 0x2040a },
+	{ 0x3d40012c, 0x1809010e },
+	{ 0x3d400130, 0x8 },
+	{ 0x3d40013c, 0x0 },
+	{ 0x3d400180, 0x1000040 },
+	{ 0x3d400184, 0x493e },
+	{ 0x3d400190, 0x38b8207 },
+	{ 0x3d400194, 0x2020303 },
+	{ 0x3d400198, 0x7f04011 },
+	{ 0x3d40019c, 0xb0 },
+	{ 0x3d4001a0, 0xe0400018 },
+	{ 0x3d4001a4, 0x48005a },
+	{ 0x3d4001a8, 0x80000000 },
+	{ 0x3d4001b0, 0x1 },
+	{ 0x3d4001b4, 0xb07 },
+	{ 0x3d4001b8, 0x4 },
+	{ 0x3d4001c0, 0x1 },
+	{ 0x3d4001c4, 0x0 },
+	{ 0x3d400200, 0x3f1f },
+	{ 0x3d400204, 0x3f0909 },
+	{ 0x3d400208, 0x700 },
+	{ 0x3d40020c, 0x0 },
+	{ 0x3d400210, 0x1f1f },
+	{ 0x3d400214, 0x7070707 },
+	{ 0x3d400218, 0x7070707 },
+	{ 0x3d40021c, 0xf07 },
+	{ 0x3d400220, 0x3f01 },
+	{ 0x3d400240, 0x6000610 },
+	{ 0x3d400244, 0x1323 },
+	{ 0x3d400400, 0x100 },
 
 	/* performance setting */
 	{ 0x3d400250, 0x00001f05 },
@@ -126,141 +78,136 @@
 	{ 0x3d400498, 0x03ff0000 },
 	{ 0x3d40049c, 0x01000e00 },
 	{ 0x3d4004a0, 0x03ff0000 },
+
+	{ 0x3d402050, 0x210070 },
+	{ 0x3d402064, 0x400093 },
+	{ 0x3d4020dc, 0x105 },
+	{ 0x3d4020e0, 0x0 },
+	{ 0x3d4020e8, 0x2000600 },
+	{ 0x3d4020ec, 0x10 },
+	{ 0x3d402100, 0xb081209 },
+	{ 0x3d402104, 0x2020d },
+	{ 0x3d402108, 0x5050309 },
+	{ 0x3d40210c, 0x400c },
+	{ 0x3d402110, 0x5030206 },
+	{ 0x3d402114, 0x3030202 },
+	{ 0x3d40211c, 0x303 },
+	{ 0x3d402120, 0x4040d06 },
+	{ 0x3d402124, 0x20208 },
+	{ 0x3d40212c, 0x1205010e },
+	{ 0x3d402130, 0x8 },
+	{ 0x3d40213c, 0x0 },
+	{ 0x3d402180, 0x1000040 },
+	{ 0x3d402190, 0x3848204 },
+	{ 0x3d402194, 0x2020303 },
+	{ 0x3d4021b4, 0x404 },
+	{ 0x3d4021b8, 0x4 },
+	{ 0x3d402240, 0x6000600 },
+	{ 0x3d4020f4, 0xec7 },
 };
 
 /* PHY Initialize Configuration */
 struct dram_cfg_param ddr_ddrphy_cfg[] = {
-	{0x0001005f, 0x000002fd},
-	{0x0001015f, 0x000002fd},
-	{0x0001105f, 0x000002fd},
-	{0x0001115f, 0x000002fd},
-	{0x0011005f, 0x000002fd},
-	{0x0011015f, 0x000002fd},
-	{0x0011105f, 0x000002fd},
-	{0x0011115f, 0x000002fd},
-	{0x0021005f, 0x000002fd},
-	{0x0021015f, 0x000002fd},
-	{0x0021105f, 0x000002fd},
-	{0x0021115f, 0x000002fd},
-	{0x00000055, 0x00000355},
-	{0x00001055, 0x00000355},
-	{0x00002055, 0x00000355},
-	{0x00003055, 0x00000355},
-	{0x00004055, 0x00000055},
-	{0x00005055, 0x00000055},
-	{0x00006055, 0x00000355},
-	{0x00007055, 0x00000355},
-	{0x00008055, 0x00000355},
-	{0x00009055, 0x00000355},
-	{0x000200c5, 0x0000000a},
-	{0x001200c5, 0x00000007},
-	{0x002200c5, 0x00000007},
-	{0x0002002e, 0x00000002},
-	{0x0012002e, 0x00000002},
-	{0x0022002e, 0x00000002},
-	{0x00020024, 0x00000008},
-	{0x0002003a, 0x00000002},
-	{0x0002007d, 0x00000212},
-	{0x0002007c, 0x00000061},
-	{0x00120024, 0x00000008},
-	{0x0002003a, 0x00000002},
-	{0x0012007d, 0x00000212},
-	{0x0012007c, 0x00000061},
-	{0x00220024, 0x00000008},
-	{0x0002003a, 0x00000002},
-	{0x0022007d, 0x00000212},
-	{0x0022007c, 0x00000061},
-	{0x00020056, 0x00000006},
-	{0x00120056, 0x0000000a},
-	{0x00220056, 0x0000000a},
-	{0x0001004d, 0x0000001a},
-	{0x0001014d, 0x0000001a},
-	{0x0001104d, 0x0000001a},
-	{0x0001114d, 0x0000001a},
-	{0x0011004d, 0x0000001a},
-	{0x0011014d, 0x0000001a},
-	{0x0011104d, 0x0000001a},
-	{0x0011114d, 0x0000001a},
-	{0x0021004d, 0x0000001a},
-	{0x0021014d, 0x0000001a},
-	{0x0021104d, 0x0000001a},
-	{0x0021114d, 0x0000001a},
-	{0x00010049, 0x00000e38},
-	{0x00010149, 0x00000e38},
-	{0x00011049, 0x00000e38},
-	{0x00011149, 0x00000e38},
-	{0x00110049, 0x00000e38},
-	{0x00110149, 0x00000e38},
-	{0x00111049, 0x00000e38},
-	{0x00111149, 0x00000e38},
-	{0x00210049, 0x00000e38},
-	{0x00210149, 0x00000e38},
-	{0x00211049, 0x00000e38},
-	{0x00211149, 0x00000e38},
-	{0x00000043, 0x00000063},
-	{0x00001043, 0x00000063},
-	{0x00002043, 0x00000063},
-	{0x00003043, 0x00000063},
-	{0x00004043, 0x00000063},
-	{0x00005043, 0x00000063},
-	{0x00006043, 0x00000063},
-	{0x00007043, 0x00000063},
-	{0x00008043, 0x00000063},
-	{0x00009043, 0x00000063},
-	{0x00020018, 0x00000001},
-	{0x00020075, 0x00000002},
-	{0x00020050, 0x00000000},
-	{0x00020008, 0x00000258},
-	{0x00120008, 0x00000064},
-	{0x00220008, 0x00000019},
-	{0x00020088, 0x00000009},
-	{0x000200b2, 0x00000268},
-	{0x00010043, 0x000005b1},
-	{0x00010143, 0x000005b1},
-	{0x00011043, 0x000005b1},
-	{0x00011143, 0x000005b1},
-	{0x001200b2, 0x00000268},
-	{0x00110043, 0x000005b1},
-	{0x00110143, 0x000005b1},
-	{0x00111043, 0x000005b1},
-	{0x00111143, 0x000005b1},
-	{0x002200b2, 0x00000268},
-	{0x00210043, 0x000005b1},
-	{0x00210143, 0x000005b1},
-	{0x00211043, 0x000005b1},
-	{0x00211143, 0x000005b1},
-	{0x0002005b, 0x00007529},
-	{0x0002005c, 0x00000000},
-	{0x000200fa, 0x00000001},
-	{0x001200fa, 0x00000001},
-	{0x002200fa, 0x00000001},
-	{0x00020019, 0x00000005},
-	{0x00120019, 0x00000005},
-	{0x00220019, 0x00000005},
-	{0x000200f0, 0x00005665},
-	{0x000200f1, 0x00005555},
-	{0x000200f2, 0x00005555},
-	{0x000200f3, 0x00005555},
-	{0x000200f4, 0x00005555},
-	{0x000200f5, 0x00005555},
-	{0x000200f6, 0x00005555},
-	{0x000200f7, 0x0000f000},
-	{0x0001004a, 0x00000500},
-	{0x0001104a, 0x00000500},
-	{0x00020025, 0x00000000},
-	{0x0002002d, 0x00000000},
-	{0x0012002d, 0x00000000},
-	{0x0022002d, 0x00000000},
-	{0x0002002c, 0x00000000},
-	{0x000200c7, 0x00000021},
-	{0x000200ca, 0x00000024},
-	{0x000200cc, 0x000001f7},
-	{0x001200c7, 0x00000021},
-	{0x001200ca, 0x00000024},
-	{0x001200cc, 0x000001f7},
-	{0x002200c7, 0x00000021},
-	{0x002200ca, 0x00000024},
-	{0x002200cc, 0x000001f7},
+	{ 0x1005f, 0x2fd },
+	{ 0x1015f, 0x2fd },
+	{ 0x1105f, 0x2fd },
+	{ 0x1115f, 0x2fd },
+	{ 0x11005f, 0x2fd },
+	{ 0x11015f, 0x2fd },
+	{ 0x11105f, 0x2fd },
+	{ 0x11115f, 0x2fd },
+	{ 0x55, 0x355 },
+	{ 0x1055, 0x355 },
+	{ 0x2055, 0x355 },
+	{ 0x3055, 0x355 },
+	{ 0x4055, 0x55 },
+	{ 0x5055, 0x55 },
+	{ 0x6055, 0x355 },
+	{ 0x7055, 0x355 },
+	{ 0x8055, 0x355 },
+	{ 0x9055, 0x355 },
+	{ 0x200c5, 0xa },
+	{ 0x1200c5, 0x6 },
+	{ 0x2002e, 0x2 },
+	{ 0x12002e, 0x1 },
+	{ 0x20024, 0x8 },
+	{ 0x2003a, 0x2 },
+	{ 0x120024, 0x8 },
+	{ 0x2003a, 0x2 },
+	{ 0x20056, 0x6 },
+	{ 0x120056, 0xa },
+	{ 0x1004d, 0x1a },
+	{ 0x1014d, 0x1a },
+	{ 0x1104d, 0x1a },
+	{ 0x1114d, 0x1a },
+	{ 0x11004d, 0x1a },
+	{ 0x11014d, 0x1a },
+	{ 0x11104d, 0x1a },
+	{ 0x11114d, 0x1a },
+	{ 0x10049, 0xe38 },
+	{ 0x10149, 0xe38 },
+	{ 0x11049, 0xe38 },
+	{ 0x11149, 0xe38 },
+	{ 0x110049, 0xe38 },
+	{ 0x110149, 0xe38 },
+	{ 0x111049, 0xe38 },
+	{ 0x111149, 0xe38 },
+	{ 0x43, 0x63 },
+	{ 0x1043, 0x63 },
+	{ 0x2043, 0x63 },
+	{ 0x3043, 0x63 },
+	{ 0x4043, 0x63 },
+	{ 0x5043, 0x63 },
+	{ 0x6043, 0x63 },
+	{ 0x7043, 0x63 },
+	{ 0x8043, 0x63 },
+	{ 0x9043, 0x63 },
+	{ 0x20018, 0x1 },
+	{ 0x20075, 0x2 },
+	{ 0x20050, 0x0 },
+	{ 0x20008, 0x258 },
+	{ 0x120008, 0x10a },
+	{ 0x20088, 0x9 },
+	{ 0x200b2, 0x268 },
+	{ 0x10043, 0x5b1 },
+	{ 0x10143, 0x5b1 },
+	{ 0x11043, 0x5b1 },
+	{ 0x11143, 0x5b1 },
+	{ 0x1200b2, 0x268 },
+	{ 0x110043, 0x5b1 },
+	{ 0x110143, 0x5b1 },
+	{ 0x111043, 0x5b1 },
+	{ 0x111143, 0x5b1 },
+	{ 0x200fa, 0x1 },
+	{ 0x1200fa, 0x1 },
+	{ 0x20019, 0x5 },
+	{ 0x120019, 0x5 },
+	{ 0x200f0, 0x5555 },
+	{ 0x200f1, 0x5555 },
+	{ 0x200f2, 0x5555 },
+	{ 0x200f3, 0x5555 },
+	{ 0x200f4, 0x5555 },
+	{ 0x200f5, 0x5555 },
+	{ 0x200f6, 0x5555 },
+	{ 0x200f7, 0xf000 },
+	{ 0x20025, 0x0 },
+	{ 0x2002d, 0x0 },
+	{ 0x12002d, 0x0 },
+	{ 0x2005b, 0x7529 },
+	{ 0x2005c, 0x0 },
+	{ 0x200c7, 0x21 },
+	{ 0x200ca, 0x24 },
+	{ 0x200cc, 0x1f7 },
+	{ 0x1200c7, 0x21 },
+	{ 0x1200ca, 0x24 },
+	{ 0x1200cc, 0x1f7 },
+	{ 0x2007d, 0x212 },
+	{ 0x12007d, 0x212 },
+	{ 0x2007c, 0x61 },
+	{ 0x12007c, 0x61 },
+	{ 0x1004a, 0x500 },
+	{ 0x1104a, 0x500 },
+	{ 0x2002c, 0x0 },
 };
 
 /* ddr phy trained csr */
@@ -792,378 +739,279 @@
 
 /* P0 message block paremeter for training firmware */
 struct dram_cfg_param ddr_fsp0_cfg[] = {
-	{0x000d0000, 0x00000000},
-	{0x00020060, 0x00000002},
-	{0x00054000, 0x00000000},
-	{0x00054001, 0x00000000},
-	{0x00054002, 0x00000000},
-	{0x00054003, 0x00000960},
-	{0x00054004, 0x00000002},
-	{0x00054005, 0x00000000},
-	{0x00054006, 0x0000025e},
-	{0x00054007, 0x00001000},
-	{0x00054008, 0x00000101},
-	{0x00054009, 0x00000000},
-	{0x0005400a, 0x00000000},
-	{0x0005400b, 0x0000031f},
-	{0x0005400c, 0x000000c8},
-	{0x0005400d, 0x00000100},
-	{0x0005400e, 0x00000000},
-	{0x0005400f, 0x00000000},
-	{0x00054010, 0x00000000},
-	{0x00054011, 0x00000000},
-	{0x00054012, 0x00000001},
-	{0x0005402f, 0x00000834},
-	{0x00054030, 0x00000105},
-	{0x00054031, 0x00000018},
-	{0x00054032, 0x00000200},
-	{0x00054033, 0x00000200},
-	{0x00054034, 0x00000740},
-	{0x00054035, 0x00000850},
-	{0x00054036, 0x00000103},
-	{0x00054037, 0x00000000},
-	{0x00054038, 0x00000000},
-	{0x00054039, 0x00000000},
-	{0x0005403a, 0x00000000},
-	{0x0005403b, 0x00000000},
-	{0x0005403c, 0x00000000},
-	{0x0005403d, 0x00000000},
-	{0x0005403e, 0x00000000},
-	{0x0005403f, 0x00001221},
-	{0x000541fc, 0x00000100},
-	{0x000d0000, 0x00000001},
+	{ 0xd0000, 0x0 },
+	{ 0x54003, 0x960 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, 0x2830 },
+	{ 0x54006, 0x25e },
+	{ 0x54007, 0x1000 },
+	{ 0x54008, 0x101 },
+	{ 0x5400b, 0x31f },
+	{ 0x5400c, 0xc8 },
+	{ 0x5400d, 0x100 },
+	{ 0x54012, 0x1 },
+	{ 0x5402f, 0x834 },
+	{ 0x54030, 0x105 },
+	{ 0x54031, 0x18 },
+	{ 0x54032, 0x200 },
+	{ 0x54033, 0x200 },
+	{ 0x54034, 0x600 },
+	{ 0x54035, 0x810 },
+	{ 0x54036, 0x101 },
+	{ 0x5403f, 0x1221 },
+	{ 0x541fc, 0x100 },
+	{ 0xd0000, 0x1 },
 };
 
 /* P1 message block paremeter for training firmware */
 struct dram_cfg_param ddr_fsp1_cfg[] = {
-	{0x000d0000, 0x00000000},
-	{0x00054000, 0x00000000},
-	{0x00054001, 0x00000000},
-	{0x00054002, 0x00000101},
-	{0x00054003, 0x00000190},
-	{0x00054004, 0x00000002},
-	{0x00054005, 0x00000000},
-	{0x00054006, 0x0000025e},
-	{0x00054007, 0x00001000},
-	{0x00054008, 0x00000101},
-	{0x00054009, 0x00000000},
-	{0x0005400a, 0x00000000},
-	{0x0005400b, 0x0000021f},
-	{0x0005400c, 0x000000c8},
-	{0x0005400d, 0x00000100},
-	{0x0005400e, 0x00000000},
-	{0x0005400f, 0x00000000},
-	{0x00054010, 0x00000000},
-	{0x00054011, 0x00000000},
-	{0x00054012, 0x00000001},
-	{0x0005402f, 0x00000000},
-	{0x00054030, 0x00000105},
-	{0x00054031, 0x00000000},
-	{0x00054032, 0x00000000},
-	{0x00054033, 0x00000200},
-	{0x00054034, 0x00000740},
-	{0x00054035, 0x00000050},
-	{0x00054036, 0x00000103},
-	{0x00054037, 0x00000000},
-	{0x00054038, 0x00000000},
-	{0x00054039, 0x00000000},
-	{0x0005403a, 0x00000000},
-	{0x0005403b, 0x00000000},
-	{0x0005403c, 0x00000000},
-	{0x0005403d, 0x00000000},
-	{0x0005403e, 0x00000000},
-	{0x0005403f, 0x00001221},
-	{0x000541fc, 0x00000100},
-	{0x000d0000, 0x00000001},
+	{ 0xd0000, 0x0 },
+	{ 0x54002, 0x1 },
+	{ 0x54003, 0x42a },
+	{ 0x54004, 0x2 },
+	{ 0x54005, 0x2830 },
+	{ 0x54006, 0x25e },
+	{ 0x54007, 0x1000 },
+	{ 0x54008, 0x101 },
+	{ 0x5400b, 0x21f },
+	{ 0x5400c, 0xc8 },
+	{ 0x5400d, 0x100 },
+	{ 0x54012, 0x1 },
+	{ 0x54030, 0x105 },
+	{ 0x54033, 0x200 },
+	{ 0x54034, 0x600 },
+	{ 0x54035, 0x10 },
+	{ 0x54036, 0x101 },
+	{ 0x5403f, 0x1221 },
+	{ 0x541fc, 0x100 },
+	{ 0xd0000, 0x1 },
 };
 
-/* P2 message block paremeter for training firmware */
-struct dram_cfg_param ddr_fsp2_cfg[] = {
-	{0x000d0000, 0x00000000},
-	{0x00054000, 0x00000000},
-	{0x00054001, 0x00000000},
-	{0x00054002, 0x00000102},
-	{0x00054003, 0x00000064},
-	{0x00054004, 0x00000002},
-	{0x00054005, 0x00000000},
-	{0x00054006, 0x0000025e},
-	{0x00054007, 0x00001000},
-	{0x00054008, 0x00000101},
-	{0x00054009, 0x00000000},
-	{0x0005400a, 0x00000000},
-	{0x0005400b, 0x0000021f},
-	{0x0005400c, 0x000000c8},
-	{0x0005400d, 0x00000100},
-	{0x0005400e, 0x00000000},
-	{0x0005400f, 0x00000000},
-	{0x00054010, 0x00000000},
-	{0x00054011, 0x00000000},
-	{0x00054012, 0x00000001},
-	{0x0005402f, 0x00000000},
-	{0x00054030, 0x00000105},
-	{0x00054031, 0x00000000},
-	{0x00054032, 0x00000000},
-	{0x00054033, 0x00000200},
-	{0x00054034, 0x00000740},
-	{0x00054035, 0x00000050},
-	{0x00054036, 0x00000103},
-	{0x00054037, 0x00000000},
-	{0x00054038, 0x00000000},
-	{0x00054039, 0x00000000},
-	{0x0005403a, 0x00000000},
-	{0x0005403b, 0x00000000},
-	{0x0005403c, 0x00000000},
-	{0x0005403d, 0x00000000},
-	{0x0005403e, 0x00000000},
-	{0x0005403f, 0x00001221},
-	{0x000541fc, 0x00000100},
-	{0x000d0000, 0x00000001},
-};
 
 /* P0 2D message block paremeter for training firmware */
 struct dram_cfg_param ddr_fsp0_2d_cfg[] = {
-	{0x000d0000, 0x00000000},
-	{0x00054000, 0x00000000},
-	{0x00054001, 0x00000000},
-	{0x00054002, 0x00000000},
-	{0x00054003, 0x00000960},
-	{0x00054004, 0x00000002},
-	{0x00054005, 0x00000000},
-	{0x00054006, 0x0000025e},
-	{0x00054007, 0x00001000},
-	{0x00054008, 0x00000101},
-	{0x00054009, 0x00000000},
-	{0x0005400a, 0x00000000},
-	{0x0005400b, 0x00000061},
-	{0x0005400c, 0x000000c8},
-	{0x0005400d, 0x00000100},
-	{0x0005400e, 0x00001f7f},
-	{0x0005400f, 0x00000000},
-	{0x00054010, 0x00000000},
-	{0x00054011, 0x00000000},
-	{0x00054012, 0x00000001},
-	{0x0005402f, 0x00000834},
-	{0x00054030, 0x00000105},
-	{0x00054031, 0x00000018},
-	{0x00054032, 0x00000200},
-	{0x00054033, 0x00000200},
-	{0x00054034, 0x00000740},
-	{0x00054035, 0x00000850},
-	{0x00054036, 0x00000103},
-	{0x00054037, 0x00000000},
-	{0x00054038, 0x00000000},
-	{0x00054039, 0x00000000},
-	{0x0005403a, 0x00000000},
-	{0x0005403b, 0x00000000},
-	{0x0005403c, 0x00000000},
-	{0x0005403d, 0x00000000},
-	{0x0005403e, 0x00000000},
-	{0x0005403f, 0x00001221},
-	{0x000541fc, 0x00000100},
-	{0x000d0000, 0x00000001},
+	{ 0xd0000, 0x0 },
+	{ 0x54003, 0x960 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, 0x2830 },
+	{ 0x54006, 0x25e },
+	{ 0x54007, 0x1000 },
+	{ 0x54008, 0x101 },
+	{ 0x5400b, 0x61 },
+	{ 0x5400c, 0xc8 },
+	{ 0x5400d, 0x100 },
+	{ 0x5400e, 0x1f7f },
+	{ 0x54012, 0x1 },
+	{ 0x5402f, 0x834 },
+	{ 0x54030, 0x105 },
+	{ 0x54031, 0x18 },
+	{ 0x54032, 0x200 },
+	{ 0x54033, 0x200 },
+	{ 0x54034, 0x600 },
+	{ 0x54035, 0x810 },
+	{ 0x54036, 0x101 },
+	{ 0x5403f, 0x1221 },
+	{ 0x541fc, 0x100 },
+	{ 0xd0000, 0x1 },
 };
 
 /* DRAM PHY init engine image */
 struct dram_cfg_param ddr_phy_pie[] = {
-	{0xd0000, 0x0},
-	{0x90000, 0x10},
-	{0x90001, 0x400},
-	{0x90002, 0x10e},
-	{0x90003, 0x0},
-	{0x90004, 0x0},
-	{0x90005, 0x8},
-	{0x90029, 0xb},
-	{0x9002a, 0x480},
-	{0x9002b, 0x109},
-	{0x9002c, 0x8},
-	{0x9002d, 0x448},
-	{0x9002e, 0x139},
-	{0x9002f, 0x8},
-	{0x90030, 0x478},
-	{0x90031, 0x109},
-	{0x90032, 0x2},
-	{0x90033, 0x10},
-	{0x90034, 0x139},
-	{0x90035, 0xb},
-	{0x90036, 0x7c0},
-	{0x90037, 0x139},
-	{0x90038, 0x44},
-	{0x90039, 0x633},
-	{0x9003a, 0x159},
-	{0x9003b, 0x14f},
-	{0x9003c, 0x630},
-	{0x9003d, 0x159},
-	{0x9003e, 0x47},
-	{0x9003f, 0x633},
-	{0x90040, 0x149},
-	{0x90041, 0x4f},
-	{0x90042, 0x633},
-	{0x90043, 0x179},
-	{0x90044, 0x8},
-	{0x90045, 0xe0},
-	{0x90046, 0x109},
-	{0x90047, 0x0},
-	{0x90048, 0x7c8},
-	{0x90049, 0x109},
-	{0x9004a, 0x0},
-	{0x9004b, 0x1},
-	{0x9004c, 0x8},
-	{0x9004d, 0x0},
-	{0x9004e, 0x45a},
-	{0x9004f, 0x9},
-	{0x90050, 0x0},
-	{0x90051, 0x448},
-	{0x90052, 0x109},
-	{0x90053, 0x40},
-	{0x90054, 0x633},
-	{0x90055, 0x179},
-	{0x90056, 0x1},
-	{0x90057, 0x618},
-	{0x90058, 0x109},
-	{0x90059, 0x40c0},
-	{0x9005a, 0x633},
-	{0x9005b, 0x149},
-	{0x9005c, 0x8},
-	{0x9005d, 0x4},
-	{0x9005e, 0x48},
-	{0x9005f, 0x4040},
-	{0x90060, 0x633},
-	{0x90061, 0x149},
-	{0x90062, 0x0},
-	{0x90063, 0x4},
-	{0x90064, 0x48},
-	{0x90065, 0x40},
-	{0x90066, 0x633},
-	{0x90067, 0x149},
-	{0x90068, 0x10},
-	{0x90069, 0x4},
-	{0x9006a, 0x18},
-	{0x9006b, 0x0},
-	{0x9006c, 0x4},
-	{0x9006d, 0x78},
-	{0x9006e, 0x549},
-	{0x9006f, 0x633},
-	{0x90070, 0x159},
-	{0x90071, 0xd49},
-	{0x90072, 0x633},
-	{0x90073, 0x159},
-	{0x90074, 0x94a},
-	{0x90075, 0x633},
-	{0x90076, 0x159},
-	{0x90077, 0x441},
-	{0x90078, 0x633},
-	{0x90079, 0x149},
-	{0x9007a, 0x42},
-	{0x9007b, 0x633},
-	{0x9007c, 0x149},
-	{0x9007d, 0x1},
-	{0x9007e, 0x633},
-	{0x9007f, 0x149},
-	{0x90080, 0x0},
-	{0x90081, 0xe0},
-	{0x90082, 0x109},
-	{0x90083, 0xa},
-	{0x90084, 0x10},
-	{0x90085, 0x109},
-	{0x90086, 0x9},
-	{0x90087, 0x3c0},
-	{0x90088, 0x149},
-	{0x90089, 0x9},
-	{0x9008a, 0x3c0},
-	{0x9008b, 0x159},
-	{0x9008c, 0x18},
-	{0x9008d, 0x10},
-	{0x9008e, 0x109},
-	{0x9008f, 0x0},
-	{0x90090, 0x3c0},
-	{0x90091, 0x109},
-	{0x90092, 0x18},
-	{0x90093, 0x4},
-	{0x90094, 0x48},
-	{0x90095, 0x18},
-	{0x90096, 0x4},
-	{0x90097, 0x58},
-	{0x90098, 0xb},
-	{0x90099, 0x10},
-	{0x9009a, 0x109},
-	{0x9009b, 0x1},
-	{0x9009c, 0x10},
-	{0x9009d, 0x109},
-	{0x9009e, 0x5},
-	{0x9009f, 0x7c0},
-	{0x900a0, 0x109},
-	{0x900a1, 0x0},
-	{0x900a2, 0x8140},
-	{0x900a3, 0x10c},
-	{0x900a4, 0x10},
-	{0x900a5, 0x8138},
-	{0x900a6, 0x10c},
-	{0x900a7, 0x8},
-	{0x900a8, 0x7c8},
-	{0x900a9, 0x101},
-	{0x900aa, 0x8},
-	{0x900ab, 0x448},
-	{0x900ac, 0x109},
-	{0x900ad, 0xf},
-	{0x900ae, 0x7c0},
-	{0x900af, 0x109},
-	{0x900b0, 0x47},
-	{0x900b1, 0x630},
-	{0x900b2, 0x109},
-	{0x900b3, 0x8},
-	{0x900b4, 0x618},
-	{0x900b5, 0x109},
-	{0x900b6, 0x8},
-	{0x900b7, 0xe0},
-	{0x900b8, 0x109},
-	{0x900b9, 0x0},
-	{0x900ba, 0x7c8},
-	{0x900bb, 0x109},
-	{0x900bc, 0x8},
-	{0x900bd, 0x8140},
-	{0x900be, 0x10c},
-	{0x900bf, 0x0},
-	{0x900c0, 0x1},
-	{0x900c1, 0x8},
-	{0x900c2, 0x8},
-	{0x900c3, 0x4},
-	{0x900c4, 0x8},
-	{0x900c5, 0x8},
-	{0x900c6, 0x7c8},
-	{0x900c7, 0x101},
-	{0x90006, 0x0},
-	{0x90007, 0x0},
-	{0x90008, 0x8},
-	{0x90009, 0x0},
-	{0x9000a, 0x0},
-	{0x9000b, 0x0},
-	{0xd00e7, 0x400},
-	{0x90017, 0x0},
-	{0x90026, 0x2b},
-	{0x2000b, 0x4b},
-	{0x2000c, 0x96},
-	{0x2000d, 0x5dc},
-	{0x2000e, 0x2c},
-	{0x12000b, 0xc},
-	{0x12000c, 0x16},
-	{0x12000d, 0xfa},
-	{0x12000e, 0x10},
-	{0x22000b, 0x3},
-	{0x22000c, 0x3},
-	{0x22000d, 0x3e},
-	{0x22000e, 0x10},
-	{0x9000c, 0x0},
-	{0x9000d, 0x173},
-	{0x9000e, 0x60},
-	{0x9000f, 0x6110},
-	{0x90010, 0x2152},
-	{0x90011, 0xdfbd},
-	{0x90012, 0xffff},
-	{0x90013, 0x6152},
-	{0x20089, 0x1},
-	{0x20088, 0x19},
-	{0xc0080, 0x0},
-	{0xd0000, 0x1},
+	{ 0xd0000, 0x0 },
+	{ 0x90000, 0x10 },
+	{ 0x90001, 0x400 },
+	{ 0x90002, 0x10e },
+	{ 0x90003, 0x0 },
+	{ 0x90004, 0x0 },
+	{ 0x90005, 0x8 },
+	{ 0x90029, 0xb },
+	{ 0x9002a, 0x480 },
+	{ 0x9002b, 0x109 },
+	{ 0x9002c, 0x8 },
+	{ 0x9002d, 0x448 },
+	{ 0x9002e, 0x139 },
+	{ 0x9002f, 0x8 },
+	{ 0x90030, 0x478 },
+	{ 0x90031, 0x109 },
+	{ 0x90032, 0x2 },
+	{ 0x90033, 0x10 },
+	{ 0x90034, 0x139 },
+	{ 0x90035, 0xb },
+	{ 0x90036, 0x7c0 },
+	{ 0x90037, 0x139 },
+	{ 0x90038, 0x44 },
+	{ 0x90039, 0x633 },
+	{ 0x9003a, 0x159 },
+	{ 0x9003b, 0x14f },
+	{ 0x9003c, 0x630 },
+	{ 0x9003d, 0x159 },
+	{ 0x9003e, 0x47 },
+	{ 0x9003f, 0x633 },
+	{ 0x90040, 0x149 },
+	{ 0x90041, 0x4f },
+	{ 0x90042, 0x633 },
+	{ 0x90043, 0x179 },
+	{ 0x90044, 0x8 },
+	{ 0x90045, 0xe0 },
+	{ 0x90046, 0x109 },
+	{ 0x90047, 0x0 },
+	{ 0x90048, 0x7c8 },
+	{ 0x90049, 0x109 },
+	{ 0x9004a, 0x0 },
+	{ 0x9004b, 0x1 },
+	{ 0x9004c, 0x8 },
+	{ 0x9004d, 0x0 },
+	{ 0x9004e, 0x45a },
+	{ 0x9004f, 0x9 },
+	{ 0x90050, 0x0 },
+	{ 0x90051, 0x448 },
+	{ 0x90052, 0x109 },
+	{ 0x90053, 0x40 },
+	{ 0x90054, 0x633 },
+	{ 0x90055, 0x179 },
+	{ 0x90056, 0x1 },
+	{ 0x90057, 0x618 },
+	{ 0x90058, 0x109 },
+	{ 0x90059, 0x40c0 },
+	{ 0x9005a, 0x633 },
+	{ 0x9005b, 0x149 },
+	{ 0x9005c, 0x8 },
+	{ 0x9005d, 0x4 },
+	{ 0x9005e, 0x48 },
+	{ 0x9005f, 0x4040 },
+	{ 0x90060, 0x633 },
+	{ 0x90061, 0x149 },
+	{ 0x90062, 0x0 },
+	{ 0x90063, 0x4 },
+	{ 0x90064, 0x48 },
+	{ 0x90065, 0x40 },
+	{ 0x90066, 0x633 },
+	{ 0x90067, 0x149 },
+	{ 0x90068, 0x10 },
+	{ 0x90069, 0x4 },
+	{ 0x9006a, 0x18 },
+	{ 0x9006b, 0x0 },
+	{ 0x9006c, 0x4 },
+	{ 0x9006d, 0x78 },
+	{ 0x9006e, 0x549 },
+	{ 0x9006f, 0x633 },
+	{ 0x90070, 0x159 },
+	{ 0x90071, 0xd49 },
+	{ 0x90072, 0x633 },
+	{ 0x90073, 0x159 },
+	{ 0x90074, 0x94a },
+	{ 0x90075, 0x633 },
+	{ 0x90076, 0x159 },
+	{ 0x90077, 0x441 },
+	{ 0x90078, 0x633 },
+	{ 0x90079, 0x149 },
+	{ 0x9007a, 0x42 },
+	{ 0x9007b, 0x633 },
+	{ 0x9007c, 0x149 },
+	{ 0x9007d, 0x1 },
+	{ 0x9007e, 0x633 },
+	{ 0x9007f, 0x149 },
+	{ 0x90080, 0x0 },
+	{ 0x90081, 0xe0 },
+	{ 0x90082, 0x109 },
+	{ 0x90083, 0xa },
+	{ 0x90084, 0x10 },
+	{ 0x90085, 0x109 },
+	{ 0x90086, 0x9 },
+	{ 0x90087, 0x3c0 },
+	{ 0x90088, 0x149 },
+	{ 0x90089, 0x9 },
+	{ 0x9008a, 0x3c0 },
+	{ 0x9008b, 0x159 },
+	{ 0x9008c, 0x18 },
+	{ 0x9008d, 0x10 },
+	{ 0x9008e, 0x109 },
+	{ 0x9008f, 0x0 },
+	{ 0x90090, 0x3c0 },
+	{ 0x90091, 0x109 },
+	{ 0x90092, 0x18 },
+	{ 0x90093, 0x4 },
+	{ 0x90094, 0x48 },
+	{ 0x90095, 0x18 },
+	{ 0x90096, 0x4 },
+	{ 0x90097, 0x58 },
+	{ 0x90098, 0xb },
+	{ 0x90099, 0x10 },
+	{ 0x9009a, 0x109 },
+	{ 0x9009b, 0x1 },
+	{ 0x9009c, 0x10 },
+	{ 0x9009d, 0x109 },
+	{ 0x9009e, 0x5 },
+	{ 0x9009f, 0x7c0 },
+	{ 0x900a0, 0x109 },
+	{ 0x900a1, 0x0 },
+	{ 0x900a2, 0x8140 },
+	{ 0x900a3, 0x10c },
+	{ 0x900a4, 0x10 },
+	{ 0x900a5, 0x8138 },
+	{ 0x900a6, 0x10c },
+	{ 0x900a7, 0x8 },
+	{ 0x900a8, 0x7c8 },
+	{ 0x900a9, 0x101 },
+	{ 0x900aa, 0x8 },
+	{ 0x900ab, 0x448 },
+	{ 0x900ac, 0x109 },
+	{ 0x900ad, 0xf },
+	{ 0x900ae, 0x7c0 },
+	{ 0x900af, 0x109 },
+	{ 0x900b0, 0x47 },
+	{ 0x900b1, 0x630 },
+	{ 0x900b2, 0x109 },
+	{ 0x900b3, 0x8 },
+	{ 0x900b4, 0x618 },
+	{ 0x900b5, 0x109 },
+	{ 0x900b6, 0x8 },
+	{ 0x900b7, 0xe0 },
+	{ 0x900b8, 0x109 },
+	{ 0x900b9, 0x0 },
+	{ 0x900ba, 0x7c8 },
+	{ 0x900bb, 0x109 },
+	{ 0x900bc, 0x8 },
+	{ 0x900bd, 0x8140 },
+	{ 0x900be, 0x10c },
+	{ 0x900bf, 0x0 },
+	{ 0x900c0, 0x1 },
+	{ 0x900c1, 0x8 },
+	{ 0x900c2, 0x8 },
+	{ 0x900c3, 0x4 },
+	{ 0x900c4, 0x8 },
+	{ 0x900c5, 0x8 },
+	{ 0x900c6, 0x7c8 },
+	{ 0x900c7, 0x101 },
+	{ 0x90006, 0x0 },
+	{ 0x90007, 0x0 },
+	{ 0x90008, 0x8 },
+	{ 0x90009, 0x0 },
+	{ 0x9000a, 0x0 },
+	{ 0x9000b, 0x0 },
+	{ 0xd00e7, 0x400 },
+	{ 0x90017, 0x0 },
+	{ 0x90026, 0x2b },
+	{ 0x2000b, 0x4b },
+	{ 0x2000c, 0x96 },
+	{ 0x2000d, 0x5dc },
+	{ 0x2000e, 0x2c },
+	{ 0x12000b, 0x21 },
+	{ 0x12000c, 0x42 },
+	{ 0x12000d, 0x29a },
+	{ 0x12000e, 0x21 },
+	{ 0x9000c, 0x0 },
+	{ 0x9000d, 0x173 },
+	{ 0x9000e, 0x60 },
+	{ 0x9000f, 0x6110 },
+	{ 0x90010, 0x2152 },
+	{ 0x90011, 0xdfbd },
+	{ 0x90012, 0xffff },
+	{ 0x90013, 0x6152 },
+	{ 0x20089, 0x1 },
+	{ 0x20088, 0x19 },
+	{ 0xc0080, 0x0 },
+	{ 0xd0000, 0x1 }
 };
 
 struct dram_fsp_msg ddr_dram_fsp_msg[] = {
@@ -1175,20 +1023,13 @@
 		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_cfg),
 	},
 	{
-		/* P1 400mts 1D */
-		.drate = 400,
+		/* P1 1066mts 1D */
+		.drate = 1066,
 		.fw_type = FW_1D_IMAGE,
 		.fsp_cfg = ddr_fsp1_cfg,
 		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp1_cfg),
 	},
 	{
-		/* P2 100mts 1D */
-		.drate = 100,
-		.fw_type = FW_1D_IMAGE,
-		.fsp_cfg = ddr_fsp2_cfg,
-		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp2_cfg),
-	},
-	{
 		/* P0 2400mts 2D */
 		.drate = 2400,
 		.fw_type = FW_2D_IMAGE,
@@ -1209,6 +1050,6 @@
 	.ddrphy_trained_csr_num = ARRAY_SIZE(ddr_ddrphy_trained_csr),
 	.ddrphy_pie = ddr_phy_pie,
 	.ddrphy_pie_num = ARRAY_SIZE(ddr_phy_pie),
-	.fsp_table = { 2400, 400, 100,},
+	.fsp_table = { 2400, 1066, },
 };
 
diff --git a/board/freescale/imx8mn_evk/ddr4_timing_ld.c b/board/freescale/imx8mn_evk/ddr4_timing_ld.c
new file mode 100644
index 0000000..983fc7d
--- /dev/null
+++ b/board/freescale/imx8mn_evk/ddr4_timing_ld.c
@@ -0,0 +1,1057 @@
+/*
+ * Copyright 2019 NXP
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * Generated code from MX8M_DDR_tool
+ * Align with uboot version:
+ * imx_v2018.03_4.14.78_1.0.0_ga ~ imx_v2018.04_4.19.35_1.1.0_ga
+ */
+
+#include <linux/kernel.h>
+#include <asm/arch/ddr.h>
+
+struct dram_cfg_param ddr_ddrc_cfg[] = {
+	/** Initialize DDRC registers **/
+	{ 0x3d400000, 0x81040010 },
+	{ 0x3d400030, 0x20 },
+	{ 0x3d400034, 0x221306 },
+	{ 0x3d400050, 0x210070 },
+	{ 0x3d400054, 0x10008 },
+	{ 0x3d400060, 0x0 },
+	{ 0x3d400064, 0x6100dc },
+	{ 0x3d4000c0, 0x0 },
+	{ 0x3d4000c4, 0x1000 },
+	{ 0x3d4000d0, 0xc00200c5 },
+	{ 0x3d4000d4, 0x500000 },
+	{ 0x3d4000dc, 0x2340105 },
+	{ 0x3d4000e0, 0x0 },
+	{ 0x3d4000e4, 0x110000 },
+	{ 0x3d4000e8, 0x2000600 },
+	{ 0x3d4000ec, 0x410 },
+	{ 0x3d4000f0, 0x20 },
+	{ 0x3d4000f4, 0xec7 },
+	{ 0x3d400100, 0xd0c1b0d },
+	{ 0x3d400104, 0x30313 },
+	{ 0x3d400108, 0x508060a },
+	{ 0x3d40010c, 0x400c },
+	{ 0x3d400110, 0x6030306 },
+	{ 0x3d400114, 0x4040302 },
+	{ 0x3d40011c, 0x404 },
+	{ 0x3d400120, 0x5050d08 },
+	{ 0x3d400124, 0x20308 },
+	{ 0x3d40012c, 0x1406010e },
+	{ 0x3d400130, 0x8 },
+	{ 0x3d40013c, 0x0 },
+	{ 0x3d400180, 0x1000040 },
+	{ 0x3d400184, 0x30d4 },
+	{ 0x3d400190, 0x38b8204 },
+	{ 0x3d400194, 0x2020303 },
+	{ 0x3d400198, 0x7f04011 },
+	{ 0x3d40019c, 0xb0 },
+	{ 0x3d4001a0, 0xe0400018 },
+	{ 0x3d4001a4, 0x48005a },
+	{ 0x3d4001a8, 0x80000000 },
+	{ 0x3d4001b0, 0x1 },
+	{ 0x3d4001b4, 0xb04 },
+	{ 0x3d4001b8, 0x4 },
+	{ 0x3d4001c0, 0x1 },
+	{ 0x3d4001c4, 0x0 },
+	{ 0x3d400200, 0x3f1f },
+	{ 0x3d400204, 0x3f0909 },
+	{ 0x3d400208, 0x700 },
+	{ 0x3d40020c, 0x0 },
+	{ 0x3d400210, 0x1f1f },
+	{ 0x3d400214, 0x7070707 },
+	{ 0x3d400218, 0x7070707 },
+	{ 0x3d40021c, 0xf07 },
+	{ 0x3d400220, 0x3f01 },
+	{ 0x3d400240, 0x600061c },
+	{ 0x3d400244, 0x1323 },
+	{ 0x3d400400, 0x100 },
+	{ 0x3d400250, 0x317d1a07 },
+	{ 0x3d400254, 0xf },
+	{ 0x3d40025c, 0x2a001b76 },
+	{ 0x3d400264, 0x7300b473 },
+	{ 0x3d40026c, 0x30000e06 },
+	{ 0x3d400300, 0x14 },
+	{ 0x3d40036c, 0x10 },
+	{ 0x3d400404, 0x13193 },
+	{ 0x3d400408, 0x6096 },
+	{ 0x3d400490, 0x1 },
+	{ 0x3d400494, 0x2000c00 },
+	{ 0x3d400498, 0x3c00db },
+	{ 0x3d40049c, 0x100009 },
+	{ 0x3d4004a0, 0x2 },
+	{ 0x3d402050, 0x210070 },
+	{ 0x3d402064, 0x400093 },
+	{ 0x3d4020dc, 0x40105 },
+	{ 0x3d4020e0, 0x0 },
+	{ 0x3d4020e8, 0x2000600 },
+	{ 0x3d4020ec, 0x10 },
+	{ 0x3d402100, 0xb081209 },
+	{ 0x3d402104, 0x2020d },
+	{ 0x3d402108, 0x5050309 },
+	{ 0x3d40210c, 0x400c },
+	{ 0x3d402110, 0x5030206 },
+	{ 0x3d402114, 0x3030202 },
+	{ 0x3d40211c, 0x303 },
+	{ 0x3d402120, 0x4040d06 },
+	{ 0x3d402124, 0x20208 },
+	{ 0x3d40212c, 0x1205010e },
+	{ 0x3d402130, 0x8 },
+	{ 0x3d40213c, 0x0 },
+	{ 0x3d402180, 0x1000040 },
+	{ 0x3d402190, 0x3858204 },
+	{ 0x3d402194, 0x2020303 },
+	{ 0x3d4021b4, 0x504 },
+	{ 0x3d4021b8, 0x4 },
+	{ 0x3d402240, 0x6000604 },
+	{ 0x3d4020f4, 0xec7 },
+};
+
+/* PHY Initialize Configuration */
+struct dram_cfg_param ddr_ddrphy_cfg[] = {
+	{ 0x1005f, 0x2fd },
+	{ 0x1015f, 0x2fd },
+	{ 0x1105f, 0x2fd },
+	{ 0x1115f, 0x2fd },
+	{ 0x11005f, 0x2fd },
+	{ 0x11015f, 0x2fd },
+	{ 0x11105f, 0x2fd },
+	{ 0x11115f, 0x2fd },
+	{ 0x55, 0x355 },
+	{ 0x1055, 0x355 },
+	{ 0x2055, 0x355 },
+	{ 0x3055, 0x355 },
+	{ 0x4055, 0x55 },
+	{ 0x5055, 0x55 },
+	{ 0x6055, 0x355 },
+	{ 0x7055, 0x355 },
+	{ 0x8055, 0x355 },
+	{ 0x9055, 0x355 },
+	{ 0x200c5, 0xb },
+	{ 0x1200c5, 0x6 },
+	{ 0x2002e, 0x1 },
+	{ 0x12002e, 0x1 },
+	{ 0x20024, 0x8 },
+	{ 0x2003a, 0x2 },
+	{ 0x120024, 0x8 },
+	{ 0x2003a, 0x2 },
+	{ 0x20056, 0xa },
+	{ 0x120056, 0xa },
+	{ 0x1004d, 0x1a },
+	{ 0x1014d, 0x1a },
+	{ 0x1104d, 0x1a },
+	{ 0x1114d, 0x1a },
+	{ 0x11004d, 0x1a },
+	{ 0x11014d, 0x1a },
+	{ 0x11104d, 0x1a },
+	{ 0x11114d, 0x1a },
+	{ 0x10049, 0xe38 },
+	{ 0x10149, 0xe38 },
+	{ 0x11049, 0xe38 },
+	{ 0x11149, 0xe38 },
+	{ 0x110049, 0xe38 },
+	{ 0x110149, 0xe38 },
+	{ 0x111049, 0xe38 },
+	{ 0x111149, 0xe38 },
+	{ 0x43, 0x63 },
+	{ 0x1043, 0x63 },
+	{ 0x2043, 0x63 },
+	{ 0x3043, 0x63 },
+	{ 0x4043, 0x63 },
+	{ 0x5043, 0x63 },
+	{ 0x6043, 0x63 },
+	{ 0x7043, 0x63 },
+	{ 0x8043, 0x63 },
+	{ 0x9043, 0x63 },
+	{ 0x20018, 0x1 },
+	{ 0x20075, 0x2 },
+	{ 0x20050, 0x0 },
+	{ 0x20008, 0x190 },
+	{ 0x120008, 0x10a },
+	{ 0x20088, 0x9 },
+	{ 0x200b2, 0x268 },
+	{ 0x10043, 0x5b1 },
+	{ 0x10143, 0x5b1 },
+	{ 0x11043, 0x5b1 },
+	{ 0x11143, 0x5b1 },
+	{ 0x1200b2, 0x268 },
+	{ 0x110043, 0x5b1 },
+	{ 0x110143, 0x5b1 },
+	{ 0x111043, 0x5b1 },
+	{ 0x111143, 0x5b1 },
+	{ 0x200fa, 0x1 },
+	{ 0x1200fa, 0x1 },
+	{ 0x20019, 0x5 },
+	{ 0x120019, 0x5 },
+	{ 0x200f0, 0x5555 },
+	{ 0x200f1, 0x5555 },
+	{ 0x200f2, 0x5555 },
+	{ 0x200f3, 0x5555 },
+	{ 0x200f4, 0x5555 },
+	{ 0x200f5, 0x5555 },
+	{ 0x200f6, 0x5555 },
+	{ 0x200f7, 0xf000 },
+	{ 0x20025, 0x0 },
+	{ 0x2002d, 0x0 },
+	{ 0x12002d, 0x0 },
+	{ 0x2005b, 0x7529 },
+	{ 0x2005c, 0x0 },
+	{ 0x200c7, 0x21 },
+	{ 0x200ca, 0x24 },
+	{ 0x200cc, 0x1f7 },
+	{ 0x1200c7, 0x21 },
+	{ 0x1200ca, 0x24 },
+	{ 0x1200cc, 0x1f7 },
+	{ 0x2007d, 0x212 },
+	{ 0x12007d, 0x212 },
+	{ 0x2007c, 0x61 },
+	{ 0x12007c, 0x61 },
+	{ 0x1004a, 0x500 },
+	{ 0x1104a, 0x500 },
+	{ 0x2002c, 0x0 },
+};
+
+/* ddr phy trained csr */
+struct dram_cfg_param ddr_ddrphy_trained_csr[] = {
+	{0x0200b2, 0x0},
+	{0x1200b2, 0x0},
+	{0x2200b2, 0x0},
+	{0x0200cb, 0x0},
+	{0x010043, 0x0},
+	{0x110043, 0x0},
+	{0x210043, 0x0},
+	{0x010143, 0x0},
+	{0x110143, 0x0},
+	{0x210143, 0x0},
+	{0x011043, 0x0},
+	{0x111043, 0x0},
+	{0x211043, 0x0},
+	{0x011143, 0x0},
+	{0x111143, 0x0},
+	{0x211143, 0x0},
+	{0x000080, 0x0},
+	{0x100080, 0x0},
+	{0x200080, 0x0},
+	{0x001080, 0x0},
+	{0x101080, 0x0},
+	{0x201080, 0x0},
+	{0x002080, 0x0},
+	{0x102080, 0x0},
+	{0x202080, 0x0},
+	{0x003080, 0x0},
+	{0x103080, 0x0},
+	{0x203080, 0x0},
+	{0x004080, 0x0},
+	{0x104080, 0x0},
+	{0x204080, 0x0},
+	{0x005080, 0x0},
+	{0x105080, 0x0},
+	{0x205080, 0x0},
+	{0x006080, 0x0},
+	{0x106080, 0x0},
+	{0x206080, 0x0},
+	{0x007080, 0x0},
+	{0x107080, 0x0},
+	{0x207080, 0x0},
+	{0x008080, 0x0},
+	{0x108080, 0x0},
+	{0x208080, 0x0},
+	{0x009080, 0x0},
+	{0x109080, 0x0},
+	{0x209080, 0x0},
+	{0x010080, 0x0},
+	{0x110080, 0x0},
+	{0x210080, 0x0},
+	{0x010180, 0x0},
+	{0x110180, 0x0},
+	{0x210180, 0x0},
+	{0x010081, 0x0},
+	{0x110081, 0x0},
+	{0x210081, 0x0},
+	{0x010181, 0x0},
+	{0x110181, 0x0},
+	{0x210181, 0x0},
+	{0x010082, 0x0},
+	{0x110082, 0x0},
+	{0x210082, 0x0},
+	{0x010182, 0x0},
+	{0x110182, 0x0},
+	{0x210182, 0x0},
+	{0x010083, 0x0},
+	{0x110083, 0x0},
+	{0x210083, 0x0},
+	{0x010183, 0x0},
+	{0x110183, 0x0},
+	{0x210183, 0x0},
+	{0x011080, 0x0},
+	{0x111080, 0x0},
+	{0x211080, 0x0},
+	{0x011180, 0x0},
+	{0x111180, 0x0},
+	{0x211180, 0x0},
+	{0x011081, 0x0},
+	{0x111081, 0x0},
+	{0x211081, 0x0},
+	{0x011181, 0x0},
+	{0x111181, 0x0},
+	{0x211181, 0x0},
+	{0x011082, 0x0},
+	{0x111082, 0x0},
+	{0x211082, 0x0},
+	{0x011182, 0x0},
+	{0x111182, 0x0},
+	{0x211182, 0x0},
+	{0x011083, 0x0},
+	{0x111083, 0x0},
+	{0x211083, 0x0},
+	{0x011183, 0x0},
+	{0x111183, 0x0},
+	{0x211183, 0x0},
+	{0x0100d0, 0x0},
+	{0x1100d0, 0x0},
+	{0x2100d0, 0x0},
+	{0x0101d0, 0x0},
+	{0x1101d0, 0x0},
+	{0x2101d0, 0x0},
+	{0x0100d1, 0x0},
+	{0x1100d1, 0x0},
+	{0x2100d1, 0x0},
+	{0x0101d1, 0x0},
+	{0x1101d1, 0x0},
+	{0x2101d1, 0x0},
+	{0x0100d2, 0x0},
+	{0x1100d2, 0x0},
+	{0x2100d2, 0x0},
+	{0x0101d2, 0x0},
+	{0x1101d2, 0x0},
+	{0x2101d2, 0x0},
+	{0x0100d3, 0x0},
+	{0x1100d3, 0x0},
+	{0x2100d3, 0x0},
+	{0x0101d3, 0x0},
+	{0x1101d3, 0x0},
+	{0x2101d3, 0x0},
+	{0x0110d0, 0x0},
+	{0x1110d0, 0x0},
+	{0x2110d0, 0x0},
+	{0x0111d0, 0x0},
+	{0x1111d0, 0x0},
+	{0x2111d0, 0x0},
+	{0x0110d1, 0x0},
+	{0x1110d1, 0x0},
+	{0x2110d1, 0x0},
+	{0x0111d1, 0x0},
+	{0x1111d1, 0x0},
+	{0x2111d1, 0x0},
+	{0x0110d2, 0x0},
+	{0x1110d2, 0x0},
+	{0x2110d2, 0x0},
+	{0x0111d2, 0x0},
+	{0x1111d2, 0x0},
+	{0x2111d2, 0x0},
+	{0x0110d3, 0x0},
+	{0x1110d3, 0x0},
+	{0x2110d3, 0x0},
+	{0x0111d3, 0x0},
+	{0x1111d3, 0x0},
+	{0x2111d3, 0x0},
+	{0x010068, 0x0},
+	{0x010168, 0x0},
+	{0x010268, 0x0},
+	{0x010368, 0x0},
+	{0x010468, 0x0},
+	{0x010568, 0x0},
+	{0x010668, 0x0},
+	{0x010768, 0x0},
+	{0x010868, 0x0},
+	{0x010069, 0x0},
+	{0x010169, 0x0},
+	{0x010269, 0x0},
+	{0x010369, 0x0},
+	{0x010469, 0x0},
+	{0x010569, 0x0},
+	{0x010669, 0x0},
+	{0x010769, 0x0},
+	{0x010869, 0x0},
+	{0x01006a, 0x0},
+	{0x01016a, 0x0},
+	{0x01026a, 0x0},
+	{0x01036a, 0x0},
+	{0x01046a, 0x0},
+	{0x01056a, 0x0},
+	{0x01066a, 0x0},
+	{0x01076a, 0x0},
+	{0x01086a, 0x0},
+	{0x01006b, 0x0},
+	{0x01016b, 0x0},
+	{0x01026b, 0x0},
+	{0x01036b, 0x0},
+	{0x01046b, 0x0},
+	{0x01056b, 0x0},
+	{0x01066b, 0x0},
+	{0x01076b, 0x0},
+	{0x01086b, 0x0},
+	{0x011068, 0x0},
+	{0x011168, 0x0},
+	{0x011268, 0x0},
+	{0x011368, 0x0},
+	{0x011468, 0x0},
+	{0x011568, 0x0},
+	{0x011668, 0x0},
+	{0x011768, 0x0},
+	{0x011868, 0x0},
+	{0x011069, 0x0},
+	{0x011169, 0x0},
+	{0x011269, 0x0},
+	{0x011369, 0x0},
+	{0x011469, 0x0},
+	{0x011569, 0x0},
+	{0x011669, 0x0},
+	{0x011769, 0x0},
+	{0x011869, 0x0},
+	{0x01106a, 0x0},
+	{0x01116a, 0x0},
+	{0x01126a, 0x0},
+	{0x01136a, 0x0},
+	{0x01146a, 0x0},
+	{0x01156a, 0x0},
+	{0x01166a, 0x0},
+	{0x01176a, 0x0},
+	{0x01186a, 0x0},
+	{0x01106b, 0x0},
+	{0x01116b, 0x0},
+	{0x01126b, 0x0},
+	{0x01136b, 0x0},
+	{0x01146b, 0x0},
+	{0x01156b, 0x0},
+	{0x01166b, 0x0},
+	{0x01176b, 0x0},
+	{0x01186b, 0x0},
+	{0x01008c, 0x0},
+	{0x11008c, 0x0},
+	{0x21008c, 0x0},
+	{0x01018c, 0x0},
+	{0x11018c, 0x0},
+	{0x21018c, 0x0},
+	{0x01008d, 0x0},
+	{0x11008d, 0x0},
+	{0x21008d, 0x0},
+	{0x01018d, 0x0},
+	{0x11018d, 0x0},
+	{0x21018d, 0x0},
+	{0x01008e, 0x0},
+	{0x11008e, 0x0},
+	{0x21008e, 0x0},
+	{0x01018e, 0x0},
+	{0x11018e, 0x0},
+	{0x21018e, 0x0},
+	{0x01008f, 0x0},
+	{0x11008f, 0x0},
+	{0x21008f, 0x0},
+	{0x01018f, 0x0},
+	{0x11018f, 0x0},
+	{0x21018f, 0x0},
+	{0x01108c, 0x0},
+	{0x11108c, 0x0},
+	{0x21108c, 0x0},
+	{0x01118c, 0x0},
+	{0x11118c, 0x0},
+	{0x21118c, 0x0},
+	{0x01108d, 0x0},
+	{0x11108d, 0x0},
+	{0x21108d, 0x0},
+	{0x01118d, 0x0},
+	{0x11118d, 0x0},
+	{0x21118d, 0x0},
+	{0x01108e, 0x0},
+	{0x11108e, 0x0},
+	{0x21108e, 0x0},
+	{0x01118e, 0x0},
+	{0x11118e, 0x0},
+	{0x21118e, 0x0},
+	{0x01108f, 0x0},
+	{0x11108f, 0x0},
+	{0x21108f, 0x0},
+	{0x01118f, 0x0},
+	{0x11118f, 0x0},
+	{0x21118f, 0x0},
+	{0x0100c0, 0x0},
+	{0x1100c0, 0x0},
+	{0x2100c0, 0x0},
+	{0x0101c0, 0x0},
+	{0x1101c0, 0x0},
+	{0x2101c0, 0x0},
+	{0x0102c0, 0x0},
+	{0x1102c0, 0x0},
+	{0x2102c0, 0x0},
+	{0x0103c0, 0x0},
+	{0x1103c0, 0x0},
+	{0x2103c0, 0x0},
+	{0x0104c0, 0x0},
+	{0x1104c0, 0x0},
+	{0x2104c0, 0x0},
+	{0x0105c0, 0x0},
+	{0x1105c0, 0x0},
+	{0x2105c0, 0x0},
+	{0x0106c0, 0x0},
+	{0x1106c0, 0x0},
+	{0x2106c0, 0x0},
+	{0x0107c0, 0x0},
+	{0x1107c0, 0x0},
+	{0x2107c0, 0x0},
+	{0x0108c0, 0x0},
+	{0x1108c0, 0x0},
+	{0x2108c0, 0x0},
+	{0x0100c1, 0x0},
+	{0x1100c1, 0x0},
+	{0x2100c1, 0x0},
+	{0x0101c1, 0x0},
+	{0x1101c1, 0x0},
+	{0x2101c1, 0x0},
+	{0x0102c1, 0x0},
+	{0x1102c1, 0x0},
+	{0x2102c1, 0x0},
+	{0x0103c1, 0x0},
+	{0x1103c1, 0x0},
+	{0x2103c1, 0x0},
+	{0x0104c1, 0x0},
+	{0x1104c1, 0x0},
+	{0x2104c1, 0x0},
+	{0x0105c1, 0x0},
+	{0x1105c1, 0x0},
+	{0x2105c1, 0x0},
+	{0x0106c1, 0x0},
+	{0x1106c1, 0x0},
+	{0x2106c1, 0x0},
+	{0x0107c1, 0x0},
+	{0x1107c1, 0x0},
+	{0x2107c1, 0x0},
+	{0x0108c1, 0x0},
+	{0x1108c1, 0x0},
+	{0x2108c1, 0x0},
+	{0x0100c2, 0x0},
+	{0x1100c2, 0x0},
+	{0x2100c2, 0x0},
+	{0x0101c2, 0x0},
+	{0x1101c2, 0x0},
+	{0x2101c2, 0x0},
+	{0x0102c2, 0x0},
+	{0x1102c2, 0x0},
+	{0x2102c2, 0x0},
+	{0x0103c2, 0x0},
+	{0x1103c2, 0x0},
+	{0x2103c2, 0x0},
+	{0x0104c2, 0x0},
+	{0x1104c2, 0x0},
+	{0x2104c2, 0x0},
+	{0x0105c2, 0x0},
+	{0x1105c2, 0x0},
+	{0x2105c2, 0x0},
+	{0x0106c2, 0x0},
+	{0x1106c2, 0x0},
+	{0x2106c2, 0x0},
+	{0x0107c2, 0x0},
+	{0x1107c2, 0x0},
+	{0x2107c2, 0x0},
+	{0x0108c2, 0x0},
+	{0x1108c2, 0x0},
+	{0x2108c2, 0x0},
+	{0x0100c3, 0x0},
+	{0x1100c3, 0x0},
+	{0x2100c3, 0x0},
+	{0x0101c3, 0x0},
+	{0x1101c3, 0x0},
+	{0x2101c3, 0x0},
+	{0x0102c3, 0x0},
+	{0x1102c3, 0x0},
+	{0x2102c3, 0x0},
+	{0x0103c3, 0x0},
+	{0x1103c3, 0x0},
+	{0x2103c3, 0x0},
+	{0x0104c3, 0x0},
+	{0x1104c3, 0x0},
+	{0x2104c3, 0x0},
+	{0x0105c3, 0x0},
+	{0x1105c3, 0x0},
+	{0x2105c3, 0x0},
+	{0x0106c3, 0x0},
+	{0x1106c3, 0x0},
+	{0x2106c3, 0x0},
+	{0x0107c3, 0x0},
+	{0x1107c3, 0x0},
+	{0x2107c3, 0x0},
+	{0x0108c3, 0x0},
+	{0x1108c3, 0x0},
+	{0x2108c3, 0x0},
+	{0x0110c0, 0x0},
+	{0x1110c0, 0x0},
+	{0x2110c0, 0x0},
+	{0x0111c0, 0x0},
+	{0x1111c0, 0x0},
+	{0x2111c0, 0x0},
+	{0x0112c0, 0x0},
+	{0x1112c0, 0x0},
+	{0x2112c0, 0x0},
+	{0x0113c0, 0x0},
+	{0x1113c0, 0x0},
+	{0x2113c0, 0x0},
+	{0x0114c0, 0x0},
+	{0x1114c0, 0x0},
+	{0x2114c0, 0x0},
+	{0x0115c0, 0x0},
+	{0x1115c0, 0x0},
+	{0x2115c0, 0x0},
+	{0x0116c0, 0x0},
+	{0x1116c0, 0x0},
+	{0x2116c0, 0x0},
+	{0x0117c0, 0x0},
+	{0x1117c0, 0x0},
+	{0x2117c0, 0x0},
+	{0x0118c0, 0x0},
+	{0x1118c0, 0x0},
+	{0x2118c0, 0x0},
+	{0x0110c1, 0x0},
+	{0x1110c1, 0x0},
+	{0x2110c1, 0x0},
+	{0x0111c1, 0x0},
+	{0x1111c1, 0x0},
+	{0x2111c1, 0x0},
+	{0x0112c1, 0x0},
+	{0x1112c1, 0x0},
+	{0x2112c1, 0x0},
+	{0x0113c1, 0x0},
+	{0x1113c1, 0x0},
+	{0x2113c1, 0x0},
+	{0x0114c1, 0x0},
+	{0x1114c1, 0x0},
+	{0x2114c1, 0x0},
+	{0x0115c1, 0x0},
+	{0x1115c1, 0x0},
+	{0x2115c1, 0x0},
+	{0x0116c1, 0x0},
+	{0x1116c1, 0x0},
+	{0x2116c1, 0x0},
+	{0x0117c1, 0x0},
+	{0x1117c1, 0x0},
+	{0x2117c1, 0x0},
+	{0x0118c1, 0x0},
+	{0x1118c1, 0x0},
+	{0x2118c1, 0x0},
+	{0x0110c2, 0x0},
+	{0x1110c2, 0x0},
+	{0x2110c2, 0x0},
+	{0x0111c2, 0x0},
+	{0x1111c2, 0x0},
+	{0x2111c2, 0x0},
+	{0x0112c2, 0x0},
+	{0x1112c2, 0x0},
+	{0x2112c2, 0x0},
+	{0x0113c2, 0x0},
+	{0x1113c2, 0x0},
+	{0x2113c2, 0x0},
+	{0x0114c2, 0x0},
+	{0x1114c2, 0x0},
+	{0x2114c2, 0x0},
+	{0x0115c2, 0x0},
+	{0x1115c2, 0x0},
+	{0x2115c2, 0x0},
+	{0x0116c2, 0x0},
+	{0x1116c2, 0x0},
+	{0x2116c2, 0x0},
+	{0x0117c2, 0x0},
+	{0x1117c2, 0x0},
+	{0x2117c2, 0x0},
+	{0x0118c2, 0x0},
+	{0x1118c2, 0x0},
+	{0x2118c2, 0x0},
+	{0x0110c3, 0x0},
+	{0x1110c3, 0x0},
+	{0x2110c3, 0x0},
+	{0x0111c3, 0x0},
+	{0x1111c3, 0x0},
+	{0x2111c3, 0x0},
+	{0x0112c3, 0x0},
+	{0x1112c3, 0x0},
+	{0x2112c3, 0x0},
+	{0x0113c3, 0x0},
+	{0x1113c3, 0x0},
+	{0x2113c3, 0x0},
+	{0x0114c3, 0x0},
+	{0x1114c3, 0x0},
+	{0x2114c3, 0x0},
+	{0x0115c3, 0x0},
+	{0x1115c3, 0x0},
+	{0x2115c3, 0x0},
+	{0x0116c3, 0x0},
+	{0x1116c3, 0x0},
+	{0x2116c3, 0x0},
+	{0x0117c3, 0x0},
+	{0x1117c3, 0x0},
+	{0x2117c3, 0x0},
+	{0x0118c3, 0x0},
+	{0x1118c3, 0x0},
+	{0x2118c3, 0x0},
+	{0x010020, 0x0},
+	{0x110020, 0x0},
+	{0x210020, 0x0},
+	{0x011020, 0x0},
+	{0x111020, 0x0},
+	{0x211020, 0x0},
+	{0x02007d, 0x0},
+	{0x12007d, 0x0},
+	{0x22007d, 0x0},
+	{0x010040, 0x0},
+	{0x010140, 0x0},
+	{0x010240, 0x0},
+	{0x010340, 0x0},
+	{0x010440, 0x0},
+	{0x010540, 0x0},
+	{0x010640, 0x0},
+	{0x010740, 0x0},
+	{0x010840, 0x0},
+	{0x010030, 0x0},
+	{0x010130, 0x0},
+	{0x010230, 0x0},
+	{0x010330, 0x0},
+	{0x010430, 0x0},
+	{0x010530, 0x0},
+	{0x010630, 0x0},
+	{0x010730, 0x0},
+	{0x010830, 0x0},
+	{0x011040, 0x0},
+	{0x011140, 0x0},
+	{0x011240, 0x0},
+	{0x011340, 0x0},
+	{0x011440, 0x0},
+	{0x011540, 0x0},
+	{0x011640, 0x0},
+	{0x011740, 0x0},
+	{0x011840, 0x0},
+	{0x011030, 0x0},
+	{0x011130, 0x0},
+	{0x011230, 0x0},
+	{0x011330, 0x0},
+	{0x011430, 0x0},
+	{0x011530, 0x0},
+	{0x011630, 0x0},
+	{0x011730, 0x0},
+	{0x011830, 0x0},
+};
+
+/* P0 message block paremeter for training firmware */
+struct dram_cfg_param ddr_fsp0_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54003, 0x640 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, 0x2830 },
+	{ 0x54006, 0x25e },
+	{ 0x54007, 0x1000 },
+	{ 0x54008, 0x101 },
+	{ 0x5400b, 0x31f },
+	{ 0x5400c, 0xc8 },
+	{ 0x5400d, 0x100 },
+	{ 0x54012, 0x1 },
+	{ 0x5402f, 0x234 },
+	{ 0x54030, 0x105 },
+	{ 0x54033, 0x200 },
+	{ 0x54034, 0x600 },
+	{ 0x54035, 0x410 },
+	{ 0x54036, 0x101 },
+	{ 0x5403f, 0x1221 },
+	{ 0x541fc, 0x100 },
+	{ 0xd0000, 0x1 },
+};
+
+
+/* P1 message block paremeter for training firmware */
+struct dram_cfg_param ddr_fsp1_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54002, 0x1 },
+	{ 0x54003, 0x42a },
+	{ 0x54004, 0x2 },
+	{ 0x54005, 0x2830 },
+	{ 0x54006, 0x25e },
+	{ 0x54007, 0x1000 },
+	{ 0x54008, 0x101 },
+	{ 0x5400b, 0x21f },
+	{ 0x5400c, 0xc8 },
+	{ 0x5400d, 0x100 },
+	{ 0x54012, 0x1 },
+	{ 0x5402f, 0x4 },
+	{ 0x54030, 0x105 },
+	{ 0x54033, 0x200 },
+	{ 0x54034, 0x600 },
+	{ 0x54035, 0x10 },
+	{ 0x54036, 0x101 },
+	{ 0x5403f, 0x1221 },
+	{ 0x541fc, 0x100 },
+	{ 0xd0000, 0x1 },
+};
+
+
+/* P0 2D message block paremeter for training firmware */
+struct dram_cfg_param ddr_fsp0_2d_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54003, 0x640 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, 0x2830 },
+	{ 0x54006, 0x25e },
+	{ 0x54007, 0x1000 },
+	{ 0x54008, 0x101 },
+	{ 0x5400b, 0x61 },
+	{ 0x5400c, 0xc8 },
+	{ 0x5400d, 0x100 },
+	{ 0x5400e, 0x1f7f },
+	{ 0x54012, 0x1 },
+	{ 0x5402f, 0x234 },
+	{ 0x54030, 0x105 },
+	{ 0x54033, 0x200 },
+	{ 0x54034, 0x600 },
+	{ 0x54035, 0x410 },
+	{ 0x54036, 0x101 },
+	{ 0x5403f, 0x1221 },
+	{ 0x541fc, 0x100 },
+	{ 0xd0000, 0x1 },
+};
+
+/* DRAM PHY init engine image */
+struct dram_cfg_param ddr_phy_pie[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x90000, 0x10 },
+	{ 0x90001, 0x400 },
+	{ 0x90002, 0x10e },
+	{ 0x90003, 0x0 },
+	{ 0x90004, 0x0 },
+	{ 0x90005, 0x8 },
+	{ 0x90029, 0xb },
+	{ 0x9002a, 0x480 },
+	{ 0x9002b, 0x109 },
+	{ 0x9002c, 0x8 },
+	{ 0x9002d, 0x448 },
+	{ 0x9002e, 0x139 },
+	{ 0x9002f, 0x8 },
+	{ 0x90030, 0x478 },
+	{ 0x90031, 0x109 },
+	{ 0x90032, 0x2 },
+	{ 0x90033, 0x10 },
+	{ 0x90034, 0x139 },
+	{ 0x90035, 0xb },
+	{ 0x90036, 0x7c0 },
+	{ 0x90037, 0x139 },
+	{ 0x90038, 0x44 },
+	{ 0x90039, 0x633 },
+	{ 0x9003a, 0x159 },
+	{ 0x9003b, 0x14f },
+	{ 0x9003c, 0x630 },
+	{ 0x9003d, 0x159 },
+	{ 0x9003e, 0x47 },
+	{ 0x9003f, 0x633 },
+	{ 0x90040, 0x149 },
+	{ 0x90041, 0x4f },
+	{ 0x90042, 0x633 },
+	{ 0x90043, 0x179 },
+	{ 0x90044, 0x8 },
+	{ 0x90045, 0xe0 },
+	{ 0x90046, 0x109 },
+	{ 0x90047, 0x0 },
+	{ 0x90048, 0x7c8 },
+	{ 0x90049, 0x109 },
+	{ 0x9004a, 0x0 },
+	{ 0x9004b, 0x1 },
+	{ 0x9004c, 0x8 },
+	{ 0x9004d, 0x0 },
+	{ 0x9004e, 0x45a },
+	{ 0x9004f, 0x9 },
+	{ 0x90050, 0x0 },
+	{ 0x90051, 0x448 },
+	{ 0x90052, 0x109 },
+	{ 0x90053, 0x40 },
+	{ 0x90054, 0x633 },
+	{ 0x90055, 0x179 },
+	{ 0x90056, 0x1 },
+	{ 0x90057, 0x618 },
+	{ 0x90058, 0x109 },
+	{ 0x90059, 0x40c0 },
+	{ 0x9005a, 0x633 },
+	{ 0x9005b, 0x149 },
+	{ 0x9005c, 0x8 },
+	{ 0x9005d, 0x4 },
+	{ 0x9005e, 0x48 },
+	{ 0x9005f, 0x4040 },
+	{ 0x90060, 0x633 },
+	{ 0x90061, 0x149 },
+	{ 0x90062, 0x0 },
+	{ 0x90063, 0x4 },
+	{ 0x90064, 0x48 },
+	{ 0x90065, 0x40 },
+	{ 0x90066, 0x633 },
+	{ 0x90067, 0x149 },
+	{ 0x90068, 0x10 },
+	{ 0x90069, 0x4 },
+	{ 0x9006a, 0x18 },
+	{ 0x9006b, 0x0 },
+	{ 0x9006c, 0x4 },
+	{ 0x9006d, 0x78 },
+	{ 0x9006e, 0x549 },
+	{ 0x9006f, 0x633 },
+	{ 0x90070, 0x159 },
+	{ 0x90071, 0xd49 },
+	{ 0x90072, 0x633 },
+	{ 0x90073, 0x159 },
+	{ 0x90074, 0x94a },
+	{ 0x90075, 0x633 },
+	{ 0x90076, 0x159 },
+	{ 0x90077, 0x441 },
+	{ 0x90078, 0x633 },
+	{ 0x90079, 0x149 },
+	{ 0x9007a, 0x42 },
+	{ 0x9007b, 0x633 },
+	{ 0x9007c, 0x149 },
+	{ 0x9007d, 0x1 },
+	{ 0x9007e, 0x633 },
+	{ 0x9007f, 0x149 },
+	{ 0x90080, 0x0 },
+	{ 0x90081, 0xe0 },
+	{ 0x90082, 0x109 },
+	{ 0x90083, 0xa },
+	{ 0x90084, 0x10 },
+	{ 0x90085, 0x109 },
+	{ 0x90086, 0x9 },
+	{ 0x90087, 0x3c0 },
+	{ 0x90088, 0x149 },
+	{ 0x90089, 0x9 },
+	{ 0x9008a, 0x3c0 },
+	{ 0x9008b, 0x159 },
+	{ 0x9008c, 0x18 },
+	{ 0x9008d, 0x10 },
+	{ 0x9008e, 0x109 },
+	{ 0x9008f, 0x0 },
+	{ 0x90090, 0x3c0 },
+	{ 0x90091, 0x109 },
+	{ 0x90092, 0x18 },
+	{ 0x90093, 0x4 },
+	{ 0x90094, 0x48 },
+	{ 0x90095, 0x18 },
+	{ 0x90096, 0x4 },
+	{ 0x90097, 0x58 },
+	{ 0x90098, 0xb },
+	{ 0x90099, 0x10 },
+	{ 0x9009a, 0x109 },
+	{ 0x9009b, 0x1 },
+	{ 0x9009c, 0x10 },
+	{ 0x9009d, 0x109 },
+	{ 0x9009e, 0x5 },
+	{ 0x9009f, 0x7c0 },
+	{ 0x900a0, 0x109 },
+	{ 0x900a1, 0x0 },
+	{ 0x900a2, 0x8140 },
+	{ 0x900a3, 0x10c },
+	{ 0x900a4, 0x10 },
+	{ 0x900a5, 0x8138 },
+	{ 0x900a6, 0x10c },
+	{ 0x900a7, 0x8 },
+	{ 0x900a8, 0x7c8 },
+	{ 0x900a9, 0x101 },
+	{ 0x900aa, 0x8 },
+	{ 0x900ab, 0x448 },
+	{ 0x900ac, 0x109 },
+	{ 0x900ad, 0xf },
+	{ 0x900ae, 0x7c0 },
+	{ 0x900af, 0x109 },
+	{ 0x900b0, 0x47 },
+	{ 0x900b1, 0x630 },
+	{ 0x900b2, 0x109 },
+	{ 0x900b3, 0x8 },
+	{ 0x900b4, 0x618 },
+	{ 0x900b5, 0x109 },
+	{ 0x900b6, 0x8 },
+	{ 0x900b7, 0xe0 },
+	{ 0x900b8, 0x109 },
+	{ 0x900b9, 0x0 },
+	{ 0x900ba, 0x7c8 },
+	{ 0x900bb, 0x109 },
+	{ 0x900bc, 0x8 },
+	{ 0x900bd, 0x8140 },
+	{ 0x900be, 0x10c },
+	{ 0x900bf, 0x0 },
+	{ 0x900c0, 0x1 },
+	{ 0x900c1, 0x8 },
+	{ 0x900c2, 0x8 },
+	{ 0x900c3, 0x4 },
+	{ 0x900c4, 0x8 },
+	{ 0x900c5, 0x8 },
+	{ 0x900c6, 0x7c8 },
+	{ 0x900c7, 0x101 },
+	{ 0x90006, 0x0 },
+	{ 0x90007, 0x0 },
+	{ 0x90008, 0x8 },
+	{ 0x90009, 0x0 },
+	{ 0x9000a, 0x0 },
+	{ 0x9000b, 0x0 },
+	{ 0xd00e7, 0x400 },
+	{ 0x90017, 0x0 },
+	{ 0x90026, 0x2b },
+	{ 0x2000b, 0x32 },
+	{ 0x2000c, 0x64 },
+	{ 0x2000d, 0x3e8 },
+	{ 0x2000e, 0x2c },
+	{ 0x12000b, 0x21 },
+	{ 0x12000c, 0x42 },
+	{ 0x12000d, 0x29a },
+	{ 0x12000e, 0x21 },
+	{ 0x9000c, 0x0 },
+	{ 0x9000d, 0x173 },
+	{ 0x9000e, 0x60 },
+	{ 0x9000f, 0x6110 },
+	{ 0x90010, 0x2152 },
+	{ 0x90011, 0xdfbd },
+	{ 0x90012, 0xffff },
+	{ 0x90013, 0x6152 },
+	{ 0x20089, 0x1 },
+	{ 0x20088, 0x19 },
+	{ 0xc0080, 0x0 },
+	{ 0xd0000, 0x1 }
+};
+
+struct dram_fsp_msg ddr_dram_fsp_msg[] = {
+	{
+		/* P0 1600mts 1D */
+		.drate = 1600,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = ddr_fsp0_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_cfg),
+	},
+	{
+		/* P1 1066mts 1D */
+		.drate = 1066,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = ddr_fsp1_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp1_cfg),
+	},
+	{
+		/* P0 1600mts 2D */
+		.drate = 1600,
+		.fw_type = FW_2D_IMAGE,
+		.fsp_cfg = ddr_fsp0_2d_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_2d_cfg),
+	},
+};
+
+/* ddr timing config params */
+struct dram_timing_info dram_timing = {
+	.ddrc_cfg = ddr_ddrc_cfg,
+	.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg),
+	.ddrphy_cfg = ddr_ddrphy_cfg,
+	.ddrphy_cfg_num = ARRAY_SIZE(ddr_ddrphy_cfg),
+	.fsp_msg = ddr_dram_fsp_msg,
+	.fsp_msg_num = ARRAY_SIZE(ddr_dram_fsp_msg),
+	.ddrphy_trained_csr = ddr_ddrphy_trained_csr,
+	.ddrphy_trained_csr_num = ARRAY_SIZE(ddr_ddrphy_trained_csr),
+	.ddrphy_pie = ddr_phy_pie,
+	.ddrphy_pie_num = ARRAY_SIZE(ddr_phy_pie),
+	.fsp_table = { 1600, 1066, },
+};
+
diff --git a/board/freescale/imx8mn_evk/imximage-8mn-ddr4.cfg b/board/freescale/imx8mn_evk/imximage-8mn-ddr4.cfg
new file mode 100644
index 0000000..22aec26
--- /dev/null
+++ b/board/freescale/imx8mn_evk/imximage-8mn-ddr4.cfg
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2021 NXP
+ */
+
+#define __ASSEMBLY__
+
+ROM_VERSION	v2
+BOOT_FROM	sd
+LOADER		mkimage.flash.mkimage	0x912000
diff --git a/board/freescale/imx8mn_evk/lpddr4_timing.c b/board/freescale/imx8mn_evk/lpddr4_timing.c
new file mode 100644
index 0000000..671e924
--- /dev/null
+++ b/board/freescale/imx8mn_evk/lpddr4_timing.c
@@ -0,0 +1,1587 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ *
+ * Generated code from MX8M_DDR_tool
+ * Align with uboot-imx_v2018.03_4.14.78_1.0.0_ga
+ */
+
+#include <linux/kernel.h>
+#include <asm/arch/ddr.h>
+
+struct dram_cfg_param ddr_ddrc_cfg[] = {
+	{0x3d400020, 0x00000213},
+	{0x3d400024, 0x0003e800},
+	{0x3d400030, 0x00000120},
+	{0x3d400000, 0xa3080020},
+	{0x3d400064, 0x006100e0},
+	{0x3d4000d0, 0xc003061c},
+	{0x3d4000d4, 0x009e0000},
+	{0x3d4000dc, 0x00d4002d},
+	{0x3d4000e0, 0x00310000},
+	{0x3d4000e8, 0x0066004d},
+	{0x3d4000ec, 0x0016004a},
+	{0x3d400100, 0x1a201b22},
+	{0x3d400104, 0x00060633},
+	{0x3d40010c, 0x00c0c000},
+	{0x3d400110, 0x0f04080f},
+	{0x3d400114, 0x02040c0c},
+	{0x3d400118, 0x01010007},
+	{0x3d40011c, 0x00000401},
+	{0x3d400130, 0x00020600},
+	{0x3d400134, 0x0c100002},
+	{0x3d400138, 0x000000e6},
+	{0x3d400144, 0x00a00050},
+	{0x3d400180, 0x03200018},
+	{0x3d400184, 0x028061a8},
+	{0x3d400188, 0x00000000},
+	{0x3d400190, 0x0497820a},
+	{0x3d4001b4, 0x0000170a},
+	{0x3d400108, 0x070e1617},
+	{0x3d4001c0, 0x00000001},
+	{0x3d400194, 0x00080303},
+	{0x3d4001a0, 0xe0400018},
+	{0x3d4001a4, 0x00df00e4},
+	{0x3d4001a8, 0x80000000},
+	{0x3d4001b0, 0x00000011},
+	{0x3d4001c4, 0x00000001},
+	{0x3d4000f4, 0x00000c99},
+	{0x3d400200, 0x00000017},
+	{0x3d400204, 0x00080808},
+	{0x3d400208, 0x00000000},
+	{0x3d40020c, 0x00000000},
+	{0x3d400210, 0x00001f1f},
+	{0x3d400214, 0x07070707},
+	{0x3d400218, 0x07070707},
+	{0x3d40021c, 0x00000f0f},
+	{0x3d400250, 0x29001701},
+	{0x3d400254, 0x0000002c},
+	{0x3d40025c, 0x04000030},
+	{0x3d400264, 0x900093e7},
+	{0x3d40026c, 0x20005574},
+	{0x3d400400, 0x00000111},
+	{0x3d400408, 0x000072ff},
+	{0x3d400494, 0x02100e07},
+	{0x3d400498, 0x00620096},
+	{0x3d40049c, 0x01100e07},
+	{0x3d4004a0, 0x00c8012c},
+	{0x3d402020, 0x00000011},
+	{0x3d402024, 0x00007d00},
+	{0x3d402050, 0x0020d040},
+	{0x3d402064, 0x000c001d},
+	{0x3d4020f4, 0x00000c99},
+	{0x3d402100, 0x0a040305},
+	{0x3d402104, 0x00030407},
+	{0x3d402108, 0x0203060b},
+	{0x3d40210c, 0x00505000},
+	{0x3d402110, 0x02040202},
+	{0x3d402114, 0x02030202},
+	{0x3d402118, 0x01010004},
+	{0x3d40211c, 0x00000301},
+	{0x3d402130, 0x00020300},
+	{0x3d402134, 0x0a100002},
+	{0x3d402138, 0x0000001d},
+	{0x3d402144, 0x0014000a},
+	{0x3d402180, 0x00650004},
+	{0x3d402190, 0x03818200},
+	{0x3d402194, 0x00080303},
+	{0x3d4021b4, 0x00000100},
+	{0x3d4020dc, 0x00840000},
+	{0x3d4020e0, 0x00310000},
+	{0x3d4020e8, 0x0066004d},
+	{0x3d4020ec, 0x0016004a},
+	{0x3d403020, 0x00000011},
+	{0x3d403024, 0x00001f40},
+	{0x3d403050, 0x0020d040},
+	{0x3d403064, 0x00030007},
+	{0x3d4030f4, 0x00000c99},
+	{0x3d403100, 0x0a010102},
+	{0x3d403104, 0x00030404},
+	{0x3d403108, 0x0203060b},
+	{0x3d40310c, 0x00505000},
+	{0x3d403110, 0x02040202},
+	{0x3d403114, 0x02030202},
+	{0x3d403118, 0x01010004},
+	{0x3d40311c, 0x00000301},
+	{0x3d403130, 0x00020300},
+	{0x3d403134, 0x0a100002},
+	{0x3d403138, 0x00000008},
+	{0x3d403144, 0x00050003},
+	{0x3d403180, 0x00190004},
+	{0x3d403190, 0x03818200},
+	{0x3d403194, 0x00080303},
+	{0x3d4031b4, 0x00000100},
+	{0x3d4030dc, 0x00840000},
+	{0x3d4030e0, 0x00310000},
+	{0x3d4030e8, 0x0066004d},
+	{0x3d4030ec, 0x0016004a},
+
+	/* default boot point */
+	{ 0x3d400028, 0x0 },
+};
+
+/* PHY Initialize Configuration */
+struct dram_cfg_param ddr_ddrphy_cfg[] = {
+	{0x000d0000, 0x00000000},
+	{0x000100a0, 0x00000000},
+	{0x000100a1, 0x00000001},
+	{0x000100a2, 0x00000002},
+	{0x000100a3, 0x00000003},
+	{0x000100a4, 0x00000004},
+	{0x000100a5, 0x00000005},
+	{0x000100a6, 0x00000006},
+	{0x000100a7, 0x00000007},
+	{0x000110a0, 0x00000000},
+	{0x000110a1, 0x00000001},
+	{0x000110a2, 0x00000003},
+	{0x000110a3, 0x00000004},
+	{0x000110a4, 0x00000005},
+	{0x000110a5, 0x00000002},
+	{0x000110a6, 0x00000007},
+	{0x000110a7, 0x00000006},
+	{0x0001005f, 0x0000015f},
+	{0x0001015f, 0x0000015f},
+	{0x0001105f, 0x0000015f},
+	{0x0001115f, 0x0000015f},
+	{0x0011005f, 0x0000015f},
+	{0x0011015f, 0x0000015f},
+	{0x0011105f, 0x0000015f},
+	{0x0011115f, 0x0000015f},
+	{0x0021005f, 0x0000015f},
+	{0x0021015f, 0x0000015f},
+	{0x0021105f, 0x0000015f},
+	{0x0021115f, 0x0000015f},
+	{0x00000055, 0x0000016f},
+	{0x00001055, 0x0000016f},
+	{0x00002055, 0x0000016f},
+	{0x00003055, 0x0000016f},
+	{0x00004055, 0x0000016f},
+	{0x00005055, 0x0000016f},
+	{0x00006055, 0x0000016f},
+	{0x00007055, 0x0000016f},
+	{0x00008055, 0x0000016f},
+	{0x00009055, 0x0000016f},
+	{0x000200c5, 0x00000019},
+	{0x001200c5, 0x00000007},
+	{0x002200c5, 0x00000007},
+	{0x0002002e, 0x00000002},
+	{0x0012002e, 0x00000002},
+	{0x0022002e, 0x00000002},
+	{0x00090204, 0x00000000},
+	{0x00190204, 0x00000000},
+	{0x00290204, 0x00000000},
+	{0x00020024, 0x000001a3},
+	{0x0002003a, 0x00000002},
+	{0x0002007d, 0x00000212},
+	{0x0002007c, 0x00000061},
+	{0x00120024, 0x000001a3},
+	{0x0002003a, 0x00000002},
+	{0x0012007d, 0x00000212},
+	{0x0012007c, 0x00000061},
+	{0x00220024, 0x000001a3},
+	{0x0002003a, 0x00000002},
+	{0x0022007d, 0x00000212},
+	{0x0022007c, 0x00000061},
+	{0x00020056, 0x00000003},
+	{0x00120056, 0x00000003},
+	{0x00220056, 0x00000003},
+	{0x0001004d, 0x00000f80},
+	{0x0001014d, 0x00000f80},
+	{0x0001104d, 0x00000f80},
+	{0x0001114d, 0x00000f80},
+	{0x0011004d, 0x00000f80},
+	{0x0011014d, 0x00000f80},
+	{0x0011104d, 0x00000f80},
+	{0x0011114d, 0x00000f80},
+	{0x0021004d, 0x00000f80},
+	{0x0021014d, 0x00000f80},
+	{0x0021104d, 0x00000f80},
+	{0x0021114d, 0x00000f80},
+	{0x00010049, 0x00000fbe},
+	{0x00010149, 0x00000fbe},
+	{0x00011049, 0x00000fbe},
+	{0x00011149, 0x00000fbe},
+	{0x00110049, 0x00000fbe},
+	{0x00110149, 0x00000fbe},
+	{0x00111049, 0x00000fbe},
+	{0x00111149, 0x00000fbe},
+	{0x00210049, 0x00000fbe},
+	{0x00210149, 0x00000fbe},
+	{0x00211049, 0x00000fbe},
+	{0x00211149, 0x00000fbe},
+	{0x00000043, 0x00000063},
+	{0x00001043, 0x00000063},
+	{0x00002043, 0x00000063},
+	{0x00003043, 0x00000063},
+	{0x00004043, 0x00000063},
+	{0x00005043, 0x00000063},
+	{0x00006043, 0x00000063},
+	{0x00007043, 0x00000063},
+	{0x00008043, 0x00000063},
+	{0x00009043, 0x00000063},
+	{0x00020018, 0x00000001},
+	{0x00020075, 0x00000004},
+	{0x00020050, 0x00000000},
+	{0x00020008, 0x00000320},
+	{0x00120008, 0x00000064},
+	{0x00220008, 0x00000019},
+	{0x00020088, 0x00000009},
+	{0x000200b2, 0x000000dc},
+	{0x00010043, 0x000005a1},
+	{0x00010143, 0x000005a1},
+	{0x00011043, 0x000005a1},
+	{0x00011143, 0x000005a1},
+	{0x001200b2, 0x000000dc},
+	{0x00110043, 0x000005a1},
+	{0x00110143, 0x000005a1},
+	{0x00111043, 0x000005a1},
+	{0x00111143, 0x000005a1},
+	{0x002200b2, 0x000000dc},
+	{0x00210043, 0x000005a1},
+	{0x00210143, 0x000005a1},
+	{0x00211043, 0x000005a1},
+	{0x00211143, 0x000005a1},
+	{0x000200fa, 0x00000001},
+	{0x001200fa, 0x00000001},
+	{0x002200fa, 0x00000001},
+	{0x00020019, 0x00000001},
+	{0x00120019, 0x00000001},
+	{0x00220019, 0x00000001},
+	{0x000200f0, 0x00000660},
+	{0x000200f1, 0x00000000},
+	{0x000200f2, 0x00004444},
+	{0x000200f3, 0x00008888},
+	{0x000200f4, 0x00005665},
+	{0x000200f5, 0x00000000},
+	{0x000200f6, 0x00000000},
+	{0x000200f7, 0x0000f000},
+	{0x0001004a, 0x00000500},
+	{0x0001104a, 0x00000500},
+	{0x00020025, 0x00000000},
+	{0x0002002d, 0x00000000},
+	{0x0012002d, 0x00000000},
+	{0x0022002d, 0x00000000},
+	{0x0002002c, 0x00000000},
+	{0x000200c7, 0x00000021},
+	{0x000200ca, 0x00000024},
+	{0x000200cc, 0x000001f7},
+	{0x001200c7, 0x00000021},
+	{0x001200ca, 0x00000024},
+	{0x001200cc, 0x000001f7},
+	{0x002200c7, 0x00000021},
+	{0x002200ca, 0x00000024},
+	{0x002200cc, 0x000001f7},
+	{0x00020060, 0x00000002},
+	{0x000d0000, 0x00000001},
+};
+
+/* ddr phy trained csr */
+struct dram_cfg_param ddr_ddrphy_trained_csr[] = {
+	{0x0200b2, 0x0},
+	{0x1200b2, 0x0},
+	{0x2200b2, 0x0},
+	{0x0200cb, 0x0},
+	{0x010043, 0x0},
+	{0x110043, 0x0},
+	{0x210043, 0x0},
+	{0x010143, 0x0},
+	{0x110143, 0x0},
+	{0x210143, 0x0},
+	{0x011043, 0x0},
+	{0x111043, 0x0},
+	{0x211043, 0x0},
+	{0x011143, 0x0},
+	{0x111143, 0x0},
+	{0x211143, 0x0},
+	{0x000080, 0x0},
+	{0x100080, 0x0},
+	{0x200080, 0x0},
+	{0x001080, 0x0},
+	{0x101080, 0x0},
+	{0x201080, 0x0},
+	{0x002080, 0x0},
+	{0x102080, 0x0},
+	{0x202080, 0x0},
+	{0x003080, 0x0},
+	{0x103080, 0x0},
+	{0x203080, 0x0},
+	{0x004080, 0x0},
+	{0x104080, 0x0},
+	{0x204080, 0x0},
+	{0x005080, 0x0},
+	{0x105080, 0x0},
+	{0x205080, 0x0},
+	{0x006080, 0x0},
+	{0x106080, 0x0},
+	{0x206080, 0x0},
+	{0x007080, 0x0},
+	{0x107080, 0x0},
+	{0x207080, 0x0},
+	{0x008080, 0x0},
+	{0x108080, 0x0},
+	{0x208080, 0x0},
+	{0x009080, 0x0},
+	{0x109080, 0x0},
+	{0x209080, 0x0},
+	{0x010080, 0x0},
+	{0x110080, 0x0},
+	{0x210080, 0x0},
+	{0x010180, 0x0},
+	{0x110180, 0x0},
+	{0x210180, 0x0},
+	{0x011080, 0x0},
+	{0x111080, 0x0},
+	{0x211080, 0x0},
+	{0x011180, 0x0},
+	{0x111180, 0x0},
+	{0x211180, 0x0},
+	{0x010081, 0x0},
+	{0x110081, 0x0},
+	{0x210081, 0x0},
+	{0x010181, 0x0},
+	{0x110181, 0x0},
+	{0x210181, 0x0},
+	{0x011081, 0x0},
+	{0x111081, 0x0},
+	{0x211081, 0x0},
+	{0x011181, 0x0},
+	{0x111181, 0x0},
+	{0x211181, 0x0},
+	{0x0100d0, 0x0},
+	{0x1100d0, 0x0},
+	{0x2100d0, 0x0},
+	{0x0101d0, 0x0},
+	{0x1101d0, 0x0},
+	{0x2101d0, 0x0},
+	{0x0110d0, 0x0},
+	{0x1110d0, 0x0},
+	{0x2110d0, 0x0},
+	{0x0111d0, 0x0},
+	{0x1111d0, 0x0},
+	{0x2111d0, 0x0},
+	{0x0100d1, 0x0},
+	{0x1100d1, 0x0},
+	{0x2100d1, 0x0},
+	{0x0101d1, 0x0},
+	{0x1101d1, 0x0},
+	{0x2101d1, 0x0},
+	{0x0110d1, 0x0},
+	{0x1110d1, 0x0},
+	{0x2110d1, 0x0},
+	{0x0111d1, 0x0},
+	{0x1111d1, 0x0},
+	{0x2111d1, 0x0},
+	{0x010068, 0x0},
+	{0x010168, 0x0},
+	{0x010268, 0x0},
+	{0x010368, 0x0},
+	{0x010468, 0x0},
+	{0x010568, 0x0},
+	{0x010668, 0x0},
+	{0x010768, 0x0},
+	{0x010868, 0x0},
+	{0x011068, 0x0},
+	{0x011168, 0x0},
+	{0x011268, 0x0},
+	{0x011368, 0x0},
+	{0x011468, 0x0},
+	{0x011568, 0x0},
+	{0x011668, 0x0},
+	{0x011768, 0x0},
+	{0x011868, 0x0},
+	{0x010069, 0x0},
+	{0x010169, 0x0},
+	{0x010269, 0x0},
+	{0x010369, 0x0},
+	{0x010469, 0x0},
+	{0x010569, 0x0},
+	{0x010669, 0x0},
+	{0x010769, 0x0},
+	{0x010869, 0x0},
+	{0x011069, 0x0},
+	{0x011169, 0x0},
+	{0x011269, 0x0},
+	{0x011369, 0x0},
+	{0x011469, 0x0},
+	{0x011569, 0x0},
+	{0x011669, 0x0},
+	{0x011769, 0x0},
+	{0x011869, 0x0},
+	{0x01008c, 0x0},
+	{0x11008c, 0x0},
+	{0x21008c, 0x0},
+	{0x01018c, 0x0},
+	{0x11018c, 0x0},
+	{0x21018c, 0x0},
+	{0x01108c, 0x0},
+	{0x11108c, 0x0},
+	{0x21108c, 0x0},
+	{0x01118c, 0x0},
+	{0x11118c, 0x0},
+	{0x21118c, 0x0},
+	{0x01008d, 0x0},
+	{0x11008d, 0x0},
+	{0x21008d, 0x0},
+	{0x01018d, 0x0},
+	{0x11018d, 0x0},
+	{0x21018d, 0x0},
+	{0x01108d, 0x0},
+	{0x11108d, 0x0},
+	{0x21108d, 0x0},
+	{0x01118d, 0x0},
+	{0x11118d, 0x0},
+	{0x21118d, 0x0},
+	{0x0100c0, 0x0},
+	{0x1100c0, 0x0},
+	{0x2100c0, 0x0},
+	{0x0101c0, 0x0},
+	{0x1101c0, 0x0},
+	{0x2101c0, 0x0},
+	{0x0102c0, 0x0},
+	{0x1102c0, 0x0},
+	{0x2102c0, 0x0},
+	{0x0103c0, 0x0},
+	{0x1103c0, 0x0},
+	{0x2103c0, 0x0},
+	{0x0104c0, 0x0},
+	{0x1104c0, 0x0},
+	{0x2104c0, 0x0},
+	{0x0105c0, 0x0},
+	{0x1105c0, 0x0},
+	{0x2105c0, 0x0},
+	{0x0106c0, 0x0},
+	{0x1106c0, 0x0},
+	{0x2106c0, 0x0},
+	{0x0107c0, 0x0},
+	{0x1107c0, 0x0},
+	{0x2107c0, 0x0},
+	{0x0108c0, 0x0},
+	{0x1108c0, 0x0},
+	{0x2108c0, 0x0},
+	{0x0110c0, 0x0},
+	{0x1110c0, 0x0},
+	{0x2110c0, 0x0},
+	{0x0111c0, 0x0},
+	{0x1111c0, 0x0},
+	{0x2111c0, 0x0},
+	{0x0112c0, 0x0},
+	{0x1112c0, 0x0},
+	{0x2112c0, 0x0},
+	{0x0113c0, 0x0},
+	{0x1113c0, 0x0},
+	{0x2113c0, 0x0},
+	{0x0114c0, 0x0},
+	{0x1114c0, 0x0},
+	{0x2114c0, 0x0},
+	{0x0115c0, 0x0},
+	{0x1115c0, 0x0},
+	{0x2115c0, 0x0},
+	{0x0116c0, 0x0},
+	{0x1116c0, 0x0},
+	{0x2116c0, 0x0},
+	{0x0117c0, 0x0},
+	{0x1117c0, 0x0},
+	{0x2117c0, 0x0},
+	{0x0118c0, 0x0},
+	{0x1118c0, 0x0},
+	{0x2118c0, 0x0},
+	{0x0100c1, 0x0},
+	{0x1100c1, 0x0},
+	{0x2100c1, 0x0},
+	{0x0101c1, 0x0},
+	{0x1101c1, 0x0},
+	{0x2101c1, 0x0},
+	{0x0102c1, 0x0},
+	{0x1102c1, 0x0},
+	{0x2102c1, 0x0},
+	{0x0103c1, 0x0},
+	{0x1103c1, 0x0},
+	{0x2103c1, 0x0},
+	{0x0104c1, 0x0},
+	{0x1104c1, 0x0},
+	{0x2104c1, 0x0},
+	{0x0105c1, 0x0},
+	{0x1105c1, 0x0},
+	{0x2105c1, 0x0},
+	{0x0106c1, 0x0},
+	{0x1106c1, 0x0},
+	{0x2106c1, 0x0},
+	{0x0107c1, 0x0},
+	{0x1107c1, 0x0},
+	{0x2107c1, 0x0},
+	{0x0108c1, 0x0},
+	{0x1108c1, 0x0},
+	{0x2108c1, 0x0},
+	{0x0110c1, 0x0},
+	{0x1110c1, 0x0},
+	{0x2110c1, 0x0},
+	{0x0111c1, 0x0},
+	{0x1111c1, 0x0},
+	{0x2111c1, 0x0},
+	{0x0112c1, 0x0},
+	{0x1112c1, 0x0},
+	{0x2112c1, 0x0},
+	{0x0113c1, 0x0},
+	{0x1113c1, 0x0},
+	{0x2113c1, 0x0},
+	{0x0114c1, 0x0},
+	{0x1114c1, 0x0},
+	{0x2114c1, 0x0},
+	{0x0115c1, 0x0},
+	{0x1115c1, 0x0},
+	{0x2115c1, 0x0},
+	{0x0116c1, 0x0},
+	{0x1116c1, 0x0},
+	{0x2116c1, 0x0},
+	{0x0117c1, 0x0},
+	{0x1117c1, 0x0},
+	{0x2117c1, 0x0},
+	{0x0118c1, 0x0},
+	{0x1118c1, 0x0},
+	{0x2118c1, 0x0},
+	{0x010020, 0x0},
+	{0x110020, 0x0},
+	{0x210020, 0x0},
+	{0x011020, 0x0},
+	{0x111020, 0x0},
+	{0x211020, 0x0},
+	{0x020072, 0x0},
+	{0x020073, 0x0},
+	{0x020074, 0x0},
+	{0x0100aa, 0x0},
+	{0x0110aa, 0x0},
+	{0x020010, 0x0},
+	{0x120010, 0x0},
+	{0x220010, 0x0},
+	{0x020011, 0x0},
+	{0x120011, 0x0},
+	{0x220011, 0x0},
+	{0x0100ae, 0x0},
+	{0x1100ae, 0x0},
+	{0x2100ae, 0x0},
+	{0x0100af, 0x0},
+	{0x1100af, 0x0},
+	{0x2100af, 0x0},
+	{0x0110ae, 0x0},
+	{0x1110ae, 0x0},
+	{0x2110ae, 0x0},
+	{0x0110af, 0x0},
+	{0x1110af, 0x0},
+	{0x2110af, 0x0},
+	{0x020020, 0x0},
+	{0x120020, 0x0},
+	{0x220020, 0x0},
+	{0x0100a0, 0x0},
+	{0x0100a1, 0x0},
+	{0x0100a2, 0x0},
+	{0x0100a3, 0x0},
+	{0x0100a4, 0x0},
+	{0x0100a5, 0x0},
+	{0x0100a6, 0x0},
+	{0x0100a7, 0x0},
+	{0x0110a0, 0x0},
+	{0x0110a1, 0x0},
+	{0x0110a2, 0x0},
+	{0x0110a3, 0x0},
+	{0x0110a4, 0x0},
+	{0x0110a5, 0x0},
+	{0x0110a6, 0x0},
+	{0x0110a7, 0x0},
+	{0x02007c, 0x0},
+	{0x12007c, 0x0},
+	{0x22007c, 0x0},
+	{0x02007d, 0x0},
+	{0x12007d, 0x0},
+	{0x22007d, 0x0},
+	{0x0400fd, 0x0},
+	{0x0400c0, 0x0},
+	{0x090201, 0x0},
+	{0x190201, 0x0},
+	{0x290201, 0x0},
+	{0x090202, 0x0},
+	{0x190202, 0x0},
+	{0x290202, 0x0},
+	{0x090203, 0x0},
+	{0x190203, 0x0},
+	{0x290203, 0x0},
+	{0x090204, 0x0},
+	{0x190204, 0x0},
+	{0x290204, 0x0},
+	{0x090205, 0x0},
+	{0x190205, 0x0},
+	{0x290205, 0x0},
+	{0x090206, 0x0},
+	{0x190206, 0x0},
+	{0x290206, 0x0},
+	{0x090207, 0x0},
+	{0x190207, 0x0},
+	{0x290207, 0x0},
+	{0x090208, 0x0},
+	{0x190208, 0x0},
+	{0x290208, 0x0},
+	{0x010062, 0x0},
+	{0x010162, 0x0},
+	{0x010262, 0x0},
+	{0x010362, 0x0},
+	{0x010462, 0x0},
+	{0x010562, 0x0},
+	{0x010662, 0x0},
+	{0x010762, 0x0},
+	{0x010862, 0x0},
+	{0x011062, 0x0},
+	{0x011162, 0x0},
+	{0x011262, 0x0},
+	{0x011362, 0x0},
+	{0x011462, 0x0},
+	{0x011562, 0x0},
+	{0x011662, 0x0},
+	{0x011762, 0x0},
+	{0x011862, 0x0},
+	{0x020077, 0x0},
+	{0x010001, 0x0},
+	{0x011001, 0x0},
+	{0x010040, 0x0},
+	{0x010140, 0x0},
+	{0x010240, 0x0},
+	{0x010340, 0x0},
+	{0x010440, 0x0},
+	{0x010540, 0x0},
+	{0x010640, 0x0},
+	{0x010740, 0x0},
+	{0x010840, 0x0},
+	{0x010030, 0x0},
+	{0x010130, 0x0},
+	{0x010230, 0x0},
+	{0x010330, 0x0},
+	{0x010430, 0x0},
+	{0x010530, 0x0},
+	{0x010630, 0x0},
+	{0x010730, 0x0},
+	{0x010830, 0x0},
+	{0x011040, 0x0},
+	{0x011140, 0x0},
+	{0x011240, 0x0},
+	{0x011340, 0x0},
+	{0x011440, 0x0},
+	{0x011540, 0x0},
+	{0x011640, 0x0},
+	{0x011740, 0x0},
+	{0x011840, 0x0},
+	{0x011030, 0x0},
+	{0x011130, 0x0},
+	{0x011230, 0x0},
+	{0x011330, 0x0},
+	{0x011430, 0x0},
+	{0x011530, 0x0},
+	{0x011630, 0x0},
+	{0x011730, 0x0},
+	{0x011830, 0x0},
+};
+
+/* P0 message block paremeter for training firmware */
+struct dram_cfg_param ddr_fsp0_cfg[] = {
+	{0x000d0000, 0x00000000},
+	{0x00054000, 0x00000000},
+	{0x00054001, 0x00000000},
+	{0x00054002, 0x00000000},
+	{0x00054003, 0x00000c80},
+	{0x00054004, 0x00000002},
+	{0x00054005, 0x00000000},
+	{0x00054006, 0x00000011},
+	{0x00054007, 0x00000000},
+	{0x00054008, 0x0000131f},
+	{0x00054009, 0x000000c8},
+	{0x0005400a, 0x00000000},
+	{0x0005400b, 0x00000002},
+	{0x0005400c, 0x00000000},
+	{0x0005400d, 0x00000000},
+	{0x0005400e, 0x00000000},
+	{0x0005400f, 0x00000100},
+	{0x00054010, 0x00000000},
+	{0x00054011, 0x00000000},
+	{0x00054012, 0x00000310},
+	{0x00054013, 0x00000000},
+	{0x00054014, 0x00000000},
+	{0x00054015, 0x00000000},
+	{0x00054016, 0x00000000},
+	{0x00054017, 0x00000000},
+	{0x00054018, 0x00000000},
+	{0x00054019, 0x00002dd4},
+	{0x0005401a, 0x00000031},
+	{0x0005401b, 0x00004d66},
+	{0x0005401c, 0x00004a00},
+	{0x0005401d, 0x00000000},
+	{0x0005401e, 0x00000016},
+	{0x0005401f, 0x00002dd4},
+	{0x00054020, 0x00000031},
+	{0x00054021, 0x00004d66},
+	{0x00054022, 0x00004a00},
+	{0x00054023, 0x00000000},
+	{0x00054024, 0x0000002e},
+	{0x00054025, 0x00000000},
+	{0x00054026, 0x00000000},
+	{0x00054027, 0x00000000},
+	{0x00054028, 0x00000000},
+	{0x00054029, 0x00000000},
+	{0x0005402a, 0x00000000},
+	{0x0005402b, 0x00000000},
+	{0x0005402c, 0x00000000},
+	{0x0005402d, 0x00000000},
+	{0x0005402e, 0x00000000},
+	{0x0005402f, 0x00000000},
+	{0x00054030, 0x00000000},
+	{0x00054031, 0x00000000},
+	{0x00054032, 0x0000d400},
+	{0x00054033, 0x0000312d},
+	{0x00054034, 0x00006600},
+	{0x00054035, 0x0000004d},
+	{0x00054036, 0x0000004a},
+	{0x00054037, 0x00001600},
+	{0x00054038, 0x0000d400},
+	{0x00054039, 0x0000312d},
+	{0x0005403a, 0x00006600},
+	{0x0005403b, 0x0000004d},
+	{0x0005403c, 0x0000004a},
+	{0x0005403d, 0x00002e00},
+	{0x0005403e, 0x00000000},
+	{0x0005403f, 0x00000000},
+	{0x00054040, 0x00000000},
+	{0x00054041, 0x00000000},
+	{0x00054042, 0x00000000},
+	{0x00054043, 0x00000000},
+	{0x00054044, 0x00000000},
+	{0x000d0000, 0x00000001},
+};
+
+/* P1 message block paremeter for training firmware */
+struct dram_cfg_param ddr_fsp1_cfg[] = {
+	{0x000d0000, 0x00000000},
+	{0x00054000, 0x00000000},
+	{0x00054001, 0x00000000},
+	{0x00054002, 0x00000101},
+	{0x00054003, 0x00000190},
+	{0x00054004, 0x00000002},
+	{0x00054005, 0x00000000},
+	{0x00054006, 0x00000011},
+	{0x00054007, 0x00000000},
+	{0x00054008, 0x0000121f},
+	{0x00054009, 0x000000c8},
+	{0x0005400a, 0x00000000},
+	{0x0005400b, 0x00000002},
+	{0x0005400c, 0x00000000},
+	{0x0005400d, 0x00000000},
+	{0x0005400e, 0x00000000},
+	{0x0005400f, 0x00000100},
+	{0x00054010, 0x00000000},
+	{0x00054011, 0x00000000},
+	{0x00054012, 0x00000310},
+	{0x00054013, 0x00000000},
+	{0x00054014, 0x00000000},
+	{0x00054015, 0x00000000},
+	{0x00054016, 0x00000000},
+	{0x00054017, 0x00000000},
+	{0x00054018, 0x00000000},
+	{0x00054019, 0x00000084},
+	{0x0005401a, 0x00000031},
+	{0x0005401b, 0x00004d66},
+	{0x0005401c, 0x00004a00},
+	{0x0005401d, 0x00000000},
+	{0x0005401e, 0x00000016},
+	{0x0005401f, 0x00000084},
+	{0x00054020, 0x00000031},
+	{0x00054021, 0x00004d66},
+	{0x00054022, 0x00004a00},
+	{0x00054023, 0x00000000},
+	{0x00054024, 0x0000002e},
+	{0x00054025, 0x00000000},
+	{0x00054026, 0x00000000},
+	{0x00054027, 0x00000000},
+	{0x00054028, 0x00000000},
+	{0x00054029, 0x00000000},
+	{0x0005402a, 0x00000000},
+	{0x0005402b, 0x00000000},
+	{0x0005402c, 0x00000000},
+	{0x0005402d, 0x00000000},
+	{0x0005402e, 0x00000000},
+	{0x0005402f, 0x00000000},
+	{0x00054030, 0x00000000},
+	{0x00054031, 0x00000000},
+	{0x00054032, 0x00008400},
+	{0x00054033, 0x00003100},
+	{0x00054034, 0x00006600},
+	{0x00054035, 0x0000004d},
+	{0x00054036, 0x0000004a},
+	{0x00054037, 0x00001600},
+	{0x00054038, 0x00008400},
+	{0x00054039, 0x00003100},
+	{0x0005403a, 0x00006600},
+	{0x0005403b, 0x0000004d},
+	{0x0005403c, 0x0000004a},
+	{0x0005403d, 0x00002e00},
+	{0x0005403e, 0x00000000},
+	{0x0005403f, 0x00000000},
+	{0x00054040, 0x00000000},
+	{0x00054041, 0x00000000},
+	{0x00054042, 0x00000000},
+	{0x00054043, 0x00000000},
+	{0x00054044, 0x00000000},
+	{0x000d0000, 0x00000001},
+};
+
+/* P2 message block paremeter for training firmware */
+struct dram_cfg_param ddr_fsp2_cfg[] = {
+	{0x000d0000, 0x00000000},
+	{0x00054000, 0x00000000},
+	{0x00054001, 0x00000000},
+	{0x00054002, 0x00000102},
+	{0x00054003, 0x00000064},
+	{0x00054004, 0x00000002},
+	{0x00054005, 0x00000000},
+	{0x00054006, 0x00000011},
+	{0x00054007, 0x00000000},
+	{0x00054008, 0x0000121f},
+	{0x00054009, 0x000000c8},
+	{0x0005400a, 0x00000000},
+	{0x0005400b, 0x00000002},
+	{0x0005400c, 0x00000000},
+	{0x0005400d, 0x00000000},
+	{0x0005400e, 0x00000000},
+	{0x0005400f, 0x00000100},
+	{0x00054010, 0x00000000},
+	{0x00054011, 0x00000000},
+	{0x00054012, 0x00000310},
+	{0x00054013, 0x00000000},
+	{0x00054014, 0x00000000},
+	{0x00054015, 0x00000000},
+	{0x00054016, 0x00000000},
+	{0x00054017, 0x00000000},
+	{0x00054018, 0x00000000},
+	{0x00054019, 0x00000084},
+	{0x0005401a, 0x00000031},
+	{0x0005401b, 0x00004d66},
+	{0x0005401c, 0x00004a00},
+	{0x0005401d, 0x00000000},
+	{0x0005401e, 0x00000016},
+	{0x0005401f, 0x00000084},
+	{0x00054020, 0x00000031},
+	{0x00054021, 0x00004d66},
+	{0x00054022, 0x00004a00},
+	{0x00054023, 0x00000000},
+	{0x00054024, 0x0000002e},
+	{0x00054025, 0x00000000},
+	{0x00054026, 0x00000000},
+	{0x00054027, 0x00000000},
+	{0x00054028, 0x00000000},
+	{0x00054029, 0x00000000},
+	{0x0005402a, 0x00000000},
+	{0x0005402b, 0x00000000},
+	{0x0005402c, 0x00000000},
+	{0x0005402d, 0x00000000},
+	{0x0005402e, 0x00000000},
+	{0x0005402f, 0x00000000},
+	{0x00054030, 0x00000000},
+	{0x00054031, 0x00000000},
+	{0x00054032, 0x00008400},
+	{0x00054033, 0x00003100},
+	{0x00054034, 0x00006600},
+	{0x00054035, 0x0000004d},
+	{0x00054036, 0x0000004a},
+	{0x00054037, 0x00001600},
+	{0x00054038, 0x00008400},
+	{0x00054039, 0x00003100},
+	{0x0005403a, 0x00006600},
+	{0x0005403b, 0x0000004d},
+	{0x0005403c, 0x0000004a},
+	{0x0005403d, 0x00002e00},
+	{0x0005403e, 0x00000000},
+	{0x0005403f, 0x00000000},
+	{0x00054040, 0x00000000},
+	{0x00054041, 0x00000000},
+	{0x00054042, 0x00000000},
+	{0x00054043, 0x00000000},
+	{0x00054044, 0x00000000},
+	{0x000d0000, 0x00000001},
+};
+
+/* P0 2D message block paremeter for training firmware */
+struct dram_cfg_param ddr_fsp0_2d_cfg[] = {
+	{0x000d0000, 0x00000000},
+	{0x00054000, 0x00000000},
+	{0x00054001, 0x00000000},
+	{0x00054002, 0x00000000},
+	{0x00054003, 0x00000c80},
+	{0x00054004, 0x00000002},
+	{0x00054005, 0x00000000},
+	{0x00054006, 0x00000011},
+	{0x00054007, 0x00000000},
+	{0x00054008, 0x00000061},
+	{0x00054009, 0x000000c8},
+	{0x0005400a, 0x00000000},
+	{0x0005400b, 0x00000002},
+	{0x0005400c, 0x00000000},
+	{0x0005400d, 0x00000000},
+	{0x0005400e, 0x00000000},
+	{0x0005400f, 0x00000100},
+	{0x00054010, 0x00001f7f},
+	{0x00054011, 0x00000000},
+	{0x00054012, 0x00000310},
+	{0x00054013, 0x00000000},
+	{0x00054014, 0x00000000},
+	{0x00054015, 0x00000000},
+	{0x00054016, 0x00000000},
+	{0x00054017, 0x00000000},
+	{0x00054018, 0x00000000},
+	{0x00054019, 0x00002dd4},
+	{0x0005401a, 0x00000031},
+	{0x0005401b, 0x00004d66},
+	{0x0005401c, 0x00004a00},
+	{0x0005401d, 0x00000000},
+	{0x0005401e, 0x00000016},
+	{0x0005401f, 0x00002dd4},
+	{0x00054020, 0x00000031},
+	{0x00054021, 0x00004d66},
+	{0x00054022, 0x00004a00},
+	{0x00054023, 0x00000000},
+	{0x00054024, 0x0000002e},
+	{0x00054025, 0x00000000},
+	{0x00054026, 0x00000000},
+	{0x00054027, 0x00000000},
+	{0x00054028, 0x00000000},
+	{0x00054029, 0x00000000},
+	{0x0005402a, 0x00000000},
+	{0x0005402b, 0x00000000},
+	{0x0005402c, 0x00000000},
+	{0x0005402d, 0x00000000},
+	{0x0005402e, 0x00000000},
+	{0x0005402f, 0x00000000},
+	{0x00054030, 0x00000000},
+	{0x00054031, 0x00000000},
+	{0x00054032, 0x0000d400},
+	{0x00054033, 0x0000312d},
+	{0x00054034, 0x00006600},
+	{0x00054035, 0x0000004d},
+	{0x00054036, 0x0000004a},
+	{0x00054037, 0x00001600},
+	{0x00054038, 0x0000d400},
+	{0x00054039, 0x0000312d},
+	{0x0005403a, 0x00006600},
+	{0x0005403b, 0x0000004d},
+	{0x0005403c, 0x0000004a},
+	{0x0005403d, 0x00002e00},
+	{0x0005403e, 0x00000000},
+	{0x0005403f, 0x00000000},
+	{0x00054040, 0x00000000},
+	{0x00054041, 0x00000000},
+	{0x00054042, 0x00000000},
+	{0x00054043, 0x00000000},
+	{0x00054044, 0x00000000},
+	{0x000d0000, 0x00000001},
+};
+
+/* DRAM PHY init engine image */
+struct dram_cfg_param ddr_phy_pie[] = {
+	{0xd0000, 0x0},
+	{0x90000, 0x10},
+	{0x90001, 0x400},
+	{0x90002, 0x10e},
+	{0x90003, 0x0},
+	{0x90004, 0x0},
+	{0x90005, 0x8},
+	{0x90029, 0xb},
+	{0x9002a, 0x480},
+	{0x9002b, 0x109},
+	{0x9002c, 0x8},
+	{0x9002d, 0x448},
+	{0x9002e, 0x139},
+	{0x9002f, 0x8},
+	{0x90030, 0x478},
+	{0x90031, 0x109},
+	{0x90032, 0x0},
+	{0x90033, 0xe8},
+	{0x90034, 0x109},
+	{0x90035, 0x2},
+	{0x90036, 0x10},
+	{0x90037, 0x139},
+	{0x90038, 0xb},
+	{0x90039, 0x7c0},
+	{0x9003a, 0x139},
+	{0x9003b, 0x44},
+	{0x9003c, 0x633},
+	{0x9003d, 0x159},
+	{0x9003e, 0x14f},
+	{0x9003f, 0x630},
+	{0x90040, 0x159},
+	{0x90041, 0x47},
+	{0x90042, 0x633},
+	{0x90043, 0x149},
+	{0x90044, 0x4f},
+	{0x90045, 0x633},
+	{0x90046, 0x179},
+	{0x90047, 0x8},
+	{0x90048, 0xe0},
+	{0x90049, 0x109},
+	{0x9004a, 0x0},
+	{0x9004b, 0x7c8},
+	{0x9004c, 0x109},
+	{0x9004d, 0x0},
+	{0x9004e, 0x1},
+	{0x9004f, 0x8},
+	{0x90050, 0x0},
+	{0x90051, 0x45a},
+	{0x90052, 0x9},
+	{0x90053, 0x0},
+	{0x90054, 0x448},
+	{0x90055, 0x109},
+	{0x90056, 0x40},
+	{0x90057, 0x633},
+	{0x90058, 0x179},
+	{0x90059, 0x1},
+	{0x9005a, 0x618},
+	{0x9005b, 0x109},
+	{0x9005c, 0x40c0},
+	{0x9005d, 0x633},
+	{0x9005e, 0x149},
+	{0x9005f, 0x8},
+	{0x90060, 0x4},
+	{0x90061, 0x48},
+	{0x90062, 0x4040},
+	{0x90063, 0x633},
+	{0x90064, 0x149},
+	{0x90065, 0x0},
+	{0x90066, 0x4},
+	{0x90067, 0x48},
+	{0x90068, 0x40},
+	{0x90069, 0x633},
+	{0x9006a, 0x149},
+	{0x9006b, 0x10},
+	{0x9006c, 0x4},
+	{0x9006d, 0x18},
+	{0x9006e, 0x0},
+	{0x9006f, 0x4},
+	{0x90070, 0x78},
+	{0x90071, 0x549},
+	{0x90072, 0x633},
+	{0x90073, 0x159},
+	{0x90074, 0xd49},
+	{0x90075, 0x633},
+	{0x90076, 0x159},
+	{0x90077, 0x94a},
+	{0x90078, 0x633},
+	{0x90079, 0x159},
+	{0x9007a, 0x441},
+	{0x9007b, 0x633},
+	{0x9007c, 0x149},
+	{0x9007d, 0x42},
+	{0x9007e, 0x633},
+	{0x9007f, 0x149},
+	{0x90080, 0x1},
+	{0x90081, 0x633},
+	{0x90082, 0x149},
+	{0x90083, 0x0},
+	{0x90084, 0xe0},
+	{0x90085, 0x109},
+	{0x90086, 0xa},
+	{0x90087, 0x10},
+	{0x90088, 0x109},
+	{0x90089, 0x9},
+	{0x9008a, 0x3c0},
+	{0x9008b, 0x149},
+	{0x9008c, 0x9},
+	{0x9008d, 0x3c0},
+	{0x9008e, 0x159},
+	{0x9008f, 0x18},
+	{0x90090, 0x10},
+	{0x90091, 0x109},
+	{0x90092, 0x0},
+	{0x90093, 0x3c0},
+	{0x90094, 0x109},
+	{0x90095, 0x18},
+	{0x90096, 0x4},
+	{0x90097, 0x48},
+	{0x90098, 0x18},
+	{0x90099, 0x4},
+	{0x9009a, 0x58},
+	{0x9009b, 0xb},
+	{0x9009c, 0x10},
+	{0x9009d, 0x109},
+	{0x9009e, 0x1},
+	{0x9009f, 0x10},
+	{0x900a0, 0x109},
+	{0x900a1, 0x5},
+	{0x900a2, 0x7c0},
+	{0x900a3, 0x109},
+	{0x40000, 0x811},
+	{0x40020, 0x880},
+	{0x40040, 0x0},
+	{0x40060, 0x0},
+	{0x40001, 0x4008},
+	{0x40021, 0x83},
+	{0x40041, 0x4f},
+	{0x40061, 0x0},
+	{0x40002, 0x4040},
+	{0x40022, 0x83},
+	{0x40042, 0x51},
+	{0x40062, 0x0},
+	{0x40003, 0x811},
+	{0x40023, 0x880},
+	{0x40043, 0x0},
+	{0x40063, 0x0},
+	{0x40004, 0x720},
+	{0x40024, 0xf},
+	{0x40044, 0x1740},
+	{0x40064, 0x0},
+	{0x40005, 0x16},
+	{0x40025, 0x83},
+	{0x40045, 0x4b},
+	{0x40065, 0x0},
+	{0x40006, 0x716},
+	{0x40026, 0xf},
+	{0x40046, 0x2001},
+	{0x40066, 0x0},
+	{0x40007, 0x716},
+	{0x40027, 0xf},
+	{0x40047, 0x2800},
+	{0x40067, 0x0},
+	{0x40008, 0x716},
+	{0x40028, 0xf},
+	{0x40048, 0xf00},
+	{0x40068, 0x0},
+	{0x40009, 0x720},
+	{0x40029, 0xf},
+	{0x40049, 0x1400},
+	{0x40069, 0x0},
+	{0x4000a, 0xe08},
+	{0x4002a, 0xc15},
+	{0x4004a, 0x0},
+	{0x4006a, 0x0},
+	{0x4000b, 0x625},
+	{0x4002b, 0x15},
+	{0x4004b, 0x0},
+	{0x4006b, 0x0},
+	{0x4000c, 0x4028},
+	{0x4002c, 0x80},
+	{0x4004c, 0x0},
+	{0x4006c, 0x0},
+	{0x4000d, 0xe08},
+	{0x4002d, 0xc1a},
+	{0x4004d, 0x0},
+	{0x4006d, 0x0},
+	{0x4000e, 0x625},
+	{0x4002e, 0x1a},
+	{0x4004e, 0x0},
+	{0x4006e, 0x0},
+	{0x4000f, 0x4040},
+	{0x4002f, 0x80},
+	{0x4004f, 0x0},
+	{0x4006f, 0x0},
+	{0x40010, 0x2604},
+	{0x40030, 0x15},
+	{0x40050, 0x0},
+	{0x40070, 0x0},
+	{0x40011, 0x708},
+	{0x40031, 0x5},
+	{0x40051, 0x0},
+	{0x40071, 0x2002},
+	{0x40012, 0x8},
+	{0x40032, 0x80},
+	{0x40052, 0x0},
+	{0x40072, 0x0},
+	{0x40013, 0x2604},
+	{0x40033, 0x1a},
+	{0x40053, 0x0},
+	{0x40073, 0x0},
+	{0x40014, 0x708},
+	{0x40034, 0xa},
+	{0x40054, 0x0},
+	{0x40074, 0x2002},
+	{0x40015, 0x4040},
+	{0x40035, 0x80},
+	{0x40055, 0x0},
+	{0x40075, 0x0},
+	{0x40016, 0x60a},
+	{0x40036, 0x15},
+	{0x40056, 0x1200},
+	{0x40076, 0x0},
+	{0x40017, 0x61a},
+	{0x40037, 0x15},
+	{0x40057, 0x1300},
+	{0x40077, 0x0},
+	{0x40018, 0x60a},
+	{0x40038, 0x1a},
+	{0x40058, 0x1200},
+	{0x40078, 0x0},
+	{0x40019, 0x642},
+	{0x40039, 0x1a},
+	{0x40059, 0x1300},
+	{0x40079, 0x0},
+	{0x4001a, 0x4808},
+	{0x4003a, 0x880},
+	{0x4005a, 0x0},
+	{0x4007a, 0x0},
+	{0x900a4, 0x0},
+	{0x900a5, 0x790},
+	{0x900a6, 0x11a},
+	{0x900a7, 0x8},
+	{0x900a8, 0x7aa},
+	{0x900a9, 0x2a},
+	{0x900aa, 0x10},
+	{0x900ab, 0x7b2},
+	{0x900ac, 0x2a},
+	{0x900ad, 0x0},
+	{0x900ae, 0x7c8},
+	{0x900af, 0x109},
+	{0x900b0, 0x10},
+	{0x900b1, 0x10},
+	{0x900b2, 0x109},
+	{0x900b3, 0x10},
+	{0x900b4, 0x2a8},
+	{0x900b5, 0x129},
+	{0x900b6, 0x8},
+	{0x900b7, 0x370},
+	{0x900b8, 0x129},
+	{0x900b9, 0xa},
+	{0x900ba, 0x3c8},
+	{0x900bb, 0x1a9},
+	{0x900bc, 0xc},
+	{0x900bd, 0x408},
+	{0x900be, 0x199},
+	{0x900bf, 0x14},
+	{0x900c0, 0x790},
+	{0x900c1, 0x11a},
+	{0x900c2, 0x8},
+	{0x900c3, 0x4},
+	{0x900c4, 0x18},
+	{0x900c5, 0xe},
+	{0x900c6, 0x408},
+	{0x900c7, 0x199},
+	{0x900c8, 0x8},
+	{0x900c9, 0x8568},
+	{0x900ca, 0x108},
+	{0x900cb, 0x18},
+	{0x900cc, 0x790},
+	{0x900cd, 0x16a},
+	{0x900ce, 0x8},
+	{0x900cf, 0x1d8},
+	{0x900d0, 0x169},
+	{0x900d1, 0x10},
+	{0x900d2, 0x8558},
+	{0x900d3, 0x168},
+	{0x900d4, 0x70},
+	{0x900d5, 0x788},
+	{0x900d6, 0x16a},
+	{0x900d7, 0x1ff8},
+	{0x900d8, 0x85a8},
+	{0x900d9, 0x1e8},
+	{0x900da, 0x50},
+	{0x900db, 0x798},
+	{0x900dc, 0x16a},
+	{0x900dd, 0x60},
+	{0x900de, 0x7a0},
+	{0x900df, 0x16a},
+	{0x900e0, 0x8},
+	{0x900e1, 0x8310},
+	{0x900e2, 0x168},
+	{0x900e3, 0x8},
+	{0x900e4, 0xa310},
+	{0x900e5, 0x168},
+	{0x900e6, 0xa},
+	{0x900e7, 0x408},
+	{0x900e8, 0x169},
+	{0x900e9, 0x6e},
+	{0x900ea, 0x0},
+	{0x900eb, 0x68},
+	{0x900ec, 0x0},
+	{0x900ed, 0x408},
+	{0x900ee, 0x169},
+	{0x900ef, 0x0},
+	{0x900f0, 0x8310},
+	{0x900f1, 0x168},
+	{0x900f2, 0x0},
+	{0x900f3, 0xa310},
+	{0x900f4, 0x168},
+	{0x900f5, 0x1ff8},
+	{0x900f6, 0x85a8},
+	{0x900f7, 0x1e8},
+	{0x900f8, 0x68},
+	{0x900f9, 0x798},
+	{0x900fa, 0x16a},
+	{0x900fb, 0x78},
+	{0x900fc, 0x7a0},
+	{0x900fd, 0x16a},
+	{0x900fe, 0x68},
+	{0x900ff, 0x790},
+	{0x90100, 0x16a},
+	{0x90101, 0x8},
+	{0x90102, 0x8b10},
+	{0x90103, 0x168},
+	{0x90104, 0x8},
+	{0x90105, 0xab10},
+	{0x90106, 0x168},
+	{0x90107, 0xa},
+	{0x90108, 0x408},
+	{0x90109, 0x169},
+	{0x9010a, 0x58},
+	{0x9010b, 0x0},
+	{0x9010c, 0x68},
+	{0x9010d, 0x0},
+	{0x9010e, 0x408},
+	{0x9010f, 0x169},
+	{0x90110, 0x0},
+	{0x90111, 0x8b10},
+	{0x90112, 0x168},
+	{0x90113, 0x1},
+	{0x90114, 0xab10},
+	{0x90115, 0x168},
+	{0x90116, 0x0},
+	{0x90117, 0x1d8},
+	{0x90118, 0x169},
+	{0x90119, 0x80},
+	{0x9011a, 0x790},
+	{0x9011b, 0x16a},
+	{0x9011c, 0x18},
+	{0x9011d, 0x7aa},
+	{0x9011e, 0x6a},
+	{0x9011f, 0xa},
+	{0x90120, 0x0},
+	{0x90121, 0x1e9},
+	{0x90122, 0x8},
+	{0x90123, 0x8080},
+	{0x90124, 0x108},
+	{0x90125, 0xf},
+	{0x90126, 0x408},
+	{0x90127, 0x169},
+	{0x90128, 0xc},
+	{0x90129, 0x0},
+	{0x9012a, 0x68},
+	{0x9012b, 0x9},
+	{0x9012c, 0x0},
+	{0x9012d, 0x1a9},
+	{0x9012e, 0x0},
+	{0x9012f, 0x408},
+	{0x90130, 0x169},
+	{0x90131, 0x0},
+	{0x90132, 0x8080},
+	{0x90133, 0x108},
+	{0x90134, 0x8},
+	{0x90135, 0x7aa},
+	{0x90136, 0x6a},
+	{0x90137, 0x0},
+	{0x90138, 0x8568},
+	{0x90139, 0x108},
+	{0x9013a, 0xb7},
+	{0x9013b, 0x790},
+	{0x9013c, 0x16a},
+	{0x9013d, 0x1f},
+	{0x9013e, 0x0},
+	{0x9013f, 0x68},
+	{0x90140, 0x8},
+	{0x90141, 0x8558},
+	{0x90142, 0x168},
+	{0x90143, 0xf},
+	{0x90144, 0x408},
+	{0x90145, 0x169},
+	{0x90146, 0xd},
+	{0x90147, 0x0},
+	{0x90148, 0x68},
+	{0x90149, 0x0},
+	{0x9014a, 0x408},
+	{0x9014b, 0x169},
+	{0x9014c, 0x0},
+	{0x9014d, 0x8558},
+	{0x9014e, 0x168},
+	{0x9014f, 0x8},
+	{0x90150, 0x3c8},
+	{0x90151, 0x1a9},
+	{0x90152, 0x3},
+	{0x90153, 0x370},
+	{0x90154, 0x129},
+	{0x90155, 0x20},
+	{0x90156, 0x2aa},
+	{0x90157, 0x9},
+	{0x90158, 0x0},
+	{0x90159, 0x400},
+	{0x9015a, 0x10e},
+	{0x9015b, 0x8},
+	{0x9015c, 0xe8},
+	{0x9015d, 0x109},
+	{0x9015e, 0x0},
+	{0x9015f, 0x8140},
+	{0x90160, 0x10c},
+	{0x90161, 0x10},
+	{0x90162, 0x8138},
+	{0x90163, 0x10c},
+	{0x90164, 0x8},
+	{0x90165, 0x7c8},
+	{0x90166, 0x101},
+	{0x90167, 0x8},
+	{0x90168, 0x448},
+	{0x90169, 0x109},
+	{0x9016a, 0xf},
+	{0x9016b, 0x7c0},
+	{0x9016c, 0x109},
+	{0x9016d, 0x0},
+	{0x9016e, 0xe8},
+	{0x9016f, 0x109},
+	{0x90170, 0x47},
+	{0x90171, 0x630},
+	{0x90172, 0x109},
+	{0x90173, 0x8},
+	{0x90174, 0x618},
+	{0x90175, 0x109},
+	{0x90176, 0x8},
+	{0x90177, 0xe0},
+	{0x90178, 0x109},
+	{0x90179, 0x0},
+	{0x9017a, 0x7c8},
+	{0x9017b, 0x109},
+	{0x9017c, 0x8},
+	{0x9017d, 0x8140},
+	{0x9017e, 0x10c},
+	{0x9017f, 0x0},
+	{0x90180, 0x1},
+	{0x90181, 0x8},
+	{0x90182, 0x8},
+	{0x90183, 0x4},
+	{0x90184, 0x8},
+	{0x90185, 0x8},
+	{0x90186, 0x7c8},
+	{0x90187, 0x101},
+	{0x90006, 0x0},
+	{0x90007, 0x0},
+	{0x90008, 0x8},
+	{0x90009, 0x0},
+	{0x9000a, 0x0},
+	{0x9000b, 0x0},
+	{0xd00e7, 0x400},
+	{0x90017, 0x0},
+	{0x9001f, 0x29},
+	{0x90026, 0x6a},
+	{0x400d0, 0x0},
+	{0x400d1, 0x101},
+	{0x400d2, 0x105},
+	{0x400d3, 0x107},
+	{0x400d4, 0x10f},
+	{0x400d5, 0x202},
+	{0x400d6, 0x20a},
+	{0x400d7, 0x20b},
+	{0x2003a, 0x2},
+	{0x2000b, 0x64},
+	{0x2000c, 0xc8},
+	{0x2000d, 0x7d0},
+	{0x2000e, 0x2c},
+	{0x12000b, 0xc},
+	{0x12000c, 0x19},
+	{0x12000d, 0xfa},
+	{0x12000e, 0x10},
+	{0x22000b, 0x3},
+	{0x22000c, 0x6},
+	{0x22000d, 0x3e},
+	{0x22000e, 0x10},
+	{0x9000c, 0x0},
+	{0x9000d, 0x173},
+	{0x9000e, 0x60},
+	{0x9000f, 0x6110},
+	{0x90010, 0x2152},
+	{0x90011, 0xdfbd},
+	{0x90012, 0x2060},
+	{0x90013, 0x6152},
+	{0x20010, 0x5a},
+	{0x20011, 0x3},
+	{0x40080, 0xe0},
+	{0x40081, 0x12},
+	{0x40082, 0xe0},
+	{0x40083, 0x12},
+	{0x40084, 0xe0},
+	{0x40085, 0x12},
+	{0x140080, 0xe0},
+	{0x140081, 0x12},
+	{0x140082, 0xe0},
+	{0x140083, 0x12},
+	{0x140084, 0xe0},
+	{0x140085, 0x12},
+	{0x240080, 0xe0},
+	{0x240081, 0x12},
+	{0x240082, 0xe0},
+	{0x240083, 0x12},
+	{0x240084, 0xe0},
+	{0x240085, 0x12},
+	{0x400fd, 0xf},
+	{0x10011, 0x1},
+	{0x10012, 0x1},
+	{0x10013, 0x180},
+	{0x10018, 0x1},
+	{0x10002, 0x6209},
+	{0x100b2, 0x1},
+	{0x101b4, 0x1},
+	{0x102b4, 0x1},
+	{0x103b4, 0x1},
+	{0x104b4, 0x1},
+	{0x105b4, 0x1},
+	{0x106b4, 0x1},
+	{0x107b4, 0x1},
+	{0x108b4, 0x1},
+	{0x11011, 0x1},
+	{0x11012, 0x1},
+	{0x11013, 0x180},
+	{0x11018, 0x1},
+	{0x11002, 0x6209},
+	{0x110b2, 0x1},
+	{0x111b4, 0x1},
+	{0x112b4, 0x1},
+	{0x113b4, 0x1},
+	{0x114b4, 0x1},
+	{0x115b4, 0x1},
+	{0x116b4, 0x1},
+	{0x117b4, 0x1},
+	{0x118b4, 0x1},
+	{0x20089, 0x1},
+	{0x20088, 0x19},
+	{0xc0080, 0x2},
+	{0xd0000, 0x1},
+};
+
+struct dram_fsp_msg ddr_dram_fsp_msg[] = {
+	{
+		/* P0 3200mts 1D */
+		.drate = 3200,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = ddr_fsp0_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_cfg),
+	},
+	{
+		/* P1 400mts 1D */
+		.drate = 400,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = ddr_fsp1_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp1_cfg),
+	},
+	{
+		/* P2 100mts 1D */
+		.drate = 100,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = ddr_fsp2_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp2_cfg),
+	},
+	{
+		/* P0 3200mts 2D */
+		.drate = 3200,
+		.fw_type = FW_2D_IMAGE,
+		.fsp_cfg = ddr_fsp0_2d_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_2d_cfg),
+	},
+};
+
+/* ddr timing config params */
+struct dram_timing_info dram_timing = {
+	.ddrc_cfg = ddr_ddrc_cfg,
+	.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg),
+	.ddrphy_cfg = ddr_ddrphy_cfg,
+	.ddrphy_cfg_num = ARRAY_SIZE(ddr_ddrphy_cfg),
+	.fsp_msg = ddr_dram_fsp_msg,
+	.fsp_msg_num = ARRAY_SIZE(ddr_dram_fsp_msg),
+	.ddrphy_trained_csr = ddr_ddrphy_trained_csr,
+	.ddrphy_trained_csr_num = ARRAY_SIZE(ddr_ddrphy_trained_csr),
+	.ddrphy_pie = ddr_phy_pie,
+	.ddrphy_pie_num = ARRAY_SIZE(ddr_phy_pie),
+	.fsp_table = { 3200, 400, 100, },
+};
diff --git a/board/freescale/imx8mn_evk/lpddr4_timing_ld.c b/board/freescale/imx8mn_evk/lpddr4_timing_ld.c
new file mode 100644
index 0000000..aa23c35
--- /dev/null
+++ b/board/freescale/imx8mn_evk/lpddr4_timing_ld.c
@@ -0,0 +1,1440 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ *
+ * Generated code from MX8M_DDR_tool
+ * Align with uboot version:
+ * imx_v2018.03_4.14.78_1.0.0_ga ~ imx_v2018.04_4.19.35_1.1.0_ga
+ */
+
+#include <linux/kernel.h>
+#include <asm/arch/ddr.h>
+
+struct dram_cfg_param ddr_ddrc_cfg[] = {
+	/** Initialize DDRC registers **/
+	{ 0x3d400304, 0x1 },
+	{ 0x3d400030, 0x1 },
+	{ 0x3d400000, 0xa3080020 },
+	{ 0x3d400020, 0x111 },
+	{ 0x3d400024, 0x1f400 },
+	{ 0x3d400064, 0x300070 },
+	{ 0x3d4000d0, 0xc002030f },
+	{ 0x3d4000d4, 0x500000 },
+	{ 0x3d4000dc, 0xa40012 },
+	{ 0x3d4000e0, 0x310000 },
+	{ 0x3d4000e8, 0x66004d },
+	{ 0x3d4000ec, 0x16004d },
+	{ 0x3d400100, 0x10100d11 },
+	{ 0x3d400104, 0x3041a },
+	{ 0x3d40010c, 0x606000 },
+	{ 0x3d400110, 0x8040408 },
+	{ 0x3d400114, 0x2030606 },
+	{ 0x3d400118, 0x1010004 },
+	{ 0x3d40011c, 0x301 },
+	{ 0x3d400130, 0x20300 },
+	{ 0x3d400134, 0xa100002 },
+	{ 0x3d400138, 0x73 },
+	{ 0x3d400144, 0x500028 },
+	{ 0x3d400180, 0x190000c },
+	{ 0x3d400184, 0x14030d4 },
+	{ 0x3d400188, 0x0 },
+	{ 0x3d400190, 0x4898204 },
+	{ 0x3d400194, 0x80303 },
+	{ 0x3d4001b4, 0x904 },
+	{ 0x3d4001a0, 0xe0400018 },
+	{ 0x3d4001a4, 0xdf00e4 },
+	{ 0x3d4001a8, 0x80000000 },
+	{ 0x3d4001b0, 0x11 },
+	{ 0x3d4001c0, 0x1 },
+	{ 0x3d4001c4, 0x1 },
+	{ 0x3d4000f4, 0xc99 },
+	{ 0x3d400108, 0x4070f0f },
+	{ 0x3d400200, 0x17 },
+	{ 0x3d40020c, 0x0 },
+	{ 0x3d400210, 0x1f1f },
+	{ 0x3d400204, 0x80808 },
+	{ 0x3d400214, 0x7070707 },
+	{ 0x3d400218, 0x7070707 },
+	{ 0x3d400250, 0x29001701 },
+	{ 0x3d400254, 0x2c },
+	{ 0x3d40025c, 0x4000030 },
+	{ 0x3d400264, 0x900093e7 },
+	{ 0x3d40026c, 0x2005574 },
+	{ 0x3d400400, 0x111 },
+	{ 0x3d400408, 0x72ff },
+	{ 0x3d400494, 0x2100e07 },
+	{ 0x3d400498, 0x620096 },
+	{ 0x3d40049c, 0x1100e07 },
+	{ 0x3d4004a0, 0xc8012c },
+	{ 0x3d402020, 0x11 },
+	{ 0x3d402024, 0x7d00 },
+	{ 0x3d402050, 0x20d040 },
+	{ 0x3d402064, 0xc001c },
+	{ 0x3d4020dc, 0x840000 },
+	{ 0x3d4020e0, 0x310000 },
+	{ 0x3d4020e8, 0x66004d },
+	{ 0x3d4020ec, 0x16004d },
+	{ 0x3d402100, 0xa040305 },
+	{ 0x3d402104, 0x30407 },
+	{ 0x3d402108, 0x203060b },
+	{ 0x3d40210c, 0x505000 },
+	{ 0x3d402110, 0x2040202 },
+	{ 0x3d402114, 0x2030202 },
+	{ 0x3d402118, 0x1010004 },
+	{ 0x3d40211c, 0x301 },
+	{ 0x3d402130, 0x20300 },
+	{ 0x3d402134, 0xa100002 },
+	{ 0x3d402138, 0x1d },
+	{ 0x3d402144, 0x14000a },
+	{ 0x3d402180, 0x640004 },
+	{ 0x3d402190, 0x3818200 },
+	{ 0x3d402194, 0x80303 },
+	{ 0x3d4021b4, 0x100 },
+	{ 0x3d4020f4, 0xc99 },
+	{ 0x3d403020, 0x11 },
+	{ 0x3d403024, 0x1f40 },
+	{ 0x3d403050, 0x20d040 },
+	{ 0x3d403064, 0x30007 },
+	{ 0x3d4030dc, 0x840000 },
+	{ 0x3d4030e0, 0x310000 },
+	{ 0x3d4030e8, 0x66004d },
+	{ 0x3d4030ec, 0x16004d },
+	{ 0x3d403100, 0xa010102 },
+	{ 0x3d403104, 0x30404 },
+	{ 0x3d403108, 0x203060b },
+	{ 0x3d40310c, 0x505000 },
+	{ 0x3d403110, 0x2040202 },
+	{ 0x3d403114, 0x2030202 },
+	{ 0x3d403118, 0x1010004 },
+	{ 0x3d40311c, 0x301 },
+	{ 0x3d403130, 0x20300 },
+	{ 0x3d403134, 0xa100002 },
+	{ 0x3d403138, 0x8 },
+	{ 0x3d403144, 0x50003 },
+	{ 0x3d403180, 0x190004 },
+	{ 0x3d403190, 0x3818200 },
+	{ 0x3d403194, 0x80303 },
+	{ 0x3d4031b4, 0x100 },
+	{ 0x3d4030f4, 0xc99 },
+	{ 0x3d400028, 0x0 },
+};
+
+/* PHY Initialize Configuration */
+struct dram_cfg_param ddr_ddrphy_cfg[] = {
+	{ 0x100a0, 0x0 },
+	{ 0x100a1, 0x1 },
+	{ 0x100a2, 0x2 },
+	{ 0x100a3, 0x3 },
+	{ 0x100a4, 0x4 },
+	{ 0x100a5, 0x5 },
+	{ 0x100a6, 0x6 },
+	{ 0x100a7, 0x7 },
+	{ 0x110a0, 0x0 },
+	{ 0x110a1, 0x1 },
+	{ 0x110a2, 0x3 },
+	{ 0x110a3, 0x4 },
+	{ 0x110a4, 0x5 },
+	{ 0x110a5, 0x2 },
+	{ 0x110a6, 0x7 },
+	{ 0x110a7, 0x6 },
+	{ 0x1005f, 0x1ff },
+	{ 0x1015f, 0x1ff },
+	{ 0x1105f, 0x1ff },
+	{ 0x1115f, 0x1ff },
+	{ 0x11005f, 0x1ff },
+	{ 0x11015f, 0x1ff },
+	{ 0x11105f, 0x1ff },
+	{ 0x11115f, 0x1ff },
+	{ 0x21005f, 0x1ff },
+	{ 0x21015f, 0x1ff },
+	{ 0x21105f, 0x1ff },
+	{ 0x21115f, 0x1ff },
+	{ 0x55, 0x1ff },
+	{ 0x1055, 0x1ff },
+	{ 0x2055, 0x1ff },
+	{ 0x3055, 0x1ff },
+	{ 0x4055, 0x1ff },
+	{ 0x5055, 0x1ff },
+	{ 0x6055, 0x1ff },
+	{ 0x7055, 0x1ff },
+	{ 0x8055, 0x1ff },
+	{ 0x9055, 0x1ff },
+	{ 0x200c5, 0xb },
+	{ 0x1200c5, 0x7 },
+	{ 0x2200c5, 0x7 },
+	{ 0x2002e, 0x1 },
+	{ 0x12002e, 0x2 },
+	{ 0x22002e, 0x2 },
+	{ 0x90204, 0x0 },
+	{ 0x190204, 0x0 },
+	{ 0x290204, 0x0 },
+	{ 0x20024, 0x1a3 },
+	{ 0x2003a, 0x2 },
+	{ 0x120024, 0x1a3 },
+	{ 0x2003a, 0x2 },
+	{ 0x220024, 0x1a3 },
+	{ 0x2003a, 0x2 },
+	{ 0x20056, 0x3 },
+	{ 0x120056, 0x3 },
+	{ 0x220056, 0x3 },
+	{ 0x1004d, 0xe00 },
+	{ 0x1014d, 0xe00 },
+	{ 0x1104d, 0xe00 },
+	{ 0x1114d, 0xe00 },
+	{ 0x11004d, 0xe00 },
+	{ 0x11014d, 0xe00 },
+	{ 0x11104d, 0xe00 },
+	{ 0x11114d, 0xe00 },
+	{ 0x21004d, 0xe00 },
+	{ 0x21014d, 0xe00 },
+	{ 0x21104d, 0xe00 },
+	{ 0x21114d, 0xe00 },
+	{ 0x10049, 0xeba },
+	{ 0x10149, 0xeba },
+	{ 0x11049, 0xeba },
+	{ 0x11149, 0xeba },
+	{ 0x110049, 0xeba },
+	{ 0x110149, 0xeba },
+	{ 0x111049, 0xeba },
+	{ 0x111149, 0xeba },
+	{ 0x210049, 0xeba },
+	{ 0x210149, 0xeba },
+	{ 0x211049, 0xeba },
+	{ 0x211149, 0xeba },
+	{ 0x43, 0x63 },
+	{ 0x1043, 0x63 },
+	{ 0x2043, 0x63 },
+	{ 0x3043, 0x63 },
+	{ 0x4043, 0x63 },
+	{ 0x5043, 0x63 },
+	{ 0x6043, 0x63 },
+	{ 0x7043, 0x63 },
+	{ 0x8043, 0x63 },
+	{ 0x9043, 0x63 },
+	{ 0x20018, 0x1 },
+	{ 0x20075, 0x4 },
+	{ 0x20050, 0x0 },
+	{ 0x20008, 0x190 },
+	{ 0x120008, 0x64 },
+	{ 0x220008, 0x19 },
+	{ 0x20088, 0x9 },
+	{ 0x200b2, 0xdc },
+	{ 0x10043, 0x5a1 },
+	{ 0x10143, 0x5a1 },
+	{ 0x11043, 0x5a1 },
+	{ 0x11143, 0x5a1 },
+	{ 0x1200b2, 0xdc },
+	{ 0x110043, 0x5a1 },
+	{ 0x110143, 0x5a1 },
+	{ 0x111043, 0x5a1 },
+	{ 0x111143, 0x5a1 },
+	{ 0x2200b2, 0xdc },
+	{ 0x210043, 0x5a1 },
+	{ 0x210143, 0x5a1 },
+	{ 0x211043, 0x5a1 },
+	{ 0x211143, 0x5a1 },
+	{ 0x200fa, 0x1 },
+	{ 0x1200fa, 0x1 },
+	{ 0x2200fa, 0x1 },
+	{ 0x20019, 0x1 },
+	{ 0x120019, 0x1 },
+	{ 0x220019, 0x1 },
+	{ 0x200f0, 0x660 },
+	{ 0x200f1, 0x0 },
+	{ 0x200f2, 0x4444 },
+	{ 0x200f3, 0x8888 },
+	{ 0x200f4, 0x5665 },
+	{ 0x200f5, 0x0 },
+	{ 0x200f6, 0x0 },
+	{ 0x200f7, 0xf000 },
+	{ 0x20025, 0x0 },
+	{ 0x2002d, 0x0 },
+	{ 0x12002d, 0x0 },
+	{ 0x22002d, 0x0 },
+	{ 0x2005b, 0x7529 },
+	{ 0x2005c, 0x0 },
+	{ 0x200c7, 0x21 },
+	{ 0x200ca, 0x24 },
+	{ 0x200cc, 0x1f7 },
+	{ 0x1200c7, 0x21 },
+	{ 0x1200ca, 0x24 },
+	{ 0x1200cc, 0x1f7 },
+	{ 0x2200c7, 0x21 },
+	{ 0x2200ca, 0x24 },
+	{ 0x2200cc, 0x1f7 },
+	{ 0x2007d, 0x212 },
+	{ 0x12007d, 0x212 },
+	{ 0x22007d, 0x212 },
+	{ 0x2007c, 0x61 },
+	{ 0x12007c, 0x61 },
+	{ 0x22007c, 0x61 },
+	{ 0x1004a, 0x500 },
+	{ 0x1104a, 0x500 },
+	{ 0x2002c, 0x0 },
+};
+
+/* ddr phy trained csr */
+struct dram_cfg_param ddr_ddrphy_trained_csr[] = {
+	{0x0200b2, 0x0},
+	{0x1200b2, 0x0},
+	{0x2200b2, 0x0},
+	{0x0200cb, 0x0},
+	{0x010043, 0x0},
+	{0x110043, 0x0},
+	{0x210043, 0x0},
+	{0x010143, 0x0},
+	{0x110143, 0x0},
+	{0x210143, 0x0},
+	{0x011043, 0x0},
+	{0x111043, 0x0},
+	{0x211043, 0x0},
+	{0x011143, 0x0},
+	{0x111143, 0x0},
+	{0x211143, 0x0},
+	{0x000080, 0x0},
+	{0x100080, 0x0},
+	{0x200080, 0x0},
+	{0x001080, 0x0},
+	{0x101080, 0x0},
+	{0x201080, 0x0},
+	{0x002080, 0x0},
+	{0x102080, 0x0},
+	{0x202080, 0x0},
+	{0x003080, 0x0},
+	{0x103080, 0x0},
+	{0x203080, 0x0},
+	{0x004080, 0x0},
+	{0x104080, 0x0},
+	{0x204080, 0x0},
+	{0x005080, 0x0},
+	{0x105080, 0x0},
+	{0x205080, 0x0},
+	{0x006080, 0x0},
+	{0x106080, 0x0},
+	{0x206080, 0x0},
+	{0x007080, 0x0},
+	{0x107080, 0x0},
+	{0x207080, 0x0},
+	{0x008080, 0x0},
+	{0x108080, 0x0},
+	{0x208080, 0x0},
+	{0x009080, 0x0},
+	{0x109080, 0x0},
+	{0x209080, 0x0},
+	{0x010080, 0x0},
+	{0x110080, 0x0},
+	{0x210080, 0x0},
+	{0x010180, 0x0},
+	{0x110180, 0x0},
+	{0x210180, 0x0},
+	{0x011080, 0x0},
+	{0x111080, 0x0},
+	{0x211080, 0x0},
+	{0x011180, 0x0},
+	{0x111180, 0x0},
+	{0x211180, 0x0},
+	{0x010081, 0x0},
+	{0x110081, 0x0},
+	{0x210081, 0x0},
+	{0x010181, 0x0},
+	{0x110181, 0x0},
+	{0x210181, 0x0},
+	{0x011081, 0x0},
+	{0x111081, 0x0},
+	{0x211081, 0x0},
+	{0x011181, 0x0},
+	{0x111181, 0x0},
+	{0x211181, 0x0},
+	{0x0100d0, 0x0},
+	{0x1100d0, 0x0},
+	{0x2100d0, 0x0},
+	{0x0101d0, 0x0},
+	{0x1101d0, 0x0},
+	{0x2101d0, 0x0},
+	{0x0110d0, 0x0},
+	{0x1110d0, 0x0},
+	{0x2110d0, 0x0},
+	{0x0111d0, 0x0},
+	{0x1111d0, 0x0},
+	{0x2111d0, 0x0},
+	{0x0100d1, 0x0},
+	{0x1100d1, 0x0},
+	{0x2100d1, 0x0},
+	{0x0101d1, 0x0},
+	{0x1101d1, 0x0},
+	{0x2101d1, 0x0},
+	{0x0110d1, 0x0},
+	{0x1110d1, 0x0},
+	{0x2110d1, 0x0},
+	{0x0111d1, 0x0},
+	{0x1111d1, 0x0},
+	{0x2111d1, 0x0},
+	{0x010068, 0x0},
+	{0x010168, 0x0},
+	{0x010268, 0x0},
+	{0x010368, 0x0},
+	{0x010468, 0x0},
+	{0x010568, 0x0},
+	{0x010668, 0x0},
+	{0x010768, 0x0},
+	{0x010868, 0x0},
+	{0x011068, 0x0},
+	{0x011168, 0x0},
+	{0x011268, 0x0},
+	{0x011368, 0x0},
+	{0x011468, 0x0},
+	{0x011568, 0x0},
+	{0x011668, 0x0},
+	{0x011768, 0x0},
+	{0x011868, 0x0},
+	{0x010069, 0x0},
+	{0x010169, 0x0},
+	{0x010269, 0x0},
+	{0x010369, 0x0},
+	{0x010469, 0x0},
+	{0x010569, 0x0},
+	{0x010669, 0x0},
+	{0x010769, 0x0},
+	{0x010869, 0x0},
+	{0x011069, 0x0},
+	{0x011169, 0x0},
+	{0x011269, 0x0},
+	{0x011369, 0x0},
+	{0x011469, 0x0},
+	{0x011569, 0x0},
+	{0x011669, 0x0},
+	{0x011769, 0x0},
+	{0x011869, 0x0},
+	{0x01008c, 0x0},
+	{0x11008c, 0x0},
+	{0x21008c, 0x0},
+	{0x01018c, 0x0},
+	{0x11018c, 0x0},
+	{0x21018c, 0x0},
+	{0x01108c, 0x0},
+	{0x11108c, 0x0},
+	{0x21108c, 0x0},
+	{0x01118c, 0x0},
+	{0x11118c, 0x0},
+	{0x21118c, 0x0},
+	{0x01008d, 0x0},
+	{0x11008d, 0x0},
+	{0x21008d, 0x0},
+	{0x01018d, 0x0},
+	{0x11018d, 0x0},
+	{0x21018d, 0x0},
+	{0x01108d, 0x0},
+	{0x11108d, 0x0},
+	{0x21108d, 0x0},
+	{0x01118d, 0x0},
+	{0x11118d, 0x0},
+	{0x21118d, 0x0},
+	{0x0100c0, 0x0},
+	{0x1100c0, 0x0},
+	{0x2100c0, 0x0},
+	{0x0101c0, 0x0},
+	{0x1101c0, 0x0},
+	{0x2101c0, 0x0},
+	{0x0102c0, 0x0},
+	{0x1102c0, 0x0},
+	{0x2102c0, 0x0},
+	{0x0103c0, 0x0},
+	{0x1103c0, 0x0},
+	{0x2103c0, 0x0},
+	{0x0104c0, 0x0},
+	{0x1104c0, 0x0},
+	{0x2104c0, 0x0},
+	{0x0105c0, 0x0},
+	{0x1105c0, 0x0},
+	{0x2105c0, 0x0},
+	{0x0106c0, 0x0},
+	{0x1106c0, 0x0},
+	{0x2106c0, 0x0},
+	{0x0107c0, 0x0},
+	{0x1107c0, 0x0},
+	{0x2107c0, 0x0},
+	{0x0108c0, 0x0},
+	{0x1108c0, 0x0},
+	{0x2108c0, 0x0},
+	{0x0110c0, 0x0},
+	{0x1110c0, 0x0},
+	{0x2110c0, 0x0},
+	{0x0111c0, 0x0},
+	{0x1111c0, 0x0},
+	{0x2111c0, 0x0},
+	{0x0112c0, 0x0},
+	{0x1112c0, 0x0},
+	{0x2112c0, 0x0},
+	{0x0113c0, 0x0},
+	{0x1113c0, 0x0},
+	{0x2113c0, 0x0},
+	{0x0114c0, 0x0},
+	{0x1114c0, 0x0},
+	{0x2114c0, 0x0},
+	{0x0115c0, 0x0},
+	{0x1115c0, 0x0},
+	{0x2115c0, 0x0},
+	{0x0116c0, 0x0},
+	{0x1116c0, 0x0},
+	{0x2116c0, 0x0},
+	{0x0117c0, 0x0},
+	{0x1117c0, 0x0},
+	{0x2117c0, 0x0},
+	{0x0118c0, 0x0},
+	{0x1118c0, 0x0},
+	{0x2118c0, 0x0},
+	{0x0100c1, 0x0},
+	{0x1100c1, 0x0},
+	{0x2100c1, 0x0},
+	{0x0101c1, 0x0},
+	{0x1101c1, 0x0},
+	{0x2101c1, 0x0},
+	{0x0102c1, 0x0},
+	{0x1102c1, 0x0},
+	{0x2102c1, 0x0},
+	{0x0103c1, 0x0},
+	{0x1103c1, 0x0},
+	{0x2103c1, 0x0},
+	{0x0104c1, 0x0},
+	{0x1104c1, 0x0},
+	{0x2104c1, 0x0},
+	{0x0105c1, 0x0},
+	{0x1105c1, 0x0},
+	{0x2105c1, 0x0},
+	{0x0106c1, 0x0},
+	{0x1106c1, 0x0},
+	{0x2106c1, 0x0},
+	{0x0107c1, 0x0},
+	{0x1107c1, 0x0},
+	{0x2107c1, 0x0},
+	{0x0108c1, 0x0},
+	{0x1108c1, 0x0},
+	{0x2108c1, 0x0},
+	{0x0110c1, 0x0},
+	{0x1110c1, 0x0},
+	{0x2110c1, 0x0},
+	{0x0111c1, 0x0},
+	{0x1111c1, 0x0},
+	{0x2111c1, 0x0},
+	{0x0112c1, 0x0},
+	{0x1112c1, 0x0},
+	{0x2112c1, 0x0},
+	{0x0113c1, 0x0},
+	{0x1113c1, 0x0},
+	{0x2113c1, 0x0},
+	{0x0114c1, 0x0},
+	{0x1114c1, 0x0},
+	{0x2114c1, 0x0},
+	{0x0115c1, 0x0},
+	{0x1115c1, 0x0},
+	{0x2115c1, 0x0},
+	{0x0116c1, 0x0},
+	{0x1116c1, 0x0},
+	{0x2116c1, 0x0},
+	{0x0117c1, 0x0},
+	{0x1117c1, 0x0},
+	{0x2117c1, 0x0},
+	{0x0118c1, 0x0},
+	{0x1118c1, 0x0},
+	{0x2118c1, 0x0},
+	{0x010020, 0x0},
+	{0x110020, 0x0},
+	{0x210020, 0x0},
+	{0x011020, 0x0},
+	{0x111020, 0x0},
+	{0x211020, 0x0},
+	{0x020072, 0x0},
+	{0x020073, 0x0},
+	{0x020074, 0x0},
+	{0x0100aa, 0x0},
+	{0x0110aa, 0x0},
+	{0x020010, 0x0},
+	{0x120010, 0x0},
+	{0x220010, 0x0},
+	{0x020011, 0x0},
+	{0x120011, 0x0},
+	{0x220011, 0x0},
+	{0x0100ae, 0x0},
+	{0x1100ae, 0x0},
+	{0x2100ae, 0x0},
+	{0x0100af, 0x0},
+	{0x1100af, 0x0},
+	{0x2100af, 0x0},
+	{0x0110ae, 0x0},
+	{0x1110ae, 0x0},
+	{0x2110ae, 0x0},
+	{0x0110af, 0x0},
+	{0x1110af, 0x0},
+	{0x2110af, 0x0},
+	{0x020020, 0x0},
+	{0x120020, 0x0},
+	{0x220020, 0x0},
+	{0x0100a0, 0x0},
+	{0x0100a1, 0x0},
+	{0x0100a2, 0x0},
+	{0x0100a3, 0x0},
+	{0x0100a4, 0x0},
+	{0x0100a5, 0x0},
+	{0x0100a6, 0x0},
+	{0x0100a7, 0x0},
+	{0x0110a0, 0x0},
+	{0x0110a1, 0x0},
+	{0x0110a2, 0x0},
+	{0x0110a3, 0x0},
+	{0x0110a4, 0x0},
+	{0x0110a5, 0x0},
+	{0x0110a6, 0x0},
+	{0x0110a7, 0x0},
+	{0x02007c, 0x0},
+	{0x12007c, 0x0},
+	{0x22007c, 0x0},
+	{0x02007d, 0x0},
+	{0x12007d, 0x0},
+	{0x22007d, 0x0},
+	{0x0400fd, 0x0},
+	{0x0400c0, 0x0},
+	{0x090201, 0x0},
+	{0x190201, 0x0},
+	{0x290201, 0x0},
+	{0x090202, 0x0},
+	{0x190202, 0x0},
+	{0x290202, 0x0},
+	{0x090203, 0x0},
+	{0x190203, 0x0},
+	{0x290203, 0x0},
+	{0x090204, 0x0},
+	{0x190204, 0x0},
+	{0x290204, 0x0},
+	{0x090205, 0x0},
+	{0x190205, 0x0},
+	{0x290205, 0x0},
+	{0x090206, 0x0},
+	{0x190206, 0x0},
+	{0x290206, 0x0},
+	{0x090207, 0x0},
+	{0x190207, 0x0},
+	{0x290207, 0x0},
+	{0x090208, 0x0},
+	{0x190208, 0x0},
+	{0x290208, 0x0},
+	{0x010062, 0x0},
+	{0x010162, 0x0},
+	{0x010262, 0x0},
+	{0x010362, 0x0},
+	{0x010462, 0x0},
+	{0x010562, 0x0},
+	{0x010662, 0x0},
+	{0x010762, 0x0},
+	{0x010862, 0x0},
+	{0x011062, 0x0},
+	{0x011162, 0x0},
+	{0x011262, 0x0},
+	{0x011362, 0x0},
+	{0x011462, 0x0},
+	{0x011562, 0x0},
+	{0x011662, 0x0},
+	{0x011762, 0x0},
+	{0x011862, 0x0},
+	{0x020077, 0x0},
+	{0x010001, 0x0},
+	{0x011001, 0x0},
+	{0x010040, 0x0},
+	{0x010140, 0x0},
+	{0x010240, 0x0},
+	{0x010340, 0x0},
+	{0x010440, 0x0},
+	{0x010540, 0x0},
+	{0x010640, 0x0},
+	{0x010740, 0x0},
+	{0x010840, 0x0},
+	{0x010030, 0x0},
+	{0x010130, 0x0},
+	{0x010230, 0x0},
+	{0x010330, 0x0},
+	{0x010430, 0x0},
+	{0x010530, 0x0},
+	{0x010630, 0x0},
+	{0x010730, 0x0},
+	{0x010830, 0x0},
+	{0x011040, 0x0},
+	{0x011140, 0x0},
+	{0x011240, 0x0},
+	{0x011340, 0x0},
+	{0x011440, 0x0},
+	{0x011540, 0x0},
+	{0x011640, 0x0},
+	{0x011740, 0x0},
+	{0x011840, 0x0},
+	{0x011030, 0x0},
+	{0x011130, 0x0},
+	{0x011230, 0x0},
+	{0x011330, 0x0},
+	{0x011430, 0x0},
+	{0x011530, 0x0},
+	{0x011630, 0x0},
+	{0x011730, 0x0},
+	{0x011830, 0x0},
+};
+
+/* P0 message block paremeter for training firmware */
+struct dram_cfg_param ddr_fsp0_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54003, 0x640 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, 0x2228 },
+	{ 0x54006, 0x11 },
+	{ 0x54008, 0x131f },
+	{ 0x54009, 0xc8 },
+	{ 0x5400b, 0x2 },
+	{ 0x5400f, 0x100 },
+	{ 0x54012, 0x310 },
+	{ 0x54019, 0x12a4 },
+	{ 0x5401a, 0x31 },
+	{ 0x5401b, 0x4d66 },
+	{ 0x5401c, 0x4d00 },
+	{ 0x5401e, 0x16 },
+	{ 0x5401f, 0x12a4 },
+	{ 0x54020, 0x31 },
+	{ 0x54021, 0x4d66 },
+	{ 0x54022, 0x4d00 },
+	{ 0x54024, 0x16 },
+	{ 0x54032, 0xa400 },
+	{ 0x54033, 0x3112 },
+	{ 0x54034, 0x6600 },
+	{ 0x54035, 0x4d },
+	{ 0x54036, 0x4d },
+	{ 0x54037, 0x1600 },
+	{ 0x54038, 0xa400 },
+	{ 0x54039, 0x3112 },
+	{ 0x5403a, 0x6600 },
+	{ 0x5403b, 0x4d },
+	{ 0x5403c, 0x4d },
+	{ 0x5403d, 0x1600 },
+	{ 0xd0000, 0x1 },
+};
+
+/* P1 message block paremeter for training firmware */
+struct dram_cfg_param ddr_fsp1_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54002, 0x101 },
+	{ 0x54003, 0x190 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, 0x2228 },
+	{ 0x54006, 0x11 },
+	{ 0x54008, 0x121f },
+	{ 0x54009, 0xc8 },
+	{ 0x5400b, 0x2 },
+	{ 0x5400f, 0x100 },
+	{ 0x54012, 0x310 },
+	{ 0x54019, 0x84 },
+	{ 0x5401a, 0x31 },
+	{ 0x5401b, 0x4d66 },
+	{ 0x5401c, 0x4d00 },
+	{ 0x5401e, 0x16 },
+	{ 0x5401f, 0x84 },
+	{ 0x54020, 0x31 },
+	{ 0x54021, 0x4d66 },
+	{ 0x54022, 0x4d00 },
+	{ 0x54024, 0x16 },
+	{ 0x54032, 0x8400 },
+	{ 0x54033, 0x3100 },
+	{ 0x54034, 0x6600 },
+	{ 0x54035, 0x4d },
+	{ 0x54036, 0x4d },
+	{ 0x54037, 0x1600 },
+	{ 0x54038, 0x8400 },
+	{ 0x54039, 0x3100 },
+	{ 0x5403a, 0x6600 },
+	{ 0x5403b, 0x4d },
+	{ 0x5403c, 0x4d },
+	{ 0x5403d, 0x1600 },
+	{ 0xd0000, 0x1 },
+};
+
+/* P2 message block paremeter for training firmware */
+struct dram_cfg_param ddr_fsp2_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54002, 0x102 },
+	{ 0x54003, 0x64 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, 0x2228 },
+	{ 0x54006, 0x11 },
+	{ 0x54008, 0x121f },
+	{ 0x54009, 0xc8 },
+	{ 0x5400b, 0x2 },
+	{ 0x5400f, 0x100 },
+	{ 0x54012, 0x310 },
+	{ 0x54019, 0x84 },
+	{ 0x5401a, 0x31 },
+	{ 0x5401b, 0x4d66 },
+	{ 0x5401c, 0x4d00 },
+	{ 0x5401e, 0x16 },
+	{ 0x5401f, 0x84 },
+	{ 0x54020, 0x31 },
+	{ 0x54021, 0x4d66 },
+	{ 0x54022, 0x4d00 },
+	{ 0x54024, 0x16 },
+	{ 0x54032, 0x8400 },
+	{ 0x54033, 0x3100 },
+	{ 0x54034, 0x6600 },
+	{ 0x54035, 0x4d },
+	{ 0x54036, 0x4d },
+	{ 0x54037, 0x1600 },
+	{ 0x54038, 0x8400 },
+	{ 0x54039, 0x3100 },
+	{ 0x5403a, 0x6600 },
+	{ 0x5403b, 0x4d },
+	{ 0x5403c, 0x4d },
+	{ 0x5403d, 0x1600 },
+	{ 0xd0000, 0x1 },
+};
+
+/* P0 2D message block paremeter for training firmware */
+struct dram_cfg_param ddr_fsp0_2d_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54003, 0x640 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, 0x2228 },
+	{ 0x54006, 0x11 },
+	{ 0x54008, 0x61 },
+	{ 0x54009, 0xc8 },
+	{ 0x5400b, 0x2 },
+	{ 0x5400f, 0x100 },
+	{ 0x54010, 0x1f7f },
+	{ 0x54012, 0x310 },
+	{ 0x54019, 0x12a4 },
+	{ 0x5401a, 0x31 },
+	{ 0x5401b, 0x4d66 },
+	{ 0x5401c, 0x4d00 },
+	{ 0x5401e, 0x16 },
+	{ 0x5401f, 0x12a4 },
+	{ 0x54020, 0x31 },
+	{ 0x54021, 0x4d66 },
+	{ 0x54022, 0x4d00 },
+	{ 0x54024, 0x16 },
+	{ 0x54032, 0xa400 },
+	{ 0x54033, 0x3112 },
+	{ 0x54034, 0x6600 },
+	{ 0x54035, 0x4d },
+	{ 0x54036, 0x4d },
+	{ 0x54037, 0x1600 },
+	{ 0x54038, 0xa400 },
+	{ 0x54039, 0x3112 },
+	{ 0x5403a, 0x6600 },
+	{ 0x5403b, 0x4d },
+	{ 0x5403c, 0x4d },
+	{ 0x5403d, 0x1600 },
+	{ 0xd0000, 0x1 },
+};
+
+/* DRAM PHY init engine image */
+struct dram_cfg_param ddr_phy_pie[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x90000, 0x10 },
+	{ 0x90001, 0x400 },
+	{ 0x90002, 0x10e },
+	{ 0x90003, 0x0 },
+	{ 0x90004, 0x0 },
+	{ 0x90005, 0x8 },
+	{ 0x90029, 0xb },
+	{ 0x9002a, 0x480 },
+	{ 0x9002b, 0x109 },
+	{ 0x9002c, 0x8 },
+	{ 0x9002d, 0x448 },
+	{ 0x9002e, 0x139 },
+	{ 0x9002f, 0x8 },
+	{ 0x90030, 0x478 },
+	{ 0x90031, 0x109 },
+	{ 0x90032, 0x0 },
+	{ 0x90033, 0xe8 },
+	{ 0x90034, 0x109 },
+	{ 0x90035, 0x2 },
+	{ 0x90036, 0x10 },
+	{ 0x90037, 0x139 },
+	{ 0x90038, 0xb },
+	{ 0x90039, 0x7c0 },
+	{ 0x9003a, 0x139 },
+	{ 0x9003b, 0x44 },
+	{ 0x9003c, 0x633 },
+	{ 0x9003d, 0x159 },
+	{ 0x9003e, 0x14f },
+	{ 0x9003f, 0x630 },
+	{ 0x90040, 0x159 },
+	{ 0x90041, 0x47 },
+	{ 0x90042, 0x633 },
+	{ 0x90043, 0x149 },
+	{ 0x90044, 0x4f },
+	{ 0x90045, 0x633 },
+	{ 0x90046, 0x179 },
+	{ 0x90047, 0x8 },
+	{ 0x90048, 0xe0 },
+	{ 0x90049, 0x109 },
+	{ 0x9004a, 0x0 },
+	{ 0x9004b, 0x7c8 },
+	{ 0x9004c, 0x109 },
+	{ 0x9004d, 0x0 },
+	{ 0x9004e, 0x1 },
+	{ 0x9004f, 0x8 },
+	{ 0x90050, 0x0 },
+	{ 0x90051, 0x45a },
+	{ 0x90052, 0x9 },
+	{ 0x90053, 0x0 },
+	{ 0x90054, 0x448 },
+	{ 0x90055, 0x109 },
+	{ 0x90056, 0x40 },
+	{ 0x90057, 0x633 },
+	{ 0x90058, 0x179 },
+	{ 0x90059, 0x1 },
+	{ 0x9005a, 0x618 },
+	{ 0x9005b, 0x109 },
+	{ 0x9005c, 0x40c0 },
+	{ 0x9005d, 0x633 },
+	{ 0x9005e, 0x149 },
+	{ 0x9005f, 0x8 },
+	{ 0x90060, 0x4 },
+	{ 0x90061, 0x48 },
+	{ 0x90062, 0x4040 },
+	{ 0x90063, 0x633 },
+	{ 0x90064, 0x149 },
+	{ 0x90065, 0x0 },
+	{ 0x90066, 0x4 },
+	{ 0x90067, 0x48 },
+	{ 0x90068, 0x40 },
+	{ 0x90069, 0x633 },
+	{ 0x9006a, 0x149 },
+	{ 0x9006b, 0x10 },
+	{ 0x9006c, 0x4 },
+	{ 0x9006d, 0x18 },
+	{ 0x9006e, 0x0 },
+	{ 0x9006f, 0x4 },
+	{ 0x90070, 0x78 },
+	{ 0x90071, 0x549 },
+	{ 0x90072, 0x633 },
+	{ 0x90073, 0x159 },
+	{ 0x90074, 0xd49 },
+	{ 0x90075, 0x633 },
+	{ 0x90076, 0x159 },
+	{ 0x90077, 0x94a },
+	{ 0x90078, 0x633 },
+	{ 0x90079, 0x159 },
+	{ 0x9007a, 0x441 },
+	{ 0x9007b, 0x633 },
+	{ 0x9007c, 0x149 },
+	{ 0x9007d, 0x42 },
+	{ 0x9007e, 0x633 },
+	{ 0x9007f, 0x149 },
+	{ 0x90080, 0x1 },
+	{ 0x90081, 0x633 },
+	{ 0x90082, 0x149 },
+	{ 0x90083, 0x0 },
+	{ 0x90084, 0xe0 },
+	{ 0x90085, 0x109 },
+	{ 0x90086, 0xa },
+	{ 0x90087, 0x10 },
+	{ 0x90088, 0x109 },
+	{ 0x90089, 0x9 },
+	{ 0x9008a, 0x3c0 },
+	{ 0x9008b, 0x149 },
+	{ 0x9008c, 0x9 },
+	{ 0x9008d, 0x3c0 },
+	{ 0x9008e, 0x159 },
+	{ 0x9008f, 0x18 },
+	{ 0x90090, 0x10 },
+	{ 0x90091, 0x109 },
+	{ 0x90092, 0x0 },
+	{ 0x90093, 0x3c0 },
+	{ 0x90094, 0x109 },
+	{ 0x90095, 0x18 },
+	{ 0x90096, 0x4 },
+	{ 0x90097, 0x48 },
+	{ 0x90098, 0x18 },
+	{ 0x90099, 0x4 },
+	{ 0x9009a, 0x58 },
+	{ 0x9009b, 0xb },
+	{ 0x9009c, 0x10 },
+	{ 0x9009d, 0x109 },
+	{ 0x9009e, 0x1 },
+	{ 0x9009f, 0x10 },
+	{ 0x900a0, 0x109 },
+	{ 0x900a1, 0x5 },
+	{ 0x900a2, 0x7c0 },
+	{ 0x900a3, 0x109 },
+	{ 0x40000, 0x811 },
+	{ 0x40020, 0x880 },
+	{ 0x40040, 0x0 },
+	{ 0x40060, 0x0 },
+	{ 0x40001, 0x4008 },
+	{ 0x40021, 0x83 },
+	{ 0x40041, 0x4f },
+	{ 0x40061, 0x0 },
+	{ 0x40002, 0x4040 },
+	{ 0x40022, 0x83 },
+	{ 0x40042, 0x51 },
+	{ 0x40062, 0x0 },
+	{ 0x40003, 0x811 },
+	{ 0x40023, 0x880 },
+	{ 0x40043, 0x0 },
+	{ 0x40063, 0x0 },
+	{ 0x40004, 0x720 },
+	{ 0x40024, 0xf },
+	{ 0x40044, 0x1740 },
+	{ 0x40064, 0x0 },
+	{ 0x40005, 0x16 },
+	{ 0x40025, 0x83 },
+	{ 0x40045, 0x4b },
+	{ 0x40065, 0x0 },
+	{ 0x40006, 0x716 },
+	{ 0x40026, 0xf },
+	{ 0x40046, 0x2001 },
+	{ 0x40066, 0x0 },
+	{ 0x40007, 0x716 },
+	{ 0x40027, 0xf },
+	{ 0x40047, 0x2800 },
+	{ 0x40067, 0x0 },
+	{ 0x40008, 0x716 },
+	{ 0x40028, 0xf },
+	{ 0x40048, 0xf00 },
+	{ 0x40068, 0x0 },
+	{ 0x40009, 0x720 },
+	{ 0x40029, 0xf },
+	{ 0x40049, 0x1400 },
+	{ 0x40069, 0x0 },
+	{ 0x4000a, 0xe08 },
+	{ 0x4002a, 0xc15 },
+	{ 0x4004a, 0x0 },
+	{ 0x4006a, 0x0 },
+	{ 0x4000b, 0x625 },
+	{ 0x4002b, 0x15 },
+	{ 0x4004b, 0x0 },
+	{ 0x4006b, 0x0 },
+	{ 0x4000c, 0x4028 },
+	{ 0x4002c, 0x80 },
+	{ 0x4004c, 0x0 },
+	{ 0x4006c, 0x0 },
+	{ 0x4000d, 0xe08 },
+	{ 0x4002d, 0xc1a },
+	{ 0x4004d, 0x0 },
+	{ 0x4006d, 0x0 },
+	{ 0x4000e, 0x625 },
+	{ 0x4002e, 0x1a },
+	{ 0x4004e, 0x0 },
+	{ 0x4006e, 0x0 },
+	{ 0x4000f, 0x4040 },
+	{ 0x4002f, 0x80 },
+	{ 0x4004f, 0x0 },
+	{ 0x4006f, 0x0 },
+	{ 0x40010, 0x2604 },
+	{ 0x40030, 0x15 },
+	{ 0x40050, 0x0 },
+	{ 0x40070, 0x0 },
+	{ 0x40011, 0x708 },
+	{ 0x40031, 0x5 },
+	{ 0x40051, 0x0 },
+	{ 0x40071, 0x2002 },
+	{ 0x40012, 0x8 },
+	{ 0x40032, 0x80 },
+	{ 0x40052, 0x0 },
+	{ 0x40072, 0x0 },
+	{ 0x40013, 0x2604 },
+	{ 0x40033, 0x1a },
+	{ 0x40053, 0x0 },
+	{ 0x40073, 0x0 },
+	{ 0x40014, 0x708 },
+	{ 0x40034, 0xa },
+	{ 0x40054, 0x0 },
+	{ 0x40074, 0x2002 },
+	{ 0x40015, 0x4040 },
+	{ 0x40035, 0x80 },
+	{ 0x40055, 0x0 },
+	{ 0x40075, 0x0 },
+	{ 0x40016, 0x60a },
+	{ 0x40036, 0x15 },
+	{ 0x40056, 0x1200 },
+	{ 0x40076, 0x0 },
+	{ 0x40017, 0x61a },
+	{ 0x40037, 0x15 },
+	{ 0x40057, 0x1300 },
+	{ 0x40077, 0x0 },
+	{ 0x40018, 0x60a },
+	{ 0x40038, 0x1a },
+	{ 0x40058, 0x1200 },
+	{ 0x40078, 0x0 },
+	{ 0x40019, 0x642 },
+	{ 0x40039, 0x1a },
+	{ 0x40059, 0x1300 },
+	{ 0x40079, 0x0 },
+	{ 0x4001a, 0x4808 },
+	{ 0x4003a, 0x880 },
+	{ 0x4005a, 0x0 },
+	{ 0x4007a, 0x0 },
+	{ 0x900a4, 0x0 },
+	{ 0x900a5, 0x790 },
+	{ 0x900a6, 0x11a },
+	{ 0x900a7, 0x8 },
+	{ 0x900a8, 0x7aa },
+	{ 0x900a9, 0x2a },
+	{ 0x900aa, 0x10 },
+	{ 0x900ab, 0x7b2 },
+	{ 0x900ac, 0x2a },
+	{ 0x900ad, 0x0 },
+	{ 0x900ae, 0x7c8 },
+	{ 0x900af, 0x109 },
+	{ 0x900b0, 0x10 },
+	{ 0x900b1, 0x10 },
+	{ 0x900b2, 0x109 },
+	{ 0x900b3, 0x10 },
+	{ 0x900b4, 0x2a8 },
+	{ 0x900b5, 0x129 },
+	{ 0x900b6, 0x8 },
+	{ 0x900b7, 0x370 },
+	{ 0x900b8, 0x129 },
+	{ 0x900b9, 0xa },
+	{ 0x900ba, 0x3c8 },
+	{ 0x900bb, 0x1a9 },
+	{ 0x900bc, 0xc },
+	{ 0x900bd, 0x408 },
+	{ 0x900be, 0x199 },
+	{ 0x900bf, 0x14 },
+	{ 0x900c0, 0x790 },
+	{ 0x900c1, 0x11a },
+	{ 0x900c2, 0x8 },
+	{ 0x900c3, 0x4 },
+	{ 0x900c4, 0x18 },
+	{ 0x900c5, 0xe },
+	{ 0x900c6, 0x408 },
+	{ 0x900c7, 0x199 },
+	{ 0x900c8, 0x8 },
+	{ 0x900c9, 0x8568 },
+	{ 0x900ca, 0x108 },
+	{ 0x900cb, 0x18 },
+	{ 0x900cc, 0x790 },
+	{ 0x900cd, 0x16a },
+	{ 0x900ce, 0x8 },
+	{ 0x900cf, 0x1d8 },
+	{ 0x900d0, 0x169 },
+	{ 0x900d1, 0x10 },
+	{ 0x900d2, 0x8558 },
+	{ 0x900d3, 0x168 },
+	{ 0x900d4, 0x70 },
+	{ 0x900d5, 0x788 },
+	{ 0x900d6, 0x16a },
+	{ 0x900d7, 0x1ff8 },
+	{ 0x900d8, 0x85a8 },
+	{ 0x900d9, 0x1e8 },
+	{ 0x900da, 0x50 },
+	{ 0x900db, 0x798 },
+	{ 0x900dc, 0x16a },
+	{ 0x900dd, 0x60 },
+	{ 0x900de, 0x7a0 },
+	{ 0x900df, 0x16a },
+	{ 0x900e0, 0x8 },
+	{ 0x900e1, 0x8310 },
+	{ 0x900e2, 0x168 },
+	{ 0x900e3, 0x8 },
+	{ 0x900e4, 0xa310 },
+	{ 0x900e5, 0x168 },
+	{ 0x900e6, 0xa },
+	{ 0x900e7, 0x408 },
+	{ 0x900e8, 0x169 },
+	{ 0x900e9, 0x6e },
+	{ 0x900ea, 0x0 },
+	{ 0x900eb, 0x68 },
+	{ 0x900ec, 0x0 },
+	{ 0x900ed, 0x408 },
+	{ 0x900ee, 0x169 },
+	{ 0x900ef, 0x0 },
+	{ 0x900f0, 0x8310 },
+	{ 0x900f1, 0x168 },
+	{ 0x900f2, 0x0 },
+	{ 0x900f3, 0xa310 },
+	{ 0x900f4, 0x168 },
+	{ 0x900f5, 0x1ff8 },
+	{ 0x900f6, 0x85a8 },
+	{ 0x900f7, 0x1e8 },
+	{ 0x900f8, 0x68 },
+	{ 0x900f9, 0x798 },
+	{ 0x900fa, 0x16a },
+	{ 0x900fb, 0x78 },
+	{ 0x900fc, 0x7a0 },
+	{ 0x900fd, 0x16a },
+	{ 0x900fe, 0x68 },
+	{ 0x900ff, 0x790 },
+	{ 0x90100, 0x16a },
+	{ 0x90101, 0x8 },
+	{ 0x90102, 0x8b10 },
+	{ 0x90103, 0x168 },
+	{ 0x90104, 0x8 },
+	{ 0x90105, 0xab10 },
+	{ 0x90106, 0x168 },
+	{ 0x90107, 0xa },
+	{ 0x90108, 0x408 },
+	{ 0x90109, 0x169 },
+	{ 0x9010a, 0x58 },
+	{ 0x9010b, 0x0 },
+	{ 0x9010c, 0x68 },
+	{ 0x9010d, 0x0 },
+	{ 0x9010e, 0x408 },
+	{ 0x9010f, 0x169 },
+	{ 0x90110, 0x0 },
+	{ 0x90111, 0x8b10 },
+	{ 0x90112, 0x168 },
+	{ 0x90113, 0x0 },
+	{ 0x90114, 0xab10 },
+	{ 0x90115, 0x168 },
+	{ 0x90116, 0x0 },
+	{ 0x90117, 0x1d8 },
+	{ 0x90118, 0x169 },
+	{ 0x90119, 0x80 },
+	{ 0x9011a, 0x790 },
+	{ 0x9011b, 0x16a },
+	{ 0x9011c, 0x18 },
+	{ 0x9011d, 0x7aa },
+	{ 0x9011e, 0x6a },
+	{ 0x9011f, 0xa },
+	{ 0x90120, 0x0 },
+	{ 0x90121, 0x1e9 },
+	{ 0x90122, 0x8 },
+	{ 0x90123, 0x8080 },
+	{ 0x90124, 0x108 },
+	{ 0x90125, 0xf },
+	{ 0x90126, 0x408 },
+	{ 0x90127, 0x169 },
+	{ 0x90128, 0xc },
+	{ 0x90129, 0x0 },
+	{ 0x9012a, 0x68 },
+	{ 0x9012b, 0x9 },
+	{ 0x9012c, 0x0 },
+	{ 0x9012d, 0x1a9 },
+	{ 0x9012e, 0x0 },
+	{ 0x9012f, 0x408 },
+	{ 0x90130, 0x169 },
+	{ 0x90131, 0x0 },
+	{ 0x90132, 0x8080 },
+	{ 0x90133, 0x108 },
+	{ 0x90134, 0x8 },
+	{ 0x90135, 0x7aa },
+	{ 0x90136, 0x6a },
+	{ 0x90137, 0x0 },
+	{ 0x90138, 0x8568 },
+	{ 0x90139, 0x108 },
+	{ 0x9013a, 0xb7 },
+	{ 0x9013b, 0x790 },
+	{ 0x9013c, 0x16a },
+	{ 0x9013d, 0x1f },
+	{ 0x9013e, 0x0 },
+	{ 0x9013f, 0x68 },
+	{ 0x90140, 0x8 },
+	{ 0x90141, 0x8558 },
+	{ 0x90142, 0x168 },
+	{ 0x90143, 0xf },
+	{ 0x90144, 0x408 },
+	{ 0x90145, 0x169 },
+	{ 0x90146, 0xd },
+	{ 0x90147, 0x0 },
+	{ 0x90148, 0x68 },
+	{ 0x90149, 0x0 },
+	{ 0x9014a, 0x408 },
+	{ 0x9014b, 0x169 },
+	{ 0x9014c, 0x0 },
+	{ 0x9014d, 0x8558 },
+	{ 0x9014e, 0x168 },
+	{ 0x9014f, 0x8 },
+	{ 0x90150, 0x3c8 },
+	{ 0x90151, 0x1a9 },
+	{ 0x90152, 0x3 },
+	{ 0x90153, 0x370 },
+	{ 0x90154, 0x129 },
+	{ 0x90155, 0x20 },
+	{ 0x90156, 0x2aa },
+	{ 0x90157, 0x9 },
+	{ 0x90158, 0x0 },
+	{ 0x90159, 0x400 },
+	{ 0x9015a, 0x10e },
+	{ 0x9015b, 0x8 },
+	{ 0x9015c, 0xe8 },
+	{ 0x9015d, 0x109 },
+	{ 0x9015e, 0x0 },
+	{ 0x9015f, 0x8140 },
+	{ 0x90160, 0x10c },
+	{ 0x90161, 0x10 },
+	{ 0x90162, 0x8138 },
+	{ 0x90163, 0x10c },
+	{ 0x90164, 0x8 },
+	{ 0x90165, 0x7c8 },
+	{ 0x90166, 0x101 },
+	{ 0x90167, 0x8 },
+	{ 0x90168, 0x448 },
+	{ 0x90169, 0x109 },
+	{ 0x9016a, 0xf },
+	{ 0x9016b, 0x7c0 },
+	{ 0x9016c, 0x109 },
+	{ 0x9016d, 0x0 },
+	{ 0x9016e, 0xe8 },
+	{ 0x9016f, 0x109 },
+	{ 0x90170, 0x47 },
+	{ 0x90171, 0x630 },
+	{ 0x90172, 0x109 },
+	{ 0x90173, 0x8 },
+	{ 0x90174, 0x618 },
+	{ 0x90175, 0x109 },
+	{ 0x90176, 0x8 },
+	{ 0x90177, 0xe0 },
+	{ 0x90178, 0x109 },
+	{ 0x90179, 0x0 },
+	{ 0x9017a, 0x7c8 },
+	{ 0x9017b, 0x109 },
+	{ 0x9017c, 0x8 },
+	{ 0x9017d, 0x8140 },
+	{ 0x9017e, 0x10c },
+	{ 0x9017f, 0x0 },
+	{ 0x90180, 0x1 },
+	{ 0x90181, 0x8 },
+	{ 0x90182, 0x8 },
+	{ 0x90183, 0x4 },
+	{ 0x90184, 0x8 },
+	{ 0x90185, 0x8 },
+	{ 0x90186, 0x7c8 },
+	{ 0x90187, 0x101 },
+	{ 0x90006, 0x0 },
+	{ 0x90007, 0x0 },
+	{ 0x90008, 0x8 },
+	{ 0x90009, 0x0 },
+	{ 0x9000a, 0x0 },
+	{ 0x9000b, 0x0 },
+	{ 0xd00e7, 0x400 },
+	{ 0x90017, 0x0 },
+	{ 0x9001f, 0x29 },
+	{ 0x90026, 0x6a },
+	{ 0x400d0, 0x0 },
+	{ 0x400d1, 0x101 },
+	{ 0x400d2, 0x105 },
+	{ 0x400d3, 0x107 },
+	{ 0x400d4, 0x10f },
+	{ 0x400d5, 0x202 },
+	{ 0x400d6, 0x20a },
+	{ 0x400d7, 0x20b },
+	{ 0x2003a, 0x2 },
+	{ 0x2000b, 0x32 },
+	{ 0x2000c, 0x64 },
+	{ 0x2000d, 0x3e8 },
+	{ 0x2000e, 0x2c },
+	{ 0x12000b, 0xc },
+	{ 0x12000c, 0x19 },
+	{ 0x12000d, 0xfa },
+	{ 0x12000e, 0x10 },
+	{ 0x22000b, 0x3 },
+	{ 0x22000c, 0x6 },
+	{ 0x22000d, 0x3e },
+	{ 0x22000e, 0x10 },
+	{ 0x9000c, 0x0 },
+	{ 0x9000d, 0x173 },
+	{ 0x9000e, 0x60 },
+	{ 0x9000f, 0x6110 },
+	{ 0x90010, 0x2152 },
+	{ 0x90011, 0xdfbd },
+	{ 0x90012, 0x2060 },
+	{ 0x90013, 0x6152 },
+	{ 0x20010, 0x5a },
+	{ 0x20011, 0x3 },
+	{ 0x120010, 0x5a },
+	{ 0x120011, 0x3 },
+	{ 0x220010, 0x5a },
+	{ 0x220011, 0x3 },
+	{ 0x40080, 0xe0 },
+	{ 0x40081, 0x12 },
+	{ 0x40082, 0xe0 },
+	{ 0x40083, 0x12 },
+	{ 0x40084, 0xe0 },
+	{ 0x40085, 0x12 },
+	{ 0x140080, 0xe0 },
+	{ 0x140081, 0x12 },
+	{ 0x140082, 0xe0 },
+	{ 0x140083, 0x12 },
+	{ 0x140084, 0xe0 },
+	{ 0x140085, 0x12 },
+	{ 0x240080, 0xe0 },
+	{ 0x240081, 0x12 },
+	{ 0x240082, 0xe0 },
+	{ 0x240083, 0x12 },
+	{ 0x240084, 0xe0 },
+	{ 0x240085, 0x12 },
+	{ 0x400fd, 0xf },
+	{ 0x10011, 0x1 },
+	{ 0x10012, 0x1 },
+	{ 0x10013, 0x180 },
+	{ 0x10018, 0x1 },
+	{ 0x10002, 0x6209 },
+	{ 0x100b2, 0x1 },
+	{ 0x101b4, 0x1 },
+	{ 0x102b4, 0x1 },
+	{ 0x103b4, 0x1 },
+	{ 0x104b4, 0x1 },
+	{ 0x105b4, 0x1 },
+	{ 0x106b4, 0x1 },
+	{ 0x107b4, 0x1 },
+	{ 0x108b4, 0x1 },
+	{ 0x11011, 0x1 },
+	{ 0x11012, 0x1 },
+	{ 0x11013, 0x180 },
+	{ 0x11018, 0x1 },
+	{ 0x11002, 0x6209 },
+	{ 0x110b2, 0x1 },
+	{ 0x111b4, 0x1 },
+	{ 0x112b4, 0x1 },
+	{ 0x113b4, 0x1 },
+	{ 0x114b4, 0x1 },
+	{ 0x115b4, 0x1 },
+	{ 0x116b4, 0x1 },
+	{ 0x117b4, 0x1 },
+	{ 0x118b4, 0x1 },
+	{ 0x20089, 0x1 },
+	{ 0x20088, 0x19 },
+	{ 0xc0080, 0x2 },
+	{ 0xd0000, 0x1 }
+};
+
+struct dram_fsp_msg ddr_dram_fsp_msg[] = {
+	{
+		/* P0 1600mts 1D */
+		.drate = 1600,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = ddr_fsp0_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_cfg),
+	},
+	{
+		/* P1 400mts 1D */
+		.drate = 400,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = ddr_fsp1_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp1_cfg),
+	},
+	{
+		/* P2 100mts 1D */
+		.drate = 100,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = ddr_fsp2_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp2_cfg),
+	},
+	{
+		/* P0 1600mts 2D */
+		.drate = 1600,
+		.fw_type = FW_2D_IMAGE,
+		.fsp_cfg = ddr_fsp0_2d_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_2d_cfg),
+	},
+};
+
+/* ddr timing config params */
+struct dram_timing_info dram_timing = {
+	.ddrc_cfg = ddr_ddrc_cfg,
+	.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg),
+	.ddrphy_cfg = ddr_ddrphy_cfg,
+	.ddrphy_cfg_num = ARRAY_SIZE(ddr_ddrphy_cfg),
+	.fsp_msg = ddr_dram_fsp_msg,
+	.fsp_msg_num = ARRAY_SIZE(ddr_dram_fsp_msg),
+	.ddrphy_trained_csr = ddr_ddrphy_trained_csr,
+	.ddrphy_trained_csr_num = ARRAY_SIZE(ddr_ddrphy_trained_csr),
+	.ddrphy_pie = ddr_phy_pie,
+	.ddrphy_pie_num = ARRAY_SIZE(ddr_phy_pie),
+	.fsp_table = { 1600, 400, 100, },
+};
diff --git a/board/freescale/imx8mn_evk/spl.c b/board/freescale/imx8mn_evk/spl.c
index 6d5c7a5..03f2a56 100644
--- a/board/freescale/imx8mn_evk/spl.c
+++ b/board/freescale/imx8mn_evk/spl.c
@@ -25,6 +25,12 @@
 #include <dm/device.h>
 #include <dm/uclass-internal.h>
 #include <dm/device-internal.h>
+#include <power/pmic.h>
+#include <power/pca9450.h>
+#include <asm/mach-imx/gpio.h>
+#include <asm/mach-imx/mxc_i2c.h>
+#include <fsl_esdhc_imx.h>
+#include <mmc.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -52,6 +58,48 @@
 		printf("Failed to find clock node. Check device tree\n");
 }
 
+#if CONFIG_IS_ENABLED(DM_PMIC_PCA9450)
+int power_init_board(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = pmic_get("pca9450@25", &dev);
+	if (ret == -ENODEV) {
+		puts("No pca9450@25\n");
+		return 0;
+	}
+	if (ret != 0)
+		return ret;
+
+	/* BUCKxOUT_DVS0/1 control BUCK123 output */
+	pmic_reg_write(dev, PCA9450_BUCK123_DVS, 0x29);
+
+#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
+	/* Set VDD_SOC/VDD_DRAM to 0.8v for low drive mode */
+	pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS0, 0x10);
+#else
+	/* increase VDD_SOC/VDD_DRAM to typical value 0.95V before first DRAM access */
+	pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS0, 0x1C);
+#endif
+	/* Set DVS1 to 0.85v for suspend */
+	/* Enable DVS control through PMIC_STBY_REQ and set B1_ENMODE=1 (ON by PMIC_ON_REQ=H) */
+	pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS1, 0x14);
+	pmic_reg_write(dev, PCA9450_BUCK1CTRL, 0x59);
+
+	/* set VDD_SNVS_0V8 from default 0.85V */
+	pmic_reg_write(dev, PCA9450_LDO2CTRL, 0xC0);
+
+	/* enable LDO4 to 1.2v */
+	pmic_reg_write(dev, PCA9450_LDO4CTRL, 0x44);
+
+	/* set WDOG_B_CFG to cold reset */
+	pmic_reg_write(dev, PCA9450_RESET_CTRL, 0xA1);
+
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_SPL_LOAD_FIT
 int board_fit_config_name_match(const char *name)
 {
@@ -84,8 +132,6 @@
 
 	imx_iomux_v3_setup_multiple_pads(uart_pads, ARRAY_SIZE(uart_pads));
 
-	init_uart_clk(1);
-
 	return 0;
 }
 
diff --git a/board/freescale/imx8mp_evk/boot.cmd b/board/freescale/imx8mp_evk/boot.cmd
deleted file mode 100644
index 10bcced..0000000
--- a/board/freescale/imx8mp_evk/boot.cmd
+++ /dev/null
@@ -1,25 +0,0 @@
-setenv bootargs console=${console} root=${mmcroot};
-
-for boot_target in ${boot_targets};
-do
-        if test "${boot_target}" = "mmc1" ; then
-                if fatload mmc 1:${mmcpart} ${kernel_addr_r} ${image}; then
-                        if fatload mmc 1:${mmcpart} ${fdt_addr} ${fdt_file}; then
-                                echo Load image and .dtb from SD card(mmc1);
-                                booti ${kernel_addr_r} - ${fdt_addr};
-                                exit;
-                        fi
-                fi
-        fi
-
-        if test "${boot_target}" = "mmc2" ; then
-                if fatload mmc 2:${mmcpart} ${kernel_addr_r} ${image}; then
-                        if fatload mmc 2:${mmcpart} ${fdt_addr} ${fdt_file}; then
-                                echo Load image and .dtb from eMMC(mmc2);
-                                booti ${kernel_addr_r} - ${fdt_addr};
-                                exit;
-                        fi
-                fi
-        fi
-
-done
diff --git a/board/freescale/imx8mp_evk/imximage-8mp-lpddr4.cfg b/board/freescale/imx8mp_evk/imximage-8mp-lpddr4.cfg
new file mode 100644
index 0000000..b2920b4
--- /dev/null
+++ b/board/freescale/imx8mp_evk/imximage-8mp-lpddr4.cfg
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2021 NXP
+ */
+
+#define __ASSEMBLY__
+
+ROM_VERSION	v2
+BOOT_FROM	sd
+LOADER		mkimage.flash.mkimage	0x920000
diff --git a/board/freescale/imx8mp_evk/lpddr4_timing.c b/board/freescale/imx8mp_evk/lpddr4_timing.c
index 7658262..8c5306d 100644
--- a/board/freescale/imx8mp_evk/lpddr4_timing.c
+++ b/board/freescale/imx8mp_evk/lpddr4_timing.c
@@ -11,15 +11,51 @@
 	{ 0x3d400304, 0x1 },
 	{ 0x3d400030, 0x1 },
 	{ 0x3d400000, 0xa3080020 },
+#ifdef CONFIG_IMX8M_LPDDR4_FREQ0_2400MTS
+	{ 0x3d400020, 0x223 },
+	{ 0x3d400024, 0x124f800 },
+	{ 0x3d400064, 0x4900a8 },
+	{ 0x3d400070, 0x1027f90 },
+	{ 0x3d400074, 0x790 },
+	{ 0x3d4000d0, 0xc0030495 },
+	{ 0x3d4000d4, 0x770000 },
+	{ 0x3d4000dc, 0xc40024 },
+#else
 	{ 0x3d400020, 0x1323 },
 	{ 0x3d400024, 0x1e84800 },
-	{ 0x3d400064, 0x7a0118 },
+	{ 0x3d400064, 0x7a017c },
+#ifdef CONFIG_IMX8M_DRAM_INLINE_ECC
+	{ 0x3d400070, 0x1027f54 },
+#else
+	{ 0x3d400070, 0x1027f10 },
+#endif
+	{ 0x3d400074, 0x7b0 },
 	{ 0x3d4000d0, 0xc00307a3 },
 	{ 0x3d4000d4, 0xc50000 },
 	{ 0x3d4000dc, 0xf4003f },
+#endif
 	{ 0x3d4000e0, 0x330000 },
-	{ 0x3d4000e8, 0x460048 },
-	{ 0x3d4000ec, 0x150048 },
+	{ 0x3d4000e8, 0x660048 },
+	{ 0x3d4000ec, 0x160048 },
+#ifdef CONFIG_IMX8M_LPDDR4_FREQ0_2400MTS
+	{ 0x3d400100, 0x1618141a },
+	{ 0x3d400104, 0x504a6 },
+	{ 0x3d40010c, 0x909000 },
+	{ 0x3d400110, 0xb04060b },
+	{ 0x3d400114, 0x2030909 },
+	{ 0x3d400118, 0x1010006 },
+	{ 0x3d40011c, 0x301 },
+	{ 0x3d400130, 0x20500 },
+	{ 0x3d400134, 0xb100002 },
+	{ 0x3d400138, 0xad },
+	{ 0x3d400144, 0x78003c },
+	{ 0x3d400180, 0x2580012 },
+	{ 0x3d400184, 0x1e0493e },
+	{ 0x3d400188, 0x0 },
+	{ 0x3d400190, 0x4938208 },
+	{ 0x3d400194, 0x80303 },
+	{ 0x3d4001b4, 0x1308 },
+#else
 	{ 0x3d400100, 0x2028222a },
 	{ 0x3d400104, 0x807bf },
 	{ 0x3d40010c, 0xe0e000 },
@@ -29,7 +65,7 @@
 	{ 0x3d40011c, 0x501 },
 	{ 0x3d400130, 0x20800 },
 	{ 0x3d400134, 0xe100002 },
-	{ 0x3d400138, 0x120 },
+	{ 0x3d400138, 0x184 },
 	{ 0x3d400144, 0xc80064 },
 	{ 0x3d400180, 0x3e8001e },
 	{ 0x3d400184, 0x3207a12 },
@@ -37,6 +73,7 @@
 	{ 0x3d400190, 0x49f820e },
 	{ 0x3d400194, 0x80303 },
 	{ 0x3d4001b4, 0x1f0e },
+#endif
 	{ 0x3d4001a0, 0xe0400018 },
 	{ 0x3d4001a4, 0xdf00e4 },
 	{ 0x3d4001a8, 0x80000000 },
@@ -44,7 +81,8 @@
 	{ 0x3d4001c0, 0x1 },
 	{ 0x3d4001c4, 0x1 },
 	{ 0x3d4000f4, 0xc99 },
-	{ 0x3d400108, 0x9121c1c },
+#ifdef CONFIG_IMX8M_LPDDR4_FREQ0_2400MTS
+	{ 0x3d400108, 0x60c1514 },
 	{ 0x3d400200, 0x16 },
 	{ 0x3d40020c, 0x0 },
 	{ 0x3d400210, 0x1f1f },
@@ -52,26 +90,59 @@
 	{ 0x3d400214, 0x7070707 },
 	{ 0x3d400218, 0x68070707 },
 	{ 0x3d40021c, 0xf08 },
-	{ 0x3d400250, 0x00001705 },
+	{ 0x3d400250, 0x1f05 },
+	{ 0x3d400254, 0x1f },
+	{ 0x3d400264, 0x90003ff },
+	{ 0x3d40026c, 0x20003ff },
+	{ 0x3d400400, 0x111 },
+	{ 0x3d400408, 0x72ff },
+	{ 0x3d400494, 0x1000e00 },
+	{ 0x3d400498, 0x3ff0000 },
+	{ 0x3d40049c, 0x1000e00 },
+	{ 0x3d4004a0, 0x3ff0000 },
+	{ 0x3d402020, 0x21 },
+	{ 0x3d402024, 0x30d400 },
+	{ 0x3d402050, 0x20d000 },
+	{ 0x3d402064, 0xc001c },
+#else
+	{ 0x3d400108, 0x9121c1c },
+#ifdef CONFIG_IMX8M_DRAM_INLINE_ECC
+	{ 0x3d400200, 0x13 },
+	{ 0x3d40020c, 0x13131300 },
+	{ 0x3d400210, 0x1f1f },
+	{ 0x3d400204, 0x50505 },
+	{ 0x3d400214, 0x4040404 },
+	{ 0x3d400218, 0x68040404 },
+#else
+	{ 0x3d400200, 0x16 },
+	{ 0x3d40020c, 0x0 },
+	{ 0x3d400210, 0x1f1f },
+	{ 0x3d400204, 0x80808 },
+	{ 0x3d400214, 0x7070707 },
+	{ 0x3d400218, 0x68070707 },
+#endif
+	{ 0x3d40021c, 0xf08 },
+	{ 0x3d400250, 0x1705 },
 	{ 0x3d400254, 0x2c },
 	{ 0x3d40025c, 0x4000030 },
 	{ 0x3d400264, 0x900093e7 },
 	{ 0x3d40026c, 0x2005574 },
 	{ 0x3d400400, 0x111 },
-       { 0x3d400404, 0x72ff },
+	{ 0x3d400404, 0x72ff },
 	{ 0x3d400408, 0x72ff },
 	{ 0x3d400494, 0x2100e07 },
 	{ 0x3d400498, 0x620096 },
 	{ 0x3d40049c, 0x1100e07 },
 	{ 0x3d4004a0, 0xc8012c },
-	{ 0x3d402020, 0x21 },
-	{ 0x3d402024, 0x7d00 },
-	{ 0x3d402050, 0x20d040 },
-	{ 0x3d402064, 0xc001c },
+	{ 0x3d402020, 0x1021 },
+	{ 0x3d402024, 0x30d400 },
+	{ 0x3d402050, 0x20d000 },
+	{ 0x3d402064, 0xc0026 },
+#endif
 	{ 0x3d4020dc, 0x840000 },
-	{ 0x3d4020e0, 0x310000 },
-	{ 0x3d4020e8, 0x66004d },
-	{ 0x3d4020ec, 0x16004d },
+	{ 0x3d4020e0, 0x330000 },
+	{ 0x3d4020e8, 0x660048 },
+	{ 0x3d4020ec, 0x160048 },
 	{ 0x3d402100, 0xa040305 },
 	{ 0x3d402104, 0x30407 },
 	{ 0x3d402108, 0x203060b },
@@ -82,21 +153,28 @@
 	{ 0x3d40211c, 0x301 },
 	{ 0x3d402130, 0x20300 },
 	{ 0x3d402134, 0xa100002 },
-	{ 0x3d402138, 0x1d },
+	{ 0x3d402138, 0x27 },
 	{ 0x3d402144, 0x14000a },
 	{ 0x3d402180, 0x640004 },
 	{ 0x3d402190, 0x3818200 },
 	{ 0x3d402194, 0x80303 },
 	{ 0x3d4021b4, 0x100 },
 	{ 0x3d4020f4, 0xc99 },
+#ifdef CONFIG_IMX8M_LPDDR4_FREQ0_2400MTS
 	{ 0x3d403020, 0x21 },
-	{ 0x3d403024, 0x30d400 },
-	{ 0x3d403050, 0x20d040 },
+	{ 0x3d403024, 0xc3500 },
+	{ 0x3d403050, 0x20d000 },
 	{ 0x3d403064, 0x30007 },
+#else
+	{ 0x3d403020, 0x1021 },
+	{ 0x3d403024, 0xc3500 },
+	{ 0x3d403050, 0x20d000 },
+	{ 0x3d403064, 0x3000a },
+#endif
 	{ 0x3d4030dc, 0x840000 },
-	{ 0x3d4030e0, 0x310000 },
-	{ 0x3d4030e8, 0x66004d },
-	{ 0x3d4030ec, 0x16004d },
+	{ 0x3d4030e0, 0x330000 },
+	{ 0x3d4030e8, 0x660048 },
+	{ 0x3d4030ec, 0x160048 },
 	{ 0x3d403100, 0xa010102 },
 	{ 0x3d403104, 0x30404 },
 	{ 0x3d403108, 0x203060b },
@@ -107,12 +185,13 @@
 	{ 0x3d40311c, 0x301 },
 	{ 0x3d403130, 0x20300 },
 	{ 0x3d403134, 0xa100002 },
-	{ 0x3d403138, 0x8 },
+	{ 0x3d403138, 0xa },
 	{ 0x3d403144, 0x50003 },
 	{ 0x3d403180, 0x190004 },
 	{ 0x3d403190, 0x3818200 },
 	{ 0x3d403194, 0x80303 },
 	{ 0x3d4031b4, 0x100 },
+	{ 0x3d4030f4, 0xc99 },
 	{ 0x3d400028, 0x0 },
 };
 
@@ -184,7 +263,11 @@
 	{ 0x7055, 0x1ff },
 	{ 0x8055, 0x1ff },
 	{ 0x9055, 0x1ff },
+#ifdef CONFIG_IMX8M_LPDDR4_FREQ0_2400MTS
+	{ 0x200c5, 0xa },
+#else
 	{ 0x200c5, 0x18 },
+#endif
 	{ 0x1200c5, 0x7 },
 	{ 0x2200c5, 0x7 },
 	{ 0x2002e, 0x2 },
@@ -263,7 +346,11 @@
 	{ 0x20018, 0x3 },
 	{ 0x20075, 0x4 },
 	{ 0x20050, 0x0 },
+#ifdef CONFIG_IMX8M_LPDDR4_FREQ0_2400MTS
+	{ 0x20008, 0x258 },
+#else
 	{ 0x20008, 0x3e8 },
+#endif
 	{ 0x120008, 0x64 },
 	{ 0x220008, 0x19 },
 	{ 0x20088, 0x9 },
@@ -1050,6 +1137,38 @@
 
 /* P0 message block paremeter for training firmware */
 struct dram_cfg_param ddr_fsp0_cfg[] = {
+#ifdef CONFIG_IMX8M_LPDDR4_FREQ0_2400MTS
+	{ 0xd0000, 0x0 },
+	{ 0x54003, 0x960 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, 0x2228 },
+	{ 0x54006, 0x14 },
+	{ 0x54008, 0x131f },
+	{ 0x54009, 0xc8 },
+	{ 0x5400b, 0x2 },
+	{ 0x5400f, 0x100 },
+	{ 0x54012, 0x310 },
+	{ 0x54019, 0x24c4 },
+	{ 0x5401a, 0x33 },
+	{ 0x5401b, 0x4866 },
+	{ 0x5401c, 0x4800 },
+	{ 0x5401e, 0x16 },
+	{ 0x5401f, 0x24c4 },
+	{ 0x54020, 0x33 },
+	{ 0x54021, 0x4866 },
+	{ 0x54022, 0x4800 },
+	{ 0x54024, 0x16 },
+	{ 0x5402b, 0x1000 },
+	{ 0x5402c, 0x3 },
+	{ 0x54032, 0xc400 },
+	{ 0x54033, 0x3324 },
+	{ 0x54034, 0x6600 },
+	{ 0x54035, 0x48 },
+	{ 0x54036, 0x48 },
+	{ 0x54037, 0x1600 },
+	{ 0x54038, 0xc400 },
+	{ 0x54039, 0x3324 },
+#else
 	{ 0xd0000, 0x0 },
 	{ 0x54003, 0xfa0 },
 	{ 0x54004, 0x2 },
@@ -1080,6 +1199,7 @@
 	{ 0x54037, 0x1600 },
 	{ 0x54038, 0xf400 },
 	{ 0x54039, 0x333f },
+#endif
 	{ 0x5403a, 0x6600 },
 	{ 0x5403b, 0x48 },
 	{ 0x5403c, 0x48 },
@@ -1102,28 +1222,28 @@
 	{ 0x54012, 0x310 },
 	{ 0x54019, 0x84 },
 	{ 0x5401a, 0x33 },
-	{ 0x5401b, 0x4846 },
+	{ 0x5401b, 0x4866 },
 	{ 0x5401c, 0x4800 },
-	{ 0x5401e, 0x15 },
+	{ 0x5401e, 0x16 },
 	{ 0x5401f, 0x84 },
 	{ 0x54020, 0x33 },
-	{ 0x54021, 0x4846 },
+	{ 0x54021, 0x4866 },
 	{ 0x54022, 0x4800 },
-	{ 0x54024, 0x15 },
+	{ 0x54024, 0x16 },
 	{ 0x5402b, 0x1000 },
 	{ 0x5402c, 0x3 },
 	{ 0x54032, 0x8400 },
 	{ 0x54033, 0x3300 },
-	{ 0x54034, 0x4600 },
+	{ 0x54034, 0x6600 },
 	{ 0x54035, 0x48 },
 	{ 0x54036, 0x48 },
-	{ 0x54037, 0x1500 },
+	{ 0x54037, 0x1600 },
 	{ 0x54038, 0x8400 },
 	{ 0x54039, 0x3300 },
-	{ 0x5403a, 0x4600 },
+	{ 0x5403a, 0x6600 },
 	{ 0x5403b, 0x48 },
 	{ 0x5403c, 0x48 },
-	{ 0x5403d, 0x1500 },
+	{ 0x5403d, 0x1600 },
 	{ 0xd0000, 0x1 },
 };
 
@@ -1142,34 +1262,66 @@
 	{ 0x54012, 0x310 },
 	{ 0x54019, 0x84 },
 	{ 0x5401a, 0x33 },
-	{ 0x5401b, 0x4846 },
+	{ 0x5401b, 0x4866 },
 	{ 0x5401c, 0x4800 },
-	{ 0x5401e, 0x15 },
+	{ 0x5401e, 0x16 },
 	{ 0x5401f, 0x84 },
 	{ 0x54020, 0x33 },
-	{ 0x54021, 0x4846 },
+	{ 0x54021, 0x4866 },
 	{ 0x54022, 0x4800 },
-	{ 0x54024, 0x15 },
+	{ 0x54024, 0x16 },
 	{ 0x5402b, 0x1000 },
 	{ 0x5402c, 0x3 },
 	{ 0x54032, 0x8400 },
 	{ 0x54033, 0x3300 },
-	{ 0x54034, 0x4600 },
+	{ 0x54034, 0x6600 },
 	{ 0x54035, 0x48 },
 	{ 0x54036, 0x48 },
-	{ 0x54037, 0x1500 },
+	{ 0x54037, 0x1600 },
 	{ 0x54038, 0x8400 },
 	{ 0x54039, 0x3300 },
-	{ 0x5403a, 0x4600 },
+	{ 0x5403a, 0x6600 },
 	{ 0x5403b, 0x48 },
 	{ 0x5403c, 0x48 },
-	{ 0x5403d, 0x1500 },
+	{ 0x5403d, 0x1600 },
 	{ 0xd0000, 0x1 },
 };
 
 /* P0 2D message block paremeter for training firmware */
 struct dram_cfg_param ddr_fsp0_2d_cfg[] = {
 	{ 0xd0000, 0x0 },
+#ifdef CONFIG_IMX8M_LPDDR4_FREQ0_2400MTS
+	{ 0x54003, 0x960 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, 0x2228 },
+	{ 0x54006, 0x14 },
+	{ 0x54008, 0x61 },
+	{ 0x54009, 0xc8 },
+	{ 0x5400b, 0x2 },
+	{ 0x5400f, 0x100 },
+	{ 0x54010, 0x1f7f },
+	{ 0x54012, 0x310 },
+	{ 0x54019, 0x24c4 },
+	{ 0x5401a, 0x33 },
+	{ 0x5401b, 0x4866 },
+	{ 0x5401c, 0x4800 },
+	{ 0x5401e, 0x16 },
+	{ 0x5401f, 0x24c4 },
+	{ 0x54020, 0x33 },
+	{ 0x54021, 0x4866 },
+	{ 0x54022, 0x4800 },
+	{ 0x54024, 0x16 },
+	{ 0x5402b, 0x1000 },
+	{ 0x5402c, 0x3 },
+	{ 0x54032, 0xc400 },
+	{ 0x54033, 0x3324 },
+	{ 0x54034, 0x6600 },
+	{ 0x54035, 0x48 },
+	{ 0x54036, 0x48 },
+	{ 0x54037, 0x1600 },
+	{ 0x54038, 0xc400 },
+	{ 0x54039, 0x3324 },
+#else
 	{ 0x54003, 0xfa0 },
 	{ 0x54004, 0x2 },
 	{ 0x54005, 0x2228 },
@@ -1177,7 +1329,6 @@
 	{ 0x54008, 0x61 },
 	{ 0x54009, 0xc8 },
 	{ 0x5400b, 0x2 },
-	{ 0x5400d, 0x100 },
 	{ 0x5400f, 0x100 },
 	{ 0x54010, 0x1f7f },
 	{ 0x54012, 0x310 },
@@ -1201,6 +1352,7 @@
 	{ 0x54037, 0x1600 },
 	{ 0x54038, 0xf400 },
 	{ 0x54039, 0x333f },
+#endif
 	{ 0x5403a, 0x6600 },
 	{ 0x5403b, 0x48 },
 	{ 0x5403c, 0x48 },
@@ -1628,67 +1780,58 @@
 	{ 0x90155, 0x20 },
 	{ 0x90156, 0x2aa },
 	{ 0x90157, 0x9 },
-	{ 0x90158, 0x0 },
-	{ 0x90159, 0x400 },
-	{ 0x9015a, 0x10e },
-	{ 0x9015b, 0x8 },
-	{ 0x9015c, 0xe8 },
-	{ 0x9015d, 0x109 },
-	{ 0x9015e, 0x0 },
-	{ 0x9015f, 0x8140 },
-	{ 0x90160, 0x10c },
-	{ 0x90161, 0x10 },
-	{ 0x90162, 0x8138 },
-	{ 0x90163, 0x10c },
-	{ 0x90164, 0x8 },
-	{ 0x90165, 0x7c8 },
-	{ 0x90166, 0x101 },
-	{ 0x90167, 0x8 },
-	{ 0x90168, 0x448 },
+	{ 0x90158, 0x8 },
+	{ 0x90159, 0xe8 },
+	{ 0x9015a, 0x109 },
+	{ 0x9015b, 0x0 },
+	{ 0x9015c, 0x8140 },
+	{ 0x9015d, 0x10c },
+	{ 0x9015e, 0x10 },
+	{ 0x9015f, 0x8138 },
+	{ 0x90160, 0x104 },
+	{ 0x90161, 0x8 },
+	{ 0x90162, 0x448 },
+	{ 0x90163, 0x109 },
+	{ 0x90164, 0xf },
+	{ 0x90165, 0x7c0 },
+	{ 0x90166, 0x109 },
+	{ 0x90167, 0x0 },
+	{ 0x90168, 0xe8 },
 	{ 0x90169, 0x109 },
-	{ 0x9016a, 0xf },
-	{ 0x9016b, 0x7c0 },
+	{ 0x9016a, 0x47 },
+	{ 0x9016b, 0x630 },
 	{ 0x9016c, 0x109 },
-	{ 0x9016d, 0x0 },
-	{ 0x9016e, 0xe8 },
+	{ 0x9016d, 0x8 },
+	{ 0x9016e, 0x618 },
 	{ 0x9016f, 0x109 },
-	{ 0x90170, 0x47 },
-	{ 0x90171, 0x630 },
+	{ 0x90170, 0x8 },
+	{ 0x90171, 0xe0 },
 	{ 0x90172, 0x109 },
-	{ 0x90173, 0x8 },
-	{ 0x90174, 0x618 },
+	{ 0x90173, 0x0 },
+	{ 0x90174, 0x7c8 },
 	{ 0x90175, 0x109 },
 	{ 0x90176, 0x8 },
-	{ 0x90177, 0xe0 },
-	{ 0x90178, 0x109 },
+	{ 0x90177, 0x8140 },
+	{ 0x90178, 0x10c },
 	{ 0x90179, 0x0 },
-	{ 0x9017a, 0x7c8 },
+	{ 0x9017a, 0x478 },
 	{ 0x9017b, 0x109 },
-	{ 0x9017c, 0x8 },
-	{ 0x9017d, 0x8140 },
-	{ 0x9017e, 0x10c },
-	{ 0x9017f, 0x0 },
-	{ 0x90180, 0x478 },
-	{ 0x90181, 0x109 },
-	{ 0x90182, 0x0 },
-	{ 0x90183, 0x1 },
-	{ 0x90184, 0x8 },
-	{ 0x90185, 0x8 },
-	{ 0x90186, 0x4 },
-	{ 0x90187, 0x8 },
-	{ 0x90188, 0x8 },
-	{ 0x90189, 0x7c8 },
-	{ 0x9018a, 0x101 },
-	{ 0x90006, 0x0 },
-	{ 0x90007, 0x0 },
-	{ 0x90008, 0x8 },
+	{ 0x9017c, 0x0 },
+	{ 0x9017d, 0x1 },
+	{ 0x9017e, 0x8 },
+	{ 0x9017f, 0x8 },
+	{ 0x90180, 0x4 },
+	{ 0x90181, 0x0 },
+	{ 0x90006, 0x8 },
+	{ 0x90007, 0x7c8 },
+	{ 0x90008, 0x109 },
 	{ 0x90009, 0x0 },
-	{ 0x9000a, 0x0 },
-	{ 0x9000b, 0x0 },
+	{ 0x9000a, 0x400 },
+	{ 0x9000b, 0x106 },
 	{ 0xd00e7, 0x400 },
 	{ 0x90017, 0x0 },
 	{ 0x9001f, 0x29 },
-	{ 0x90026, 0x6a },
+	{ 0x90026, 0x68 },
 	{ 0x400d0, 0x0 },
 	{ 0x400d1, 0x101 },
 	{ 0x400d2, 0x105 },
@@ -1698,9 +1841,16 @@
 	{ 0x400d6, 0x20a },
 	{ 0x400d7, 0x20b },
 	{ 0x2003a, 0x2 },
+#ifdef CONFIG_IMX8M_LPDDR4_FREQ0_2400MTS
+	{ 0x2000b, 0x4b },
+	{ 0x2000c, 0x96 },
+	{ 0x2000d, 0x5dc },
+#else
+	{ 0x200be, 0x3 },
 	{ 0x2000b, 0x7d },
 	{ 0x2000c, 0xfa },
 	{ 0x2000d, 0x9c4 },
+#endif
 	{ 0x2000e, 0x2c },
 	{ 0x12000b, 0xc },
 	{ 0x12000c, 0x19 },
@@ -1720,6 +1870,12 @@
 	{ 0x90013, 0x6152 },
 	{ 0x20010, 0x5a },
 	{ 0x20011, 0x3 },
+#ifdef CONFIG_IMX8M_LPDDR4_FREQ0_2400MTS
+	{ 0x120010, 0x5a },
+	{ 0x120011, 0x3 },
+	{ 0x220010, 0x5a },
+	{ 0x220011, 0x3 },
+#endif
 	{ 0x40080, 0xe0 },
 	{ 0x40081, 0x12 },
 	{ 0x40082, 0xe0 },
@@ -1803,8 +1959,13 @@
 
 struct dram_fsp_msg ddr_dram_fsp_msg[] = {
 	{
+#ifdef CONFIG_IMX8M_LPDDR4_FREQ0_2400MTS
+		/* P0 2400mts 1D */
+		.drate = 2400,
+#else
 		/* P0 4000mts 1D */
 		.drate = 4000,
+#endif
 		.fw_type = FW_1D_IMAGE,
 		.fsp_cfg = ddr_fsp0_cfg,
 		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_cfg),
@@ -1824,8 +1985,13 @@
 		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp2_cfg),
 	},
 	{
+#ifdef CONFIG_IMX8M_LPDDR4_FREQ0_2400MTS
+		/* P0 2400mts 2D */
+		.drate = 2400,
+#else
 		/* P0 4000mts 2D */
 		.drate = 4000,
+#endif
 		.fw_type = FW_2D_IMAGE,
 		.fsp_cfg = ddr_fsp0_2d_cfg,
 		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_2d_cfg),
@@ -1844,5 +2010,39 @@
 	.ddrphy_trained_csr_num = ARRAY_SIZE(ddr_ddrphy_trained_csr),
 	.ddrphy_pie = ddr_phy_pie,
 	.ddrphy_pie_num = ARRAY_SIZE(ddr_phy_pie),
+#ifdef CONFIG_IMX8M_LPDDR4_FREQ0_2400MTS
+	.fsp_table = { 2400, 400, 100, },
+#else
 	.fsp_table = { 4000, 400, 100, },
+#endif
 };
+
+#ifndef CONFIG_IMX8M_LPDDR4_FREQ0_2400MTS
+#ifdef CONFIG_IMX8M_DRAM_INLINE_ECC
+void board_dram_ecc_scrub(void)
+{
+	ddrc_inline_ecc_scrub(0x0, 0x3ffffff);
+	ddrc_inline_ecc_scrub(0x20000000, 0x23ffffff);
+	ddrc_inline_ecc_scrub(0x40000000, 0x43ffffff);
+	ddrc_inline_ecc_scrub(0x4000000, 0x7ffffff);
+	ddrc_inline_ecc_scrub(0x24000000, 0x27ffffff);
+	ddrc_inline_ecc_scrub(0x44000000, 0x47ffffff);
+	ddrc_inline_ecc_scrub(0x8000000, 0xbffffff);
+	ddrc_inline_ecc_scrub(0x28000000, 0x2bffffff);
+	ddrc_inline_ecc_scrub(0x48000000, 0x4bffffff);
+	ddrc_inline_ecc_scrub(0xc000000, 0xfffffff);
+	ddrc_inline_ecc_scrub(0x2c000000, 0x2fffffff);
+	ddrc_inline_ecc_scrub(0x4c000000, 0x4fffffff);
+	ddrc_inline_ecc_scrub(0x10000000, 0x13ffffff);
+	ddrc_inline_ecc_scrub(0x30000000, 0x33ffffff);
+	ddrc_inline_ecc_scrub(0x50000000, 0x53ffffff);
+	ddrc_inline_ecc_scrub(0x14000000, 0x17ffffff);
+	ddrc_inline_ecc_scrub(0x34000000, 0x37ffffff);
+	ddrc_inline_ecc_scrub(0x54000000, 0x57ffffff);
+	ddrc_inline_ecc_scrub(0x18000000, 0x1bffffff);
+	ddrc_inline_ecc_scrub(0x38000000, 0x3bffffff);
+	ddrc_inline_ecc_scrub(0x58000000, 0x5bffffff);
+	ddrc_inline_ecc_scrub_end(0x0, 0x5fffffff);
+}
+#endif
+#endif
diff --git a/board/freescale/imx8mp_evk/spl.c b/board/freescale/imx8mp_evk/spl.c
index ebfd94d..a7564e9 100644
--- a/board/freescale/imx8mp_evk/spl.c
+++ b/board/freescale/imx8mp_evk/spl.c
@@ -5,30 +5,21 @@
  */
 
 #include <common.h>
-#include <command.h>
-#include <cpu_func.h>
 #include <hang.h>
-#include <image.h>
 #include <init.h>
 #include <log.h>
 #include <spl.h>
 #include <asm/global_data.h>
-#include <asm/io.h>
-#include <errno.h>
-#include <asm/io.h>
-#include <asm/mach-imx/iomux-v3.h>
+#include <asm/arch/clock.h>
 #include <asm/arch/imx8mp_pins.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/mach-imx/boot_mode.h>
-#include <power/pmic.h>
-
-#include <power/pca9450.h>
-#include <asm/arch/clock.h>
 #include <asm/mach-imx/gpio.h>
+#include <asm/mach-imx/iomux-v3.h>
 #include <asm/mach-imx/mxc_i2c.h>
-#include <fsl_esdhc.h>
-#include <mmc.h>
 #include <asm/arch/ddr.h>
+#include <power/pmic.h>
+#include <power/pca9450.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -44,6 +35,16 @@
 
 void spl_board_init(void)
 {
+	/*
+	 * Set GIC clock to 500Mhz for OD VDD_SOC. Kernel driver does
+	 * not allow to change it. Should set the clock after PMIC
+	 * setting done. Default is 400Mhz (system_pll1_800m with div = 2)
+	 * set by ROM for ND VDD_SOC
+	 */
+	clock_enable(CCGR_GIC, 0);
+	clock_set_target_val(GIC_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(5));
+	clock_enable(CCGR_GIC, 1);
+
 	puts("Normal Boot\n");
 }
 
@@ -69,7 +70,7 @@
 	struct pmic *p;
 	int ret;
 
-	ret = power_pca9450_init(I2C_PMIC);
+	ret = power_pca9450_init(I2C_PMIC, 0x25);
 	if (ret)
 		printf("power init failed");
 	p = pmic_get("PCA9450");
@@ -84,10 +85,19 @@
 	 * Enable DVS control through PMIC_STBY_REQ and
 	 * set B1_ENMODE=1 (ON by PMIC_ON_REQ=H)
 	 */
+#ifdef CONFIG_IMX8M_VDD_SOC_850MV
+	/* set DVS0 to 0.85v for special case*/
+	pmic_reg_write(p, PCA9450_BUCK1OUT_DVS0, 0x14);
+#else
 	pmic_reg_write(p, PCA9450_BUCK1OUT_DVS0, 0x1C);
+#endif
 	pmic_reg_write(p, PCA9450_BUCK1OUT_DVS1, 0x14);
 	pmic_reg_write(p, PCA9450_BUCK1CTRL, 0x59);
 
+	/* Kernel uses OD/OD freq for SOC */
+	/* To avoid timing risk from SOC to ARM,increase VDD_ARM to OD voltage 0.95v */
+	pmic_reg_write(p, PCA9450_BUCK2OUT_DVS0, 0x1C);
+
 	/* set WDOG_B_CFG to cold reset */
 	pmic_reg_write(p, PCA9450_RESET_CTRL, 0xA1);
 
diff --git a/board/freescale/imx8mq_evk/spl.c b/board/freescale/imx8mq_evk/spl.c
index 8275358..e8e0efe 100644
--- a/board/freescale/imx8mq_evk/spl.c
+++ b/board/freescale/imx8mq_evk/spl.c
@@ -36,7 +36,7 @@
 static void spl_dram_init(void)
 {
 	/* ddr init */
-	if ((get_cpu_rev() & 0xfff) == CHIP_REV_2_1)
+	if (soc_rev() >= CHIP_REV_2_1)
 		ddr_init(&dram_timing);
 	else
 		ddr_init(&dram_timing_b0);
diff --git a/board/freescale/imx8qm_mek/imx8qm_mek.c b/board/freescale/imx8qm_mek/imx8qm_mek.c
index c677220..682099a 100644
--- a/board/freescale/imx8qm_mek/imx8qm_mek.c
+++ b/board/freescale/imx8qm_mek/imx8qm_mek.c
@@ -105,7 +105,7 @@
 /*
  * Board specific reset that is system reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	/* TODO */
 }
diff --git a/board/freescale/imx8qxp_mek/imx8qxp_mek.c b/board/freescale/imx8qxp_mek/imx8qxp_mek.c
index 7179823..21cfa14 100644
--- a/board/freescale/imx8qxp_mek/imx8qxp_mek.c
+++ b/board/freescale/imx8qxp_mek/imx8qxp_mek.c
@@ -129,7 +129,7 @@
 /*
  * Board specific reset that is system reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	/* TODO */
 }
diff --git a/board/freescale/imxrt1020-evk/imxrt1020-evk.c b/board/freescale/imxrt1020-evk/imxrt1020-evk.c
index 35241ac..479e66b 100644
--- a/board/freescale/imxrt1020-evk/imxrt1020-evk.c
+++ b/board/freescale/imxrt1020-evk/imxrt1020-evk.c
@@ -60,8 +60,8 @@
 
 void spl_board_init(void)
 {
-	spl_dram_init();
 	preloader_console_init();
+	spl_dram_init();
 	arch_cpu_init(); /* to configure mpu for sdram rw permissions */
 }
 
diff --git a/board/freescale/imxrt1050-evk/imxrt1050-evk.c b/board/freescale/imxrt1050-evk/imxrt1050-evk.c
index b8d852f..eb49239 100644
--- a/board/freescale/imxrt1050-evk/imxrt1050-evk.c
+++ b/board/freescale/imxrt1050-evk/imxrt1050-evk.c
@@ -60,8 +60,8 @@
 
 void spl_board_init(void)
 {
-	spl_dram_init();
 	preloader_console_init();
+	spl_dram_init();
 	arch_cpu_init(); /* to configure mpu for sdram rw permissions */
 }
 
diff --git a/board/freescale/mx28evk/MAINTAINERS b/board/freescale/mx28evk/MAINTAINERS
index a98a705..597118d 100644
--- a/board/freescale/mx28evk/MAINTAINERS
+++ b/board/freescale/mx28evk/MAINTAINERS
@@ -1,5 +1,5 @@
 MX28EVK BOARD
-M:	Fabio Estevam <fabio.estevam@nxp.com>
+M:	Fabio Estevam <festevam@gmail.com>
 S:	Maintained
 F:	board/freescale/mx28evk/
 F:	include/configs/mx28evk.h
diff --git a/board/freescale/mx6memcal/spl.c b/board/freescale/mx6memcal/spl.c
index c82b532..61d0ca3 100644
--- a/board/freescale/mx6memcal/spl.c
+++ b/board/freescale/mx6memcal/spl.c
@@ -425,7 +425,7 @@
 		    is_cpu_type(MXC_CPU_MX6SL)) {
 			printf("cpu type 0x%x doesn't support 64-bit bus\n",
 			       get_cpu_type());
-			reset_cpu(0);
+			reset_cpu();
 		}
 	}
 #ifdef CONFIG_MX6SL
diff --git a/board/freescale/mx6sabreauto/MAINTAINERS b/board/freescale/mx6sabreauto/MAINTAINERS
index a89f05a..6179d67 100644
--- a/board/freescale/mx6sabreauto/MAINTAINERS
+++ b/board/freescale/mx6sabreauto/MAINTAINERS
@@ -1,5 +1,5 @@
 MX6SABREAUTO BOARD
-M:	Fabio Estevam <fabio.estevam@nxp.com>
+M:	Fabio Estevam <festevam@gmail.com>
 M:	Peng Fan <peng.fan@nxp.com>
 S:	Maintained
 F:	board/freescale/mx6sabreauto/
diff --git a/board/freescale/mx6sabresd/MAINTAINERS b/board/freescale/mx6sabresd/MAINTAINERS
index 9575261..5e256ef 100644
--- a/board/freescale/mx6sabresd/MAINTAINERS
+++ b/board/freescale/mx6sabresd/MAINTAINERS
@@ -1,5 +1,5 @@
 MX6SABRESD BOARD
-M:	Fabio Estevam <fabio.estevam@nxp.com>
+M:	Fabio Estevam <festevam@gmail.com>
 S:	Maintained
 F:	board/freescale/mx6sabresd/
 F:	include/configs/mx6sabresd.h
diff --git a/board/freescale/mx6slevk/MAINTAINERS b/board/freescale/mx6slevk/MAINTAINERS
index be2f3d5..ae87fe4 100644
--- a/board/freescale/mx6slevk/MAINTAINERS
+++ b/board/freescale/mx6slevk/MAINTAINERS
@@ -1,5 +1,5 @@
 MX6SLEVK BOARD
-M:	Fabio Estevam <fabio.estevam@nxp.com>
+M:	Fabio Estevam <festevam@gmail.com>
 M:	Peng Fan <peng.fan@nxp.com>
 S:	Maintained
 F:	board/freescale/mx6slevk/
diff --git a/board/freescale/mx6sxsabreauto/MAINTAINERS b/board/freescale/mx6sxsabreauto/MAINTAINERS
index 6f2ff44..692bbd9 100644
--- a/board/freescale/mx6sxsabreauto/MAINTAINERS
+++ b/board/freescale/mx6sxsabreauto/MAINTAINERS
@@ -1,5 +1,5 @@
 MX6SXSABREAUTO BOARD
-M:	Fabio Estevam <fabio.estevam@nxp.com>
+M:	Fabio Estevam <festevam@gmail.com>
 S:	Maintained
 F:	board/freescale/mx6sxsabreauto/
 F:	include/configs/mx6sxsabreauto.h
diff --git a/board/freescale/mx6sxsabresd/MAINTAINERS b/board/freescale/mx6sxsabresd/MAINTAINERS
index a56d252..b3c8b56 100644
--- a/board/freescale/mx6sxsabresd/MAINTAINERS
+++ b/board/freescale/mx6sxsabresd/MAINTAINERS
@@ -1,5 +1,5 @@
 MX6SXSABRESD BOARD
-M:	Fabio Estevam <fabio.estevam@nxp.com>
+M:	Fabio Estevam <festevam@gmail.com>
 S:	Maintained
 F:	board/freescale/mx6sxsabresd/
 F:	include/configs/mx6sxsabresd.h
diff --git a/board/gateworks/gw_ventana/MAINTAINERS b/board/gateworks/gw_ventana/MAINTAINERS
index 265ddac..1619d23 100644
--- a/board/gateworks/gw_ventana/MAINTAINERS
+++ b/board/gateworks/gw_ventana/MAINTAINERS
@@ -6,3 +6,51 @@
 F:	configs/gwventana_nand_defconfig
 F:	configs/gwventana_emmc_defconfig
 F:	configs/gwventana_gw5904_defconfig
+F:	arch/arm/dts/imx6dl-gw51xx.dts
+F:	arch/arm/dts/imx6dl-gw52xx.dts
+F:	arch/arm/dts/imx6dl-gw53xx.dts
+F:	arch/arm/dts/imx6dl-gw54xx.dts
+F:	arch/arm/dts/imx6dl-gw551x.dts
+F:	arch/arm/dts/imx6dl-gw552x.dts
+F:	arch/arm/dts/imx6dl-gw553x.dts
+F:	arch/arm/dts/imx6dl-gw560x.dts
+F:	arch/arm/dts/imx6dl-gw5903.dts
+F:	arch/arm/dts/imx6dl-gw5904.dts
+F:	arch/arm/dts/imx6dl-gw5905.dts
+F:	arch/arm/dts/imx6dl-gw5907.dts
+F:	arch/arm/dts/imx6dl-gw5910.dts
+F:	arch/arm/dts/imx6dl-gw5912.dts
+F:	arch/arm/dts/imx6dl-gw5913.dts
+F:	arch/arm/dts/imx6qdl-gw51xx.dtsi
+F:	arch/arm/dts/imx6qdl-gw52xx.dtsi
+F:	arch/arm/dts/imx6qdl-gw53xx.dtsi
+F:	arch/arm/dts/imx6qdl-gw54xx.dtsi
+F:	arch/arm/dts/imx6qdl-gw551x.dtsi
+F:	arch/arm/dts/imx6qdl-gw552x.dtsi
+F:	arch/arm/dts/imx6qdl-gw553x.dtsi
+F:	arch/arm/dts/imx6qdl-gw560x.dtsi
+F:	arch/arm/dts/imx6qdl-gw5903.dtsi
+F:	arch/arm/dts/imx6qdl-gw5904.dtsi
+F:	arch/arm/dts/imx6qdl-gw5905.dtsi
+F:	arch/arm/dts/imx6qdl-gw5907.dtsi
+F:	arch/arm/dts/imx6qdl-gw5910.dtsi
+F:	arch/arm/dts/imx6qdl-gw5912.dtsi
+F:	arch/arm/dts/imx6qdl-gw5913.dtsi
+F:	arch/arm/dts/imx6q-gw51xx.dts
+F:	arch/arm/dts/imx6q-gw52xx.dts
+F:	arch/arm/dts/imx6q-gw53xx.dts
+F:	arch/arm/dts/imx6q-gw5400-a.dts
+F:	arch/arm/dts/imx6q-gw54xx.dts
+F:	arch/arm/dts/imx6q-gw551x.dts
+F:	arch/arm/dts/imx6q-gw552x.dts
+F:	arch/arm/dts/imx6q-gw553x.dts
+F:	arch/arm/dts/imx6q-gw560x.dts
+F:	arch/arm/dts/imx6q-gw5901.dts
+F:	arch/arm/dts/imx6q-gw5902.dts
+F:	arch/arm/dts/imx6q-gw5903.dts
+F:	arch/arm/dts/imx6q-gw5904.dts
+F:	arch/arm/dts/imx6q-gw5905.dts
+F:	arch/arm/dts/imx6q-gw5907.dts
+F:	arch/arm/dts/imx6q-gw5910.dts
+F:	arch/arm/dts/imx6q-gw5912.dts
+F:	arch/arm/dts/imx6q-gw5913.dts
diff --git a/board/gateworks/gw_ventana/common.c b/board/gateworks/gw_ventana/common.c
index 14f45bf..4627a15 100644
--- a/board/gateworks/gw_ventana/common.c
+++ b/board/gateworks/gw_ventana/common.c
@@ -970,7 +970,6 @@
 		.rs485en = IMX_GPIO_NR(3, 24),
 		.dioi2c_en = IMX_GPIO_NR(4,  5),
 		.pcie_sson = IMX_GPIO_NR(1, 20),
-		.otgpwr_en = IMX_GPIO_NR(3, 22),
 		.mmc_cd = IMX_GPIO_NR(7, 0),
 	},
 
@@ -990,7 +989,6 @@
 		.gps_shdn = IMX_GPIO_NR(1, 2),
 		.vidin_en = IMX_GPIO_NR(5, 20),
 		.wdis = IMX_GPIO_NR(7, 12),
-		.otgpwr_en = IMX_GPIO_NR(3, 22),
 		.nand = true,
 	},
 
@@ -1014,7 +1012,6 @@
 		.wdis = IMX_GPIO_NR(7, 12),
 		.msata_en = GP_MSATA_SEL,
 		.rs232_en = GP_RS232_EN,
-		.otgpwr_en = IMX_GPIO_NR(3, 22),
 		.vsel_pin = IMX_GPIO_NR(6, 14),
 		.mmc_cd = IMX_GPIO_NR(7, 0),
 		.nand = true,
@@ -1039,7 +1036,6 @@
 		.wdis = IMX_GPIO_NR(7, 12),
 		.msata_en = GP_MSATA_SEL,
 		.rs232_en = GP_RS232_EN,
-		.otgpwr_en = IMX_GPIO_NR(3, 22),
 		.vsel_pin = IMX_GPIO_NR(6, 14),
 		.mmc_cd = IMX_GPIO_NR(7, 0),
 		.nand = true,
@@ -1066,7 +1062,6 @@
 		.wdis = IMX_GPIO_NR(5, 17),
 		.msata_en = GP_MSATA_SEL,
 		.rs232_en = GP_RS232_EN,
-		.otgpwr_en = IMX_GPIO_NR(3, 22),
 		.vsel_pin = IMX_GPIO_NR(6, 14),
 		.mmc_cd = IMX_GPIO_NR(7, 0),
 		.nand = true,
@@ -1117,7 +1112,6 @@
 		.pcie_rst = IMX_GPIO_NR(1, 0),
 		.vidin_en = IMX_GPIO_NR(5, 20),
 		.wdis = IMX_GPIO_NR(7, 12),
-		.otgpwr_en = IMX_GPIO_NR(3, 22),
 		.vsel_pin = IMX_GPIO_NR(6, 14),
 		.mmc_cd = IMX_GPIO_NR(7, 0),
 		.nand = true,
@@ -1140,7 +1134,6 @@
 		.rs232_en = GP_RS232_EN,
 		.vidin_en = IMX_GPIO_NR(3, 31),
 		.wdis = IMX_GPIO_NR(7, 12),
-		.otgpwr_en = IMX_GPIO_NR(4, 15),
 		.mmc_cd = IMX_GPIO_NR(7, 0),
 	},
 
@@ -1166,7 +1159,6 @@
 		},
 		.pcie_rst = IMX_GPIO_NR(1, 0),
 		.rs232_en = GP_RS232_EN,
-		.otgpwr_en = IMX_GPIO_NR(3, 23),
 		.nand = true,
 	},
 
@@ -1179,7 +1171,6 @@
 		.leds = {
 			IMX_GPIO_NR(6, 14),
 		},
-		.otgpwr_en = IMX_GPIO_NR(4, 15),
 		.mmc_cd = IMX_GPIO_NR(6, 11),
 	},
 
@@ -1197,7 +1188,6 @@
 		.pcie_rst = IMX_GPIO_NR(1, 0),
 		.mezz_pwren = IMX_GPIO_NR(2, 19),
 		.mezz_irq = IMX_GPIO_NR(2, 18),
-		.otgpwr_en = IMX_GPIO_NR(3, 22),
 	},
 
 	/* GW5905 */
@@ -1279,7 +1269,6 @@
 		.pcie_rst = IMX_GPIO_NR(1, 0),
 		.mezz_pwren = IMX_GPIO_NR(2, 19),
 		.mezz_irq = IMX_GPIO_NR(2, 18),
-		.otgpwr_en = IMX_GPIO_NR(3, 22),
 	},
 };
 
@@ -1382,12 +1371,6 @@
 		gpio_direction_output(gpio_cfg[board].wdis, 1);
 	}
 
-	/* OTG power off */
-	if (gpio_cfg[board].otgpwr_en) {
-		gpio_request(gpio_cfg[board].otgpwr_en, "usbotg_pwr");
-		gpio_direction_output(gpio_cfg[board].otgpwr_en, 0);
-	}
-
 	/* sense vselect pin to see if we support uhs-i */
 	if (gpio_cfg[board].vsel_pin) {
 		gpio_request(gpio_cfg[board].vsel_pin, "sd3_vselect");
diff --git a/board/gateworks/gw_ventana/common.h b/board/gateworks/gw_ventana/common.h
index 5cec01c..d73850c 100644
--- a/board/gateworks/gw_ventana/common.h
+++ b/board/gateworks/gw_ventana/common.h
@@ -75,7 +75,6 @@
 	int wdis;
 	int msata_en;
 	int rs232_en;
-	int otgpwr_en;
 	int vsel_pin;
 	int mmc_cd;
 	/* various features */
diff --git a/board/gateworks/gw_ventana/gsc.c b/board/gateworks/gw_ventana/gsc.c
index bcb6bca..ffed6b5 100644
--- a/board/gateworks/gw_ventana/gsc.c
+++ b/board/gateworks/gw_ventana/gsc.c
@@ -14,6 +14,8 @@
 #include <i2c.h>
 #include <linux/ctype.h>
 
+#include <asm/arch/sys_proto.h>
+
 #include "ventana_eeprom.h"
 #include "gsc.h"
 
@@ -179,6 +181,92 @@
 	return 1;
 }
 
+/* determine BOM revision from model */
+int get_bom_rev(const char *str)
+{
+	int  rev_bom = 0;
+	int i;
+
+	for (i = strlen(str) - 1; i > 0; i--) {
+		if (str[i] == '-')
+			break;
+		if (str[i] >= '1' && str[i] <= '9') {
+			rev_bom = str[i] - '0';
+			break;
+		}
+	}
+	return rev_bom;
+}
+
+/* determine PCB revision from model */
+char get_pcb_rev(const char *str)
+{
+	char rev_pcb = 'A';
+	int i;
+
+	for (i = strlen(str) - 1; i > 0; i--) {
+		if (str[i] == '-')
+			break;
+		if (str[i] >= 'A') {
+			rev_pcb = str[i];
+			break;
+		}
+	}
+	return rev_pcb;
+}
+
+/*
+ * get dt name based on model and detail level:
+ */
+const char *gsc_get_dtb_name(int level, char *buf, int sz)
+{
+	const char *model = (const char *)ventana_info.model;
+	const char *pre = is_mx6dq() ? "imx6q-" : "imx6dl-";
+	int modelno, rev_pcb, rev_bom;
+
+	/* a few board models are dt equivalents to other models */
+	if (strncasecmp(model, "gw5906", 6) == 0)
+		model = "gw552x-d";
+	else if (strncasecmp(model, "gw5908", 6) == 0)
+		model = "gw53xx-f";
+	else if (strncasecmp(model, "gw5905", 6) == 0)
+		model = "gw5904-a";
+
+	modelno = ((model[2] - '0') * 1000)
+		  + ((model[3] - '0') * 100)
+		  + ((model[4] - '0') * 10)
+		  + (model[5] - '0');
+	rev_pcb = tolower(get_pcb_rev(model));
+	rev_bom = get_bom_rev(model);
+
+	/* compare model/rev/bom in order of most specific to least */
+	snprintf(buf, sz, "%s%04d", pre, modelno);
+	switch (level) {
+	case 0: /* full model first (ie gw5400-a1) */
+		if (rev_bom) {
+			snprintf(buf, sz, "%sgw%04d-%c%d", pre, modelno, rev_pcb, rev_bom);
+			break;
+		}
+		fallthrough;
+	case 1: /* don't care about bom rev (ie gw5400-a) */
+		snprintf(buf, sz, "%sgw%04d-%c", pre, modelno, rev_pcb);
+		break;
+	case 2: /* don't care about the pcb rev (ie gw5400) */
+		snprintf(buf, sz, "%sgw%04d", pre, modelno);
+		break;
+	case 3: /* look for generic model (ie gw540x) */
+		snprintf(buf, sz, "%sgw%03dx", pre, modelno / 10);
+		break;
+	case 4: /* look for more generic model (ie gw54xx) */
+		snprintf(buf, sz, "%sgw%02dxx", pre, modelno / 100);
+		break;
+	default: /* give up */
+		return NULL;
+	}
+
+	return buf;
+}
+
 #if defined(CONFIG_CMD_GSC) && !defined(CONFIG_SPL_BUILD)
 static int do_gsc_sleep(struct cmd_tbl *cmdtp, int flag, int argc,
 			char *const argv[])
diff --git a/board/gateworks/gw_ventana/gsc.h b/board/gateworks/gw_ventana/gsc.h
index 6dcaafa..29d375b 100644
--- a/board/gateworks/gw_ventana/gsc.h
+++ b/board/gateworks/gw_ventana/gsc.h
@@ -67,5 +67,6 @@
 int gsc_i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len);
 int gsc_info(int verbose);
 int gsc_boot_wd_disable(void);
+const char *gsc_get_dtb_name(int level, char *buf, int sz);
 #endif
 
diff --git a/board/gateworks/gw_ventana/gw_ventana.c b/board/gateworks/gw_ventana/gw_ventana.c
index 71de80c..5237f2d 100644
--- a/board/gateworks/gw_ventana/gw_ventana.c
+++ b/board/gateworks/gw_ventana/gw_ventana.c
@@ -19,17 +19,14 @@
 #include <asm/gpio.h>
 #include <asm/mach-imx/boot_mode.h>
 #include <asm/mach-imx/sata.h>
-#include <asm/mach-imx/spi.h>
 #include <asm/mach-imx/video.h>
 #include <asm/io.h>
 #include <asm/setup.h>
 #include <dm.h>
-#include <dm/platform_data/serial_mxc.h>
 #include <env.h>
 #include <hwconfig.h>
 #include <i2c.h>
 #include <fdt_support.h>
-#include <fsl_esdhc_imx.h>
 #include <jffs2/load_kernel.h>
 #include <linux/ctype.h>
 #include <miiphy.h>
@@ -43,7 +40,6 @@
 #include <power/pfuze100_pmic.h>
 #include <fdt_support.h>
 #include <jffs2/load_kernel.h>
-#include <spi_flash.h>
 
 #include "gsc.h"
 #include "common.h"
@@ -56,7 +52,6 @@
  * read it once.
  */
 struct ventana_board_info ventana_info;
-
 static int board_type;
 
 /* ENET */
@@ -83,54 +78,6 @@
 	IOMUX_PADS(PAD_ENET_TXD0__GPIO1_IO30 | DIO_PAD_CFG),
 };
 
-#ifdef CONFIG_CMD_NAND
-static iomux_v3_cfg_t const nfc_pads[] = {
-	IOMUX_PADS(PAD_NANDF_CLE__NAND_CLE     | MUX_PAD_CTRL(NO_PAD_CTRL)),
-	IOMUX_PADS(PAD_NANDF_ALE__NAND_ALE     | MUX_PAD_CTRL(NO_PAD_CTRL)),
-	IOMUX_PADS(PAD_NANDF_WP_B__NAND_WP_B   | MUX_PAD_CTRL(NO_PAD_CTRL)),
-	IOMUX_PADS(PAD_NANDF_RB0__NAND_READY_B | MUX_PAD_CTRL(NO_PAD_CTRL)),
-	IOMUX_PADS(PAD_NANDF_CS0__NAND_CE0_B   | MUX_PAD_CTRL(NO_PAD_CTRL)),
-	IOMUX_PADS(PAD_SD4_CMD__NAND_RE_B      | MUX_PAD_CTRL(NO_PAD_CTRL)),
-	IOMUX_PADS(PAD_SD4_CLK__NAND_WE_B      | MUX_PAD_CTRL(NO_PAD_CTRL)),
-	IOMUX_PADS(PAD_NANDF_D0__NAND_DATA00   | MUX_PAD_CTRL(NO_PAD_CTRL)),
-	IOMUX_PADS(PAD_NANDF_D1__NAND_DATA01   | MUX_PAD_CTRL(NO_PAD_CTRL)),
-	IOMUX_PADS(PAD_NANDF_D2__NAND_DATA02   | MUX_PAD_CTRL(NO_PAD_CTRL)),
-	IOMUX_PADS(PAD_NANDF_D3__NAND_DATA03   | MUX_PAD_CTRL(NO_PAD_CTRL)),
-	IOMUX_PADS(PAD_NANDF_D4__NAND_DATA04   | MUX_PAD_CTRL(NO_PAD_CTRL)),
-	IOMUX_PADS(PAD_NANDF_D5__NAND_DATA05   | MUX_PAD_CTRL(NO_PAD_CTRL)),
-	IOMUX_PADS(PAD_NANDF_D6__NAND_DATA06   | MUX_PAD_CTRL(NO_PAD_CTRL)),
-	IOMUX_PADS(PAD_NANDF_D7__NAND_DATA07   | MUX_PAD_CTRL(NO_PAD_CTRL)),
-};
-
-static void setup_gpmi_nand(void)
-{
-	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
-
-	/* config gpmi nand iomux */
-	SETUP_IOMUX_PADS(nfc_pads);
-
-	/* config gpmi and bch clock to 100 MHz */
-	clrsetbits_le32(&mxc_ccm->cs2cdr,
-			MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK |
-			MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK |
-			MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK,
-			MXC_CCM_CS2CDR_ENFC_CLK_PODF(0) |
-			MXC_CCM_CS2CDR_ENFC_CLK_PRED(3) |
-			MXC_CCM_CS2CDR_ENFC_CLK_SEL(3));
-
-	/* enable gpmi and bch clock gating */
-	setbits_le32(&mxc_ccm->CCGR4,
-		     MXC_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB_MASK |
-		     MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH_MASK |
-		     MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK |
-		     MXC_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB_MASK |
-		     MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_OFFSET);
-
-	/* enable apbh clock gating */
-	setbits_le32(&mxc_ccm->CCGR0, MXC_CCM_CCGR0_APBHDMA_MASK);
-}
-#endif
-
 static void setup_iomux_enet(int gpio)
 {
 	SETUP_IOMUX_PADS(enet_pads);
@@ -144,18 +91,14 @@
 }
 
 #ifdef CONFIG_USB_EHCI_MX6
-static iomux_v3_cfg_t const usb_pads[] = {
-	IOMUX_PADS(PAD_GPIO_1__USB_OTG_ID   | DIO_PAD_CFG),
-	IOMUX_PADS(PAD_KEY_COL4__USB_OTG_OC | DIO_PAD_CFG),
-	/* OTG PWR */
-	IOMUX_PADS(PAD_EIM_D22__GPIO3_IO22  | DIO_PAD_CFG),
-};
-
+/* toggle USB_HUB_RST# for boards that have it; it is not defined in dt */
 int board_ehci_hcd_init(int port)
 {
 	int gpio;
 
-	SETUP_IOMUX_PADS(usb_pads);
+	/* USB HUB is always on P1 */
+	if (port == 0)
+		return 0;
 
 	/* Reset USB HUB */
 	switch (board_type) {
@@ -180,40 +123,8 @@
 
 	return 0;
 }
-
-int board_ehci_power(int port, int on)
-{
-	/* enable OTG VBUS */
-	if (!port && board_type < GW_UNKNOWN) {
-		if (gpio_cfg[board_type].otgpwr_en)
-			gpio_set_value(gpio_cfg[board_type].otgpwr_en, on);
-	}
-	return 0;
-}
 #endif /* CONFIG_USB_EHCI_MX6 */
 
-#ifdef CONFIG_MXC_SPI
-iomux_v3_cfg_t const ecspi1_pads[] = {
-	/* SS1 */
-	IOMUX_PADS(PAD_EIM_D19__GPIO3_IO19  | MUX_PAD_CTRL(SPI_PAD_CTRL)),
-	IOMUX_PADS(PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL)),
-	IOMUX_PADS(PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL)),
-	IOMUX_PADS(PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL)),
-};
-
-int board_spi_cs_gpio(unsigned bus, unsigned cs)
-{
-	return (bus == 0 && cs == 0) ? (IMX_GPIO_NR(3, 19)) : -1;
-}
-
-static void setup_spi(void)
-{
-	gpio_request(IMX_GPIO_NR(3, 19), "spi_cs");
-	gpio_direction_output(IMX_GPIO_NR(3, 19), 1);
-	SETUP_IOMUX_PADS(ecspi1_pads);
-}
-#endif
-
 /* configure eth0 PHY board-specific LED behavior */
 int board_phy_config(struct phy_device *phydev)
 {
@@ -629,8 +540,6 @@
 
 int board_early_init_f(void)
 {
-	setup_iomux_uart();
-
 #if defined(CONFIG_VIDEO_IPUV3)
 	setup_display();
 #endif
@@ -658,25 +567,33 @@
 	setup_ventana_i2c(0);
 	board_type = read_eeprom(CONFIG_I2C_GSC, &ventana_info);
 
-#ifdef CONFIG_CMD_NAND
-	if (gpio_cfg[board_type].nand)
-		setup_gpmi_nand();
-#endif
-#ifdef CONFIG_MXC_SPI
-	setup_spi();
-#endif
 	setup_ventana_i2c(1);
 	setup_ventana_i2c(2);
 
-#ifdef CONFIG_SATA
-	setup_sata();
-#endif
-
 	setup_iomux_gpio(board_type, &ventana_info);
 
 	return 0;
 }
 
+int board_fit_config_name_match(const char *name)
+{
+	static char init;
+	const char *dtb;
+	char buf[32];
+	int i = 0;
+
+	do {
+		dtb = gsc_get_dtb_name(i++, buf, sizeof(buf));
+		if (dtb && !strcmp(dtb, name)) {
+			if (!init++)
+				printf("DTB:   %s\n", name);
+			return 0;
+		}
+	} while (dtb);
+
+	return -1;
+}
+
 #if defined(CONFIG_DISPLAY_BOARDINFO_LATE)
 /*
  * called during late init (after relocation and after board_init())
@@ -1371,12 +1288,3 @@
 	return 0;
 }
 #endif /* CONFIG_OF_BOARD_SETUP */
-
-static struct mxc_serial_plat ventana_mxc_serial_plat = {
-	.reg = (struct mxc_uart *)UART2_BASE,
-};
-
-U_BOOT_DRVINFO(ventana_serial) = {
-	.name   = "serial_mxc",
-	.plat = &ventana_mxc_serial_plat,
-};
diff --git a/board/gateworks/gw_ventana/gw_ventana_spl.c b/board/gateworks/gw_ventana/gw_ventana_spl.c
index e0e4bac..a4f6439 100644
--- a/board/gateworks/gw_ventana/gw_ventana_spl.c
+++ b/board/gateworks/gw_ventana/gw_ventana_spl.c
@@ -731,8 +731,16 @@
 /* its our chance to print info about boot device */
 void spl_board_init(void)
 {
+	u32 boot_device;
+	int board_type;
+
 	/* determine boot device from SRC_SBMR1 (BOOT_CFG[4:1]) or SRC_GPR9 */
-	u32 boot_device = spl_boot_device();
+	boot_device = spl_boot_device();
+
+	/* read eeprom again now that we have gd */
+	board_type = read_eeprom(CONFIG_I2C_GSC, &ventana_info);
+	if (board_type == GW_UNKNOWN)
+		hang();
 
 	switch (boot_device) {
 	case BOOT_DEVICE_MMC1:
diff --git a/board/gateworks/venice/gsc.c b/board/gateworks/venice/gsc.c
index ad3f8d9..d2490e6 100644
--- a/board/gateworks/venice/gsc.c
+++ b/board/gateworks/venice/gsc.c
@@ -125,29 +125,18 @@
 
 static struct udevice *gsc_get_dev(int busno, int slave)
 {
-	struct udevice *dev;
+	static const char * const i2c[] = { "i2c@30a20000", "i2c@30a30000" };
+	struct udevice *dev, *bus;
 	int ret;
 
-#if (IS_ENABLED(CONFIG_SPL_BUILD))
-	ret = i2c_get_chip_for_busnum(busno + 1, slave, 1, &dev);
+	ret = uclass_get_device_by_name(UCLASS_I2C, i2c[busno - 1], &bus);
+	if (ret) {
+		printf("GSC     : failed I2C%d probe: %d\n", busno, ret);
+		return NULL;
+	}
+	ret = dm_i2c_probe(bus, slave, 0, &dev);
 	if (ret)
 		return NULL;
-#else
-	struct udevice *bus;
-
-	busno--;
-
-	ret = uclass_get_device_by_seq(UCLASS_I2C, busno, &bus);
-	if (ret) {
-		printf("i2c%d: no bus %d\n", busno + 1, ret);
-		return NULL;
-	}
-	ret = i2c_get_chip(bus, slave, 1, &dev);
-	if (ret) {
-		printf("i2c%d@0x%02x: no chip %d\n", busno + 1, slave, ret);
-		return NULL;
-	}
-#endif
 
 	return dev;
 }
diff --git a/board/gdsys/a38x/controlcenterdc.c b/board/gdsys/a38x/controlcenterdc.c
index 4f1dc3b..dc424f2 100644
--- a/board/gdsys/a38x/controlcenterdc.c
+++ b/board/gdsys/a38x/controlcenterdc.c
@@ -288,8 +288,8 @@
 	ccdc_eth_init();
 #endif
 	ret = get_tpm(&tpm);
-	if (ret || tpm_init(tpm) || tpm_startup(tpm, TPM_ST_CLEAR) ||
-	    tpm_continue_self_test(tpm)) {
+	if (ret || tpm_init(tpm) || tpm1_startup(tpm, TPM_ST_CLEAR) ||
+	    tpm1_continue_self_test(tpm)) {
 		return 1;
 	}
 
diff --git a/board/gdsys/a38x/hre.c b/board/gdsys/a38x/hre.c
index 699241b..de5411a 100644
--- a/board/gdsys/a38x/hre.c
+++ b/board/gdsys/a38x/hre.c
@@ -107,8 +107,8 @@
 	uint8_t *ptr;
 	uint16_t v16;
 
-	err = tpm_get_capability(tpm, TPM_CAP_NV_INDEX, index,
-				 info, sizeof(info));
+	err = tpm1_get_capability(tpm, TPM_CAP_NV_INDEX, index, info,
+				  sizeof(info));
 	if (err) {
 		printf("tpm_get_capability(CAP_NV_INDEX, %08x) failed: %u\n",
 		       index, err);
@@ -150,8 +150,8 @@
 	unsigned int i;
 
 	/* fetch list of already loaded keys in the TPM */
-	err = tpm_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
-				 sizeof(buf));
+	err = tpm1_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
+				  sizeof(buf));
 	if (err)
 		return -1;
 	key_count = get_unaligned_be16(buf);
@@ -162,8 +162,8 @@
 	/* now search a(/ the) key which we can access with the given auth */
 	for (i = 0; i < key_count; ++i) {
 		buf_len = sizeof(buf);
-		err = tpm_get_pub_key_oiap(tpm, key_handles[i], auth, buf,
-					   &buf_len);
+		err = tpm1_get_pub_key_oiap(tpm, key_handles[i], auth, buf,
+					    &buf_len);
 		if (err && err != TPM_AUTHFAIL)
 			return -1;
 		if (err)
@@ -192,8 +192,8 @@
 	if (get_tpm_nv_size(tpm, NV_COMMON_DATA_INDEX, &size) ||
 	    size < NV_COMMON_DATA_MIN_SIZE)
 		return 1;
-	err = tpm_nv_read_value(tpm, NV_COMMON_DATA_INDEX,
-				buf, min(sizeof(buf), size));
+	err = tpm1_nv_read_value(tpm, NV_COMMON_DATA_INDEX, buf,
+				 min(sizeof(buf), size));
 	if (err) {
 		printf("tpm_nv_read_value() failed: %u\n", err);
 		return 1;
@@ -270,8 +270,8 @@
 	if (mode & HREG_RD) {
 		if (!result->valid) {
 			if (IS_PCR_HREG(spec)) {
-				hre_tpm_err = tpm_pcr_read(tpm, HREG_IDX(spec),
-					result->digest, 20);
+				hre_tpm_err = tpm1_pcr_read(tpm, HREG_IDX(spec),
+							    result->digest, 20);
 				result->valid = (hre_tpm_err == TPM_SUCCESS);
 			} else if (IS_FIX_HREG(spec)) {
 				switch (HREG_IDX(spec)) {
@@ -357,8 +357,8 @@
 		return -1;
 	if (find_key(tpm, src_reg->digest, dst_reg->digest, &parent_handle))
 		return -1;
-	hre_tpm_err = tpm_load_key2_oiap(tpm, parent_handle, key, key_size,
-					 src_reg->digest, &key_handle);
+	hre_tpm_err = tpm1_load_key2_oiap(tpm, parent_handle, key, key_size,
+					  src_reg->digest, &key_handle);
 	if (hre_tpm_err) {
 		hre_err = HRE_E_TPM_FAILURE;
 		return -1;
@@ -474,8 +474,8 @@
 	}
 
 	if (dst_reg && dst_modified && IS_PCR_HREG(dst_spec)) {
-		hre_tpm_err = tpm_extend(tpm, HREG_IDX(dst_spec),
-					 dst_reg->digest, dst_reg->digest);
+		hre_tpm_err = tpm1_extend(tpm, HREG_IDX(dst_spec),
+					  dst_reg->digest, dst_reg->digest);
 		if (hre_tpm_err) {
 			hre_err = HRE_E_TPM_FAILURE;
 			return NULL;
diff --git a/board/gdsys/a38x/keyprogram.c b/board/gdsys/a38x/keyprogram.c
index 853981a..7020fae 100644
--- a/board/gdsys/a38x/keyprogram.c
+++ b/board/gdsys/a38x/keyprogram.c
@@ -23,15 +23,15 @@
 	uint i;
 
 	/* fetch list of already loaded keys in the TPM */
-	err = tpm_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
-				 sizeof(buf));
+	err = tpm1_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
+				  sizeof(buf));
 	if (err)
 		return -1;
 	key_count = get_unaligned_be16(buf);
 	ptr = buf + 2;
 	for (i = 0; i < key_count; ++i, ptr += 4) {
-		err = tpm_flush_specific(tpm, get_unaligned_be32(ptr),
-					 TPM_RT_KEY);
+		err = tpm1_flush_specific(tpm, get_unaligned_be32(ptr),
+					  TPM_RT_KEY);
 		if (err && err != TPM_KEY_OWNER_CONTROL)
 			return err;
 	}
diff --git a/board/gdsys/mpc8308/gazerbeam.c b/board/gdsys/mpc8308/gazerbeam.c
index 4e974c5..3d4a7e5 100644
--- a/board/gdsys/mpc8308/gazerbeam.c
+++ b/board/gdsys/mpc8308/gazerbeam.c
@@ -145,8 +145,8 @@
 	env_set_ulong("fpga_hw_rev", fpga_hw_rev);
 
 	ret = get_tpm(&tpm);
-	if (ret || tpm_init(tpm) || tpm_startup(tpm, TPM_ST_CLEAR) ||
-	    tpm_continue_self_test(tpm)) {
+	if (ret || tpm_init(tpm) || tpm1_startup(tpm, TPM_ST_CLEAR) ||
+	    tpm1_continue_self_test(tpm)) {
 		printf("TPM init failed\n");
 	}
 
diff --git a/board/gdsys/p1022/controlcenterd-id.c b/board/gdsys/p1022/controlcenterd-id.c
index 1b5aa90..87b346a 100644
--- a/board/gdsys/p1022/controlcenterd-id.c
+++ b/board/gdsys/p1022/controlcenterd-id.c
@@ -273,8 +273,8 @@
 	uint8_t *ptr;
 	uint16_t v16;
 
-	err = tpm_get_capability(tpm, TPM_CAP_NV_INDEX, index,
-				 info, sizeof(info));
+	err = tpm1_get_capability(tpm, TPM_CAP_NV_INDEX, index, info,
+				  sizeof(info));
 	if (err) {
 		printf("tpm_get_capability(CAP_NV_INDEX, %08x) failed: %u\n",
 		       index, err);
@@ -315,8 +315,8 @@
 	unsigned int i;
 
 	/* fetch list of already loaded keys in the TPM */
-	err = tpm_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
-				 sizeof(buf));
+	err = tpm1_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
+				  sizeof(buf));
 	if (err)
 		return -1;
 	key_count = get_unaligned_be16(buf);
@@ -327,8 +327,8 @@
 	/* now search a(/ the) key which we can access with the given auth */
 	for (i = 0; i < key_count; ++i) {
 		buf_len = sizeof(buf);
-		err = tpm_get_pub_key_oiap(tpm, key_handles[i], auth, buf,
-					   &buf_len);
+		err = tpm1_get_pub_key_oiap(tpm, key_handles[i], auth, buf,
+					    &buf_len);
 		if (err && err != TPM_AUTHFAIL)
 			return -1;
 		if (err)
@@ -356,8 +356,8 @@
 	if (get_tpm_nv_size(tpm, NV_COMMON_DATA_INDEX, &size) ||
 	    size < NV_COMMON_DATA_MIN_SIZE)
 		return 1;
-	err = tpm_nv_read_value(tpm, NV_COMMON_DATA_INDEX,
-				buf, min(sizeof(buf), size));
+	err = tpm1_nv_read_value(tpm, NV_COMMON_DATA_INDEX, buf,
+				 min(sizeof(buf), size));
 	if (err) {
 		printf("tpm_nv_read_value() failed: %u\n", err);
 		return 1;
@@ -508,8 +508,8 @@
 	if (mode & HREG_RD) {
 		if (!result->valid) {
 			if (IS_PCR_HREG(spec)) {
-				hre_tpm_err = tpm_pcr_read(tpm, HREG_IDX(spec),
-					result->digest, 20);
+				hre_tpm_err = tpm1_pcr_read(tpm, HREG_IDX(spec),
+							    result->digest, 20);
 				result->valid = (hre_tpm_err == TPM_SUCCESS);
 			} else if (IS_FIX_HREG(spec)) {
 				switch (HREG_IDX(spec)) {
@@ -601,8 +601,8 @@
 		return -1;
 	if (find_key(tpm, src_reg->digest, dst_reg->digest, &parent_handle))
 		return -1;
-	hre_tpm_err = tpm_load_key2_oiap(tpm, parent_handle, key, key_size,
-					 src_reg->digest, &key_handle);
+	hre_tpm_err = tpm1_load_key2_oiap(tpm, parent_handle, key, key_size,
+					  src_reg->digest, &key_handle);
 	if (hre_tpm_err) {
 		hre_err = HRE_E_TPM_FAILURE;
 		return -1;
@@ -718,8 +718,8 @@
 	}
 
 	if (dst_reg && dst_modified && IS_PCR_HREG(dst_spec)) {
-		hre_tpm_err = tpm_extend(tpm, HREG_IDX(dst_spec),
-					 dst_reg->digest, dst_reg->digest);
+		hre_tpm_err = tpm1_extend(tpm, HREG_IDX(dst_spec),
+					  dst_reg->digest, dst_reg->digest);
 		if (hre_tpm_err) {
 			hre_err = HRE_E_TPM_FAILURE;
 			return NULL;
@@ -964,10 +964,10 @@
 
 	puts("CCDM S1: start actions\n");
 #ifndef CCDM_SECOND_STAGE
-	if (tpm_continue_self_test(tpm))
+	if (tpm1_continue_self_test(tpm))
 		goto failure;
 #else
-	tpm_continue_self_test(tpm);
+	tpm1_continue_self_test(tpm);
 #endif
 	mdelay(37);
 
@@ -1003,7 +1003,7 @@
 
 	puts("CCDM S1\n");
 	ret = get_tpm(&tpm);
-	if (ret || tpm_init(tpm) || tpm_startup(tpm, TPM_ST_CLEAR))
+	if (ret || tpm_init(tpm) || tpm1_startup(tpm, TPM_ST_CLEAR))
 		return 1;
 	ret = first_stage_actions(tpm);
 #ifndef CCDM_SECOND_STAGE
@@ -1061,7 +1061,7 @@
 	ret = get_tpm(&tpm);
 	if (ret || tpm_init(tpm))
 		return 1;
-	err = tpm_startup(tpm, TPM_ST_CLEAR);
+	err = tpm1_startup(tpm, TPM_ST_CLEAR);
 	if (err != TPM_INVALID_POSTINIT)
 		did_first_stage_run = false;
 
diff --git a/board/ge/b1x5v2/spl.c b/board/ge/b1x5v2/spl.c
index 2e6f905..52c80f7 100644
--- a/board/ge/b1x5v2/spl.c
+++ b/board/ge/b1x5v2/spl.c
@@ -436,7 +436,7 @@
 	return 1024;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
diff --git a/board/google/chromebook_coral/coral.c b/board/google/chromebook_coral/coral.c
index f9fb3f1..3f9235c 100644
--- a/board/google/chromebook_coral/coral.c
+++ b/board/google/chromebook_coral/coral.c
@@ -3,9 +3,12 @@
  * Copyright 2019 Google LLC
  */
 
+#define LOG_CATEGORY	UCLASS_SYSINFO
+
 #include <common.h>
 #include <bloblist.h>
 #include <command.h>
+#include <cros_ec.h>
 #include <dm.h>
 #include <log.h>
 #include <sysinfo.h>
@@ -15,6 +18,7 @@
 #include <asm/intel_gnvs.h>
 #include <asm/intel_pinctrl.h>
 #include <dm/acpi.h>
+#include <linux/delay.h>
 #include "variant_gpio.h"
 
 struct cros_gpio_info {
@@ -29,10 +33,125 @@
 	return 0;
 }
 
-/* This function is needed if CONFIG_CMDLINE is not enabled */
-int board_run_command(const char *cmdline)
+static int get_memconfig(struct udevice *dev)
 {
-	printf("No command line\n");
+	struct gpio_desc gpios[4];
+	int cfg;
+	int ret;
+
+	ret = gpio_request_list_by_name(dev, "memconfig-gpios", gpios,
+					ARRAY_SIZE(gpios),
+					GPIOD_IS_IN | GPIOD_PULL_UP);
+	if (ret < 0) {
+		log_debug("Cannot get GPIO list '%s' (%d)\n", dev->name, ret);
+		return ret;
+	}
+
+	/* Give the lines time to settle */
+	udelay(10);
+
+	ret = dm_gpio_get_values_as_int(gpios, ARRAY_SIZE(gpios));
+	if (ret < 0)
+		return log_msg_ret("get", ret);
+	cfg = ret;
+
+	ret = gpio_free_list(dev, gpios, ARRAY_SIZE(gpios));
+	if (ret)
+		return log_msg_ret("free", ret);
+
+	return cfg;
+}
+
+/**
+ * get_skuconfig() - Get the SKU number either from pins or the EC
+ *
+ * Two options are supported:
+ *     skuconfig-gpios - two pins in the device tree (tried first)
+ *     EC              - reading from the EC (backup)
+ *
+ * @dev: sysinfo device to use
+ * @return SKU ID, or -ve error if not found
+ */
+static int get_skuconfig(struct udevice *dev)
+{
+	struct gpio_desc gpios[2];
+	int cfg;
+	int ret;
+
+	ret = gpio_request_list_by_name(dev, "skuconfig-gpios", gpios,
+					ARRAY_SIZE(gpios),
+					GPIOD_IS_IN);
+	if (ret != ARRAY_SIZE(gpios)) {
+		struct udevice *cros_ec;
+
+		log_debug("Cannot get GPIO list '%s' (%d)\n", dev->name, ret);
+
+		/* Try the EC */
+		ret = uclass_first_device_err(UCLASS_CROS_EC, &cros_ec);
+		if (ret < 0) {
+			log_err("Cannot find EC for SKU details\n");
+			return log_msg_ret("sku", ret);
+		}
+		ret = cros_ec_get_sku_id(cros_ec);
+		if (ret < 0) {
+			log_err("Cannot read SKU details\n");
+			return log_msg_ret("sku", ret);
+		}
+
+		return ret;
+	}
+
+	ret = dm_gpio_get_values_as_int_base3(gpios, ARRAY_SIZE(gpios));
+	if (ret < 0)
+		return log_msg_ret("get", ret);
+	cfg = ret;
+
+	ret = gpio_free_list(dev, gpios, ARRAY_SIZE(gpios));
+	if (ret)
+		return log_msg_ret("free", ret);
+
+	return cfg;
+}
+
+static int coral_get_str(struct udevice *dev, int id, size_t size, char *val)
+{
+	int ret;
+
+	if (IS_ENABLED(CONFIG_SPL_BUILD))
+		return -ENOSYS;
+
+	switch (id) {
+	case SYSINFO_ID_SMBIOS_SYSTEM_VERSION:
+	case SYSINFO_ID_SMBIOS_BASEBOARD_VERSION: {
+		ret = get_skuconfig(dev);
+
+		if (ret < 0)
+			return ret;
+		if (size < 15)
+			return -ENOSPC;
+		sprintf(val, "rev%d", ret);
+		break;
+	}
+	case SYSINFO_ID_BOARD_MODEL: {
+		int mem_config, sku_config;
+		const char *model;
+
+		ret = get_memconfig(dev);
+		if (ret < 0)
+			log_warning("Unable to read memconfig (err=%d)\n", ret);
+		mem_config = ret;
+		ret = get_skuconfig(dev);
+		if (ret < 0)
+			log_warning("Unable to read skuconfig (err=%d)\n", ret);
+		sku_config = ret;
+		model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+		snprintf(val, size, "%s (memconfig %d, SKU %d)", model,
+			 mem_config, sku_config);
+		break;
+	}
+	default:
+		return -ENOENT;
+	}
 
 	return 0;
 }
@@ -45,12 +164,15 @@
 	int ret;
 
 	ret = gpio_request_by_name((struct udevice *)dev, prop, 0, &desc, 0);
-	if (ret == -ENOTBLK)
+	if (ret == -ENOTBLK) {
 		info->gpio_num = CROS_GPIO_VIRTUAL;
-	else if (ret)
+		log_debug("GPIO '%s' is virtual\n", prop);
+	} else if (ret) {
 		return log_msg_ret("gpio", ret);
-	else
+	} else {
 		info->gpio_num = desc.offset;
+		dm_gpio_free((struct udevice *)dev, &desc);
+	}
 	info->linux_name = dev_read_string(desc.dev, "linux-name");
 	if (!info->linux_name)
 		return log_msg_ret("linux-name", -ENOENT);
@@ -63,6 +185,8 @@
 	}
 	info->flags = desc.flags & GPIOD_ACTIVE_LOW ? CROS_GPIO_ACTIVE_LOW :
 		CROS_GPIO_ACTIVE_HIGH;
+	if (!ret)
+		dm_gpio_free(desc.dev, &desc);
 
 	return 0;
 }
@@ -81,11 +205,11 @@
 	ret = chromeos_get_gpio(dev, "write-protect-gpios", CROS_GPIO_WP,
 				&info[1]);
 	if (ret)
-		return log_msg_ret("rec", ret);
+		return log_msg_ret("wp", ret);
 	ret = chromeos_get_gpio(dev, "phase-enforce-gpios", CROS_GPIO_PE,
 				&info[2]);
 	if (ret)
-		return log_msg_ret("rec", ret);
+		return log_msg_ret("phase", ret);
 	acpigen_write_scope(ctx, "\\");
 	acpigen_write_name(ctx, "OIPG");
 	acpigen_write_package(ctx, count);
@@ -145,6 +269,7 @@
 };
 
 struct sysinfo_ops coral_sysinfo_ops = {
+	.get_str	= coral_get_str,
 };
 
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
diff --git a/board/google/chromebook_coral/variant_gpio.h b/board/google/chromebook_coral/variant_gpio.h
index f516d88..403e241 100644
--- a/board/google/chromebook_coral/variant_gpio.h
+++ b/board/google/chromebook_coral/variant_gpio.h
@@ -34,12 +34,6 @@
 /* Determine if board is in final shipping mode. */
 #define GPIO_SHIP_MODE	GPIO_10
 
-/*  Memory SKU GPIOs. */
-#define MEM_CONFIG3	GPIO_45
-#define MEM_CONFIG2	GPIO_38
-#define MEM_CONFIG1	GPIO_102
-#define MEM_CONFIG0	GPIO_101
-
 /* DMIC_CONFIG_PIN: High for 1-DMIC and low for 4-DMIC's */
 #define DMIC_CONFIG_PIN	GPIO_17
 
diff --git a/board/highbank/highbank.c b/board/highbank/highbank.c
index a790d45..906bd9b 100644
--- a/board/highbank/highbank.c
+++ b/board/highbank/highbank.c
@@ -128,7 +128,7 @@
 	return (midr & 0xfff0) == 0xc090;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	writel(HB_PWR_HARD_RESET, HB_SREG_A9_PWR_REQ);
 	if (is_highbank())
diff --git a/board/hisilicon/hikey/hikey.c b/board/hisilicon/hikey/hikey.c
index afe324c..c9a2d60 100644
--- a/board/hisilicon/hikey/hikey.c
+++ b/board/hisilicon/hikey/hikey.c
@@ -486,7 +486,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	writel(0x48698284, &ao_sc->stat0);
 	wfi();
diff --git a/board/hisilicon/hikey960/hikey960.c b/board/hisilicon/hikey960/hikey960.c
index 62073aa..f41fabb 100644
--- a/board/hisilicon/hikey960/hikey960.c
+++ b/board/hisilicon/hikey960/hikey960.c
@@ -185,7 +185,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	psci_system_reset();
 }
diff --git a/board/hisilicon/poplar/poplar.c b/board/hisilicon/poplar/poplar.c
index fda9a34..6cc79d9 100644
--- a/board/hisilicon/poplar/poplar.c
+++ b/board/hisilicon/poplar/poplar.c
@@ -60,7 +60,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	psci_system_reset();
 }
diff --git a/board/hoperun/hihope-rzg2/Kconfig b/board/hoperun/hihope-rzg2/Kconfig
new file mode 100644
index 0000000..ee422ba
--- /dev/null
+++ b/board/hoperun/hihope-rzg2/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_HIHOPE_RZG2
+
+config SYS_SOC
+	default "rmobile"
+
+config SYS_BOARD
+	default "hihope-rzg2"
+
+config SYS_VENDOR
+	default "hoperun"
+
+config SYS_CONFIG_NAME
+	default "hihope-rzg2"
+
+endif
diff --git a/board/hoperun/hihope-rzg2/MAINTAINERS b/board/hoperun/hihope-rzg2/MAINTAINERS
new file mode 100644
index 0000000..e3702fd
--- /dev/null
+++ b/board/hoperun/hihope-rzg2/MAINTAINERS
@@ -0,0 +1,6 @@
+HIHOPE_RZG2 BOARD
+M:	Biju Das <biju.das.jz@bp.renesas.com>
+S:	Maintained
+F:	board/hoperun/hihope-rzg2/
+F:	include/configs/hihope-rzg2.h
+F:	configs/hihope_rzg2_defconfig
diff --git a/board/hoperun/hihope-rzg2/Makefile b/board/hoperun/hihope-rzg2/Makefile
new file mode 100644
index 0000000..e989e7a
--- /dev/null
+++ b/board/hoperun/hihope-rzg2/Makefile
@@ -0,0 +1,9 @@
+#
+# board/hoperun/hihope-rzg2/Makefile
+#
+# Copyright (C) 2021 Renesas Electronics Corporation
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y	:= hihope-rzg2.o ../../renesas/rcar-common/common.o
diff --git a/board/hoperun/hihope-rzg2/hihope-rzg2.c b/board/hoperun/hihope-rzg2/hihope-rzg2.c
new file mode 100644
index 0000000..c1bfdcb
--- /dev/null
+++ b/board/hoperun/hihope-rzg2/hihope-rzg2.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * board/hoperun/hihope-rzg2/hihope-rzg2.c
+ *     This file is HiHope RZ/G2[HMN] board support.
+ *
+ * Copyright (C) 2021 Renesas Electronics Corporation
+ */
+
+#include <common.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/arch/rmobile.h>
+#include <asm/arch/rcar-mstp.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/libfdt.h>
+
+#define RST_BASE	0xE6160000
+#define RST_CA57RESCNT	(RST_BASE + 0x40)
+#define RST_CA53RESCNT	(RST_BASE + 0x44)
+#define RST_CA57_CODE	0xA5A5000F
+#define RST_CA53_CODE	0x5A5A000F
+
+DECLARE_GLOBAL_DATA_PTR;
+#define HSUSB_MSTP704		BIT(4)	/* HSUSB */
+
+/* HSUSB block registers */
+#define HSUSB_REG_LPSTS			0xE6590102
+#define HSUSB_REG_LPSTS_SUSPM_NORMAL	BIT(14)
+#define HSUSB_REG_UGCTRL2		0xE6590184
+#define HSUSB_REG_UGCTRL2_USB0SEL_EHCI	0x10
+#define HSUSB_REG_UGCTRL2_RESERVED_3	0x1 /* bit[3:0] should be B'0001 */
+
+#define PRR_REGISTER (0xFFF00044)
+
+int board_init(void)
+{
+	u32 i;
+
+	/* address of boot parameters */
+	gd->bd->bi_boot_params = CONFIG_SYS_TEXT_BASE + 0x50000;
+
+	/* Configure the HSUSB block */
+	mstp_clrbits_le32(SMSTPCR7, SMSTPCR7, HSUSB_MSTP704);
+	/*
+	 * We need to add a barrier instruction after HSUSB module stop release.
+	 * This barrier instruction can be either reading back the same MSTP
+	 * register or any other register in the same IP block. So like linux
+	 * adding check for MSTPSR register, which indicates the clock has been
+	 * started.
+	 */
+	for (i = 1000; i > 0; --i) {
+		if (!(readl(MSTPSR7) & HSUSB_MSTP704))
+			break;
+		cpu_relax();
+	}
+
+	/* Select EHCI/OHCI host module for USB2.0 ch0 */
+	writel(HSUSB_REG_UGCTRL2_USB0SEL_EHCI | HSUSB_REG_UGCTRL2_RESERVED_3,
+	       HSUSB_REG_UGCTRL2);
+	/* low power status */
+	setbits_le16(HSUSB_REG_LPSTS, HSUSB_REG_LPSTS_SUSPM_NORMAL);
+
+	return 0;
+}
+
+void reset_cpu(ulong addr)
+{
+	unsigned long midr, cputype;
+
+	asm volatile("mrs %0, midr_el1" : "=r" (midr));
+	cputype = (midr >> 4) & 0xfff;
+
+	if (cputype == 0xd03)
+		writel(RST_CA53_CODE, RST_CA53RESCNT);
+	else
+		writel(RST_CA57_CODE, RST_CA57RESCNT);
+}
+
+#if defined(CONFIG_MULTI_DTB_FIT)
+/* If the firmware passed a device tree, use it for board identification. */
+extern u64 rcar_atf_boot_args[];
+
+static bool is_hoperun_hihope_rzg2_board(const char *board_name)
+{
+	void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
+	bool ret = false;
+
+	if ((fdt_magic(atf_fdt_blob) == FDT_MAGIC) &&
+	    (fdt_node_check_compatible(atf_fdt_blob, 0, board_name) == 0))
+		ret = true;
+
+	return ret;
+}
+
+int board_fit_config_name_match(const char *name)
+{
+	if (is_hoperun_hihope_rzg2_board("hoperun,hihope-rzg2m") &&
+	    !strcmp(name, "r8a774a1-hihope-rzg2m-u-boot"))
+		return 0;
+
+	if (is_hoperun_hihope_rzg2_board("hoperun,hihope-rzg2n") &&
+	    !strcmp(name, "r8a774b1-hihope-rzg2n-u-boot"))
+		return 0;
+
+	if (is_hoperun_hihope_rzg2_board("hoperun,hihope-rzg2h") &&
+	    !strcmp(name, "r8a774e1-hihope-rzg2h-u-boot"))
+		return 0;
+
+	return -1;
+}
+#endif
diff --git a/board/kmc/kzm9g/kzm9g.c b/board/kmc/kzm9g/kzm9g.c
index 02c87a0..dccf469 100644
--- a/board/kmc/kzm9g/kzm9g.c
+++ b/board/kmc/kzm9g/kzm9g.c
@@ -366,7 +366,7 @@
 	return ret;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	/* Soft Power On Reset */
 	writel((1 << 31), RESCNT2);
diff --git a/board/liebherr/display5/spl.c b/board/liebherr/display5/spl.c
index b8658c8..39f70f5 100644
--- a/board/liebherr/display5/spl.c
+++ b/board/liebherr/display5/spl.c
@@ -376,7 +376,7 @@
 #endif
 }
 
-void reset_cpu(ulong addr) {}
+void reset_cpu(void) {}
 
 #ifdef CONFIG_SPL_LOAD_FIT
 int board_fit_config_name_match(const char *name)
diff --git a/board/mediatek/pumpkin/Kconfig b/board/mediatek/mt8183/Kconfig
similarity index 66%
copy from board/mediatek/pumpkin/Kconfig
copy to board/mediatek/mt8183/Kconfig
index 34b1c0b..b75c3b8 100644
--- a/board/mediatek/pumpkin/Kconfig
+++ b/board/mediatek/mt8183/Kconfig
@@ -1,10 +1,10 @@
-if TARGET_MT8516
+if TARGET_MT8183
 
 config SYS_BOARD
-	default "pumpkin"
+	default "mt8183"
 
 config SYS_CONFIG_NAME
-	default "pumpkin"
+	default "mt8183"
 
 config MTK_BROM_HEADER_INFO
 	string
diff --git a/board/mediatek/mt8183/MAINTAINERS b/board/mediatek/mt8183/MAINTAINERS
new file mode 100644
index 0000000..a49995e
--- /dev/null
+++ b/board/mediatek/mt8183/MAINTAINERS
@@ -0,0 +1,6 @@
+MT8183 Pumpkin
+M:	Fabien Parent <fparent@baylibre.com>
+S:	Maintained
+F:	board/mediatek/mt8183
+F:	include/configs/mt8183.h
+F:	configs/mt8183_pumpkin_defconfig
diff --git a/board/mediatek/mt8183/Makefile b/board/mediatek/mt8183/Makefile
new file mode 100644
index 0000000..90b5b72
--- /dev/null
+++ b/board/mediatek/mt8183/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier:	GPL-2.0
+
+obj-y += mt8183_pumpkin.o
diff --git a/board/mediatek/pumpkin/pumpkin.c b/board/mediatek/mt8183/mt8183_pumpkin.c
similarity index 68%
copy from board/mediatek/pumpkin/pumpkin.c
copy to board/mediatek/mt8183/mt8183_pumpkin.c
index 37daf1c..db613eb 100644
--- a/board/mediatek/pumpkin/pumpkin.c
+++ b/board/mediatek/mt8183/mt8183_pumpkin.c
@@ -1,18 +1,15 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (C) 2019 BayLibre SAS
+ * Copyright (C) 2020 BayLibre SAS
+ * Author: Fabien Parent <fparent@baylibre.com>
  */
 
 #include <common.h>
 #include <dm.h>
+#include <net.h>
 
 int board_init(void)
 {
-	return 0;
-}
-
-int board_late_init(void)
-{
 	struct udevice *dev;
 	int ret;
 
@@ -24,5 +21,8 @@
 		}
 	}
 
+	if (CONFIG_IS_ENABLED(USB_ETHER))
+		usb_ether_init();
+
 	return 0;
 }
diff --git a/board/mediatek/pumpkin/Kconfig b/board/mediatek/mt8516/Kconfig
similarity index 76%
rename from board/mediatek/pumpkin/Kconfig
rename to board/mediatek/mt8516/Kconfig
index 34b1c0b..a87d387 100644
--- a/board/mediatek/pumpkin/Kconfig
+++ b/board/mediatek/mt8516/Kconfig
@@ -1,10 +1,10 @@
 if TARGET_MT8516
 
 config SYS_BOARD
-	default "pumpkin"
+	default "mt8516"
 
 config SYS_CONFIG_NAME
-	default "pumpkin"
+	default "mt8516"
 
 config MTK_BROM_HEADER_INFO
 	string
diff --git a/board/mediatek/mt8516/MAINTAINERS b/board/mediatek/mt8516/MAINTAINERS
new file mode 100644
index 0000000..2f0d8f6
--- /dev/null
+++ b/board/mediatek/mt8516/MAINTAINERS
@@ -0,0 +1,6 @@
+MT8516 Pumpkin
+M:	Fabien Parent <fparent@baylibre.com>
+S:	Maintained
+F:	board/mediatek/mt8516
+F:	include/configs/mt8516.h
+F:	configs/mt8516_pumpkin_defconfig
diff --git a/board/mediatek/mt8516/Makefile b/board/mediatek/mt8516/Makefile
new file mode 100644
index 0000000..1d4815d
--- /dev/null
+++ b/board/mediatek/mt8516/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier:	GPL-2.0
+
+obj-y += mt8516_pumpkin.o
diff --git a/board/mediatek/pumpkin/pumpkin.c b/board/mediatek/mt8516/mt8516_pumpkin.c
similarity index 84%
rename from board/mediatek/pumpkin/pumpkin.c
rename to board/mediatek/mt8516/mt8516_pumpkin.c
index 37daf1c..42f3863 100644
--- a/board/mediatek/pumpkin/pumpkin.c
+++ b/board/mediatek/mt8516/mt8516_pumpkin.c
@@ -5,6 +5,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <net.h>
 
 int board_init(void)
 {
@@ -24,5 +25,8 @@
 		}
 	}
 
+	if (CONFIG_IS_ENABLED(USB_ETHER))
+		usb_ether_init();
+
 	return 0;
 }
diff --git a/board/mediatek/pumpkin/MAINTAINERS b/board/mediatek/pumpkin/MAINTAINERS
deleted file mode 100644
index 16beadc..0000000
--- a/board/mediatek/pumpkin/MAINTAINERS
+++ /dev/null
@@ -1,6 +0,0 @@
-Pumpkin
-M:	Fabien Parent <fparent@baylibre.com>
-S:	Maintained
-F:	board/mediatek/pumpkin
-F:	include/configs/pumpkin.h
-F:	configs/pumpkin_defconfig
diff --git a/board/olimex/mx23_olinuxino/mx23_olinuxino.c b/board/olimex/mx23_olinuxino/mx23_olinuxino.c
index d1e189c..bdd5fcd 100644
--- a/board/olimex/mx23_olinuxino/mx23_olinuxino.c
+++ b/board/olimex/mx23_olinuxino/mx23_olinuxino.c
@@ -57,18 +57,6 @@
 	return mxs_dram_init();
 }
 
-#ifdef	CONFIG_CMD_MMC
-static int mx23_olx_mmc_cd(int id)
-{
-	return 1;	/* Card always present */
-}
-
-int board_mmc_init(struct bd_info *bis)
-{
-	return mxsmmc_initialize(bis, 0, NULL, mx23_olx_mmc_cd);
-}
-#endif
-
 int board_init(void)
 {
 	/* Adress of boot parameters */
diff --git a/board/phytec/phycore_imx8mp/spl.c b/board/phytec/phycore_imx8mp/spl.c
index eefdd7f..f9fa8d1 100644
--- a/board/phytec/phycore_imx8mp/spl.c
+++ b/board/phytec/phycore_imx8mp/spl.c
@@ -53,7 +53,7 @@
 	struct pmic *p;
 	int ret;
 
-	ret = power_pca9450_init(0);
+	ret = power_pca9450_init(0, 0x25);
 	if (ret)
 		printf("power init failed");
 	p = pmic_get("PCA9450");
diff --git a/board/phytium/durian/durian.c b/board/phytium/durian/durian.c
index 8a82a45..ef13f7c 100644
--- a/board/phytium/durian/durian.c
+++ b/board/phytium/durian/durian.c
@@ -42,7 +42,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	struct arm_smccc_res res;
 
diff --git a/board/qualcomm/dragonboard410c/dragonboard410c.c b/board/qualcomm/dragonboard410c/dragonboard410c.c
index 646013c..0d282de 100644
--- a/board/qualcomm/dragonboard410c/dragonboard410c.c
+++ b/board/qualcomm/dragonboard410c/dragonboard410c.c
@@ -203,7 +203,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	psci_system_reset();
 }
diff --git a/board/qualcomm/dragonboard820c/dragonboard820c.c b/board/qualcomm/dragonboard820c/dragonboard820c.c
index 877e34c..4ccb1a0 100644
--- a/board/qualcomm/dragonboard820c/dragonboard820c.c
+++ b/board/qualcomm/dragonboard820c/dragonboard820c.c
@@ -127,7 +127,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	psci_system_reset();
 }
diff --git a/board/renesas/alt/alt.c b/board/renesas/alt/alt.c
index 854c476..3b60afc 100644
--- a/board/renesas/alt/alt.c
+++ b/board/renesas/alt/alt.c
@@ -111,7 +111,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	struct udevice *dev;
 	const u8 pmic_bus = 7;
diff --git a/board/renesas/alt/alt_spl.c b/board/renesas/alt/alt_spl.c
index 2de236f..cdaa04e 100644
--- a/board/renesas/alt/alt_spl.c
+++ b/board/renesas/alt/alt_spl.c
@@ -408,6 +408,6 @@
 	spl_boot_list[2] = BOOT_DEVICE_NONE;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
diff --git a/board/renesas/blanche/blanche.c b/board/renesas/blanche/blanche.c
index 9671382..a365269 100644
--- a/board/renesas/blanche/blanche.c
+++ b/board/renesas/blanche/blanche.c
@@ -360,7 +360,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	struct udevice *dev;
 	const u8 pmic_bus = 6;
diff --git a/board/renesas/condor/condor.c b/board/renesas/condor/condor.c
index 4454061..e930de3 100644
--- a/board/renesas/condor/condor.c
+++ b/board/renesas/condor/condor.c
@@ -34,7 +34,7 @@
 #define RST_CA57_CODE	0xA5A5000F
 #define RST_CA53_CODE	0x5A5A000F
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	unsigned long midr, cputype;
 
diff --git a/board/renesas/draak/draak.c b/board/renesas/draak/draak.c
index ffd52eb..1d76f95 100644
--- a/board/renesas/draak/draak.c
+++ b/board/renesas/draak/draak.c
@@ -75,7 +75,7 @@
 #define RST_CA53RESCNT	(RST_BASE + 0x44)
 #define RST_CA53_CODE	0x5A5A000F
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	writel(RST_CA53_CODE, RST_CA53RESCNT);
 }
diff --git a/board/renesas/eagle/eagle.c b/board/renesas/eagle/eagle.c
index f9e553f..bb32e3d 100644
--- a/board/renesas/eagle/eagle.c
+++ b/board/renesas/eagle/eagle.c
@@ -78,7 +78,7 @@
 #define RST_CA57_CODE	0xA5A5000F
 #define RST_CA53_CODE	0x5A5A000F
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	unsigned long midr, cputype;
 
diff --git a/board/renesas/ebisu/ebisu.c b/board/renesas/ebisu/ebisu.c
index 82cd2a5..9d4af8d 100644
--- a/board/renesas/ebisu/ebisu.c
+++ b/board/renesas/ebisu/ebisu.c
@@ -42,7 +42,7 @@
 #define RST_CA53RESCNT	(RST_BASE + 0x44)
 #define RST_CA53_CODE	0x5A5A000F
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	writel(RST_CA53_CODE, RST_CA53RESCNT);
 }
diff --git a/board/renesas/gose/gose.c b/board/renesas/gose/gose.c
index 56cdc73..51768c3 100644
--- a/board/renesas/gose/gose.c
+++ b/board/renesas/gose/gose.c
@@ -117,7 +117,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	struct udevice *dev;
 	const u8 pmic_bus = 6;
diff --git a/board/renesas/gose/gose_spl.c b/board/renesas/gose/gose_spl.c
index 624ba5d..c0bf720 100644
--- a/board/renesas/gose/gose_spl.c
+++ b/board/renesas/gose/gose_spl.c
@@ -405,6 +405,6 @@
 	spl_boot_list[2] = BOOT_DEVICE_NONE;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
diff --git a/board/renesas/grpeach/grpeach.c b/board/renesas/grpeach/grpeach.c
index ac989eb..199ec4a 100644
--- a/board/renesas/grpeach/grpeach.c
+++ b/board/renesas/grpeach/grpeach.c
@@ -40,7 +40,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	/* Dummy read (must read WRCSR:WOVF at least once before clearing) */
 	readb(RZA1_WDT_BASE + WRCSR);
diff --git a/board/renesas/koelsch/koelsch.c b/board/renesas/koelsch/koelsch.c
index b0a66ea..7e94bd8 100644
--- a/board/renesas/koelsch/koelsch.c
+++ b/board/renesas/koelsch/koelsch.c
@@ -119,7 +119,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	struct udevice *dev;
 	const u8 pmic_bus = 6;
diff --git a/board/renesas/koelsch/koelsch_spl.c b/board/renesas/koelsch/koelsch_spl.c
index 449bbfa..b377f70 100644
--- a/board/renesas/koelsch/koelsch_spl.c
+++ b/board/renesas/koelsch/koelsch_spl.c
@@ -407,6 +407,6 @@
 	spl_boot_list[2] = BOOT_DEVICE_NONE;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
diff --git a/board/renesas/lager/lager.c b/board/renesas/lager/lager.c
index add4eef..87c5e01 100644
--- a/board/renesas/lager/lager.c
+++ b/board/renesas/lager/lager.c
@@ -128,7 +128,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	struct udevice *dev;
 	const u8 pmic_bus = 2;
diff --git a/board/renesas/lager/lager_spl.c b/board/renesas/lager/lager_spl.c
index 1ca857c..d3d397e 100644
--- a/board/renesas/lager/lager_spl.c
+++ b/board/renesas/lager/lager_spl.c
@@ -393,6 +393,6 @@
 	spl_boot_list[2] = BOOT_DEVICE_NONE;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
diff --git a/board/renesas/porter/porter.c b/board/renesas/porter/porter.c
index b3e4c08..b0f8505 100644
--- a/board/renesas/porter/porter.c
+++ b/board/renesas/porter/porter.c
@@ -117,7 +117,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	struct udevice *dev;
 	const u8 pmic_bus = 6;
diff --git a/board/renesas/porter/porter_spl.c b/board/renesas/porter/porter_spl.c
index f10c6cf..8595770 100644
--- a/board/renesas/porter/porter_spl.c
+++ b/board/renesas/porter/porter_spl.c
@@ -488,6 +488,6 @@
 	spl_boot_list[2] = BOOT_DEVICE_NONE;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
diff --git a/board/renesas/rcar-common/gen3-spl.c b/board/renesas/rcar-common/gen3-spl.c
index fd6e505..b02a946 100644
--- a/board/renesas/rcar-common/gen3-spl.c
+++ b/board/renesas/rcar-common/gen3-spl.c
@@ -55,6 +55,6 @@
 {
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
diff --git a/board/renesas/salvator-x/salvator-x.c b/board/renesas/salvator-x/salvator-x.c
index 08ed725..071076a 100644
--- a/board/renesas/salvator-x/salvator-x.c
+++ b/board/renesas/salvator-x/salvator-x.c
@@ -76,7 +76,7 @@
 #define RST_RSTOUTCR	(RST_BASE + 0x58)
 #define RST_CODE	0xA5A5000F
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 #if defined(CONFIG_SYS_I2C) && defined(CONFIG_SYS_I2C_SH)
 	i2c_reg_write(CONFIG_SYS_I2C_POWERIC_ADDR, 0x20, 0x80);
diff --git a/board/renesas/silk/silk.c b/board/renesas/silk/silk.c
index 05af5f4..4558070 100644
--- a/board/renesas/silk/silk.c
+++ b/board/renesas/silk/silk.c
@@ -112,7 +112,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	struct udevice *dev;
 	const u8 pmic_bus = 1;
diff --git a/board/renesas/silk/silk_spl.c b/board/renesas/silk/silk_spl.c
index f10f84a..afb9f85 100644
--- a/board/renesas/silk/silk_spl.c
+++ b/board/renesas/silk/silk_spl.c
@@ -422,6 +422,6 @@
 	spl_boot_list[2] = BOOT_DEVICE_NONE;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
diff --git a/board/renesas/stout/cpld.c b/board/renesas/stout/cpld.c
index b56ed17..ac8048c 100644
--- a/board/renesas/stout/cpld.c
+++ b/board/renesas/stout/cpld.c
@@ -163,7 +163,7 @@
 	"cpld write addr val\n"
 );
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	cpld_write(CPLD_ADDR_RESET, 1);
 }
diff --git a/board/renesas/stout/stout_spl.c b/board/renesas/stout/stout_spl.c
index 57c1fab..c37c055 100644
--- a/board/renesas/stout/stout_spl.c
+++ b/board/renesas/stout/stout_spl.c
@@ -474,6 +474,6 @@
 	spl_boot_list[2] = BOOT_DEVICE_NONE;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
diff --git a/board/rockchip/evb_rk3399/MAINTAINERS b/board/rockchip/evb_rk3399/MAINTAINERS
index 4c889e0..25e308d 100644
--- a/board/rockchip/evb_rk3399/MAINTAINERS
+++ b/board/rockchip/evb_rk3399/MAINTAINERS
@@ -49,12 +49,24 @@
 F:	configs/nanopi-m4-2gb-rk3399_defconfig
 F:	arch/arm/dts/rk3399-nanopi-m4-2gb-u-boot.dtsi
 
+NANOPI-M4B
+M:	Alexandre Vicenzi <linux@alxd.me>
+S:	Maintained
+F:	configs/nanopi-m4b-rk3399_defconfig
+F:	arch/arm/dts/rk3399-nanopi-m4b-u-boot.dtsi
+
 NANOPI-NEO4
 M:	Jagan Teki <jagan@amarulasolutions.com>
 S:	Maintained
 F:	configs/nanopi-neo4-rk3399_defconfig
 F:	arch/arm/dts/rk3399-nanopi-neo4-u-boot.dtsi
 
+NANOPI-R4S
+M:	Xiaobo Tian <peterwillcn@gmail.com>
+S:	Maintained
+F:	configs/nanopi-r4s-rk3399_defconfig
+F:	arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi
+
 ORANGEPI-RK3399
 M:	Jagan Teki <jagan@amarulasolutions.com>
 S:	Maintained
diff --git a/board/sandbox/MAINTAINERS b/board/sandbox/MAINTAINERS
index 433be48..d32561c 100644
--- a/board/sandbox/MAINTAINERS
+++ b/board/sandbox/MAINTAINERS
@@ -20,6 +20,13 @@
 F:	include/configs/sandbox_spl.h
 F:	configs/sandbox_spl_defconfig
 
+SANDBOX NOINST BOARD
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	board/sandbox/
+F:	include/configs/sandbox_spl.h
+F:	configs/sandbox_noinst_defconfig
+
 SANDBOX FLAT TREE BOARD
 M:	Simon Glass <sjg@chromium.org>
 S:	Maintained
diff --git a/board/sandbox/sandbox.c b/board/sandbox/sandbox.c
index 3c63d45..902b99e 100644
--- a/board/sandbox/sandbox.c
+++ b/board/sandbox/sandbox.c
@@ -48,6 +48,7 @@
 static enum env_location env_locations[] = {
 	ENVL_NOWHERE,
 	ENVL_EXT4,
+	ENVL_FAT,
 };
 
 enum env_location env_get_location(enum env_operation op, int prio)
diff --git a/board/siemens/capricorn/board.c b/board/siemens/capricorn/board.c
index 56973a1..dcbab8e 100644
--- a/board/siemens/capricorn/board.c
+++ b/board/siemens/capricorn/board.c
@@ -232,7 +232,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
diff --git a/board/sifive/fu540/MAINTAINERS b/board/sifive/fu540/MAINTAINERS
deleted file mode 100644
index 2762072..0000000
--- a/board/sifive/fu540/MAINTAINERS
+++ /dev/null
@@ -1,10 +0,0 @@
-SiFive FU540 BOARD
-M:	Paul Walmsley <paul.walmsley@sifive.com>
-M:	Palmer Dabbelt <palmer@dabbelt.com>
-M:	Anup Patel <anup.patel@wdc.com>
-M:	Atish Patra <atish.patra@wdc.com>
-S:	Maintained
-F:	board/sifive/fu540/
-F:	doc/board/sifive/fu540.rst
-F:	include/configs/sifive-fu540.h
-F:	configs/sifive_fu540_defconfig
diff --git a/board/sifive/fu540/Kconfig b/board/sifive/unleashed/Kconfig
similarity index 91%
rename from board/sifive/fu540/Kconfig
rename to board/sifive/unleashed/Kconfig
index 64fdbd4..dbffd59 100644
--- a/board/sifive/fu540/Kconfig
+++ b/board/sifive/unleashed/Kconfig
@@ -1,7 +1,7 @@
-if TARGET_SIFIVE_FU540
+if TARGET_SIFIVE_UNLEASHED
 
 config SYS_BOARD
-	default "fu540"
+	default "unleashed"
 
 config SYS_VENDOR
 	default "sifive"
@@ -10,7 +10,7 @@
 	default "fu540"
 
 config SYS_CONFIG_NAME
-	default "sifive-fu540"
+	default "sifive-unleashed"
 
 config SYS_TEXT_BASE
 	default 0x80200000 if SPL
diff --git a/board/sifive/unleashed/MAINTAINERS b/board/sifive/unleashed/MAINTAINERS
new file mode 100644
index 0000000..2ea0074
--- /dev/null
+++ b/board/sifive/unleashed/MAINTAINERS
@@ -0,0 +1,10 @@
+SiFive HiFive Unleashed BOARD
+M:	Paul Walmsley <paul.walmsley@sifive.com>
+M:	Palmer Dabbelt <palmer@dabbelt.com>
+M:	Anup Patel <anup.patel@wdc.com>
+M:	Atish Patra <atish.patra@wdc.com>
+S:	Maintained
+F:	board/sifive/unleashed/
+F:	doc/board/sifive/unleashed.rst
+F:	include/configs/sifive-unleashed.h
+F:	configs/sifive_unleashed_defconfig
diff --git a/board/sifive/fu540/Makefile b/board/sifive/unleashed/Makefile
similarity index 87%
rename from board/sifive/fu540/Makefile
rename to board/sifive/unleashed/Makefile
index b05e2f5..5821679 100644
--- a/board/sifive/fu540/Makefile
+++ b/board/sifive/unleashed/Makefile
@@ -2,7 +2,7 @@
 #
 # Copyright (c) 2019 Western Digital Corporation or its affiliates.
 
-obj-y	+= fu540.o
+obj-y	+= unleashed.o
 
 ifdef CONFIG_SPL_BUILD
 obj-y += spl.o
diff --git a/board/sifive/fu540/spl.c b/board/sifive/unleashed/spl.c
similarity index 100%
rename from board/sifive/fu540/spl.c
rename to board/sifive/unleashed/spl.c
diff --git a/board/sifive/fu540/fu540.c b/board/sifive/unleashed/unleashed.c
similarity index 100%
rename from board/sifive/fu540/fu540.c
rename to board/sifive/unleashed/unleashed.c
diff --git a/board/silinux/ek874/Kconfig b/board/silinux/ek874/Kconfig
new file mode 100644
index 0000000..60b390a
--- /dev/null
+++ b/board/silinux/ek874/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_SILINUX_EK874
+
+config SYS_SOC
+	default "rmobile"
+
+config SYS_BOARD
+	default "ek874"
+
+config SYS_VENDOR
+	default "silinux"
+
+config SYS_CONFIG_NAME
+	default "silinux-ek874"
+
+endif
diff --git a/board/silinux/ek874/MAINTAINERS b/board/silinux/ek874/MAINTAINERS
new file mode 100644
index 0000000..57a71b8
--- /dev/null
+++ b/board/silinux/ek874/MAINTAINERS
@@ -0,0 +1,6 @@
+SILINUX_EK874 BOARD
+M:	Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+S:	Maintained
+F:	board/silinux/ek874/
+F:	include/configs/silinux-ek874.h
+F:	configs/silinux_ek874_defconfig
diff --git a/board/silinux/ek874/Makefile b/board/silinux/ek874/Makefile
new file mode 100644
index 0000000..4c8f092
--- /dev/null
+++ b/board/silinux/ek874/Makefile
@@ -0,0 +1,13 @@
+#
+# board/silinux/ek874/Makefile
+#
+# Copyright (C) 2021 Renesas Electronics Corporation
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+ifdef CONFIG_SPL_BUILD
+obj-y	:= ../../renesas/rcar-common/gen3-spl.o
+else
+obj-y	:= ek874.o ../../renesas/rcar-common/common.o
+endif
diff --git a/board/silinux/ek874/ek874.c b/board/silinux/ek874/ek874.c
new file mode 100644
index 0000000..5a219cd
--- /dev/null
+++ b/board/silinux/ek874/ek874.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * board/silinux/ek874/ek874.c
+ *     This file is ek874 board support.
+ *
+ * Copyright (C) 2021 Renesas Electronics Corporation
+ */
+
+#include <common.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+
+#define RST_BASE	0xE6160000
+#define RST_CA53RESCNT	(RST_BASE + 0x44)
+#define RST_CA53_CODE	0x5A5A000F
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_init(void)
+{
+	/* address of boot parameters */
+	gd->bd->bi_boot_params = CONFIG_SYS_TEXT_BASE + 0x50000;
+
+	return 0;
+}
+
+void reset_cpu(ulong addr)
+{
+	writel(RST_CA53_CODE, RST_CA53RESCNT);
+}
diff --git a/board/sipeed/maix/Kconfig b/board/sipeed/maix/Kconfig
index 2cdea8e..adf6abb 100644
--- a/board/sipeed/maix/Kconfig
+++ b/board/sipeed/maix/Kconfig
@@ -69,4 +69,6 @@
 	imply EFI_PARTITION
 	imply CMD_PART
 	imply CMD_FS_GENERIC
+	imply WDT
+	imply DESIGNWARE_WATCHDOG
 endif
diff --git a/board/solidrun/mx6cuboxi/MAINTAINERS b/board/solidrun/mx6cuboxi/MAINTAINERS
index bd098b4..0558521 100644
--- a/board/solidrun/mx6cuboxi/MAINTAINERS
+++ b/board/solidrun/mx6cuboxi/MAINTAINERS
@@ -1,6 +1,6 @@
 MX6CUBOXI BOARD
 M:	Baruch Siach <baruch@tkos.co.il>
-M:	Fabio Estevam <fabio.estevam@nxp.com>
+M:	Fabio Estevam <festevam@gmail.com>
 S:	Maintained
 F:	board/solidrun/mx6cuboxi/
 F:	include/configs/mx6cuboxi.h
diff --git a/board/st/stm32f746-disco/stm32f746-disco.c b/board/st/stm32f746-disco/stm32f746-disco.c
index 143cc6e..efa38a0 100644
--- a/board/st/stm32f746-disco/stm32f746-disco.c
+++ b/board/st/stm32f746-disco/stm32f746-disco.c
@@ -69,8 +69,8 @@
 }
 void spl_board_init(void)
 {
-	spl_dram_init();
 	preloader_console_init();
+	spl_dram_init();
 	arch_cpu_init(); /* to configure mpu for sdram rw permissions */
 }
 u32 spl_boot_device(void)
diff --git a/board/synopsys/emsdp/emsdp.c b/board/synopsys/emsdp/emsdp.c
index 997120e..a3cee23 100644
--- a/board/synopsys/emsdp/emsdp.c
+++ b/board/synopsys/emsdp/emsdp.c
@@ -98,7 +98,7 @@
 /* Bits in CREG_BOOT register */
 #define CREG_BOOT_WP_BIT	BIT(8)
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	writel(1, CREG_IP_SW_RESET);
 	while (1)
diff --git a/board/synopsys/iot_devkit/iot_devkit.c b/board/synopsys/iot_devkit/iot_devkit.c
index c605136..650958f 100644
--- a/board/synopsys/iot_devkit/iot_devkit.c
+++ b/board/synopsys/iot_devkit/iot_devkit.c
@@ -151,7 +151,7 @@
 
 #define IOTDK_RESET_SEQ		0x55AA6699
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	writel(IOTDK_RESET_SEQ, RESET_REG);
 }
diff --git a/board/technexion/pico-imx6ul/MAINTAINERS b/board/technexion/pico-imx6ul/MAINTAINERS
index e9b5a97..f94a011 100644
--- a/board/technexion/pico-imx6ul/MAINTAINERS
+++ b/board/technexion/pico-imx6ul/MAINTAINERS
@@ -1,6 +1,6 @@
 TechNexion PICO-IMX6UL board
 M:	Richard Hu <richard.hu@technexion.com>
-M:	Fabio Estevam <fabio.estevam@nxp.com>
+M:	Fabio Estevam <festevam@gmail.com>
 S:	Maintained
 F:	board/technexion/pico-imx6ul/
 F:	include/configs/pico-imx6ul.h
diff --git a/board/technexion/pico-imx6ul/pico-imx6ul.c b/board/technexion/pico-imx6ul/pico-imx6ul.c
index 62a54d0c..682c88d 100644
--- a/board/technexion/pico-imx6ul/pico-imx6ul.c
+++ b/board/technexion/pico-imx6ul/pico-imx6ul.c
@@ -159,7 +159,7 @@
 	struct udevice *dev;
 	int ret, dev_id, rev_id;
 
-	ret = pmic_get("pfuze3000", &dev);
+	ret = pmic_get("pfuze3000@8", &dev);
 	if (ret == -ENODEV)
 		return 0;
 	if (ret != 0)
diff --git a/board/technexion/pico-imx6ul/spl.c b/board/technexion/pico-imx6ul/spl.c
index 3807779..251f5a1 100644
--- a/board/technexion/pico-imx6ul/spl.c
+++ b/board/technexion/pico-imx6ul/spl.c
@@ -147,7 +147,7 @@
 	board_init_r(NULL, 0);
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
diff --git a/board/technexion/pico-imx7d/spl.c b/board/technexion/pico-imx7d/spl.c
index bed0f21..df5f058 100644
--- a/board/technexion/pico-imx7d/spl.c
+++ b/board/technexion/pico-imx7d/spl.c
@@ -127,7 +127,7 @@
 	board_init_r(NULL, 0);
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
diff --git a/board/theobroma-systems/puma_rk3399/Kconfig b/board/theobroma-systems/puma_rk3399/Kconfig
index e82623a..21946d9 100644
--- a/board/theobroma-systems/puma_rk3399/Kconfig
+++ b/board/theobroma-systems/puma_rk3399/Kconfig
@@ -13,7 +13,7 @@
 	def_bool y
 
 config ENV_SIZE
-	default 0x2000
+	default 0x4000
 
 config ENV_OFFSET
 	default 0x3fc000 if ENV_IS_IN_SPI_FLASH
diff --git a/board/toradex/apalis-imx8/apalis-imx8.c b/board/toradex/apalis-imx8/apalis-imx8.c
index 76faa6e..04877fc 100644
--- a/board/toradex/apalis-imx8/apalis-imx8.c
+++ b/board/toradex/apalis-imx8/apalis-imx8.c
@@ -117,7 +117,7 @@
 /*
  * Board specific reset that is system reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	/* TODO */
 }
diff --git a/board/toradex/apalis-imx8x/apalis-imx8x.c b/board/toradex/apalis-imx8x/apalis-imx8x.c
index b6f3bdd..ac3bac6 100644
--- a/board/toradex/apalis-imx8x/apalis-imx8x.c
+++ b/board/toradex/apalis-imx8x/apalis-imx8x.c
@@ -127,7 +127,7 @@
 /*
  * Board specific reset that is system reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	/* TODO */
 }
diff --git a/board/toradex/apalis_imx6/apalis_imx6.c b/board/toradex/apalis_imx6/apalis_imx6.c
index 0c857b5..74060da 100644
--- a/board/toradex/apalis_imx6/apalis_imx6.c
+++ b/board/toradex/apalis_imx6/apalis_imx6.c
@@ -1139,7 +1139,7 @@
 }
 #endif
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
diff --git a/board/toradex/colibri-imx8x/colibri-imx8x.c b/board/toradex/colibri-imx8x/colibri-imx8x.c
index 562199a..169d4d0 100644
--- a/board/toradex/colibri-imx8x/colibri-imx8x.c
+++ b/board/toradex/colibri-imx8x/colibri-imx8x.c
@@ -129,7 +129,7 @@
 /*
  * Board specific reset that is system reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	/* TODO */
 }
diff --git a/board/toradex/colibri_imx6/colibri_imx6.c b/board/toradex/colibri_imx6/colibri_imx6.c
index 74d59e5..c0e7754 100644
--- a/board/toradex/colibri_imx6/colibri_imx6.c
+++ b/board/toradex/colibri_imx6/colibri_imx6.c
@@ -1081,7 +1081,7 @@
 	board_init_r(NULL, 0);
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
diff --git a/board/toradex/colibri_imx7/colibri_imx7.c b/board/toradex/colibri_imx7/colibri_imx7.c
index 8f7ef99..301b07d 100644
--- a/board/toradex/colibri_imx7/colibri_imx7.c
+++ b/board/toradex/colibri_imx7/colibri_imx7.c
@@ -237,7 +237,7 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	struct udevice *dev;
 
diff --git a/board/udoo/MAINTAINERS b/board/udoo/MAINTAINERS
index b05243c..195882b 100644
--- a/board/udoo/MAINTAINERS
+++ b/board/udoo/MAINTAINERS
@@ -1,5 +1,5 @@
 UDOO BOARD
-M:	Fabio Estevam <fabio.estevam@nxp.com>
+M:	Fabio Estevam <festevam@gmail.com>
 S:	Maintained
 F:	board/udoo/
 F:	include/configs/udoo.h
diff --git a/board/udoo/udoo.c b/board/udoo/udoo.c
index d83f23d..5c49388 100644
--- a/board/udoo/udoo.c
+++ b/board/udoo/udoo.c
@@ -19,8 +19,6 @@
 #include <asm/gpio.h>
 #include <asm/mach-imx/iomux-v3.h>
 #include <asm/mach-imx/sata.h>
-#include <mmc.h>
-#include <fsl_esdhc_imx.h>
 #include <asm/arch/crm_regs.h>
 #include <asm/io.h>
 #include <asm/arch/sys_proto.h>
@@ -56,15 +54,6 @@
 	IOMUX_PADS(PAD_EIM_D27__UART2_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)),
 };
 
-static iomux_v3_cfg_t const usdhc3_pads[] = {
-	IOMUX_PADS(PAD_SD3_CLK__SD3_CLK    | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
-	IOMUX_PADS(PAD_SD3_CMD__SD3_CMD    | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
-	IOMUX_PADS(PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
-	IOMUX_PADS(PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
-	IOMUX_PADS(PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
-	IOMUX_PADS(PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
-};
-
 static iomux_v3_cfg_t const wdog_pads[] = {
 	IOMUX_PADS(PAD_EIM_A24__GPIO5_IO04 | MUX_PAD_CTRL(NO_PAD_CTRL)),
 	IOMUX_PADS(PAD_EIM_D19__GPIO3_IO19),
@@ -99,45 +88,8 @@
 	return 0;
 }
 
-static iomux_v3_cfg_t const enet_pads1[] = {
-	IOMUX_PADS(PAD_ENET_MDIO__ENET_MDIO		| MUX_PAD_CTRL(ENET_PAD_CTRL)),
-	IOMUX_PADS(PAD_ENET_MDC__ENET_MDC		| MUX_PAD_CTRL(ENET_PAD_CTRL)),
-	IOMUX_PADS(PAD_RGMII_TXC__RGMII_TXC	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
-	IOMUX_PADS(PAD_RGMII_TD0__RGMII_TD0	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
-	IOMUX_PADS(PAD_RGMII_TD1__RGMII_TD1	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
-	IOMUX_PADS(PAD_RGMII_TD2__RGMII_TD2	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
-	IOMUX_PADS(PAD_RGMII_TD3__RGMII_TD3	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
-	IOMUX_PADS(PAD_RGMII_TX_CTL__RGMII_TX_CTL	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
-	IOMUX_PADS(PAD_ENET_REF_CLK__ENET_TX_CLK	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
-	IOMUX_PADS(PAD_RGMII_RXC__RGMII_RXC	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
-	/* RGMII reset */
-	IOMUX_PADS(PAD_EIM_D23__GPIO3_IO23		| MUX_PAD_CTRL(NO_PAD_CTRL)),
-	/* Ethernet power supply */
-	IOMUX_PADS(PAD_EIM_EB3__GPIO2_IO31		| MUX_PAD_CTRL(NO_PAD_CTRL)),
-	/* pin 32 - 1 - (MODE0) all */
-	IOMUX_PADS(PAD_RGMII_RD0__GPIO6_IO25		| MUX_PAD_CTRL(NO_PAD_CTRL)),
-	/* pin 31 - 1 - (MODE1) all */
-	IOMUX_PADS(PAD_RGMII_RD1__GPIO6_IO27		| MUX_PAD_CTRL(NO_PAD_CTRL)),
-	/* pin 28 - 1 - (MODE2) all */
-	IOMUX_PADS(PAD_RGMII_RD2__GPIO6_IO28		| MUX_PAD_CTRL(NO_PAD_CTRL)),
-	/* pin 27 - 1 - (MODE3) all */
-	IOMUX_PADS(PAD_RGMII_RD3__GPIO6_IO29		| MUX_PAD_CTRL(NO_PAD_CTRL)),
-	/* pin 33 - 1 - (CLK125_EN) 125Mhz clockout enabled */
-	IOMUX_PADS(PAD_RGMII_RX_CTL__GPIO6_IO24	| MUX_PAD_CTRL(NO_PAD_CTRL)),
-};
-
-static iomux_v3_cfg_t const enet_pads2[] = {
-	IOMUX_PADS(PAD_RGMII_RD0__RGMII_RD0	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
-	IOMUX_PADS(PAD_RGMII_RD1__RGMII_RD1	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
-	IOMUX_PADS(PAD_RGMII_RD2__RGMII_RD2	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
-	IOMUX_PADS(PAD_RGMII_RD3__RGMII_RD3	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
-	IOMUX_PADS(PAD_RGMII_RX_CTL__RGMII_RX_CTL	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
-};
-
 static void setup_iomux_enet(void)
 {
-	SETUP_IOMUX_PADS(enet_pads1);
-	udelay(20);
 	gpio_direction_output(IMX_GPIO_NR(2, 31), 1); /* Power supply on */
 
 	gpio_direction_output(IMX_GPIO_NR(3, 23), 0); /* assert PHY rst */
@@ -159,8 +111,6 @@
 	gpio_free(IMX_GPIO_NR(6, 27));
 	gpio_free(IMX_GPIO_NR(6, 28));
 	gpio_free(IMX_GPIO_NR(6, 29));
-
-	SETUP_IOMUX_PADS(enet_pads2);
 }
 
 static void setup_iomux_uart(void)
@@ -176,56 +126,6 @@
 	gpio_direction_input(WDT_TRG);
 }
 
-static struct fsl_esdhc_cfg usdhc_cfg = { USDHC3_BASE_ADDR };
-
-int board_mmc_getcd(struct mmc *mmc)
-{
-	return 1; /* Always present */
-}
-
-int board_eth_init(struct bd_info *bis)
-{
-	uint32_t base = IMX_FEC_BASE;
-	struct mii_dev *bus = NULL;
-	struct phy_device *phydev = NULL;
-	int ret;
-
-	setup_iomux_enet();
-
-#ifdef CONFIG_FEC_MXC
-	bus = fec_get_miibus(base, -1);
-	if (!bus)
-		return -EINVAL;
-	/* scan phy 4,5,6,7 */
-	phydev = phy_find_by_mask(bus, (0xf << 4), PHY_INTERFACE_MODE_RGMII);
-
-	if (!phydev) {
-		ret = -EINVAL;
-		goto free_bus;
-	}
-	printf("using phy at %d\n", phydev->addr);
-	ret  = fec_probe(bis, -1, base, bus, phydev);
-	if (ret)
-		goto free_phydev;
-#endif
-	return 0;
-
-free_phydev:
-	free(phydev);
-free_bus:
-	free(bus);
-	return ret;
-}
-
-int board_mmc_init(struct bd_info *bis)
-{
-	SETUP_IOMUX_PADS(usdhc3_pads);
-	usdhc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
-	usdhc_cfg.max_bus_width = 4;
-
-	return fsl_esdhc_initialize(bis, &usdhc_cfg);
-}
-
 int board_early_init_f(void)
 {
 	setup_iomux_wdog();
@@ -248,9 +148,6 @@
 	/* address of boot parameters */
 	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
 
-#ifdef CONFIG_SATA
-	setup_sata();
-#endif
 	return 0;
 }
 
@@ -262,6 +159,8 @@
 	else
 		env_set("board_rev", "MX6DL");
 #endif
+	setup_iomux_enet();
+
 	return 0;
 }
 
diff --git a/board/wandboard/MAINTAINERS b/board/wandboard/MAINTAINERS
index 00a31a93..3c2a06c 100644
--- a/board/wandboard/MAINTAINERS
+++ b/board/wandboard/MAINTAINERS
@@ -1,5 +1,5 @@
 WANDBOARD BOARD
-M:	Fabio Estevam <fabio.estevam@nxp.com>
+M:	Fabio Estevam <festevam@gmail.com>
 S:	Maintained
 F:	arch/arm/dts/imx6qdl-wandboard.dtsi
 F:	arch/arm/dts/imx6qdl-wandboard-revb1.dtsi
diff --git a/board/warp7/MAINTAINERS b/board/warp7/MAINTAINERS
index 55f8c81..ebb21f8 100644
--- a/board/warp7/MAINTAINERS
+++ b/board/warp7/MAINTAINERS
@@ -1,5 +1,5 @@
 WARP7 BOARD
-M:	Fabio Estevam <fabio.estevam@nxp.com>
+M:	Fabio Estevam <festevam@gmail.com>
 S:	Maintained
 F:	board/warp7/
 F:	include/configs/warp7.h
diff --git a/board/xen/xenguest_arm64/xenguest_arm64.c b/board/xen/xenguest_arm64/xenguest_arm64.c
index 7d0d782..21363d8 100644
--- a/board/xen/xenguest_arm64/xenguest_arm64.c
+++ b/board/xen/xenguest_arm64/xenguest_arm64.c
@@ -171,7 +171,7 @@
 /*
  * Board specific reset that is system reset.
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
diff --git a/board/xilinx/versal/board.c b/board/xilinx/versal/board.c
index c644fe8..e2f9d13 100644
--- a/board/xilinx/versal/board.c
+++ b/board/xilinx/versal/board.c
@@ -242,6 +242,6 @@
 	return 0;
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
diff --git a/board/xilinx/zynqmp/zynqmp-zcu1275-revB/psu_init_gpl.c b/board/xilinx/zynqmp/zynqmp-zcu1275-revB/psu_init_gpl.c
index d3eb713..2d93b20 100644
--- a/board/xilinx/zynqmp/zynqmp-zcu1275-revB/psu_init_gpl.c
+++ b/board/xilinx/zynqmp/zynqmp-zcu1275-revB/psu_init_gpl.c
@@ -8,77 +8,88 @@
 
 static unsigned long psu_pll_init_data(void)
 {
-	psu_mask_write(0xFF5E0034, 0xFE7FEDEFU, 0x7E4E2C62U);
-	psu_mask_write(0xFF5E0030, 0x00717F00U, 0x00013C00U);
+	psu_mask_write(0xFF5E0034, 0xFE7FEDEFU, 0x7E4B0C62U);
+	psu_mask_write(0xFF5E0030, 0x00717F00U, 0x00014600U);
 	psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000008U);
 	psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000001U);
 	psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000000U);
 	mask_poll(0xFF5E0040, 0x00000002U);
 	psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000000U);
-	psu_mask_write(0xFF5E0048, 0x00003F00U, 0x00000200U);
-	psu_mask_write(0xFF5E0024, 0xFE7FEDEFU, 0x7E4B0C82U);
-	psu_mask_write(0xFF5E0020, 0x00717F00U, 0x00015A00U);
+	psu_mask_write(0xFF5E0048, 0x00003F00U, 0x00000300U);
+	psu_mask_write(0xFF5E0038, 0x8000FFFFU, 0x00000000U);
+	psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01012300U);
+	psu_mask_write(0xFF5E0024, 0xFE7FEDEFU, 0x7E672C6CU);
+	psu_mask_write(0xFF5E0020, 0x00717F00U, 0x00002D00U);
 	psu_mask_write(0xFF5E0020, 0x00000008U, 0x00000008U);
 	psu_mask_write(0xFF5E0020, 0x00000001U, 0x00000001U);
 	psu_mask_write(0xFF5E0020, 0x00000001U, 0x00000000U);
 	mask_poll(0xFF5E0040, 0x00000001U);
 	psu_mask_write(0xFF5E0020, 0x00000008U, 0x00000000U);
 	psu_mask_write(0xFF5E0044, 0x00003F00U, 0x00000300U);
+	psu_mask_write(0xFF5E0028, 0x8000FFFFU, 0x00000000U);
 	psu_mask_write(0xFD1A0024, 0xFE7FEDEFU, 0x7E4B0C62U);
-	psu_mask_write(0xFD1A0020, 0x00717F00U, 0x00014200U);
+	psu_mask_write(0xFD1A0020, 0x00717F00U, 0x00014800U);
 	psu_mask_write(0xFD1A0020, 0x00000008U, 0x00000008U);
 	psu_mask_write(0xFD1A0020, 0x00000001U, 0x00000001U);
 	psu_mask_write(0xFD1A0020, 0x00000001U, 0x00000000U);
 	mask_poll(0xFD1A0044, 0x00000001U);
 	psu_mask_write(0xFD1A0020, 0x00000008U, 0x00000000U);
 	psu_mask_write(0xFD1A0048, 0x00003F00U, 0x00000300U);
+	psu_mask_write(0xFD1A0028, 0x8000FFFFU, 0x00000000U);
 	psu_mask_write(0xFD1A0030, 0xFE7FEDEFU, 0x7E4B0C62U);
-	psu_mask_write(0xFD1A002C, 0x00717F00U, 0x00014800U);
+	psu_mask_write(0xFD1A002C, 0x00717F00U, 0x00014000U);
 	psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000008U);
 	psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000001U);
 	psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000000U);
 	mask_poll(0xFD1A0044, 0x00000002U);
 	psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000000U);
 	psu_mask_write(0xFD1A004C, 0x00003F00U, 0x00000300U);
+	psu_mask_write(0xFD1A0034, 0x8000FFFFU, 0x00000000U);
 	psu_mask_write(0xFD1A003C, 0xFE7FEDEFU, 0x7E4B0C62U);
-	psu_mask_write(0xFD1A0038, 0x00717F00U, 0x00014000U);
+	psu_mask_write(0xFD1A0038, 0x00717F00U, 0x00014700U);
 	psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000008U);
 	psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000001U);
 	psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000000U);
 	mask_poll(0xFD1A0044, 0x00000004U);
 	psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000000U);
-	psu_mask_write(0xFD1A0050, 0x00003F00U, 0x00000200U);
+	psu_mask_write(0xFD1A0050, 0x00003F00U, 0x00000300U);
+	psu_mask_write(0xFD1A0040, 0x8000FFFFU, 0x00000000U);
 
 	return 1;
 }
 
 static unsigned long psu_clock_init_data(void)
 {
+	psu_mask_write(0xFF5E0054, 0x063F3F07U, 0x06010C00U);
+	psu_mask_write(0xFF180308, 0x00000060U, 0x00000060U);
+	psu_mask_write(0xFF5E0100, 0x013F3F07U, 0x01010600U);
+	psu_mask_write(0xFF5E0060, 0x023F3F07U, 0x02010600U);
+	psu_mask_write(0xFF5E004C, 0x023F3F07U, 0x020F0500U);
 	psu_mask_write(0xFF5E0068, 0x013F3F07U, 0x01010C00U);
-	psu_mask_write(0xFF5E0070, 0x013F3F07U, 0x01010502U);
+	psu_mask_write(0xFF5E0070, 0x013F3F07U, 0x01010800U);
 	psu_mask_write(0xFF18030C, 0x00020000U, 0x00000000U);
 	psu_mask_write(0xFF5E0074, 0x013F3F07U, 0x01010F00U);
 	psu_mask_write(0xFF5E0120, 0x013F3F07U, 0x01010F00U);
 	psu_mask_write(0xFF5E0090, 0x01003F07U, 0x01000302U);
-	psu_mask_write(0xFF5E009C, 0x01003F07U, 0x01000400U);
-	psu_mask_write(0xFF5E00A4, 0x01003F07U, 0x01000900U);
+	psu_mask_write(0xFF5E009C, 0x01003F07U, 0x01000602U);
+	psu_mask_write(0xFF5E00A4, 0x01003F07U, 0x01000800U);
 	psu_mask_write(0xFF5E00A8, 0x01003F07U, 0x01000302U);
 	psu_mask_write(0xFF5E00AC, 0x01003F07U, 0x01000F02U);
 	psu_mask_write(0xFF5E00B0, 0x01003F07U, 0x01000602U);
 	psu_mask_write(0xFF5E00B8, 0x01003F07U, 0x01000302U);
-	psu_mask_write(0xFF5E00C0, 0x013F3F07U, 0x01010A02U);
-	psu_mask_write(0xFF5E00C4, 0x013F3F07U, 0x01010402U);
-	psu_mask_write(0xFF5E00C8, 0x013F3F07U, 0x01010802U);
+	psu_mask_write(0xFF5E00C0, 0x013F3F07U, 0x01010F00U);
+	psu_mask_write(0xFF5E00C4, 0x013F3F07U, 0x01010400U);
+	psu_mask_write(0xFF5E00C8, 0x013F3F07U, 0x01010C00U);
+	psu_mask_write(0xFF5E00CC, 0x013F3F07U, 0x01010400U);
 	psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01011D02U);
 	psu_mask_write(0xFF5E0104, 0x00000007U, 0x00000000U);
-	psu_mask_write(0xFF5E0128, 0x01003F07U, 0x01000104U);
+	psu_mask_write(0xFF5E0128, 0x01003F07U, 0x01000F00U);
 	psu_mask_write(0xFD1A0060, 0x03003F07U, 0x03000100U);
 	psu_mask_write(0xFD1A0068, 0x01003F07U, 0x01000200U);
-	psu_mask_write(0xFD1A0080, 0x00003F07U, 0x00000600U);
-	psu_mask_write(0xFD1A0084, 0x07003F07U, 0x07000203U);
-	psu_mask_write(0xFD1A00B8, 0x01003F07U, 0x01000203U);
-	psu_mask_write(0xFD1A00BC, 0x01003F07U, 0x01000203U);
-	psu_mask_write(0xFD1A00C0, 0x01003F07U, 0x01000202U);
+	psu_mask_write(0xFD1A0080, 0x00003F07U, 0x00000200U);
+	psu_mask_write(0xFD1A00B8, 0x01003F07U, 0x01000200U);
+	psu_mask_write(0xFD1A00BC, 0x01003F07U, 0x01000200U);
+	psu_mask_write(0xFD1A00C0, 0x01003F07U, 0x01000203U);
 	psu_mask_write(0xFD1A00C4, 0x01003F07U, 0x01000502U);
 	psu_mask_write(0xFD1A00F8, 0x00003F07U, 0x00000200U);
 	psu_mask_write(0xFF180380, 0x000000FFU, 0x00000000U);
@@ -94,50 +105,50 @@
 	psu_mask_write(0xFD1A0108, 0x00000008U, 0x00000008U);
 	psu_mask_write(0xFD070000, 0xE30FBE3DU, 0x81040001U);
 	psu_mask_write(0xFD070010, 0x8000F03FU, 0x00000030U);
-	psu_mask_write(0xFD070020, 0x000003F3U, 0x00000100U);
+	psu_mask_write(0xFD070020, 0x000003F3U, 0x00000200U);
 	psu_mask_write(0xFD070024, 0xFFFFFFFFU, 0x00800000U);
 	psu_mask_write(0xFD070030, 0x0000007FU, 0x00000000U);
-	psu_mask_write(0xFD070034, 0x00FFFF1FU, 0x00403210U);
+	psu_mask_write(0xFD070034, 0x00FFFF1FU, 0x00408410U);
 	psu_mask_write(0xFD070050, 0x00F1F1F4U, 0x00210000U);
 	psu_mask_write(0xFD070054, 0x0FFF0FFFU, 0x00000000U);
 	psu_mask_write(0xFD070060, 0x00000073U, 0x00000001U);
-	psu_mask_write(0xFD070064, 0x0FFF83FFU, 0x00308034U);
+	psu_mask_write(0xFD070064, 0x0FFF83FFU, 0x0081808BU);
 	psu_mask_write(0xFD070070, 0x00000017U, 0x00000010U);
 	psu_mask_write(0xFD070074, 0x00000003U, 0x00000000U);
 	psu_mask_write(0xFD0700C4, 0x3F000391U, 0x10000200U);
 	psu_mask_write(0xFD0700C8, 0x01FF1F3FU, 0x0030051FU);
-	psu_mask_write(0xFD0700D0, 0xC3FF0FFFU, 0x00020063U);
-	psu_mask_write(0xFD0700D4, 0x01FF7F0FU, 0x00290000U);
-	psu_mask_write(0xFD0700D8, 0x0000FF0FU, 0x00000E05U);
-	psu_mask_write(0xFD0700DC, 0xFFFFFFFFU, 0x05200004U);
-	psu_mask_write(0xFD0700E0, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD0700D0, 0xC3FF0FFFU, 0x00020106U);
+	psu_mask_write(0xFD0700D4, 0x01FF7F0FU, 0x006A0000U);
+	psu_mask_write(0xFD0700D8, 0x0000FF0FU, 0x00002305U);
+	psu_mask_write(0xFD0700DC, 0xFFFFFFFFU, 0x01240004U);
+	psu_mask_write(0xFD0700E0, 0xFFFFFFFFU, 0x00280000U);
 	psu_mask_write(0xFD0700E4, 0x00FF03FFU, 0x00110004U);
 	psu_mask_write(0xFD0700E8, 0xFFFFFFFFU, 0x00000000U);
 	psu_mask_write(0xFD0700EC, 0xFFFF0000U, 0x00000000U);
 	psu_mask_write(0xFD0700F0, 0x0000003FU, 0x00000010U);
 	psu_mask_write(0xFD0700F4, 0x00000FFFU, 0x0000066FU);
-	psu_mask_write(0xFD070100, 0x7F3F7F3FU, 0x07080D07U);
-	psu_mask_write(0xFD070104, 0x001F1F7FU, 0x0005020BU);
-	psu_mask_write(0xFD070108, 0x3F3F3F3FU, 0x03030607U);
-	psu_mask_write(0xFD07010C, 0x3FF3F3FFU, 0x00502006U);
-	psu_mask_write(0xFD070110, 0x1F0F0F1FU, 0x13020206U);
-	psu_mask_write(0xFD070114, 0x0F0F3F1FU, 0x03030202U);
-	psu_mask_write(0xFD070118, 0x0F0F000FU, 0x01010003U);
-	psu_mask_write(0xFD07011C, 0x00000F0FU, 0x00000303U);
-	psu_mask_write(0xFD070120, 0x7F7F7F7FU, 0x02020909U);
+	psu_mask_write(0xFD070100, 0x7F3F7F3FU, 0x0F102412U);
+	psu_mask_write(0xFD070104, 0x001F1F7FU, 0x000D041AU);
+	psu_mask_write(0xFD070108, 0x3F3F3F3FU, 0x0507070BU);
+	psu_mask_write(0xFD07010C, 0x3FF3F3FFU, 0x00502008U);
+	psu_mask_write(0xFD070110, 0x1F0F0F1FU, 0x07020408U);
+	psu_mask_write(0xFD070114, 0x0F0F3F1FU, 0x06060403U);
+	psu_mask_write(0xFD070118, 0x0F0F000FU, 0x01010004U);
+	psu_mask_write(0xFD07011C, 0x00000F0FU, 0x00000606U);
+	psu_mask_write(0xFD070120, 0x7F7F7F7FU, 0x03030909U);
 	psu_mask_write(0xFD070124, 0x40070F3FU, 0x0004040DU);
 	psu_mask_write(0xFD07012C, 0x7F1F031FU, 0x440C011CU);
 	psu_mask_write(0xFD070130, 0x00030F1FU, 0x00020608U);
-	psu_mask_write(0xFD070180, 0xF7FF03FFU, 0x80800020U);
-	psu_mask_write(0xFD070184, 0x3FFFFFFFU, 0x02009896U);
-	psu_mask_write(0xFD070190, 0x1FBFBF3FU, 0x04828202U);
+	psu_mask_write(0xFD070180, 0xF7FF03FFU, 0x80AB002BU);
+	psu_mask_write(0xFD070184, 0x3FFFFFFFU, 0x020196E6U);
+	psu_mask_write(0xFD070190, 0x1FBFBF3FU, 0x048A8207U);
 	psu_mask_write(0xFD070194, 0xF31F0F0FU, 0x00020304U);
 	psu_mask_write(0xFD070198, 0x0FF1F1F1U, 0x07000101U);
 	psu_mask_write(0xFD07019C, 0x000000F1U, 0x00000021U);
 	psu_mask_write(0xFD0701A0, 0xC3FF03FFU, 0x00400003U);
 	psu_mask_write(0xFD0701A4, 0x00FF00FFU, 0x00C800FFU);
 	psu_mask_write(0xFD0701B0, 0x00000007U, 0x00000000U);
-	psu_mask_write(0xFD0701B4, 0x00003F3FU, 0x00000000U);
+	psu_mask_write(0xFD0701B4, 0x00003F3FU, 0x00000805U);
 	psu_mask_write(0xFD0701C0, 0x00000007U, 0x00000000U);
 	psu_mask_write(0xFD070200, 0x0000001FU, 0x0000001FU);
 	psu_mask_write(0xFD070204, 0x001F1F1FU, 0x00080808U);
@@ -151,7 +162,7 @@
 	psu_mask_write(0xFD070224, 0x0F0F0F0FU, 0x07070707U);
 	psu_mask_write(0xFD070228, 0x0F0F0F0FU, 0x07070707U);
 	psu_mask_write(0xFD07022C, 0x0000000FU, 0x00000007U);
-	psu_mask_write(0xFD070240, 0x0F1F0F7CU, 0x06000604U);
+	psu_mask_write(0xFD070240, 0x0F1F0F7CU, 0x06000610U);
 	psu_mask_write(0xFD070244, 0x00003333U, 0x00000001U);
 	psu_mask_write(0xFD070250, 0x7FFF3F07U, 0x01002001U);
 	psu_mask_write(0xFD070264, 0xFF00FFFFU, 0x08000040U);
@@ -209,30 +220,30 @@
 	psu_mask_write(0xFD072190, 0x1FBFBF3FU, 0x07828002U);
 	psu_mask_write(0xFD1A0108, 0x0000000CU, 0x00000000U);
 	psu_mask_write(0xFD080010, 0xFFFFFFFFU, 0x07001E00U);
-	psu_mask_write(0xFD080018, 0xFFFFFFFFU, 0x00F05D90U);
+	psu_mask_write(0xFD080018, 0xFFFFFFFFU, 0x00F10010U);
 	psu_mask_write(0xFD08001C, 0xFFFFFFFFU, 0x55AA5480U);
 	psu_mask_write(0xFD080024, 0xFFFFFFFFU, 0x010100F4U);
-	psu_mask_write(0xFD080040, 0xFFFFFFFFU, 0x1900C810U);
-	psu_mask_write(0xFD080044, 0xFFFFFFFFU, 0x4E200708U);
-	psu_mask_write(0xFD080068, 0xFFFFFFFFU, 0x06124000U);
-	psu_mask_write(0xFD080090, 0xFFFFFFFFU, 0x02A04061U);
+	psu_mask_write(0xFD080040, 0xFFFFFFFFU, 0x42C21590U);
+	psu_mask_write(0xFD080044, 0xFFFFFFFFU, 0xD05612C0U);
+	psu_mask_write(0xFD080068, 0xFFFFFFFFU, 0x01100000U);
+	psu_mask_write(0xFD080090, 0xFFFFFFFFU, 0x02A04161U);
 	psu_mask_write(0xFD0800C0, 0xFFFFFFFFU, 0x00000000U);
-	psu_mask_write(0xFD0800C4, 0xFFFFFFFFU, 0x000000DAU);
+	psu_mask_write(0xFD0800C4, 0xFFFFFFFFU, 0x000000E3U);
 	psu_mask_write(0xFD080100, 0xFFFFFFFFU, 0x0800040BU);
-	psu_mask_write(0xFD080110, 0xFFFFFFFFU, 0x040E0A04U);
-	psu_mask_write(0xFD080114, 0xFFFFFFFFU, 0x28100004U);
+	psu_mask_write(0xFD080110, 0xFFFFFFFFU, 0x08240E08U);
+	psu_mask_write(0xFD080114, 0xFFFFFFFFU, 0x28200404U);
 	psu_mask_write(0xFD080118, 0xFFFFFFFFU, 0x000F0200U);
 	psu_mask_write(0xFD08011C, 0xFFFFFFFFU, 0x82000800U);
-	psu_mask_write(0xFD080120, 0xFFFFFFFFU, 0x00682B0AU);
-	psu_mask_write(0xFD080124, 0xFFFFFFFFU, 0x00152504U);
-	psu_mask_write(0xFD080128, 0xFFFFFFFFU, 0x00000506U);
+	psu_mask_write(0xFD080120, 0xFFFFFFFFU, 0x01162B1AU);
+	psu_mask_write(0xFD080124, 0xFFFFFFFFU, 0x00330E08U);
+	psu_mask_write(0xFD080128, 0xFFFFFFFFU, 0x00000A0EU);
 	psu_mask_write(0xFD080140, 0xFFFFFFFFU, 0x08400020U);
 	psu_mask_write(0xFD080144, 0xFFFFFFFFU, 0x00000C80U);
 	psu_mask_write(0xFD080150, 0xFFFFFFFFU, 0x00000000U);
 	psu_mask_write(0xFD080154, 0xFFFFFFFFU, 0x00000000U);
-	psu_mask_write(0xFD080180, 0xFFFFFFFFU, 0x00000520U);
+	psu_mask_write(0xFD080180, 0xFFFFFFFFU, 0x00000124U);
 	psu_mask_write(0xFD080184, 0xFFFFFFFFU, 0x00000004U);
-	psu_mask_write(0xFD080188, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080188, 0xFFFFFFFFU, 0x00000028U);
 	psu_mask_write(0xFD08018C, 0xFFFFFFFFU, 0x00000000U);
 	psu_mask_write(0xFD080190, 0xFFFFFFFFU, 0x00000000U);
 	psu_mask_write(0xFD080194, 0xFFFFFFFFU, 0x00000000U);
@@ -261,7 +272,7 @@
 	psu_mask_write(0xFD08055C, 0xFFFFFFFFU, 0x00000000U);
 	psu_mask_write(0xFD080560, 0xFFFFFFFFU, 0x00000000U);
 	psu_mask_write(0xFD080564, 0xFFFFFFFFU, 0x00000000U);
-	psu_mask_write(0xFD080680, 0xFFFFFFFFU, 0x0088E858U);
+	psu_mask_write(0xFD080680, 0xFFFFFFFFU, 0x008AA858U);
 	psu_mask_write(0xFD080684, 0xFFFFFFFFU, 0x000077BBU);
 	psu_mask_write(0xFD080694, 0xFFFFFFFFU, 0x01E10210U);
 	psu_mask_write(0xFD080698, 0xFFFFFFFFU, 0x01E10000U);
@@ -281,13 +292,13 @@
 	psu_mask_write(0xFD080900, 0xFFFFFFFFU, 0x40800604U);
 	psu_mask_write(0xFD080904, 0xFFFFFFFFU, 0x00007FFFU);
 	psu_mask_write(0xFD08090C, 0xFFFFFFFFU, 0x3F000008U);
-	psu_mask_write(0xFD080910, 0xFFFFFFFFU, 0x0E00B00CU);
+	psu_mask_write(0xFD080910, 0xFFFFFFFFU, 0x0E00B004U);
 	psu_mask_write(0xFD080914, 0xFFFFFFFFU, 0x09093030U);
 	psu_mask_write(0xFD080918, 0xFFFFFFFFU, 0x09092B2BU);
 	psu_mask_write(0xFD080A00, 0xFFFFFFFFU, 0x40800604U);
 	psu_mask_write(0xFD080A04, 0xFFFFFFFFU, 0x00007FFFU);
 	psu_mask_write(0xFD080A0C, 0xFFFFFFFFU, 0x3F000008U);
-	psu_mask_write(0xFD080A10, 0xFFFFFFFFU, 0x0E00B00CU);
+	psu_mask_write(0xFD080A10, 0xFFFFFFFFU, 0x0E00B004U);
 	psu_mask_write(0xFD080A14, 0xFFFFFFFFU, 0x09093030U);
 	psu_mask_write(0xFD080A18, 0xFFFFFFFFU, 0x09092B2BU);
 	psu_mask_write(0xFD080B00, 0xFFFFFFFFU, 0x40800604U);
@@ -318,7 +329,7 @@
 	psu_mask_write(0xFD080E10, 0xFFFFFFFFU, 0x0E00B00CU);
 	psu_mask_write(0xFD080E14, 0xFFFFFFFFU, 0x09093030U);
 	psu_mask_write(0xFD080E18, 0xFFFFFFFFU, 0x09092B2BU);
-	psu_mask_write(0xFD080F00, 0xFFFFFFFFU, 0x40803660U);
+	psu_mask_write(0xFD080F00, 0xFFFFFFFFU, 0x80803660U);
 	psu_mask_write(0xFD080F04, 0xFFFFFFFFU, 0x55556000U);
 	psu_mask_write(0xFD080F08, 0xFFFFFFFFU, 0xAAAAAAAAU);
 	psu_mask_write(0xFD080F0C, 0xFFFFFFFFU, 0x0029A4A4U);
@@ -326,36 +337,55 @@
 	psu_mask_write(0xFD080F14, 0xFFFFFFFFU, 0x09093030U);
 	psu_mask_write(0xFD080F18, 0xFFFFFFFFU, 0x09092B2BU);
 	psu_mask_write(0xFD081400, 0xFFFFFFFFU, 0x2A019FFEU);
-	psu_mask_write(0xFD081404, 0xFFFFFFFFU, 0x06124000U);
+	psu_mask_write(0xFD081404, 0xFFFFFFFFU, 0x01100000U);
 	psu_mask_write(0xFD08141C, 0xFFFFFFFFU, 0x01264300U);
 	psu_mask_write(0xFD08142C, 0xFFFFFFFFU, 0x00041800U);
 	psu_mask_write(0xFD081430, 0xFFFFFFFFU, 0x70000000U);
 	psu_mask_write(0xFD081440, 0xFFFFFFFFU, 0x2A019FFEU);
-	psu_mask_write(0xFD081444, 0xFFFFFFFFU, 0x06124000U);
+	psu_mask_write(0xFD081444, 0xFFFFFFFFU, 0x01100000U);
 	psu_mask_write(0xFD08145C, 0xFFFFFFFFU, 0x01264300U);
 	psu_mask_write(0xFD08146C, 0xFFFFFFFFU, 0x00041800U);
 	psu_mask_write(0xFD081470, 0xFFFFFFFFU, 0x70000000U);
 	psu_mask_write(0xFD081480, 0xFFFFFFFFU, 0x2A019FFEU);
-	psu_mask_write(0xFD081484, 0xFFFFFFFFU, 0x06124000U);
+	psu_mask_write(0xFD081484, 0xFFFFFFFFU, 0x01100000U);
 	psu_mask_write(0xFD08149C, 0xFFFFFFFFU, 0x01264300U);
 	psu_mask_write(0xFD0814AC, 0xFFFFFFFFU, 0x00041800U);
 	psu_mask_write(0xFD0814B0, 0xFFFFFFFFU, 0x70000000U);
 	psu_mask_write(0xFD0814C0, 0xFFFFFFFFU, 0x2A019FFEU);
-	psu_mask_write(0xFD0814C4, 0xFFFFFFFFU, 0x06124000U);
+	psu_mask_write(0xFD0814C4, 0xFFFFFFFFU, 0x01100000U);
 	psu_mask_write(0xFD0814DC, 0xFFFFFFFFU, 0x01264300U);
 	psu_mask_write(0xFD0814EC, 0xFFFFFFFFU, 0x00041800U);
 	psu_mask_write(0xFD0814F0, 0xFFFFFFFFU, 0x70000000U);
 	psu_mask_write(0xFD081500, 0xFFFFFFFFU, 0x15019FFEU);
-	psu_mask_write(0xFD081504, 0xFFFFFFFFU, 0x06124000U);
-	psu_mask_write(0xFD08151C, 0xFFFFFFFFU, 0x01264300U);
+	psu_mask_write(0xFD081504, 0xFFFFFFFFU, 0x21100000U);
+	psu_mask_write(0xFD08151C, 0xFFFFFFFFU, 0x01266300U);
 	psu_mask_write(0xFD08152C, 0xFFFFFFFFU, 0x00041800U);
-	psu_mask_write(0xFD081530, 0xFFFFFFFFU, 0x70000000U);
-	psu_mask_write(0xFD0817C4, 0xFFFFFFFFU, 0x06124000U);
+	psu_mask_write(0xFD081530, 0xFFFFFFFFU, 0x70400000U);
 	psu_mask_write(0xFD0817DC, 0xFFFFFFFFU, 0x012643C4U);
 
 	return 1;
 }
 
+static unsigned long psu_ddr_qos_init_data(void)
+{
+	psu_mask_write(0xFD360008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD36001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD370008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD37001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD380008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD38001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD390008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD39001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD3A0008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD3A001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD3B0008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD3B001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFF9B0008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFF9B001C, 0x0000000FU, 0x00000000U);
+
+	return 1;
+}
+
 static unsigned long psu_mio_init_data(void)
 {
 	psu_mask_write(0xFF180000, 0x000000FEU, 0x00000002U);
@@ -378,8 +408,20 @@
 	psu_mask_write(0xFF1800C4, 0x000000FEU, 0x00000010U);
 	psu_mask_write(0xFF1800C8, 0x000000FEU, 0x00000010U);
 	psu_mask_write(0xFF1800CC, 0x000000FEU, 0x00000010U);
-	psu_mask_write(0xFF180204, 0x0000007FU, 0x00000002U);
-	psu_mask_write(0xFF180208, 0x000FFF8CU, 0x00003004U);
+	psu_mask_write(0xFF1800D0, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800D4, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800D8, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800DC, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800E0, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800E4, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800E8, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800EC, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800F0, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800F4, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800F8, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800FC, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF180204, 0x00000073U, 0x00000002U);
+	psu_mask_write(0xFF180208, 0xFFFFFF8CU, 0x00B03004U);
 	psu_mask_write(0xFF180138, 0x03FFFFFFU, 0x03FFFFFFU);
 	psu_mask_write(0xFF18013C, 0x03FFFFFFU, 0x03FFFFFFU);
 	psu_mask_write(0xFF180140, 0x03FFFFFFU, 0x00000000U);
@@ -405,35 +447,49 @@
 
 static unsigned long psu_peripherals_pre_init_data(void)
 {
-	psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x00012302U);
+	psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01012302U);
+	psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000001U);
 
 	return 1;
 }
 
 static unsigned long psu_peripherals_init_data(void)
 {
-	psu_mask_write(0xFD1A0100, 0x0000807CU, 0x00000000U);
+	psu_mask_write(0xFD1A0100, 0x00008044U, 0x00000000U);
 	psu_mask_write(0xFF5E0238, 0x001A0000U, 0x00000000U);
 	psu_mask_write(0xFF5E023C, 0x0093C018U, 0x00000000U);
+	psu_mask_write(0xFF5E0230, 0x00000002U, 0x00000000U);
 	psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000000U);
 	psu_mask_write(0xFF180390, 0x00000004U, 0x00000004U);
+	psu_mask_write(0xFF5E023C, 0x00000400U, 0x00000000U);
+	psu_mask_write(0xFF5E023C, 0x00000140U, 0x00000140U);
+	psu_mask_write(0xFF9D0080, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFF9D007C, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFF5E023C, 0x00000140U, 0x00000000U);
 	psu_mask_write(0xFF5E0238, 0x00000040U, 0x00000000U);
 	psu_mask_write(0xFF180310, 0x00008000U, 0x00000000U);
-	psu_mask_write(0xFF180320, 0x33800000U, 0x02800000U);
+	psu_mask_write(0xFF180320, 0x33840000U, 0x02840000U);
 	psu_mask_write(0xFF18031C, 0x7FFE0000U, 0x64500000U);
 	psu_mask_write(0xFF180358, 0x00000008U, 0x00000008U);
 	psu_mask_write(0xFF180324, 0x03C00000U, 0x00000000U);
 	psu_mask_write(0xFF5E0238, 0x00000200U, 0x00000000U);
 	psu_mask_write(0xFF5E0238, 0x00008000U, 0x00000000U);
-	psu_mask_write(0xFF5E0238, 0x00000800U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00007800U, 0x00000000U);
 	psu_mask_write(0xFF5E0238, 0x00000002U, 0x00000000U);
 	psu_mask_write(0xFF5E0238, 0x00040000U, 0x00000000U);
 	psu_mask_write(0xFF4B0024, 0x000000FFU, 0x000000FFU);
 	psu_mask_write(0xFFCA5000, 0x00001FFFU, 0x00000000U);
 	psu_mask_write(0xFD5C0060, 0x000F000FU, 0x00000000U);
 	psu_mask_write(0xFFA60040, 0x80000000U, 0x80000000U);
-	psu_mask_write(0xFF260020, 0xFFFFFFFFU, 0x01FC9F08U);
+	psu_mask_write(0xFF260020, 0xFFFFFFFFU, 0x05F5E100U);
 	psu_mask_write(0xFF260000, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
+
+	mask_delay(1);
+	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000002U);
+
+	mask_delay(5);
+	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
 
 	return 1;
 }
@@ -459,15 +515,21 @@
 
 		while ((Xil_In32(0xFD080030) & 0x1) != 1)
 			;
-
-		pll_locked = (Xil_In32(0xFD080030) & 0x80000000) >> 31;
-		pll_locked &= (Xil_In32(0xFD0807E0) & 0x10000) >> 16;
+		pll_locked = (Xil_In32(0xFD080030) & 0x80000000)
+		    >> 31;
+		pll_locked &= (Xil_In32(0xFD0807E0) & 0x10000)
+		    >> 16;
 		pll_locked &= (Xil_In32(0xFD0809E0) & 0x10000) >> 16;
-		pll_locked &= (Xil_In32(0xFD080BE0) & 0x10000) >> 16;
-		pll_locked &= (Xil_In32(0xFD080DE0) & 0x10000) >> 16;
+		pll_locked &= (Xil_In32(0xFD080BE0) & 0x10000)
+		    >> 16;
+		pll_locked &= (Xil_In32(0xFD080DE0) & 0x10000)
+		    >> 16;
 		pll_retry--;
 	}
-	Xil_Out32(0xFD0800C0, Xil_In32(0xFD0800C0) | (pll_retry << 16));
+	Xil_Out32(0xFD0800C4, Xil_In32(0xFD0800C4) | (pll_retry << 16));
+	if (!pll_locked)
+		return 0;
+
 	Xil_Out32(0xFD080004U, 0x00040063U);
 
 	while ((Xil_In32(0xFD080030U) & 0x0000000FU) != 0x0000000FU)
@@ -485,7 +547,10 @@
 	regval = Xil_In32(0xFD080030);
 	while (regval != 0x80000FFF)
 		regval = Xil_In32(0xFD080030);
-	Xil_Out32(0xFD070180U, 0x00800020U);
+	regval = ((Xil_In32(0xFD080030) & 0x1FFF0000) >> 18);
+	if (regval != 0)
+		return 0;
+	Xil_Out32(0xFD070180U, 0x00AB002BU);
 	Xil_Out32(0xFD070060U, 0x00000000U);
 	prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000000U);
 
@@ -511,6 +576,7 @@
 	init_peripheral();
 
 	status &= psu_afi_config();
+	psu_ddr_qos_init_data();
 
 	if (status == 0)
 		return 1;
diff --git a/board/xilinx/zynqmp/zynqmp-zcu208-revA/psu_init_gpl.c b/board/xilinx/zynqmp/zynqmp-zcu208-revA/psu_init_gpl.c
new file mode 100644
index 0000000..f07e60a
--- /dev/null
+++ b/board/xilinx/zynqmp/zynqmp-zcu208-revA/psu_init_gpl.c
@@ -0,0 +1,1880 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (c) Copyright 2015 Xilinx, Inc. All rights reserved.
+ */
+
+#include <asm/arch/psu_init_gpl.h>
+#include <xil_io.h>
+
+static int serdes_illcalib(u32 lane3_protocol, u32 lane3_rate,
+			   u32 lane2_protocol, u32 lane2_rate,
+			   u32 lane1_protocol, u32 lane1_rate,
+			   u32 lane0_protocol, u32 lane0_rate);
+
+static unsigned long psu_pll_init_data(void)
+{
+	psu_mask_write(0xFF5E0034, 0xFE7FEDEFU, 0x7E4B0C82U);
+	psu_mask_write(0xFF5E0030, 0x00717F00U, 0x00015A00U);
+	psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000000U);
+	mask_poll(0xFF5E0040, 0x00000002U);
+	psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFF5E0048, 0x00003F00U, 0x00000300U);
+	psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01012300U);
+	psu_mask_write(0xFF5E0024, 0xFE7FEDEFU, 0x7E4B0C82U);
+	psu_mask_write(0xFF5E0020, 0x00717F00U, 0x00015A00U);
+	psu_mask_write(0xFF5E0020, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFF5E0020, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFF5E0020, 0x00000001U, 0x00000000U);
+	mask_poll(0xFF5E0040, 0x00000001U);
+	psu_mask_write(0xFF5E0020, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFF5E0044, 0x00003F00U, 0x00000300U);
+	psu_mask_write(0xFD1A0024, 0xFE7FEDEFU, 0x7E4B0C62U);
+	psu_mask_write(0xFD1A0020, 0x00717F00U, 0x00014800U);
+	psu_mask_write(0xFD1A0020, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFD1A0020, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD1A0020, 0x00000001U, 0x00000000U);
+	mask_poll(0xFD1A0044, 0x00000001U);
+	psu_mask_write(0xFD1A0020, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFD1A0048, 0x00003F00U, 0x00000300U);
+	psu_mask_write(0xFD1A0030, 0xFE7FEDEFU, 0x7E4B0C62U);
+	psu_mask_write(0xFD1A002C, 0x00717F00U, 0x00013F00U);
+	psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000000U);
+	mask_poll(0xFD1A0044, 0x00000002U);
+	psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFD1A004C, 0x00003F00U, 0x00000200U);
+	psu_mask_write(0xFD1A003C, 0xFE7FEDEFU, 0x7E4B0C82U);
+	psu_mask_write(0xFD1A0038, 0x00717F00U, 0x00015A00U);
+	psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000000U);
+	mask_poll(0xFD1A0044, 0x00000004U);
+	psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFD1A0050, 0x00003F00U, 0x00000300U);
+
+	return 1;
+}
+
+static unsigned long psu_clock_init_data(void)
+{
+	psu_mask_write(0xFF5E005C, 0x063F3F07U, 0x06010C00U);
+	psu_mask_write(0xFF5E0100, 0x013F3F07U, 0x01010600U);
+	psu_mask_write(0xFF5E0060, 0x023F3F07U, 0x02010600U);
+	psu_mask_write(0xFF5E004C, 0x023F3F07U, 0x02031900U);
+	psu_mask_write(0xFF5E0068, 0x013F3F07U, 0x01010C00U);
+	psu_mask_write(0xFF5E0070, 0x013F3F07U, 0x01010800U);
+	psu_mask_write(0xFF18030C, 0x00020000U, 0x00000000U);
+	psu_mask_write(0xFF5E0074, 0x013F3F07U, 0x01010F00U);
+	psu_mask_write(0xFF5E0120, 0x013F3F07U, 0x01010F00U);
+	psu_mask_write(0xFF5E0124, 0x013F3F07U, 0x01010F00U);
+	psu_mask_write(0xFF5E0090, 0x01003F07U, 0x01000302U);
+	psu_mask_write(0xFF5E009C, 0x01003F07U, 0x01000602U);
+	psu_mask_write(0xFF5E00A4, 0x01003F07U, 0x01000800U);
+	psu_mask_write(0xFF5E00A8, 0x01003F07U, 0x01000302U);
+	psu_mask_write(0xFF5E00AC, 0x01003F07U, 0x01000F02U);
+	psu_mask_write(0xFF5E00B0, 0x01003F07U, 0x01000602U);
+	psu_mask_write(0xFF5E00B8, 0x01003F07U, 0x01000302U);
+	psu_mask_write(0xFF5E00C0, 0x013F3F07U, 0x01010F00U);
+	psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01011E02U);
+	psu_mask_write(0xFF5E0104, 0x00000007U, 0x00000000U);
+	psu_mask_write(0xFF5E0128, 0x01003F07U, 0x01000F00U);
+	psu_mask_write(0xFD1A00A0, 0x01003F07U, 0x01000200U);
+	psu_mask_write(0xFD1A0060, 0x03003F07U, 0x03000100U);
+	psu_mask_write(0xFD1A0068, 0x01003F07U, 0x01000200U);
+	psu_mask_write(0xFD1A0080, 0x00003F07U, 0x00000200U);
+	psu_mask_write(0xFD1A00B8, 0x01003F07U, 0x01000200U);
+	psu_mask_write(0xFD1A00BC, 0x01003F07U, 0x01000200U);
+	psu_mask_write(0xFD1A00C0, 0x01003F07U, 0x01000203U);
+	psu_mask_write(0xFD1A00C4, 0x01003F07U, 0x01000502U);
+	psu_mask_write(0xFD1A00F8, 0x00003F07U, 0x00000200U);
+	psu_mask_write(0xFF180380, 0x000000FFU, 0x00000000U);
+	psu_mask_write(0xFD610100, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFF180300, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFF410050, 0x00000001U, 0x00000000U);
+
+	return 1;
+}
+
+static unsigned long psu_ddr_init_data(void)
+{
+	psu_mask_write(0xFD1A0108, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFD070000, 0xE30FBE3DU, 0x81040010U);
+	psu_mask_write(0xFD070010, 0x8000F03FU, 0x00000030U);
+	psu_mask_write(0xFD070020, 0x000003F3U, 0x00000200U);
+	psu_mask_write(0xFD070024, 0xFFFFFFFFU, 0x00800000U);
+	psu_mask_write(0xFD070030, 0x0000007FU, 0x00000000U);
+	psu_mask_write(0xFD070034, 0x00FFFF1FU, 0x00408210U);
+	psu_mask_write(0xFD070050, 0x00F1F1F4U, 0x00210000U);
+	psu_mask_write(0xFD070054, 0x0FFF0FFFU, 0x00000000U);
+	psu_mask_write(0xFD070060, 0x00000073U, 0x00000001U);
+	psu_mask_write(0xFD070064, 0x0FFF83FFU, 0x007F80B8U);
+	psu_mask_write(0xFD070070, 0x00000017U, 0x00000010U);
+	psu_mask_write(0xFD070074, 0x00000003U, 0x00000000U);
+	psu_mask_write(0xFD0700C4, 0x3F000391U, 0x10000200U);
+	psu_mask_write(0xFD0700C8, 0x01FF1F3FU, 0x0040051FU);
+	psu_mask_write(0xFD0700D0, 0xC3FF0FFFU, 0x00020102U);
+	psu_mask_write(0xFD0700D4, 0x01FF7F0FU, 0x00020000U);
+	psu_mask_write(0xFD0700D8, 0x0000FF0FU, 0x00002205U);
+	psu_mask_write(0xFD0700DC, 0xFFFFFFFFU, 0x07300301U);
+	psu_mask_write(0xFD0700E0, 0xFFFFFFFFU, 0x00100200U);
+	psu_mask_write(0xFD0700E4, 0x00FF03FFU, 0x00210004U);
+	psu_mask_write(0xFD0700E8, 0xFFFFFFFFU, 0x000006C0U);
+	psu_mask_write(0xFD0700EC, 0xFFFF0000U, 0x08190000U);
+	psu_mask_write(0xFD0700F0, 0x0000003FU, 0x00000010U);
+	psu_mask_write(0xFD0700F4, 0x00000FFFU, 0x0000066FU);
+	psu_mask_write(0xFD070100, 0x7F3F7F3FU, 0x0F102311U);
+	psu_mask_write(0xFD070104, 0x001F1F7FU, 0x00040419U);
+	psu_mask_write(0xFD070108, 0x3F3F3F3FU, 0x0608070CU);
+	psu_mask_write(0xFD07010C, 0x3FF3F3FFU, 0x0050400CU);
+	psu_mask_write(0xFD070110, 0x1F0F0F1FU, 0x08030409U);
+	psu_mask_write(0xFD070114, 0x0F0F3F1FU, 0x06060403U);
+	psu_mask_write(0xFD070118, 0x0F0F000FU, 0x01010004U);
+	psu_mask_write(0xFD07011C, 0x00000F0FU, 0x00000606U);
+	psu_mask_write(0xFD070120, 0x7F7F7F7FU, 0x04040D07U);
+	psu_mask_write(0xFD070124, 0x40070F3FU, 0x00020309U);
+	psu_mask_write(0xFD07012C, 0x7F1F031FU, 0x1207010EU);
+	psu_mask_write(0xFD070130, 0x00030F1FU, 0x00020608U);
+	psu_mask_write(0xFD070180, 0xF7FF03FFU, 0x81000040U);
+	psu_mask_write(0xFD070184, 0x3FFFFFFFU, 0x0201908AU);
+	psu_mask_write(0xFD070190, 0x1FBFBF3FU, 0x048B8208U);
+	psu_mask_write(0xFD070194, 0xF31F0F0FU, 0x00030304U);
+	psu_mask_write(0xFD070198, 0x0FF1F1F1U, 0x07000101U);
+	psu_mask_write(0xFD07019C, 0x000000F1U, 0x00000021U);
+	psu_mask_write(0xFD0701A0, 0xC3FF03FFU, 0x00400003U);
+	psu_mask_write(0xFD0701A4, 0x00FF00FFU, 0x00C800FFU);
+	psu_mask_write(0xFD0701B0, 0x00000007U, 0x00000000U);
+	psu_mask_write(0xFD0701B4, 0x00003F3FU, 0x00000906U);
+	psu_mask_write(0xFD0701C0, 0x00000007U, 0x00000001U);
+	psu_mask_write(0xFD070200, 0x0000001FU, 0x0000001FU);
+	psu_mask_write(0xFD070204, 0x001F1F1FU, 0x001F0909U);
+	psu_mask_write(0xFD070208, 0x0F0F0F0FU, 0x01010100U);
+	psu_mask_write(0xFD07020C, 0x0F0F0F0FU, 0x01010101U);
+	psu_mask_write(0xFD070210, 0x00000F0FU, 0x00000F0FU);
+	psu_mask_write(0xFD070214, 0x0F0F0F0FU, 0x070F0707U);
+	psu_mask_write(0xFD070218, 0x8F0F0F0FU, 0x07070707U);
+	psu_mask_write(0xFD07021C, 0x00000F0FU, 0x00000F0FU);
+	psu_mask_write(0xFD070220, 0x00001F1FU, 0x00001F01U);
+	psu_mask_write(0xFD070224, 0x0F0F0F0FU, 0x07070707U);
+	psu_mask_write(0xFD070228, 0x0F0F0F0FU, 0x07070707U);
+	psu_mask_write(0xFD07022C, 0x0000000FU, 0x00000007U);
+	psu_mask_write(0xFD070240, 0x0F1F0F7CU, 0x0600060CU);
+	psu_mask_write(0xFD070244, 0x00003333U, 0x00000001U);
+	psu_mask_write(0xFD070250, 0x7FFF3F07U, 0x01002001U);
+	psu_mask_write(0xFD070264, 0xFF00FFFFU, 0x08000040U);
+	psu_mask_write(0xFD07026C, 0xFF00FFFFU, 0x08000040U);
+	psu_mask_write(0xFD070280, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD070284, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD070288, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD07028C, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD070290, 0x0000FFFFU, 0x00000000U);
+	psu_mask_write(0xFD070294, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD070300, 0x00000011U, 0x00000000U);
+	psu_mask_write(0xFD07030C, 0x80000033U, 0x00000000U);
+	psu_mask_write(0xFD070320, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFD070400, 0x00000111U, 0x00000001U);
+	psu_mask_write(0xFD070404, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070408, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070490, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD070494, 0x0033000FU, 0x0020000BU);
+	psu_mask_write(0xFD070498, 0x07FF07FFU, 0x00000000U);
+	psu_mask_write(0xFD0704B4, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD0704B8, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070540, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD070544, 0x03330F0FU, 0x02000B03U);
+	psu_mask_write(0xFD070548, 0x07FF07FFU, 0x00000000U);
+	psu_mask_write(0xFD070564, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070568, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD0705F0, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD0705F4, 0x03330F0FU, 0x02000B03U);
+	psu_mask_write(0xFD0705F8, 0x07FF07FFU, 0x00000000U);
+	psu_mask_write(0xFD070614, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070618, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD0706A0, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD0706A4, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD0706A8, 0x07FF07FFU, 0x0000004FU);
+	psu_mask_write(0xFD0706AC, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD0706B0, 0x000007FFU, 0x0000004FU);
+	psu_mask_write(0xFD0706C4, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD0706C8, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070750, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD070754, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD070758, 0x07FF07FFU, 0x0000004FU);
+	psu_mask_write(0xFD07075C, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD070760, 0x000007FFU, 0x0000004FU);
+	psu_mask_write(0xFD070774, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070778, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070800, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD070804, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD070808, 0x07FF07FFU, 0x0000004FU);
+	psu_mask_write(0xFD07080C, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD070810, 0x000007FFU, 0x0000004FU);
+	psu_mask_write(0xFD070F04, 0x000001FFU, 0x00000000U);
+	psu_mask_write(0xFD070F08, 0x000000FFU, 0x00000000U);
+	psu_mask_write(0xFD070F0C, 0x000001FFU, 0x00000010U);
+	psu_mask_write(0xFD070F10, 0x000000FFU, 0x0000000FU);
+	psu_mask_write(0xFD072190, 0x1FBFBF3FU, 0x07828002U);
+	psu_mask_write(0xFD1A0108, 0x0000000CU, 0x00000000U);
+	psu_mask_write(0xFD080010, 0xFFFFFFFFU, 0x07001E00U);
+	psu_mask_write(0xFD080018, 0xFFFFFFFFU, 0x00F0FC00U);
+	psu_mask_write(0xFD08001C, 0xFFFFFFFFU, 0x55AA5480U);
+	psu_mask_write(0xFD080024, 0xFFFFFFFFU, 0x010100F4U);
+	psu_mask_write(0xFD080040, 0xFFFFFFFFU, 0x41A20D10U);
+	psu_mask_write(0xFD080044, 0xFFFFFFFFU, 0xCD141275U);
+	psu_mask_write(0xFD080068, 0xFFFFFFFFU, 0x01100000U);
+	psu_mask_write(0xFD080090, 0xFFFFFFFFU, 0x02A04161U);
+	psu_mask_write(0xFD0800C0, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD0800C4, 0xFFFFFFFFU, 0x000000E3U);
+	psu_mask_write(0xFD080100, 0xFFFFFFFFU, 0x0800040CU);
+	psu_mask_write(0xFD080110, 0xFFFFFFFFU, 0x07220F08U);
+	psu_mask_write(0xFD080114, 0xFFFFFFFFU, 0x28200008U);
+	psu_mask_write(0xFD080118, 0xFFFFFFFFU, 0x000F0300U);
+	psu_mask_write(0xFD08011C, 0xFFFFFFFFU, 0x83000800U);
+	psu_mask_write(0xFD080120, 0xFFFFFFFFU, 0x01702B07U);
+	psu_mask_write(0xFD080124, 0xFFFFFFFFU, 0x00310F08U);
+	psu_mask_write(0xFD080128, 0xFFFFFFFFU, 0x00000B0FU);
+	psu_mask_write(0xFD080140, 0xFFFFFFFFU, 0x08400020U);
+	psu_mask_write(0xFD080144, 0xFFFFFFFFU, 0x00000C80U);
+	psu_mask_write(0xFD080150, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080154, 0xFFFFFFFFU, 0x00000200U);
+	psu_mask_write(0xFD080180, 0xFFFFFFFFU, 0x00000630U);
+	psu_mask_write(0xFD080184, 0xFFFFFFFFU, 0x00000301U);
+	psu_mask_write(0xFD080188, 0xFFFFFFFFU, 0x00000010U);
+	psu_mask_write(0xFD08018C, 0xFFFFFFFFU, 0x00000200U);
+	psu_mask_write(0xFD080190, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080194, 0xFFFFFFFFU, 0x000006C0U);
+	psu_mask_write(0xFD080198, 0xFFFFFFFFU, 0x00000819U);
+	psu_mask_write(0xFD0801AC, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD0801B0, 0xFFFFFFFFU, 0x0000004DU);
+	psu_mask_write(0xFD0801B4, 0xFFFFFFFFU, 0x00000008U);
+	psu_mask_write(0xFD0801B8, 0xFFFFFFFFU, 0x0000004DU);
+	psu_mask_write(0xFD0801D8, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080200, 0xFFFFFFFFU, 0x800091C7U);
+	psu_mask_write(0xFD080204, 0xFFFFFFFFU, 0x00010236U);
+	psu_mask_write(0xFD080240, 0xFFFFFFFFU, 0x00141054U);
+	psu_mask_write(0xFD080250, 0xFFFFFFFFU, 0x00088000U);
+	psu_mask_write(0xFD080414, 0xFFFFFFFFU, 0x12341000U);
+	psu_mask_write(0xFD0804F4, 0xFFFFFFFFU, 0x00000005U);
+	psu_mask_write(0xFD080500, 0xFFFFFFFFU, 0x30000028U);
+	psu_mask_write(0xFD080508, 0xFFFFFFFFU, 0x0A000000U);
+	psu_mask_write(0xFD08050C, 0xFFFFFFFFU, 0x00000009U);
+	psu_mask_write(0xFD080510, 0xFFFFFFFFU, 0x0A000000U);
+	psu_mask_write(0xFD080520, 0xFFFFFFFFU, 0x0300B0CEU);
+	psu_mask_write(0xFD080528, 0xFFFFFFFFU, 0xF9032019U);
+	psu_mask_write(0xFD08052C, 0xFFFFFFFFU, 0x07F001E3U);
+	psu_mask_write(0xFD080544, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080548, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080558, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD08055C, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080560, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080564, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080680, 0xFFFFFFFFU, 0x008A8A58U);
+	psu_mask_write(0xFD080684, 0xFFFFFFFFU, 0x000079DDU);
+	psu_mask_write(0xFD080694, 0xFFFFFFFFU, 0x01E10210U);
+	psu_mask_write(0xFD080698, 0xFFFFFFFFU, 0x01E10000U);
+	psu_mask_write(0xFD0806A4, 0xFFFFFFFFU, 0x00087BDBU);
+	psu_mask_write(0xFD080700, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080704, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD08070C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080710, 0xFFFFFFFFU, 0x0E00B03CU);
+	psu_mask_write(0xFD080714, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080718, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080800, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080804, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD08080C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080810, 0xFFFFFFFFU, 0x0E00B03CU);
+	psu_mask_write(0xFD080814, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080818, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080900, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080904, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD08090C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080910, 0xFFFFFFFFU, 0x0E00B004U);
+	psu_mask_write(0xFD080914, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080918, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080A00, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080A04, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD080A0C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080A10, 0xFFFFFFFFU, 0x0E00B004U);
+	psu_mask_write(0xFD080A14, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080A18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080B00, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080B04, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD080B08, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080B0C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080B10, 0xFFFFFFFFU, 0x0E00B004U);
+	psu_mask_write(0xFD080B14, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080B18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080C00, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080C04, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD080C08, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080C0C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080C10, 0xFFFFFFFFU, 0x0E00B03CU);
+	psu_mask_write(0xFD080C14, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080C18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080D00, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080D04, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD080D08, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080D0C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080D10, 0xFFFFFFFFU, 0x0E00B004U);
+	psu_mask_write(0xFD080D14, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080D18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080E00, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080E04, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD080E08, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080E0C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080E10, 0xFFFFFFFFU, 0x0E00B03CU);
+	psu_mask_write(0xFD080E14, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080E18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080F00, 0xFFFFFFFFU, 0x80803660U);
+	psu_mask_write(0xFD080F04, 0xFFFFFFFFU, 0x55556000U);
+	psu_mask_write(0xFD080F08, 0xFFFFFFFFU, 0xAAAAAAAAU);
+	psu_mask_write(0xFD080F0C, 0xFFFFFFFFU, 0x0029A4A4U);
+	psu_mask_write(0xFD080F10, 0xFFFFFFFFU, 0x0C00B000U);
+	psu_mask_write(0xFD080F14, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080F18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD081400, 0xFFFFFFFFU, 0x2A019FFEU);
+	psu_mask_write(0xFD081404, 0xFFFFFFFFU, 0x01100000U);
+	psu_mask_write(0xFD08141C, 0xFFFFFFFFU, 0x01264300U);
+	psu_mask_write(0xFD08142C, 0xFFFFFFFFU, 0x00041800U);
+	psu_mask_write(0xFD081430, 0xFFFFFFFFU, 0x70800000U);
+	psu_mask_write(0xFD081440, 0xFFFFFFFFU, 0x2A019FFEU);
+	psu_mask_write(0xFD081444, 0xFFFFFFFFU, 0x01100000U);
+	psu_mask_write(0xFD08145C, 0xFFFFFFFFU, 0x01264300U);
+	psu_mask_write(0xFD08146C, 0xFFFFFFFFU, 0x00041800U);
+	psu_mask_write(0xFD081470, 0xFFFFFFFFU, 0x70800000U);
+	psu_mask_write(0xFD081480, 0xFFFFFFFFU, 0x2A019FFEU);
+	psu_mask_write(0xFD081484, 0xFFFFFFFFU, 0x01100000U);
+	psu_mask_write(0xFD08149C, 0xFFFFFFFFU, 0x01264300U);
+	psu_mask_write(0xFD0814AC, 0xFFFFFFFFU, 0x00041800U);
+	psu_mask_write(0xFD0814B0, 0xFFFFFFFFU, 0x70800000U);
+	psu_mask_write(0xFD0814C0, 0xFFFFFFFFU, 0x2A019FFEU);
+	psu_mask_write(0xFD0814C4, 0xFFFFFFFFU, 0x01100000U);
+	psu_mask_write(0xFD0814DC, 0xFFFFFFFFU, 0x01264300U);
+	psu_mask_write(0xFD0814EC, 0xFFFFFFFFU, 0x00041800U);
+	psu_mask_write(0xFD0814F0, 0xFFFFFFFFU, 0x70800000U);
+	psu_mask_write(0xFD081500, 0xFFFFFFFFU, 0x15019FFEU);
+	psu_mask_write(0xFD081504, 0xFFFFFFFFU, 0x21100000U);
+	psu_mask_write(0xFD08151C, 0xFFFFFFFFU, 0x01266300U);
+	psu_mask_write(0xFD08152C, 0xFFFFFFFFU, 0x00041800U);
+	psu_mask_write(0xFD081530, 0xFFFFFFFFU, 0x70400000U);
+	psu_mask_write(0xFD0817DC, 0xFFFFFFFFU, 0x012643C4U);
+
+	return 1;
+}
+
+static unsigned long psu_ddr_qos_init_data(void)
+{
+	psu_mask_write(0xFD360008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD36001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD370008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD37001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD380008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD38001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD390008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD39001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD3A0008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD3A001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD3B0008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD3B001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFF9B0008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFF9B001C, 0x0000000FU, 0x00000000U);
+
+	return 1;
+}
+
+static unsigned long psu_mio_init_data(void)
+{
+	psu_mask_write(0xFF180000, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180004, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180008, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF18000C, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180010, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180014, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180018, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF18001C, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180020, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180024, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180028, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF18002C, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180030, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180034, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180038, 0x000000FEU, 0x00000040U);
+	psu_mask_write(0xFF18003C, 0x000000FEU, 0x00000040U);
+	psu_mask_write(0xFF180040, 0x000000FEU, 0x00000040U);
+	psu_mask_write(0xFF180044, 0x000000FEU, 0x00000040U);
+	psu_mask_write(0xFF180048, 0x000000FEU, 0x000000C0U);
+	psu_mask_write(0xFF18004C, 0x000000FEU, 0x000000C0U);
+	psu_mask_write(0xFF180050, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180054, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180058, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF18005C, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180060, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180064, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180068, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF18006C, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180070, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180074, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180078, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF18007C, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180080, 0x000000FEU, 0x00000008U);
+	psu_mask_write(0xFF180084, 0x000000FEU, 0x00000008U);
+	psu_mask_write(0xFF180098, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF18009C, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800A0, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800A4, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800A8, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800AC, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF1800B0, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF1800B4, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800B8, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800BC, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800C0, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800C4, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800C8, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800CC, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800D0, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800D4, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800D8, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800DC, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800E0, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800E4, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800E8, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800EC, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800F0, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800F4, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800F8, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800FC, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF180100, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180104, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180108, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF18010C, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180110, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180114, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180118, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF18011C, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180120, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180124, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180128, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF18012C, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180130, 0x000000FEU, 0x000000C0U);
+	psu_mask_write(0xFF180134, 0x000000FEU, 0x000000C0U);
+	psu_mask_write(0xFF180204, 0xFFFFFFFFU, 0x00040000U);
+	psu_mask_write(0xFF180208, 0xFFFFFFFFU, 0x00B02000U);
+	psu_mask_write(0xFF18020C, 0x00003FFFU, 0x00000FC0U);
+	psu_mask_write(0xFF180138, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF18013C, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180140, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF180144, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180148, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF18014C, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF180154, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180158, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF18015C, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF180160, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180164, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180168, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF180170, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180174, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180178, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF18017C, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180180, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180184, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF180200, 0x0000000FU, 0x00000000U);
+
+	return 1;
+}
+
+static unsigned long psu_peripherals_pre_init_data(void)
+{
+	psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01012302U);
+	psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000001U);
+
+	return 1;
+}
+
+static unsigned long psu_peripherals_init_data(void)
+{
+	psu_mask_write(0xFD1A0100, 0x00008046U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x001A0000U, 0x00000000U);
+	psu_mask_write(0xFF5E023C, 0x0093C018U, 0x00000000U);
+	psu_mask_write(0xFF5E0230, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFF180390, 0x00000004U, 0x00000004U);
+	psu_mask_write(0xFF5E023C, 0x00000400U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000040U, 0x00000000U);
+	psu_mask_write(0xFF180310, 0x00008000U, 0x00000000U);
+	psu_mask_write(0xFF180320, 0x33840000U, 0x02840000U);
+	psu_mask_write(0xFF18031C, 0x7FFE0000U, 0x64500000U);
+	psu_mask_write(0xFF180358, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFF180324, 0x03C00000U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000600U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00008000U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00007800U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000002U, 0x00000000U);
+	psu_mask_write(0xFF000034, 0x000000FFU, 0x00000006U);
+	psu_mask_write(0xFF000018, 0x0000FFFFU, 0x0000007CU);
+	psu_mask_write(0xFF000000, 0x000001FFU, 0x00000017U);
+	psu_mask_write(0xFF000004, 0x000003FFU, 0x00000020U);
+	psu_mask_write(0xFF5E0238, 0x00040000U, 0x00000000U);
+	psu_mask_write(0xFF4B0024, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFFCA5000, 0x00001FFFU, 0x00000000U);
+	psu_mask_write(0xFD5C0060, 0x000F000FU, 0x00000000U);
+	psu_mask_write(0xFFA60040, 0x80000000U, 0x80000000U);
+	psu_mask_write(0xFF260020, 0xFFFFFFFFU, 0x05F5DD18U);
+	psu_mask_write(0xFF260000, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
+
+	mask_delay(1);
+	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000002U);
+
+	mask_delay(5);
+	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
+
+	return 1;
+}
+
+static unsigned long psu_serdes_init_data(void)
+{
+	psu_mask_write(0xFD410008, 0x0000001FU, 0x00000008U);
+	psu_mask_write(0xFD41000C, 0x0000001FU, 0x0000000FU);
+	psu_mask_write(0xFD402868, 0x00000080U, 0x00000080U);
+	psu_mask_write(0xFD40286C, 0x00000080U, 0x00000080U);
+	psu_mask_write(0xFD40A094, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD40A368, 0x000000FFU, 0x00000038U);
+	psu_mask_write(0xFD40A36C, 0x00000007U, 0x00000003U);
+	psu_mask_write(0xFD40E368, 0x000000FFU, 0x000000E0U);
+	psu_mask_write(0xFD40E36C, 0x00000007U, 0x00000003U);
+	psu_mask_write(0xFD40A370, 0x000000FFU, 0x000000F4U);
+	psu_mask_write(0xFD40A374, 0x000000FFU, 0x00000031U);
+	psu_mask_write(0xFD40A378, 0x000000FFU, 0x00000002U);
+	psu_mask_write(0xFD40A37C, 0x00000033U, 0x00000030U);
+	psu_mask_write(0xFD40E370, 0x000000FFU, 0x000000C9U);
+	psu_mask_write(0xFD40E374, 0x000000FFU, 0x000000D2U);
+	psu_mask_write(0xFD40E378, 0x000000FFU, 0x00000001U);
+	psu_mask_write(0xFD40E37C, 0x000000B3U, 0x000000B0U);
+	psu_mask_write(0xFD40906C, 0x00000003U, 0x00000003U);
+	psu_mask_write(0xFD4080F4, 0x00000003U, 0x00000003U);
+	psu_mask_write(0xFD40E360, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40D06C, 0x0000000FU, 0x0000000FU);
+	psu_mask_write(0xFD40C0F4, 0x0000000BU, 0x0000000BU);
+	psu_mask_write(0xFD4090CC, 0x00000020U, 0x00000020U);
+	psu_mask_write(0xFD401074, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD405074, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD409074, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD40D074, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD401994, 0x00000007U, 0x00000007U);
+	psu_mask_write(0xFD405994, 0x00000007U, 0x00000007U);
+	psu_mask_write(0xFD40989C, 0x00000080U, 0x00000080U);
+	psu_mask_write(0xFD4098F8, 0x000000FFU, 0x0000001AU);
+	psu_mask_write(0xFD4098FC, 0x000000FFU, 0x0000001AU);
+	psu_mask_write(0xFD409990, 0x000000FFU, 0x00000010U);
+	psu_mask_write(0xFD409924, 0x000000FFU, 0x000000FEU);
+	psu_mask_write(0xFD409928, 0x000000FFU, 0x00000000U);
+	psu_mask_write(0xFD409900, 0x000000FFU, 0x0000001AU);
+	psu_mask_write(0xFD40992C, 0x000000FFU, 0x00000000U);
+	psu_mask_write(0xFD409980, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD409914, 0x000000FFU, 0x000000F7U);
+	psu_mask_write(0xFD409918, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD409940, 0x000000FFU, 0x000000F7U);
+	psu_mask_write(0xFD409944, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD409994, 0x00000007U, 0x00000007U);
+	psu_mask_write(0xFD40D89C, 0x00000080U, 0x00000080U);
+	psu_mask_write(0xFD40D8F8, 0x000000FFU, 0x0000007DU);
+	psu_mask_write(0xFD40D8FC, 0x000000FFU, 0x0000007DU);
+	psu_mask_write(0xFD40D990, 0x000000FFU, 0x00000001U);
+	psu_mask_write(0xFD40D924, 0x000000FFU, 0x0000009CU);
+	psu_mask_write(0xFD40D928, 0x000000FFU, 0x00000039U);
+	psu_mask_write(0xFD40D98C, 0x000000F0U, 0x00000020U);
+	psu_mask_write(0xFD40D900, 0x000000FFU, 0x0000007DU);
+	psu_mask_write(0xFD40D92C, 0x000000FFU, 0x00000064U);
+	psu_mask_write(0xFD40D980, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD40D914, 0x000000FFU, 0x000000F7U);
+	psu_mask_write(0xFD40D918, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD40D940, 0x000000FFU, 0x000000F7U);
+	psu_mask_write(0xFD40D944, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD40D994, 0x00000007U, 0x00000007U);
+	psu_mask_write(0xFD40107C, 0x0000000FU, 0x00000001U);
+	psu_mask_write(0xFD40507C, 0x0000000FU, 0x00000001U);
+	psu_mask_write(0xFD40907C, 0x0000000FU, 0x00000001U);
+	psu_mask_write(0xFD40D07C, 0x0000000FU, 0x00000001U);
+	psu_mask_write(0xFD4019A4, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD401038, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40102C, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD4059A4, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD405038, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40502C, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD4099A4, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD409038, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40902C, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40D9A4, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD40D038, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40D02C, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD4019AC, 0x00000003U, 0x00000000U);
+	psu_mask_write(0xFD4059AC, 0x00000003U, 0x00000000U);
+	psu_mask_write(0xFD4099AC, 0x00000003U, 0x00000000U);
+	psu_mask_write(0xFD40D9AC, 0x00000003U, 0x00000000U);
+	psu_mask_write(0xFD401978, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD405978, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD409978, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD40D978, 0x00000010U, 0x00000010U);
+
+	serdes_illcalib(2, 3, 3, 0, 0, 0, 0, 0);
+	psu_mask_write(0xFD410014, 0x00000077U, 0x00000023U);
+	psu_mask_write(0xFD40C1D8, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD40DC14, 0x000000FFU, 0x000000E6U);
+	psu_mask_write(0xFD40DC40, 0x0000001FU, 0x0000000CU);
+	psu_mask_write(0xFD40D94C, 0x00000020U, 0x00000020U);
+	psu_mask_write(0xFD40D950, 0x00000007U, 0x00000006U);
+	psu_mask_write(0xFD40C048, 0x000000FFU, 0x00000001U);
+
+	return 1;
+}
+
+static unsigned long psu_resetout_init_data(void)
+{
+	psu_mask_write(0xFF5E023C, 0x00000400U, 0x00000000U);
+	psu_mask_write(0xFF9D0080, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFF9D007C, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFF5E023C, 0x00000140U, 0x00000000U);
+	psu_mask_write(0xFF5E0230, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFD3D0100, 0x00000003U, 0x00000003U);
+	psu_mask_write(0xFD1A0100, 0x00000002U, 0x00000000U);
+	psu_mask_write(0xFE20C200, 0x00023FFFU, 0x00022457U);
+	psu_mask_write(0xFE20C630, 0x003FFF00U, 0x00000000U);
+	psu_mask_write(0xFE20C11C, 0x00000600U, 0x00000600U);
+	psu_mask_write(0xFE20C12C, 0x00004000U, 0x00004000U);
+	psu_mask_write(0xFD480064, 0x00000200U, 0x00000200U);
+	mask_poll(0xFD40A3E4, 0x00000010U);
+	mask_poll(0xFD40E3E4, 0x00000010U);
+	psu_mask_write(0xFD0C00AC, 0xFFFFFFFFU, 0x28184018U);
+	psu_mask_write(0xFD0C00B0, 0xFFFFFFFFU, 0x0E081406U);
+	psu_mask_write(0xFD0C00B4, 0xFFFFFFFFU, 0x064A0813U);
+	psu_mask_write(0xFD0C00B8, 0xFFFFFFFFU, 0x3FFC96A4U);
+
+	return 1;
+}
+
+static unsigned long psu_resetin_init_data(void)
+{
+	psu_mask_write(0xFF5E023C, 0x00000540U, 0x00000540U);
+	psu_mask_write(0xFF5E0230, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFD1A0100, 0x00000002U, 0x00000002U);
+
+	return 1;
+}
+
+static unsigned long psu_afi_config(void)
+{
+	psu_mask_write(0xFD1A0100, 0x00001F80U, 0x00000000U);
+	psu_mask_write(0xFF5E023C, 0x00080000U, 0x00000000U);
+	psu_mask_write(0xFD615000, 0x00000300U, 0x00000200U);
+	psu_mask_write(0xFD360000, 0x00000003U, 0x00000002U);
+	psu_mask_write(0xFD370000, 0x00000003U, 0x00000002U);
+	psu_mask_write(0xFD360014, 0x00000003U, 0x00000002U);
+	psu_mask_write(0xFD370014, 0x00000003U, 0x00000002U);
+
+	return 1;
+}
+
+static unsigned long psu_ddr_phybringup_data(void)
+{
+	unsigned int regval = 0;
+	unsigned int pll_retry = 10;
+	unsigned int pll_locked = 0;
+	int cur_R006_tREFPRD;
+
+	while ((pll_retry > 0) && (!pll_locked)) {
+		Xil_Out32(0xFD080004, 0x00040010);
+		Xil_Out32(0xFD080004, 0x00040011);
+
+		while ((Xil_In32(0xFD080030) & 0x1) != 1)
+			;
+		pll_locked = (Xil_In32(0xFD080030) & 0x80000000)
+		    >> 31;
+		pll_locked &= (Xil_In32(0xFD0807E0) & 0x10000)
+		    >> 16;
+		pll_locked &= (Xil_In32(0xFD0809E0) & 0x10000) >> 16;
+		pll_locked &= (Xil_In32(0xFD080BE0) & 0x10000)
+		    >> 16;
+		pll_locked &= (Xil_In32(0xFD080DE0) & 0x10000)
+		    >> 16;
+		pll_retry--;
+	}
+	Xil_Out32(0xFD0800C4, Xil_In32(0xFD0800C4) | (pll_retry << 16));
+	if (!pll_locked)
+		return 0;
+
+	Xil_Out32(0xFD080004U, 0x00040063U);
+
+	while ((Xil_In32(0xFD080030U) & 0x0000000FU) != 0x0000000FU)
+		;
+	prog_reg(0xFD080004U, 0x00000001U, 0x00000000U, 0x00000001U);
+
+	while ((Xil_In32(0xFD080030U) & 0x000000FFU) != 0x0000001FU)
+		;
+	Xil_Out32(0xFD0701B0U, 0x00000001U);
+	Xil_Out32(0xFD070320U, 0x00000001U);
+	while ((Xil_In32(0xFD070004U) & 0x0000000FU) != 0x00000001U)
+		;
+	prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000001U);
+	Xil_Out32(0xFD080004, 0x0004FE01);
+	regval = Xil_In32(0xFD080030);
+	while (regval != 0x80000FFF)
+		regval = Xil_In32(0xFD080030);
+	regval = ((Xil_In32(0xFD080030) & 0x1FFF0000) >> 18);
+	if (regval != 0)
+		return 0;
+
+	Xil_Out32(0xFD080200U, 0x100091C7U);
+
+	cur_R006_tREFPRD = (Xil_In32(0xFD080018U) & 0x0003FFFFU) >> 0x00000000U;
+	prog_reg(0xFD080018, 0x3FFFF, 0x0, cur_R006_tREFPRD);
+
+	prog_reg(0xFD08001CU, 0x00000018U, 0x00000003U, 0x00000003U);
+	prog_reg(0xFD08142CU, 0x00000030U, 0x00000004U, 0x00000003U);
+	prog_reg(0xFD08146CU, 0x00000030U, 0x00000004U, 0x00000003U);
+	prog_reg(0xFD0814ACU, 0x00000030U, 0x00000004U, 0x00000003U);
+	prog_reg(0xFD0814ECU, 0x00000030U, 0x00000004U, 0x00000003U);
+	prog_reg(0xFD08152CU, 0x00000030U, 0x00000004U, 0x00000003U);
+
+	Xil_Out32(0xFD080004, 0x00060001);
+	regval = Xil_In32(0xFD080030);
+	while ((regval & 0x80004001) != 0x80004001)
+		regval = Xil_In32(0xFD080030);
+
+	regval = ((Xil_In32(0xFD080030) & 0x1FFF0000) >> 18);
+	if (regval != 0)
+		return 0;
+
+	prog_reg(0xFD08001CU, 0x00000018U, 0x00000003U, 0x00000000U);
+	prog_reg(0xFD08142CU, 0x00000030U, 0x00000004U, 0x00000000U);
+	prog_reg(0xFD08146CU, 0x00000030U, 0x00000004U, 0x00000000U);
+	prog_reg(0xFD0814ACU, 0x00000030U, 0x00000004U, 0x00000000U);
+	prog_reg(0xFD0814ECU, 0x00000030U, 0x00000004U, 0x00000000U);
+	prog_reg(0xFD08152CU, 0x00000030U, 0x00000004U, 0x00000000U);
+
+	Xil_Out32(0xFD080200U, 0x800091C7U);
+	prog_reg(0xFD080018, 0x3FFFF, 0x0, cur_R006_tREFPRD);
+
+	Xil_Out32(0xFD080004, 0x0000C001);
+	regval = Xil_In32(0xFD080030);
+	while ((regval & 0x80000C01) != 0x80000C01)
+		regval = Xil_In32(0xFD080030);
+
+	Xil_Out32(0xFD070180U, 0x01000040U);
+	Xil_Out32(0xFD070060U, 0x00000000U);
+	prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000000U);
+
+	return 1;
+}
+
+static int serdes_rst_seq(u32 lane3_protocol, u32 lane3_rate,
+			  u32 lane2_protocol, u32 lane2_rate,
+			  u32 lane1_protocol, u32 lane1_rate,
+			  u32 lane0_protocol, u32 lane0_rate)
+{
+	Xil_Out32(0xFD410098, 0x00000000);
+	Xil_Out32(0xFD401010, 0x00000040);
+	Xil_Out32(0xFD405010, 0x00000040);
+	Xil_Out32(0xFD409010, 0x00000040);
+	Xil_Out32(0xFD40D010, 0x00000040);
+	Xil_Out32(0xFD402084, 0x00000080);
+	Xil_Out32(0xFD406084, 0x00000080);
+	Xil_Out32(0xFD40A084, 0x00000080);
+	Xil_Out32(0xFD40E084, 0x00000080);
+	Xil_Out32(0xFD410098, 0x00000004);
+	mask_delay(50);
+	if (lane0_rate == 1)
+		Xil_Out32(0xFD410098, 0x0000000E);
+	Xil_Out32(0xFD410098, 0x00000006);
+	if (lane0_rate == 1) {
+		Xil_Out32(0xFD40000C, 0x00000004);
+		Xil_Out32(0xFD40400C, 0x00000004);
+		Xil_Out32(0xFD40800C, 0x00000004);
+		Xil_Out32(0xFD40C00C, 0x00000004);
+		Xil_Out32(0xFD410098, 0x00000007);
+		mask_delay(400);
+		Xil_Out32(0xFD40000C, 0x0000000C);
+		Xil_Out32(0xFD40400C, 0x0000000C);
+		Xil_Out32(0xFD40800C, 0x0000000C);
+		Xil_Out32(0xFD40C00C, 0x0000000C);
+		mask_delay(15);
+		Xil_Out32(0xFD410098, 0x0000000F);
+		mask_delay(100);
+	}
+	if (lane0_protocol != 0)
+		mask_poll(0xFD4023E4, 0x00000010U);
+	if (lane1_protocol != 0)
+		mask_poll(0xFD4063E4, 0x00000010U);
+	if (lane2_protocol != 0)
+		mask_poll(0xFD40A3E4, 0x00000010U);
+	if (lane3_protocol != 0)
+		mask_poll(0xFD40E3E4, 0x00000010U);
+	mask_delay(50);
+	Xil_Out32(0xFD401010, 0x000000C0);
+	Xil_Out32(0xFD405010, 0x000000C0);
+	Xil_Out32(0xFD409010, 0x000000C0);
+	Xil_Out32(0xFD40D010, 0x000000C0);
+	Xil_Out32(0xFD401010, 0x00000080);
+	Xil_Out32(0xFD405010, 0x00000080);
+	Xil_Out32(0xFD409010, 0x00000080);
+	Xil_Out32(0xFD40D010, 0x00000080);
+
+	Xil_Out32(0xFD402084, 0x000000C0);
+	Xil_Out32(0xFD406084, 0x000000C0);
+	Xil_Out32(0xFD40A084, 0x000000C0);
+	Xil_Out32(0xFD40E084, 0x000000C0);
+	mask_delay(50);
+	Xil_Out32(0xFD402084, 0x00000080);
+	Xil_Out32(0xFD406084, 0x00000080);
+	Xil_Out32(0xFD40A084, 0x00000080);
+	Xil_Out32(0xFD40E084, 0x00000080);
+	mask_delay(50);
+	Xil_Out32(0xFD401010, 0x00000000);
+	Xil_Out32(0xFD405010, 0x00000000);
+	Xil_Out32(0xFD409010, 0x00000000);
+	Xil_Out32(0xFD40D010, 0x00000000);
+	Xil_Out32(0xFD402084, 0x00000000);
+	Xil_Out32(0xFD406084, 0x00000000);
+	Xil_Out32(0xFD40A084, 0x00000000);
+	Xil_Out32(0xFD40E084, 0x00000000);
+	mask_delay(500);
+	return 1;
+}
+
+static int serdes_bist_static_settings(u32 lane_active)
+{
+	if (lane_active == 0) {
+		Xil_Out32(0xFD403004, (Xil_In32(0xFD403004) & 0xFFFFFF1F));
+		Xil_Out32(0xFD403068, 0x1);
+		Xil_Out32(0xFD40306C, 0x1);
+		Xil_Out32(0xFD4010AC, 0x0020);
+		Xil_Out32(0xFD403008, 0x0);
+		Xil_Out32(0xFD40300C, 0xF4);
+		Xil_Out32(0xFD403010, 0x0);
+		Xil_Out32(0xFD403014, 0x0);
+		Xil_Out32(0xFD403018, 0x00);
+		Xil_Out32(0xFD40301C, 0xFB);
+		Xil_Out32(0xFD403020, 0xFF);
+		Xil_Out32(0xFD403024, 0x0);
+		Xil_Out32(0xFD403028, 0x00);
+		Xil_Out32(0xFD40302C, 0x00);
+		Xil_Out32(0xFD403030, 0x4A);
+		Xil_Out32(0xFD403034, 0x4A);
+		Xil_Out32(0xFD403038, 0x4A);
+		Xil_Out32(0xFD40303C, 0x4A);
+		Xil_Out32(0xFD403040, 0x0);
+		Xil_Out32(0xFD403044, 0x14);
+		Xil_Out32(0xFD403048, 0x02);
+		Xil_Out32(0xFD403004, (Xil_In32(0xFD403004) & 0xFFFFFF1F));
+	}
+	if (lane_active == 1) {
+		Xil_Out32(0xFD407004, (Xil_In32(0xFD407004) & 0xFFFFFF1F));
+		Xil_Out32(0xFD407068, 0x1);
+		Xil_Out32(0xFD40706C, 0x1);
+		Xil_Out32(0xFD4050AC, 0x0020);
+		Xil_Out32(0xFD407008, 0x0);
+		Xil_Out32(0xFD40700C, 0xF4);
+		Xil_Out32(0xFD407010, 0x0);
+		Xil_Out32(0xFD407014, 0x0);
+		Xil_Out32(0xFD407018, 0x00);
+		Xil_Out32(0xFD40701C, 0xFB);
+		Xil_Out32(0xFD407020, 0xFF);
+		Xil_Out32(0xFD407024, 0x0);
+		Xil_Out32(0xFD407028, 0x00);
+		Xil_Out32(0xFD40702C, 0x00);
+		Xil_Out32(0xFD407030, 0x4A);
+		Xil_Out32(0xFD407034, 0x4A);
+		Xil_Out32(0xFD407038, 0x4A);
+		Xil_Out32(0xFD40703C, 0x4A);
+		Xil_Out32(0xFD407040, 0x0);
+		Xil_Out32(0xFD407044, 0x14);
+		Xil_Out32(0xFD407048, 0x02);
+		Xil_Out32(0xFD407004, (Xil_In32(0xFD407004) & 0xFFFFFF1F));
+	}
+
+	if (lane_active == 2) {
+		Xil_Out32(0xFD40B004, (Xil_In32(0xFD40B004) & 0xFFFFFF1F));
+		Xil_Out32(0xFD40B068, 0x1);
+		Xil_Out32(0xFD40B06C, 0x1);
+		Xil_Out32(0xFD4090AC, 0x0020);
+		Xil_Out32(0xFD40B008, 0x0);
+		Xil_Out32(0xFD40B00C, 0xF4);
+		Xil_Out32(0xFD40B010, 0x0);
+		Xil_Out32(0xFD40B014, 0x0);
+		Xil_Out32(0xFD40B018, 0x00);
+		Xil_Out32(0xFD40B01C, 0xFB);
+		Xil_Out32(0xFD40B020, 0xFF);
+		Xil_Out32(0xFD40B024, 0x0);
+		Xil_Out32(0xFD40B028, 0x00);
+		Xil_Out32(0xFD40B02C, 0x00);
+		Xil_Out32(0xFD40B030, 0x4A);
+		Xil_Out32(0xFD40B034, 0x4A);
+		Xil_Out32(0xFD40B038, 0x4A);
+		Xil_Out32(0xFD40B03C, 0x4A);
+		Xil_Out32(0xFD40B040, 0x0);
+		Xil_Out32(0xFD40B044, 0x14);
+		Xil_Out32(0xFD40B048, 0x02);
+		Xil_Out32(0xFD40B004, (Xil_In32(0xFD40B004) & 0xFFFFFF1F));
+	}
+
+	if (lane_active == 3) {
+		Xil_Out32(0xFD40F004, (Xil_In32(0xFD40F004) & 0xFFFFFF1F));
+		Xil_Out32(0xFD40F068, 0x1);
+		Xil_Out32(0xFD40F06C, 0x1);
+		Xil_Out32(0xFD40D0AC, 0x0020);
+		Xil_Out32(0xFD40F008, 0x0);
+		Xil_Out32(0xFD40F00C, 0xF4);
+		Xil_Out32(0xFD40F010, 0x0);
+		Xil_Out32(0xFD40F014, 0x0);
+		Xil_Out32(0xFD40F018, 0x00);
+		Xil_Out32(0xFD40F01C, 0xFB);
+		Xil_Out32(0xFD40F020, 0xFF);
+		Xil_Out32(0xFD40F024, 0x0);
+		Xil_Out32(0xFD40F028, 0x00);
+		Xil_Out32(0xFD40F02C, 0x00);
+		Xil_Out32(0xFD40F030, 0x4A);
+		Xil_Out32(0xFD40F034, 0x4A);
+		Xil_Out32(0xFD40F038, 0x4A);
+		Xil_Out32(0xFD40F03C, 0x4A);
+		Xil_Out32(0xFD40F040, 0x0);
+		Xil_Out32(0xFD40F044, 0x14);
+		Xil_Out32(0xFD40F048, 0x02);
+		Xil_Out32(0xFD40F004, (Xil_In32(0xFD40F004) & 0xFFFFFF1F));
+	}
+	return 1;
+}
+
+static int serdes_bist_run(u32 lane_active)
+{
+	if (lane_active == 0) {
+		psu_mask_write(0xFD410044, 0x00000003U, 0x00000000U);
+		psu_mask_write(0xFD410040, 0x00000003U, 0x00000000U);
+		psu_mask_write(0xFD410038, 0x00000007U, 0x00000001U);
+		Xil_Out32(0xFD4010AC, 0x0020);
+		Xil_Out32(0xFD403004, (Xil_In32(0xFD403004) | 0x1));
+	}
+	if (lane_active == 1) {
+		psu_mask_write(0xFD410044, 0x0000000CU, 0x00000000U);
+		psu_mask_write(0xFD410040, 0x0000000CU, 0x00000000U);
+		psu_mask_write(0xFD410038, 0x00000070U, 0x00000010U);
+		Xil_Out32(0xFD4050AC, 0x0020);
+		Xil_Out32(0xFD407004, (Xil_In32(0xFD407004) | 0x1));
+	}
+	if (lane_active == 2) {
+		psu_mask_write(0xFD410044, 0x00000030U, 0x00000000U);
+		psu_mask_write(0xFD410040, 0x00000030U, 0x00000000U);
+		psu_mask_write(0xFD41003C, 0x00000007U, 0x00000001U);
+		Xil_Out32(0xFD4090AC, 0x0020);
+		Xil_Out32(0xFD40B004, (Xil_In32(0xFD40B004) | 0x1));
+	}
+	if (lane_active == 3) {
+		psu_mask_write(0xFD410040, 0x000000C0U, 0x00000000U);
+		psu_mask_write(0xFD410044, 0x000000C0U, 0x00000000U);
+		psu_mask_write(0xFD41003C, 0x00000070U, 0x00000010U);
+		Xil_Out32(0xFD40D0AC, 0x0020);
+		Xil_Out32(0xFD40F004, (Xil_In32(0xFD40F004) | 0x1));
+	}
+	mask_delay(100);
+	return 1;
+}
+
+static int serdes_bist_result(u32 lane_active)
+{
+	u32 pkt_cnt_l0, pkt_cnt_h0, err_cnt_l0, err_cnt_h0;
+
+	if (lane_active == 0) {
+		pkt_cnt_l0 = Xil_In32(0xFD40304C);
+		pkt_cnt_h0 = Xil_In32(0xFD403050);
+		err_cnt_l0 = Xil_In32(0xFD403054);
+		err_cnt_h0 = Xil_In32(0xFD403058);
+	}
+	if (lane_active == 1) {
+		pkt_cnt_l0 = Xil_In32(0xFD40704C);
+		pkt_cnt_h0 = Xil_In32(0xFD407050);
+		err_cnt_l0 = Xil_In32(0xFD407054);
+		err_cnt_h0 = Xil_In32(0xFD407058);
+	}
+	if (lane_active == 2) {
+		pkt_cnt_l0 = Xil_In32(0xFD40B04C);
+		pkt_cnt_h0 = Xil_In32(0xFD40B050);
+		err_cnt_l0 = Xil_In32(0xFD40B054);
+		err_cnt_h0 = Xil_In32(0xFD40B058);
+	}
+	if (lane_active == 3) {
+		pkt_cnt_l0 = Xil_In32(0xFD40F04C);
+		pkt_cnt_h0 = Xil_In32(0xFD40F050);
+		err_cnt_l0 = Xil_In32(0xFD40F054);
+		err_cnt_h0 = Xil_In32(0xFD40F058);
+	}
+	if (lane_active == 0)
+		Xil_Out32(0xFD403004, 0x0);
+	if (lane_active == 1)
+		Xil_Out32(0xFD407004, 0x0);
+	if (lane_active == 2)
+		Xil_Out32(0xFD40B004, 0x0);
+	if (lane_active == 3)
+		Xil_Out32(0xFD40F004, 0x0);
+	if (err_cnt_l0 > 0 || err_cnt_h0 > 0 ||
+	    (pkt_cnt_l0 == 0 && pkt_cnt_h0 == 0))
+		return 0;
+	return 1;
+}
+
+static int serdes_illcalib_pcie_gen1(u32 lane3_protocol, u32 lane3_rate,
+				     u32 lane2_protocol, u32 lane2_rate,
+				     u32 lane1_protocol, u32 lane1_rate,
+				     u32 lane0_protocol, u32 lane0_rate,
+				     u32 gen2_calib)
+{
+	u64 tempbistresult;
+	u32 currbistresult[4];
+	u32 prevbistresult[4];
+	u32 itercount = 0;
+	u32 ill12_val[4], ill1_val[4];
+	u32 loop = 0;
+	u32 iterresult[8];
+	u32 meancount[4];
+	u32 bistpasscount[4];
+	u32 meancountalt[4];
+	u32 meancountalt_bistpasscount[4];
+	u32 lane0_active;
+	u32 lane1_active;
+	u32 lane2_active;
+	u32 lane3_active;
+
+	lane0_active = (lane0_protocol == 1);
+	lane1_active = (lane1_protocol == 1);
+	lane2_active = (lane2_protocol == 1);
+	lane3_active = (lane3_protocol == 1);
+	for (loop = 0; loop <= 3; loop++) {
+		iterresult[loop] = 0;
+		iterresult[loop + 4] = 0;
+		meancountalt[loop] = 0;
+		meancountalt_bistpasscount[loop] = 0;
+		meancount[loop] = 0;
+		prevbistresult[loop] = 0;
+		bistpasscount[loop] = 0;
+	}
+	itercount = 0;
+	if (lane0_active)
+		serdes_bist_static_settings(0);
+	if (lane1_active)
+		serdes_bist_static_settings(1);
+	if (lane2_active)
+		serdes_bist_static_settings(2);
+	if (lane3_active)
+		serdes_bist_static_settings(3);
+	do {
+		if (gen2_calib != 1) {
+			if (lane0_active == 1)
+				ill1_val[0] = ((0x04 + itercount * 8) % 0x100);
+			if (lane0_active == 1)
+				ill12_val[0] =
+				    ((0x04 + itercount * 8) >=
+				     0x100) ? 0x10 : 0x00;
+			if (lane1_active == 1)
+				ill1_val[1] = ((0x04 + itercount * 8) % 0x100);
+			if (lane1_active == 1)
+				ill12_val[1] =
+				    ((0x04 + itercount * 8) >=
+				     0x100) ? 0x10 : 0x00;
+			if (lane2_active == 1)
+				ill1_val[2] = ((0x04 + itercount * 8) % 0x100);
+			if (lane2_active == 1)
+				ill12_val[2] =
+				    ((0x04 + itercount * 8) >=
+				     0x100) ? 0x10 : 0x00;
+			if (lane3_active == 1)
+				ill1_val[3] = ((0x04 + itercount * 8) % 0x100);
+			if (lane3_active == 1)
+				ill12_val[3] =
+				    ((0x04 + itercount * 8) >=
+				     0x100) ? 0x10 : 0x00;
+
+			if (lane0_active == 1)
+				Xil_Out32(0xFD401924, ill1_val[0]);
+			if (lane0_active == 1)
+				psu_mask_write(0xFD401990, 0x000000F0U,
+					       ill12_val[0]);
+			if (lane1_active == 1)
+				Xil_Out32(0xFD405924, ill1_val[1]);
+			if (lane1_active == 1)
+				psu_mask_write(0xFD405990, 0x000000F0U,
+					       ill12_val[1]);
+			if (lane2_active == 1)
+				Xil_Out32(0xFD409924, ill1_val[2]);
+			if (lane2_active == 1)
+				psu_mask_write(0xFD409990, 0x000000F0U,
+					       ill12_val[2]);
+			if (lane3_active == 1)
+				Xil_Out32(0xFD40D924, ill1_val[3]);
+			if (lane3_active == 1)
+				psu_mask_write(0xFD40D990, 0x000000F0U,
+					       ill12_val[3]);
+		}
+		if (gen2_calib == 1) {
+			if (lane0_active == 1)
+				ill1_val[0] = ((0x104 + itercount * 8) % 0x100);
+			if (lane0_active == 1)
+				ill12_val[0] =
+				    ((0x104 + itercount * 8) >=
+				     0x200) ? 0x02 : 0x01;
+			if (lane1_active == 1)
+				ill1_val[1] = ((0x104 + itercount * 8) % 0x100);
+			if (lane1_active == 1)
+				ill12_val[1] =
+				    ((0x104 + itercount * 8) >=
+				     0x200) ? 0x02 : 0x01;
+			if (lane2_active == 1)
+				ill1_val[2] = ((0x104 + itercount * 8) % 0x100);
+			if (lane2_active == 1)
+				ill12_val[2] =
+				    ((0x104 + itercount * 8) >=
+				     0x200) ? 0x02 : 0x01;
+			if (lane3_active == 1)
+				ill1_val[3] = ((0x104 + itercount * 8) % 0x100);
+			if (lane3_active == 1)
+				ill12_val[3] =
+				    ((0x104 + itercount * 8) >=
+				     0x200) ? 0x02 : 0x01;
+
+			if (lane0_active == 1)
+				Xil_Out32(0xFD401928, ill1_val[0]);
+			if (lane0_active == 1)
+				psu_mask_write(0xFD401990, 0x0000000FU,
+					       ill12_val[0]);
+			if (lane1_active == 1)
+				Xil_Out32(0xFD405928, ill1_val[1]);
+			if (lane1_active == 1)
+				psu_mask_write(0xFD405990, 0x0000000FU,
+					       ill12_val[1]);
+			if (lane2_active == 1)
+				Xil_Out32(0xFD409928, ill1_val[2]);
+			if (lane2_active == 1)
+				psu_mask_write(0xFD409990, 0x0000000FU,
+					       ill12_val[2]);
+			if (lane3_active == 1)
+				Xil_Out32(0xFD40D928, ill1_val[3]);
+			if (lane3_active == 1)
+				psu_mask_write(0xFD40D990, 0x0000000FU,
+					       ill12_val[3]);
+		}
+
+		if (lane0_active == 1)
+			psu_mask_write(0xFD401018, 0x00000030U, 0x00000010U);
+		if (lane1_active == 1)
+			psu_mask_write(0xFD405018, 0x00000030U, 0x00000010U);
+		if (lane2_active == 1)
+			psu_mask_write(0xFD409018, 0x00000030U, 0x00000010U);
+		if (lane3_active == 1)
+			psu_mask_write(0xFD40D018, 0x00000030U, 0x00000010U);
+		if (lane0_active == 1)
+			currbistresult[0] = 0;
+		if (lane1_active == 1)
+			currbistresult[1] = 0;
+		if (lane2_active == 1)
+			currbistresult[2] = 0;
+		if (lane3_active == 1)
+			currbistresult[3] = 0;
+		serdes_rst_seq(lane3_protocol, lane3_rate, lane2_protocol,
+			       lane2_rate, lane1_protocol, lane1_rate,
+			       lane0_protocol, lane0_rate);
+		if (lane3_active == 1)
+			serdes_bist_run(3);
+		if (lane2_active == 1)
+			serdes_bist_run(2);
+		if (lane1_active == 1)
+			serdes_bist_run(1);
+		if (lane0_active == 1)
+			serdes_bist_run(0);
+		tempbistresult = 0;
+		if (lane3_active == 1)
+			tempbistresult = tempbistresult | serdes_bist_result(3);
+		tempbistresult = tempbistresult << 1;
+		if (lane2_active == 1)
+			tempbistresult = tempbistresult | serdes_bist_result(2);
+		tempbistresult = tempbistresult << 1;
+		if (lane1_active == 1)
+			tempbistresult = tempbistresult | serdes_bist_result(1);
+		tempbistresult = tempbistresult << 1;
+		if (lane0_active == 1)
+			tempbistresult = tempbistresult | serdes_bist_result(0);
+		Xil_Out32(0xFD410098, 0x0);
+		Xil_Out32(0xFD410098, 0x2);
+
+		if (itercount < 32) {
+			iterresult[0] =
+			    ((iterresult[0] << 1) |
+			     ((tempbistresult & 0x1) == 0x1));
+			iterresult[1] =
+			    ((iterresult[1] << 1) |
+			     ((tempbistresult & 0x2) == 0x2));
+			iterresult[2] =
+			    ((iterresult[2] << 1) |
+			     ((tempbistresult & 0x4) == 0x4));
+			iterresult[3] =
+			    ((iterresult[3] << 1) |
+			     ((tempbistresult & 0x8) == 0x8));
+		} else {
+			iterresult[4] =
+			    ((iterresult[4] << 1) |
+			     ((tempbistresult & 0x1) == 0x1));
+			iterresult[5] =
+			    ((iterresult[5] << 1) |
+			     ((tempbistresult & 0x2) == 0x2));
+			iterresult[6] =
+			    ((iterresult[6] << 1) |
+			     ((tempbistresult & 0x4) == 0x4));
+			iterresult[7] =
+			    ((iterresult[7] << 1) |
+			     ((tempbistresult & 0x8) == 0x8));
+		}
+		currbistresult[0] =
+		    currbistresult[0] | ((tempbistresult & 0x1) == 1);
+		currbistresult[1] =
+		    currbistresult[1] | ((tempbistresult & 0x2) == 0x2);
+		currbistresult[2] =
+		    currbistresult[2] | ((tempbistresult & 0x4) == 0x4);
+		currbistresult[3] =
+		    currbistresult[3] | ((tempbistresult & 0x8) == 0x8);
+
+		for (loop = 0; loop <= 3; loop++) {
+			if (currbistresult[loop] == 1 && prevbistresult[loop] == 1)
+				bistpasscount[loop] = bistpasscount[loop] + 1;
+			if (bistpasscount[loop] < 4 &&
+			    currbistresult[loop] == 0 && itercount > 2) {
+				if (meancountalt_bistpasscount[loop] <
+				    bistpasscount[loop]) {
+					meancountalt_bistpasscount[loop] =
+					    bistpasscount[loop];
+					meancountalt[loop] =
+					    ((itercount - 1) -
+					     ((bistpasscount[loop] + 1) / 2));
+				}
+				bistpasscount[loop] = 0;
+			}
+			if (meancount[loop] == 0 && bistpasscount[loop] >= 4 &&
+			    (currbistresult[loop] == 0 || itercount == 63) &&
+			    prevbistresult[loop] == 1)
+				meancount[loop] =
+				    (itercount - 1) -
+				    ((bistpasscount[loop] + 1) / 2);
+			prevbistresult[loop] = currbistresult[loop];
+		}
+	} while (++itercount < 64);
+
+	for (loop = 0; loop <= 3; loop++) {
+		if (lane0_active == 0 && loop == 0)
+			continue;
+		if (lane1_active == 0 && loop == 1)
+			continue;
+		if (lane2_active == 0 && loop == 2)
+			continue;
+		if (lane3_active == 0 && loop == 3)
+			continue;
+
+		if (meancount[loop] == 0)
+			meancount[loop] = meancountalt[loop];
+
+		if (gen2_calib != 1) {
+			ill1_val[loop] = ((0x04 + meancount[loop] * 8) % 0x100);
+			ill12_val[loop] =
+			    ((0x04 + meancount[loop] * 8) >=
+			     0x100) ? 0x10 : 0x00;
+			Xil_Out32(0xFFFE0000 + loop * 4, iterresult[loop]);
+			Xil_Out32(0xFFFE0010 + loop * 4, iterresult[loop + 4]);
+			Xil_Out32(0xFFFE0020 + loop * 4, bistpasscount[loop]);
+			Xil_Out32(0xFFFE0030 + loop * 4, meancount[loop]);
+		}
+		if (gen2_calib == 1) {
+			ill1_val[loop] =
+			    ((0x104 + meancount[loop] * 8) % 0x100);
+			ill12_val[loop] =
+			    ((0x104 + meancount[loop] * 8) >=
+			     0x200) ? 0x02 : 0x01;
+			Xil_Out32(0xFFFE0040 + loop * 4, iterresult[loop]);
+			Xil_Out32(0xFFFE0050 + loop * 4, iterresult[loop + 4]);
+			Xil_Out32(0xFFFE0060 + loop * 4, bistpasscount[loop]);
+			Xil_Out32(0xFFFE0070 + loop * 4, meancount[loop]);
+		}
+	}
+	if (gen2_calib != 1) {
+		if (lane0_active == 1)
+			Xil_Out32(0xFD401924, ill1_val[0]);
+		if (lane0_active == 1)
+			psu_mask_write(0xFD401990, 0x000000F0U, ill12_val[0]);
+		if (lane1_active == 1)
+			Xil_Out32(0xFD405924, ill1_val[1]);
+		if (lane1_active == 1)
+			psu_mask_write(0xFD405990, 0x000000F0U, ill12_val[1]);
+		if (lane2_active == 1)
+			Xil_Out32(0xFD409924, ill1_val[2]);
+		if (lane2_active == 1)
+			psu_mask_write(0xFD409990, 0x000000F0U, ill12_val[2]);
+		if (lane3_active == 1)
+			Xil_Out32(0xFD40D924, ill1_val[3]);
+		if (lane3_active == 1)
+			psu_mask_write(0xFD40D990, 0x000000F0U, ill12_val[3]);
+	}
+	if (gen2_calib == 1) {
+		if (lane0_active == 1)
+			Xil_Out32(0xFD401928, ill1_val[0]);
+		if (lane0_active == 1)
+			psu_mask_write(0xFD401990, 0x0000000FU, ill12_val[0]);
+		if (lane1_active == 1)
+			Xil_Out32(0xFD405928, ill1_val[1]);
+		if (lane1_active == 1)
+			psu_mask_write(0xFD405990, 0x0000000FU, ill12_val[1]);
+		if (lane2_active == 1)
+			Xil_Out32(0xFD409928, ill1_val[2]);
+		if (lane2_active == 1)
+			psu_mask_write(0xFD409990, 0x0000000FU, ill12_val[2]);
+		if (lane3_active == 1)
+			Xil_Out32(0xFD40D928, ill1_val[3]);
+		if (lane3_active == 1)
+			psu_mask_write(0xFD40D990, 0x0000000FU, ill12_val[3]);
+	}
+
+	if (lane0_active == 1)
+		psu_mask_write(0xFD401018, 0x00000030U, 0x00000000U);
+	if (lane1_active == 1)
+		psu_mask_write(0xFD405018, 0x00000030U, 0x00000000U);
+	if (lane2_active == 1)
+		psu_mask_write(0xFD409018, 0x00000030U, 0x00000000U);
+	if (lane3_active == 1)
+		psu_mask_write(0xFD40D018, 0x00000030U, 0x00000000U);
+
+	Xil_Out32(0xFD410098, 0);
+	if (lane0_active == 1) {
+		Xil_Out32(0xFD403004, 0);
+		Xil_Out32(0xFD403008, 0);
+		Xil_Out32(0xFD40300C, 0);
+		Xil_Out32(0xFD403010, 0);
+		Xil_Out32(0xFD403014, 0);
+		Xil_Out32(0xFD403018, 0);
+		Xil_Out32(0xFD40301C, 0);
+		Xil_Out32(0xFD403020, 0);
+		Xil_Out32(0xFD403024, 0);
+		Xil_Out32(0xFD403028, 0);
+		Xil_Out32(0xFD40302C, 0);
+		Xil_Out32(0xFD403030, 0);
+		Xil_Out32(0xFD403034, 0);
+		Xil_Out32(0xFD403038, 0);
+		Xil_Out32(0xFD40303C, 0);
+		Xil_Out32(0xFD403040, 0);
+		Xil_Out32(0xFD403044, 0);
+		Xil_Out32(0xFD403048, 0);
+		Xil_Out32(0xFD40304C, 0);
+		Xil_Out32(0xFD403050, 0);
+		Xil_Out32(0xFD403054, 0);
+		Xil_Out32(0xFD403058, 0);
+		Xil_Out32(0xFD403068, 1);
+		Xil_Out32(0xFD40306C, 0);
+		Xil_Out32(0xFD4010AC, 0);
+		psu_mask_write(0xFD410044, 0x00000003U, 0x00000001U);
+		psu_mask_write(0xFD410040, 0x00000003U, 0x00000001U);
+		psu_mask_write(0xFD410038, 0x00000007U, 0x00000000U);
+	}
+	if (lane1_active == 1) {
+		Xil_Out32(0xFD407004, 0);
+		Xil_Out32(0xFD407008, 0);
+		Xil_Out32(0xFD40700C, 0);
+		Xil_Out32(0xFD407010, 0);
+		Xil_Out32(0xFD407014, 0);
+		Xil_Out32(0xFD407018, 0);
+		Xil_Out32(0xFD40701C, 0);
+		Xil_Out32(0xFD407020, 0);
+		Xil_Out32(0xFD407024, 0);
+		Xil_Out32(0xFD407028, 0);
+		Xil_Out32(0xFD40702C, 0);
+		Xil_Out32(0xFD407030, 0);
+		Xil_Out32(0xFD407034, 0);
+		Xil_Out32(0xFD407038, 0);
+		Xil_Out32(0xFD40703C, 0);
+		Xil_Out32(0xFD407040, 0);
+		Xil_Out32(0xFD407044, 0);
+		Xil_Out32(0xFD407048, 0);
+		Xil_Out32(0xFD40704C, 0);
+		Xil_Out32(0xFD407050, 0);
+		Xil_Out32(0xFD407054, 0);
+		Xil_Out32(0xFD407058, 0);
+		Xil_Out32(0xFD407068, 1);
+		Xil_Out32(0xFD40706C, 0);
+		Xil_Out32(0xFD4050AC, 0);
+		psu_mask_write(0xFD410044, 0x0000000CU, 0x00000004U);
+		psu_mask_write(0xFD410040, 0x0000000CU, 0x00000004U);
+		psu_mask_write(0xFD410038, 0x00000070U, 0x00000000U);
+	}
+	if (lane2_active == 1) {
+		Xil_Out32(0xFD40B004, 0);
+		Xil_Out32(0xFD40B008, 0);
+		Xil_Out32(0xFD40B00C, 0);
+		Xil_Out32(0xFD40B010, 0);
+		Xil_Out32(0xFD40B014, 0);
+		Xil_Out32(0xFD40B018, 0);
+		Xil_Out32(0xFD40B01C, 0);
+		Xil_Out32(0xFD40B020, 0);
+		Xil_Out32(0xFD40B024, 0);
+		Xil_Out32(0xFD40B028, 0);
+		Xil_Out32(0xFD40B02C, 0);
+		Xil_Out32(0xFD40B030, 0);
+		Xil_Out32(0xFD40B034, 0);
+		Xil_Out32(0xFD40B038, 0);
+		Xil_Out32(0xFD40B03C, 0);
+		Xil_Out32(0xFD40B040, 0);
+		Xil_Out32(0xFD40B044, 0);
+		Xil_Out32(0xFD40B048, 0);
+		Xil_Out32(0xFD40B04C, 0);
+		Xil_Out32(0xFD40B050, 0);
+		Xil_Out32(0xFD40B054, 0);
+		Xil_Out32(0xFD40B058, 0);
+		Xil_Out32(0xFD40B068, 1);
+		Xil_Out32(0xFD40B06C, 0);
+		Xil_Out32(0xFD4090AC, 0);
+		psu_mask_write(0xFD410044, 0x00000030U, 0x00000010U);
+		psu_mask_write(0xFD410040, 0x00000030U, 0x00000010U);
+		psu_mask_write(0xFD41003C, 0x00000007U, 0x00000000U);
+	}
+	if (lane3_active == 1) {
+		Xil_Out32(0xFD40F004, 0);
+		Xil_Out32(0xFD40F008, 0);
+		Xil_Out32(0xFD40F00C, 0);
+		Xil_Out32(0xFD40F010, 0);
+		Xil_Out32(0xFD40F014, 0);
+		Xil_Out32(0xFD40F018, 0);
+		Xil_Out32(0xFD40F01C, 0);
+		Xil_Out32(0xFD40F020, 0);
+		Xil_Out32(0xFD40F024, 0);
+		Xil_Out32(0xFD40F028, 0);
+		Xil_Out32(0xFD40F02C, 0);
+		Xil_Out32(0xFD40F030, 0);
+		Xil_Out32(0xFD40F034, 0);
+		Xil_Out32(0xFD40F038, 0);
+		Xil_Out32(0xFD40F03C, 0);
+		Xil_Out32(0xFD40F040, 0);
+		Xil_Out32(0xFD40F044, 0);
+		Xil_Out32(0xFD40F048, 0);
+		Xil_Out32(0xFD40F04C, 0);
+		Xil_Out32(0xFD40F050, 0);
+		Xil_Out32(0xFD40F054, 0);
+		Xil_Out32(0xFD40F058, 0);
+		Xil_Out32(0xFD40F068, 1);
+		Xil_Out32(0xFD40F06C, 0);
+		Xil_Out32(0xFD40D0AC, 0);
+		psu_mask_write(0xFD410044, 0x000000C0U, 0x00000040U);
+		psu_mask_write(0xFD410040, 0x000000C0U, 0x00000040U);
+		psu_mask_write(0xFD41003C, 0x00000070U, 0x00000000U);
+	}
+	return 1;
+}
+
+static int serdes_illcalib(u32 lane3_protocol, u32 lane3_rate,
+			   u32 lane2_protocol, u32 lane2_rate,
+			   u32 lane1_protocol, u32 lane1_rate,
+			   u32 lane0_protocol, u32 lane0_rate)
+{
+	unsigned int rdata = 0;
+	unsigned int sata_gen2 = 1;
+	unsigned int temp_ill12 = 0;
+	unsigned int temp_PLL_REF_SEL_OFFSET;
+	unsigned int temp_TM_IQ_ILL1;
+	unsigned int temp_TM_E_ILL1;
+	unsigned int temp_tx_dig_tm_61;
+	unsigned int temp_tm_dig_6;
+	unsigned int temp_pll_fbdiv_frac_3_msb_offset;
+
+	if (lane0_protocol == 2 || lane0_protocol == 1) {
+		Xil_Out32(0xFD401910, 0xF3);
+		Xil_Out32(0xFD40193C, 0xF3);
+		Xil_Out32(0xFD401914, 0xF3);
+		Xil_Out32(0xFD401940, 0xF3);
+	}
+	if (lane1_protocol == 2 || lane1_protocol == 1) {
+		Xil_Out32(0xFD405910, 0xF3);
+		Xil_Out32(0xFD40593C, 0xF3);
+		Xil_Out32(0xFD405914, 0xF3);
+		Xil_Out32(0xFD405940, 0xF3);
+	}
+	if (lane2_protocol == 2 || lane2_protocol == 1) {
+		Xil_Out32(0xFD409910, 0xF3);
+		Xil_Out32(0xFD40993C, 0xF3);
+		Xil_Out32(0xFD409914, 0xF3);
+		Xil_Out32(0xFD409940, 0xF3);
+	}
+	if (lane3_protocol == 2 || lane3_protocol == 1) {
+		Xil_Out32(0xFD40D910, 0xF3);
+		Xil_Out32(0xFD40D93C, 0xF3);
+		Xil_Out32(0xFD40D914, 0xF3);
+		Xil_Out32(0xFD40D940, 0xF3);
+	}
+
+	if (sata_gen2 == 1) {
+		if (lane0_protocol == 2) {
+			temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD402360);
+			Xil_Out32(0xFD402360, 0x0);
+			temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD410000);
+			psu_mask_write(0xFD410000, 0x0000001FU, 0x0000000DU);
+			temp_TM_IQ_ILL1 = Xil_In32(0xFD4018F8);
+			temp_TM_E_ILL1 = Xil_In32(0xFD401924);
+			Xil_Out32(0xFD4018F8, 0x78);
+			temp_tx_dig_tm_61 = Xil_In32(0xFD4000F4);
+			temp_tm_dig_6 = Xil_In32(0xFD40106C);
+			psu_mask_write(0xFD4000F4, 0x0000000BU, 0x00000000U);
+			psu_mask_write(0xFD40106C, 0x0000000FU, 0x00000000U);
+			temp_ill12 = Xil_In32(0xFD401990) & 0xF0;
+
+			serdes_illcalib_pcie_gen1(0, 0, 0, 0, 0, 0, 1, 0, 0);
+
+			Xil_Out32(0xFD402360, temp_pll_fbdiv_frac_3_msb_offset);
+			Xil_Out32(0xFD41000C, temp_PLL_REF_SEL_OFFSET);
+			Xil_Out32(0xFD4018F8, temp_TM_IQ_ILL1);
+			Xil_Out32(0xFD4000F4, temp_tx_dig_tm_61);
+			Xil_Out32(0xFD40106C, temp_tm_dig_6);
+			Xil_Out32(0xFD401928, Xil_In32(0xFD401924));
+			temp_ill12 =
+			    temp_ill12 | (Xil_In32(0xFD401990) >> 4 & 0xF);
+			Xil_Out32(0xFD401990, temp_ill12);
+			Xil_Out32(0xFD401924, temp_TM_E_ILL1);
+		}
+		if (lane1_protocol == 2) {
+			temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD406360);
+			Xil_Out32(0xFD406360, 0x0);
+			temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD410004);
+			psu_mask_write(0xFD410004, 0x0000001FU, 0x0000000DU);
+			temp_TM_IQ_ILL1 = Xil_In32(0xFD4058F8);
+			temp_TM_E_ILL1 = Xil_In32(0xFD405924);
+			Xil_Out32(0xFD4058F8, 0x78);
+			temp_tx_dig_tm_61 = Xil_In32(0xFD4040F4);
+			temp_tm_dig_6 = Xil_In32(0xFD40506C);
+			psu_mask_write(0xFD4040F4, 0x0000000BU, 0x00000000U);
+			psu_mask_write(0xFD40506C, 0x0000000FU, 0x00000000U);
+			temp_ill12 = Xil_In32(0xFD405990) & 0xF0;
+
+			serdes_illcalib_pcie_gen1(0, 0, 0, 0, 1, 0, 0, 0, 0);
+
+			Xil_Out32(0xFD406360, temp_pll_fbdiv_frac_3_msb_offset);
+			Xil_Out32(0xFD41000C, temp_PLL_REF_SEL_OFFSET);
+			Xil_Out32(0xFD4058F8, temp_TM_IQ_ILL1);
+			Xil_Out32(0xFD4040F4, temp_tx_dig_tm_61);
+			Xil_Out32(0xFD40506C, temp_tm_dig_6);
+			Xil_Out32(0xFD405928, Xil_In32(0xFD405924));
+			temp_ill12 =
+			    temp_ill12 | (Xil_In32(0xFD405990) >> 4 & 0xF);
+			Xil_Out32(0xFD405990, temp_ill12);
+			Xil_Out32(0xFD405924, temp_TM_E_ILL1);
+		}
+		if (lane2_protocol == 2) {
+			temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD40A360);
+			Xil_Out32(0xFD40A360, 0x0);
+			temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD410008);
+			psu_mask_write(0xFD410008, 0x0000001FU, 0x0000000DU);
+			temp_TM_IQ_ILL1 = Xil_In32(0xFD4098F8);
+			temp_TM_E_ILL1 = Xil_In32(0xFD409924);
+			Xil_Out32(0xFD4098F8, 0x78);
+			temp_tx_dig_tm_61 = Xil_In32(0xFD4080F4);
+			temp_tm_dig_6 = Xil_In32(0xFD40906C);
+			psu_mask_write(0xFD4080F4, 0x0000000BU, 0x00000000U);
+			psu_mask_write(0xFD40906C, 0x0000000FU, 0x00000000U);
+			temp_ill12 = Xil_In32(0xFD409990) & 0xF0;
+
+			serdes_illcalib_pcie_gen1(0, 0, 1, 0, 0, 0, 0, 0, 0);
+
+			Xil_Out32(0xFD40A360, temp_pll_fbdiv_frac_3_msb_offset);
+			Xil_Out32(0xFD41000C, temp_PLL_REF_SEL_OFFSET);
+			Xil_Out32(0xFD4098F8, temp_TM_IQ_ILL1);
+			Xil_Out32(0xFD4080F4, temp_tx_dig_tm_61);
+			Xil_Out32(0xFD40906C, temp_tm_dig_6);
+			Xil_Out32(0xFD409928, Xil_In32(0xFD409924));
+			temp_ill12 =
+			    temp_ill12 | (Xil_In32(0xFD409990) >> 4 & 0xF);
+			Xil_Out32(0xFD409990, temp_ill12);
+			Xil_Out32(0xFD409924, temp_TM_E_ILL1);
+		}
+		if (lane3_protocol == 2) {
+			temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD40E360);
+			Xil_Out32(0xFD40E360, 0x0);
+			temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD41000C);
+			psu_mask_write(0xFD41000C, 0x0000001FU, 0x0000000DU);
+			temp_TM_IQ_ILL1 = Xil_In32(0xFD40D8F8);
+			temp_TM_E_ILL1 = Xil_In32(0xFD40D924);
+			Xil_Out32(0xFD40D8F8, 0x78);
+			temp_tx_dig_tm_61 = Xil_In32(0xFD40C0F4);
+			temp_tm_dig_6 = Xil_In32(0xFD40D06C);
+			psu_mask_write(0xFD40C0F4, 0x0000000BU, 0x00000000U);
+			psu_mask_write(0xFD40D06C, 0x0000000FU, 0x00000000U);
+			temp_ill12 = Xil_In32(0xFD40D990) & 0xF0;
+
+			serdes_illcalib_pcie_gen1(1, 0, 0, 0, 0, 0, 0, 0, 0);
+
+			Xil_Out32(0xFD40E360, temp_pll_fbdiv_frac_3_msb_offset);
+			Xil_Out32(0xFD41000C, temp_PLL_REF_SEL_OFFSET);
+			Xil_Out32(0xFD40D8F8, temp_TM_IQ_ILL1);
+			Xil_Out32(0xFD40C0F4, temp_tx_dig_tm_61);
+			Xil_Out32(0xFD40D06C, temp_tm_dig_6);
+			Xil_Out32(0xFD40D928, Xil_In32(0xFD40D924));
+			temp_ill12 =
+			    temp_ill12 | (Xil_In32(0xFD40D990) >> 4 & 0xF);
+			Xil_Out32(0xFD40D990, temp_ill12);
+			Xil_Out32(0xFD40D924, temp_TM_E_ILL1);
+		}
+		rdata = Xil_In32(0xFD410098);
+		rdata = (rdata & 0xDF);
+		Xil_Out32(0xFD410098, rdata);
+	}
+
+	if (lane0_protocol == 2 && lane0_rate == 3) {
+		psu_mask_write(0xFD40198C, 0x000000F0U, 0x00000020U);
+		psu_mask_write(0xFD40192C, 0x000000FFU, 0x00000094U);
+	}
+	if (lane1_protocol == 2 && lane1_rate == 3) {
+		psu_mask_write(0xFD40598C, 0x000000F0U, 0x00000020U);
+		psu_mask_write(0xFD40592C, 0x000000FFU, 0x00000094U);
+	}
+	if (lane2_protocol == 2 && lane2_rate == 3) {
+		psu_mask_write(0xFD40998C, 0x000000F0U, 0x00000020U);
+		psu_mask_write(0xFD40992C, 0x000000FFU, 0x00000094U);
+	}
+	if (lane3_protocol == 2 && lane3_rate == 3) {
+		psu_mask_write(0xFD40D98C, 0x000000F0U, 0x00000020U);
+		psu_mask_write(0xFD40D92C, 0x000000FFU, 0x00000094U);
+	}
+
+	if (lane0_protocol == 1) {
+		if (lane0_rate == 0) {
+			serdes_illcalib_pcie_gen1(lane3_protocol, lane3_rate,
+						  lane2_protocol, lane2_rate,
+						  lane1_protocol, lane1_rate,
+						  lane0_protocol, 0, 0);
+		} else {
+			serdes_illcalib_pcie_gen1(lane3_protocol, lane3_rate,
+						  lane2_protocol, lane2_rate,
+						  lane1_protocol, lane1_rate,
+						  lane0_protocol, 0, 0);
+			serdes_illcalib_pcie_gen1(lane3_protocol, lane3_rate,
+						  lane2_protocol, lane2_rate,
+						  lane1_protocol, lane1_rate,
+						  lane0_protocol, lane0_rate,
+						  1);
+		}
+	}
+
+	if (lane0_protocol == 3)
+		Xil_Out32(0xFD401914, 0xF3);
+	if (lane0_protocol == 3)
+		Xil_Out32(0xFD401940, 0xF3);
+	if (lane0_protocol == 3)
+		Xil_Out32(0xFD401990, 0x20);
+	if (lane0_protocol == 3)
+		Xil_Out32(0xFD401924, 0x37);
+
+	if (lane1_protocol == 3)
+		Xil_Out32(0xFD405914, 0xF3);
+	if (lane1_protocol == 3)
+		Xil_Out32(0xFD405940, 0xF3);
+	if (lane1_protocol == 3)
+		Xil_Out32(0xFD405990, 0x20);
+	if (lane1_protocol == 3)
+		Xil_Out32(0xFD405924, 0x37);
+
+	if (lane2_protocol == 3)
+		Xil_Out32(0xFD409914, 0xF3);
+	if (lane2_protocol == 3)
+		Xil_Out32(0xFD409940, 0xF3);
+	if (lane2_protocol == 3)
+		Xil_Out32(0xFD409990, 0x20);
+	if (lane2_protocol == 3)
+		Xil_Out32(0xFD409924, 0x37);
+
+	if (lane3_protocol == 3)
+		Xil_Out32(0xFD40D914, 0xF3);
+	if (lane3_protocol == 3)
+		Xil_Out32(0xFD40D940, 0xF3);
+	if (lane3_protocol == 3)
+		Xil_Out32(0xFD40D990, 0x20);
+	if (lane3_protocol == 3)
+		Xil_Out32(0xFD40D924, 0x37);
+
+	return 1;
+}
+
+static int serdes_enb_coarse_saturation(void)
+{
+	Xil_Out32(0xFD402094, 0x00000010);
+	Xil_Out32(0xFD406094, 0x00000010);
+	Xil_Out32(0xFD40A094, 0x00000010);
+	Xil_Out32(0xFD40E094, 0x00000010);
+	return 1;
+}
+
+static int serdes_fixcal_code(void)
+{
+	int maskstatus = 1;
+	unsigned int rdata = 0;
+	unsigned int match_pmos_code[23];
+	unsigned int match_nmos_code[23];
+	unsigned int match_ical_code[7];
+	unsigned int match_rcal_code[7];
+	unsigned int p_code = 0;
+	unsigned int n_code = 0;
+	unsigned int i_code = 0;
+	unsigned int r_code = 0;
+	unsigned int repeat_count = 0;
+	unsigned int L3_TM_CALIB_DIG20 = 0;
+	unsigned int L3_TM_CALIB_DIG19 = 0;
+	unsigned int L3_TM_CALIB_DIG18 = 0;
+	unsigned int L3_TM_CALIB_DIG16 = 0;
+	unsigned int L3_TM_CALIB_DIG15 = 0;
+	unsigned int L3_TM_CALIB_DIG14 = 0;
+	int i = 0;
+	int count = 0;
+
+	rdata = Xil_In32(0xFD40289C);
+	rdata = rdata & ~0x03;
+	rdata = rdata | 0x1;
+	Xil_Out32(0xFD40289C, rdata);
+
+	do {
+		if (count == 1100000)
+			break;
+		rdata = Xil_In32(0xFD402B1C);
+		count++;
+	} while ((rdata & 0x0000000E) != 0x0000000E);
+
+	for (i = 0; i < 23; i++) {
+		match_pmos_code[i] = 0;
+		match_nmos_code[i] = 0;
+	}
+	for (i = 0; i < 7; i++) {
+		match_ical_code[i] = 0;
+		match_rcal_code[i] = 0;
+	}
+
+	do {
+		Xil_Out32(0xFD410010, 0x00000000);
+		Xil_Out32(0xFD410014, 0x00000000);
+
+		Xil_Out32(0xFD410010, 0x00000001);
+		Xil_Out32(0xFD410014, 0x00000000);
+
+		maskstatus = mask_poll(0xFD40EF14, 0x2);
+		if (maskstatus == 0) {
+			xil_printf("#SERDES initialization timed out\n\r");
+			return maskstatus;
+		}
+
+		p_code = mask_read(0xFD40EF18, 0xFFFFFFFF);
+		n_code = mask_read(0xFD40EF1C, 0xFFFFFFFF);
+		;
+		i_code = mask_read(0xFD40EF24, 0xFFFFFFFF);
+		r_code = mask_read(0xFD40EF28, 0xFFFFFFFF);
+		;
+
+		if (p_code >= 0x26 && p_code <= 0x3C)
+			match_pmos_code[p_code - 0x26] += 1;
+
+		if (n_code >= 0x26 && n_code <= 0x3C)
+			match_nmos_code[n_code - 0x26] += 1;
+
+		if (i_code >= 0xC && i_code <= 0x12)
+			match_ical_code[i_code - 0xc] += 1;
+
+		if (r_code >= 0x6 && r_code <= 0xC)
+			match_rcal_code[r_code - 0x6] += 1;
+
+	} while (repeat_count++ < 10);
+
+	for (i = 0; i < 23; i++) {
+		if (match_pmos_code[i] >= match_pmos_code[0]) {
+			match_pmos_code[0] = match_pmos_code[i];
+			p_code = 0x26 + i;
+		}
+		if (match_nmos_code[i] >= match_nmos_code[0]) {
+			match_nmos_code[0] = match_nmos_code[i];
+			n_code = 0x26 + i;
+		}
+	}
+
+	for (i = 0; i < 7; i++) {
+		if (match_ical_code[i] >= match_ical_code[0]) {
+			match_ical_code[0] = match_ical_code[i];
+			i_code = 0xC + i;
+		}
+		if (match_rcal_code[i] >= match_rcal_code[0]) {
+			match_rcal_code[0] = match_rcal_code[i];
+			r_code = 0x6 + i;
+		}
+	}
+
+	L3_TM_CALIB_DIG20 = mask_read(0xFD40EC50, 0xFFFFFFF0);
+	L3_TM_CALIB_DIG20 = L3_TM_CALIB_DIG20 | 0x8 | ((p_code >> 2) & 0x7);
+
+	L3_TM_CALIB_DIG19 = mask_read(0xFD40EC4C, 0xFFFFFF18);
+	L3_TM_CALIB_DIG19 = L3_TM_CALIB_DIG19 | ((p_code & 0x3) << 6)
+	    | 0x20 | 0x4 | ((n_code >> 3) & 0x3);
+
+	L3_TM_CALIB_DIG18 = mask_read(0xFD40EC48, 0xFFFFFF0F);
+	L3_TM_CALIB_DIG18 = L3_TM_CALIB_DIG18 | ((n_code & 0x7) << 5) | 0x10;
+
+	L3_TM_CALIB_DIG16 = mask_read(0xFD40EC40, 0xFFFFFFF8);
+	L3_TM_CALIB_DIG16 = L3_TM_CALIB_DIG16 | ((r_code >> 1) & 0x7);
+
+	L3_TM_CALIB_DIG15 = mask_read(0xFD40EC3C, 0xFFFFFF30);
+	L3_TM_CALIB_DIG15 = L3_TM_CALIB_DIG15 | ((r_code & 0x1) << 7)
+	    | 0x40 | 0x8 | ((i_code >> 1) & 0x7);
+
+	L3_TM_CALIB_DIG14 = mask_read(0xFD40EC38, 0xFFFFFF3F);
+	L3_TM_CALIB_DIG14 = L3_TM_CALIB_DIG14 | ((i_code & 0x1) << 7) | 0x40;
+
+	Xil_Out32(0xFD40EC50, L3_TM_CALIB_DIG20);
+	Xil_Out32(0xFD40EC4C, L3_TM_CALIB_DIG19);
+	Xil_Out32(0xFD40EC48, L3_TM_CALIB_DIG18);
+	Xil_Out32(0xFD40EC40, L3_TM_CALIB_DIG16);
+	Xil_Out32(0xFD40EC3C, L3_TM_CALIB_DIG15);
+	Xil_Out32(0xFD40EC38, L3_TM_CALIB_DIG14);
+	return maskstatus;
+}
+
+static int init_serdes(void)
+{
+	int status = 1;
+
+	status &= psu_resetin_init_data();
+
+	status &= serdes_fixcal_code();
+	status &= serdes_enb_coarse_saturation();
+
+	status &= psu_serdes_init_data();
+	status &= psu_resetout_init_data();
+
+	return status;
+}
+
+static void init_peripheral(void)
+{
+	psu_mask_write(0xFD5F0018, 0x8000001FU, 0x8000001FU);
+}
+
+int psu_init(void)
+{
+	int status = 1;
+
+	status &= psu_mio_init_data();
+	status &= psu_peripherals_pre_init_data();
+	status &= psu_pll_init_data();
+	status &= psu_clock_init_data();
+	status &= psu_ddr_init_data();
+	status &= psu_ddr_phybringup_data();
+	status &= psu_peripherals_init_data();
+	status &= init_serdes();
+	init_peripheral();
+
+	status &= psu_afi_config();
+	psu_ddr_qos_init_data();
+
+	if (status == 0)
+		return 1;
+	return 0;
+}
diff --git a/board/xilinx/zynqmp/zynqmp-zcu216-revA/psu_init_gpl.c b/board/xilinx/zynqmp/zynqmp-zcu216-revA/psu_init_gpl.c
new file mode 100644
index 0000000..fc3605d
--- /dev/null
+++ b/board/xilinx/zynqmp/zynqmp-zcu216-revA/psu_init_gpl.c
@@ -0,0 +1,1882 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (c) Copyright 2015 Xilinx, Inc. All rights reserved.
+ */
+
+#include <asm/arch/psu_init_gpl.h>
+#include <xil_io.h>
+
+static int serdes_illcalib(u32 lane3_protocol, u32 lane3_rate,
+			   u32 lane2_protocol, u32 lane2_rate,
+			   u32 lane1_protocol, u32 lane1_rate,
+			   u32 lane0_protocol, u32 lane0_rate);
+
+static unsigned long psu_pll_init_data(void)
+{
+	psu_mask_write(0xFF5E0034, 0xFE7FEDEFU, 0x7E4B0C82U);
+	psu_mask_write(0xFF5E0030, 0x00717F00U, 0x00015A00U);
+	psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFF5E0030, 0x00000001U, 0x00000000U);
+	mask_poll(0xFF5E0040, 0x00000002U);
+	psu_mask_write(0xFF5E0030, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFF5E0048, 0x00003F00U, 0x00000300U);
+	psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01012300U);
+	psu_mask_write(0xFF5E0024, 0xFE7FEDEFU, 0x7E4B0C82U);
+	psu_mask_write(0xFF5E0020, 0x00717F00U, 0x00015A00U);
+	psu_mask_write(0xFF5E0020, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFF5E0020, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFF5E0020, 0x00000001U, 0x00000000U);
+	mask_poll(0xFF5E0040, 0x00000001U);
+	psu_mask_write(0xFF5E0020, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFF5E0044, 0x00003F00U, 0x00000300U);
+	psu_mask_write(0xFD1A0024, 0xFE7FEDEFU, 0x7E4B0C62U);
+	psu_mask_write(0xFD1A0020, 0x00717F00U, 0x00014800U);
+	psu_mask_write(0xFD1A0020, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFD1A0020, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD1A0020, 0x00000001U, 0x00000000U);
+	mask_poll(0xFD1A0044, 0x00000001U);
+	psu_mask_write(0xFD1A0020, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFD1A0048, 0x00003F00U, 0x00000300U);
+	psu_mask_write(0xFD1A0030, 0xFE7FEDEFU, 0x7E4B0C62U);
+	psu_mask_write(0xFD1A002C, 0x00717F00U, 0x00013F00U);
+	psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD1A002C, 0x00000001U, 0x00000000U);
+	mask_poll(0xFD1A0044, 0x00000002U);
+	psu_mask_write(0xFD1A002C, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFD1A004C, 0x00003F00U, 0x00000200U);
+	psu_mask_write(0xFD1A003C, 0xFE7FEDEFU, 0x7E4B0C82U);
+	psu_mask_write(0xFD1A0038, 0x00717F00U, 0x00015A00U);
+	psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD1A0038, 0x00000001U, 0x00000000U);
+	mask_poll(0xFD1A0044, 0x00000004U);
+	psu_mask_write(0xFD1A0038, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFD1A0050, 0x00003F00U, 0x00000300U);
+
+	return 1;
+}
+
+static unsigned long psu_clock_init_data(void)
+{
+	psu_mask_write(0xFF5E005C, 0x063F3F07U, 0x06010C00U);
+	psu_mask_write(0xFF5E0100, 0x013F3F07U, 0x01010600U);
+	psu_mask_write(0xFF5E0060, 0x023F3F07U, 0x02010600U);
+	psu_mask_write(0xFF5E004C, 0x023F3F07U, 0x02031900U);
+	psu_mask_write(0xFF5E0068, 0x013F3F07U, 0x01010C00U);
+	psu_mask_write(0xFF5E0070, 0x013F3F07U, 0x01010800U);
+	psu_mask_write(0xFF18030C, 0x00020000U, 0x00000000U);
+	psu_mask_write(0xFF5E0074, 0x013F3F07U, 0x01010F00U);
+	psu_mask_write(0xFF5E0120, 0x013F3F07U, 0x01010F00U);
+	psu_mask_write(0xFF5E0124, 0x013F3F07U, 0x01010F00U);
+	psu_mask_write(0xFF5E0090, 0x01003F07U, 0x01000302U);
+	psu_mask_write(0xFF5E009C, 0x01003F07U, 0x01000602U);
+	psu_mask_write(0xFF5E00A4, 0x01003F07U, 0x01000800U);
+	psu_mask_write(0xFF5E00A8, 0x01003F07U, 0x01000302U);
+	psu_mask_write(0xFF5E00AC, 0x01003F07U, 0x01000F02U);
+	psu_mask_write(0xFF5E00B0, 0x01003F07U, 0x01000602U);
+	psu_mask_write(0xFF5E00B8, 0x01003F07U, 0x01000302U);
+	psu_mask_write(0xFF5E00C0, 0x013F3F07U, 0x01010F00U);
+	psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01011E02U);
+	psu_mask_write(0xFF5E0104, 0x00000007U, 0x00000000U);
+	psu_mask_write(0xFF5E0128, 0x01003F07U, 0x01000F00U);
+	psu_mask_write(0xFD1A00A0, 0x01003F07U, 0x01000200U);
+	psu_mask_write(0xFD1A0060, 0x03003F07U, 0x03000100U);
+	psu_mask_write(0xFD1A0068, 0x01003F07U, 0x01000200U);
+	psu_mask_write(0xFD1A0080, 0x00003F07U, 0x00000200U);
+	psu_mask_write(0xFD1A00B8, 0x01003F07U, 0x01000200U);
+	psu_mask_write(0xFD1A00BC, 0x01003F07U, 0x01000200U);
+	psu_mask_write(0xFD1A00C0, 0x01003F07U, 0x01000203U);
+	psu_mask_write(0xFD1A00C4, 0x01003F07U, 0x01000502U);
+	psu_mask_write(0xFD1A00F8, 0x00003F07U, 0x00000200U);
+	psu_mask_write(0xFF180380, 0x000000FFU, 0x00000000U);
+	psu_mask_write(0xFD610100, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFF180300, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFF410050, 0x00000001U, 0x00000000U);
+
+	return 1;
+}
+
+static unsigned long psu_ddr_init_data(void)
+{
+	psu_mask_write(0xFD1A0108, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFD070000, 0xE30FBE3DU, 0x81040010U);
+	psu_mask_write(0xFD070010, 0x8000F03FU, 0x00000030U);
+	psu_mask_write(0xFD070020, 0x000003F3U, 0x00000200U);
+	psu_mask_write(0xFD070024, 0xFFFFFFFFU, 0x00800000U);
+	psu_mask_write(0xFD070030, 0x0000007FU, 0x00000000U);
+	psu_mask_write(0xFD070034, 0x00FFFF1FU, 0x00408210U);
+	psu_mask_write(0xFD070050, 0x00F1F1F4U, 0x00210000U);
+	psu_mask_write(0xFD070054, 0x0FFF0FFFU, 0x00000000U);
+	psu_mask_write(0xFD070060, 0x00000073U, 0x00000001U);
+	psu_mask_write(0xFD070064, 0x0FFF83FFU, 0x007F80B8U);
+	psu_mask_write(0xFD070070, 0x00000017U, 0x00000010U);
+	psu_mask_write(0xFD070074, 0x00000003U, 0x00000000U);
+	psu_mask_write(0xFD0700C4, 0x3F000391U, 0x10000200U);
+	psu_mask_write(0xFD0700C8, 0x01FF1F3FU, 0x0040051FU);
+	psu_mask_write(0xFD0700D0, 0xC3FF0FFFU, 0x00020102U);
+	psu_mask_write(0xFD0700D4, 0x01FF7F0FU, 0x00020000U);
+	psu_mask_write(0xFD0700D8, 0x0000FF0FU, 0x00002205U);
+	psu_mask_write(0xFD0700DC, 0xFFFFFFFFU, 0x07300301U);
+	psu_mask_write(0xFD0700E0, 0xFFFFFFFFU, 0x00100200U);
+	psu_mask_write(0xFD0700E4, 0x00FF03FFU, 0x00210004U);
+	psu_mask_write(0xFD0700E8, 0xFFFFFFFFU, 0x000006C0U);
+	psu_mask_write(0xFD0700EC, 0xFFFF0000U, 0x08190000U);
+	psu_mask_write(0xFD0700F0, 0x0000003FU, 0x00000010U);
+	psu_mask_write(0xFD0700F4, 0x00000FFFU, 0x0000066FU);
+	psu_mask_write(0xFD070100, 0x7F3F7F3FU, 0x0F102311U);
+	psu_mask_write(0xFD070104, 0x001F1F7FU, 0x00040419U);
+	psu_mask_write(0xFD070108, 0x3F3F3F3FU, 0x0608070CU);
+	psu_mask_write(0xFD07010C, 0x3FF3F3FFU, 0x0050400CU);
+	psu_mask_write(0xFD070110, 0x1F0F0F1FU, 0x08030409U);
+	psu_mask_write(0xFD070114, 0x0F0F3F1FU, 0x06060403U);
+	psu_mask_write(0xFD070118, 0x0F0F000FU, 0x01010004U);
+	psu_mask_write(0xFD07011C, 0x00000F0FU, 0x00000606U);
+	psu_mask_write(0xFD070120, 0x7F7F7F7FU, 0x04040D07U);
+	psu_mask_write(0xFD070124, 0x40070F3FU, 0x00020309U);
+	psu_mask_write(0xFD07012C, 0x7F1F031FU, 0x1207010EU);
+	psu_mask_write(0xFD070130, 0x00030F1FU, 0x00020608U);
+	psu_mask_write(0xFD070180, 0xF7FF03FFU, 0x81000040U);
+	psu_mask_write(0xFD070184, 0x3FFFFFFFU, 0x0201908AU);
+	psu_mask_write(0xFD070190, 0x1FBFBF3FU, 0x048B8208U);
+	psu_mask_write(0xFD070194, 0xF31F0F0FU, 0x00030304U);
+	psu_mask_write(0xFD070198, 0x0FF1F1F1U, 0x07000101U);
+	psu_mask_write(0xFD07019C, 0x000000F1U, 0x00000021U);
+	psu_mask_write(0xFD0701A0, 0xC3FF03FFU, 0x00400003U);
+	psu_mask_write(0xFD0701A4, 0x00FF00FFU, 0x00C800FFU);
+	psu_mask_write(0xFD0701B0, 0x00000007U, 0x00000000U);
+	psu_mask_write(0xFD0701B4, 0x00003F3FU, 0x00000906U);
+	psu_mask_write(0xFD0701C0, 0x00000007U, 0x00000001U);
+	psu_mask_write(0xFD070200, 0x0000001FU, 0x0000001FU);
+	psu_mask_write(0xFD070204, 0x001F1F1FU, 0x001F0909U);
+	psu_mask_write(0xFD070208, 0x0F0F0F0FU, 0x01010100U);
+	psu_mask_write(0xFD07020C, 0x0F0F0F0FU, 0x01010101U);
+	psu_mask_write(0xFD070210, 0x00000F0FU, 0x00000F0FU);
+	psu_mask_write(0xFD070214, 0x0F0F0F0FU, 0x070F0707U);
+	psu_mask_write(0xFD070218, 0x8F0F0F0FU, 0x07070707U);
+	psu_mask_write(0xFD07021C, 0x00000F0FU, 0x00000F0FU);
+	psu_mask_write(0xFD070220, 0x00001F1FU, 0x00001F01U);
+	psu_mask_write(0xFD070224, 0x0F0F0F0FU, 0x07070707U);
+	psu_mask_write(0xFD070228, 0x0F0F0F0FU, 0x07070707U);
+	psu_mask_write(0xFD07022C, 0x0000000FU, 0x00000007U);
+	psu_mask_write(0xFD070240, 0x0F1F0F7CU, 0x0600060CU);
+	psu_mask_write(0xFD070244, 0x00003333U, 0x00000001U);
+	psu_mask_write(0xFD070250, 0x7FFF3F07U, 0x01002001U);
+	psu_mask_write(0xFD070264, 0xFF00FFFFU, 0x08000040U);
+	psu_mask_write(0xFD07026C, 0xFF00FFFFU, 0x08000040U);
+	psu_mask_write(0xFD070280, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD070284, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD070288, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD07028C, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD070290, 0x0000FFFFU, 0x00000000U);
+	psu_mask_write(0xFD070294, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD070300, 0x00000011U, 0x00000000U);
+	psu_mask_write(0xFD07030C, 0x80000033U, 0x00000000U);
+	psu_mask_write(0xFD070320, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFD070400, 0x00000111U, 0x00000001U);
+	psu_mask_write(0xFD070404, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070408, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070490, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD070494, 0x0033000FU, 0x0020000BU);
+	psu_mask_write(0xFD070498, 0x07FF07FFU, 0x00000000U);
+	psu_mask_write(0xFD0704B4, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD0704B8, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070540, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD070544, 0x03330F0FU, 0x02000B03U);
+	psu_mask_write(0xFD070548, 0x07FF07FFU, 0x00000000U);
+	psu_mask_write(0xFD070564, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070568, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD0705F0, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD0705F4, 0x03330F0FU, 0x02000B03U);
+	psu_mask_write(0xFD0705F8, 0x07FF07FFU, 0x00000000U);
+	psu_mask_write(0xFD070614, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070618, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD0706A0, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD0706A4, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD0706A8, 0x07FF07FFU, 0x0000004FU);
+	psu_mask_write(0xFD0706AC, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD0706B0, 0x000007FFU, 0x0000004FU);
+	psu_mask_write(0xFD0706C4, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD0706C8, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070750, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD070754, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD070758, 0x07FF07FFU, 0x0000004FU);
+	psu_mask_write(0xFD07075C, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD070760, 0x000007FFU, 0x0000004FU);
+	psu_mask_write(0xFD070774, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070778, 0x000073FFU, 0x0000200FU);
+	psu_mask_write(0xFD070800, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD070804, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD070808, 0x07FF07FFU, 0x0000004FU);
+	psu_mask_write(0xFD07080C, 0x0033000FU, 0x00100003U);
+	psu_mask_write(0xFD070810, 0x000007FFU, 0x0000004FU);
+	psu_mask_write(0xFD070F04, 0x000001FFU, 0x00000000U);
+	psu_mask_write(0xFD070F08, 0x000000FFU, 0x00000000U);
+	psu_mask_write(0xFD070F0C, 0x000001FFU, 0x00000010U);
+	psu_mask_write(0xFD070F10, 0x000000FFU, 0x0000000FU);
+	psu_mask_write(0xFD072190, 0x1FBFBF3FU, 0x07828002U);
+	psu_mask_write(0xFD1A0108, 0x0000000CU, 0x00000000U);
+	psu_mask_write(0xFD080010, 0xFFFFFFFFU, 0x07001E00U);
+	psu_mask_write(0xFD080018, 0xFFFFFFFFU, 0x00F0FC00U);
+	psu_mask_write(0xFD08001C, 0xFFFFFFFFU, 0x55AA5480U);
+	psu_mask_write(0xFD080024, 0xFFFFFFFFU, 0x010100F4U);
+	psu_mask_write(0xFD080040, 0xFFFFFFFFU, 0x41A20D10U);
+	psu_mask_write(0xFD080044, 0xFFFFFFFFU, 0xCD141275U);
+	psu_mask_write(0xFD080068, 0xFFFFFFFFU, 0x01100000U);
+	psu_mask_write(0xFD080090, 0xFFFFFFFFU, 0x02A04161U);
+	psu_mask_write(0xFD0800C0, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD0800C4, 0xFFFFFFFFU, 0x000000E3U);
+	psu_mask_write(0xFD080100, 0xFFFFFFFFU, 0x0800040CU);
+	psu_mask_write(0xFD080110, 0xFFFFFFFFU, 0x07220F08U);
+	psu_mask_write(0xFD080114, 0xFFFFFFFFU, 0x28200008U);
+	psu_mask_write(0xFD080118, 0xFFFFFFFFU, 0x000F0300U);
+	psu_mask_write(0xFD08011C, 0xFFFFFFFFU, 0x83000800U);
+	psu_mask_write(0xFD080120, 0xFFFFFFFFU, 0x01702B07U);
+	psu_mask_write(0xFD080124, 0xFFFFFFFFU, 0x00310F08U);
+	psu_mask_write(0xFD080128, 0xFFFFFFFFU, 0x00000B0FU);
+	psu_mask_write(0xFD080140, 0xFFFFFFFFU, 0x08400020U);
+	psu_mask_write(0xFD080144, 0xFFFFFFFFU, 0x00000C80U);
+	psu_mask_write(0xFD080150, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080154, 0xFFFFFFFFU, 0x00000200U);
+	psu_mask_write(0xFD080180, 0xFFFFFFFFU, 0x00000630U);
+	psu_mask_write(0xFD080184, 0xFFFFFFFFU, 0x00000301U);
+	psu_mask_write(0xFD080188, 0xFFFFFFFFU, 0x00000010U);
+	psu_mask_write(0xFD08018C, 0xFFFFFFFFU, 0x00000200U);
+	psu_mask_write(0xFD080190, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080194, 0xFFFFFFFFU, 0x000006C0U);
+	psu_mask_write(0xFD080198, 0xFFFFFFFFU, 0x00000819U);
+	psu_mask_write(0xFD0801AC, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD0801B0, 0xFFFFFFFFU, 0x0000004DU);
+	psu_mask_write(0xFD0801B4, 0xFFFFFFFFU, 0x00000008U);
+	psu_mask_write(0xFD0801B8, 0xFFFFFFFFU, 0x0000004DU);
+	psu_mask_write(0xFD0801D8, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080200, 0xFFFFFFFFU, 0x800091C7U);
+	psu_mask_write(0xFD080204, 0xFFFFFFFFU, 0x00010236U);
+	psu_mask_write(0xFD080240, 0xFFFFFFFFU, 0x00141054U);
+	psu_mask_write(0xFD080250, 0xFFFFFFFFU, 0x00088000U);
+	psu_mask_write(0xFD080414, 0xFFFFFFFFU, 0x12341000U);
+	psu_mask_write(0xFD0804F4, 0xFFFFFFFFU, 0x00000005U);
+	psu_mask_write(0xFD080500, 0xFFFFFFFFU, 0x30000028U);
+	psu_mask_write(0xFD080508, 0xFFFFFFFFU, 0x0A000000U);
+	psu_mask_write(0xFD08050C, 0xFFFFFFFFU, 0x00000009U);
+	psu_mask_write(0xFD080510, 0xFFFFFFFFU, 0x0A000000U);
+	psu_mask_write(0xFD080520, 0xFFFFFFFFU, 0x0300B0CEU);
+	psu_mask_write(0xFD080528, 0xFFFFFFFFU, 0xF9032019U);
+	psu_mask_write(0xFD08052C, 0xFFFFFFFFU, 0x07F001E3U);
+	psu_mask_write(0xFD080544, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080548, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080558, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD08055C, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080560, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080564, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080680, 0xFFFFFFFFU, 0x008A8A58U);
+	psu_mask_write(0xFD080684, 0xFFFFFFFFU, 0x000079DDU);
+	psu_mask_write(0xFD080694, 0xFFFFFFFFU, 0x01E10210U);
+	psu_mask_write(0xFD080698, 0xFFFFFFFFU, 0x01E10000U);
+	psu_mask_write(0xFD0806A4, 0xFFFFFFFFU, 0x00087BDBU);
+	psu_mask_write(0xFD080700, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080704, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD08070C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080710, 0xFFFFFFFFU, 0x0E00B03CU);
+	psu_mask_write(0xFD080714, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080718, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080800, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080804, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD08080C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080810, 0xFFFFFFFFU, 0x0E00B03CU);
+	psu_mask_write(0xFD080814, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080818, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080900, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080904, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD08090C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080910, 0xFFFFFFFFU, 0x0E00B004U);
+	psu_mask_write(0xFD080914, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080918, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080A00, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080A04, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD080A0C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080A10, 0xFFFFFFFFU, 0x0E00B004U);
+	psu_mask_write(0xFD080A14, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080A18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080B00, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080B04, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD080B08, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080B0C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080B10, 0xFFFFFFFFU, 0x0E00B004U);
+	psu_mask_write(0xFD080B14, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080B18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080C00, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080C04, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD080C08, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080C0C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080C10, 0xFFFFFFFFU, 0x0E00B03CU);
+	psu_mask_write(0xFD080C14, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080C18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080D00, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080D04, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD080D08, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080D0C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080D10, 0xFFFFFFFFU, 0x0E00B004U);
+	psu_mask_write(0xFD080D14, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080D18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080E00, 0xFFFFFFFFU, 0x40800604U);
+	psu_mask_write(0xFD080E04, 0xFFFFFFFFU, 0x00007FFFU);
+	psu_mask_write(0xFD080E08, 0xFFFFFFFFU, 0x00000000U);
+	psu_mask_write(0xFD080E0C, 0xFFFFFFFFU, 0x3F000008U);
+	psu_mask_write(0xFD080E10, 0xFFFFFFFFU, 0x0E00B03CU);
+	psu_mask_write(0xFD080E14, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080E18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD080F00, 0xFFFFFFFFU, 0x80803660U);
+	psu_mask_write(0xFD080F04, 0xFFFFFFFFU, 0x55556000U);
+	psu_mask_write(0xFD080F08, 0xFFFFFFFFU, 0xAAAAAAAAU);
+	psu_mask_write(0xFD080F0C, 0xFFFFFFFFU, 0x0029A4A4U);
+	psu_mask_write(0xFD080F10, 0xFFFFFFFFU, 0x0C00B000U);
+	psu_mask_write(0xFD080F14, 0xFFFFFFFFU, 0x09095555U);
+	psu_mask_write(0xFD080F18, 0xFFFFFFFFU, 0x09092B2BU);
+	psu_mask_write(0xFD081400, 0xFFFFFFFFU, 0x2A019FFEU);
+	psu_mask_write(0xFD081404, 0xFFFFFFFFU, 0x01100000U);
+	psu_mask_write(0xFD08141C, 0xFFFFFFFFU, 0x01264300U);
+	psu_mask_write(0xFD08142C, 0xFFFFFFFFU, 0x00041800U);
+	psu_mask_write(0xFD081430, 0xFFFFFFFFU, 0x70800000U);
+	psu_mask_write(0xFD081440, 0xFFFFFFFFU, 0x2A019FFEU);
+	psu_mask_write(0xFD081444, 0xFFFFFFFFU, 0x01100000U);
+	psu_mask_write(0xFD08145C, 0xFFFFFFFFU, 0x01264300U);
+	psu_mask_write(0xFD08146C, 0xFFFFFFFFU, 0x00041800U);
+	psu_mask_write(0xFD081470, 0xFFFFFFFFU, 0x70800000U);
+	psu_mask_write(0xFD081480, 0xFFFFFFFFU, 0x2A019FFEU);
+	psu_mask_write(0xFD081484, 0xFFFFFFFFU, 0x01100000U);
+	psu_mask_write(0xFD08149C, 0xFFFFFFFFU, 0x01264300U);
+	psu_mask_write(0xFD0814AC, 0xFFFFFFFFU, 0x00041800U);
+	psu_mask_write(0xFD0814B0, 0xFFFFFFFFU, 0x70800000U);
+	psu_mask_write(0xFD0814C0, 0xFFFFFFFFU, 0x2A019FFEU);
+	psu_mask_write(0xFD0814C4, 0xFFFFFFFFU, 0x01100000U);
+	psu_mask_write(0xFD0814DC, 0xFFFFFFFFU, 0x01264300U);
+	psu_mask_write(0xFD0814EC, 0xFFFFFFFFU, 0x00041800U);
+	psu_mask_write(0xFD0814F0, 0xFFFFFFFFU, 0x70800000U);
+	psu_mask_write(0xFD081500, 0xFFFFFFFFU, 0x15019FFEU);
+	psu_mask_write(0xFD081504, 0xFFFFFFFFU, 0x21100000U);
+	psu_mask_write(0xFD08151C, 0xFFFFFFFFU, 0x01266300U);
+	psu_mask_write(0xFD08152C, 0xFFFFFFFFU, 0x00041800U);
+	psu_mask_write(0xFD081530, 0xFFFFFFFFU, 0x70400000U);
+	psu_mask_write(0xFD0817DC, 0xFFFFFFFFU, 0x012643C4U);
+
+	return 1;
+}
+
+static unsigned long psu_ddr_qos_init_data(void)
+{
+	psu_mask_write(0xFD360008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD36001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD370008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD37001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD380008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD38001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD390008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD39001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD3A0008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD3A001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD3B0008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFD3B001C, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFF9B0008, 0x0000000FU, 0x00000000U);
+	psu_mask_write(0xFF9B001C, 0x0000000FU, 0x00000000U);
+
+	return 1;
+}
+
+static unsigned long psu_mio_init_data(void)
+{
+	psu_mask_write(0xFF180000, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180004, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180008, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF18000C, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180010, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180014, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180018, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF18001C, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180020, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180024, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180028, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF18002C, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180030, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180034, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180038, 0x000000FEU, 0x00000040U);
+	psu_mask_write(0xFF18003C, 0x000000FEU, 0x00000040U);
+	psu_mask_write(0xFF180040, 0x000000FEU, 0x00000040U);
+	psu_mask_write(0xFF180044, 0x000000FEU, 0x00000040U);
+	psu_mask_write(0xFF180048, 0x000000FEU, 0x000000C0U);
+	psu_mask_write(0xFF18004C, 0x000000FEU, 0x000000C0U);
+	psu_mask_write(0xFF180050, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180054, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180058, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF18005C, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180060, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180064, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180068, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF18006C, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180070, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180074, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180078, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF18007C, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF180080, 0x000000FEU, 0x00000008U);
+	psu_mask_write(0xFF180084, 0x000000FEU, 0x00000008U);
+	psu_mask_write(0xFF180098, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF18009C, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800A0, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800A4, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800A8, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800AC, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF1800B0, 0x000000FEU, 0x00000000U);
+	psu_mask_write(0xFF1800B4, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800B8, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800BC, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800C0, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800C4, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800C8, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800CC, 0x000000FEU, 0x00000010U);
+	psu_mask_write(0xFF1800D0, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800D4, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800D8, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800DC, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800E0, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800E4, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800E8, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800EC, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800F0, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800F4, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800F8, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF1800FC, 0x000000FEU, 0x00000004U);
+	psu_mask_write(0xFF180100, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180104, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180108, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF18010C, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180110, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180114, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180118, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF18011C, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180120, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180124, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180128, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF18012C, 0x000000FEU, 0x00000002U);
+	psu_mask_write(0xFF180130, 0x000000FEU, 0x000000C0U);
+	psu_mask_write(0xFF180134, 0x000000FEU, 0x000000C0U);
+	psu_mask_write(0xFF180204, 0xFFFFFFFFU, 0x00040000U);
+	psu_mask_write(0xFF180208, 0xFFFFFFFFU, 0x00B02000U);
+	psu_mask_write(0xFF18020C, 0x00003FFFU, 0x00000FC0U);
+	psu_mask_write(0xFF180138, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF18013C, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180140, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF180144, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180148, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF18014C, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF180154, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180158, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF18015C, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF180160, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180164, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180168, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF180170, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180174, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180178, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF18017C, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180180, 0x03FFFFFFU, 0x03FFFFFFU);
+	psu_mask_write(0xFF180184, 0x03FFFFFFU, 0x00000000U);
+	psu_mask_write(0xFF180200, 0x0000000FU, 0x00000000U);
+
+	return 1;
+}
+
+static unsigned long psu_peripherals_pre_init_data(void)
+{
+	psu_mask_write(0xFF5E0108, 0x013F3F07U, 0x01012302U);
+	psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000001U);
+
+	return 1;
+}
+
+static unsigned long psu_peripherals_init_data(void)
+{
+	psu_mask_write(0xFD1A0100, 0x00008046U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x001A0000U, 0x00000000U);
+	psu_mask_write(0xFF5E023C, 0x0093C018U, 0x00000000U);
+	psu_mask_write(0xFF5E0230, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFF180390, 0x00000004U, 0x00000004U);
+	psu_mask_write(0xFF5E023C, 0x00000400U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000040U, 0x00000000U);
+	psu_mask_write(0xFF180310, 0x00008000U, 0x00000000U);
+	psu_mask_write(0xFF180320, 0x33840000U, 0x02840000U);
+	psu_mask_write(0xFF18031C, 0x7FFE0000U, 0x64500000U);
+	psu_mask_write(0xFF180358, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFF180324, 0x03C00000U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000600U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00008000U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00007800U, 0x00000000U);
+	psu_mask_write(0xFF5E0238, 0x00000002U, 0x00000000U);
+	psu_mask_write(0xFF000034, 0x000000FFU, 0x00000006U);
+	psu_mask_write(0xFF000018, 0x0000FFFFU, 0x0000007CU);
+	psu_mask_write(0xFF000000, 0x000001FFU, 0x00000017U);
+	psu_mask_write(0xFF000004, 0x000003FFU, 0x00000020U);
+	psu_mask_write(0xFF5E0238, 0x00040000U, 0x00000000U);
+	psu_mask_write(0xFF4B0024, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFFCA5000, 0x00001FFFU, 0x00000000U);
+	psu_mask_write(0xFD5C0060, 0x000F000FU, 0x00000000U);
+	psu_mask_write(0xFFA60040, 0x80000000U, 0x80000000U);
+	psu_mask_write(0xFF260020, 0xFFFFFFFFU, 0x05F5DD18U);
+	psu_mask_write(0xFF260000, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
+
+	mask_delay(1);
+	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000002U);
+
+	mask_delay(5);
+	psu_mask_write(0xFF5E0250, 0x00000F0FU, 0x00000202U);
+
+	return 1;
+}
+
+static unsigned long psu_serdes_init_data(void)
+{
+	psu_mask_write(0xFD410008, 0x0000001FU, 0x00000008U);
+	psu_mask_write(0xFD41000C, 0x0000001FU, 0x0000000FU);
+	psu_mask_write(0xFD402868, 0x00000080U, 0x00000080U);
+	psu_mask_write(0xFD40286C, 0x00000080U, 0x00000080U);
+	psu_mask_write(0xFD40A094, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD40A368, 0x000000FFU, 0x00000038U);
+	psu_mask_write(0xFD40A36C, 0x00000007U, 0x00000003U);
+	psu_mask_write(0xFD40E368, 0x000000FFU, 0x000000E0U);
+	psu_mask_write(0xFD40E36C, 0x00000007U, 0x00000003U);
+	psu_mask_write(0xFD40A370, 0x000000FFU, 0x000000F4U);
+	psu_mask_write(0xFD40A374, 0x000000FFU, 0x00000031U);
+	psu_mask_write(0xFD40A378, 0x000000FFU, 0x00000002U);
+	psu_mask_write(0xFD40A37C, 0x00000033U, 0x00000030U);
+	psu_mask_write(0xFD40E370, 0x000000FFU, 0x000000C9U);
+	psu_mask_write(0xFD40E374, 0x000000FFU, 0x000000D2U);
+	psu_mask_write(0xFD40E378, 0x000000FFU, 0x00000001U);
+	psu_mask_write(0xFD40E37C, 0x000000B3U, 0x000000B0U);
+	psu_mask_write(0xFD40906C, 0x00000003U, 0x00000003U);
+	psu_mask_write(0xFD4080F4, 0x00000003U, 0x00000003U);
+	psu_mask_write(0xFD40E360, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40D06C, 0x0000000FU, 0x0000000FU);
+	psu_mask_write(0xFD40C0F4, 0x0000000BU, 0x0000000BU);
+	psu_mask_write(0xFD4090CC, 0x00000020U, 0x00000020U);
+	psu_mask_write(0xFD401074, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD405074, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD409074, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD40D074, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD401994, 0x00000007U, 0x00000007U);
+	psu_mask_write(0xFD405994, 0x00000007U, 0x00000007U);
+	psu_mask_write(0xFD40989C, 0x00000080U, 0x00000080U);
+	psu_mask_write(0xFD4098F8, 0x000000FFU, 0x0000001AU);
+	psu_mask_write(0xFD4098FC, 0x000000FFU, 0x0000001AU);
+	psu_mask_write(0xFD409990, 0x000000FFU, 0x00000010U);
+	psu_mask_write(0xFD409924, 0x000000FFU, 0x000000FEU);
+	psu_mask_write(0xFD409928, 0x000000FFU, 0x00000000U);
+	psu_mask_write(0xFD409900, 0x000000FFU, 0x0000001AU);
+	psu_mask_write(0xFD40992C, 0x000000FFU, 0x00000000U);
+	psu_mask_write(0xFD409980, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD409914, 0x000000FFU, 0x000000F7U);
+	psu_mask_write(0xFD409918, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD409940, 0x000000FFU, 0x000000F7U);
+	psu_mask_write(0xFD409944, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD409994, 0x00000007U, 0x00000007U);
+	psu_mask_write(0xFD40D89C, 0x00000080U, 0x00000080U);
+	psu_mask_write(0xFD40D8F8, 0x000000FFU, 0x0000007DU);
+	psu_mask_write(0xFD40D8FC, 0x000000FFU, 0x0000007DU);
+	psu_mask_write(0xFD40D990, 0x000000FFU, 0x00000001U);
+	psu_mask_write(0xFD40D924, 0x000000FFU, 0x0000009CU);
+	psu_mask_write(0xFD40D928, 0x000000FFU, 0x00000039U);
+	psu_mask_write(0xFD40D98C, 0x000000F0U, 0x00000020U);
+	psu_mask_write(0xFD40D900, 0x000000FFU, 0x0000007DU);
+	psu_mask_write(0xFD40D92C, 0x000000FFU, 0x00000064U);
+	psu_mask_write(0xFD40D980, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD40D914, 0x000000FFU, 0x000000F7U);
+	psu_mask_write(0xFD40D918, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD40D940, 0x000000FFU, 0x000000F7U);
+	psu_mask_write(0xFD40D944, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD40D994, 0x00000007U, 0x00000007U);
+	psu_mask_write(0xFD40107C, 0x0000000FU, 0x00000001U);
+	psu_mask_write(0xFD40507C, 0x0000000FU, 0x00000001U);
+	psu_mask_write(0xFD40907C, 0x0000000FU, 0x00000001U);
+	psu_mask_write(0xFD40D07C, 0x0000000FU, 0x00000001U);
+	psu_mask_write(0xFD4019A4, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD401038, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40102C, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD4059A4, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD405038, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40502C, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD4099A4, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD409038, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40902C, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40D9A4, 0x000000FFU, 0x000000FFU);
+	psu_mask_write(0xFD40D038, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD40D02C, 0x00000040U, 0x00000040U);
+	psu_mask_write(0xFD4019AC, 0x00000003U, 0x00000000U);
+	psu_mask_write(0xFD4059AC, 0x00000003U, 0x00000000U);
+	psu_mask_write(0xFD4099AC, 0x00000003U, 0x00000000U);
+	psu_mask_write(0xFD40D9AC, 0x00000003U, 0x00000000U);
+	psu_mask_write(0xFD401978, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD405978, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD409978, 0x00000010U, 0x00000010U);
+	psu_mask_write(0xFD40D978, 0x00000010U, 0x00000010U);
+
+	serdes_illcalib(2, 3, 3, 0, 0, 0, 0, 0);
+	psu_mask_write(0xFD410014, 0x00000077U, 0x00000023U);
+	psu_mask_write(0xFD40C1D8, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFD40DC14, 0x000000FFU, 0x000000E6U);
+	psu_mask_write(0xFD40DC40, 0x0000001FU, 0x0000000CU);
+	psu_mask_write(0xFD40D94C, 0x00000020U, 0x00000020U);
+	psu_mask_write(0xFD40D950, 0x00000007U, 0x00000006U);
+	psu_mask_write(0xFD40C048, 0x000000FFU, 0x00000001U);
+
+	return 1;
+}
+
+static unsigned long psu_resetout_init_data(void)
+{
+	psu_mask_write(0xFF5E023C, 0x00000400U, 0x00000000U);
+	psu_mask_write(0xFF9D0080, 0x00000001U, 0x00000001U);
+	psu_mask_write(0xFF9D007C, 0x00000001U, 0x00000000U);
+	psu_mask_write(0xFF5E023C, 0x00000140U, 0x00000000U);
+	psu_mask_write(0xFF5E0230, 0x00000008U, 0x00000000U);
+	psu_mask_write(0xFD3D0100, 0x00000003U, 0x00000003U);
+	psu_mask_write(0xFD1A0100, 0x00000002U, 0x00000000U);
+	psu_mask_write(0xFE20C200, 0x00023FFFU, 0x00022457U);
+	psu_mask_write(0xFE20C630, 0x003FFF00U, 0x00000000U);
+	psu_mask_write(0xFE20C11C, 0x00000600U, 0x00000600U);
+	psu_mask_write(0xFE20C12C, 0x00004000U, 0x00004000U);
+	psu_mask_write(0xFD480064, 0x00000200U, 0x00000200U);
+	mask_poll(0xFD40A3E4, 0x00000010U);
+	mask_poll(0xFD40E3E4, 0x00000010U);
+	psu_mask_write(0xFD0C00AC, 0xFFFFFFFFU, 0x28184018U);
+	psu_mask_write(0xFD0C00B0, 0xFFFFFFFFU, 0x0E081406U);
+	psu_mask_write(0xFD0C00B4, 0xFFFFFFFFU, 0x064A0813U);
+	psu_mask_write(0xFD0C00B8, 0xFFFFFFFFU, 0x3FFC96A4U);
+
+	return 1;
+}
+
+static unsigned long psu_resetin_init_data(void)
+{
+	psu_mask_write(0xFF5E023C, 0x00000540U, 0x00000540U);
+	psu_mask_write(0xFF5E0230, 0x00000008U, 0x00000008U);
+	psu_mask_write(0xFD1A0100, 0x00000002U, 0x00000002U);
+
+	return 1;
+}
+
+static unsigned long psu_afi_config(void)
+{
+	psu_mask_write(0xFD1A0100, 0x00001F80U, 0x00000000U);
+	psu_mask_write(0xFF5E023C, 0x00080000U, 0x00000000U);
+	psu_mask_write(0xFD615000, 0x00000300U, 0x00000200U);
+	psu_mask_write(0xFD360000, 0x00000003U, 0x00000002U);
+	psu_mask_write(0xFD370000, 0x00000003U, 0x00000002U);
+	psu_mask_write(0xFD360014, 0x00000003U, 0x00000002U);
+	psu_mask_write(0xFD370014, 0x00000003U, 0x00000002U);
+
+	return 1;
+}
+
+static unsigned long psu_ddr_phybringup_data(void)
+{
+	unsigned int regval = 0;
+	unsigned int pll_retry = 10;
+	unsigned int pll_locked = 0;
+	int cur_R006_tREFPRD;
+
+	while ((pll_retry > 0) && (!pll_locked)) {
+		Xil_Out32(0xFD080004, 0x00040010);
+		Xil_Out32(0xFD080004, 0x00040011);
+
+		while ((Xil_In32(0xFD080030) & 0x1) != 1)
+			;
+		pll_locked = (Xil_In32(0xFD080030) & 0x80000000)
+		    >> 31;
+		pll_locked &= (Xil_In32(0xFD0807E0) & 0x10000)
+		    >> 16;
+		pll_locked &= (Xil_In32(0xFD0809E0) & 0x10000) >> 16;
+		pll_locked &= (Xil_In32(0xFD080BE0) & 0x10000)
+		    >> 16;
+		pll_locked &= (Xil_In32(0xFD080DE0) & 0x10000)
+		    >> 16;
+		pll_retry--;
+	}
+	Xil_Out32(0xFD0800C4, Xil_In32(0xFD0800C4) | (pll_retry << 16));
+	if (!pll_locked)
+		return 0;
+
+	Xil_Out32(0xFD080004U, 0x00040063U);
+
+	while ((Xil_In32(0xFD080030U) & 0x0000000FU) != 0x0000000FU)
+		;
+	prog_reg(0xFD080004U, 0x00000001U, 0x00000000U, 0x00000001U);
+
+	while ((Xil_In32(0xFD080030U) & 0x000000FFU) != 0x0000001FU)
+		;
+	Xil_Out32(0xFD0701B0U, 0x00000001U);
+	Xil_Out32(0xFD070320U, 0x00000001U);
+	while ((Xil_In32(0xFD070004U) & 0x0000000FU) != 0x00000001U)
+		;
+	prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000001U);
+	Xil_Out32(0xFD080004, 0x0004FE01);
+	regval = Xil_In32(0xFD080030);
+	while (regval != 0x80000FFF)
+		regval = Xil_In32(0xFD080030);
+	regval = ((Xil_In32(0xFD080030) & 0x1FFF0000) >> 18);
+	if (regval != 0)
+		return 0;
+
+	Xil_Out32(0xFD080200U, 0x100091C7U);
+
+	cur_R006_tREFPRD = (Xil_In32(0xFD080018U) & 0x0003FFFFU) >> 0x00000000U;
+	prog_reg(0xFD080018, 0x3FFFF, 0x0, cur_R006_tREFPRD);
+
+	prog_reg(0xFD08001CU, 0x00000018U, 0x00000003U, 0x00000003U);
+	prog_reg(0xFD08142CU, 0x00000030U, 0x00000004U, 0x00000003U);
+	prog_reg(0xFD08146CU, 0x00000030U, 0x00000004U, 0x00000003U);
+	prog_reg(0xFD0814ACU, 0x00000030U, 0x00000004U, 0x00000003U);
+	prog_reg(0xFD0814ECU, 0x00000030U, 0x00000004U, 0x00000003U);
+	prog_reg(0xFD08152CU, 0x00000030U, 0x00000004U, 0x00000003U);
+
+	Xil_Out32(0xFD080004, 0x00060001);
+	regval = Xil_In32(0xFD080030);
+	while ((regval & 0x80004001) != 0x80004001)
+		regval = Xil_In32(0xFD080030);
+
+	regval = ((Xil_In32(0xFD080030) & 0x1FFF0000) >> 18);
+	if (regval != 0)
+		return 0;
+
+	prog_reg(0xFD08001CU, 0x00000018U, 0x00000003U, 0x00000000U);
+	prog_reg(0xFD08142CU, 0x00000030U, 0x00000004U, 0x00000000U);
+	prog_reg(0xFD08146CU, 0x00000030U, 0x00000004U, 0x00000000U);
+	prog_reg(0xFD0814ACU, 0x00000030U, 0x00000004U, 0x00000000U);
+	prog_reg(0xFD0814ECU, 0x00000030U, 0x00000004U, 0x00000000U);
+	prog_reg(0xFD08152CU, 0x00000030U, 0x00000004U, 0x00000000U);
+
+	Xil_Out32(0xFD080200U, 0x800091C7U);
+	prog_reg(0xFD080018, 0x3FFFF, 0x0, cur_R006_tREFPRD);
+
+	Xil_Out32(0xFD080004, 0x0000C001);
+	regval = Xil_In32(0xFD080030);
+	while ((regval & 0x80000C01) != 0x80000C01)
+		regval = Xil_In32(0xFD080030);
+
+	Xil_Out32(0xFD070180U, 0x01000040U);
+	Xil_Out32(0xFD070060U, 0x00000000U);
+	prog_reg(0xFD080014U, 0x00000040U, 0x00000006U, 0x00000000U);
+
+	return 1;
+}
+
+static int serdes_rst_seq(u32 lane3_protocol, u32 lane3_rate,
+			  u32 lane2_protocol, u32 lane2_rate,
+			  u32 lane1_protocol, u32 lane1_rate,
+			  u32 lane0_protocol, u32 lane0_rate)
+{
+	Xil_Out32(0xFD410098, 0x00000000);
+	Xil_Out32(0xFD401010, 0x00000040);
+	Xil_Out32(0xFD405010, 0x00000040);
+	Xil_Out32(0xFD409010, 0x00000040);
+	Xil_Out32(0xFD40D010, 0x00000040);
+	Xil_Out32(0xFD402084, 0x00000080);
+	Xil_Out32(0xFD406084, 0x00000080);
+	Xil_Out32(0xFD40A084, 0x00000080);
+	Xil_Out32(0xFD40E084, 0x00000080);
+	Xil_Out32(0xFD410098, 0x00000004);
+	mask_delay(50);
+	if (lane0_rate == 1)
+		Xil_Out32(0xFD410098, 0x0000000E);
+	Xil_Out32(0xFD410098, 0x00000006);
+	if (lane0_rate == 1) {
+		Xil_Out32(0xFD40000C, 0x00000004);
+		Xil_Out32(0xFD40400C, 0x00000004);
+		Xil_Out32(0xFD40800C, 0x00000004);
+		Xil_Out32(0xFD40C00C, 0x00000004);
+		Xil_Out32(0xFD410098, 0x00000007);
+		mask_delay(400);
+		Xil_Out32(0xFD40000C, 0x0000000C);
+		Xil_Out32(0xFD40400C, 0x0000000C);
+		Xil_Out32(0xFD40800C, 0x0000000C);
+		Xil_Out32(0xFD40C00C, 0x0000000C);
+		mask_delay(15);
+		Xil_Out32(0xFD410098, 0x0000000F);
+		mask_delay(100);
+	}
+	if (lane0_protocol != 0)
+		mask_poll(0xFD4023E4, 0x00000010U);
+	if (lane1_protocol != 0)
+		mask_poll(0xFD4063E4, 0x00000010U);
+	if (lane2_protocol != 0)
+		mask_poll(0xFD40A3E4, 0x00000010U);
+	if (lane3_protocol != 0)
+		mask_poll(0xFD40E3E4, 0x00000010U);
+	mask_delay(50);
+	Xil_Out32(0xFD401010, 0x000000C0);
+	Xil_Out32(0xFD405010, 0x000000C0);
+	Xil_Out32(0xFD409010, 0x000000C0);
+	Xil_Out32(0xFD40D010, 0x000000C0);
+	Xil_Out32(0xFD401010, 0x00000080);
+	Xil_Out32(0xFD405010, 0x00000080);
+	Xil_Out32(0xFD409010, 0x00000080);
+	Xil_Out32(0xFD40D010, 0x00000080);
+
+	Xil_Out32(0xFD402084, 0x000000C0);
+	Xil_Out32(0xFD406084, 0x000000C0);
+	Xil_Out32(0xFD40A084, 0x000000C0);
+	Xil_Out32(0xFD40E084, 0x000000C0);
+	mask_delay(50);
+	Xil_Out32(0xFD402084, 0x00000080);
+	Xil_Out32(0xFD406084, 0x00000080);
+	Xil_Out32(0xFD40A084, 0x00000080);
+	Xil_Out32(0xFD40E084, 0x00000080);
+	mask_delay(50);
+	Xil_Out32(0xFD401010, 0x00000000);
+	Xil_Out32(0xFD405010, 0x00000000);
+	Xil_Out32(0xFD409010, 0x00000000);
+	Xil_Out32(0xFD40D010, 0x00000000);
+	Xil_Out32(0xFD402084, 0x00000000);
+	Xil_Out32(0xFD406084, 0x00000000);
+	Xil_Out32(0xFD40A084, 0x00000000);
+	Xil_Out32(0xFD40E084, 0x00000000);
+	mask_delay(500);
+	return 1;
+}
+
+static int serdes_bist_static_settings(u32 lane_active)
+{
+	if (lane_active == 0) {
+		Xil_Out32(0xFD403004, (Xil_In32(0xFD403004) & 0xFFFFFF1F));
+		Xil_Out32(0xFD403068, 0x1);
+		Xil_Out32(0xFD40306C, 0x1);
+		Xil_Out32(0xFD4010AC, 0x0020);
+		Xil_Out32(0xFD403008, 0x0);
+		Xil_Out32(0xFD40300C, 0xF4);
+		Xil_Out32(0xFD403010, 0x0);
+		Xil_Out32(0xFD403014, 0x0);
+		Xil_Out32(0xFD403018, 0x00);
+		Xil_Out32(0xFD40301C, 0xFB);
+		Xil_Out32(0xFD403020, 0xFF);
+		Xil_Out32(0xFD403024, 0x0);
+		Xil_Out32(0xFD403028, 0x00);
+		Xil_Out32(0xFD40302C, 0x00);
+		Xil_Out32(0xFD403030, 0x4A);
+		Xil_Out32(0xFD403034, 0x4A);
+		Xil_Out32(0xFD403038, 0x4A);
+		Xil_Out32(0xFD40303C, 0x4A);
+		Xil_Out32(0xFD403040, 0x0);
+		Xil_Out32(0xFD403044, 0x14);
+		Xil_Out32(0xFD403048, 0x02);
+		Xil_Out32(0xFD403004, (Xil_In32(0xFD403004) & 0xFFFFFF1F));
+	}
+	if (lane_active == 1) {
+		Xil_Out32(0xFD407004, (Xil_In32(0xFD407004) & 0xFFFFFF1F));
+		Xil_Out32(0xFD407068, 0x1);
+		Xil_Out32(0xFD40706C, 0x1);
+		Xil_Out32(0xFD4050AC, 0x0020);
+		Xil_Out32(0xFD407008, 0x0);
+		Xil_Out32(0xFD40700C, 0xF4);
+		Xil_Out32(0xFD407010, 0x0);
+		Xil_Out32(0xFD407014, 0x0);
+		Xil_Out32(0xFD407018, 0x00);
+		Xil_Out32(0xFD40701C, 0xFB);
+		Xil_Out32(0xFD407020, 0xFF);
+		Xil_Out32(0xFD407024, 0x0);
+		Xil_Out32(0xFD407028, 0x00);
+		Xil_Out32(0xFD40702C, 0x00);
+		Xil_Out32(0xFD407030, 0x4A);
+		Xil_Out32(0xFD407034, 0x4A);
+		Xil_Out32(0xFD407038, 0x4A);
+		Xil_Out32(0xFD40703C, 0x4A);
+		Xil_Out32(0xFD407040, 0x0);
+		Xil_Out32(0xFD407044, 0x14);
+		Xil_Out32(0xFD407048, 0x02);
+		Xil_Out32(0xFD407004, (Xil_In32(0xFD407004) & 0xFFFFFF1F));
+	}
+
+	if (lane_active == 2) {
+		Xil_Out32(0xFD40B004, (Xil_In32(0xFD40B004) & 0xFFFFFF1F));
+		Xil_Out32(0xFD40B068, 0x1);
+		Xil_Out32(0xFD40B06C, 0x1);
+		Xil_Out32(0xFD4090AC, 0x0020);
+		Xil_Out32(0xFD40B008, 0x0);
+		Xil_Out32(0xFD40B00C, 0xF4);
+		Xil_Out32(0xFD40B010, 0x0);
+		Xil_Out32(0xFD40B014, 0x0);
+		Xil_Out32(0xFD40B018, 0x00);
+		Xil_Out32(0xFD40B01C, 0xFB);
+		Xil_Out32(0xFD40B020, 0xFF);
+		Xil_Out32(0xFD40B024, 0x0);
+		Xil_Out32(0xFD40B028, 0x00);
+		Xil_Out32(0xFD40B02C, 0x00);
+		Xil_Out32(0xFD40B030, 0x4A);
+		Xil_Out32(0xFD40B034, 0x4A);
+		Xil_Out32(0xFD40B038, 0x4A);
+		Xil_Out32(0xFD40B03C, 0x4A);
+		Xil_Out32(0xFD40B040, 0x0);
+		Xil_Out32(0xFD40B044, 0x14);
+		Xil_Out32(0xFD40B048, 0x02);
+		Xil_Out32(0xFD40B004, (Xil_In32(0xFD40B004) & 0xFFFFFF1F));
+	}
+
+	if (lane_active == 3) {
+		Xil_Out32(0xFD40F004, (Xil_In32(0xFD40F004) & 0xFFFFFF1F));
+		Xil_Out32(0xFD40F068, 0x1);
+		Xil_Out32(0xFD40F06C, 0x1);
+		Xil_Out32(0xFD40D0AC, 0x0020);
+		Xil_Out32(0xFD40F008, 0x0);
+		Xil_Out32(0xFD40F00C, 0xF4);
+		Xil_Out32(0xFD40F010, 0x0);
+		Xil_Out32(0xFD40F014, 0x0);
+		Xil_Out32(0xFD40F018, 0x00);
+		Xil_Out32(0xFD40F01C, 0xFB);
+		Xil_Out32(0xFD40F020, 0xFF);
+		Xil_Out32(0xFD40F024, 0x0);
+		Xil_Out32(0xFD40F028, 0x00);
+		Xil_Out32(0xFD40F02C, 0x00);
+		Xil_Out32(0xFD40F030, 0x4A);
+		Xil_Out32(0xFD40F034, 0x4A);
+		Xil_Out32(0xFD40F038, 0x4A);
+		Xil_Out32(0xFD40F03C, 0x4A);
+		Xil_Out32(0xFD40F040, 0x0);
+		Xil_Out32(0xFD40F044, 0x14);
+		Xil_Out32(0xFD40F048, 0x02);
+		Xil_Out32(0xFD40F004, (Xil_In32(0xFD40F004) & 0xFFFFFF1F));
+	}
+	return 1;
+}
+
+static int serdes_bist_run(u32 lane_active)
+{
+	if (lane_active == 0) {
+		psu_mask_write(0xFD410044, 0x00000003U, 0x00000000U);
+		psu_mask_write(0xFD410040, 0x00000003U, 0x00000000U);
+		psu_mask_write(0xFD410038, 0x00000007U, 0x00000001U);
+		Xil_Out32(0xFD4010AC, 0x0020);
+		Xil_Out32(0xFD403004, (Xil_In32(0xFD403004) | 0x1));
+	}
+	if (lane_active == 1) {
+		psu_mask_write(0xFD410044, 0x0000000CU, 0x00000000U);
+		psu_mask_write(0xFD410040, 0x0000000CU, 0x00000000U);
+		psu_mask_write(0xFD410038, 0x00000070U, 0x00000010U);
+		Xil_Out32(0xFD4050AC, 0x0020);
+		Xil_Out32(0xFD407004, (Xil_In32(0xFD407004) | 0x1));
+	}
+	if (lane_active == 2) {
+		psu_mask_write(0xFD410044, 0x00000030U, 0x00000000U);
+		psu_mask_write(0xFD410040, 0x00000030U, 0x00000000U);
+		psu_mask_write(0xFD41003C, 0x00000007U, 0x00000001U);
+		Xil_Out32(0xFD4090AC, 0x0020);
+		Xil_Out32(0xFD40B004, (Xil_In32(0xFD40B004) | 0x1));
+	}
+	if (lane_active == 3) {
+		psu_mask_write(0xFD410040, 0x000000C0U, 0x00000000U);
+		psu_mask_write(0xFD410044, 0x000000C0U, 0x00000000U);
+		psu_mask_write(0xFD41003C, 0x00000070U, 0x00000010U);
+		Xil_Out32(0xFD40D0AC, 0x0020);
+		Xil_Out32(0xFD40F004, (Xil_In32(0xFD40F004) | 0x1));
+	}
+	mask_delay(100);
+	return 1;
+}
+
+static int serdes_bist_result(u32 lane_active)
+{
+	u32 pkt_cnt_l0, pkt_cnt_h0, err_cnt_l0, err_cnt_h0;
+
+	if (lane_active == 0) {
+		pkt_cnt_l0 = Xil_In32(0xFD40304C);
+		pkt_cnt_h0 = Xil_In32(0xFD403050);
+		err_cnt_l0 = Xil_In32(0xFD403054);
+		err_cnt_h0 = Xil_In32(0xFD403058);
+	}
+	if (lane_active == 1) {
+		pkt_cnt_l0 = Xil_In32(0xFD40704C);
+		pkt_cnt_h0 = Xil_In32(0xFD407050);
+		err_cnt_l0 = Xil_In32(0xFD407054);
+		err_cnt_h0 = Xil_In32(0xFD407058);
+	}
+	if (lane_active == 2) {
+		pkt_cnt_l0 = Xil_In32(0xFD40B04C);
+		pkt_cnt_h0 = Xil_In32(0xFD40B050);
+		err_cnt_l0 = Xil_In32(0xFD40B054);
+		err_cnt_h0 = Xil_In32(0xFD40B058);
+	}
+	if (lane_active == 3) {
+		pkt_cnt_l0 = Xil_In32(0xFD40F04C);
+		pkt_cnt_h0 = Xil_In32(0xFD40F050);
+		err_cnt_l0 = Xil_In32(0xFD40F054);
+		err_cnt_h0 = Xil_In32(0xFD40F058);
+	}
+	if (lane_active == 0)
+		Xil_Out32(0xFD403004, 0x0);
+	if (lane_active == 1)
+		Xil_Out32(0xFD407004, 0x0);
+	if (lane_active == 2)
+		Xil_Out32(0xFD40B004, 0x0);
+	if (lane_active == 3)
+		Xil_Out32(0xFD40F004, 0x0);
+	if (err_cnt_l0 > 0 || err_cnt_h0 > 0 ||
+	    (pkt_cnt_l0 == 0 && pkt_cnt_h0 == 0))
+		return 0;
+	return 1;
+}
+
+static int serdes_illcalib_pcie_gen1(u32 lane3_protocol, u32 lane3_rate,
+				     u32 lane2_protocol, u32 lane2_rate,
+				     u32 lane1_protocol, u32 lane1_rate,
+				     u32 lane0_protocol, u32 lane0_rate,
+				     u32 gen2_calib)
+{
+	u64 tempbistresult;
+	u32 currbistresult[4];
+	u32 prevbistresult[4];
+	u32 itercount = 0;
+	u32 ill12_val[4], ill1_val[4];
+	u32 loop = 0;
+	u32 iterresult[8];
+	u32 meancount[4];
+	u32 bistpasscount[4];
+	u32 meancountalt[4];
+	u32 meancountalt_bistpasscount[4];
+	u32 lane0_active;
+	u32 lane1_active;
+	u32 lane2_active;
+	u32 lane3_active;
+
+	lane0_active = (lane0_protocol == 1);
+	lane1_active = (lane1_protocol == 1);
+	lane2_active = (lane2_protocol == 1);
+	lane3_active = (lane3_protocol == 1);
+	for (loop = 0; loop <= 3; loop++) {
+		iterresult[loop] = 0;
+		iterresult[loop + 4] = 0;
+		meancountalt[loop] = 0;
+		meancountalt_bistpasscount[loop] = 0;
+		meancount[loop] = 0;
+		prevbistresult[loop] = 0;
+		bistpasscount[loop] = 0;
+	}
+	itercount = 0;
+	if (lane0_active)
+		serdes_bist_static_settings(0);
+	if (lane1_active)
+		serdes_bist_static_settings(1);
+	if (lane2_active)
+		serdes_bist_static_settings(2);
+	if (lane3_active)
+		serdes_bist_static_settings(3);
+	do {
+		if (gen2_calib != 1) {
+			if (lane0_active == 1)
+				ill1_val[0] = ((0x04 + itercount * 8) % 0x100);
+			if (lane0_active == 1)
+				ill12_val[0] =
+				    ((0x04 + itercount * 8) >=
+				     0x100) ? 0x10 : 0x00;
+			if (lane1_active == 1)
+				ill1_val[1] = ((0x04 + itercount * 8) % 0x100);
+			if (lane1_active == 1)
+				ill12_val[1] =
+				    ((0x04 + itercount * 8) >=
+				     0x100) ? 0x10 : 0x00;
+			if (lane2_active == 1)
+				ill1_val[2] = ((0x04 + itercount * 8) % 0x100);
+			if (lane2_active == 1)
+				ill12_val[2] =
+				    ((0x04 + itercount * 8) >=
+				     0x100) ? 0x10 : 0x00;
+			if (lane3_active == 1)
+				ill1_val[3] = ((0x04 + itercount * 8) % 0x100);
+			if (lane3_active == 1)
+				ill12_val[3] =
+				    ((0x04 + itercount * 8) >=
+				     0x100) ? 0x10 : 0x00;
+
+			if (lane0_active == 1)
+				Xil_Out32(0xFD401924, ill1_val[0]);
+			if (lane0_active == 1)
+				psu_mask_write(0xFD401990, 0x000000F0U,
+					       ill12_val[0]);
+			if (lane1_active == 1)
+				Xil_Out32(0xFD405924, ill1_val[1]);
+			if (lane1_active == 1)
+				psu_mask_write(0xFD405990, 0x000000F0U,
+					       ill12_val[1]);
+			if (lane2_active == 1)
+				Xil_Out32(0xFD409924, ill1_val[2]);
+			if (lane2_active == 1)
+				psu_mask_write(0xFD409990, 0x000000F0U,
+					       ill12_val[2]);
+			if (lane3_active == 1)
+				Xil_Out32(0xFD40D924, ill1_val[3]);
+			if (lane3_active == 1)
+				psu_mask_write(0xFD40D990, 0x000000F0U,
+					       ill12_val[3]);
+		}
+		if (gen2_calib == 1) {
+			if (lane0_active == 1)
+				ill1_val[0] = ((0x104 + itercount * 8) % 0x100);
+			if (lane0_active == 1)
+				ill12_val[0] =
+				    ((0x104 + itercount * 8) >=
+				     0x200) ? 0x02 : 0x01;
+			if (lane1_active == 1)
+				ill1_val[1] = ((0x104 + itercount * 8) % 0x100);
+			if (lane1_active == 1)
+				ill12_val[1] =
+				    ((0x104 + itercount * 8) >=
+				     0x200) ? 0x02 : 0x01;
+			if (lane2_active == 1)
+				ill1_val[2] = ((0x104 + itercount * 8) % 0x100);
+			if (lane2_active == 1)
+				ill12_val[2] =
+				    ((0x104 + itercount * 8) >=
+				     0x200) ? 0x02 : 0x01;
+			if (lane3_active == 1)
+				ill1_val[3] = ((0x104 + itercount * 8) % 0x100);
+			if (lane3_active == 1)
+				ill12_val[3] =
+				    ((0x104 + itercount * 8) >=
+				     0x200) ? 0x02 : 0x01;
+
+			if (lane0_active == 1)
+				Xil_Out32(0xFD401928, ill1_val[0]);
+			if (lane0_active == 1)
+				psu_mask_write(0xFD401990, 0x0000000FU,
+					       ill12_val[0]);
+			if (lane1_active == 1)
+				Xil_Out32(0xFD405928, ill1_val[1]);
+			if (lane1_active == 1)
+				psu_mask_write(0xFD405990, 0x0000000FU,
+					       ill12_val[1]);
+			if (lane2_active == 1)
+				Xil_Out32(0xFD409928, ill1_val[2]);
+			if (lane2_active == 1)
+				psu_mask_write(0xFD409990, 0x0000000FU,
+					       ill12_val[2]);
+			if (lane3_active == 1)
+				Xil_Out32(0xFD40D928, ill1_val[3]);
+			if (lane3_active == 1)
+				psu_mask_write(0xFD40D990, 0x0000000FU,
+					       ill12_val[3]);
+		}
+
+		if (lane0_active == 1)
+			psu_mask_write(0xFD401018, 0x00000030U, 0x00000010U);
+		if (lane1_active == 1)
+			psu_mask_write(0xFD405018, 0x00000030U, 0x00000010U);
+		if (lane2_active == 1)
+			psu_mask_write(0xFD409018, 0x00000030U, 0x00000010U);
+		if (lane3_active == 1)
+			psu_mask_write(0xFD40D018, 0x00000030U, 0x00000010U);
+		if (lane0_active == 1)
+			currbistresult[0] = 0;
+		if (lane1_active == 1)
+			currbistresult[1] = 0;
+		if (lane2_active == 1)
+			currbistresult[2] = 0;
+		if (lane3_active == 1)
+			currbistresult[3] = 0;
+		serdes_rst_seq(lane3_protocol, lane3_rate, lane2_protocol,
+			       lane2_rate, lane1_protocol, lane1_rate,
+			       lane0_protocol, lane0_rate);
+		if (lane3_active == 1)
+			serdes_bist_run(3);
+		if (lane2_active == 1)
+			serdes_bist_run(2);
+		if (lane1_active == 1)
+			serdes_bist_run(1);
+		if (lane0_active == 1)
+			serdes_bist_run(0);
+		tempbistresult = 0;
+		if (lane3_active == 1)
+			tempbistresult = tempbistresult | serdes_bist_result(3);
+		tempbistresult = tempbistresult << 1;
+		if (lane2_active == 1)
+			tempbistresult = tempbistresult | serdes_bist_result(2);
+		tempbistresult = tempbistresult << 1;
+		if (lane1_active == 1)
+			tempbistresult = tempbistresult | serdes_bist_result(1);
+		tempbistresult = tempbistresult << 1;
+		if (lane0_active == 1)
+			tempbistresult = tempbistresult | serdes_bist_result(0);
+		Xil_Out32(0xFD410098, 0x0);
+		Xil_Out32(0xFD410098, 0x2);
+
+		if (itercount < 32) {
+			iterresult[0] =
+			    ((iterresult[0] << 1) |
+			     ((tempbistresult & 0x1) == 0x1));
+			iterresult[1] =
+			    ((iterresult[1] << 1) |
+			     ((tempbistresult & 0x2) == 0x2));
+			iterresult[2] =
+			    ((iterresult[2] << 1) |
+			     ((tempbistresult & 0x4) == 0x4));
+			iterresult[3] =
+			    ((iterresult[3] << 1) |
+			     ((tempbistresult & 0x8) == 0x8));
+		} else {
+			iterresult[4] =
+			    ((iterresult[4] << 1) |
+			     ((tempbistresult & 0x1) == 0x1));
+			iterresult[5] =
+			    ((iterresult[5] << 1) |
+			     ((tempbistresult & 0x2) == 0x2));
+			iterresult[6] =
+			    ((iterresult[6] << 1) |
+			     ((tempbistresult & 0x4) == 0x4));
+			iterresult[7] =
+			    ((iterresult[7] << 1) |
+			     ((tempbistresult & 0x8) == 0x8));
+		}
+		currbistresult[0] =
+		    currbistresult[0] | ((tempbistresult & 0x1) == 1);
+		currbistresult[1] =
+		    currbistresult[1] | ((tempbistresult & 0x2) == 0x2);
+		currbistresult[2] =
+		    currbistresult[2] | ((tempbistresult & 0x4) == 0x4);
+		currbistresult[3] =
+		    currbistresult[3] | ((tempbistresult & 0x8) == 0x8);
+
+		for (loop = 0; loop <= 3; loop++) {
+			if (currbistresult[loop] == 1 && prevbistresult[loop] == 1)
+				bistpasscount[loop] = bistpasscount[loop] + 1;
+			if (bistpasscount[loop] < 4 && currbistresult[loop] == 0 &&
+			    itercount > 2) {
+				if (meancountalt_bistpasscount[loop] <
+				    bistpasscount[loop]) {
+					meancountalt_bistpasscount[loop] =
+					    bistpasscount[loop];
+					meancountalt[loop] =
+					    ((itercount - 1) -
+					     ((bistpasscount[loop] + 1) / 2));
+				}
+				bistpasscount[loop] = 0;
+			}
+			if (meancount[loop] == 0 && bistpasscount[loop] >= 4 &&
+			    (currbistresult[loop] == 0 || itercount == 63) &&
+			    prevbistresult[loop] == 1)
+				meancount[loop] =
+				    (itercount - 1) -
+				    ((bistpasscount[loop] + 1) / 2);
+			prevbistresult[loop] = currbistresult[loop];
+		}
+	} while (++itercount < 64);
+
+	for (loop = 0; loop <= 3; loop++) {
+		if (lane0_active == 0 && loop == 0)
+			continue;
+		if (lane1_active == 0 && loop == 1)
+			continue;
+		if (lane2_active == 0 && loop == 2)
+			continue;
+		if (lane3_active == 0 && loop == 3)
+			continue;
+
+		if (meancount[loop] == 0)
+			meancount[loop] = meancountalt[loop];
+
+		if (gen2_calib != 1) {
+			ill1_val[loop] = ((0x04 + meancount[loop] * 8) % 0x100);
+			ill12_val[loop] =
+			    ((0x04 + meancount[loop] * 8) >=
+			     0x100) ? 0x10 : 0x00;
+			Xil_Out32(0xFFFE0000 + loop * 4, iterresult[loop]);
+			Xil_Out32(0xFFFE0010 + loop * 4, iterresult[loop + 4]);
+			Xil_Out32(0xFFFE0020 + loop * 4, bistpasscount[loop]);
+			Xil_Out32(0xFFFE0030 + loop * 4, meancount[loop]);
+		}
+		if (gen2_calib == 1) {
+			ill1_val[loop] =
+			    ((0x104 + meancount[loop] * 8) % 0x100);
+			ill12_val[loop] =
+			    ((0x104 + meancount[loop] * 8) >=
+			     0x200) ? 0x02 : 0x01;
+			Xil_Out32(0xFFFE0040 + loop * 4, iterresult[loop]);
+			Xil_Out32(0xFFFE0050 + loop * 4, iterresult[loop + 4]);
+			Xil_Out32(0xFFFE0060 + loop * 4, bistpasscount[loop]);
+			Xil_Out32(0xFFFE0070 + loop * 4, meancount[loop]);
+		}
+	}
+	if (gen2_calib != 1) {
+		if (lane0_active == 1)
+			Xil_Out32(0xFD401924, ill1_val[0]);
+		if (lane0_active == 1)
+			psu_mask_write(0xFD401990, 0x000000F0U, ill12_val[0]);
+		if (lane1_active == 1)
+			Xil_Out32(0xFD405924, ill1_val[1]);
+		if (lane1_active == 1)
+			psu_mask_write(0xFD405990, 0x000000F0U, ill12_val[1]);
+		if (lane2_active == 1)
+			Xil_Out32(0xFD409924, ill1_val[2]);
+		if (lane2_active == 1)
+			psu_mask_write(0xFD409990, 0x000000F0U, ill12_val[2]);
+		if (lane3_active == 1)
+			Xil_Out32(0xFD40D924, ill1_val[3]);
+		if (lane3_active == 1)
+			psu_mask_write(0xFD40D990, 0x000000F0U, ill12_val[3]);
+	}
+	if (gen2_calib == 1) {
+		if (lane0_active == 1)
+			Xil_Out32(0xFD401928, ill1_val[0]);
+		if (lane0_active == 1)
+			psu_mask_write(0xFD401990, 0x0000000FU, ill12_val[0]);
+		if (lane1_active == 1)
+			Xil_Out32(0xFD405928, ill1_val[1]);
+		if (lane1_active == 1)
+			psu_mask_write(0xFD405990, 0x0000000FU, ill12_val[1]);
+		if (lane2_active == 1)
+			Xil_Out32(0xFD409928, ill1_val[2]);
+		if (lane2_active == 1)
+			psu_mask_write(0xFD409990, 0x0000000FU, ill12_val[2]);
+		if (lane3_active == 1)
+			Xil_Out32(0xFD40D928, ill1_val[3]);
+		if (lane3_active == 1)
+			psu_mask_write(0xFD40D990, 0x0000000FU, ill12_val[3]);
+	}
+
+	if (lane0_active == 1)
+		psu_mask_write(0xFD401018, 0x00000030U, 0x00000000U);
+	if (lane1_active == 1)
+		psu_mask_write(0xFD405018, 0x00000030U, 0x00000000U);
+	if (lane2_active == 1)
+		psu_mask_write(0xFD409018, 0x00000030U, 0x00000000U);
+	if (lane3_active == 1)
+		psu_mask_write(0xFD40D018, 0x00000030U, 0x00000000U);
+
+	Xil_Out32(0xFD410098, 0);
+	if (lane0_active == 1) {
+		Xil_Out32(0xFD403004, 0);
+		Xil_Out32(0xFD403008, 0);
+		Xil_Out32(0xFD40300C, 0);
+		Xil_Out32(0xFD403010, 0);
+		Xil_Out32(0xFD403014, 0);
+		Xil_Out32(0xFD403018, 0);
+		Xil_Out32(0xFD40301C, 0);
+		Xil_Out32(0xFD403020, 0);
+		Xil_Out32(0xFD403024, 0);
+		Xil_Out32(0xFD403028, 0);
+		Xil_Out32(0xFD40302C, 0);
+		Xil_Out32(0xFD403030, 0);
+		Xil_Out32(0xFD403034, 0);
+		Xil_Out32(0xFD403038, 0);
+		Xil_Out32(0xFD40303C, 0);
+		Xil_Out32(0xFD403040, 0);
+		Xil_Out32(0xFD403044, 0);
+		Xil_Out32(0xFD403048, 0);
+		Xil_Out32(0xFD40304C, 0);
+		Xil_Out32(0xFD403050, 0);
+		Xil_Out32(0xFD403054, 0);
+		Xil_Out32(0xFD403058, 0);
+		Xil_Out32(0xFD403068, 1);
+		Xil_Out32(0xFD40306C, 0);
+		Xil_Out32(0xFD4010AC, 0);
+		psu_mask_write(0xFD410044, 0x00000003U, 0x00000001U);
+		psu_mask_write(0xFD410040, 0x00000003U, 0x00000001U);
+		psu_mask_write(0xFD410038, 0x00000007U, 0x00000000U);
+	}
+	if (lane1_active == 1) {
+		Xil_Out32(0xFD407004, 0);
+		Xil_Out32(0xFD407008, 0);
+		Xil_Out32(0xFD40700C, 0);
+		Xil_Out32(0xFD407010, 0);
+		Xil_Out32(0xFD407014, 0);
+		Xil_Out32(0xFD407018, 0);
+		Xil_Out32(0xFD40701C, 0);
+		Xil_Out32(0xFD407020, 0);
+		Xil_Out32(0xFD407024, 0);
+		Xil_Out32(0xFD407028, 0);
+		Xil_Out32(0xFD40702C, 0);
+		Xil_Out32(0xFD407030, 0);
+		Xil_Out32(0xFD407034, 0);
+		Xil_Out32(0xFD407038, 0);
+		Xil_Out32(0xFD40703C, 0);
+		Xil_Out32(0xFD407040, 0);
+		Xil_Out32(0xFD407044, 0);
+		Xil_Out32(0xFD407048, 0);
+		Xil_Out32(0xFD40704C, 0);
+		Xil_Out32(0xFD407050, 0);
+		Xil_Out32(0xFD407054, 0);
+		Xil_Out32(0xFD407058, 0);
+		Xil_Out32(0xFD407068, 1);
+		Xil_Out32(0xFD40706C, 0);
+		Xil_Out32(0xFD4050AC, 0);
+		psu_mask_write(0xFD410044, 0x0000000CU, 0x00000004U);
+		psu_mask_write(0xFD410040, 0x0000000CU, 0x00000004U);
+		psu_mask_write(0xFD410038, 0x00000070U, 0x00000000U);
+	}
+	if (lane2_active == 1) {
+		Xil_Out32(0xFD40B004, 0);
+		Xil_Out32(0xFD40B008, 0);
+		Xil_Out32(0xFD40B00C, 0);
+		Xil_Out32(0xFD40B010, 0);
+		Xil_Out32(0xFD40B014, 0);
+		Xil_Out32(0xFD40B018, 0);
+		Xil_Out32(0xFD40B01C, 0);
+		Xil_Out32(0xFD40B020, 0);
+		Xil_Out32(0xFD40B024, 0);
+		Xil_Out32(0xFD40B028, 0);
+		Xil_Out32(0xFD40B02C, 0);
+		Xil_Out32(0xFD40B030, 0);
+		Xil_Out32(0xFD40B034, 0);
+		Xil_Out32(0xFD40B038, 0);
+		Xil_Out32(0xFD40B03C, 0);
+		Xil_Out32(0xFD40B040, 0);
+		Xil_Out32(0xFD40B044, 0);
+		Xil_Out32(0xFD40B048, 0);
+		Xil_Out32(0xFD40B04C, 0);
+		Xil_Out32(0xFD40B050, 0);
+		Xil_Out32(0xFD40B054, 0);
+		Xil_Out32(0xFD40B058, 0);
+		Xil_Out32(0xFD40B068, 1);
+		Xil_Out32(0xFD40B06C, 0);
+		Xil_Out32(0xFD4090AC, 0);
+		psu_mask_write(0xFD410044, 0x00000030U, 0x00000010U);
+		psu_mask_write(0xFD410040, 0x00000030U, 0x00000010U);
+		psu_mask_write(0xFD41003C, 0x00000007U, 0x00000000U);
+	}
+	if (lane3_active == 1) {
+		Xil_Out32(0xFD40F004, 0);
+		Xil_Out32(0xFD40F008, 0);
+		Xil_Out32(0xFD40F00C, 0);
+		Xil_Out32(0xFD40F010, 0);
+		Xil_Out32(0xFD40F014, 0);
+		Xil_Out32(0xFD40F018, 0);
+		Xil_Out32(0xFD40F01C, 0);
+		Xil_Out32(0xFD40F020, 0);
+		Xil_Out32(0xFD40F024, 0);
+		Xil_Out32(0xFD40F028, 0);
+		Xil_Out32(0xFD40F02C, 0);
+		Xil_Out32(0xFD40F030, 0);
+		Xil_Out32(0xFD40F034, 0);
+		Xil_Out32(0xFD40F038, 0);
+		Xil_Out32(0xFD40F03C, 0);
+		Xil_Out32(0xFD40F040, 0);
+		Xil_Out32(0xFD40F044, 0);
+		Xil_Out32(0xFD40F048, 0);
+		Xil_Out32(0xFD40F04C, 0);
+		Xil_Out32(0xFD40F050, 0);
+		Xil_Out32(0xFD40F054, 0);
+		Xil_Out32(0xFD40F058, 0);
+		Xil_Out32(0xFD40F068, 1);
+		Xil_Out32(0xFD40F06C, 0);
+		Xil_Out32(0xFD40D0AC, 0);
+		psu_mask_write(0xFD410044, 0x000000C0U, 0x00000040U);
+		psu_mask_write(0xFD410040, 0x000000C0U, 0x00000040U);
+		psu_mask_write(0xFD41003C, 0x00000070U, 0x00000000U);
+	}
+	return 1;
+}
+
+static int serdes_illcalib(u32 lane3_protocol, u32 lane3_rate,
+			   u32 lane2_protocol, u32 lane2_rate,
+			   u32 lane1_protocol, u32 lane1_rate,
+			   u32 lane0_protocol, u32 lane0_rate)
+{
+	unsigned int rdata = 0;
+	unsigned int sata_gen2 = 1;
+	unsigned int temp_ill12 = 0;
+	unsigned int temp_PLL_REF_SEL_OFFSET;
+	unsigned int temp_TM_IQ_ILL1;
+	unsigned int temp_TM_E_ILL1;
+	unsigned int temp_tx_dig_tm_61;
+	unsigned int temp_tm_dig_6;
+	unsigned int temp_pll_fbdiv_frac_3_msb_offset;
+
+	if (lane0_protocol == 2 || lane0_protocol == 1) {
+		Xil_Out32(0xFD401910, 0xF3);
+		Xil_Out32(0xFD40193C, 0xF3);
+		Xil_Out32(0xFD401914, 0xF3);
+		Xil_Out32(0xFD401940, 0xF3);
+	}
+	if (lane1_protocol == 2 || lane1_protocol == 1) {
+		Xil_Out32(0xFD405910, 0xF3);
+		Xil_Out32(0xFD40593C, 0xF3);
+		Xil_Out32(0xFD405914, 0xF3);
+		Xil_Out32(0xFD405940, 0xF3);
+	}
+	if (lane2_protocol == 2 || lane2_protocol == 1) {
+		Xil_Out32(0xFD409910, 0xF3);
+		Xil_Out32(0xFD40993C, 0xF3);
+		Xil_Out32(0xFD409914, 0xF3);
+		Xil_Out32(0xFD409940, 0xF3);
+	}
+	if (lane3_protocol == 2 || lane3_protocol == 1) {
+		Xil_Out32(0xFD40D910, 0xF3);
+		Xil_Out32(0xFD40D93C, 0xF3);
+		Xil_Out32(0xFD40D914, 0xF3);
+		Xil_Out32(0xFD40D940, 0xF3);
+	}
+
+	if (sata_gen2 == 1) {
+		if (lane0_protocol == 2) {
+			temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD402360);
+			Xil_Out32(0xFD402360, 0x0);
+			temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD410000);
+			psu_mask_write(0xFD410000, 0x0000001FU, 0x0000000DU);
+			temp_TM_IQ_ILL1 = Xil_In32(0xFD4018F8);
+			temp_TM_E_ILL1 = Xil_In32(0xFD401924);
+			Xil_Out32(0xFD4018F8, 0x78);
+			temp_tx_dig_tm_61 = Xil_In32(0xFD4000F4);
+			temp_tm_dig_6 = Xil_In32(0xFD40106C);
+			psu_mask_write(0xFD4000F4, 0x0000000BU, 0x00000000U);
+			psu_mask_write(0xFD40106C, 0x0000000FU, 0x00000000U);
+			temp_ill12 = Xil_In32(0xFD401990) & 0xF0;
+
+			serdes_illcalib_pcie_gen1(0, 0, 0, 0, 0, 0, 1, 0, 0);
+
+			Xil_Out32(0xFD402360, temp_pll_fbdiv_frac_3_msb_offset);
+			Xil_Out32(0xFD41000C, temp_PLL_REF_SEL_OFFSET);
+			Xil_Out32(0xFD4018F8, temp_TM_IQ_ILL1);
+			Xil_Out32(0xFD4000F4, temp_tx_dig_tm_61);
+			Xil_Out32(0xFD40106C, temp_tm_dig_6);
+			Xil_Out32(0xFD401928, Xil_In32(0xFD401924));
+			temp_ill12 =
+			    temp_ill12 | (Xil_In32(0xFD401990) >> 4 & 0xF);
+			Xil_Out32(0xFD401990, temp_ill12);
+			Xil_Out32(0xFD401924, temp_TM_E_ILL1);
+		}
+		if (lane1_protocol == 2) {
+			temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD406360);
+			Xil_Out32(0xFD406360, 0x0);
+			temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD410004);
+			psu_mask_write(0xFD410004, 0x0000001FU, 0x0000000DU);
+			temp_TM_IQ_ILL1 = Xil_In32(0xFD4058F8);
+			temp_TM_E_ILL1 = Xil_In32(0xFD405924);
+			Xil_Out32(0xFD4058F8, 0x78);
+			temp_tx_dig_tm_61 = Xil_In32(0xFD4040F4);
+			temp_tm_dig_6 = Xil_In32(0xFD40506C);
+			psu_mask_write(0xFD4040F4, 0x0000000BU, 0x00000000U);
+			psu_mask_write(0xFD40506C, 0x0000000FU, 0x00000000U);
+			temp_ill12 = Xil_In32(0xFD405990) & 0xF0;
+
+			serdes_illcalib_pcie_gen1(0, 0, 0, 0, 1, 0, 0, 0, 0);
+
+			Xil_Out32(0xFD406360, temp_pll_fbdiv_frac_3_msb_offset);
+			Xil_Out32(0xFD41000C, temp_PLL_REF_SEL_OFFSET);
+			Xil_Out32(0xFD4058F8, temp_TM_IQ_ILL1);
+			Xil_Out32(0xFD4040F4, temp_tx_dig_tm_61);
+			Xil_Out32(0xFD40506C, temp_tm_dig_6);
+			Xil_Out32(0xFD405928, Xil_In32(0xFD405924));
+			temp_ill12 =
+			    temp_ill12 | (Xil_In32(0xFD405990) >> 4 & 0xF);
+			Xil_Out32(0xFD405990, temp_ill12);
+			Xil_Out32(0xFD405924, temp_TM_E_ILL1);
+		}
+		if (lane2_protocol == 2) {
+			temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD40A360);
+			Xil_Out32(0xFD40A360, 0x0);
+			temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD410008);
+			psu_mask_write(0xFD410008, 0x0000001FU, 0x0000000DU);
+			temp_TM_IQ_ILL1 = Xil_In32(0xFD4098F8);
+			temp_TM_E_ILL1 = Xil_In32(0xFD409924);
+			Xil_Out32(0xFD4098F8, 0x78);
+			temp_tx_dig_tm_61 = Xil_In32(0xFD4080F4);
+			temp_tm_dig_6 = Xil_In32(0xFD40906C);
+			psu_mask_write(0xFD4080F4, 0x0000000BU, 0x00000000U);
+			psu_mask_write(0xFD40906C, 0x0000000FU, 0x00000000U);
+			temp_ill12 = Xil_In32(0xFD409990) & 0xF0;
+
+			serdes_illcalib_pcie_gen1(0, 0, 1, 0, 0, 0, 0, 0, 0);
+
+			Xil_Out32(0xFD40A360, temp_pll_fbdiv_frac_3_msb_offset);
+			Xil_Out32(0xFD41000C, temp_PLL_REF_SEL_OFFSET);
+			Xil_Out32(0xFD4098F8, temp_TM_IQ_ILL1);
+			Xil_Out32(0xFD4080F4, temp_tx_dig_tm_61);
+			Xil_Out32(0xFD40906C, temp_tm_dig_6);
+			Xil_Out32(0xFD409928, Xil_In32(0xFD409924));
+			temp_ill12 =
+			    temp_ill12 | (Xil_In32(0xFD409990) >> 4 & 0xF);
+			Xil_Out32(0xFD409990, temp_ill12);
+			Xil_Out32(0xFD409924, temp_TM_E_ILL1);
+		}
+		if (lane3_protocol == 2) {
+			temp_pll_fbdiv_frac_3_msb_offset = Xil_In32(0xFD40E360);
+			Xil_Out32(0xFD40E360, 0x0);
+			temp_PLL_REF_SEL_OFFSET = Xil_In32(0xFD41000C);
+			psu_mask_write(0xFD41000C, 0x0000001FU, 0x0000000DU);
+			temp_TM_IQ_ILL1 = Xil_In32(0xFD40D8F8);
+			temp_TM_E_ILL1 = Xil_In32(0xFD40D924);
+			Xil_Out32(0xFD40D8F8, 0x78);
+			temp_tx_dig_tm_61 = Xil_In32(0xFD40C0F4);
+			temp_tm_dig_6 = Xil_In32(0xFD40D06C);
+			psu_mask_write(0xFD40C0F4, 0x0000000BU, 0x00000000U);
+			psu_mask_write(0xFD40D06C, 0x0000000FU, 0x00000000U);
+			temp_ill12 = Xil_In32(0xFD40D990) & 0xF0;
+
+			serdes_illcalib_pcie_gen1(1, 0, 0, 0, 0, 0, 0, 0, 0);
+
+			Xil_Out32(0xFD40E360, temp_pll_fbdiv_frac_3_msb_offset);
+			Xil_Out32(0xFD41000C, temp_PLL_REF_SEL_OFFSET);
+			Xil_Out32(0xFD40D8F8, temp_TM_IQ_ILL1);
+			Xil_Out32(0xFD40C0F4, temp_tx_dig_tm_61);
+			Xil_Out32(0xFD40D06C, temp_tm_dig_6);
+			Xil_Out32(0xFD40D928, Xil_In32(0xFD40D924));
+			temp_ill12 =
+			    temp_ill12 | (Xil_In32(0xFD40D990) >> 4 & 0xF);
+			Xil_Out32(0xFD40D990, temp_ill12);
+			Xil_Out32(0xFD40D924, temp_TM_E_ILL1);
+		}
+		rdata = Xil_In32(0xFD410098);
+		rdata = (rdata & 0xDF);
+		Xil_Out32(0xFD410098, rdata);
+	}
+
+	if (lane0_protocol == 2 && lane0_rate == 3) {
+		psu_mask_write(0xFD40198C, 0x000000F0U, 0x00000020U);
+		psu_mask_write(0xFD40192C, 0x000000FFU, 0x00000094U);
+	}
+	if (lane1_protocol == 2 && lane1_rate == 3) {
+		psu_mask_write(0xFD40598C, 0x000000F0U, 0x00000020U);
+		psu_mask_write(0xFD40592C, 0x000000FFU, 0x00000094U);
+	}
+	if (lane2_protocol == 2 && lane2_rate == 3) {
+		psu_mask_write(0xFD40998C, 0x000000F0U, 0x00000020U);
+		psu_mask_write(0xFD40992C, 0x000000FFU, 0x00000094U);
+	}
+	if (lane3_protocol == 2 && lane3_rate == 3) {
+		psu_mask_write(0xFD40D98C, 0x000000F0U, 0x00000020U);
+		psu_mask_write(0xFD40D92C, 0x000000FFU, 0x00000094U);
+	}
+
+	if (lane0_protocol == 1) {
+		if (lane0_rate == 0) {
+			serdes_illcalib_pcie_gen1(lane3_protocol, lane3_rate,
+						  lane2_protocol, lane2_rate,
+						  lane1_protocol, lane1_rate,
+						  lane0_protocol, 0, 0);
+		} else {
+			serdes_illcalib_pcie_gen1(lane3_protocol, lane3_rate,
+						  lane2_protocol, lane2_rate,
+						  lane1_protocol, lane1_rate,
+						  lane0_protocol, 0, 0);
+			serdes_illcalib_pcie_gen1(lane3_protocol, lane3_rate,
+						  lane2_protocol, lane2_rate,
+						  lane1_protocol, lane1_rate,
+						  lane0_protocol, lane0_rate,
+						  1);
+		}
+	}
+
+	if (lane0_protocol == 3)
+		Xil_Out32(0xFD401914, 0xF3);
+	if (lane0_protocol == 3)
+		Xil_Out32(0xFD401940, 0xF3);
+	if (lane0_protocol == 3)
+		Xil_Out32(0xFD401990, 0x20);
+	if (lane0_protocol == 3)
+		Xil_Out32(0xFD401924, 0x37);
+
+	if (lane1_protocol == 3)
+		Xil_Out32(0xFD405914, 0xF3);
+	if (lane1_protocol == 3)
+		Xil_Out32(0xFD405940, 0xF3);
+	if (lane1_protocol == 3)
+		Xil_Out32(0xFD405990, 0x20);
+	if (lane1_protocol == 3)
+		Xil_Out32(0xFD405924, 0x37);
+
+	if (lane2_protocol == 3)
+		Xil_Out32(0xFD409914, 0xF3);
+	if (lane2_protocol == 3)
+		Xil_Out32(0xFD409940, 0xF3);
+	if (lane2_protocol == 3)
+		Xil_Out32(0xFD409990, 0x20);
+	if (lane2_protocol == 3)
+		Xil_Out32(0xFD409924, 0x37);
+
+	if (lane3_protocol == 3)
+		Xil_Out32(0xFD40D914, 0xF3);
+	if (lane3_protocol == 3)
+		Xil_Out32(0xFD40D940, 0xF3);
+	if (lane3_protocol == 3)
+		Xil_Out32(0xFD40D990, 0x20);
+	if (lane3_protocol == 3)
+		Xil_Out32(0xFD40D924, 0x37);
+
+	return 1;
+}
+
+static int serdes_enb_coarse_saturation(void)
+{
+	Xil_Out32(0xFD402094, 0x00000010);
+	Xil_Out32(0xFD406094, 0x00000010);
+	Xil_Out32(0xFD40A094, 0x00000010);
+	Xil_Out32(0xFD40E094, 0x00000010);
+	return 1;
+}
+
+static int serdes_fixcal_code(void)
+{
+	int maskstatus = 1;
+	unsigned int rdata = 0;
+	unsigned int match_pmos_code[23];
+	unsigned int match_nmos_code[23];
+	unsigned int match_ical_code[7];
+	unsigned int match_rcal_code[7];
+	unsigned int p_code = 0;
+	unsigned int n_code = 0;
+	unsigned int i_code = 0;
+	unsigned int r_code = 0;
+	unsigned int repeat_count = 0;
+	unsigned int L3_TM_CALIB_DIG20 = 0;
+	unsigned int L3_TM_CALIB_DIG19 = 0;
+	unsigned int L3_TM_CALIB_DIG18 = 0;
+	unsigned int L3_TM_CALIB_DIG16 = 0;
+	unsigned int L3_TM_CALIB_DIG15 = 0;
+	unsigned int L3_TM_CALIB_DIG14 = 0;
+	int i = 0;
+	int count = 0;
+
+	rdata = Xil_In32(0xFD40289C);
+	rdata = rdata & ~0x03;
+	rdata = rdata | 0x1;
+	Xil_Out32(0xFD40289C, rdata);
+
+	do {
+		if (count == 1100000)
+			break;
+		rdata = Xil_In32(0xFD402B1C);
+		count++;
+	} while ((rdata & 0x0000000E) != 0x0000000E);
+
+	for (i = 0; i < 23; i++) {
+		match_pmos_code[i] = 0;
+		match_nmos_code[i] = 0;
+	}
+	for (i = 0; i < 7; i++) {
+		match_ical_code[i] = 0;
+		match_rcal_code[i] = 0;
+	}
+
+	do {
+		Xil_Out32(0xFD410010, 0x00000000);
+		Xil_Out32(0xFD410014, 0x00000000);
+
+		Xil_Out32(0xFD410010, 0x00000001);
+		Xil_Out32(0xFD410014, 0x00000000);
+
+		maskstatus = mask_poll(0xFD40EF14, 0x2);
+		if (maskstatus == 0) {
+			xil_printf("#SERDES initialization timed out\n\r");
+			return maskstatus;
+		}
+
+		p_code = mask_read(0xFD40EF18, 0xFFFFFFFF);
+		n_code = mask_read(0xFD40EF1C, 0xFFFFFFFF);
+		;
+		i_code = mask_read(0xFD40EF24, 0xFFFFFFFF);
+		r_code = mask_read(0xFD40EF28, 0xFFFFFFFF);
+		;
+
+		if (p_code >= 0x26 && p_code <= 0x3C)
+			match_pmos_code[p_code - 0x26] += 1;
+
+		if (n_code >= 0x26 && n_code <= 0x3C)
+			match_nmos_code[n_code - 0x26] += 1;
+
+		if (i_code >= 0xC && i_code <= 0x12)
+			match_ical_code[i_code - 0xc] += 1;
+
+		if (r_code >= 0x6 && r_code <= 0xC)
+			match_rcal_code[r_code - 0x6] += 1;
+
+	} while (repeat_count++ < 10);
+
+	for (i = 0; i < 23; i++) {
+		if (match_pmos_code[i] >= match_pmos_code[0]) {
+			match_pmos_code[0] = match_pmos_code[i];
+			p_code = 0x26 + i;
+		}
+		if (match_nmos_code[i] >= match_nmos_code[0]) {
+			match_nmos_code[0] = match_nmos_code[i];
+			n_code = 0x26 + i;
+		}
+	}
+
+	for (i = 0; i < 7; i++) {
+		if (match_ical_code[i] >= match_ical_code[0]) {
+			match_ical_code[0] = match_ical_code[i];
+			i_code = 0xC + i;
+		}
+		if (match_rcal_code[i] >= match_rcal_code[0]) {
+			match_rcal_code[0] = match_rcal_code[i];
+			r_code = 0x6 + i;
+		}
+	}
+
+	L3_TM_CALIB_DIG20 = mask_read(0xFD40EC50, 0xFFFFFFF0);
+	L3_TM_CALIB_DIG20 = L3_TM_CALIB_DIG20 | 0x8 | ((p_code >> 2) & 0x7);
+
+	L3_TM_CALIB_DIG19 = mask_read(0xFD40EC4C, 0xFFFFFF18);
+	L3_TM_CALIB_DIG19 = L3_TM_CALIB_DIG19 | ((p_code & 0x3) << 6)
+	    | 0x20 | 0x4 | ((n_code >> 3) & 0x3);
+
+	L3_TM_CALIB_DIG18 = mask_read(0xFD40EC48, 0xFFFFFF0F);
+	L3_TM_CALIB_DIG18 = L3_TM_CALIB_DIG18 | ((n_code & 0x7) << 5) | 0x10;
+
+	L3_TM_CALIB_DIG16 = mask_read(0xFD40EC40, 0xFFFFFFF8);
+	L3_TM_CALIB_DIG16 = L3_TM_CALIB_DIG16 | ((r_code >> 1) & 0x7);
+
+	L3_TM_CALIB_DIG15 = mask_read(0xFD40EC3C, 0xFFFFFF30);
+	L3_TM_CALIB_DIG15 = L3_TM_CALIB_DIG15 | ((r_code & 0x1) << 7)
+	    | 0x40 | 0x8 | ((i_code >> 1) & 0x7);
+
+	L3_TM_CALIB_DIG14 = mask_read(0xFD40EC38, 0xFFFFFF3F);
+	L3_TM_CALIB_DIG14 = L3_TM_CALIB_DIG14 | ((i_code & 0x1) << 7) | 0x40;
+
+	Xil_Out32(0xFD40EC50, L3_TM_CALIB_DIG20);
+	Xil_Out32(0xFD40EC4C, L3_TM_CALIB_DIG19);
+	Xil_Out32(0xFD40EC48, L3_TM_CALIB_DIG18);
+	Xil_Out32(0xFD40EC40, L3_TM_CALIB_DIG16);
+	Xil_Out32(0xFD40EC3C, L3_TM_CALIB_DIG15);
+	Xil_Out32(0xFD40EC38, L3_TM_CALIB_DIG14);
+	return maskstatus;
+}
+
+static int init_serdes(void)
+{
+	int status = 1;
+
+	status &= psu_resetin_init_data();
+
+	status &= serdes_fixcal_code();
+	status &= serdes_enb_coarse_saturation();
+
+	status &= psu_serdes_init_data();
+	status &= psu_resetout_init_data();
+
+	return status;
+}
+
+static void init_peripheral(void)
+{
+	psu_mask_write(0xFD5F0018, 0x8000001FU, 0x8000001FU);
+}
+
+int psu_init(void)
+{
+	int status = 1;
+
+	status &= psu_mio_init_data();
+	status &= psu_peripherals_pre_init_data();
+	status &= psu_pll_init_data();
+	status &= psu_clock_init_data();
+
+	status &= psu_ddr_init_data();
+	status &= psu_ddr_phybringup_data();
+
+	status &= psu_peripherals_init_data();
+	status &= init_serdes();
+	init_peripheral();
+
+	status &= psu_afi_config();
+	psu_ddr_qos_init_data();
+
+	if (status == 0)
+		return 1;
+	return 0;
+}
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
index 4466717..23c12f4 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -436,7 +436,7 @@
 }
 #endif
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 }
 
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 863b7f9..c735e81 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1960,6 +1960,8 @@
 
 config CMD_BLOB
 	bool "Enable the 'blob' command"
+	depends on !MX6ULL && !MX6SLL && !MX6SL
+	select IMX_HAB if ARCH_MX6 || ARCH_MX7 || ARCH_MX7ULP || ARCH_IMX8M
 	help
 	  This is used with the Freescale secure boot mechanism.
 
@@ -2031,12 +2033,19 @@
 	help
 	  Add -v option to verify data against a hash.
 
+config CMD_SCP03
+	bool "scp03 - SCP03 enable and rotate/provision operations"
+	depends on SCP03
+	help
+	  This command provides access to a Trusted Application
+	  running in a TEE to request Secure Channel Protocol 03
+	  (SCP03) enablement and/or rotation of its SCP03 keys.
+
 config CMD_TPM_V1
 	bool
 
 config CMD_TPM_V2
 	bool
-	select CMD_LOG
 
 config CMD_TPM
 	bool "Enable the 'tpm' command"
@@ -2245,6 +2254,15 @@
 	  for some PowerPC processors. For details please see the
 	  documentation in doc/README.bedbug.
 
+config CMD_CBSYSINFO
+	bool "cbsysinfo"
+	depends on X86
+	default y if SYS_COREBOOT
+	help
+	  This provides information about the coreboot sysinfo table stored in
+	  memory by coreboot before jumping to U-Boot. It can be useful for
+	  debugging the beaaviour of coreboot or U-Boot.
+
 config CMD_DIAG
 	bool "diag - Board diagnostics"
 	help
diff --git a/cmd/Makefile b/cmd/Makefile
index 567e2b7..e606ac4 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -194,6 +194,9 @@
 # Android Verified Boot 2.0
 obj-$(CONFIG_CMD_AVB) += avb.o
 
+# Foundries.IO SCP03
+obj-$(CONFIG_CMD_SCP03) += scp03.o
+
 obj-$(CONFIG_ARM) += arm/
 obj-$(CONFIG_RISCV) += riscv/
 obj-$(CONFIG_SANDBOX) += sandbox/
diff --git a/cmd/acpi.c b/cmd/acpi.c
index 157261b..e5b9a17 100644
--- a/cmd/acpi.c
+++ b/cmd/acpi.c
@@ -187,10 +187,12 @@
 	return 0;
 }
 
+#ifdef CONFIG_SYS_LONGHELP
 static char acpi_help_text[] =
 	"list - list ACPI tables\n"
 	"acpi items [-d]  - List/dump each piece of ACPI data from devices\n"
 	"acpi dump <name> - Dump ACPI table";
+#endif
 
 U_BOOT_CMD_WITH_SUBCMDS(acpi, "ACPI tables", acpi_help_text,
 	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_acpi_list),
diff --git a/cmd/blob.c b/cmd/blob.c
index c80e697..887219c 100644
--- a/cmd/blob.c
+++ b/cmd/blob.c
@@ -9,6 +9,11 @@
 #include <malloc.h>
 #include <asm/byteorder.h>
 #include <linux/compiler.h>
+#if defined(CONFIG_ARCH_MX6) || defined(CONFIG_ARCH_MX7) || \
+	defined(CONFIG_ARCH_MX7ULP) || defined(CONFIG_ARCH_IMX8M)
+#include <fsl_sec.h>
+#include <asm/arch/clock.h>
+#endif
 
 /**
  * blob_decap() - Decapsulate the data as a blob
@@ -74,6 +79,17 @@
 	src_ptr = (uint8_t *)(uintptr_t)src_addr;
 	dst_ptr = (uint8_t *)(uintptr_t)dst_addr;
 
+#if defined(CONFIG_ARCH_MX6) || defined(CONFIG_ARCH_MX7) || \
+	defined(CONFIG_ARCH_MX7ULP) || defined(CONFIG_ARCH_IMX8M)
+
+	hab_caam_clock_enable(1);
+
+	u32 out_jr_size = sec_in32(CONFIG_SYS_FSL_JR0_ADDR +
+				   FSL_CAAM_ORSR_JRa_OFFSET);
+	if (out_jr_size != FSL_CAAM_MAX_JR_SIZE)
+		sec_init();
+#endif
+
 	if (enc)
 		ret = blob_encap(km_ptr, src_ptr, dst_ptr, len);
 	else
diff --git a/cmd/bloblist.c b/cmd/bloblist.c
index 97b5734..21e7ff6 100644
--- a/cmd/bloblist.c
+++ b/cmd/bloblist.c
@@ -29,9 +29,11 @@
 	return 0;
 }
 
+#ifdef CONFIG_SYS_LONGHELP
 static char bloblist_help_text[] =
 	"info   - show information about the bloblist\n"
 	"bloblist list   - list blobs in the bloblist";
+#endif
 
 U_BOOT_CMD_WITH_SUBCMDS(bloblist, "Bloblists", bloblist_help_text,
 	U_BOOT_SUBCMD_MKENT(info, 1, 1, do_bloblist_info),
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 271b385..cba81ff 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -358,6 +358,9 @@
 
 	free(load_options);
 
+	if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD))
+		efi_initrd_deregister();
+
 	return ret;
 }
 
diff --git a/cmd/efidebug.c b/cmd/efidebug.c
index 55c7abe..6e36575 100644
--- a/cmd/efidebug.c
+++ b/cmd/efidebug.c
@@ -9,6 +9,7 @@
 #include <common.h>
 #include <command.h>
 #include <efi_dt_fixup.h>
+#include <efi_load_initrd.h>
 #include <efi_loader.h>
 #include <efi_rng.h>
 #include <exports.h>
@@ -19,6 +20,7 @@
 #include <part.h>
 #include <search.h>
 #include <linux/ctype.h>
+#include <linux/err.h>
 
 #define BS systab.boottime
 #define RT systab.runtime
@@ -129,6 +131,82 @@
 	return CMD_RET_SUCCESS;
 }
 
+#ifdef CONFIG_EFI_ESRT
+
+#define EFI_ESRT_FW_TYPE_NUM 4
+char *efi_fw_type_str[EFI_ESRT_FW_TYPE_NUM] = {"unknown", "system FW", "device FW",
+	 "UEFI driver"};
+
+#define EFI_ESRT_UPDATE_STATUS_NUM 9
+char *efi_update_status_str[EFI_ESRT_UPDATE_STATUS_NUM] = {"success", "unsuccessful",
+	"insufficient resources", "incorrect version", "invalid format",
+	"auth error", "power event (AC)", "power event (batt)",
+	"unsatisfied dependencies"};
+
+#define EFI_FW_TYPE_STR_GET(idx) (\
+EFI_ESRT_FW_TYPE_NUM > (idx) ? efi_fw_type_str[(idx)] : "error"\
+)
+
+#define EFI_FW_STATUS_STR_GET(idx) (\
+EFI_ESRT_UPDATE_STATUS_NUM  > (idx) ? efi_update_status_str[(idx)] : "error"\
+)
+
+/**
+ * do_efi_capsule_esrt() - manage UEFI capsules
+ *
+ * @cmdtp:	Command table
+ * @flag:	Command flag
+ * @argc:	Number of arguments
+ * @argv:	Argument array
+ * Return:	CMD_RET_SUCCESS on success,
+ *		CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "capsule esrt" sub-command.
+ * The prints the current ESRT table.
+ *
+ *     efidebug capsule esrt
+ */
+static int do_efi_capsule_esrt(struct cmd_tbl *cmdtp, int flag,
+			       int argc, char * const argv[])
+{
+	struct efi_system_resource_table *esrt = NULL;
+
+	if (argc != 1)
+		return CMD_RET_USAGE;
+
+	for (int idx = 0; idx < systab.nr_tables; idx++)
+		if (!guidcmp(&efi_esrt_guid, &systab.tables[idx].guid))
+			esrt = (struct efi_system_resource_table *)systab.tables[idx].table;
+
+	if (!esrt) {
+		log_info("ESRT: table not present\n");
+		return CMD_RET_SUCCESS;
+	}
+
+	printf("========================================\n");
+	printf("ESRT: fw_resource_count=%d\n", esrt->fw_resource_count);
+	printf("ESRT: fw_resource_count_max=%d\n", esrt->fw_resource_count_max);
+	printf("ESRT: fw_resource_version=%lld\n", esrt->fw_resource_version);
+
+	for (int idx = 0; idx < esrt->fw_resource_count; idx++) {
+		printf("[entry %d]==============================\n", idx);
+		printf("ESRT: fw_class=%pUL\n", &esrt->entries[idx].fw_class);
+		printf("ESRT: fw_type=%s\n", EFI_FW_TYPE_STR_GET(esrt->entries[idx].fw_type));
+		printf("ESRT: fw_version=%d\n", esrt->entries[idx].fw_version);
+		printf("ESRT: lowest_supported_fw_version=%d\n",
+		       esrt->entries[idx].lowest_supported_fw_version);
+		printf("ESRT: capsule_flags=%d\n",
+		       esrt->entries[idx].capsule_flags);
+		printf("ESRT: last_attempt_version=%d\n",
+		       esrt->entries[idx].last_attempt_version);
+		printf("ESRT: last_attempt_status=%s\n",
+		       EFI_FW_STATUS_STR_GET(esrt->entries[idx].last_attempt_status));
+	}
+	printf("========================================\n");
+
+	return CMD_RET_SUCCESS;
+}
+#endif /*  CONFIG_EFI_ESRT */
 /**
  * do_efi_capsule_res() - show a capsule update result
  *
@@ -221,6 +299,10 @@
 			 "", ""),
 	U_BOOT_CMD_MKENT(show, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_show,
 			 "", ""),
+#ifdef CONFIG_EFI_ESRT
+	U_BOOT_CMD_MKENT(esrt, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_esrt,
+			 "", ""),
+#endif
 	U_BOOT_CMD_MKENT(disk-update, 0, 0, do_efi_capsule_on_disk_update,
 			 "", ""),
 	U_BOOT_CMD_MKENT(result, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_res,
@@ -517,6 +599,10 @@
 		EFI_ACPI_TABLE_GUID,
 	},
 	{
+		"EFI System Resource Table",
+		EFI_SYSTEM_RESOURCE_TABLE_GUID,
+	},
+	{
 		"device tree",
 		EFI_FDT_GUID,
 	},
@@ -799,6 +885,54 @@
 }
 
 /**
+ * create_initrd_dp() - Create a special device for our Boot### option
+ *
+ * @dev:	Device
+ * @part:	Disk partition
+ * @file:	Filename
+ * Return:	Pointer to the device path or ERR_PTR
+ *
+ */
+static
+struct efi_device_path *create_initrd_dp(const char *dev, const char *part,
+					 const char *file)
+
+{
+	struct efi_device_path *tmp_dp = NULL, *tmp_fp = NULL;
+	struct efi_device_path *initrd_dp = NULL;
+	efi_status_t ret;
+	const struct efi_initrd_dp id_dp = {
+		.vendor = {
+			{
+			DEVICE_PATH_TYPE_MEDIA_DEVICE,
+			DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
+			sizeof(id_dp.vendor),
+			},
+			EFI_INITRD_MEDIA_GUID,
+		},
+		.end = {
+			DEVICE_PATH_TYPE_END,
+			DEVICE_PATH_SUB_TYPE_END,
+			sizeof(id_dp.end),
+		}
+	};
+
+	ret = efi_dp_from_name(dev, part, file, &tmp_dp, &tmp_fp);
+	if (ret != EFI_SUCCESS) {
+		printf("Cannot create device path for \"%s %s\"\n", part, file);
+		goto out;
+	}
+
+	initrd_dp = efi_dp_append((const struct efi_device_path *)&id_dp,
+				  tmp_fp);
+
+out:
+	efi_free_pool(tmp_dp);
+	efi_free_pool(tmp_fp);
+	return initrd_dp;
+}
+
+/**
  * do_efi_boot_add() - set UEFI load option
  *
  * @cmdtp:	Command table
@@ -810,7 +944,9 @@
  *
  * Implement efidebug "boot add" sub-command. Create or change UEFI load option.
  *
- *     efidebug boot add <id> <label> <interface> <devnum>[:<part>] <file> <options>
+ * efidebug boot add -b <id> <label> <interface> <devnum>[:<part>] <file>
+ *                   -i <file> <interface2> <devnum2>[:<part>] <initrd>
+ *                   -s '<options>'
  */
 static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag,
 			   int argc, char *const argv[])
@@ -823,55 +959,105 @@
 	size_t label_len, label_len16;
 	u16 *label;
 	struct efi_device_path *device_path = NULL, *file_path = NULL;
+	struct efi_device_path *final_fp = NULL;
+	struct efi_device_path *initrd_dp = NULL;
 	struct efi_load_option lo;
 	void *data = NULL;
 	efi_uintn_t size;
+	efi_uintn_t fp_size = 0;
 	efi_status_t ret;
 	int r = CMD_RET_SUCCESS;
 
-	if (argc < 6 || argc > 7)
-		return CMD_RET_USAGE;
-
-	id = (int)simple_strtoul(argv[1], &endp, 16);
-	if (*endp != '\0' || id > 0xffff)
-		return CMD_RET_USAGE;
-
-	sprintf(var_name, "Boot%04X", id);
-	p = var_name16;
-	utf8_utf16_strncpy(&p, var_name, 9);
-
 	guid = efi_global_variable_guid;
 
 	/* attributes */
 	lo.attributes = LOAD_OPTION_ACTIVE; /* always ACTIVE */
+	lo.optional_data = NULL;
+	lo.label = NULL;
 
-	/* label */
-	label_len = strlen(argv[2]);
-	label_len16 = utf8_utf16_strnlen(argv[2], label_len);
-	label = malloc((label_len16 + 1) * sizeof(u16));
-	if (!label)
-		return CMD_RET_FAILURE;
-	lo.label = label; /* label will be changed below */
-	utf8_utf16_strncpy(&label, argv[2], label_len);
+	argc--;
+	argv++; /* 'add' */
+	for (; argc > 0; argc--, argv++) {
+		if (!strcmp(argv[0], "-b")) {
+			if (argc <  5 || lo.label) {
+				r = CMD_RET_USAGE;
+				goto out;
+			}
+			id = (int)simple_strtoul(argv[1], &endp, 16);
+			if (*endp != '\0' || id > 0xffff)
+				return CMD_RET_USAGE;
 
-	/* file path */
-	ret = efi_dp_from_name(argv[3], argv[4], argv[5], &device_path,
-			       &file_path);
-	if (ret != EFI_SUCCESS) {
-		printf("Cannot create device path for \"%s %s\"\n",
-		       argv[3], argv[4]);
+			sprintf(var_name, "Boot%04X", id);
+			p = var_name16;
+			utf8_utf16_strncpy(&p, var_name, 9);
+
+			/* label */
+			label_len = strlen(argv[2]);
+			label_len16 = utf8_utf16_strnlen(argv[2], label_len);
+			label = malloc((label_len16 + 1) * sizeof(u16));
+			if (!label)
+				return CMD_RET_FAILURE;
+			lo.label = label; /* label will be changed below */
+			utf8_utf16_strncpy(&label, argv[2], label_len);
+
+			/* file path */
+			ret = efi_dp_from_name(argv[3], argv[4], argv[5],
+					       &device_path, &file_path);
+			if (ret != EFI_SUCCESS) {
+				printf("Cannot create device path for \"%s %s\"\n",
+				       argv[3], argv[4]);
+				r = CMD_RET_FAILURE;
+				goto out;
+			}
+			fp_size += efi_dp_size(file_path) +
+				sizeof(struct efi_device_path);
+			argc -= 5;
+			argv += 5;
+		} else if (!strcmp(argv[0], "-i")) {
+			if (argc < 3 || initrd_dp) {
+				r = CMD_RET_USAGE;
+				goto out;
+			}
+
+			initrd_dp = create_initrd_dp(argv[1], argv[2], argv[3]);
+			if (!initrd_dp) {
+				printf("Cannot add an initrd\n");
+				r = CMD_RET_FAILURE;
+				goto out;
+			}
+			argc -= 3;
+			argv += 3;
+			fp_size += efi_dp_size(initrd_dp) +
+				sizeof(struct efi_device_path);
+		} else if (!strcmp(argv[0], "-s")) {
+			if (argc < 1 || lo.optional_data) {
+				r = CMD_RET_USAGE;
+				goto out;
+			}
+			lo.optional_data = (const u8 *)argv[1];
+			argc -= 1;
+			argv += 1;
+		} else {
+			r = CMD_RET_USAGE;
+			goto out;
+		}
+	}
+
+	if (!file_path) {
+		printf("Missing binary\n");
+		r = CMD_RET_USAGE;
+		goto out;
+	}
+
+	final_fp = efi_dp_concat(file_path, initrd_dp);
+	if (!final_fp) {
+		printf("Cannot create final device path\n");
 		r = CMD_RET_FAILURE;
 		goto out;
 	}
-	lo.file_path = file_path;
-	lo.file_path_length = efi_dp_size(file_path)
-				+ sizeof(struct efi_device_path); /* for END */
 
-	/* optional data */
-	if (argc == 6)
-		lo.optional_data = NULL;
-	else
-		lo.optional_data = (const u8 *)argv[6];
+	lo.file_path = final_fp;
+	lo.file_path_length = fp_size;
 
 	size = efi_serialize_load_option(&lo, (u8 **)&data);
 	if (!size) {
@@ -888,8 +1074,11 @@
 		printf("Cannot set %ls\n", var_name16);
 		r = CMD_RET_FAILURE;
 	}
+
 out:
 	free(data);
+	efi_free_pool(final_fp);
+	efi_free_pool(initrd_dp);
 	efi_free_pool(device_path);
 	efi_free_pool(file_path);
 	free(lo.label);
@@ -955,11 +1144,14 @@
  */
 static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size)
 {
+	struct efi_device_path *initrd_path = NULL;
 	struct efi_load_option lo;
 	char *label, *p;
 	size_t label_len16, label_len;
 	u16 *dp_str;
 	efi_status_t ret;
+	efi_uintn_t initrd_dp_size;
+	const efi_guid_t lf2_initrd_guid = EFI_INITRD_MEDIA_GUID;
 
 	ret = efi_deserialize_load_option(&lo, data, size);
 	if (ret != EFI_SUCCESS) {
@@ -990,6 +1182,14 @@
 	printf("  file_path: %ls\n", dp_str);
 	efi_free_pool(dp_str);
 
+	initrd_path = efi_dp_from_lo(&lo, &initrd_dp_size, lf2_initrd_guid);
+	if (initrd_path) {
+		dp_str = efi_dp_str(initrd_path);
+		printf("  initrd_path: %ls\n", dp_str);
+		efi_free_pool(dp_str);
+		efi_free_pool(initrd_path);
+	}
+
 	printf("  data:\n");
 	print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
 		       lo.optional_data, *size, true);
@@ -1559,7 +1759,10 @@
 static char efidebug_help_text[] =
 	"  - UEFI Shell-like interface to configure UEFI environment\n"
 	"\n"
-	"efidebug boot add <bootid> <label> <interface> <devnum>[:<part>] <file path> [<load options>]\n"
+	"efidebug boot add "
+	"-b <bootid> <label> <interface> <devnum>[:<part>] <file path> "
+	"-i <interface> <devnum>[:<part>] <initrd file path> "
+	"-s '<optional data>'\n"
 	"  - set UEFI BootXXXX variable\n"
 	"    <load options> will be passed to UEFI application\n"
 	"efidebug boot rm <bootid#1> [<bootid#2> [<bootid#3> [...]]]\n"
@@ -1580,6 +1783,10 @@
 	"  - show capsule information\n"
 	"efidebug capsule result [<capsule result var>]\n"
 	"  - show a capsule update result\n"
+#ifdef CONFIG_EFI_ESRT
+	"efidebug capsule esrt\n"
+	"  - print the ESRT\n"
+#endif
 	"\n"
 #endif
 	"efidebug devices\n"
@@ -1603,7 +1810,7 @@
 #endif
 
 U_BOOT_CMD(
-	efidebug, 10, 0, do_efidebug,
+	efidebug, CONFIG_SYS_MAXARGS, 0, do_efidebug,
 	"Configure UEFI environment",
 	efidebug_help_text
 );
diff --git a/cmd/host.c b/cmd/host.c
index 1d21f79..6aa3d91 100644
--- a/cmd/host.c
+++ b/cmd/host.c
@@ -41,17 +41,35 @@
 static int do_host_bind(struct cmd_tbl *cmdtp, int flag, int argc,
 			char *const argv[])
 {
-	if (argc < 2 || argc > 3)
-		return CMD_RET_USAGE;
+	bool removable = false;
+	const char *dev_str;
+	char *file;
 	char *ep;
-	char *dev_str = argv[1];
-	char *file = argc >= 3 ? argv[2] : NULL;
-	int dev = simple_strtoul(dev_str, &ep, 16);
+	int dev;
+
+	/* Skip 'bind' */
+	argc--;
+	argv++;
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	if (!strcmp(argv[0], "-r")) {
+		removable = true;
+		argc--;
+		argv++;
+	}
+
+	if (argc > 2)
+		return CMD_RET_USAGE;
+	dev_str = argv[0];
+	dev = simple_strtoul(dev_str, &ep, 16);
 	if (*ep) {
 		printf("** Bad device specification %s **\n", dev_str);
 		return CMD_RET_USAGE;
 	}
-	return !!host_dev_bind(dev, file);
+	file = argc > 1 ? argv[1] : NULL;
+
+	return !!host_dev_bind(dev, file, removable);
 }
 
 static int do_host_info(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -146,7 +164,7 @@
 	U_BOOT_CMD_MKENT(ls, 3, 0, do_host_ls, "", ""),
 	U_BOOT_CMD_MKENT(save, 6, 0, do_host_save, "", ""),
 	U_BOOT_CMD_MKENT(size, 3, 0, do_host_size, "", ""),
-	U_BOOT_CMD_MKENT(bind, 3, 0, do_host_bind, "", ""),
+	U_BOOT_CMD_MKENT(bind, 4, 0, do_host_bind, "", ""),
 	U_BOOT_CMD_MKENT(info, 3, 0, do_host_info, "", ""),
 	U_BOOT_CMD_MKENT(dev, 0, 1, do_host_dev, "", ""),
 };
@@ -178,7 +196,8 @@
 	"host save hostfs - <addr> <filename> <bytes> [<offset>] - "
 		"save a file to host\n"
 	"host size hostfs - <filename> - determine size of file on host\n"
-	"host bind <dev> [<filename>] - bind \"host\" device to file\n"
+	"host bind [-r] <dev> [<filename>] - bind \"host\" device to file\n"
+	"     -r = mark as removable\n"
 	"host info [<dev>]            - show device binding & info\n"
 	"host dev [<dev>] - Set or retrieve the current host device\n"
 	"host commands use the \"hostfs\" device. The \"host\" device is used\n"
diff --git a/cmd/mmc.c b/cmd/mmc.c
index cb6b59f..a10f137 100644
--- a/cmd/mmc.c
+++ b/cmd/mmc.c
@@ -735,8 +735,45 @@
 		return CMD_RET_FAILURE;
 	}
 
+	/*
+	 * BOOT_BUS_CONDITIONS[177]
+	 * BOOT_MODE[4:3]
+	 * 0x0 : Use SDR + Backward compatible timing in boot operation
+	 * 0x1 : Use SDR + High Speed Timing in boot operation mode
+	 * 0x2 : Use DDR in boot operation
+	 * RESET_BOOT_BUS_CONDITIONS
+	 * 0x0 : Reset bus width to x1, SDR, Backward compatible
+	 * 0x1 : Retain BOOT_BUS_WIDTH and BOOT_MODE
+	 * BOOT_BUS_WIDTH
+	 * 0x0 : x1(sdr) or x4 (ddr) buswidth
+	 * 0x1 : x4(sdr/ddr) buswith
+	 * 0x2 : x8(sdr/ddr) buswith
+	 *
+	 */
+	if (width >= 0x3) {
+		printf("boot_bus_width %d is invalid\n", width);
+		return CMD_RET_FAILURE;
+	}
+
+	if (reset >= 0x2) {
+		printf("reset_boot_bus_width %d is invalid\n", reset);
+		return CMD_RET_FAILURE;
+	}
+
+	if (mode >= 0x3) {
+		printf("reset_boot_bus_width %d is invalid\n", mode);
+		return CMD_RET_FAILURE;
+	}
+
 	/* acknowledge to be sent during boot operation */
-	return mmc_set_boot_bus_width(mmc, width, reset, mode);
+	if (mmc_set_boot_bus_width(mmc, width, reset, mode)) {
+		puts("BOOT_BUS_WIDTH is failed to change.\n");
+		return CMD_RET_FAILURE;
+	}
+
+	printf("Set to BOOT_BUS_WIDTH = 0x%x, RESET = 0x%x, BOOT_MODE = 0x%x\n",
+			width, reset, mode);
+	return CMD_RET_SUCCESS;
 }
 
 static int do_mmc_boot_resize(struct cmd_tbl *cmdtp, int flag,
@@ -1008,11 +1045,14 @@
 	"mmc list - lists available devices\n"
 	"mmc wp - power on write protect boot partitions\n"
 #if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
-	"mmc hwpartition [args...] - does hardware partitioning\n"
+	"mmc hwpartition <USER> <GP> <MODE> - does hardware partitioning\n"
 	"  arguments (sizes in 512-byte blocks):\n"
-	"    [user [enh start cnt] [wrrel {on|off}]] - sets user data area attributes\n"
-	"    [gp1|gp2|gp3|gp4 cnt [enh] [wrrel {on|off}]] - general purpose partition\n"
-	"    [check|set|complete] - mode, complete set partitioning completed\n"
+	"   USER - <user> <enh> <start> <cnt> <wrrel> <{on|off}>\n"
+	"	: sets user data area attributes\n"
+	"   GP - <{gp1|gp2|gp3|gp4}> <cnt> <enh> <wrrel> <{on|off}>\n"
+	"	: general purpose partition\n"
+	"   MODE - <{check|set|complete}>\n"
+	"	: mode, complete set partitioning completed\n"
 	"  WARNING: Partitioning is a write-once setting once it is set to complete.\n"
 	"  Power cycling is required to initialize partitions after set to complete.\n"
 #endif
diff --git a/cmd/scp03.c b/cmd/scp03.c
new file mode 100644
index 0000000..655e0bb
--- /dev/null
+++ b/cmd/scp03.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2021, Foundries.IO
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <scp03.h>
+
+int do_scp03_enable(struct cmd_tbl *cmdtp, int flag, int argc,
+		    char *const argv[])
+{
+	if (argc != 1)
+		return CMD_RET_USAGE;
+
+	if (tee_enable_scp03()) {
+		printf("TEE failed to enable SCP03\n");
+		return CMD_RET_FAILURE;
+	}
+
+	printf("SCP03 is enabled\n");
+
+	return CMD_RET_SUCCESS;
+}
+
+int do_scp03_provision(struct cmd_tbl *cmdtp, int flag, int argc,
+		       char *const argv[])
+{
+	if (argc != 1)
+		return CMD_RET_USAGE;
+
+	if (tee_provision_scp03()) {
+		printf("TEE failed to provision SCP03 keys\n");
+		return CMD_RET_FAILURE;
+	}
+
+	printf("SCP03 is provisioned\n");
+
+	return CMD_RET_SUCCESS;
+}
+
+static char text[] =
+	"provides a command to enable SCP03 and provision the SCP03 keys\n"
+	" enable    - enable SCP03 on the TEE\n"
+	" provision - provision SCP03 on the TEE\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(scp03, "Secure Channel Protocol 03 control", text,
+	U_BOOT_SUBCMD_MKENT(enable, 1, 1, do_scp03_enable),
+	U_BOOT_SUBCMD_MKENT(provision, 1, 1, do_scp03_provision));
+
diff --git a/cmd/tpm-v1.c b/cmd/tpm-v1.c
index 0e2168a..3a7e35d 100644
--- a/cmd/tpm-v1.c
+++ b/cmd/tpm-v1.c
@@ -11,6 +11,7 @@
 #include <tpm-common.h>
 #include <tpm-v1.h>
 #include "tpm-user-utils.h"
+#include <tpm_api.h>
 
 static int do_tpm_startup(struct cmd_tbl *cmdtp, int flag, int argc,
 			  char *const argv[])
@@ -55,7 +56,7 @@
 	perm = simple_strtoul(argv[2], NULL, 0);
 	size = simple_strtoul(argv[3], NULL, 0);
 
-	return report_return_code(tpm_nv_define_space(dev, index, perm, size));
+	return report_return_code(tpm1_nv_define_space(dev, index, perm, size));
 }
 
 static int do_tpm_nv_read_value(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -130,7 +131,7 @@
 		return CMD_RET_FAILURE;
 	}
 
-	rc = tpm_extend(dev, index, in_digest, out_digest);
+	rc = tpm_pcr_extend(dev, index, in_digest, out_digest);
 	if (!rc) {
 		puts("PCR value after execution of the command:\n");
 		print_byte_string(out_digest, sizeof(out_digest));
@@ -304,7 +305,7 @@
 	index = simple_strtoul(argv[2], NULL, 0);
 	perm = simple_strtoul(argv[3], NULL, 0);
 
-	return report_return_code(tpm_nv_define_space(dev, index, perm, size));
+	return report_return_code(tpm1_nv_define_space(dev, index, perm, size));
 }
 
 static int do_tpm_nv_read(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -389,7 +390,7 @@
 	if (rc)
 		return rc;
 
-	err = tpm_oiap(dev, &auth_handle);
+	err = tpm1_oiap(dev, &auth_handle);
 
 	return report_return_code(err);
 }
@@ -461,8 +462,8 @@
 		return CMD_RET_FAILURE;
 	parse_byte_string(argv[4], usage_auth, NULL);
 
-	err = tpm_load_key2_oiap(dev, parent_handle, key, key_len, usage_auth,
-				 &key_handle);
+	err = tpm1_load_key2_oiap(dev, parent_handle, key, key_len, usage_auth,
+				  &key_handle);
 	if (!err)
 		printf("Key handle is 0x%x\n", key_handle);
 
@@ -491,8 +492,8 @@
 		return CMD_RET_FAILURE;
 	parse_byte_string(argv[2], usage_auth, NULL);
 
-	err = tpm_get_pub_key_oiap(dev, key_handle, usage_auth, pub_key_buffer,
-				   &pub_key_len);
+	err = tpm1_get_pub_key_oiap(dev, key_handle, usage_auth, pub_key_buffer,
+				    &pub_key_len);
 	if (!err) {
 		printf("dump of received pub key structure:\n");
 		print_byte_string(pub_key_buffer, pub_key_len);
@@ -500,7 +501,7 @@
 	return report_return_code(err);
 }
 
-TPM_COMMAND_NO_ARG(tpm_end_oiap)
+TPM_COMMAND_NO_ARG(tpm1_end_oiap)
 
 #endif /* CONFIG_TPM_AUTH_SESSIONS */
 
@@ -562,7 +563,7 @@
 		res_count = get_unaligned_be16(buf);
 		ptr = buf + 2;
 		for (i = 0; i < res_count; ++i, ptr += 4)
-			tpm_flush_specific(dev, get_unaligned_be32(ptr), type);
+			tpm1_flush_specific(dev, get_unaligned_be32(ptr), type);
 	} else {
 		u32 handle = simple_strtoul(argv[2], NULL, 0);
 
@@ -570,7 +571,7 @@
 			printf("Illegal resource handle %s\n", argv[2]);
 			return -1;
 		}
-		tpm_flush_specific(dev, cpu_to_be32(handle), type);
+		tpm1_flush_specific(dev, cpu_to_be32(handle), type);
 	}
 
 	return 0;
@@ -691,7 +692,7 @@
 	U_BOOT_CMD_MKENT(oiap, 0, 1,
 			 do_tpm_oiap, "", ""),
 	U_BOOT_CMD_MKENT(end_oiap, 0, 1,
-			 do_tpm_end_oiap, "", ""),
+			 do_tpm1_end_oiap, "", ""),
 	U_BOOT_CMD_MKENT(load_key2_oiap, 0, 1,
 			 do_tpm_load_key2_oiap, "", ""),
 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
diff --git a/cmd/tpm_test.c b/cmd/tpm_test.c
index ebfb25c..a3ccb12 100644
--- a/cmd/tpm_test.c
+++ b/cmd/tpm_test.c
@@ -9,6 +9,7 @@
 #include <log.h>
 #include <tpm-v1.h>
 #include "tpm-user-utils.h"
+#include <tpm_api.h>
 
 /* Prints error and returns on failure */
 #define TPM_CHECK(tpm_command) do { \
@@ -49,7 +50,7 @@
 	struct tpm_permanent_flags pflags;
 	uint32_t result;
 
-	result = tpm_get_permanent_flags(dev, &pflags);
+	result = tpm1_get_permanent_flags(dev, &pflags);
 	if (result)
 		return result;
 	if (disable)
@@ -90,7 +91,7 @@
 	tpm_init(dev);
 	TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
 	TPM_CHECK(tpm_continue_self_test(dev));
-	TPM_CHECK(tpm_extend(dev, 1, value_in, value_out));
+	TPM_CHECK(tpm_pcr_extend(dev, 1, value_in, value_out));
 	printf("done\n");
 	return 0;
 }
@@ -146,7 +147,7 @@
 
 #define reboot() do { \
 	printf("\trebooting...\n"); \
-	reset_cpu(0); \
+	reset_cpu(); \
 } while (0)
 
 static int test_fast_enable(struct udevice *dev)
@@ -238,18 +239,18 @@
 	uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE;
 
 	printf("\tInitialising spaces\n");
-	tpm_nv_set_locked(dev);  /* useful only the first time */
-	tpm_nv_define_space(dev, INDEX0, perm, 4);
+	tpm1_nv_set_locked(dev);  /* useful only the first time */
+	tpm1_nv_define_space(dev, INDEX0, perm, 4);
 	tpm_nv_write_value(dev, INDEX0, (uint8_t *)&zero, 4);
-	tpm_nv_define_space(dev, INDEX1, perm, 4);
+	tpm1_nv_define_space(dev, INDEX1, perm, 4);
 	tpm_nv_write_value(dev, INDEX1, (uint8_t *)&zero, 4);
-	tpm_nv_define_space(dev, INDEX2, perm, 4);
+	tpm1_nv_define_space(dev, INDEX2, perm, 4);
 	tpm_nv_write_value(dev, INDEX2, (uint8_t *)&zero, 4);
-	tpm_nv_define_space(dev, INDEX3, perm, 4);
+	tpm1_nv_define_space(dev, INDEX3, perm, 4);
 	tpm_nv_write_value(dev, INDEX3, (uint8_t *)&zero, 4);
 	perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR |
 		TPM_NV_PER_PPWRITE;
-	tpm_nv_define_space(dev, INDEX_INITIALISED, perm, 1);
+	tpm1_nv_define_space(dev, INDEX_INITIALISED, perm, 1);
 }
 
 static int test_readonly(struct udevice *dev)
@@ -325,30 +326,33 @@
 
 	/* Redefines spaces a couple of times. */
 	perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK;
-	TPM_CHECK(tpm_nv_define_space(dev, INDEX0, perm, 2 * sizeof(uint32_t)));
-	TPM_CHECK(tpm_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t)));
+	TPM_CHECK(tpm1_nv_define_space(dev, INDEX0, perm,
+				       2 * sizeof(uint32_t)));
+	TPM_CHECK(tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t)));
 	perm = TPM_NV_PER_PPWRITE;
-	TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, 2 * sizeof(uint32_t)));
-	TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
+	TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm,
+				       2 * sizeof(uint32_t)));
+	TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
 
 	/* Sets the global lock */
 	tpm_set_global_lock(dev);
 
 	/* Verifies that index0 cannot be redefined */
-	result = tpm_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
+	result = tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
 	assert(result == TPM_AREA_LOCKED);
 
 	/* Checks that index1 can */
-	TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, 2 * sizeof(uint32_t)));
-	TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
+	TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm,
+				       2 * sizeof(uint32_t)));
+	TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
 
 	/* Turns off PP */
 	tpm_tsc_physical_presence(dev, PHYS_PRESENCE);
 
 	/* Verifies that neither index0 nor index1 can be redefined */
-	result = tpm_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
+	result = tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
 	assert(result == TPM_BAD_PRESENCE);
-	result = tpm_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t));
+	result = tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t));
 	assert(result == TPM_BAD_PRESENCE);
 
 	printf("done\n");
@@ -434,7 +438,7 @@
 		   100);
 	TTPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)),
 		   100);
-	TTPM_CHECK(tpm_extend(dev, 0, in, out), 200);
+	TTPM_CHECK(tpm_pcr_extend(dev, 0, in, out), 200);
 	TTPM_CHECK(tpm_set_global_lock(dev), 50);
 	TTPM_CHECK(tpm_tsc_physical_presence(dev, PHYS_PRESENCE), 100);
 	printf("done\n");
diff --git a/cmd/version.c b/cmd/version.c
index 3686b87..685b458 100644
--- a/cmd/version.c
+++ b/cmd/version.c
@@ -9,7 +9,7 @@
 #include <version.h>
 #include <linux/compiler.h>
 #ifdef CONFIG_SYS_COREBOOT
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
 #endif
 
 const char __weak version_string[] = U_BOOT_VERSION_STRING;
diff --git a/cmd/x86/Makefile b/cmd/x86/Makefile
index 144b1cf..5f82204 100644
--- a/cmd/x86/Makefile
+++ b/cmd/x86/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0+
 
+obj-$(CONFIG_CMD_CBSYSINFO) += cbsysinfo.o
 obj-y += mtrr.o
 obj-$(CONFIG_CMD_EXCEPTION) += exception.o
 obj-$(CONFIG_USE_HOB) += hob.o
diff --git a/cmd/x86/cbsysinfo.c b/cmd/x86/cbsysinfo.c
new file mode 100644
index 0000000..a0db0ad
--- /dev/null
+++ b/cmd/x86/cbsysinfo.c
@@ -0,0 +1,394 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <asm/cb_sysinfo.h>
+#include <command.h>
+#include <console.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void cbprompt(const char *name)
+{
+	for (; *name == '>'; name++)
+		puts("   ");
+	printf("%-12s: ", name);
+}
+
+static void print_dec(const char *name, int value)
+{
+	cbprompt(name);
+	printf(value > 9 ? "0d%d\n" : "%d\n", value);
+}
+
+static void print_hex(const char *name, int value)
+{
+	cbprompt(name);
+	printf("%x\n", value);
+}
+
+static void print_addr(const char *name, ulong value)
+{
+	cbprompt(name);
+	printf("%08lx\n", value);
+}
+
+static void print_addr64(const char *name, u64 value)
+{
+	cbprompt(name);
+	printf("%16llx\n", value);
+}
+
+static void print_ptr(const char *name, const void *value)
+{
+	cbprompt(name);
+	printf("%p\n", value);
+}
+
+static void print_str(const char *name, const char *value)
+{
+	if (value) {
+		cbprompt(name);
+		printf("%s\n", value);
+	}
+}
+
+static void print_idx(const char *name, uint idx, const u8 *strings)
+{
+	const char *ptr;
+
+	cbprompt(name);
+	ptr = (char *)strings + idx;
+	printf("%d: %s\n", idx, ptr ? ptr : "(unknown)");
+}
+
+static const char *const cb_mem_name[] = {
+	NULL,
+	"ram",
+	"reserved",
+	"acpi",
+	"nvs",
+	"unusable",
+	"vendor",
+};
+
+static const char *get_mem_name(int tag)
+{
+	if (tag >= CB_MEM_RAM && tag <= CB_MEM_VENDOR_RSVD)
+		return cb_mem_name[tag];
+
+	if (tag == CB_MEM_TABLE)
+		return "table";
+
+	return "(unknown)";
+}
+
+static const struct timestamp_id_to_name {
+	uint id;
+	const char *name;
+} timestamp_ids[] = {
+	/* Marker to report base_time */
+	{ 0,			"1st timestamp" },
+	{ TS_START_ROMSTAGE,	"start of romstage" },
+	{ TS_BEFORE_INITRAM,	"before ram initialization" },
+	{ TS_AFTER_INITRAM,	"after ram initialization" },
+	{ TS_END_ROMSTAGE,	"end of romstage" },
+	{ TS_START_VBOOT,	"start of verified boot" },
+	{ TS_END_VBOOT,		"end of verified boot" },
+	{ TS_START_COPYRAM,	"starting to load ramstage" },
+	{ TS_END_COPYRAM,	"finished loading ramstage" },
+	{ TS_START_RAMSTAGE,	"start of ramstage" },
+	{ TS_START_BOOTBLOCK,	"start of bootblock" },
+	{ TS_END_BOOTBLOCK,	"end of bootblock" },
+	{ TS_START_COPYROM,	"starting to load romstage" },
+	{ TS_END_COPYROM,	"finished loading romstage" },
+	{ TS_START_ULZMA,	"starting LZMA decompress (ignore for x86)" },
+	{ TS_END_ULZMA,		"finished LZMA decompress (ignore for x86)" },
+	{ TS_START_ULZ4F,	"starting LZ4 decompress (ignore for x86)" },
+	{ TS_END_ULZ4F,		"finished LZ4 decompress (ignore for x86)" },
+	{ TS_DEVICE_ENUMERATE,	"device enumeration" },
+	{ TS_DEVICE_CONFIGURE,	"device configuration" },
+	{ TS_DEVICE_ENABLE,	"device enable" },
+	{ TS_DEVICE_INITIALIZE,	"device initialization" },
+	{ TS_DEVICE_DONE,	"device setup done" },
+	{ TS_CBMEM_POST,	"cbmem post" },
+	{ TS_WRITE_TABLES,	"write tables" },
+	{ TS_FINALIZE_CHIPS,	"finalize chips" },
+	{ TS_LOAD_PAYLOAD,	"load payload" },
+	{ TS_ACPI_WAKE_JUMP,	"ACPI wake jump" },
+	{ TS_SELFBOOT_JUMP,	"selfboot jump" },
+
+	{ TS_START_COPYVER,	"starting to load verstage" },
+	{ TS_END_COPYVER,	"finished loading verstage" },
+	{ TS_START_TPMINIT,	"starting to initialize TPM" },
+	{ TS_END_TPMINIT,	"finished TPM initialization" },
+	{ TS_START_VERIFY_SLOT,	"starting to verify keyblock/preamble (RSA)" },
+	{ TS_END_VERIFY_SLOT,	"finished verifying keyblock/preamble (RSA)" },
+	{ TS_START_HASH_BODY,	"starting to verify body (load+SHA2+RSA) " },
+	{ TS_DONE_LOADING,	"finished loading body (ignore for x86)" },
+	{ TS_DONE_HASHING,	"finished calculating body hash (SHA2)" },
+	{ TS_END_HASH_BODY,	"finished verifying body signature (RSA)" },
+
+	{ TS_START_COPYVPD,	"starting to load Chrome OS VPD" },
+	{ TS_END_COPYVPD_RO,	"finished loading Chrome OS VPD (RO)" },
+	{ TS_END_COPYVPD_RW,	"finished loading Chrome OS VPD (RW)" },
+
+	{ TS_U_BOOT_INITTED,	"U-Boot start" },
+	{ TS_RO_PARAMS_INIT,	"RO parameter init" },
+	{ TS_RO_VB_INIT,	"RO vboot init" },
+	{ TS_RO_VB_SELECT_FIRMWARE,		"RO vboot select firmware" },
+	{ TS_RO_VB_SELECT_AND_LOAD_KERNEL,	"RO vboot select&load kernel" },
+	{ TS_RW_VB_SELECT_AND_LOAD_KERNEL,	"RW vboot select&load kernel" },
+	{ TS_VB_SELECT_AND_LOAD_KERNEL,		"vboot select&load kernel" },
+	{ TS_VB_EC_VBOOT_DONE,	"finished EC verification" },
+	{ TS_VB_STORAGE_INIT_DONE, "finished storage device initialization" },
+	{ TS_VB_READ_KERNEL_DONE, "finished reading kernel from disk" },
+	{ TS_VB_VBOOT_DONE,	"finished vboot kernel verification" },
+	{ TS_KERNEL_DECOMPRESSION, "starting kernel decompression/relocation" },
+	{ TS_START_KERNEL,	"jumping to kernel" },
+	{ TS_U_BOOT_START_KERNEL,	"just before jump to kernel" },
+
+	/* Intel ME-related timestamps */
+	{ TS_ME_INFORM_DRAM_WAIT, "waiting for ME acknowledgment of raminit"},
+	{ TS_ME_INFORM_DRAM_DONE, "finished waiting for ME response"},
+
+	/* FSP-related timestamps */
+	{ TS_FSP_MEMORY_INIT_START, "calling FspMemoryInit" },
+	{ TS_FSP_MEMORY_INIT_END, "returning from FspMemoryInit" },
+	{ TS_FSP_TEMP_RAM_EXIT_START, "calling FspTempRamExit" },
+	{ TS_FSP_TEMP_RAM_EXIT_END, "returning from FspTempRamExit" },
+	{ TS_FSP_SILICON_INIT_START, "calling FspSiliconInit" },
+	{ TS_FSP_SILICON_INIT_END, "returning from FspSiliconInit" },
+	{ TS_FSP_BEFORE_ENUMERATE, "calling FspNotify(AfterPciEnumeration)" },
+	{ TS_FSP_AFTER_ENUMERATE,
+		 "returning from FspNotify(AfterPciEnumeration)" },
+	{ TS_FSP_BEFORE_FINALIZE, "calling FspNotify(ReadyToBoot)" },
+	{ TS_FSP_AFTER_FINALIZE, "returning from FspNotify(ReadyToBoot)" },
+	{ TS_FSP_BEFORE_END_OF_FIRMWARE, "calling FspNotify(EndOfFirmware)" },
+	{ TS_FSP_AFTER_END_OF_FIRMWARE,
+		"returning from FspNotify(EndOfFirmware)" },
+};
+
+static const char *timestamp_name(uint32_t id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(timestamp_ids); i++) {
+		if (timestamp_ids[i].id == id)
+			return timestamp_ids[i].name;
+	}
+
+	return "<unknown>";
+}
+
+static void show_table(struct sysinfo_t *info, bool verbose)
+{
+	struct cb_serial *ser = info->serial;
+	int i;
+
+	printf("Coreboot table at %lx, decoded to %p",
+	       gd->arch.coreboot_table, info);
+	if (info->header)
+		printf(", forwarded to %p\n", info->header);
+	printf("\n");
+
+	print_dec("CPU KHz", info->cpu_khz);
+
+	print_addr("Serial I/O port", info->ser_ioport);
+	print_addr(">base", info->ser_base);
+	print_ptr(">pointer", ser);
+	if (ser) {
+		print_hex(">type", ser->type);
+		print_addr(">base", ser->baseaddr);
+		print_dec(">baud", ser->baud);
+		print_hex(">baud", ser->regwidth);
+		print_dec(">input_hz", ser->input_hertz);
+		print_addr(">PCI addr", ser->uart_pci_addr);
+	}
+
+	print_dec("Mem ranges", info->n_memranges);
+	printf("%12s: %-11s        ||   base        ||   size\n", "id", "type");
+	for (i = 0; i < info->n_memranges; i++) {
+		const struct memrange *mr = &info->memrange[i];
+
+		printf("%12d: %02x:%-8s %016llx %016llx\n", i, mr->type,
+		       get_mem_name(mr->type), mr->base, mr->size);
+	}
+	print_ptr("option_table", info->option_table);
+
+	print_hex("CMOS start", info->cmos_range_start);
+	if (info->cmos_range_start) {
+		print_hex(">CMOS end", info->cmos_range_end);
+		print_hex(">CMOS csum loc", info->cmos_checksum_location);
+	}
+
+	print_hex("VBNV start", info->vbnv_start);
+	print_hex("VBNV size", info->vbnv_size);
+
+	print_str("CB version", info->cb_version);
+	print_str(">Extra", info->extra_version);
+	print_str(">Build", info->build);
+	print_str(">Time", info->compile_time);
+	print_str(">By", info->compile_by);
+	print_str(">Host", info->compile_host);
+	print_str(">Domain", info->compile_domain);
+	print_str(">Compiler", info->compiler);
+	print_str(">Linker", info->linker);
+	print_str(">Assembler", info->assembler);
+
+	print_ptr("Framebuffer", info->framebuffer);
+	if (info->framebuffer) {
+		struct cb_framebuffer *fb = info->framebuffer;
+
+		print_addr64(">Phys addr", fb->physical_address);
+		print_dec(">X res", fb->x_resolution);
+		print_dec(">X res", fb->y_resolution);
+		print_hex(">Bytes / line", fb->bytes_per_line);
+		print_dec(">Bpp", fb->bits_per_pixel);
+		printf("   %-12s  red %d/%d, green %d/%d, blue %d/%d, reserved %d/%d\n",
+		       "pos/size", fb->red_mask_pos, fb->red_mask_size,
+		       fb->green_mask_pos, fb->green_mask_size,
+		       fb->blue_mask_pos, fb->blue_mask_size,
+		       fb->reserved_mask_pos, fb->reserved_mask_size);
+	}
+
+	print_dec("GPIOs", info->num_gpios);
+	printf("%12s: %4s %12s %3s %s\n", "id", "port", "polarity", "val",
+	       "name");
+	for (i = 0; i < info->num_gpios; i++) {
+		const struct cb_gpio *gpio = &info->gpios[i];
+		char portstr[4];
+
+		if (gpio->port == 0xffffffff)
+			strcpy(portstr, "-");
+		else
+			sprintf(portstr, "%x", gpio->port);
+		printf("%12d: %4s %12s %3d %s\n", i, portstr,
+		       gpio->polarity == CB_GPIO_ACTIVE_LOW ? "active-low" :
+		       "active-high", gpio->value, gpio->name);
+	}
+	print_dec("MACs", info->num_macs);
+	for (i = 0; i < info->num_macs; i++) {
+		const struct mac_address *mac = &info->macs[i];
+		int j;
+
+		printf("%12d: ", i);
+		for (j = 0; j < sizeof(mac->mac_addr); j++)
+			printf("%s%02x", j ? ":" : "", mac->mac_addr[j]);
+		printf("\n");
+	}
+	print_str(">Serial #", info->serialno);
+	print_ptr("Multiboot tab", info->mbtable);
+	print_ptr("CB header", info->header);
+	print_ptr("CB mainboard", info->mainboard);
+	if (info->mainboard) {
+		struct cb_mainboard *mb = info->mainboard;
+
+		print_idx(">vendor", mb->vendor_idx, mb->strings);
+		print_idx(">part_number", mb->part_number_idx, mb->strings);
+	}
+	print_ptr("vboot handoff", info->vboot_handoff);
+	print_hex(">size", info->vboot_handoff_size);
+	print_ptr(">vdat addr", info->vdat_addr);
+	print_hex(">size", info->vdat_size);
+
+	print_addr64("SMBIOS", info->smbios_start);
+	print_hex(">size", info->smbios_size);
+	print_hex("ROM MTRR", info->x86_rom_var_mtrr_index);
+
+	print_ptr("Tstamp table", info->tstamp_table);
+	if (verbose && info->tstamp_table) {
+		struct timestamp_table *ts = info->tstamp_table;
+
+		printf("%-12s", "Base_time");
+		print_grouped_ull(ts->base_time, 12);
+		printf("\n");
+		print_dec("Tick MHz", ts->tick_freq_mhz);
+		for (i = 0; i < ts->num_entries; i++) {
+			const struct timestamp_entry *tse;
+
+			tse = &ts->entries[i];
+			printf("   ");
+			print_grouped_ull(tse->entry_stamp, 12);
+			printf("  %s\n", timestamp_name(tse->entry_id));
+		}
+	}
+
+	print_ptr("CBmem cons", info->cbmem_cons);
+	if (info->cbmem_cons) {
+		struct cbmem_console *cons = info->cbmem_cons;
+		int i;
+
+		print_hex("Size", cons->size);
+		print_hex("Cursor", cons->cursor);
+		if (verbose) {
+			for (i = 0; i < cons->cursor; i++) {
+				int ch = cons->body[i];
+
+				putc(ch);
+
+				if (ch == '\n') {
+					/* check for ctrl-c to abort... */
+					if (ctrlc()) {
+						puts("Abort\n");
+						return;
+					}
+					printf("   ");
+				}
+			}
+			printf("\n");
+		}
+	}
+
+	print_ptr("MRC cache", info->mrc_cache);
+	print_ptr("ACPI GNVS", info->acpi_gnvs);
+	print_hex("Board ID", info->board_id);
+	print_hex("RAM code", info->ram_code);
+	print_ptr("WiFi calib", info->wifi_calibration);
+	print_addr64("Ramoops buff", info->ramoops_buffer);
+	print_hex(">size", info->ramoops_buffer_size);
+	print_hex("SF size", info->spi_flash.size);
+	print_hex("SF sector", info->spi_flash.sector_size);
+	print_hex("SF erase cmd", info->spi_flash.erase_cmd);
+
+	print_addr64("FMAP offset", info->fmap_offset);
+	print_addr64("CBFS offset", info->cbfs_offset);
+	print_addr64("CBFS size", info->cbfs_size);
+	print_addr64("Boot media size", info->boot_media_size);
+	print_addr64("MTC start", info->mtc_start);
+	print_hex("MTC size", info->mtc_size);
+
+	print_ptr("Chrome OS VPD", info->chromeos_vpd);
+}
+
+static int do_cbsysinfo(struct cmd_tbl *cmdtp, int flag, int argc,
+			char *const argv[])
+{
+	bool verbose = false;
+
+	if (argc > 1) {
+		if (!strcmp("-v", argv[1]))
+			verbose = true;
+		else
+			return CMD_RET_USAGE;
+	}
+
+	if (!gd->arch.coreboot_table) {
+		printf("No coreboot sysinfo table found\n");
+		return CMD_RET_FAILURE;
+	}
+	show_table(&lib_sysinfo, verbose);
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	cbsysinfo,	2,	1,	do_cbsysinfo,
+	"Show coreboot sysinfo table",
+	"[-v]         Dumps out the contents of the sysinfo table. This only\n"
+	"works if U-Boot is booted from coreboot"
+);
diff --git a/common/Kconfig b/common/Kconfig
index 2bb3798..0e36dfd 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -527,6 +527,12 @@
 	  U-Boot calls last_stage_init() before the command-line interpreter is
 	  started.
 
+config MISC_INIT_F
+	bool "Execute pre-relocation misc init"
+	help
+	  Enabling this option calls the 'misc_init_f' function in the init
+	  sequence just before DRAM is inited.
+
 config MISC_INIT_R
 	bool "Execute Misc Init"
 	default y if ARCH_KEYSTONE || ARCH_SUNXI || MPC85xx
@@ -588,6 +594,14 @@
 
 endif # AVB_VERIFY
 
+config SCP03
+	bool "Build SCP03 - Secure Channel Protocol O3 - controls"
+	depends on OPTEE || SANDBOX
+	depends on TEE
+	help
+	  This option allows U-Boot to enable and or provision SCP03 on an OPTEE
+	  controlled Secured Element.
+
 config SPL_HASH
 	bool # "Support hashing API (SHA1, SHA256, etc.)"
 	help
diff --git a/common/Makefile b/common/Makefile
index daeea67..215b8b2 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -137,3 +137,4 @@
 obj-$(CONFIG_$(SPL_TPL_)YMODEM_SUPPORT) += xyzModem.o
 
 obj-$(CONFIG_AVB_VERIFY) += avb_verify.o
+obj-$(CONFIG_SCP03) += scp03.o
diff --git a/common/board_info.c b/common/board_info.c
index b54aa30..1cfe34f 100644
--- a/common/board_info.c
+++ b/common/board_info.c
@@ -1,31 +1,52 @@
 // SPDX-License-Identifier: GPL-2.0+
 
 #include <common.h>
+#include <dm.h>
 #include <init.h>
+#include <sysinfo.h>
 #include <asm/global_data.h>
 #include <linux/libfdt.h>
 #include <linux/compiler.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 int __weak checkboard(void)
 {
 	return 0;
 }
 
 /*
- * If the root node of the DTB has a "model" property, show it.
+ * Check sysinfo for board information. Failing that if the root node of the DTB
+ * has a "model" property, show it.
+ *
  * Then call checkboard().
  */
 int __weak show_board_info(void)
 {
-#ifdef CONFIG_OF_CONTROL
-	DECLARE_GLOBAL_DATA_PTR;
-	const char *model;
+	if (IS_ENABLED(CONFIG_OF_CONTROL)) {
+		struct udevice *dev;
+		const char *model;
+		char str[80];
+		int ret = -ENOSYS;
 
-	model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+		if (IS_ENABLED(CONFIG_SYSINFO)) {
+			/* This might provide more detail */
+			ret = uclass_first_device_err(UCLASS_SYSINFO, &dev);
+			if (!ret)
+				ret = sysinfo_get_str(dev,
+						      SYSINFO_ID_BOARD_MODEL,
+						      sizeof(str), str);
+		}
 
-	if (model)
-		printf("Model: %s\n", model);
-#endif
+		/* Fail back to the main 'model' if available */
+		if (ret)
+			model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+		else
+			model = str;
+
+		if (model)
+			printf("Model: %s\n", model);
+	}
 
 	return checkboard();
 }
diff --git a/common/bootm.c b/common/bootm.c
index defaed8..ea71522 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -583,10 +583,11 @@
 		if (ret)
 			return log_msg_ret("silent", ret);
 	}
-	if (IS_ENABLED(CONFIG_BOOTARGS_SUBST) && (flags & BOOTM_CL_SUBST)) {
+	if (IS_ENABLED(CONFIG_BOOTARGS_SUBST) && IS_ENABLED(CONFIG_CMDLINE) &&
+	    (flags & BOOTM_CL_SUBST)) {
 		ret = process_subst(buf, maxlen);
 		if (ret)
-			return log_msg_ret("silent", ret);
+			return log_msg_ret("subst", ret);
 	}
 
 	return 0;
diff --git a/common/bootstage.c b/common/bootstage.c
index 2c0110c..4621105 100644
--- a/common/bootstage.c
+++ b/common/bootstage.c
@@ -9,6 +9,8 @@
  * permits accurate timestamping of each.
  */
 
+#define LOG_CATEGORY	LOGC_BOOT
+
 #include <common.h>
 #include <bootstage.h>
 #include <hang.h>
@@ -127,12 +129,16 @@
 
 	/* Only record the first event for each */
 	rec = find_id(data, id);
-	if (!rec && data->rec_count < RECORD_COUNT) {
-		rec = &data->record[data->rec_count++];
-		rec->time_us = mark;
-		rec->name = name;
-		rec->flags = flags;
-		rec->id = id;
+	if (!rec) {
+		if (data->rec_count < RECORD_COUNT) {
+			rec = &data->record[data->rec_count++];
+			rec->time_us = mark;
+			rec->name = name;
+			rec->flags = flags;
+			rec->id = id;
+		} else {
+			log_warning("Bootstage space exhasuted\n");
+		}
 	}
 
 	/* Tell the board about this progress */
diff --git a/common/image-fit.c b/common/image-fit.c
index 94501b1..b972042 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -1512,6 +1512,10 @@
 	uint8_t image_arch;
 	int aarch32_support = 0;
 
+	/* Let's assume that sandbox can load any architecture */
+	if (IS_ENABLED(CONFIG_SANDBOX))
+		return true;
+
 	if (IS_ENABLED(CONFIG_ARM64_SUPPORT_AARCH32))
 		aarch32_support = 1;
 
diff --git a/common/log.c b/common/log.c
index 6b0034c..ea407c6 100644
--- a/common/log.c
+++ b/common/log.c
@@ -153,7 +153,7 @@
 {
 	struct log_filter *filt;
 
-	if (rec->force_debug)
+	if (rec->flags & LOGRECF_FORCE_DEBUG)
 		return true;
 
 	/* If there are no filters, filter on the default log level */
@@ -218,8 +218,11 @@
 		if ((ldev->flags & LOGDF_ENABLE) &&
 		    log_passes_filters(ldev, rec)) {
 			if (!rec->msg) {
-				vsnprintf(buf, sizeof(buf), fmt, args);
+				int len;
+
+				len = vsnprintf(buf, sizeof(buf), fmt, args);
 				rec->msg = buf;
+				gd->log_cont = len && buf[len - 1] != '\n';
 			}
 			ldev->drv->emit(ldev, rec);
 		}
@@ -245,7 +248,11 @@
 
 	rec.cat = cat;
 	rec.level = level & LOGL_LEVEL_MASK;
-	rec.force_debug = level & LOGL_FORCE_DEBUG;
+	rec.flags = 0;
+	if (level & LOGL_FORCE_DEBUG)
+		rec.flags |= LOGRECF_FORCE_DEBUG;
+	if (gd->log_cont)
+		rec.flags |= LOGRECF_CONT;
 	rec.file = file;
 	rec.line = line;
 	rec.func = func;
@@ -255,7 +262,8 @@
 		gd->log_drop_count++;
 
 		/* display dropped traces with console puts and DEBUG_UART */
-		if (rec.level <= CONFIG_LOG_DEFAULT_LEVEL || rec.force_debug) {
+		if (rec.level <= CONFIG_LOG_DEFAULT_LEVEL ||
+		    rec.flags & LOGRECF_FORCE_DEBUG) {
 			char buf[CONFIG_SYS_CBSIZE];
 
 			va_start(args, fmt);
diff --git a/common/log_console.c b/common/log_console.c
index 6abb13c..3f61774 100644
--- a/common/log_console.c
+++ b/common/log_console.c
@@ -15,6 +15,7 @@
 static int log_console_emit(struct log_device *ldev, struct log_rec *rec)
 {
 	int fmt = gd->log_fmt;
+	bool add_space = false;
 
 	/*
 	 * The output format is designed to give someone a fighting chance of
@@ -26,18 +27,21 @@
 	 *    - function is an identifier and ends with ()
 	 *    - message has a space before it unless it is on its own
 	 */
-	if (fmt & BIT(LOGF_LEVEL))
-		printf("%s.", log_get_level_name(rec->level));
-	if (fmt & BIT(LOGF_CAT))
-		printf("%s,", log_get_cat_name(rec->cat));
-	if (fmt & BIT(LOGF_FILE))
-		printf("%s:", rec->file);
-	if (fmt & BIT(LOGF_LINE))
-		printf("%d-", rec->line);
-	if (fmt & BIT(LOGF_FUNC))
-		printf("%s()", rec->func);
+	if (!(rec->flags & LOGRECF_CONT) && fmt != BIT(LOGF_MSG)) {
+		add_space = true;
+		if (fmt & BIT(LOGF_LEVEL))
+			printf("%s.", log_get_level_name(rec->level));
+		if (fmt & BIT(LOGF_CAT))
+			printf("%s,", log_get_cat_name(rec->cat));
+		if (fmt & BIT(LOGF_FILE))
+			printf("%s:", rec->file);
+		if (fmt & BIT(LOGF_LINE))
+			printf("%d-", rec->line);
+		if (fmt & BIT(LOGF_FUNC))
+			printf("%s()", rec->func);
+	}
 	if (fmt & BIT(LOGF_MSG))
-		printf("%s%s", fmt != BIT(LOGF_MSG) ? " " : "", rec->msg);
+		printf("%s%s", add_space ? " " : "", rec->msg);
 
 	return 0;
 }
diff --git a/common/scp03.c b/common/scp03.c
new file mode 100644
index 0000000..09ef7b5
--- /dev/null
+++ b/common/scp03.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2021, Foundries.IO
+ *
+ */
+
+#include <common.h>
+#include <scp03.h>
+#include <tee.h>
+#include <tee/optee_ta_scp03.h>
+
+static int scp03_enable(bool provision)
+{
+	const struct tee_optee_ta_uuid uuid = PTA_SCP03_UUID;
+	struct tee_open_session_arg session;
+	struct tee_invoke_arg invoke;
+	struct tee_param param;
+	struct udevice *tee = NULL;
+
+	tee = tee_find_device(tee, NULL, NULL, NULL);
+	if (!tee)
+		return -ENODEV;
+
+	memset(&session, 0, sizeof(session));
+	tee_optee_ta_uuid_to_octets(session.uuid, &uuid);
+	if (tee_open_session(tee, &session, 0, NULL))
+		return -ENXIO;
+
+	memset(&param, 0, sizeof(param));
+	param.attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
+	param.u.value.a = provision;
+
+	memset(&invoke, 0, sizeof(invoke));
+	invoke.func = PTA_CMD_ENABLE_SCP03;
+	invoke.session = session.session;
+
+	if (tee_invoke_func(tee, &invoke, 1, &param))
+		return -EIO;
+
+	tee_close_session(tee, session.session);
+
+	return 0;
+}
+
+int tee_enable_scp03(void)
+{
+	return scp03_enable(false);
+}
+
+int tee_provision_scp03(void)
+{
+	return scp03_enable(true);
+}
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 774541c..0f528f3 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -276,6 +276,19 @@
 	  location is used. Normally we put the device tree at the end of BSS
 	  but with this option enabled, it goes at _image_binary_end.
 
+config SPL_READ_ONLY
+	bool
+	depends on SPL_OF_PLATDATA
+	# Bind cannot be supported because the udevice structs are in read-only
+	# memory so we cannot update the linked lists.
+	select SPL_OF_PLATDATA_NO_BIND
+	select SPL_OF_PLATDATA_RT
+	help
+	  Some platforms (e.g. x86 Apollo Lake) load SPL into a read-only
+	  section of memory. This means that of-platdata must make a copy (in
+	  writeable memory) of anything it wants to modify, such as
+	  device-private data.
+
 config SPL_BANNER_PRINT
 	bool "Enable output of the SPL banner 'U-Boot SPL ...'"
 	default y
@@ -317,7 +330,8 @@
 		     ARCH_MX6 || ARCH_MX7 || \
 		     ARCH_ROCKCHIP || ARCH_MVEBU ||  ARCH_SOCFPGA || \
 		     ARCH_AT91 || ARCH_ZYNQ || ARCH_KEYSTONE || OMAP34XX || \
-		     OMAP44XX || OMAP54XX || AM33XX || AM43XX || TARGET_SIFIVE_FU540
+		     OMAP44XX || OMAP54XX || AM33XX || AM43XX || \
+		     TARGET_SIFIVE_UNLEASHED
 	help
 	  Use sector number for specifying U-Boot location on MMC/SD in
 	  raw mode.
@@ -334,7 +348,7 @@
 	default 0x300 if ARCH_ZYNQ || ARCH_KEYSTONE || OMAP34XX || OMAP44XX || \
 		         OMAP54XX || AM33XX || AM43XX || ARCH_K3
 	default 0x4000 if ARCH_ROCKCHIP
-	default 0x822 if TARGET_SIFIVE_FU540
+	default 0x822 if TARGET_SIFIVE_UNLEASHED
 	help
 	  Address on the MMC to load U-Boot from, when the MMC is being used
 	  in raw mode. Units: MMC sectors (1 sector = 512 bytes).
@@ -487,7 +501,7 @@
 	  future requests for that data can be served faster. Enable this option
 	  to build the drivers in drivers/cache as part of an SPL build.
 
-config SPL_CPU_SUPPORT
+config SPL_CPU
 	bool "Support CPU drivers"
 	help
 	  Enable this to support CPU drivers in SPL. These drivers can set
@@ -1440,6 +1454,17 @@
 	  The address of the initial stack-pointer for the TPL stage.
 	  Usually this will be the (aligned) top-of-stack.
 
+config TPL_READ_ONLY
+	bool
+	depends on TPL_OF_PLATDATA
+	select TPL_OF_PLATDATA_NO_BIND
+	select TPL_OF_PLATDATA_RT
+	help
+	  Some platforms (e.g. x86 Apollo Lake) load SPL into a read-only
+	  section of memory. This means that of-platdata must make a copy (in
+	  writeable memory) of anything it wants to modify, such as
+	  device-private data.
+
 config TPL_BOOTROM_SUPPORT
         bool "Support returning to the BOOTROM (from TPL)"
 	help
diff --git a/common/spl/spl.c b/common/spl/spl.c
index e3d8408..556a91a 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -16,6 +16,7 @@
 #include <init.h>
 #include <irq_func.h>
 #include <log.h>
+#include <mapmem.h>
 #include <serial.h>
 #include <spl.h>
 #include <asm/global_data.h>
@@ -168,7 +169,7 @@
 
 __weak struct image_header *spl_get_load_buffer(ssize_t offset, size_t size)
 {
-	return (struct image_header *)(CONFIG_SYS_TEXT_BASE + offset);
+	return map_sysmem(CONFIG_SYS_TEXT_BASE + offset, 0);
 }
 
 void spl_set_header_raw_uboot(struct spl_image_info *spl_image)
@@ -386,6 +387,22 @@
 
 #endif /* HANDOFF */
 
+/**
+ * get_bootstage_id() - Get the bootstage ID to emit
+ *
+ * @start: true if this is for starting SPL, false for ending it
+ * @return bootstage ID to use
+ */
+static enum bootstage_id get_bootstage_id(bool start)
+{
+	enum u_boot_phase phase = spl_phase();
+
+	if (IS_ENABLED(CONFIG_TPL_BUILD) && phase == PHASE_TPL)
+		return start ? BOOTSTAGE_ID_START_TPL : BOOTSTAGE_ID_END_TPL;
+	else
+		return start ? BOOTSTAGE_ID_START_SPL : BOOTSTAGE_ID_END_SPL;
+}
+
 static int spl_common_init(bool setup_malloc)
 {
 	int ret;
@@ -416,8 +433,8 @@
 			      __func__, ret);
 	}
 #endif /* CONFIG_BOOTSTAGE_STASH */
-	bootstage_mark_name(spl_phase() == PHASE_TPL ? BOOTSTAGE_ID_START_TPL :
-			    BOOTSTAGE_ID_START_SPL, SPL_TPL_NAME);
+	bootstage_mark_name(get_bootstage_id(true),
+			    spl_phase_name(spl_phase()));
 #if CONFIG_IS_ENABLED(LOG)
 	ret = log_init();
 	if (ret) {
@@ -694,7 +711,7 @@
 #endif
 	switch (spl_image.os) {
 	case IH_OS_U_BOOT:
-		debug("Jumping to U-Boot\n");
+		debug("Jumping to %s...\n", spl_phase_name(spl_next_phase()));
 		break;
 #if CONFIG_IS_ENABLED(ATF)
 	case IH_OS_ARM_TRUSTED_FIRMWARE:
@@ -732,8 +749,7 @@
 	debug("SPL malloc() used 0x%lx bytes (%ld KB)\n", gd->malloc_ptr,
 	      gd->malloc_ptr / 1024);
 #endif
-	bootstage_mark_name(spl_phase() == PHASE_TPL ? BOOTSTAGE_ID_END_TPL :
-			    BOOTSTAGE_ID_END_SPL, "end " SPL_TPL_NAME);
+	bootstage_mark_name(get_bootstage_id(false), "end phase");
 #ifdef CONFIG_BOOTSTAGE_STASH
 	ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR,
 			      CONFIG_BOOTSTAGE_STASH_SIZE);
@@ -741,7 +757,6 @@
 		debug("Failed to stash bootstage: err=%d\n", ret);
 #endif
 
-	debug("loaded - jumping to %s...\n", spl_phase_name(spl_next_phase()));
 	spl_board_prepare_for_boot();
 	jump_to_image_no_args(&spl_image);
 }
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 75c8ff0..49508fc 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -11,6 +11,7 @@
 #include <image.h>
 #include <log.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <spl.h>
 #include <sysinfo.h>
 #include <asm/cache.h>
@@ -235,11 +236,11 @@
 	size_t length;
 	int len;
 	ulong size;
-	ulong load_addr, load_ptr;
+	ulong load_addr;
+	void *load_ptr;
 	void *src;
 	ulong overhead;
 	int nr_sectors;
-	int align_len = ARCH_DMA_MINALIGN - 1;
 	uint8_t image_comp = -1, type = -1;
 	const void *data;
 	const void *fit = ctx->fit;
@@ -269,11 +270,13 @@
 	}
 
 	if (external_data) {
+		void *src_ptr;
+
 		/* External data */
 		if (fit_image_get_data_size(fit, node, &len))
 			return -ENOENT;
 
-		load_ptr = (load_addr + align_len) & ~align_len;
+		src_ptr = map_sysmem(ALIGN(load_addr, ARCH_DMA_MINALIGN), len);
 		length = len;
 
 		overhead = get_aligned_image_overhead(info, offset);
@@ -281,12 +284,12 @@
 
 		if (info->read(info,
 			       sector + get_aligned_image_offset(info, offset),
-			       nr_sectors, (void *)load_ptr) != nr_sectors)
+			       nr_sectors, src_ptr) != nr_sectors)
 			return -EIO;
 
-		debug("External data: dst=%lx, offset=%x, size=%lx\n",
-		      load_ptr, offset, (unsigned long)length);
-		src = (void *)load_ptr + overhead;
+		debug("External data: dst=%p, offset=%x, size=%lx\n",
+		      src_ptr, offset, (unsigned long)length);
+		src = src_ptr + overhead;
 	} else {
 		/* Embedded data */
 		if (fit_image_get_data(fit, node, &data, &length)) {
@@ -295,7 +298,7 @@
 		}
 		debug("Embedded data: dst=%lx, size=%lx\n", load_addr,
 		      (unsigned long)length);
-		src = (void *)data;
+		src = (void *)data;	/* cast away const */
 	}
 
 	if (CONFIG_IS_ENABLED(FIT_SIGNATURE)) {
@@ -309,16 +312,16 @@
 	if (CONFIG_IS_ENABLED(FIT_IMAGE_POST_PROCESS))
 		board_fit_image_post_process(&src, &length);
 
+	load_ptr = map_sysmem(load_addr, length);
 	if (IS_ENABLED(CONFIG_SPL_GZIP) && image_comp == IH_COMP_GZIP) {
 		size = length;
-		if (gunzip((void *)load_addr, CONFIG_SYS_BOOTM_LEN,
-			   src, &size)) {
+		if (gunzip(load_ptr, CONFIG_SYS_BOOTM_LEN, src, &size)) {
 			puts("Uncompressing error\n");
 			return -EIO;
 		}
 		length = size;
 	} else {
-		memcpy((void *)load_addr, src, length);
+		memcpy(load_ptr, src, length);
 	}
 
 	if (image_info) {
@@ -383,7 +386,7 @@
 	}
 
 	/* Make the load-address of the FDT available for the SPL framework */
-	spl_image->fdt_addr = (void *)image_info.load_addr;
+	spl_image->fdt_addr = map_sysmem(image_info.load_addr, 0);
 	if (CONFIG_IS_ENABLED(FIT_IMAGE_TINY))
 		return 0;
 
diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c
index d13a524..59f4a84 100644
--- a/common/spl/spl_nand.c
+++ b/common/spl/spl_nand.c
@@ -42,21 +42,33 @@
 static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs,
 			       ulong size, void *dst)
 {
-	ulong sector;
 	int err;
+#ifdef CONFIG_SYS_NAND_BLOCK_SIZE
+	ulong sector;
 
 	sector = *(int *)load->priv;
 	offs = sector + nand_spl_adjust_offset(sector, offs - sector);
+#else
+	offs *= load->bl_len;
+	size *= load->bl_len;
+#endif
 	err = nand_spl_load_image(offs, size, dst);
 	if (err)
 		return 0;
 
-	return size;
+	return size / load->bl_len;
+}
+
+struct mtd_info * __weak nand_get_mtd(void)
+{
+	return NULL;
 }
 
 static int spl_nand_load_element(struct spl_image_info *spl_image,
 				 int offset, struct image_header *header)
 {
+	struct mtd_info *mtd = nand_get_mtd();
+	int bl_len = mtd ? mtd->writesize : 1;
 	int err;
 
 	err = nand_spl_load_image(offset, sizeof(*header), (void *)header);
@@ -71,18 +83,18 @@
 		load.dev = NULL;
 		load.priv = &offset;
 		load.filename = NULL;
-		load.bl_len = 1;
+		load.bl_len = bl_len;
 		load.read = spl_nand_fit_read;
-		return spl_load_simple_fit(spl_image, &load, offset, header);
+		return spl_load_simple_fit(spl_image, &load, offset / bl_len, header);
 	} else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
 		struct spl_load_info load;
 
 		load.dev = NULL;
 		load.priv = NULL;
 		load.filename = NULL;
-		load.bl_len = 1;
+		load.bl_len = bl_len;
 		load.read = spl_nand_fit_read;
-		return spl_load_imx_container(spl_image, &load, offset);
+		return spl_load_imx_container(spl_image, &load, offset / bl_len);
 	} else {
 		err = spl_parse_image_header(spl_image, header);
 		if (err)
diff --git a/common/usb_hub.c b/common/usb_hub.c
index 3d856e7..ba11a18 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -144,7 +144,8 @@
 
 	if (!usb_hub_is_root_hub(dev->dev) && usb_hub_is_superspeed(dev)) {
 		struct usb_port_status *status = (struct usb_port_status *)data;
-		u16 tmp = (status->wPortStatus) & USB_SS_PORT_STAT_MASK;
+		u16 tmp = le16_to_cpu(status->wPortStatus) &
+			USB_SS_PORT_STAT_MASK;
 
 		if (status->wPortStatus & USB_SS_PORT_STAT_POWER)
 			tmp |= USB_PORT_STAT_POWER;
@@ -152,7 +153,7 @@
 		    USB_SS_PORT_STAT_SPEED_5GBPS)
 			tmp |= USB_PORT_STAT_SUPER_SPEED;
 
-		status->wPortStatus = tmp;
+		status->wPortStatus = cpu_to_le16(tmp);
 	}
 #endif
 
diff --git a/configs/MPC8349ITXGP_defconfig b/configs/MPC8349ITXGP_defconfig
index 28e4ebf..92f2093 100644
--- a/configs/MPC8349ITXGP_defconfig
+++ b/configs/MPC8349ITXGP_defconfig
@@ -154,6 +154,7 @@
 CONFIG_BOOTDELAY=6
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=:/nfsroot/rootfs ip=::::mpc8349emitxgp:eth0:off console=ttyS0,115200"
+CONFIG_MISC_INIT_F=y
 CONFIG_MISC_INIT_R=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="MPC8349E-mITX-GP> "
diff --git a/configs/MPC8349ITX_LOWBOOT_defconfig b/configs/MPC8349ITX_LOWBOOT_defconfig
index 46f7afc..cf1e90d 100644
--- a/configs/MPC8349ITX_LOWBOOT_defconfig
+++ b/configs/MPC8349ITX_LOWBOOT_defconfig
@@ -153,6 +153,7 @@
 CONFIG_BOOTDELAY=6
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=:/nfsroot/rootfs ip=::::mpc8349emitx:eth0:off console=ttyS0,115200"
+CONFIG_MISC_INIT_F=y
 CONFIG_MISC_INIT_R=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="MPC8349E-mITX> "
diff --git a/configs/MPC8349ITX_defconfig b/configs/MPC8349ITX_defconfig
index 1f70b75..733e5d3 100644
--- a/configs/MPC8349ITX_defconfig
+++ b/configs/MPC8349ITX_defconfig
@@ -152,6 +152,7 @@
 CONFIG_BOOTDELAY=6
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=:/nfsroot/rootfs ip=::::mpc8349emitx:eth0:off console=ttyS0,115200"
+CONFIG_MISC_INIT_F=y
 CONFIG_MISC_INIT_R=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="MPC8349E-mITX> "
diff --git a/configs/beelink-gtking_defconfig b/configs/beelink-gtking_defconfig
index 6270c23..12caa58 100644
--- a/configs/beelink-gtking_defconfig
+++ b/configs/beelink-gtking_defconfig
@@ -30,9 +30,12 @@
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_MTD=y
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MESON_G12A=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_G12A_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_G12A=y
diff --git a/configs/beelink-gtkingpro_defconfig b/configs/beelink-gtkingpro_defconfig
index 310654e..2b022e4 100644
--- a/configs/beelink-gtkingpro_defconfig
+++ b/configs/beelink-gtkingpro_defconfig
@@ -30,9 +30,12 @@
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_MTD=y
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MESON_G12A=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_G12A_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_G12A=y
diff --git a/configs/bitmain_antminer_s9_defconfig b/configs/bitmain_antminer_s9_defconfig
index f990448..76cccfa 100644
--- a/configs/bitmain_antminer_s9_defconfig
+++ b/configs/bitmain_antminer_s9_defconfig
@@ -19,6 +19,7 @@
 CONFIG_FIT=y
 CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_BOOTDELAY=3
 CONFIG_USE_PREBOOT=y
 # CONFIG_DISPLAY_CPUINFO is not set
@@ -50,6 +51,7 @@
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_FAT=y
 CONFIG_ENV_IS_IN_NAND=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/chromebook_coral_defconfig b/configs/chromebook_coral_defconfig
index 0811ffd..4823913 100644
--- a/configs/chromebook_coral_defconfig
+++ b/configs/chromebook_coral_defconfig
@@ -43,7 +43,7 @@
 CONFIG_HANDOFF=y
 CONFIG_TPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_SEPARATE_BSS=y
-CONFIG_SPL_CPU_SUPPORT=y
+CONFIG_SPL_CPU=y
 CONFIG_SPL_DM_SPI_FLASH=y
 CONFIG_SPL_PCI=y
 # CONFIG_SPL_SPI_FLASH_TINY is not set
@@ -73,6 +73,7 @@
 CONFIG_ISO_PARTITION=y
 CONFIG_EFI_PARTITION=y
 # CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_OF_SPL_REMOVE_PROPS="clocks clock-names interrupt-parent interrupts linux-name acpi,name acpi,path u-boot,acpi-dsdt-order u-boot,acpi-ssdt-order"
 CONFIG_ENV_OVERWRITE=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
diff --git a/configs/chromebook_link64_defconfig b/configs/chromebook_link64_defconfig
index 8f56ee3..872e33d 100644
--- a/configs/chromebook_link64_defconfig
+++ b/configs/chromebook_link64_defconfig
@@ -31,7 +31,7 @@
 CONFIG_LAST_STAGE_INIT=y
 CONFIG_MISC_INIT_R=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_CPU_SUPPORT=y
+CONFIG_SPL_CPU=y
 CONFIG_SPL_ENV_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_DM_SPI_FLASH=y
diff --git a/configs/ds414_defconfig b/configs/ds414_defconfig
index 3e6dcec..e1c0f69 100644
--- a/configs/ds414_defconfig
+++ b/configs/ds414_defconfig
@@ -20,11 +20,11 @@
 CONFIG_DEBUG_UART=y
 CONFIG_BOOTDELAY=3
 CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="console=ttyS0,115200"
-CONFIG_USE_PREBOOT=y
-CONFIG_PREBOOT="usb start; sf probe"
+CONFIG_BOOTARGS="console=ttyS0,115200 ip=off initrd=0x8000040,8M root=/dev/md0 rw syno_hw_version=DS414r1 ihd_num=4 netif_num=2 flash_size=8 SataLedSpecial=1 HddHotplug=1"
+# CONFIG_USE_PREBOOT is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_MISC_INIT_R=y
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_I2C=y
@@ -47,7 +47,6 @@
 CONFIG_USE_ENV_SPI_MAX_HZ=y
 CONFIG_ENV_SPI_MAX_HZ=50000000
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
-CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_OF_TRANSLATE=y
 CONFIG_BLK=y
 # CONFIG_MMC is not set
@@ -65,5 +64,8 @@
 CONFIG_KIRKWOOD_SPI=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_USB_XHCI_HCD=y
+# CONFIG_USB_XHCI_MVEBU is not set
+CONFIG_USB_XHCI_PCI=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
diff --git a/configs/gwventana_emmc_defconfig b/configs/gwventana_emmc_defconfig
index 41e190b..d5270c5 100644
--- a/configs/gwventana_emmc_defconfig
+++ b/configs/gwventana_emmc_defconfig
@@ -18,8 +18,13 @@
 CONFIG_SPL=y
 CONFIG_ENV_OFFSET_REDUND=0xD1400
 CONFIG_CMD_HDMIDETECT=y
+CONFIG_DEFAULT_DEVICE_TREE="imx6q-gw54xx"
+CONFIG_AHCI=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
+# CONFIG_USE_SPL_FIT_GENERATOR is not set
+# CONFIG_LEGACY_IMAGE_FORMAT is not set
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/spl_sd.cfg"
@@ -31,6 +36,7 @@
 CONFIG_MISC_INIT_R=y
 CONFIG_SPL_BOARD_INIT=y
 CONFIG_SPL_STACK_R=y
+CONFIG_SPL_FIT_IMAGE_TINY=y
 CONFIG_SPL_DMA=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
@@ -62,6 +68,9 @@
 CONFIG_MTDIDS_DEFAULT="nand0=nand"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=nand:16m(uboot),1m(env),-(rootfs)"
 CONFIG_CMD_UBI=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_LIST="imx6q-gw51xx imx6dl-gw51xx imx6q-gw52xx imx6dl-gw52xx imx6q-gw53xx imx6dl-gw53xx imx6q-gw54xx imx6dl-gw54xx imx6q-gw551x imx6dl-gw551x imx6q-gw552x imx6dl-gw552x imx6q-gw553x imx6dl-gw553x imx6q-gw560x imx6dl-gw560x imx6q-gw5903 imx6dl-gw5903 imx6q-gw5904 imx6dl-gw5904 imx6q-gw5907 imx6dl-gw5907 imx6q-gw5910 imx6dl-gw5910 imx6q-gw5912 imx6dl-gw5912 imx6q-gw5913 imx6dl-gw5913"
+CONFIG_MULTI_DTB_FIT=y
 CONFIG_ENV_OVERWRITE=y
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
@@ -71,6 +80,7 @@
 CONFIG_DM=y
 CONFIG_BOUNCE_BUFFER=y
 CONFIG_DWC_AHSATA=y
+CONFIG_DM_MMC=y
 CONFIG_SUPPORT_EMMC_RPMB=y
 CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_FSL_USDHC=y
@@ -79,11 +89,20 @@
 CONFIG_E1000=y
 CONFIG_MII=y
 CONFIG_PCI=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_IMX6=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_CONS_INDEX=2
 CONFIG_DM_SERIAL=y
 CONFIG_MXC_UART=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_MXC_SPI=y
 CONFIG_DM_THERMAL=y
 CONFIG_IMX_THERMAL=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
@@ -107,5 +126,4 @@
 CONFIG_SYS_WHITE_ON_BLACK=y
 # CONFIG_PANEL is not set
 CONFIG_VIDEO_IPUV3=y
-CONFIG_OF_LIBFDT=y
 CONFIG_FDT_FIXUP_PARTITIONS=y
diff --git a/configs/gwventana_gw5904_defconfig b/configs/gwventana_gw5904_defconfig
index 66b0441..091bf30 100644
--- a/configs/gwventana_gw5904_defconfig
+++ b/configs/gwventana_gw5904_defconfig
@@ -18,8 +18,13 @@
 CONFIG_SPL=y
 CONFIG_ENV_OFFSET_REDUND=0xD1400
 CONFIG_CMD_HDMIDETECT=y
+CONFIG_DEFAULT_DEVICE_TREE="imx6q-gw54xx"
+CONFIG_AHCI=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
+# CONFIG_USE_SPL_FIT_GENERATOR is not set
+# CONFIG_LEGACY_IMAGE_FORMAT is not set
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/spl_sd.cfg"
@@ -31,6 +36,7 @@
 CONFIG_MISC_INIT_R=y
 CONFIG_SPL_BOARD_INIT=y
 CONFIG_SPL_STACK_R=y
+CONFIG_SPL_FIT_IMAGE_TINY=y
 CONFIG_SPL_DMA=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
@@ -62,6 +68,9 @@
 CONFIG_MTDIDS_DEFAULT="nand0=nand"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=nand:16m(uboot),1m(env),-(rootfs)"
 CONFIG_CMD_UBI=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_LIST="imx6q-gw51xx imx6dl-gw51xx imx6q-gw52xx imx6dl-gw52xx imx6q-gw53xx imx6dl-gw53xx imx6q-gw54xx imx6dl-gw54xx imx6q-gw551x imx6dl-gw551x imx6q-gw552x imx6dl-gw552x imx6q-gw553x imx6dl-gw553x imx6q-gw560x imx6dl-gw560x imx6q-gw5903 imx6dl-gw5903 imx6q-gw5904 imx6dl-gw5904 imx6q-gw5907 imx6dl-gw5907 imx6q-gw5910 imx6dl-gw5910 imx6q-gw5912 imx6dl-gw5912 imx6q-gw5913 imx6dl-gw5913"
+CONFIG_MULTI_DTB_FIT=y
 CONFIG_ENV_OVERWRITE=y
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
@@ -71,6 +80,7 @@
 CONFIG_DM=y
 CONFIG_BOUNCE_BUFFER=y
 CONFIG_DWC_AHSATA=y
+CONFIG_DM_MMC=y
 CONFIG_SUPPORT_EMMC_RPMB=y
 CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_FSL_USDHC=y
@@ -83,11 +93,20 @@
 CONFIG_E1000=y
 CONFIG_MII=y
 CONFIG_PCI=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_IMX6=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_CONS_INDEX=2
 CONFIG_DM_SERIAL=y
 CONFIG_MXC_UART=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_MXC_SPI=y
 CONFIG_DM_THERMAL=y
 CONFIG_IMX_THERMAL=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
@@ -111,5 +130,4 @@
 CONFIG_SYS_WHITE_ON_BLACK=y
 # CONFIG_PANEL is not set
 CONFIG_VIDEO_IPUV3=y
-CONFIG_OF_LIBFDT=y
 CONFIG_FDT_FIXUP_PARTITIONS=y
diff --git a/configs/gwventana_nand_defconfig b/configs/gwventana_nand_defconfig
index 9022f35..0ccd3e9 100644
--- a/configs/gwventana_nand_defconfig
+++ b/configs/gwventana_nand_defconfig
@@ -18,8 +18,13 @@
 CONFIG_SPL=y
 CONFIG_ENV_OFFSET_REDUND=0x1080000
 CONFIG_CMD_HDMIDETECT=y
+CONFIG_DEFAULT_DEVICE_TREE="imx6q-gw54xx"
+CONFIG_AHCI=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
+# CONFIG_USE_SPL_FIT_GENERATOR is not set
+# CONFIG_LEGACY_IMAGE_FORMAT is not set
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/spl_sd.cfg"
@@ -31,6 +36,7 @@
 CONFIG_MISC_INIT_R=y
 CONFIG_SPL_BOARD_INIT=y
 CONFIG_SPL_STACK_R=y
+CONFIG_SPL_FIT_IMAGE_TINY=y
 CONFIG_SPL_DMA=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
@@ -65,6 +71,9 @@
 CONFIG_MTDIDS_DEFAULT="nand0=nand"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=nand:16m(uboot),1m(env),-(rootfs)"
 CONFIG_CMD_UBI=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_LIST="imx6q-gw51xx imx6dl-gw51xx imx6q-gw52xx imx6dl-gw52xx imx6q-gw53xx imx6dl-gw53xx imx6q-gw54xx imx6dl-gw54xx imx6q-gw551x imx6dl-gw551x imx6q-gw552x imx6dl-gw552x imx6q-gw553x imx6dl-gw553x imx6q-gw560x imx6dl-gw560x imx6q-gw5903 imx6dl-gw5903 imx6q-gw5904 imx6dl-gw5904 imx6q-gw5907 imx6dl-gw5907 imx6q-gw5910 imx6dl-gw5910 imx6q-gw5912 imx6dl-gw5912 imx6q-gw5913 imx6dl-gw5913"
+CONFIG_MULTI_DTB_FIT=y
 CONFIG_ENV_OVERWRITE=y
 CONFIG_ENV_IS_IN_NAND=y
 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
@@ -73,21 +82,33 @@
 CONFIG_DM=y
 CONFIG_BOUNCE_BUFFER=y
 CONFIG_DWC_AHSATA=y
+CONFIG_DM_MMC=y
 CONFIG_SUPPORT_EMMC_RPMB=y
 CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_FSL_USDHC=y
 CONFIG_MTD=y
+CONFIG_DM_MTD=y
 CONFIG_MTD_RAW_NAND=y
 CONFIG_NAND_MXS=y
+CONFIG_NAND_MXS_DT=y
 CONFIG_PHYLIB=y
 CONFIG_E1000=y
 CONFIG_MII=y
 CONFIG_PCI=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_IMX6=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_CONS_INDEX=2
 CONFIG_DM_SERIAL=y
 CONFIG_MXC_UART=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_MXC_SPI=y
 CONFIG_DM_THERMAL=y
 CONFIG_IMX_THERMAL=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
@@ -111,5 +132,4 @@
 CONFIG_SYS_WHITE_ON_BLACK=y
 # CONFIG_PANEL is not set
 CONFIG_VIDEO_IPUV3=y
-CONFIG_OF_LIBFDT=y
 CONFIG_FDT_FIXUP_PARTITIONS=y
diff --git a/configs/hihope_rzg2_defconfig b/configs/hihope_rzg2_defconfig
new file mode 100644
index 0000000..69eaab0
--- /dev/null
+++ b/configs/hihope_rzg2_defconfig
@@ -0,0 +1,82 @@
+CONFIG_ARM=y
+CONFIG_ARCH_CPU_INIT=y
+CONFIG_ARCH_RMOBILE=y
+CONFIG_SYS_TEXT_BASE=0x50000000
+CONFIG_ENV_SIZE=0x20000
+CONFIG_ENV_OFFSET=0xFFFE0000
+CONFIG_DM_GPIO=y
+CONFIG_RCAR_GEN3=y
+CONFIG_TARGET_HIHOPE_RZG2=y
+# CONFIG_SPL is not set
+CONFIG_DEFAULT_DEVICE_TREE="r8a774a1-hihope-rzg2m-u-boot"
+CONFIG_FIT=y
+CONFIG_SUPPORT_RAW_INITRD=y
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=192.168.0.1:/export/rfs ip=192.168.0.20"
+CONFIG_DEFAULT_FDT_FILE="r8a774a1-hihope-rzg2m.dtb"
+# CONFIG_BOARD_EARLY_INIT_F is not set
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_LIST="r8a774a1-hihope-rzg2m-u-boot r8a774b1-hihope-rzg2n-u-boot r8a774e1-hihope-rzg2h-u-boot"
+CONFIG_MULTI_DTB_FIT_LZO=y
+CONFIG_MULTI_DTB_FIT_USER_DEFINED_AREA=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_SYS_MMC_ENV_DEV=1
+CONFIG_SYS_MMC_ENV_PART=2
+CONFIG_VERSION_VARIABLE=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CLK=y
+CONFIG_CLK_RENESAS=y
+CONFIG_GPIO_HOG=y
+CONFIG_RCAR_GPIO=y
+CONFIG_DM_PCA953X=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_RCAR_I2C=y
+CONFIG_SYS_I2C_RCAR_IIC=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_IO_VOLTAGE=y
+CONFIG_MMC_UHS_SUPPORT=y
+CONFIG_MMC_HS400_SUPPORT=y
+CONFIG_RENESAS_SDHI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_USE_4K_SECTORS=y
+CONFIG_BITBANGMII=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DM_ETH=y
+CONFIG_RENESAS_RAVB=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_GPIO=y
+CONFIG_SCIF_CONSOLE=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_RENESAS_RPC_SPI=y
+CONFIG_TEE=y
+CONFIG_OPTEE=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_STORAGE=y
+CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/imx8mm_evk_defconfig b/configs/imx8mm_evk_defconfig
index e22b7de..23741a1 100644
--- a/configs/imx8mm_evk_defconfig
+++ b/configs/imx8mm_evk_defconfig
@@ -21,9 +21,9 @@
 CONFIG_FIT=y
 CONFIG_FIT_EXTERNAL_OFFSET=0x3000
 CONFIG_SPL_LOAD_FIT=y
-CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-imx/mkimage_fit_atf.sh"
+# CONFIG_USE_SPL_FIT_GENERATOR is not set
 CONFIG_OF_SYSTEM_SETUP=y
-CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/imx8m/imximage-8mm-lpddr4.cfg"
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/imx8mm_evk/imximage-8mm-lpddr4.cfg"
 CONFIG_BOARD_LATE_INIT=y
 CONFIG_SPL_BOARD_INIT=y
 CONFIG_SPL_SEPARATE_BSS=y
@@ -83,7 +83,7 @@
 CONFIG_SPL_PINCTRL=y
 CONFIG_PINCTRL_IMX8M=y
 CONFIG_DM_PMIC=y
-CONFIG_SPL_DM_PMIC_BD71837=y
+CONFIG_SPL_DM_PMIC_PCA9450=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
 CONFIG_DM_REGULATOR_GPIO=y
diff --git a/configs/imx8mn_beacon_defconfig b/configs/imx8mn_beacon_defconfig
index d6a3385..567a6e5 100644
--- a/configs/imx8mn_beacon_defconfig
+++ b/configs/imx8mn_beacon_defconfig
@@ -49,6 +49,7 @@
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_PART=y
+CONFIG_CMD_SPI=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
@@ -90,11 +91,14 @@
 CONFIG_MMC_HS400_ES_SUPPORT=y
 CONFIG_MMC_HS400_SUPPORT=y
 CONFIG_FSL_USDHC=y
+CONFIG_MTD=y
+CONFIG_DM_MTD=y
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SF_DEFAULT_MODE=0
 CONFIG_SF_DEFAULT_SPEED=40000000
 CONFIG_SPI_FLASH_BAR=y
 CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_MTD=y
 CONFIG_PHYLIB=y
 CONFIG_PHY_ATHEROS=y
 CONFIG_DM_ETH=y
@@ -116,6 +120,7 @@
 CONFIG_MXC_UART=y
 CONFIG_SPI=y
 CONFIG_DM_SPI=y
+CONFIG_NXP_FSPI=y
 CONFIG_SYSRESET=y
 CONFIG_SYSRESET_PSCI=y
 CONFIG_DM_THERMAL=y
diff --git a/configs/imx8mn_ddr4_evk_defconfig b/configs/imx8mn_ddr4_evk_defconfig
index 2c12bda..b10cd13 100644
--- a/configs/imx8mn_ddr4_evk_defconfig
+++ b/configs/imx8mn_ddr4_evk_defconfig
@@ -22,9 +22,9 @@
 CONFIG_FIT=y
 CONFIG_FIT_EXTERNAL_OFFSET=0x3000
 CONFIG_SPL_LOAD_FIT=y
-CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-imx/mkimage_fit_atf.sh"
+# CONFIG_USE_SPL_FIT_GENERATOR is not set
 CONFIG_OF_SYSTEM_SETUP=y
-CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/imx8m/imximage-8mn-ddr4.cfg"
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/imx8mn_evk/imximage-8mn-ddr4.cfg"
 CONFIG_DEFAULT_FDT_FILE="imx8mn-ddr4-evk.dtb"
 CONFIG_BOARD_LATE_INIT=y
 CONFIG_SPL_BOARD_INIT=y
diff --git a/configs/imx8mn_evk_defconfig b/configs/imx8mn_evk_defconfig
new file mode 100644
index 0000000..d0e5b58
--- /dev/null
+++ b/configs/imx8mn_evk_defconfig
@@ -0,0 +1,93 @@
+CONFIG_ARM=y
+CONFIG_SPL_SYS_ICACHE_OFF=y
+CONFIG_SPL_SYS_DCACHE_OFF=y
+CONFIG_ARCH_IMX8M=y
+CONFIG_SYS_TEXT_BASE=0x40200000
+CONFIG_SPL_GPIO_SUPPORT=y
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x10000
+CONFIG_ENV_SECT_SIZE=0x10000
+CONFIG_ENV_SIZE=0x1000
+CONFIG_ENV_OFFSET=0x400000
+CONFIG_SYS_I2C_MXC_I2C1=y
+CONFIG_SYS_I2C_MXC_I2C2=y
+CONFIG_SYS_I2C_MXC_I2C3=y
+CONFIG_DM_GPIO=y
+CONFIG_SPL_TEXT_BASE=0x912000
+CONFIG_TARGET_IMX8MN_EVK=y
+CONFIG_ARCH_MISC_INIT=y
+CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_SPL=y
+CONFIG_SPL_IMX_ROMAPI_LOADADDR=0x48000000
+CONFIG_DEFAULT_DEVICE_TREE="imx8mn-evk"
+CONFIG_FIT=y
+CONFIG_FIT_EXTERNAL_OFFSET=0x3000
+CONFIG_SPL_LOAD_FIT=y
+# CONFIG_USE_SPL_FIT_GENERATOR is not set
+CONFIG_OF_SYSTEM_SETUP=y
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/imx8mn_evk/imximage-8mn-ddr4.cfg"
+CONFIG_DEFAULT_FDT_FILE="imx8mn-evk.dtb"
+CONFIG_BOARD_LATE_INIT=y
+CONFIG_SPL_BOARD_INIT=y
+CONFIG_SPL_BOOTROM_SUPPORT=y
+CONFIG_SPL_SEPARATE_BSS=y
+CONFIG_SPL_I2C_SUPPORT=y
+CONFIG_SPL_WATCHDOG_SUPPORT=y
+CONFIG_SPL_POWER_SUPPORT=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="u-boot=> "
+# CONFIG_CMD_EXPORTENV is not set
+# CONFIG_CMD_IMPORTENV is not set
+CONFIG_CMD_ERASEENV=y
+# CONFIG_CMD_CRC32 is not set
+CONFIG_CMD_CLK=y
+CONFIG_CMD_FUSE=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_CLK_COMPOSITE_CCF=y
+CONFIG_CLK_COMPOSITE_CCF=y
+CONFIG_SPL_CLK_IMX8MN=y
+CONFIG_CLK_IMX8MN=y
+CONFIG_MXC_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_MXC=y
+CONFIG_DM_MMC=y
+CONFIG_SUPPORT_EMMC_BOOT=y
+CONFIG_MMC_IO_VOLTAGE=y
+CONFIG_MMC_UHS_SUPPORT=y
+CONFIG_MMC_HS400_ES_SUPPORT=y
+CONFIG_MMC_HS400_SUPPORT=y
+CONFIG_FSL_ESDHC_IMX=y
+CONFIG_PHYLIB=y
+CONFIG_DM_ETH=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_PINCTRL_IMX8M=y
+CONFIG_DM_PMIC=y
+CONFIG_SPL_DM_PMIC_PCA9450=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_GPIO=y
+CONFIG_MXC_UART=y
+CONFIG_SYSRESET=y
+CONFIG_SPL_SYSRESET=y
+CONFIG_SYSRESET_PSCI=y
+CONFIG_SYSRESET_WATCHDOG=y
+CONFIG_DM_THERMAL=y
+CONFIG_IMX_WATCHDOG=y
diff --git a/configs/imx8mp_evk_defconfig b/configs/imx8mp_evk_defconfig
index 47a52ee..089ec26 100644
--- a/configs/imx8mp_evk_defconfig
+++ b/configs/imx8mp_evk_defconfig
@@ -22,9 +22,9 @@
 CONFIG_FIT=y
 CONFIG_FIT_EXTERNAL_OFFSET=0x3000
 CONFIG_SPL_LOAD_FIT=y
-CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-imx/mkimage_fit_atf.sh"
+# CONFIG_USE_SPL_FIT_GENERATOR is not set
 CONFIG_OF_SYSTEM_SETUP=y
-CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/imx8m/imximage-8mp-lpddr4.cfg"
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/imx8mp_evk/imximage-8mp-lpddr4.cfg"
 CONFIG_DEFAULT_FDT_FILE="imx8mp-evk.dtb"
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_BOARD_LATE_INIT=y
diff --git a/configs/khadas-vim2_defconfig b/configs/khadas-vim2_defconfig
index c26c0ca..0aaa6c0 100644
--- a/configs/khadas-vim2_defconfig
+++ b/configs/khadas-vim2_defconfig
@@ -36,9 +36,12 @@
 CONFIG_DM_MTD=y
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MMIOREG=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXL=y
diff --git a/configs/khadas-vim3_defconfig b/configs/khadas-vim3_defconfig
index bc17430..cd0327c 100644
--- a/configs/khadas-vim3_defconfig
+++ b/configs/khadas-vim3_defconfig
@@ -41,9 +41,12 @@
 CONFIG_DM_MTD=y
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MESON_G12A=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_G12A_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_G12A=y
diff --git a/configs/khadas-vim3l_defconfig b/configs/khadas-vim3l_defconfig
index c187792..ef85f00 100644
--- a/configs/khadas-vim3l_defconfig
+++ b/configs/khadas-vim3l_defconfig
@@ -41,9 +41,12 @@
 CONFIG_DM_MTD=y
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MESON_G12A=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_G12A_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_G12A=y
diff --git a/configs/khadas-vim_defconfig b/configs/khadas-vim_defconfig
index e7e5c42..60cdfff 100644
--- a/configs/khadas-vim_defconfig
+++ b/configs/khadas-vim_defconfig
@@ -30,11 +30,12 @@
 CONFIG_SARADC_MESON=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
-CONFIG_PHY_ADDR_ENABLE=y
-CONFIG_PHY_ADDR=8
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MMIOREG=y
 CONFIG_PHY_MESON_GXL=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXL=y
diff --git a/configs/kmcoge4_defconfig b/configs/kmcoge4_defconfig
index ddc8f8a..462e567 100644
--- a/configs/kmcoge4_defconfig
+++ b/configs/kmcoge4_defconfig
@@ -20,6 +20,7 @@
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_LAST_STAGE_INIT=y
+CONFIG_MISC_INIT_F=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_ASKENV=y
 CONFIG_CMD_GREPENV=y
diff --git a/configs/kontron_sl28_defconfig b/configs/kontron_sl28_defconfig
index 0c6c191..1c781e0 100644
--- a/configs/kontron_sl28_defconfig
+++ b/configs/kontron_sl28_defconfig
@@ -70,7 +70,7 @@
 CONFIG_I2C_DEFAULT_BUS_NUMBER=0
 CONFIG_I2C_MUX=y
 CONFIG_DM_MMC=y
-CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_MMC_HS400_SUPPORT=y
 CONFIG_FSL_ESDHC=y
 CONFIG_FSL_ESDHC_SUPPORT_ADMA2=y
 CONFIG_DM_SPI_FLASH=y
diff --git a/configs/libretech-ac_defconfig b/configs/libretech-ac_defconfig
index ca61591..b383dfb 100644
--- a/configs/libretech-ac_defconfig
+++ b/configs/libretech-ac_defconfig
@@ -37,16 +37,17 @@
 CONFIG_SARADC_MESON=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MMIOREG=y
 CONFIG_MTD=y
 CONFIG_DM_MTD=y
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH_GIGADEVICE=y
 CONFIG_SPI_FLASH_SPANSION=y
-CONFIG_PHY_ADDR_ENABLE=y
-CONFIG_PHY_ADDR=8
 CONFIG_PHY_MESON_GXL=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXL=y
diff --git a/configs/libretech-cc_defconfig b/configs/libretech-cc_defconfig
index fb4bf4c..ba59dee 100644
--- a/configs/libretech-cc_defconfig
+++ b/configs/libretech-cc_defconfig
@@ -29,11 +29,12 @@
 CONFIG_SARADC_MESON=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
-CONFIG_PHY_ADDR_ENABLE=y
-CONFIG_PHY_ADDR=8
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MMIOREG=y
 CONFIG_PHY_MESON_GXL=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXL=y
diff --git a/configs/libretech-cc_v2_defconfig b/configs/libretech-cc_v2_defconfig
index 86f88db..50ae3e1 100644
--- a/configs/libretech-cc_v2_defconfig
+++ b/configs/libretech-cc_v2_defconfig
@@ -37,11 +37,12 @@
 CONFIG_DM_MTD=y
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH_GIGADEVICE=y
-CONFIG_PHY_ADDR_ENABLE=y
-CONFIG_PHY_ADDR=8
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MMIOREG=y
 CONFIG_PHY_MESON_GXL=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_PHY=y
 CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_PINCTRL=y
diff --git a/configs/libretech-s905d-pc_defconfig b/configs/libretech-s905d-pc_defconfig
index 85dfd9c..9ef6385 100644
--- a/configs/libretech-s905d-pc_defconfig
+++ b/configs/libretech-s905d-pc_defconfig
@@ -38,9 +38,12 @@
 CONFIG_MTD=y
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MMIOREG=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXL=y
diff --git a/configs/libretech-s912-pc_defconfig b/configs/libretech-s912-pc_defconfig
index a515833..a14ac20 100644
--- a/configs/libretech-s912-pc_defconfig
+++ b/configs/libretech-s912-pc_defconfig
@@ -37,9 +37,12 @@
 CONFIG_MTD=y
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MMIOREG=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXL=y
diff --git a/configs/lion-rk3368_defconfig b/configs/lion-rk3368_defconfig
index 583dd44..6d6b73d 100644
--- a/configs/lion-rk3368_defconfig
+++ b/configs/lion-rk3368_defconfig
@@ -9,7 +9,7 @@
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
 CONFIG_TPL_LIBGENERIC_SUPPORT=y
 CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x600000
+CONFIG_TARGET_LION_RK3368=y
 CONFIG_SPL=y
 CONFIG_DEBUG_UART_BASE=0xFF180000
 CONFIG_DEBUG_UART_CLOCK=24000000
@@ -33,18 +33,22 @@
 # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
 CONFIG_TPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x4000
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x200
 CONFIG_SPL_ATF=y
 CONFIG_TPL=y
 CONFIG_TPL_DRIVERS_MISC_SUPPORT=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
 CONFIG_CMD_BOOTSTAGE=y
 CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_MTDPARTS=y
 CONFIG_SPL_OF_CONTROL=y
 CONFIG_TPL_OF_CONTROL=y
 CONFIG_OF_LIVE=y
+CONFIG_DEFAULT_DEVICE_TREE="rk3368-lion-haikou"
 CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names interrupt-parent"
 CONFIG_TPL_OF_PLATDATA=y
 CONFIG_ENV_IS_IN_MMC=y
@@ -61,14 +65,15 @@
 CONFIG_SPL_CLK=y
 CONFIG_TPL_CLK=y
 CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MTD=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_WINBOND=y
-CONFIG_PHY_MICREL=y
-CONFIG_PHY_MICREL_KSZ90X1=y
+CONFIG_PHY_MSCC=y
 CONFIG_DM_ETH=y
+CONFIG_DM_ETH_PHY=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_RGMII=y
 CONFIG_GMAC_ROCKCHIP=y
@@ -77,6 +82,7 @@
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_RK8XX=y
 CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_REGULATOR_RK8XX=y
 CONFIG_RAM=y
 CONFIG_SPL_RAM=y
 CONFIG_TPL_RAM=y
@@ -87,6 +93,13 @@
 CONFIG_SYSINFO=y
 CONFIG_SYSINFO_SMBIOS=y
 CONFIG_SYSRESET=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_DWC2=y
+CONFIG_ROCKCHIP_USB2_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_SPL_TINY_MEMSET=y
 CONFIG_LZO=y
 CONFIG_ERRNO_STR=y
diff --git a/configs/marsboard_defconfig b/configs/marsboard_defconfig
index d2bd9c4..551d09b 100644
--- a/configs/marsboard_defconfig
+++ b/configs/marsboard_defconfig
@@ -2,11 +2,13 @@
 CONFIG_ARCH_MX6=y
 CONFIG_SYS_TEXT_BASE=0x17800000
 CONFIG_NR_DRAM_BANKS=1
+CONFIG_DEFAULT_DEVICE_TREE="imx6q-marsboard"
 CONFIG_ENV_SIZE=0x2000
 CONFIG_ENV_OFFSET=0xC0000
 CONFIG_ENV_SECT_SIZE=0x2000
 CONFIG_MX6Q=y
 CONFIG_TARGET_EMBESTMX6BOARDS=y
+CONFIG_OF_CONTROL=y
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6q.cfg,DDR_MB=1024"
 CONFIG_BOOTCOMMAND="run finduuid; run distro_bootcmd"
@@ -17,6 +19,7 @@
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
+# CONFIG_CMD_PINMUX is not set
 CONFIG_CMD_SF=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_CACHE=y
@@ -25,21 +28,30 @@
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_DM=y
+CONFIG_DM_GPIO=y
 CONFIG_BOUNCE_BUFFER=y
+CONFIG_DM_MMC=y
 CONFIG_FSL_USDHC=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_IMX6=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SF_DEFAULT_MODE=0
 CONFIG_SF_DEFAULT_SPEED=20000000
 CONFIG_SPI_FLASH_SST=y
 CONFIG_PHYLIB=y
 CONFIG_PHY_ATHEROS=y
+CONFIG_DM_ETH=y
+CONFIG_FEC_MXC=y
 CONFIG_MII=y
 CONFIG_MXC_UART=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_MXC_SPI=y
 CONFIG_DM_THERMAL=y
 CONFIG_IMX_THERMAL=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_DM_VIDEO=y
diff --git a/configs/microchip_mpfs_icicle_defconfig b/configs/microchip_mpfs_icicle_defconfig
index 0c15c3b..1cb2920 100644
--- a/configs/microchip_mpfs_icicle_defconfig
+++ b/configs/microchip_mpfs_icicle_defconfig
@@ -1,4 +1,5 @@
 CONFIG_RISCV=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ENV_SIZE=0x2000
 CONFIG_DEFAULT_DEVICE_TREE="microchip-mpfs-icicle-kit"
 CONFIG_TARGET_MICROCHIP_ICICLE=y
diff --git a/configs/mt7622_rfb_defconfig b/configs/mt7622_rfb_defconfig
index fa427d8..c12ce5c 100644
--- a/configs/mt7622_rfb_defconfig
+++ b/configs/mt7622_rfb_defconfig
@@ -4,7 +4,10 @@
 CONFIG_SYS_TEXT_BASE=0x41e00000
 CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_NR_DRAM_BANKS=1
+CONFIG_DEBUG_UART_BASE=0x11002000
+CONFIG_DEBUG_UART_CLOCK=25000000
 CONFIG_DEFAULT_DEVICE_TREE="mt7622-rfb"
+CONFIG_DEBUG_UART=y
 CONFIG_FIT=y
 CONFIG_DEFAULT_FDT_FILE="mt7622-rfb"
 CONFIG_LOGLEVEL=7
@@ -51,8 +54,6 @@
 CONFIG_DM_SPI=y
 CONFIG_MTK_SNOR=y
 CONFIG_SYSRESET_WATCHDOG=y
-CONFIG_TIMER=y
-CONFIG_MTK_TIMER=y
 CONFIG_WDT_MTK=y
 CONFIG_LZO=y
 CONFIG_HEXDUMP=y
diff --git a/configs/mt7629_rfb_defconfig b/configs/mt7629_rfb_defconfig
index 2e94f97..cd9f7aa 100644
--- a/configs/mt7629_rfb_defconfig
+++ b/configs/mt7629_rfb_defconfig
@@ -10,7 +10,11 @@
 CONFIG_TARGET_MT7629=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_SPL_STACK_R_ADDR=0x40800000
+CONFIG_SPL_PAYLOAD="u-boot-lzma.img"
+CONFIG_BUILD_TARGET="u-boot-mtk.bin"
 CONFIG_DEFAULT_DEVICE_TREE="mt7629-rfb"
+CONFIG_SPL_IMAGE="spl/u-boot-spl-mtk.bin"
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_BOOTDELAY=3
@@ -18,6 +22,7 @@
 CONFIG_SYS_CONSOLE_IS_IN_ENV=y
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
+CONFIG_SPL_STACK_R=y
 CONFIG_SPL_NOR_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
 CONFIG_HUSH_PARSER=y
@@ -87,4 +92,5 @@
 CONFIG_USB_KEYBOARD=y
 CONFIG_WDT_MTK=y
 CONFIG_LZMA=y
+CONFIG_SPL_LZMA=y
 # CONFIG_EFI_LOADER is not set
diff --git a/configs/mt8183_pumpkin_defconfig b/configs/mt8183_pumpkin_defconfig
new file mode 100644
index 0000000..b0bdcb3
--- /dev/null
+++ b/configs/mt8183_pumpkin_defconfig
@@ -0,0 +1,81 @@
+CONFIG_ARM=y
+CONFIG_POSITION_INDEPENDENT=y
+CONFIG_ARCH_MEDIATEK=y
+CONFIG_SYS_TEXT_BASE=0x4c000000
+CONFIG_SYS_MALLOC_F_LEN=0x4000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_ENV_SIZE=0x1000
+CONFIG_ENV_OFFSET=0x0
+CONFIG_DM_GPIO=y
+CONFIG_TARGET_MT8183=y
+CONFIG_DEBUG_UART_BASE=0x11002000
+CONFIG_DEBUG_UART_CLOCK=26000000
+# CONFIG_PSCI_RESET is not set
+CONFIG_DEFAULT_DEVICE_TREE="mt8183-pumpkin"
+CONFIG_DEBUG_UART=y
+# CONFIG_ANDROID_BOOT_IMAGE is not set
+CONFIG_FIT=y
+# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
+CONFIG_DEFAULT_FDT_FILE="mt8183-pumpkin"
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_HUSH_PARSER=y
+# CONFIG_CMD_BDI is not set
+# CONFIG_CMD_CONSOLE is not set
+# CONFIG_CMD_BOOTD is not set
+# CONFIG_CMD_BOOTI is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_GO is not set
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_EXPORTENV is not set
+# CONFIG_CMD_IMPORTENV is not set
+# CONFIG_CMD_EDITENV is not set
+# CONFIG_CMD_CRC32 is not set
+# CONFIG_CMD_MEMORY is not set
+CONFIG_CMD_CLK=y
+CONFIG_CMD_GPT=y
+# CONFIG_RANDOM_UUID is not set
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PART=y
+# CONFIG_CMD_ITEST is not set
+# CONFIG_CMD_SETEXPR is not set
+# CONFIG_CMD_BLOCK_CACHE is not set
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_SYS_MMC_ENV_PART=2
+CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DEVRES=y
+CONFIG_CLK=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x4d000000
+CONFIG_FASTBOOT_BUF_SIZE=0x8000000
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=0
+CONFIG_FASTBOOT_MMC_BOOT1_SUPPORT=y
+# CONFIG_INPUT is not set
+CONFIG_DM_MMC=y
+# CONFIG_MMC_QUIRKS is not set
+CONFIG_MMC_MTK=y
+CONFIG_DM_ETH=y
+CONFIG_PHY=y
+CONFIG_PHY_MTK_TPHY=y
+CONFIG_BAUDRATE=921600
+CONFIG_DM_SERIAL=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_MTK_SERIAL=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_DM_USB_GADGET=y
+CONFIG_USB_MTU3=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VENDOR_NUM=0x0e8d
+CONFIG_USB_GADGET_PRODUCT_NUM=0x201c
+CONFIG_USB_ETHER=y
+CONFIG_WDT=y
+CONFIG_WDT_MTK=y
+# CONFIG_REGEX is not set
+CONFIG_OF_LIBFDT_OVERLAY=y
+# CONFIG_EFI_LOADER is not set
diff --git a/configs/pumpkin_defconfig b/configs/mt8516_pumpkin_defconfig
similarity index 100%
rename from configs/pumpkin_defconfig
rename to configs/mt8516_pumpkin_defconfig
diff --git a/configs/mvebu_espressobin-88f3720_defconfig b/configs/mvebu_espressobin-88f3720_defconfig
index 212bc00..dd586c3 100644
--- a/configs/mvebu_espressobin-88f3720_defconfig
+++ b/configs/mvebu_espressobin-88f3720_defconfig
@@ -32,6 +32,7 @@
 CONFIG_CMD_PCI=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_WDT=y
 CONFIG_CMD_TFTPPUT=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
@@ -88,4 +89,7 @@
 CONFIG_USB_ETHER_MCS7830=y
 CONFIG_USB_ETHER_RTL8152=y
 CONFIG_USB_ETHER_SMSC95XX=y
+# CONFIG_WATCHDOG_AUTOSTART is not set
+CONFIG_WDT=y
+CONFIG_WDT_ARMADA_37XX=y
 CONFIG_SHA1=y
diff --git a/configs/mx23_olinuxino_defconfig b/configs/mx23_olinuxino_defconfig
index 0da54c9..680611c 100644
--- a/configs/mx23_olinuxino_defconfig
+++ b/configs/mx23_olinuxino_defconfig
@@ -11,6 +11,8 @@
 CONFIG_TARGET_MX23_OLINUXINO=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL=y
+CONFIG_DEFAULT_DEVICE_TREE="imx23-olinuxino"
+# CONFIG_SYS_MALLOC_F is not set
 CONFIG_BOOTDELAY=3
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_ARCH_MISC_INIT=y
@@ -24,10 +26,12 @@
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_EXT2=y
 CONFIG_CMD_FAT=y
+CONFIG_OF_CONTROL=y
 CONFIG_ENV_OVERWRITE=y
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_VERSION_VARIABLE=y
+CONFIG_DM=y
 CONFIG_MXS_GPIO=y
 CONFIG_LED_STATUS=y
 CONFIG_LED_STATUS_GPIO=y
@@ -37,11 +41,10 @@
 CONFIG_LED_STATUS_BOOT_ENABLE=y
 CONFIG_LED_STATUS_BOOT=0
 CONFIG_LED_STATUS_CMD=y
+CONFIG_DM_MMC=y
 CONFIG_MMC_MXS=y
 CONFIG_CONS_INDEX=0
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_STORAGE=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_SMSC95XX=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/nanopi-k2_defconfig b/configs/nanopi-k2_defconfig
index c2dc488..4332271 100644
--- a/configs/nanopi-k2_defconfig
+++ b/configs/nanopi-k2_defconfig
@@ -29,7 +29,7 @@
 CONFIG_MMC_MESON_GX=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXBB=y
 CONFIG_DM_REGULATOR=y
diff --git a/configs/nanopi-m4b-rk3399_defconfig b/configs/nanopi-m4b-rk3399_defconfig
new file mode 100644
index 0000000..eceb67e
--- /dev/null
+++ b/configs/nanopi-m4b-rk3399_defconfig
@@ -0,0 +1,61 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_TEXT_BASE=0x00200000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_ENV_OFFSET=0x3F8000
+CONFIG_ROCKCHIP_RK3399=y
+CONFIG_TARGET_EVB_RK3399=y
+CONFIG_DEBUG_UART_BASE=0xFF1A0000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEFAULT_DEVICE_TREE="rk3399-nanopi-m4b"
+CONFIG_DEBUG_UART=y
+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-nanopi-m4b.dtb"
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000
+CONFIG_TPL=y
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TIME=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PMIC_RK8XX=y
+CONFIG_REGULATOR_PWM=y
+CONFIG_REGULATOR_RK8XX=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_BAUDRATE=1500000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYSRESET=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_KEYBOARD=y
+CONFIG_USB_HOST_ETHER=y
+CONFIG_USB_ETHER_ASIX=y
+CONFIG_USB_ETHER_ASIX88179=y
+CONFIG_USB_ETHER_MCS7830=y
+CONFIG_USB_ETHER_RTL8152=y
+CONFIG_USB_ETHER_SMSC95XX=y
+CONFIG_DM_VIDEO=y
+CONFIG_DISPLAY=y
+CONFIG_VIDEO_ROCKCHIP=y
+CONFIG_DISPLAY_ROCKCHIP_HDMI=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_ERRNO_STR=y
diff --git a/configs/nanopi-r4s-rk3399_defconfig b/configs/nanopi-r4s-rk3399_defconfig
new file mode 100644
index 0000000..0a3c28b
--- /dev/null
+++ b/configs/nanopi-r4s-rk3399_defconfig
@@ -0,0 +1,62 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_TEXT_BASE=0x00200000
+CONFIG_ENV_OFFSET=0x3F8000
+CONFIG_ROCKCHIP_RK3399=y
+CONFIG_TARGET_EVB_RK3399=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_DEBUG_UART_BASE=0xFF1A0000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART=y
+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-nanopi-r4s.dtb"
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000
+CONFIG_TPL=y
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TIME=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_DEFAULT_DEVICE_TREE="rk3399-nanopi-r4s"
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PMIC_RK8XX=y
+CONFIG_REGULATOR_PWM=y
+CONFIG_REGULATOR_RK8XX=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM_RK3399_LPDDR4=y
+CONFIG_BAUDRATE=1500000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYSRESET=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_KEYBOARD=y
+CONFIG_USB_HOST_ETHER=y
+CONFIG_USB_ETHER_ASIX=y
+CONFIG_USB_ETHER_ASIX88179=y
+CONFIG_USB_ETHER_MCS7830=y
+CONFIG_USB_ETHER_RTL8152=y
+CONFIG_USB_ETHER_SMSC95XX=y
+CONFIG_DM_VIDEO=y
+CONFIG_DISPLAY=y
+CONFIG_VIDEO_ROCKCHIP=y
+CONFIG_DISPLAY_ROCKCHIP_HDMI=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_ERRNO_STR=y
diff --git a/configs/odroid-c2_defconfig b/configs/odroid-c2_defconfig
index 5c02fa1..7ce65b1 100644
--- a/configs/odroid-c2_defconfig
+++ b/configs/odroid-c2_defconfig
@@ -32,7 +32,7 @@
 CONFIG_MMC_MESON_GX=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_PHY=y
 CONFIG_MESON_GXBB_USB_PHY=y
 CONFIG_PINCTRL=y
diff --git a/configs/odroid-c4_defconfig b/configs/odroid-c4_defconfig
index 8a9b8b0..48fb891 100644
--- a/configs/odroid-c4_defconfig
+++ b/configs/odroid-c4_defconfig
@@ -30,9 +30,12 @@
 CONFIG_SARADC_MESON=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MESON_G12A=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_G12A_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_G12A=y
diff --git a/configs/odroid-go2_defconfig b/configs/odroid-go2_defconfig
index 8538909..6aa41e3 100644
--- a/configs/odroid-go2_defconfig
+++ b/configs/odroid-go2_defconfig
@@ -24,7 +24,7 @@
 CONFIG_FIT_VERBOSE=y
 CONFIG_FIT_BEST_MATCH=y
 CONFIG_SPL_LOAD_FIT=y
-CONFIG_DEFAULT_FDT_FILE="rk3326-odroidgo2.dtb"
+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3326-odroid-go2.dtb"
 # CONFIG_CONSOLE_MUX is not set
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_DISPLAY_BOARDINFO_LATE=y
@@ -33,7 +33,6 @@
 # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
 CONFIG_SPL_STACK_R=y
 # CONFIG_TPL_BANNER_PRINT is not set
-CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x200
 CONFIG_SPL_CRC32_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_POWER_SUPPORT=y
@@ -110,4 +109,3 @@
 CONFIG_TPL_TINY_MEMSET=y
 CONFIG_LZO=y
 CONFIG_ERRNO_STR=y
-# CONFIG_EFI_LOADER is not set
diff --git a/configs/odroid-n2_defconfig b/configs/odroid-n2_defconfig
index b82bd78..d2a8c34 100644
--- a/configs/odroid-n2_defconfig
+++ b/configs/odroid-n2_defconfig
@@ -30,9 +30,12 @@
 CONFIG_SARADC_MESON=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MESON_G12A=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_G12A_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_G12A=y
diff --git a/configs/p200_defconfig b/configs/p200_defconfig
index 6efc7bc..c61e974 100644
--- a/configs/p200_defconfig
+++ b/configs/p200_defconfig
@@ -28,7 +28,7 @@
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXBB=y
 CONFIG_DM_REGULATOR=y
diff --git a/configs/p201_defconfig b/configs/p201_defconfig
index a1d3f04..34dc154 100644
--- a/configs/p201_defconfig
+++ b/configs/p201_defconfig
@@ -29,7 +29,7 @@
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXBB=y
 CONFIG_DM_REGULATOR=y
diff --git a/configs/p212_defconfig b/configs/p212_defconfig
index da66c50..c36a674 100644
--- a/configs/p212_defconfig
+++ b/configs/p212_defconfig
@@ -27,11 +27,12 @@
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
-CONFIG_PHY_ADDR_ENABLE=y
-CONFIG_PHY_ADDR=8
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MMIOREG=y
 CONFIG_PHY_MESON_GXL=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXL=y
diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig
index 99a489c..4815d8a 100644
--- a/configs/qemu-x86_64_defconfig
+++ b/configs/qemu-x86_64_defconfig
@@ -31,7 +31,7 @@
 CONFIG_LAST_STAGE_INIT=y
 CONFIG_PCI_INIT_R=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_CPU_SUPPORT=y
+CONFIG_SPL_CPU=y
 CONFIG_SPL_ENV_SUPPORT=y
 CONFIG_SPL_DM_SPI_FLASH=y
 CONFIG_SPL_NET_SUPPORT=y
diff --git a/configs/riotboard_defconfig b/configs/riotboard_defconfig
index b652057..d41b4ba 100644
--- a/configs/riotboard_defconfig
+++ b/configs/riotboard_defconfig
@@ -1,21 +1,35 @@
 CONFIG_ARM=y
 CONFIG_ARCH_MX6=y
 CONFIG_SYS_TEXT_BASE=0x17800000
+CONFIG_SPL_GPIO_SUPPORT=y
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_NR_DRAM_BANKS=1
+CONFIG_DEFAULT_DEVICE_TREE="imx6dl-riotboard"
 CONFIG_ENV_SIZE=0x2000
 CONFIG_ENV_OFFSET=0x60000
 CONFIG_MX6S=y
 CONFIG_TARGET_EMBESTMX6BOARDS=y
+CONFIG_OF_CONTROL=y
+CONFIG_SPL_TEXT_BASE=0x00908000
+CONFIG_SPL_MMC_SUPPORT=y
+CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_SPL=y
+CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_DISTRO_DEFAULTS=y
-CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6s1g.cfg,DDR_MB=1024"
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6s1g.cfg,SPL,DDR_MB=1024"
 CONFIG_BOOTCOMMAND="run finduuid; run distro_bootcmd"
 # CONFIG_CONSOLE_MUX is not set
 CONFIG_SYS_CONSOLE_IS_IN_ENV=y
 CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE=y
 CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SPL_RAW_IMAGE_SUPPORT=y
+CONFIG_SPL_FS_EXT4=y
+CONFIG_SPL_OS_BOOT=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
+# CONFIG_CMD_PINMUX is not set
 CONFIG_CMD_SF=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_CACHE=y
@@ -25,22 +39,31 @@
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SYS_MMC_ENV_DEV=2
 CONFIG_DM=y
+CONFIG_DM_GPIO=y
 CONFIG_BOUNCE_BUFFER=y
 CONFIG_SUPPORT_EMMC_BOOT=y
+CONFIG_DM_MMC=y
 CONFIG_FSL_USDHC=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_IMX6=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SF_DEFAULT_MODE=0
 CONFIG_SF_DEFAULT_SPEED=20000000
 CONFIG_SPI_FLASH_SST=y
 CONFIG_PHYLIB=y
 CONFIG_PHY_ATHEROS=y
+CONFIG_DM_ETH=y
+CONFIG_FEC_MXC=y
 CONFIG_MII=y
 CONFIG_MXC_UART=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_MXC_SPI=y
 CONFIG_DM_THERMAL=y
 CONFIG_IMX_THERMAL=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_DM_VIDEO=y
@@ -57,3 +80,4 @@
 CONFIG_VIDEO_BMP_RLE8=y
 CONFIG_BMP_16BPP=y
 CONFIG_OF_LIBFDT=y
+CONFIG_SPL_OF_LIBFDT=y
diff --git a/configs/riotboard_spl_defconfig b/configs/riotboard_spl_defconfig
deleted file mode 100644
index 95549ff..0000000
--- a/configs/riotboard_spl_defconfig
+++ /dev/null
@@ -1,70 +0,0 @@
-CONFIG_ARM=y
-CONFIG_ARCH_MX6=y
-CONFIG_SYS_TEXT_BASE=0x17800000
-CONFIG_SPL_GPIO_SUPPORT=y
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_NR_DRAM_BANKS=1
-CONFIG_ENV_SIZE=0x2000
-CONFIG_ENV_OFFSET=0x60000
-CONFIG_MX6S=y
-CONFIG_TARGET_EMBESTMX6BOARDS=y
-CONFIG_SPL_TEXT_BASE=0x00908000
-CONFIG_SPL_MMC_SUPPORT=y
-CONFIG_SPL_SERIAL_SUPPORT=y
-CONFIG_SPL=y
-CONFIG_SPL_LIBDISK_SUPPORT=y
-CONFIG_DISTRO_DEFAULTS=y
-CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6s1g.cfg,SPL,DDR_MB=1024"
-CONFIG_BOOTCOMMAND="run finduuid; run distro_bootcmd"
-# CONFIG_CONSOLE_MUX is not set
-CONFIG_SYS_CONSOLE_IS_IN_ENV=y
-CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE=y
-CONFIG_BOARD_EARLY_INIT_F=y
-CONFIG_SPL_RAW_IMAGE_SUPPORT=y
-CONFIG_SPL_FS_EXT4=y
-CONFIG_SPL_OS_BOOT=y
-CONFIG_CMD_GPIO=y
-CONFIG_CMD_I2C=y
-CONFIG_CMD_MMC=y
-CONFIG_CMD_SF=y
-CONFIG_CMD_USB=y
-CONFIG_CMD_CACHE=y
-CONFIG_CMD_EXT4_WRITE=y
-CONFIG_ENV_OVERWRITE=y
-CONFIG_ENV_IS_IN_MMC=y
-CONFIG_SYS_RELOC_GD_ENV_ADDR=y
-CONFIG_SYS_MMC_ENV_DEV=2
-CONFIG_DM=y
-CONFIG_SUPPORT_EMMC_BOOT=y
-CONFIG_FSL_USDHC=y
-CONFIG_SPI_FLASH=y
-CONFIG_SF_DEFAULT_MODE=0
-CONFIG_SF_DEFAULT_SPEED=20000000
-CONFIG_SPI_FLASH_SST=y
-CONFIG_PHYLIB=y
-CONFIG_PHY_ATHEROS=y
-CONFIG_MII=y
-CONFIG_MXC_UART=y
-CONFIG_SPI=y
-CONFIG_MXC_SPI=y
-CONFIG_DM_THERMAL=y
-CONFIG_IMX_THERMAL=y
-CONFIG_USB=y
-CONFIG_USB_HOST_ETHER=y
-CONFIG_USB_ETHER_ASIX=y
-CONFIG_DM_VIDEO=y
-# CONFIG_BACKLIGHT is not set
-# CONFIG_CMD_VIDCONSOLE is not set
-# CONFIG_VIDEO_BPP8 is not set
-# CONFIG_VIDEO_BPP32 is not set
-# CONFIG_VIDEO_ANSI is not set
-CONFIG_SYS_WHITE_ON_BLACK=y
-# CONFIG_PANEL is not set
-CONFIG_VIDEO_IPUV3=y
-CONFIG_SPLASH_SCREEN=y
-CONFIG_SPLASH_SCREEN_ALIGN=y
-CONFIG_VIDEO_BMP_RLE8=y
-CONFIG_BMP_16BPP=y
-CONFIG_OF_LIBFDT=y
-CONFIG_SPL_OF_LIBFDT=y
diff --git a/configs/rock960-rk3399_defconfig b/configs/rock960-rk3399_defconfig
index 28d1fc5..9f1aeaa 100644
--- a/configs/rock960-rk3399_defconfig
+++ b/configs/rock960-rk3399_defconfig
@@ -23,6 +23,7 @@
 CONFIG_CMD_PCI=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
+# CONFIG_CMD_SF is not set
 CONFIG_CMD_TIME=y
 CONFIG_CMD_PMIC=y
 CONFIG_CMD_REGULATOR=y
diff --git a/configs/s400_defconfig b/configs/s400_defconfig
index a15ac32..39e44c0 100644
--- a/configs/s400_defconfig
+++ b/configs/s400_defconfig
@@ -29,7 +29,7 @@
 CONFIG_MMC_MESON_GX=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_AXG=y
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index cfda834..4648808 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -20,8 +20,8 @@
 CONFIG_CONSOLE_RECORD=y
 CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
 CONFIG_PRE_CONSOLE_BUFFER=y
-CONFIG_LOG_SYSLOG=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_MISC_INIT_F=y
 CONFIG_CMD_CPU=y
 CONFIG_CMD_LICENSE=y
 CONFIG_CMD_BOOTZ=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 5bc90d0..5da8d16 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -24,6 +24,7 @@
 CONFIG_LOG_SYSLOG=y
 CONFIG_LOG_ERROR_RETURN=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_MISC_INIT_F=y
 CONFIG_ANDROID_AB=y
 CONFIG_CMD_CPU=y
 CONFIG_CMD_LICENSE=y
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index 4401f33..b68f938 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -17,8 +17,8 @@
 CONFIG_BOOTSTAGE_STASH_SIZE=0x4096
 CONFIG_CONSOLE_RECORD=y
 CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
-CONFIG_LOG_SYSLOG=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_MISC_INIT_F=y
 CONFIG_CMD_CPU=y
 CONFIG_CMD_LICENSE=y
 CONFIG_CMD_BOOTZ=y
diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig
new file mode 100644
index 0000000..1ac7e02
--- /dev/null
+++ b/configs/sandbox_noinst_defconfig
@@ -0,0 +1,231 @@
+CONFIG_SYS_TEXT_BASE=0x200000
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_SYS_MEMTEST_START=0x00100000
+CONFIG_SYS_MEMTEST_END=0x00101000
+CONFIG_ENV_SIZE=0x2000
+CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x8000
+CONFIG_SPL=y
+CONFIG_BOOTSTAGE_STASH_ADDR=0x0
+CONFIG_DEFAULT_DEVICE_TREE="sandbox"
+CONFIG_SANDBOX_SPL=y
+CONFIG_DEBUG_UART=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
+# CONFIG_USE_SPL_FIT_GENERATOR is not set
+CONFIG_BOOTSTAGE=y
+CONFIG_BOOTSTAGE_REPORT=y
+CONFIG_BOOTSTAGE_FDT=y
+CONFIG_BOOTSTAGE_STASH=y
+CONFIG_BOOTSTAGE_STASH_SIZE=0x4096
+CONFIG_CONSOLE_RECORD=y
+CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_HANDOFF=y
+CONFIG_SPL_BOARD_INIT=y
+CONFIG_SPL_ENV_SUPPORT=y
+CONFIG_SPL_I2C_SUPPORT=y
+CONFIG_SPL_RTC_SUPPORT=y
+CONFIG_CMD_CPU=y
+CONFIG_CMD_LICENSE=y
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_BOOTEFI_HELLO=y
+# CONFIG_CMD_ELF is not set
+CONFIG_CMD_ASKENV=y
+CONFIG_CMD_GREPENV=y
+CONFIG_CMD_ERASEENV=y
+CONFIG_CMD_ENV_CALLBACK=y
+CONFIG_CMD_ENV_FLAGS=y
+CONFIG_CMD_NVEDIT_INFO=y
+CONFIG_CMD_NVEDIT_LOAD=y
+CONFIG_CMD_NVEDIT_SELECT=y
+CONFIG_LOOPW=y
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MX_CYCLIC=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_DEMO=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_IDE=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_OSD=y
+CONFIG_CMD_PCI=y
+CONFIG_CMD_REMOTEPROC=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_BOOTP_DNS2=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_TFTPSRV=y
+CONFIG_CMD_RARP=y
+CONFIG_CMD_CDP=y
+CONFIG_CMD_SNTP=y
+CONFIG_CMD_DNS=y
+CONFIG_CMD_LINK_LOCAL=y
+CONFIG_CMD_BMP=y
+CONFIG_CMD_EFIDEBUG=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_TIMER=y
+CONFIG_CMD_SOUND=y
+CONFIG_CMD_QFW=y
+CONFIG_CMD_BOOTSTAGE=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_TPM=y
+CONFIG_CMD_TPM_TEST=y
+CONFIG_CMD_CBFS=y
+CONFIG_CMD_CRAMFS=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_MAC_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_HOSTFILE=y
+CONFIG_SPL_OF_PLATDATA=y
+CONFIG_ENV_IS_NOWHERE=y
+CONFIG_ENV_IS_IN_EXT4=y
+CONFIG_ENV_EXT4_INTERFACE="host"
+CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
+CONFIG_BOOTP_SEND_HOSTNAME=y
+CONFIG_NETCONSOLE=y
+CONFIG_IP_DEFRAG=y
+CONFIG_SPL_DM=y
+CONFIG_DM_DMA=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_DEVRES=y
+CONFIG_DEBUG_DEVRES=y
+# CONFIG_SPL_SIMPLE_BUS is not set
+CONFIG_ADC=y
+CONFIG_ADC_SANDBOX=y
+CONFIG_AXI=y
+CONFIG_AXI_SANDBOX=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_CPU=y
+CONFIG_DM_DEMO=y
+CONFIG_DM_DEMO_SIMPLE=y
+CONFIG_DM_DEMO_SHAPE=y
+CONFIG_SPL_FIRMWARE=y
+CONFIG_GPIO_HOG=y
+CONFIG_PM8916_GPIO=y
+CONFIG_SANDBOX_GPIO=y
+CONFIG_I2C_CROS_EC_TUNNEL=y
+CONFIG_I2C_CROS_EC_LDO=y
+CONFIG_DM_I2C_GPIO=y
+CONFIG_SYS_I2C_SANDBOX=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_ARB_GPIO_CHALLENGE=y
+CONFIG_CROS_EC_KEYB=y
+CONFIG_I8042_KEYB=y
+CONFIG_LED=y
+CONFIG_LED_BLINK=y
+CONFIG_LED_GPIO=y
+CONFIG_DM_MAILBOX=y
+CONFIG_SANDBOX_MBOX=y
+CONFIG_MISC=y
+CONFIG_CROS_EC=y
+CONFIG_CROS_EC_I2C=y
+CONFIG_CROS_EC_LPC=y
+CONFIG_CROS_EC_SANDBOX=y
+CONFIG_CROS_EC_SPI=y
+CONFIG_IRQ=y
+CONFIG_P2SB=y
+CONFIG_PWRSEQ=y
+CONFIG_SPL_PWRSEQ=y
+CONFIG_MMC_SANDBOX=y
+CONFIG_SPI_FLASH_SANDBOX=y
+CONFIG_SPI_FLASH_ATMEL=y
+CONFIG_SPI_FLASH_EON=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_SST=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_ETH=y
+CONFIG_NVME=y
+CONFIG_PCI=y
+CONFIG_DM_PCI=y
+CONFIG_DM_PCI_COMPAT=y
+CONFIG_PCI_SANDBOX=y
+CONFIG_PHY=y
+CONFIG_PHY_SANDBOX=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_PINCTRL_SANDBOX=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_ACT8846=y
+CONFIG_DM_PMIC_PFUZE100=y
+CONFIG_DM_PMIC_MAX77686=y
+CONFIG_DM_PMIC_MC34708=y
+CONFIG_PMIC_PM8916=y
+CONFIG_PMIC_RK8XX=y
+CONFIG_PMIC_S2MPS11=y
+CONFIG_DM_PMIC_SANDBOX=y
+CONFIG_PMIC_S5M8767=y
+CONFIG_PMIC_TPS65090=y
+CONFIG_DM_REGULATOR=y
+CONFIG_REGULATOR_ACT8846=y
+CONFIG_DM_REGULATOR_PFUZE100=y
+CONFIG_DM_REGULATOR_MAX77686=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_REGULATOR_RK8XX=y
+CONFIG_REGULATOR_S5M8767=y
+CONFIG_DM_REGULATOR_SANDBOX=y
+CONFIG_REGULATOR_TPS65090=y
+CONFIG_DM_PWM=y
+CONFIG_PWM_SANDBOX=y
+CONFIG_RAM=y
+CONFIG_REMOTEPROC_SANDBOX=y
+CONFIG_DM_RESET=y
+CONFIG_SANDBOX_RESET=y
+CONFIG_DM_RTC=y
+CONFIG_SPL_DM_RTC=y
+CONFIG_SANDBOX_SERIAL=y
+CONFIG_SOUND=y
+CONFIG_SOUND_SANDBOX=y
+CONFIG_SOC_DEVICE=y
+CONFIG_SANDBOX_SPI=y
+CONFIG_SPMI=y
+CONFIG_SPMI_SANDBOX=y
+CONFIG_SYSINFO=y
+CONFIG_SYSINFO_SANDBOX=y
+CONFIG_SYSRESET=y
+CONFIG_SPL_SYSRESET=y
+CONFIG_TIMER=y
+CONFIG_TIMER_EARLY=y
+CONFIG_SANDBOX_TIMER=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EMUL=y
+CONFIG_USB_KEYBOARD=y
+CONFIG_DM_VIDEO=y
+CONFIG_CONSOLE_ROTATION=y
+CONFIG_CONSOLE_TRUETYPE=y
+CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y
+CONFIG_VIDEO_SANDBOX_SDL=y
+CONFIG_OSD=y
+CONFIG_SANDBOX_OSD=y
+CONFIG_SPLASH_SCREEN_ALIGN=y
+CONFIG_VIDEO_BMP_RLE8=y
+CONFIG_FS_CBFS=y
+CONFIG_FS_CRAMFS=y
+# CONFIG_SPL_USE_TINY_PRINTF is not set
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_RSA_VERIFY_WITH_PKEY=y
+CONFIG_TPM=y
+CONFIG_LZ4=y
+CONFIG_ERRNO_STR=y
+CONFIG_UNIT_TEST=y
+CONFIG_SPL_UNIT_TEST=y
+CONFIG_UT_TIME=y
+CONFIG_UT_DM=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index c011870..0e40b17 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -1,4 +1,4 @@
-CONFIG_SYS_TEXT_BASE=0
+CONFIG_SYS_TEXT_BASE=0x200000
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_NR_DRAM_BANKS=1
@@ -7,9 +7,11 @@
 CONFIG_ENV_SIZE=0x2000
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x8000
 CONFIG_SPL=y
 CONFIG_BOOTSTAGE_STASH_ADDR=0x0
 CONFIG_DEFAULT_DEVICE_TREE="sandbox"
+CONFIG_TARGET_SANDBOX_SPL=y
 CONFIG_SANDBOX_SPL=y
 CONFIG_DEBUG_UART=y
 CONFIG_DISTRO_DEFAULTS=y
@@ -26,6 +28,7 @@
 CONFIG_CONSOLE_RECORD=y
 CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
 CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_MISC_INIT_F=y
 CONFIG_HANDOFF=y
 CONFIG_SPL_BOARD_INIT=y
 CONFIG_SPL_ENV_SUPPORT=y
@@ -87,6 +90,7 @@
 CONFIG_SPL_OF_CONTROL=y
 CONFIG_OF_HOSTFILE=y
 CONFIG_SPL_OF_PLATDATA=y
+CONFIG_SPL_OF_PLATDATA_INST=y
 CONFIG_ENV_IS_NOWHERE=y
 CONFIG_ENV_IS_IN_EXT4=y
 CONFIG_ENV_EXT4_INTERFACE="host"
@@ -102,6 +106,7 @@
 CONFIG_SPL_SYSCON=y
 CONFIG_DEVRES=y
 CONFIG_DEBUG_DEVRES=y
+# CONFIG_SPL_SIMPLE_BUS is not set
 CONFIG_ADC=y
 CONFIG_ADC_SANDBOX=y
 CONFIG_AXI=y
diff --git a/configs/sei510_defconfig b/configs/sei510_defconfig
index 7b97a2f..2c84abf 100644
--- a/configs/sei510_defconfig
+++ b/configs/sei510_defconfig
@@ -45,10 +45,11 @@
 # CONFIG_INPUT is not set
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
-CONFIG_PHY_ADDR_ENABLE=y
-CONFIG_PHY_ADDR=8
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MESON_G12A=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_G12A_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_G12A=y
diff --git a/configs/sei610_defconfig b/configs/sei610_defconfig
index 0ed1709..392ab64 100644
--- a/configs/sei610_defconfig
+++ b/configs/sei610_defconfig
@@ -45,10 +45,11 @@
 # CONFIG_INPUT is not set
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
-CONFIG_PHY_ADDR_ENABLE=y
-CONFIG_PHY_ADDR=8
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MESON_G12A=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_G12A_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_G12A=y
diff --git a/configs/sheevaplug_defconfig b/configs/sheevaplug_defconfig
index 34da356..65d8dff 100644
--- a/configs/sheevaplug_defconfig
+++ b/configs/sheevaplug_defconfig
@@ -40,6 +40,8 @@
 CONFIG_NETCONSOLE=y
 CONFIG_DM=y
 CONFIG_MVSATA_IDE=y
+CONFIG_DM_MMC=y
+CONFIG_MVEBU_MMC=y
 CONFIG_MTD=y
 CONFIG_MTD_RAW_NAND=y
 CONFIG_MVGBE=y
diff --git a/configs/sifive_fu540_defconfig b/configs/sifive_unleashed_defconfig
similarity index 95%
rename from configs/sifive_fu540_defconfig
rename to configs/sifive_unleashed_defconfig
index cabd3b1..62416a7 100644
--- a/configs/sifive_fu540_defconfig
+++ b/configs/sifive_unleashed_defconfig
@@ -8,7 +8,7 @@
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
 CONFIG_DEFAULT_DEVICE_TREE="hifive-unleashed-a00"
-CONFIG_TARGET_SIFIVE_FU540=y
+CONFIG_TARGET_SIFIVE_UNLEASHED=y
 CONFIG_ARCH_RV64I=y
 CONFIG_RISCV_SMODE=y
 CONFIG_DISTRO_DEFAULTS=y
diff --git a/configs/silinux_ek874_defconfig b/configs/silinux_ek874_defconfig
new file mode 100644
index 0000000..dcd7560
--- /dev/null
+++ b/configs/silinux_ek874_defconfig
@@ -0,0 +1,83 @@
+CONFIG_ARM=y
+CONFIG_ARCH_CPU_INIT=y
+CONFIG_ARCH_RMOBILE=y
+CONFIG_SYS_TEXT_BASE=0x50000000
+CONFIG_SPL_TEXT_BASE=0xe6318000
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ENV_SIZE=0x10000
+CONFIG_ENV_OFFSET=0x3F0000
+CONFIG_ENV_SECT_SIZE=0x10000
+CONFIG_RCAR_GEN3=y
+CONFIG_TARGET_SILINUX_EK874=y
+# CONFIG_BOARD_EARLY_INIT_F is not set
+CONFIG_SOC_DEVICE=y
+CONFIG_SOC_DEVICE_RENESAS=y
+CONFIG_DEFAULT_DEVICE_TREE="r8a774c0-ek874-u-boot"
+CONFIG_SMBIOS_PRODUCT_NAME=""
+CONFIG_FIT=y
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=192.168.0.1:/export/rfs ip=192.168.0.20"
+CONFIG_SUPPORT_RAW_INITRD=y
+CONFIG_DEFAULT_FDT_FILE="r8a774c0-ek874.dtb"
+CONFIG_VERSION_VARIABLE=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_OF_CONTROL=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_BLK=y
+CONFIG_CLK=y
+CONFIG_CLK_RENESAS=y
+CONFIG_DM_GPIO=y
+CONFIG_RCAR_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_RCAR_I2C=y
+CONFIG_SYS_I2C_RCAR_IIC=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_USE_4K_SECTORS=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_RENESAS_RPC_SPI=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_IO_VOLTAGE=y
+CONFIG_MMC_UHS_SUPPORT=y
+CONFIG_RENESAS_SDHI=y
+CONFIG_BITBANGMII=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DM_ETH=y
+CONFIG_RENESAS_RAVB=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_GPIO=y
+CONFIG_SCIF_CONSOLE=y
+CONFIG_TEE=y
+CONFIG_OPTEE=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_STORAGE=y
+CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_SMBIOS_MANUFACTURER=""
diff --git a/configs/sipeed_maix_smode_defconfig b/configs/sipeed_maix_smode_defconfig
index 2516bb7..c20c389 100644
--- a/configs/sipeed_maix_smode_defconfig
+++ b/configs/sipeed_maix_smode_defconfig
@@ -1,10 +1,21 @@
 CONFIG_RISCV=y
 CONFIG_SYS_TEXT_BASE=0x80020000
+CONFIG_ENV_SIZE=0x1000
+CONFIG_ENV_OFFSET=0xfff000
+CONFIG_ENV_SECT_SIZE=0x1000
 CONFIG_TARGET_SIPEED_MAIX=y
 CONFIG_ARCH_RV64I=y
 CONFIG_RISCV_SMODE=y
 CONFIG_STACK_SIZE=0x100000
+CONFIG_USE_BOOTCOMMAND=y
+CONFIG_BOOTCOMMAND="run k210_bootcmd"
+CONFIG_HUSH_PARSER=y
+CONFIG_MTDIDS_DEFAULT="nor0=spi3:0"
+CONFIG_MTDPARTS_DEFAULT="nor0:1M(u-boot),0x1000@0xfff000(env)"
 # CONFIG_NET is not set
 # CONFIG_INPUT is not set
+CONFIG_SF_DEFAULT_BUS=3
 # CONFIG_DM_ETH is not set
+CONFIG_FS_EXT4=y
+CONFIG_FS_FAT=y
 # CONFIG_EFI_UNICODE_CAPITALIZATION is not set
diff --git a/configs/socfpga_agilex_atf_defconfig b/configs/socfpga_agilex_atf_defconfig
index 7adda02..e5b7f4b 100644
--- a/configs/socfpga_agilex_atf_defconfig
+++ b/configs/socfpga_agilex_atf_defconfig
@@ -14,6 +14,10 @@
 CONFIG_SPL_FS_FAT=y
 CONFIG_DEFAULT_DEVICE_TREE="socfpga_agilex_socdk"
 CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_SIGNATURE_MAX_SIZE=0x10000000
+CONFIG_SPL_FIT_SIGNATURE=y
+CONFIG_SPL_CRC32_SUPPORT=y
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_SPL_LOAD_FIT_ADDRESS=0x02000000
 # CONFIG_USE_SPL_FIT_GENERATOR is not set
diff --git a/configs/socfpga_agilex_vab_defconfig b/configs/socfpga_agilex_vab_defconfig
index bca663e..fac9cf7 100644
--- a/configs/socfpga_agilex_vab_defconfig
+++ b/configs/socfpga_agilex_vab_defconfig
@@ -15,6 +15,10 @@
 CONFIG_SPL_FS_FAT=y
 CONFIG_DEFAULT_DEVICE_TREE="socfpga_agilex_socdk"
 CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_SIGNATURE_MAX_SIZE=0x10000000
+CONFIG_SPL_FIT_SIGNATURE=y
+CONFIG_SPL_CRC32_SUPPORT=y
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_SPL_LOAD_FIT_ADDRESS=0x02000000
 # CONFIG_USE_SPL_FIT_GENERATOR is not set
diff --git a/configs/socfpga_stratix10_atf_defconfig b/configs/socfpga_stratix10_atf_defconfig
index 8dbb742..7466025 100644
--- a/configs/socfpga_stratix10_atf_defconfig
+++ b/configs/socfpga_stratix10_atf_defconfig
@@ -14,6 +14,10 @@
 CONFIG_SPL_FS_FAT=y
 CONFIG_DEFAULT_DEVICE_TREE="socfpga_stratix10_socdk"
 CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_SIGNATURE_MAX_SIZE=0x10000000
+CONFIG_SPL_FIT_SIGNATURE=y
+CONFIG_SPL_CRC32_SUPPORT=y
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_SPL_LOAD_FIT_ADDRESS=0x02000000
 # CONFIG_USE_SPL_FIT_GENERATOR is not set
diff --git a/configs/tools-only_defconfig b/configs/tools-only_defconfig
index a853abf..e16f702 100644
--- a/configs/tools-only_defconfig
+++ b/configs/tools-only_defconfig
@@ -4,6 +4,7 @@
 CONFIG_ANDROID_BOOT_IMAGE=y
 CONFIG_FIT=y
 CONFIG_FIT_SIGNATURE=y
+CONFIG_MISC_INIT_F=y
 # CONFIG_CMD_BOOTD is not set
 # CONFIG_CMD_BOOTM is not set
 # CONFIG_CMD_ELF is not set
diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 4b8843d..a8218da 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -46,11 +46,13 @@
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_WDT=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_AES=y
 CONFIG_CMD_HASH=y
 CONFIG_CMD_BTRFS=y
+CONFIG_CMD_FS_UUID=y
 # CONFIG_SPL_PARTITION_UUIDS is not set
 CONFIG_ENV_OVERWRITE=y
 CONFIG_USE_ENV_SPI_MAX_HZ=y
@@ -73,6 +75,8 @@
 CONFIG_PCI=y
 CONFIG_PCI_MVEBU=y
 CONFIG_SCSI=y
+CONFIG_DM_RTC=y
+CONFIG_RTC_ARMADA38X=y
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_KIRKWOOD_SPI=y
diff --git a/configs/u200_defconfig b/configs/u200_defconfig
index b0b822b..4da02f1 100644
--- a/configs/u200_defconfig
+++ b/configs/u200_defconfig
@@ -27,10 +27,11 @@
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
-CONFIG_PHY_ADDR_ENABLE=y
-CONFIG_PHY_ADDR=8
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MESON_G12A=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_G12A_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_G12A=y
diff --git a/configs/udoo_defconfig b/configs/udoo_defconfig
index f72b964..064d545 100644
--- a/configs/udoo_defconfig
+++ b/configs/udoo_defconfig
@@ -5,15 +5,19 @@
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_NR_DRAM_BANKS=1
+CONFIG_DEFAULT_DEVICE_TREE="imx6q-udoo"
+CONFIG_OF_LIST="imx6q-udoo imx6dl-udoo"
 CONFIG_ENV_SIZE=0x2000
 CONFIG_ENV_OFFSET=0x60000
 CONFIG_MX6QDL=y
 CONFIG_TARGET_UDOO=y
+CONFIG_OF_CONTROL=y
 CONFIG_SPL_TEXT_BASE=0x00908000
 CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
+CONFIG_AHCI=y
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/spl_sd.cfg"
 CONFIG_BOOTDELAY=3
@@ -24,6 +28,7 @@
 CONFIG_SPL_WATCHDOG_SUPPORT=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_MMC=y
+# CONFIG_CMD_PINMUX is not set
 CONFIG_CMD_SATA=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_EXT4_WRITE=y
@@ -32,13 +37,19 @@
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
 CONFIG_DM=y
+CONFIG_DM_GPIO=y
 CONFIG_BOUNCE_BUFFER=y
+CONFIG_DM_MMC=y
 CONFIG_DWC_AHSATA=y
 CONFIG_FSL_USDHC=y
-CONFIG_MTD=y
+CONFIG_DM_SCSI=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_IMX6=y
 CONFIG_PHYLIB=y
 CONFIG_PHY_MICREL=y
 CONFIG_PHY_MICREL_KSZ90X1=y
+CONFIG_DM_ETH=y
+CONFIG_FEC_MXC=y
 CONFIG_MII=y
 CONFIG_MXC_UART=y
 CONFIG_DM_THERMAL=y
diff --git a/configs/usbarmory_defconfig b/configs/usbarmory_defconfig
index e1128e5..39fe860 100644
--- a/configs/usbarmory_defconfig
+++ b/configs/usbarmory_defconfig
@@ -2,11 +2,13 @@
 CONFIG_ARCH_MX5=y
 CONFIG_SYS_TEXT_BASE=0x77800000
 CONFIG_NR_DRAM_BANKS=1
+CONFIG_DEFAULT_DEVICE_TREE="imx53-usbarmory"
 CONFIG_SYS_MEMTEST_START=0x70000000
 CONFIG_SYS_MEMTEST_END=0x90000000
 CONFIG_ENV_SIZE=0x2000
 CONFIG_ENV_OFFSET=0x60000
 CONFIG_TARGET_USBARMORY=y
+CONFIG_OF_CONTROL=y
 # CONFIG_CMD_BMODE is not set
 CONFIG_DISTRO_DEFAULTS=y
 # CONFIG_USE_BOOTCOMMAND is not set
@@ -14,13 +16,22 @@
 CONFIG_CMD_FUSE=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
+# CONFIG_CMD_PINMUX is not set
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_DM=y
+CONFIG_DM_GPIO=y
 CONFIG_FSL_ESDHC_IMX=y
 CONFIG_MTD=y
 CONFIG_MXC_UART=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_IMX5=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_GPIO=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_EHCI_MX5=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/wetek-core2_defconfig b/configs/wetek-core2_defconfig
index cbe747b..098e249 100644
--- a/configs/wetek-core2_defconfig
+++ b/configs/wetek-core2_defconfig
@@ -31,9 +31,12 @@
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_MTD=y
+CONFIG_DM_MDIO=y
+CONFIG_DM_MDIO_MUX=y
+CONFIG_MDIO_MUX_MMIOREG=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_ETH=y
-CONFIG_ETH_DESIGNWARE=y
+CONFIG_ETH_DESIGNWARE_MESON8B=y
 CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXL=y
diff --git a/configs/xilinx_versal_virt_defconfig b/configs/xilinx_versal_virt_defconfig
index 69adb0b..2d639a1 100644
--- a/configs/xilinx_versal_virt_defconfig
+++ b/configs/xilinx_versal_virt_defconfig
@@ -32,6 +32,7 @@
 CONFIG_CMD_USB=y
 CONFIG_CMD_TFTPPUT=y
 CONFIG_CMD_CACHE=y
+CONFIG_CMD_EFIDEBUG=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_TIMER=y
 CONFIG_CMD_EXT4_WRITE=y
diff --git a/configs/xilinx_zynq_virt_defconfig b/configs/xilinx_zynq_virt_defconfig
index 552f1b4..2fe5318 100644
--- a/configs/xilinx_zynq_virt_defconfig
+++ b/configs/xilinx_zynq_virt_defconfig
@@ -47,6 +47,8 @@
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_TFTPPUT=y
 CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_TIMER=y
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_MTDPARTS=y
 CONFIG_CMD_MTDPARTS_SPREAD=y
diff --git a/configs/xilinx_zynqmp_mini_emmc0_defconfig b/configs/xilinx_zynqmp_mini_emmc0_defconfig
index 35eb5f1..4594f80 100644
--- a/configs/xilinx_zynqmp_mini_emmc0_defconfig
+++ b/configs/xilinx_zynqmp_mini_emmc0_defconfig
@@ -3,8 +3,10 @@
 CONFIG_SYS_ICACHE_OFF=y
 CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_TEXT_BASE=0x10000
+CONFIG_SYS_MALLOC_F_LEN=0x1000
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_ENV_SIZE=0x80
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x600
 CONFIG_SPL=y
 # CONFIG_CMD_ZYNQMP is not set
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-mini-emmc0"
diff --git a/configs/xilinx_zynqmp_mini_emmc1_defconfig b/configs/xilinx_zynqmp_mini_emmc1_defconfig
index eaec137..d7c64b9 100644
--- a/configs/xilinx_zynqmp_mini_emmc1_defconfig
+++ b/configs/xilinx_zynqmp_mini_emmc1_defconfig
@@ -3,8 +3,10 @@
 CONFIG_SYS_ICACHE_OFF=y
 CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_TEXT_BASE=0x10000
+CONFIG_SYS_MALLOC_F_LEN=0x1000
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_ENV_SIZE=0x80
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x600
 CONFIG_SPL=y
 # CONFIG_CMD_ZYNQMP is not set
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-mini-emmc1"
diff --git a/configs/xilinx_zynqmp_virt_defconfig b/configs/xilinx_zynqmp_virt_defconfig
index 0bf4b7d..fbff215 100644
--- a/configs/xilinx_zynqmp_virt_defconfig
+++ b/configs/xilinx_zynqmp_virt_defconfig
@@ -56,6 +56,7 @@
 CONFIG_CMD_TFTPPUT=y
 CONFIG_CMD_BMP=y
 CONFIG_CMD_CACHE=y
+CONFIG_CMD_EFIDEBUG=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_TIMER=y
 CONFIG_CMD_TPM=y
diff --git a/doc/Makefile b/doc/Makefile
index a686d47..683e4b5 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -56,7 +56,6 @@
 	PYTHONDONTWRITEBYTECODE=1 \
 	BUILDDIR=$(abspath $(BUILDDIR)) SPHINX_CONF=$(abspath $(srctree)/$(src)/$5/$(SPHINX_CONF)) \
 	$(SPHINXBUILD) \
-	-W \
 	-b $2 \
 	-c $(abspath $(srctree)/$(src)) \
 	-d $(abspath $(BUILDDIR)/.doctrees/$3) \
diff --git a/doc/arch/sandbox.rst b/doc/arch/sandbox.rst
index 60ee1e0..e052b6b 100644
--- a/doc/arch/sandbox.rst
+++ b/doc/arch/sandbox.rst
@@ -17,6 +17,12 @@
 all the generic code, not specific to any one architecture. The idea is to
 create unit tests which we can run to test this upper level code.
 
+Sandbox allows development of many types of new features in a traditional way,
+rather than needing to test each iteration on real hardware. Many U-Boot
+features were developed on sandbox, including the core driver model, most
+uclasses, verified boot, bloblist, logging and dozens of others. Sandbox has
+enabled many large-scale code refactors as well.
+
 CONFIG_SANDBOX is defined when building a native board.
 
 The board name is 'sandbox' but the vendor name is unset, so there is a
@@ -76,7 +82,7 @@
 You can issue commands as your would normally. If the command you want is
 not supported you can add it to include/configs/sandbox.h.
 
-To exit, type 'reset' or press Ctrl-C.
+To exit, type 'poweroff' or press Ctrl-C.
 
 
 Console / LCD support
@@ -383,6 +389,8 @@
    =>host bind 0 ./disk.raw
    =>ls host 0:2
 
+The device can be marked removeable with 'host bind -r'.
+
 A disk image can be created using the following commands::
 
    $> truncate -s 1200M ./disk.raw
@@ -486,42 +494,10 @@
 -------
 
 U-Boot sandbox can be used to run various tests, mostly in the test/
-directory. These include:
+directory.
 
-command_ut:
-  Unit tests for command parsing and handling
-compression:
-  Unit tests for U-Boot's compression algorithms, useful for
-  security checking. It supports gzip, bzip2, lzma and lzo.
-driver model:
-  Run this pytest::
-
-   ./test/py/test.py --bd sandbox --build -k ut_dm -v
-
-image:
-  Unit tests for images:
-  test/image/test-imagetools.sh - multi-file images
-  test/image/test-fit.py        - FIT images
-tracing:
-  test/trace/test-trace.sh tests the tracing system (see README.trace)
-verified boot:
-  See test/vboot/vboot_test.sh for this
-
-If you change or enhance any of the above subsystems, you shold write or
-expand a test and include it with your patch series submission. Test
-coverage in U-Boot is limited, as we need to work to improve it.
-
-Note that many of these tests are implemented as commands which you can
-run natively on your board if desired (and enabled).
-
-To run all tests use "make check".
-
-To run a single test in an existing sandbox build, you can use -T to use the
-test device tree, and -c to select the test:
-
-  /tmp/b/sandbox/u-boot -T -c "ut dm pci_busdev"
-
-This runs dm_test_pci_busdev() which is in test/dm/pci.c
+See :doc:`../develop/tests_sandbox` for more information and
+:doc:`../develop/testing` for information about testing generally.
 
 
 Memory Map
@@ -537,5 +513,7 @@
    e000   CONFIG_BLOBLIST_ADDR       Blob list
   10000   CONFIG_MALLOC_F_ADDR       Early memory allocation
   f0000   CONFIG_PRE_CON_BUF_ADDR    Pre-console buffer
- 100000   CONFIG_TRACE_EARLY_ADDR    Early trace buffer (if enabled)
+ 100000   CONFIG_TRACE_EARLY_ADDR    Early trace buffer (if enabled). Also used
+                                     as the SPL load buffer in spl_test_load().
+ 200000   CONFIG_SYS_TEXT_BASE       Load buffer for U-Boot (sandbox_spl only)
 =======   ========================   ===============================
diff --git a/doc/arch/x86.rst b/doc/arch/x86.rst
index cc307aa..2ebfed8 100644
--- a/doc/arch/x86.rst
+++ b/doc/arch/x86.rst
@@ -709,8 +709,8 @@
   No controllers found
   Hit any key to stop autoboot:  0
 
-See :doc:`../uefi/u-boot_on_efi` and :doc:`../uefi/uefi` for details of
-EFI support in U-Boot.
+See :doc:`../develop/uefi/u-boot_on_efi` and :doc:`../develop/uefi/uefi` for
+details of EFI support in U-Boot.
 
 Chain-loading
 -------------
diff --git a/doc/board/emulation/qemu_capsule_update.rst b/doc/board/emulation/qemu_capsule_update.rst
index 9fec75f..33ce4bc 100644
--- a/doc/board/emulation/qemu_capsule_update.rst
+++ b/doc/board/emulation/qemu_capsule_update.rst
@@ -60,7 +60,7 @@
 file. The BootNext, BootXXXX and OsIndications variables can be set
 using the following commands::
 
-    => efidebug boot add 0 Boot0000 virtio 0:1 <capsule_file_name>
+    => efidebug boot add -b 0 Boot0000 virtio 0:1 <capsule_file_name>
     => efidebug boot next 0
     => setenv -e -nv -bs -rt -v OsIndications =0x04
     => saveenv
@@ -198,7 +198,7 @@
     3. Set the following environment and UEFI boot variables
 
         => setenv -e -nv -bs -rt -v OsIndications =0x04
-        => efidebug boot add 0 Boot0000 virtio 0:1 <capsule_file_name>
+        => efidebug boot add -b 0 Boot0000 virtio 0:1 <capsule_file_name>
         => efidebug boot next 0
         => saveenv
 
diff --git a/doc/board/freescale/imx8mm_evk.rst b/doc/board/freescale/imx8mm_evk.rst
index a9ccdb7..7fd3d72 100644
--- a/doc/board/freescale/imx8mm_evk.rst
+++ b/doc/board/freescale/imx8mm_evk.rst
@@ -43,13 +43,14 @@
    $ export CROSS_COMPILE=aarch64-poky-linux-
    $ make imx8mm_evk_defconfig
    $ export ATF_LOAD_ADDR=0x920000
-   $ make flash.bin
+   $ make
 
 Burn the flash.bin to MicroSD card offset 33KB:
 
 .. code-block:: bash
 
    $sudo dd if=flash.bin of=/dev/sd[x] bs=1024 seek=33 conv=notrunc
+   $sudo dd if=u-boot.itb of=/dev/sdc bs=1024 seek=384 conv=sync
 
 Boot
 ----
diff --git a/doc/board/freescale/imx8mn_evk.rst b/doc/board/freescale/imx8mn_evk.rst
index 375e0bb..9fbb947 100644
--- a/doc/board/freescale/imx8mn_evk.rst
+++ b/doc/board/freescale/imx8mn_evk.rst
@@ -43,13 +43,14 @@
    $ export CROSS_COMPILE=aarch64-poky-linux-
    $ make imx8mn_ddr4_evk_defconfig
    $ export ATF_LOAD_ADDR=0x960000
-   $ make flash.bin
+   $ make
 
 Burn the flash.bin to MicroSD card offset 32KB:
 
 .. code-block:: bash
 
    $sudo dd if=flash.bin of=/dev/sd[x] bs=1024 seek=32 conv=notrunc
+   $sudo dd if=u-boot.itb of=/dev/sd[x] bs=1024 seek=384 conv=notrunc
 
 Boot
 ----
diff --git a/doc/board/freescale/imx8mp_evk.rst b/doc/board/freescale/imx8mp_evk.rst
index 796a761..609a29f 100644
--- a/doc/board/freescale/imx8mp_evk.rst
+++ b/doc/board/freescale/imx8mp_evk.rst
@@ -40,18 +40,19 @@
    $ export CROSS_COMPILE=aarch64-poky-linux-
    $ make O=build imx8mp_evk_defconfig
    $ cp ../imx-atf/build/imx8mp/release/bl31.bin ./build/bl31.bin
-   $ cp ../firmware-imx-8.10/firmware/ddr/synopsys/lpddr4_pmu_train_1d_dmem_202006.bin ./build/lpddr4_pmu_train_1d_dmem.bin
-   $ cp ../firmware-imx-8.10/firmware/ddr/synopsys/lpddr4_pmu_train_1d_imem_202006.bin ./build/lpddr4_pmu_train_1d_imem.bin
-   $ cp ../firmware-imx-8.10/firmware/ddr/synopsys/lpddr4_pmu_train_2d_dmem_202006.bin ./build/lpddr4_pmu_train_2d_dmem.bin
-   $ cp ../firmware-imx-8.10/firmware/ddr/synopsys/lpddr4_pmu_train_2d_imem_202006.bin ./build/lpddr4_pmu_train_2d_imem.bin
+   $ cp ../firmware-imx-8.10/firmware/ddr/synopsys/lpddr4_pmu_train_1d_dmem_202006.bin ./build/
+   $ cp ../firmware-imx-8.10/firmware/ddr/synopsys/lpddr4_pmu_train_1d_imem_202006.bin ./build/
+   $ cp ../firmware-imx-8.10/firmware/ddr/synopsys/lpddr4_pmu_train_2d_dmem_202006.bin ./build/
+   $ cp ../firmware-imx-8.10/firmware/ddr/synopsys/lpddr4_pmu_train_2d_imem_202006.bin ./build/
    $ export ATF_LOAD_ADDR=0x970000
-   $ make O=build flash.bin
+   $ make O=build
 
 Burn the flash.bin to the MicroSD card at offset 32KB:
 
 .. code-block:: bash
 
    $sudo dd if=build/flash.bin of=/dev/sd[x] bs=1K seek=32 conv=notrunc; sync
+   $sudo dd if=build/u-boot.itb of=/dev/sd[x] bs=1K seek=384 conv=notrunc; sync
 
 Boot
 ----
diff --git a/doc/board/google/chromebook_coral.rst b/doc/board/google/chromebook_coral.rst
index c39f1e3..4b58567 100644
--- a/doc/board/google/chromebook_coral.rst
+++ b/doc/board/google/chromebook_coral.rst
@@ -16,6 +16,169 @@
 Slim Bootloader. This documentation refers to a 'bare metal' port.
 
 
+Building
+--------
+
+First, you need the following binary blobs:
+
+   * descriptor.bin - Intel flash descriptor
+   * fitimage.bin - Base flash image structure
+   * fsp_m.bin - FSP-M, for setting up SDRAM
+   * fsp_s.bin - FSP-S, for setting up Silicon
+   * vbt.bin - for setting up display
+
+These binaries do not seem to be available publicly. If you have a ROM image,
+such as santa.bin then you can do this::
+
+  cbfstool santa.bin extract -n fspm.bin -f fsp-m.bin
+  cbfstool santa.bin extract -n fsps.bin -f fsp-s.bin
+  cbfstool santa.bin extract -n vbt-santa.bin -f vbt.bin
+  mkdir tmp
+  cd tmp
+  dump_fmap -x ../santa.bin
+  mv SI_DESC ../descriptor.bin
+  mv IFWI ../fitimage.bin
+
+Put all of these files in `board/google/chromebook_coral` so they can be found
+by the build.
+
+To build::
+
+  make O=/tmp/b/chromebook_coral chromebook_coral_defconfig
+  make O=/tmp/b/chromebook_coral -s -j30 all
+
+That should produce `/tmp/b/chrombook_coral/u-boot.rom` which you can use with
+a Dediprog em100::
+
+  em100 -s -c w25q128fw -d /tmp/b/chromebook_coral/u-boot.rom -r
+
+or you can use flashrom to write it to the board. If you do that, make sure you
+have a way to restore the old ROM without booting the board. Otherwise you may
+brick it. Having said that, you may find these instructions useful if you want
+to unbrick your device:
+
+  https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging.md
+
+You can buy Suzy-Q from Sparkfun:
+
+  https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/main/docs/ccd.md#suzyq-suzyqable
+
+Note that it will hang at the SPL prompt for 21 seconds. When booting into
+Chrome OS it will always select developer mode, so will wipe anything you have
+on the device if you let it proceed. You have two seconds in U-Boot to stop the
+auto-boot prompt and several seconds at the 'developer wipe' screen to stop it
+wiping the disk.
+
+Here is the console output::
+
+  U-Boot TPL 2021.04-rc1-00128-g344eefcdfec-dirty (Feb 11 2021 - 20:13:08 -0700)
+  Trying to boot from Mapped SPI
+
+  U-Boot SPL 2021.04-rc1-00128-g344eefcdfec-dirty (Feb 11 2021 - 20:13:08 -0700)
+  Trying to boot from Mapped SPI
+
+
+  U-Boot 2021.04-rc1-00128-g344eefcdfec-dirty (Feb 11 2021 - 20:13:08 -0700)
+
+  CPU:   Intel(R) Celeron(R) CPU N3450 @ 1.10GHz
+  DRAM:  3.9 GiB
+  MMC:   sdmmc@1b,0: 1, emmc@1c,0: 2
+  Video: 1024x768x32 @ b0000000
+  Model: Google Coral
+  Net:   No ethernet found.
+  SF: Detected w25q128fw with page size 256 Bytes, erase size 4 KiB, total 16 MiB
+  Hit any key to stop autoboot:  0
+  cmdline=console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=${uuid}/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=${uuid} add_efi_memmap boot=local noresume noswap i915.modeset=1 Kernel command line: "console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=35c775e7-3735-d745-93e5-d9e0238f7ed0/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=35c775e7-3735-d745-93e5-d9e0238f7ed0 add_efi_memmap boot=local noresume noswap i915.modeset=1 tpm_tis.force=1 tpm_tis.interrupts=0 nmi_watchdog=panic,lapic disablevmx=off  "
+  Setup located at 00090000:
+
+  ACPI RSDP addr      : 7991f000
+  E820: 14 entries
+                Addr              Size  Type
+      d0000000     1000000  <NULL>
+             0       a0000  RAM
+         a0000       60000  Reserved
+      7b000000      800000  Reserved
+      7b800000     4800000  Reserved
+      7ac00000      400000  Reserved
+        100000     ff00000  RAM
+      10000000     2151000  Reserved
+      12151000    68aaf000  RAM
+     100000000    80000000  RAM
+      e0000000    10000000  Reserved
+      7991bfd0     12e4030  Reserved
+      d0000000    10000000  Reserved
+      fed10000        8000  Reserved
+  Setup sectors       : 1e
+  Root flags          : 1
+  Sys size            : 63420
+  RAM size            : 0
+  Video mode          : ffff
+  Root dev            : 0
+  Boot flag           : 0
+  Jump                : 66eb
+  Header              : 53726448
+                        Kernel V2
+  Version             : 20d
+  Real mode switch    : 0
+  Start sys           : 1000
+  Kernel version      : 38cc
+     @00003acc:
+  Type of loader      : 80
+                        U-Boot, version 0
+  Load flags          : 81
+                      : loaded-high can-use-heap
+  Setup move size     : 8000
+  Code32 start        : 100000
+  Ramdisk image       : 0
+  Ramdisk size        : 0
+  Bootsect kludge     : 0
+  Heap end ptr        : 8e00
+  Ext loader ver      : 0
+  Ext loader type     : 0
+  Command line ptr    : 99000
+     console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=35c775e7-3735-d745-93e5-d9e0238f7ed0/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=35c775e7-3735-d745-93e5-d9e0238f7ed0 add_efi_memmap boot=local noresume noswap i915.modeset=1 tpm_tis.force=1 tpm_tis.interrupts=0 nmi_watchdog=panic,lapic disablevmx=off
+  Initrd addr max     : 7fffffff
+  Kernel alignment    : 200000
+  Relocatable kernel  : 1
+  Min alignment       : 15
+                      : 200000
+  Xload flags         : 3
+                      : 64-bit-entry can-load-above-4gb
+  Cmdline size        : 7ff
+  Hardware subarch    : 0
+  HW subarch data     : 0
+  Payload offset      : 26e
+  Payload length      : 612045
+  Setup data          : 0
+  Pref address        : 1000000
+  Init size           : 1383000
+  Handover offset     : 0
+
+  Starting kernel ...
+
+  Timer summary in microseconds (17 records):
+         Mark    Elapsed  Stage
+            0          0  reset
+      155,279    155,279  TPL
+      237,088     81,809  end phase
+      237,533        445  SPL
+      816,456    578,923  end phase
+      817,357        901  board_init_f
+    1,061,751    244,394  board_init_r
+    1,402,435    340,684  id=64
+    1,430,071     27,636  main_loop
+    5,532,057  4,101,986  start_kernel
+
+  Accumulated time:
+                     685  dm_r
+                   2,817  fast_spi
+                  33,095  dm_spl
+                  52,468  dm_f
+                 208,242  fsp-m
+                 242,221  fsp-s
+                 332,710  mmap_spi
+
+
 Boot flow - TPL
 ---------------
 
@@ -181,7 +344,7 @@
     ff000000       Bottom of ROM
     fefc0000       Top of CAR region
     fef96000       Stack for FSP-M
-    fef40000 59000 FSP-M
+    fef40000 59000 FSP-M (also VPL loads here)
     fef11000       SPL loaded here
     fef10000       CONFIG_BLOBLIST_ADDR
     fef10000       Stack top in TPL, SPL and U-Boot before relocation
@@ -195,35 +358,72 @@
      1110000       CONFIG_SYS_TEXT_BASE
 
 
+Speeding up SPL for development
+-------------------------------
+
+The 21-second wait for memory training is annoying during development, since
+every new image incurs this cost when booting. There is no cache to fall back on
+since that area of the image is empty on start-up.
+
+You can add suitable cache contents to the image to fix this, for development
+purposes only, like this::
+
+   # Read the image back after booting through SPL
+   em100 -s -c w25q128fw -u image.bin
+
+   # Extract the two cache regions
+   binman extract -i image.bin extra *cache
+
+   # Move them into the source directory
+   mv *cache board/google/chromebook_coral
+
+Then add something like this to the devicetree::
+
+  #if IS_ENABLED(CONFIG_HAVE_MRC) || IS_ENABLED(CONFIG_FSP_VERSION2)
+     /* Provide initial contents of the MRC data for faster development */
+     rw-mrc-cache {
+        type = "blob";
+        /* Mirror the offset in spi-flash@0 */
+        offset = <0xff8e0000>;
+        size = <0x10000>;
+        filename = "board/google/chromebook_coral/rw-mrc-cache";
+     };
+     rw-var-mrc-cache {
+        type = "blob";
+        size = <0x1000>;
+        filename = "board/google/chromebook_coral/rw-var-mrc-cache";
+     };
+  #endif
+
+This tells binman to put the cache contents in the same place as the
+`rw-mrc-cache` and `rw-var-mrc-cache` regions defined by the SPI-flash driver.
+
+
 Supported peripherals
 ---------------------
 
-- UART
-- SPI flash
-- Video
-- MMC (dev 0) and micro-SD (dev 1)
-- Chrome OS EC
-- Keyboard
-- USB
+The following have U-Boot drivers:
+
+   - UART
+   - SPI flash
+   - Video
+   - MMC (dev 0) and micro-SD (dev 1)
+   - Chrome OS EC
+   - Cr50 (security chip)
+   - Keyboard
+   - USB
 
 
 To do
 -----
 
 - Finish peripherals
-   - left-side USB
-   - USB-C
-   - Cr50 (security chip: a basic driver is running but not included here)
    - Sound (Intel I2S support exists, but need da7219 driver)
-   - Various minor features supported by LPC, etc.
-- Booting Chrome OS, e.g. with verified boot
-- Integrate with Chrome OS vboot
-- Improvements to booting from coreboot (i.e. as a coreboot target)
 - Use FSP-T binary instead of our own CAR implementation
 - Use the official FSP package instead of the coreboot one
-- Enable all CPU cores
 - Suspend / resume
-- ACPI
+- Fix MMC which seems to try to read even though the card is empty
+- Fix USB3 crash "WARN halted endpoint, queueing URB anyway."
 
 
 Credits
diff --git a/doc/board/rockchip/rockchip.rst b/doc/board/rockchip/rockchip.rst
index 955e685..fbb9983 100644
--- a/doc/board/rockchip/rockchip.rst
+++ b/doc/board/rockchip/rockchip.rst
@@ -61,6 +61,7 @@
      - Firefly ROC-RK3399-PC
      - FriendlyElec NanoPC-T4 (nanopc-t4-rk3399)
      - FriendlyElec NanoPi M4 (nanopi-m4-rk3399)
+     - FriendlyElec NanoPi M4B (nanopi-m4b-rk3399)
      - FriendlyARM NanoPi NEO4 (nanopi-neo4-rk3399)
      - Google Bob (chromebook_bob)
      - Khadas Edge (khadas-edge-rk3399)
diff --git a/doc/board/sifive/index.rst b/doc/board/sifive/index.rst
index ad614c9..ed7eacf 100644
--- a/doc/board/sifive/index.rst
+++ b/doc/board/sifive/index.rst
@@ -6,4 +6,4 @@
 .. toctree::
    :maxdepth: 2
 
-   fu540
+   unleashed
diff --git a/doc/board/sifive/fu540.rst b/doc/board/sifive/unleashed.rst
similarity index 100%
rename from doc/board/sifive/fu540.rst
rename to doc/board/sifive/unleashed.rst
diff --git a/doc/board/toradex/apalix-imx8x.rst b/doc/board/toradex/apalix-imx8x.rst
index ce7dde8..efa7e0c 100644
--- a/doc/board/toradex/apalix-imx8x.rst
+++ b/doc/board/toradex/apalix-imx8x.rst
@@ -1,43 +1,46 @@
 .. SPDX-License-Identifier: GPL-2.0+
 
-Apalis iMX8X V1.1A Module
+Apalis iMX8X V1.1A Module (SoC NXP i.MX8QXP RevB)
 ==========================
 
 Quick Start
 -----------
 
-- Build the ARM trusted firmware binary
-- Get scfw_tcm.bin and ahab-container.img
+- Get and Build the ARM trusted firmware
+- Get System Controller firmware
+- Get SECO container
 - Build U-Boot
 - Load U-Boot binary using uuu
 - Flash U-Boot binary into the eMMC
 - Boot
 
+Note: builddir is U-Boot build directory (source directory for in-tree builds)
+
 Get and Build the ARM Trusted Firmware
 --------------------------------------
 
 .. code-block:: bash
 
-    $ git clone -b toradex_imx_5.4.24_2.1.0 http://git.toradex.com/cgit/imx-atf.git
-    $ cd imx-atf/
-    $ make PLAT=imx8qx bl31
+    $ cd $(builddir)
+    $ git clone -b toradex_imx_5.4.70_2.3.0 http://git.toradex.com/cgit/imx-atf.git
+    $ make PLAT=imx8qx bl31 -C imx-atf
+    $ cp imx-atf/build/imx8qx/release/bl31.bin $(builddir)
 
-Get scfw_tcm.bin and ahab-container.img
+Get System Controller firmware
 ---------------------------------------
 
 .. code-block:: bash
 
-    $ wget https://github.com/toradex/i.MX-System-Controller-Firmware/blob/master/src/scfw_export_mx8qx_b0/build_mx8qx_b0/mx8qx-apalis-scfw-tcm.bin
-    $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/imx-seco-3.6.3.bin
-    $ chmod +x imx-seco-3.6.3.bin
-    $ ./imx-seco-3.6.3.bin
+    $ wget https://github.com/toradex/i.MX-System-Controller-Firmware/raw/master/src/scfw_export_mx8qx_b0/build_mx8qx_b0/mx8qx-apalis-scfw-tcm.bin
 
-Copy the following binaries to the U-Boot folder:
+Get SECO container
+---------------------------------------
 
 .. code-block:: bash
 
-    $ cp imx-atf/build/imx8qx/release/bl31.bin .
-    $ cp imx-seco-3.6.3/firmware/seco/mx8qxb0-ahab-container.img mx8qx-ahab-container.imx8_defconfig
+    $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/imx-seco-3.7.4.bin
+    $ sh imx-seco-3.7.4.bin
+    $ cp imx-seco-3.7.4/firmware/seco/mx8qxb0-ahab-container.img $(builddir)/mx8qx-ahab-container.img
 
 Build U-Boot
 ------------
@@ -58,7 +61,7 @@
 
 .. code-block:: bash
 
-    sudo ./uuu u-boot/u-boot-dtb.imx
+    sudo ./uuu $(builddir)/u-boot-dtb.imx
 
 Flash the U-Boot Binary into the eMMC
 -------------------------------------
diff --git a/doc/build/docker.rst b/doc/build/docker.rst
new file mode 100644
index 0000000..953d1b2
--- /dev/null
+++ b/doc/build/docker.rst
@@ -0,0 +1,14 @@
+GitLab CI / U-Boot runner container
+===================================
+
+In order to have a reproducible and portable build environment for CI we use a container for building in.  This means that developers can also reproduce the CI environment, to a large degree at least, locally.  This file is located in the tools/docker directory.  To build the image yourself
+
+.. code-block:: bash
+
+    sudo docker build -t your-namespace:your-tag .
+
+Or to use an existing container
+
+.. code-block:: bash
+
+    sudo docker pull trini/u-boot-gitlab-ci-runner:bionic-20200807-02Sep2020
diff --git a/doc/build/index.rst b/doc/build/index.rst
index 5f90f95..69952f9 100644
--- a/doc/build/index.rst
+++ b/doc/build/index.rst
@@ -9,4 +9,5 @@
    source
    gcc
    clang
+   docker
    tools
diff --git a/doc/README.chromium-chainload b/doc/chromium/chainload.rst
similarity index 78%
rename from doc/README.chromium-chainload
rename to doc/chromium/chainload.rst
index 45eaece..7b6bb10 100644
--- a/doc/README.chromium-chainload
+++ b/doc/chromium/chainload.rst
@@ -1,3 +1,6 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2020 Google LLC
+
 Running U-Boot from coreboot on Chromebooks
 ===========================================
 
@@ -15,7 +18,7 @@
 
 
 For all of these the standard U-Boot build instructions apply. For example on
-ARM:
+ARM::
 
    sudo apt install gcc-arm-linux-gnueabi
    mkdir b
@@ -37,14 +40,17 @@
 Nyan-big
 --------
 
-Compiled based on information here:
-https://lists.denx.de/pipermail/u-boot/2015-March/209530.html
-https://git.collabora.com/cgit/user/tomeu/u-boot.git/commit/?h=nyan-big
-https://lists.denx.de/pipermail/u-boot/2017-May/289491.html
-https://github.com/chromeos-nvidia-androidtv/gnu-linux-on-acer-chromebook-13#copy-data-to-the-sd-card
+Compiled based on information here::
+
+   https://lists.denx.de/pipermail/u-boot/2015-March/209530.html
+   https://git.collabora.com/cgit/user/tomeu/u-boot.git/commit/?h=nyan-big
+   https://lists.denx.de/pipermail/u-boot/2017-May/289491.html
+   https://github.com/chromeos-nvidia-androidtv/gnu-linux-on-acer-chromebook-13#copy-data-to-the-sd-card
 
 1. Build U-Boot
 
+Steps::
+
    mkdir b
    make -j8 O=b/nyan-big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all
 
@@ -61,16 +67,21 @@
 
 3. Build and sign an image
 
-   ./b/nyan-big/tools/mkimage -f doc/chromium/nyan-big.its u-boot-chromium.fit
+Steps::
+
+   ./b/nyan-big/tools/mkimage -f doc/chromium/files/nyan-big.its u-boot-chromium.fit
    echo test >dummy.txt
-   vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \
-	--signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \
-	--version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
-	--bootloader dummy.txt --pack u-boot.kpart
+   vbutil_kernel --arch arm \
+     --keyblock doc/chromium/files/devkeys/kernel.keyblock \
+     --signprivate doc/chromium/files/devkeys/kernel_data_key.vbprivk \
+     --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
+     --bootloader dummy.txt --pack u-boot.kpart
 
 
 4. Prepare an SD card
 
+Steps::
+
    DISK=/dev/sdc   # Replace with your actual SD card device
    sudo cgpt create $DISK
    sudo cgpt add -b 34 -s 32768 -P 1 -S 1 -t kernel $DISK
@@ -80,6 +91,8 @@
 
 5. Write U-Boot to the SD card
 
+Steps::
+
    sudo dd if=u-boot.kpart of=/dev/sdc1; sync
 
 
@@ -90,7 +103,7 @@
 'enable_dev_usb_boot'. You only need to do this once.
 
 Reboot the device with the SD card inserted. Press Clrl-U at the developer
-mode screen. It should show something like the following on the display:
+mode screen. It should show something like the following on the display::
 
    U-Boot 2017.07-00637-g242eb42-dirty (May 22 2017 - 06:14:21 -0600)
 
@@ -104,9 +117,9 @@
 
 7. Known problems
 
-On the serial console the word MMC is chopped at the start of the line:
+On the serial console the word MMC is chopped at the start of the line::
 
-C:   sdhci@700b0000: 2, sdhci@700b0400: 1, sdhci@700b0600: 0
+   C:   sdhci@700b0000: 2, sdhci@700b0400: 1, sdhci@700b0600: 0
 
 This is likely due to some problem with change-over of the serial driver
 during relocation (or perhaps updating the clock setup in board_init()).
@@ -116,7 +129,7 @@
 
 To check that you copied the u-boot.its file correctly, use these commands.
 You should see that the data at 0x100 in u-boot-chromium.fit is the first few
-bytes of U-Boot:
+bytes of U-Boot::
 
    hd u-boot-chromium.fit |head -20
    ...
@@ -141,34 +154,39 @@
 
 Open include/configs/rk3288_common.h
 
-Change:
+Change::
 
-#define CONFIG_SYS_TEXT_BASE		0x00100000
+   #define CONFIG_SYS_TEXT_BASE		0x00100000
 
-to:
+to::
 
-#define CONFIG_SYS_TEXT_BASE		0x02000100
+   #define CONFIG_SYS_TEXT_BASE		0x02000100
 
 
 
 2. Build U-Boot
 
+Steps::
+
    mkdir b
    make -j8 O=b/chromebook_jerry CROSS_COMPILE=arm-linux-gnueabi- \
-	chromebook_jerry_defconfig all
+      chromebook_jerry_defconfig all
 
 
 3. See above
 
 4. Build and sign an image
 
+Steps::
+
    ./b/chromebook_jerry/tools/mkimage -f doc/chromium/chromebook_jerry.its \
-	u-boot-chromium.fit
+      u-boot-chromium.fit
    echo test >dummy.txt
-   vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \
-	--signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \
-	--version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
-	--bootloader dummy.txt --pack u-boot.kpart
+   vbutil_kernel --arch arm \
+      --keyblock doc/chromium/files/devkeys/kernel.keyblock \
+      --signprivate doc/chromium/files/devkeys/kernel_data_key.vbprivk \
+      --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
+      --bootloader dummy.txt --pack u-boot.kpart
 
 
 5. See above
@@ -182,7 +200,7 @@
 'enable_dev_usb_boot'. You only need to do this once.
 
 Reboot the device with the SD card inserted. Press Clrl-U at the developer
-mode screen. It should show something like the following on the display:
+mode screen. It should show something like the following on the display::
 
    U-Boot 2017.05-00649-g72acdbf-dirty (May 29 2017 - 14:57:05 -0600)
 
@@ -203,18 +221,18 @@
 
 
 Other notes
-===========
+-----------
 
 flashrom
---------
+~~~~~~~~
 
-   Used to make a backup of your firmware, or to replace it.
+Used to make a backup of your firmware, or to replace it.
 
-   See: https://www.chromium.org/chromium-os/packages/cros-flashrom
+See: https://www.chromium.org/chromium-os/packages/cros-flashrom
 
 
 coreboot
---------
+~~~~~~~~
 
 Coreboot itself is not designed to actually boot an OS. Instead, a program
 called Depthcharge is used. This originally came out of U-Boot and was then
diff --git a/doc/chromium/chromebook_jerry.its b/doc/chromium/files/chromebook_jerry.its
similarity index 100%
rename from doc/chromium/chromebook_jerry.its
rename to doc/chromium/files/chromebook_jerry.its
diff --git a/doc/chromium/devkeys/kernel.keyblock b/doc/chromium/files/devkeys/kernel.keyblock
similarity index 100%
rename from doc/chromium/devkeys/kernel.keyblock
rename to doc/chromium/files/devkeys/kernel.keyblock
Binary files differ
diff --git a/doc/chromium/devkeys/kernel_data_key.vbprivk b/doc/chromium/files/devkeys/kernel_data_key.vbprivk
similarity index 100%
rename from doc/chromium/devkeys/kernel_data_key.vbprivk
rename to doc/chromium/files/devkeys/kernel_data_key.vbprivk
Binary files differ
diff --git a/doc/chromium/nyan-big.its b/doc/chromium/files/nyan-big.its
similarity index 100%
rename from doc/chromium/nyan-big.its
rename to doc/chromium/files/nyan-big.its
diff --git a/doc/chromium/index.rst b/doc/chromium/index.rst
new file mode 100644
index 0000000..0722c25
--- /dev/null
+++ b/doc/chromium/index.rst
@@ -0,0 +1,14 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2020 Google LLC
+
+Chromium OS-specific doc
+========================
+
+This provides some information about Chromium OS and U-Boot.
+
+.. toctree::
+   :maxdepth: 2
+
+   overview
+   run_vboot
+   chainload
diff --git a/doc/chromium/overview.rst b/doc/chromium/overview.rst
new file mode 100644
index 0000000..5498ed9
--- /dev/null
+++ b/doc/chromium/overview.rst
@@ -0,0 +1,74 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2020 Google LLC
+
+Chromium OS Support in U-Boot
+=============================
+
+Introduction
+------------
+
+This describes how to use U-Boot with Chromium OS. Several options are
+available:
+
+   - Running U-Boot from the 'altfw' feature, which is available on selected
+     Chromebooks from 2019 onwards (initially Grunt). Press '1' from the
+     developer-mode screen to get into U-Boot. See here for details:
+     https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_mode.md
+
+   - Running U-Boot from the disk partition. This involves signing U-Boot and
+     placing it on the disk, for booting as a 'kernel'. See
+     :doc:`chainload` for information on this. This is the only
+     option on non-U-Boot Chromebooks from 2013 to 2018 and is somewhat
+     more involved.
+
+   - Running U-Boot with Chromium OS verified boot. This allows U-Boot to be
+     used instead of either or both of depthcharge (a bootloader which forked
+     from U-Boot in 2013) and coreboot. See :doc:`run_vboot` for more
+     information on this.
+
+   - Running U-Boot from coreboot. This allows U-Boot to run on more devices
+     since many of them only support coreboot as the bootloader and have
+     no bare-metal support in U-Boot. For this, use the 'coreboot' target.
+
+   - Running U-Boot and booting into a Chrome OS image, but without verified
+     boot. This can be useful for testing.
+
+
+Talks and documents
+-------------------
+
+Here is some material relevant to Chromium OS verified boot with U-Boot:
+
+   - "U-Boot with Chrome OS and firmware packaging"
+
+     - Author: Simon Glass
+     - Presented at Open Source Firmware Conference 2018, Erlangen
+     - Describes the work in progress as at the end of 2018
+     - Slides at `OSFC <https://2018.osfc.io/uploads/talk/paper/26/U-Boot_with_Chrome_OS_and_firmware_packaging.pdf>`_
+     - Video on `Youtube <https://www.youtube.com/watch?v=1jknxUvmwpo>`_
+
+   - "Verified Boot in Chrome OS and how to make it work for you"
+
+     - Author: Simon Glass
+     - Presented at ELCE 2013, Edinburgh
+     - Describes the original 2013 implementation as shipped on snow (first
+       `ARM Chromebook was a Samsung Chromebook <https://www.cnet.com/products/samsung-series-3-chromebook-xe303c12-11-6-exynos-5250-2-gb-ram-16-gb-ssd-bilingual-english-french/>`_
+       with Samsung Exynos5250 `review <https://www.cnet.com/reviews/samsung-chromebook-series-3-review/>`_),
+       spring (`HP Chromebook 11 <https://www.cnet.com/products/hp-chromebook-11-g2-11-6-exynos-5250-4-gb-ram-16-gb-emmc/>`_)
+       and pit/pi (`Samsung Chromebook 2 <https://www.cnet.com/products/samsung-chromebook-2-xe503c12-11-6-exynos-5-octa-4-gb-ram-16-gb-ssd/>`_
+       with Exynos 5 Octa 5420 in 2014).
+     - Slides at `Google research <https://research.google/pubs/pub42038/>`_
+     - Video at `Youtube <https://www.youtube.com/watch?v=kdpZC9jFzZA>`_
+
+   - "Chrome University 2018: Chrome OS Firmware and Verified Boot 201"
+
+     - Author: Duncan Laurie
+     - Describes Chrome OS firmware as of 2018 and includes a wide range of
+       topics. This has no U-Boot information, but does cover coreboot and also
+       talks about the Chrome OS EC and Security chip. This is probably the
+       best introduction talk.
+     - Video at `YouTube <https://www.youtube.com/watch?v=WY2sWpuda2g>`_
+
+   - `Chromium OS U-Boot <https://www.chromium.org/developers/u-boot>`_
+
+   - `Firmware porting Guide <https://www.chromium.org/chromium-os/firmware-porting-guide>`_
diff --git a/doc/README.chromium b/doc/chromium/run_vboot.rst
similarity index 67%
rename from doc/README.chromium
rename to doc/chromium/run_vboot.rst
index 75f2f24..41b4f63 100644
--- a/doc/README.chromium
+++ b/doc/chromium/run_vboot.rst
@@ -1,42 +1,14 @@
-Chromium OS Support in U-Boot
-=============================
-
-Introduction
-------------
-
-This describes how to use U-Boot with Chromium OS. Several options are
-available:
-
-   - Running U-Boot from the 'altfw' feature, which is available on selected
-        Chromebooks from 2019 onwards (initially Grunt). Press '1' from the
-        developer-mode screen to get into U-Boot. See here for details:
-        https://sites.google.com/a/chromium.org/dev/chromium-os/poking-around-your-chrome-os-device?pli=1
-
-   - Running U-Boot from the disk partition. This involves signing U-Boot and
-        placing it on the disk, for booting as a 'kernel'. See
-        README.chromium-chainload for information on this. This is the only
-        option on non-U-Boot Chromebooks from 2013 to 2018 and is somewhat
-        more involved.
-
-   - Running U-Boot with Chromium OS verified boot. This allows U-Boot to be
-        used instead of either or both of depthcharge (a bootloader which forked
-        from U-Boot in 2013) and coreboot. See below for more information on
-        this.
-
-   - Running U-Boot from coreboot. This allows U-Boot to run on more devices
-        since many of them only support coreboot as the bootloader and have
-        no bare-metal support in U-Boot. For this, use the 'coreboot' target.
-
-   - Running U-Boot and booting into a Chrome OS image, but without verified
-        boot. This can be useful for testing.
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2020 Google LLC
+.. sectionauthor:: Simon Glass <sjg@chromium.org>
 
 
-U-Boot with Chromium OS verified boot
--------------------------------------
+Running U-Boot with Chromium OS verified boot
+=============================================
 
-To obtain:
+To obtain::
 
-   git clone https://github.com/sglass68/u-boot.git
+   git clone https://github.com/sjg20/u-boot.git
    cd u-boot
    git checkout cros-master
 
@@ -46,28 +18,35 @@
    git checkout 45964294
    #  futility: updater: Correct output version for Snow
 
-To build for sandbox:
+To build for sandbox::
 
    UB=/tmp/b/chromeos_sandbox    # U-Boot build directory
    cd u-boot
    make O=$UB chromeos_sandbox_defconfig
    make O=$UB -j20 -s VBOOT_SOURCE=/path/to/vboot_reference \
-	MAKEFLAGS_VBOOT=DEBUG=1 QUIET=1
+     MAKEFLAGS_VBOOT=DEBUG=1 QUIET=1
 
 Replace sandbox with another supported target.
 
 This produces $UB/image.bin which contains the firmware binaries in a SPI
 flash image.
 
-To run on sandbox:
+To run on sandbox::
 
+   CROS=~/cosarm
+   IMG=$CROS/src/build/images/coral/latest/chromiumos_image.bin
    $UB/tpl/u-boot-tpl -d $UB/u-boot.dtb.out \
-	-L6 -c "host bind 0 $CROS/src/build/images/cheza/latest/chromiumos_image.bin; vboot go auto" \
-	-l -w -s state.dtb -r
+     -L6 -c "host bind 0 $IMG; vboot go auto" \
+     -l -w -s state.dtb -r -n -m $UB/ram
+
+   $UB/tpl/u-boot-tpl -d $UB/u-boot.dtb.out -L6 -l \
+     -c "host bind 0 $IMG; vboot go auto" -w -s $UB/state.dtb -r -n -m $UB/mem
+
 
 To run on other boards:
-   Install image.bin in the SPI flash of your device
-   Boot your system
+
+   - Install image.bin in the SPI flash of your device
+   - Boot your system
 
 
 Sandbox
@@ -83,7 +62,7 @@
 phases into state.dtb and will automatically ensure that memory is shared
 between all phases. TPL will jump to SPL and then on to U-Boot proper.
 
-It is possible to run with debugging on, e.g.
+It is possible to run with debugging on, e.g.::
 
    gdb --args $UB/tpl/u-boot-tpl -d ....
 
@@ -95,7 +74,7 @@
 -----
 
 Basic support is available for samus, using the chromeos_samus target. If you
-have an em100, use:
+have an em100, use::
 
    sudo em100 -s -c W25Q128FW -d $UB/image.bin -t -r
 
@@ -119,11 +98,20 @@
 
 Several uclasses are provided in cros/:
 
-	UCLASS_CROS_AUX_FW		Chrome OS auxiliary firmware
-	UCLASS_CROS_FWSTORE		Chrome OS firmware storage
-	UCLASS_CROS_NVDATA		Chrome OS non-volatile data device
-	UCLASS_CROS_VBOOT_EC		Chrome OS vboot EC operations
-	UCLASS_CROS_VBOOT_FLAG		Chrome OS verified boot flag
+UCLASS_CROS_AUX_FW
+   Chrome OS auxiliary firmware
+
+UCLASS_CROS_FWSTORE
+   Chrome OS firmware storage
+
+UCLASS_CROS_NVDATA
+   Chrome OS non-volatile data device
+
+UCLASS_CROS_VBOOT_EC
+   Chrome OS vboot EC operations
+
+UCLASS_CROS_VBOOT_FLAG
+   Chrome OS verified boot flag
 
 The existing UCLASS_CROS_EC is also used.
 
@@ -181,7 +169,7 @@
 U-Boot without Chromium OS verified boot
 ----------------------------------------
 
-The following script can be used to boot a Chrome OS image on coral:
+The following script can be used to boot a Chrome OS image on coral::
 
    # Read the image header and obtain the address of the kernel
    # The offset 4f0 is defined by verified boot and may change for other
@@ -213,6 +201,4 @@
 Get the full ACPI tables working with Coral
 
 
-Simon Glass
-sjg@chromium.org
 7 October 2018
diff --git a/doc/driver-model/bind.rst b/doc/develop/driver-model/bind.rst
similarity index 100%
rename from doc/driver-model/bind.rst
rename to doc/develop/driver-model/bind.rst
diff --git a/doc/driver-model/debugging.rst b/doc/develop/driver-model/debugging.rst
similarity index 100%
rename from doc/driver-model/debugging.rst
rename to doc/develop/driver-model/debugging.rst
diff --git a/doc/driver-model/design.rst b/doc/develop/driver-model/design.rst
similarity index 88%
rename from doc/driver-model/design.rst
rename to doc/develop/driver-model/design.rst
index 4e5cecb..b0e6337 100644
--- a/doc/driver-model/design.rst
+++ b/doc/develop/driver-model/design.rst
@@ -900,6 +900,139 @@
 The dm_remove_devices_flags() function can be used to remove devices based on
 their driver flags.
 
+
+Error codes
+-----------
+
+Driver model tries to use errors codes in a consistent way, as follows:
+
+\-EAGAIN
+   Try later, e.g. dependencies not ready
+
+\-EINVAL
+   Invalid argument, such as `dev_read_...()` failed or any other
+   devicetree-related access. Also used when a driver method is passed an
+   argument it considers invalid or does not support.
+
+\-EIO
+   Failed to perform an I/O operation. This is used when a local device
+   (i.e. part of the SOC) does not work as expected. Use -EREMOTEIO for
+   failures to talk to a separate device, e.g. over an I2C or SPI
+   channel.
+
+\-ENODEV
+   Do not bind the device. This should not be used to indicate an
+   error probing the device or for any other purpose, lest driver model get
+   confused. Using `-ENODEV` inside a driver method makes no sense, since
+   clearly there is a device.
+
+\-ENOENT
+   Entry or object not found. This is used when a device, file or directory
+   cannot be found (e.g. when looked up by name), It can also indicate a
+   missing devicetree subnode.
+
+\-ENOMEM
+   Out of memory
+
+\-ENOSPC
+   Ran out of space (e.g. in a buffer or limited-size array)
+
+\-ENOSYS
+   Function not implemented. This is returned by uclasses where the driver does
+   not implement a particular method. It can also be returned by drivers when
+   a particular sub-method is not implemented. This is widely checked in the
+   wider code base, where a feature may or may not be compiled into U-Boot. It
+   indicates that the feature is not available, but this is often just normal
+   operation. Please do not use -ENOSUPP. If an incorrect or unknown argument
+   is provided to a method (e.g. an unknown clock ID), return -EINVAL.
+
+\-ENXIO
+   Couldn't find device/address. This is used when a device or address
+   could not be obtained or is not valid. It is often used to indicate a
+   different type of problem, if -ENOENT is already used for something else in
+   the driver.
+
+\-EPERM
+   This is -1 so some older code may use it as a generic error. This indicates
+   that an operation is not permitted, e.g. a security violation or policy
+   constraint. It is returned internally when binding devices before relocation,
+   if the device is not marked for pre-relocation use.
+
+\-EPFNOSUPPORT
+   Missing uclass. This is deliberately an uncommon error code so that it can
+   easily be distinguished. If you see this very early in U-Boot, it means that
+   a device exists with a particular uclass but the uclass does not (mostly
+   likely because it is not compiled in). Enable DEBUG in uclass.c or lists.c
+   to see which uclass ID or driver is causing the problem.
+
+\-EREMOTEIO
+   This indicates an error in talking to a peripheral over a comms link, such
+   as I2C or SPI. It might indicate that the device is not present or is not
+   responding as expected.
+
+\-ETIMEDOUT
+   Hardware access or some other operation has timed out. This is used where
+   there is an expected time of response and that was exceeded by enough of
+   a margin that there is probably something wrong.
+
+
+Less common ones:
+
+\-ECOMM
+   Not widely used, but similar to -EREMOTEIO. Can be useful as a secondary
+   error to distinguish the problem from -EREMOTEIO.
+
+\-EKEYREJECTED
+   Attempt to remove a device which does not match the removal flags. See
+   device_remove().
+
+\-EILSEQ
+   Devicetree read failure, specifically trying to read a string index which
+   does not exist, in a string-listg property
+
+\-ENOEXEC
+   Attempt to use a uclass method on a device not in that uclass. This is
+   seldom checked at present, since it is generally a programming error and a
+   waste of code space. A DEBUG-only check would be useful here.
+
+\-ENODATA
+   Devicetree read error, where a property exists but has no data associated
+   with it
+
+\-EOVERFLOW
+   Devicetree read error, where the property is longer than expected
+
+\-EPROBE_DEFER
+   Attempt to remove a non-vital device when the removal flags indicate that
+   only vital devices should be removed
+
+\-ERANGE
+   Returned by regmap functions when arguments are out of range. This can be
+   useful for disinguishing regmap errors from other errors obtained while
+   probing devices.
+
+Drivers should use the same conventions so that things function as expected.
+In particular, if a driver fails to probe, or a uclass operation fails, the
+error code is the primary way to indicate what actually happened.
+
+Printing error messages in drivers is discouraged due to code size bloat and
+since it can result in messages appearing in normal operation. For example, if
+a command tries two different devices and uses whichever one probes correctly,
+we don't want an error message displayed, even if the command itself might show
+a warning or informational message. Ideally, messages in drivers should only be
+displayed when debugging, e.g. by using log_debug() although in extreme cases
+log_warning() or log_error() may be used.
+
+Error messages can be logged using `log_msg_ret()`, so that enabling
+`CONFIG_LOG` and `CONFIG_LOG_ERROR_RETURN` shows a trace of error codes returned
+through the call stack. That can be a handy way of quickly figuring out where
+an error occurred. Get into the habit of return errors with
+`return log_msg_ret("here", ret)` instead of just `return ret`. The string
+just needs to be long enough to find in a single function, since a log record
+stores (and can print with `CONFIG_LOGF_FUNC`) the function where it was
+generated.
+
+
 Data Structures
 ---------------
 
diff --git a/doc/driver-model/ethernet.rst b/doc/develop/driver-model/ethernet.rst
similarity index 100%
rename from doc/driver-model/ethernet.rst
rename to doc/develop/driver-model/ethernet.rst
diff --git a/doc/driver-model/fdt-fixup.rst b/doc/develop/driver-model/fdt-fixup.rst
similarity index 100%
rename from doc/driver-model/fdt-fixup.rst
rename to doc/develop/driver-model/fdt-fixup.rst
diff --git a/doc/driver-model/fs_firmware_loader.rst b/doc/develop/driver-model/fs_firmware_loader.rst
similarity index 100%
rename from doc/driver-model/fs_firmware_loader.rst
rename to doc/develop/driver-model/fs_firmware_loader.rst
diff --git a/doc/driver-model/i2c-howto.rst b/doc/develop/driver-model/i2c-howto.rst
similarity index 100%
rename from doc/driver-model/i2c-howto.rst
rename to doc/develop/driver-model/i2c-howto.rst
diff --git a/doc/driver-model/index.rst b/doc/develop/driver-model/index.rst
similarity index 68%
rename from doc/driver-model/index.rst
rename to doc/develop/driver-model/index.rst
index c9faf0a..fd4575d 100644
--- a/doc/driver-model/index.rst
+++ b/doc/develop/driver-model/index.rst
@@ -3,6 +3,10 @@
 Driver Model
 ============
 
+The following holds information on the U-Boot device driver framework:
+driver-model, including the design details of itself and several driver
+subsystems
+
 .. toctree::
    :maxdepth: 2
 
diff --git a/doc/driver-model/livetree.rst b/doc/develop/driver-model/livetree.rst
similarity index 100%
rename from doc/driver-model/livetree.rst
rename to doc/develop/driver-model/livetree.rst
diff --git a/doc/driver-model/migration.rst b/doc/develop/driver-model/migration.rst
similarity index 100%
rename from doc/driver-model/migration.rst
rename to doc/develop/driver-model/migration.rst
diff --git a/doc/develop/driver-model/of-plat.rst b/doc/develop/driver-model/of-plat.rst
new file mode 100644
index 0000000..74f1932
--- /dev/null
+++ b/doc/develop/driver-model/of-plat.rst
@@ -0,0 +1,913 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Compiled-in Device Tree / Platform Data
+=======================================
+
+
+Introduction
+------------
+
+Device tree is the standard configuration method in U-Boot. It is used to
+define what devices are in the system and provide configuration information
+to these devices.
+
+The overhead of adding devicetree access to U-Boot is fairly modest,
+approximately 3KB on Thumb 2 (plus the size of the DT itself). This means
+that in most cases it is best to use devicetree for configuration.
+
+However there are some very constrained environments where U-Boot needs to
+work. These include SPL with severe memory limitations. For example, some
+SoCs require a 16KB SPL image which must include a full MMC stack. In this
+case the overhead of devicetree access may be too great.
+
+It is possible to create platform data manually by defining C structures
+for it, and reference that data in a `U_BOOT_DRVINFO()` declaration. This
+bypasses the use of devicetree completely, effectively creating a parallel
+configuration mechanism. But it is an available option for SPL.
+
+As an alternative, the 'of-platdata' feature is provided. This converts the
+devicetree contents into C code which can be compiled into the SPL binary.
+This saves the 3KB of code overhead and perhaps a few hundred more bytes due
+to more efficient storage of the data.
+
+
+How it works
+------------
+
+The feature is enabled by CONFIG OF_PLATDATA. This is only available in
+SPL/TPL and should be tested with:
+
+.. code-block:: c
+
+    #if CONFIG_IS_ENABLED(OF_PLATDATA)
+
+A tool called 'dtoc' converts a devicetree file either into a set of
+struct declarations, one for each compatible node, and a set of
+`U_BOOT_DRVINFO()` declarations along with the actual platform data for each
+device. As an example, consider this MMC node:
+
+.. code-block:: none
+
+    sdmmc: dwmmc@ff0c0000 {
+            compatible = "rockchip,rk3288-dw-mshc";
+            clock-freq-min-max = <400000 150000000>;
+            clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
+                     <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
+            clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+            fifo-depth = <0x100>;
+            interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+            reg = <0xff0c0000 0x4000>;
+            bus-width = <4>;
+            cap-mmc-highspeed;
+            cap-sd-highspeed;
+            card-detect-delay = <200>;
+            disable-wp;
+            num-slots = <1>;
+            pinctrl-names = "default";
+            pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>;
+                vmmc-supply = <&vcc_sd>;
+                status = "okay";
+                u-boot,dm-pre-reloc;
+        };
+
+
+Some of these properties are dropped by U-Boot under control of the
+CONFIG_OF_SPL_REMOVE_PROPS option. The rest are processed. This will produce
+the following C struct declaration:
+
+.. code-block:: c
+
+    struct dtd_rockchip_rk3288_dw_mshc {
+            fdt32_t         bus_width;
+            bool            cap_mmc_highspeed;
+            bool            cap_sd_highspeed;
+            fdt32_t         card_detect_delay;
+            fdt32_t         clock_freq_min_max[2];
+            struct phandle_1_arg clocks[4];
+            bool            disable_wp;
+            fdt32_t         fifo_depth;
+            fdt32_t         interrupts[3];
+            fdt32_t         num_slots;
+            fdt32_t         reg[2];
+            fdt32_t         vmmc_supply;
+    };
+
+and the following device declarations:
+
+.. code-block:: c
+
+    /* Node /clock-controller@ff760000 index 0 */
+    ...
+
+    /* Node /dwmmc@ff0c0000 index 2 */
+    static struct dtd_rockchip_rk3288_dw_mshc dtv_dwmmc_at_ff0c0000 = {
+            .fifo_depth             = 0x100,
+            .cap_sd_highspeed       = true,
+            .interrupts             = {0x0, 0x20, 0x4},
+            .clock_freq_min_max     = {0x61a80, 0x8f0d180},
+            .vmmc_supply            = 0xb,
+            .num_slots              = 0x1,
+            .clocks                 = {{0, 456},
+                                       {0, 68},
+                                       {0, 114},
+                                       {0, 118}},
+            .cap_mmc_highspeed      = true,
+            .disable_wp             = true,
+            .bus_width              = 0x4,
+            .u_boot_dm_pre_reloc    = true,
+            .reg                    = {0xff0c0000, 0x4000},
+            .card_detect_delay      = 0xc8,
+    };
+
+    U_BOOT_DRVINFO(dwmmc_at_ff0c0000) = {
+            .name           = "rockchip_rk3288_dw_mshc",
+            .plat       = &dtv_dwmmc_at_ff0c0000,
+            .plat_size  = sizeof(dtv_dwmmc_at_ff0c0000),
+            .parent_idx     = -1,
+    };
+
+The device is then instantiated at run-time and the platform data can be
+accessed using:
+
+.. code-block:: c
+
+    struct udevice *dev;
+    struct dtd_rockchip_rk3288_dw_mshc *plat = dev_get_plat(dev);
+
+This avoids the code overhead of converting the devicetree data to
+platform data in the driver. The `of_to_plat()` method should
+therefore do nothing in such a driver.
+
+Note that for the platform data to be matched with a driver, the 'name'
+property of the `U_BOOT_DRVINFO()` declaration has to match a driver declared
+via `U_BOOT_DRIVER()`. This effectively means that a `U_BOOT_DRIVER()` with a
+'name' corresponding to the devicetree 'compatible' string (after converting
+it to a valid name for C) is needed, so a dedicated driver is required for
+each 'compatible' string.
+
+In order to make this a bit more flexible, the `DM_DRIVER_ALIAS()` macro can be
+used to declare an alias for a driver name, typically a 'compatible' string.
+This macro produces no code, but is used by dtoc tool. It must be located in the
+same file as its associated driver, ideally just after it.
+
+The parent_idx is the index of the parent `driver_info` structure within its
+linker list (instantiated by the `U_BOOT_DRVINFO()` macro). This is used to
+support `dev_get_parent()`.
+
+During the build process dtoc parses both `U_BOOT_DRIVER()` and
+`DM_DRIVER_ALIAS()` to build a list of valid driver names and driver aliases.
+If the 'compatible' string used for a device does not not match a valid driver
+name, it will be checked against the list of driver aliases in order to get the
+right driver name to use. If in this step there is no match found a warning is
+issued to avoid run-time failures.
+
+Where a node has multiple compatible strings, dtoc generates a `#define` to
+make them equivalent, e.g.:
+
+.. code-block:: c
+
+    #define dtd_rockchip_rk3299_dw_mshc dtd_rockchip_rk3288_dw_mshc
+
+
+Converting of-platdata to a useful form
+---------------------------------------
+
+Of course it would be possible to use the of-platdata directly in your driver
+whenever configuration information is required. However this means that the
+driver will not be able to support devicetree, since the of-platdata
+structure is not available when devicetree is used. It would make no sense
+to use this structure if devicetree were available, since the structure has
+all the limitations metioned in caveats below.
+
+Therefore it is recommended that the of-platdata structure should be used
+only in the `probe()` method of your driver. It cannot be used in the
+`of_to_plat()` method since this is not called when platform data is
+already present.
+
+
+How to structure your driver
+----------------------------
+
+Drivers should always support devicetree as an option. The of-platdata
+feature is intended as a add-on to existing drivers.
+
+Your driver should convert the plat struct in its `probe()` method. The
+existing devicetree decoding logic should be kept in the
+`of_to_plat()` method and wrapped with `#if`.
+
+For example:
+
+.. code-block:: c
+
+    #include <dt-structs.h>
+
+    struct mmc_plat {
+    #if CONFIG_IS_ENABLED(OF_PLATDATA)
+            /* Put this first since driver model will copy the data here */
+            struct dtd_mmc dtplat;
+    #endif
+            /*
+             * Other fields can go here, to be filled in by decoding from
+             * the devicetree (or the C structures when of-platdata is used).
+             */
+            int fifo_depth;
+    };
+
+    static int mmc_of_to_plat(struct udevice *dev)
+    {
+    #if !CONFIG_IS_ENABLED(OF_PLATDATA)
+            /* Decode the devicetree data */
+            struct mmc_plat *plat = dev_get_plat(dev);
+            const void *blob = gd->fdt_blob;
+            int node = dev_of_offset(dev);
+
+            plat->fifo_depth = fdtdec_get_int(blob, node, "fifo-depth", 0);
+    #endif
+
+            return 0;
+    }
+
+    static int mmc_probe(struct udevice *dev)
+    {
+            struct mmc_plat *plat = dev_get_plat(dev);
+
+    #if CONFIG_IS_ENABLED(OF_PLATDATA)
+            /* Decode the of-platdata from the C structures */
+            struct dtd_mmc *dtplat = &plat->dtplat;
+
+            plat->fifo_depth = dtplat->fifo_depth;
+    #endif
+            /* Set up the device from the plat data */
+            writel(plat->fifo_depth, ...)
+    }
+
+    static const struct udevice_id mmc_ids[] = {
+            { .compatible = "vendor,mmc" },
+            { }
+    };
+
+    U_BOOT_DRIVER(mmc_drv) = {
+            .name           = "mmc_drv",
+            .id             = UCLASS_MMC,
+            .of_match       = mmc_ids,
+            .of_to_plat = mmc_of_to_plat,
+            .probe          = mmc_probe,
+            .priv_auto = sizeof(struct mmc_priv),
+            .plat_auto = sizeof(struct mmc_plat),
+    };
+
+    DM_DRIVER_ALIAS(mmc_drv, vendor_mmc) /* matches compatible string */
+
+Note that `struct mmc_plat` is defined in the C file, not in a header. This
+is to avoid needing to include dt-structs.h in a header file. The idea is to
+keep the use of each of-platdata struct to the smallest possible code area.
+There is just one driver C file for each struct, that can convert from the
+of-platdata struct to the standard one used by the driver.
+
+In the case where SPL_OF_PLATDATA is enabled, `plat_auto` is
+still used to allocate space for the platform data. This is different from
+the normal behaviour and is triggered by the use of of-platdata (strictly
+speaking it is a non-zero `plat_size` which triggers this).
+
+The of-platdata struct contents is copied from the C structure data to the
+start of the newly allocated area. In the case where devicetree is used,
+the platform data is allocated, and starts zeroed. In this case the
+`of_to_plat()` method should still set up the platform data (and the
+of-platdata struct will not be present).
+
+SPL must use either of-platdata or devicetree. Drivers cannot use both at
+the same time, but they must support devicetree. Supporting of-platdata is
+optional.
+
+The devicetree becomes inaccessible when CONFIG_SPL_OF_PLATDATA is enabled,
+since the devicetree access code is not compiled in. A corollary is that
+a board can only move to using of-platdata if all the drivers it uses support
+it. There would be little point in having some drivers require the device
+tree data, since then libfdt would still be needed for those drivers and
+there would be no code-size benefit.
+
+
+Build-time instantiation
+------------------------
+
+Even with of-platdata there is a fair amount of code required in driver model.
+It is possible to have U-Boot handle the instantiation of devices at build-time,
+so avoiding the need for the `device_bind()` code and some parts of
+`device_probe()`.
+
+The feature is enabled by CONFIG_OF_PLATDATA_INST.
+
+Here is an example device, as generated by dtoc::
+
+   /*
+    * Node /serial index 6
+    * driver sandbox_serial parent root_driver
+   */
+
+   #include <asm/serial.h>
+   struct sandbox_serial_plat __attribute__ ((section (".priv_data")))
+      _sandbox_serial_plat_serial = {
+      .dtplat = {
+         .sandbox_text_colour   = "cyan",
+      },
+   };
+   #include <asm/serial.h>
+   u8 _sandbox_serial_priv_serial[sizeof(struct sandbox_serial_priv)]
+      __attribute__ ((section (".priv_data")));
+   #include <serial.h>
+   u8 _sandbox_serial_uc_priv_serial[sizeof(struct serial_dev_priv)]
+      __attribute__ ((section (".priv_data")));
+
+   DM_DEVICE_INST(serial) = {
+      .driver     = DM_DRIVER_REF(sandbox_serial),
+      .name       = "sandbox_serial",
+      .plat_      = &_sandbox_serial_plat_serial,
+      .priv_      = _sandbox_serial_priv_serial,
+      .uclass     = DM_UCLASS_REF(serial),
+      .uclass_priv_ = _sandbox_serial_uc_priv_serial,
+      .uclass_node   = {
+         .prev = &DM_UCLASS_REF(serial)->dev_head,
+         .next = &DM_UCLASS_REF(serial)->dev_head,
+      },
+      .child_head   = {
+         .prev = &DM_DEVICE_REF(serial)->child_head,
+         .next = &DM_DEVICE_REF(serial)->child_head,
+      },
+      .sibling_node   = {
+         .prev = &DM_DEVICE_REF(i2c_at_0)->sibling_node,
+         .next = &DM_DEVICE_REF(spl_test)->sibling_node,
+      },
+      .seq_ = 0,
+   };
+
+Here is part of the driver, for reference::
+
+   static const struct udevice_id sandbox_serial_ids[] = {
+      { .compatible = "sandbox,serial" },
+      { }
+   };
+
+   U_BOOT_DRIVER(sandbox_serial) = {
+      .name   = "sandbox_serial",
+      .id   = UCLASS_SERIAL,
+      .of_match    = sandbox_serial_ids,
+      .of_to_plat  = sandbox_serial_of_to_plat,
+      .plat_auto   = sizeof(struct sandbox_serial_plat),
+      .priv_auto   = sizeof(struct sandbox_serial_priv),
+      .probe = sandbox_serial_probe,
+      .remove = sandbox_serial_remove,
+      .ops   = &sandbox_serial_ops,
+      .flags = DM_FLAG_PRE_RELOC,
+   };
+
+
+The `DM_DEVICE_INST()` macro declares a struct udevice so you can see that the
+members are from that struct. The private data is declared immediately above,
+as `_sandbox_serial_priv_serial`, so there is no need for run-time memory
+allocation. The #include lines are generated as well, since dtoc searches the
+U-Boot source code for the definition of `struct sandbox_serial_priv` and adds
+the relevant header so that the code will compile without errors.
+
+The `plat_` member is set to the dtv data which is declared immediately above
+the device. This is similar to how it would look without of-platdata-inst, but
+node that the `dtplat` member inside is part of the wider
+`_sandbox_serial_plat_serial` struct. This is because the driver declares its
+own platform data, and the part generated by dtoc can only be a portion of it.
+The `dtplat` part is always first in the struct. If the device has no
+`.plat_auto` field, then a simple dtv struct can be used as with this example::
+
+   static struct dtd_sandbox_clk dtv_clk_sbox = {
+      .assigned_clock_rates   = 0x141,
+      .assigned_clocks   = {0x7, 0x3},
+   };
+
+   #include <asm/clk.h>
+   u8 _sandbox_clk_priv_clk_sbox[sizeof(struct sandbox_clk_priv)]
+      __attribute__ ((section (".priv_data")));
+
+   DM_DEVICE_INST(clk_sbox) = {
+      .driver    = DM_DRIVER_REF(sandbox_clk),
+      .name      = "sandbox_clk",
+      .plat_     = &dtv_clk_sbox,
+
+Here is part of the driver, for reference::
+
+   static const struct udevice_id sandbox_clk_ids[] = {
+      { .compatible = "sandbox,clk" },
+      { }
+   };
+
+   U_BOOT_DRIVER(sandbox_clk) = {
+      .name       = "sandbox_clk",
+      .id         = UCLASS_CLK,
+      .of_match   = sandbox_clk_ids,
+      .ops        = &sandbox_clk_ops,
+      .probe      = sandbox_clk_probe,
+      .priv_auto  = sizeof(struct sandbox_clk_priv),
+   };
+
+
+You can see that `dtv_clk_sbox` just has the devicetree contents and there is
+no need for the `dtplat` separation, since the driver has no platform data of
+its own, besides that provided by the devicetree (i.e. no `.plat_auto` field).
+
+The doubly linked lists are handled by explicitly declaring the value of each
+node, as you can see with the `.prev` and `.next` values in the example above.
+Since dtoc knows the order of devices it can link them into the appropriate
+lists correctly.
+
+One of the features of driver model is the ability for a uclass to have a
+small amount of private data for each device in that uclass. This is used to
+provide a generic data structure that the uclass can use for all devices, thus
+allowing generic features to be implemented in common code. An example is I2C,
+which stores the bus speed there.
+
+Similarly, parent devices can have data associated with each of their children.
+This is used to provide information common to all children of a particular bus.
+For an I2C bus, this is used to store the I2C address of each child on the bus.
+
+This is all handled automatically by dtoc::
+
+   #include <asm/i2c.h>
+   u8 _sandbox_i2c_priv_i2c_at_0[sizeof(struct sandbox_i2c_priv)]
+      __attribute__ ((section (".priv_data")));
+   #include <i2c.h>
+   u8 _sandbox_i2c_uc_priv_i2c_at_0[sizeof(struct dm_i2c_bus)]
+      __attribute__ ((section (".priv_data")));
+
+   DM_DEVICE_INST(i2c_at_0) = {
+      .driver      = DM_DRIVER_REF(sandbox_i2c),
+      .name      = "sandbox_i2c",
+      .plat_   = &dtv_i2c_at_0,
+      .priv_      = _sandbox_i2c_priv_i2c_at_0,
+      .uclass   = DM_UCLASS_REF(i2c),
+      .uclass_priv_ = _sandbox_i2c_uc_priv_i2c_at_0,
+     ...
+
+Part of driver, for reference::
+
+   static const struct udevice_id sandbox_i2c_ids[] = {
+      { .compatible = "sandbox,i2c" },
+      { }
+   };
+
+   U_BOOT_DRIVER(sandbox_i2c) = {
+      .name   = "sandbox_i2c",
+      .id   = UCLASS_I2C,
+      .of_match = sandbox_i2c_ids,
+      .ops   = &sandbox_i2c_ops,
+      .priv_auto   = sizeof(struct sandbox_i2c_priv),
+   };
+
+Part of I2C uclass, for reference::
+
+   UCLASS_DRIVER(i2c) = {
+      .id         = UCLASS_I2C,
+      .name       = "i2c",
+      .flags      = DM_UC_FLAG_SEQ_ALIAS,
+      .post_bind  = i2c_post_bind,
+      .pre_probe  = i2c_pre_probe,
+      .post_probe = i2c_post_probe,
+      .per_device_auto   = sizeof(struct dm_i2c_bus),
+      .per_child_plat_auto   = sizeof(struct dm_i2c_chip),
+      .child_post_bind = i2c_child_post_bind,
+   };
+
+Here, `_sandbox_i2c_uc_priv_i2c_at_0` is required by the uclass but is declared
+in the device, as required by driver model. The required header file is included
+so that the code will compile without errors. A similar mechanism is used for
+child devices, but is not shown by this example.
+
+It would not be that useful to avoid binding devices but still need to allocate
+uclasses at runtime. So dtoc generates uclass instances as well::
+
+   struct list_head uclass_head = {
+      .prev = &DM_UCLASS_REF(serial)->sibling_node,
+      .next = &DM_UCLASS_REF(clk)->sibling_node,
+   };
+
+   DM_UCLASS_INST(clk) = {
+      .uc_drv      = DM_UCLASS_DRIVER_REF(clk),
+      .sibling_node   = {
+         .prev = &uclass_head,
+         .next = &DM_UCLASS_REF(i2c)->sibling_node,
+      },
+      .dev_head   = {
+         .prev = &DM_DEVICE_REF(clk_sbox)->uclass_node,
+         .next = &DM_DEVICE_REF(clk_fixed)->uclass_node,
+      },
+   };
+
+At the top is the list head. Driver model uses this on start-up, instead of
+creating its own.
+
+Below that are a set of `DM_UCLASS_INST()` macros, each declaring a
+`struct uclass`. The doubly linked lists work as for devices.
+
+All private data is placed into a `.priv_data` section so that it is contiguous
+in the resulting output binary.
+
+
+Indexes
+-------
+
+U-Boot stores drivers, devices and many other things in linker_list structures.
+These are sorted by name, so dtoc knows the order that they will appear when
+the linker runs. Each driver_info / udevice is referenced by its index in the
+linker_list array, called 'idx' in the code.
+
+When CONFIG_OF_PLATDATA_INST is enabled, idx is the udevice index, otherwise it
+is the driver_info index. In either case, indexes are used to reference devices
+using device_get_by_ofplat_idx(). This allows phandles to work as expected.
+
+
+Phases
+------
+
+U-Boot operates in several phases, typically TPL, SPL and U-Boot proper.
+The latter does not use dtoc.
+
+In some rare cases different drivers are used for two phases. For example,
+in TPL it may not be necessary to use the full PCI subsystem, so a simple
+driver can be used instead.
+
+This works in the build system simply by compiling in one driver or the
+other (e.g. PCI driver + uclass for SPL; simple_bus for TPL). But dtoc has
+no way of knowing which code is compiled in for which phase, since it does
+not inspect Makefiles or dependency graphs.
+
+So to make this work for dtoc, we need to be able to explicitly mark
+drivers with their phase. This is done by adding a macro to the driver::
+
+   /* code in tpl.c only compiled into TPL */
+   U_BOOT_DRIVER(pci_x86) = {
+      .name   = "pci_x86",
+      .id   = UCLASS_SIMPLE_BUS,
+      .of_match = of_match_ptr(tpl_fake_pci_ids),
+      DM_PHASE(tpl)
+   };
+
+
+   /* code in pci_x86.c compiled into SPL and U-Boot proper */
+   U_BOOT_DRIVER(pci_x86) = {
+      .name   = "pci_x86",
+      .id   = UCLASS_PCI,
+      .of_match = pci_x86_ids,
+      .ops   = &pci_x86_ops,
+   };
+
+
+Notice that the second driver has the same name but no DM_PHASE(), so it will be
+used for SPL and U-Boot.
+
+Note also that this only affects the code generated by dtoc. You still need to
+make sure that only the required driver is build into each phase.
+
+
+Header files
+------------
+
+With OF_PLATDATA_INST, dtoc must include the correct header file in the
+generated code for any structs that are used, so that the code will compile.
+For example, if `struct ns16550_plat` is used, the code must include the
+`ns16550.h` header file.
+
+Typically dtoc can detect the header file needed for a driver by looking
+for the structs that it uses. For example, if a driver as a `.priv_auto`
+that uses `struct ns16550_plat`, then dtoc can search header files for the
+definition of that struct and use the file.
+
+In some cases, enums are used in drivers, typically with the `.data` field
+of `struct udevice_id`. Since dtoc does not support searching for these,
+you must use the `DM_HDR()` macro to tell dtoc which header to use. This works
+as a macro included in the driver definition::
+
+   static const struct udevice_id apl_syscon_ids[] = {
+      { .compatible = "intel,apl-punit", .data = X86_SYSCON_PUNIT },
+      { }
+   };
+
+   U_BOOT_DRIVER(intel_apl_punit) = {
+      .name       = "intel_apl_punit",
+      .id         = UCLASS_SYSCON,
+      .of_match   = apl_syscon_ids,
+      .probe      = apl_punit_probe,
+      DM_HEADER(<asm/cpu.h>)    /* for X86_SYSCON_PUNIT */
+   };
+
+
+
+Caveats
+-------
+
+There are various complications with this feature which mean it should only
+be used when strictly necessary, i.e. in SPL with limited memory. Notable
+caveats include:
+
+   - Device tree does not describe data types. But the C code must define a
+     type for each property. These are guessed using heuristics which
+     are wrong in several fairly common cases. For example an 8-byte value
+     is considered to be a 2-item integer array, and is byte-swapped. A
+     boolean value that is not present means 'false', but cannot be
+     included in the structures since there is generally no mention of it
+     in the devicetree file.
+
+   - Naming of nodes and properties is automatic. This means that they follow
+     the naming in the devicetree, which may result in C identifiers that
+     look a bit strange.
+
+   - It is not possible to find a value given a property name. Code must use
+     the associated C member variable directly in the code. This makes
+     the code less robust in the face of devicetree changes. To avoid having
+     a second struct with similar members and names you need to explicitly
+     declare it as an alias with `DM_DRIVER_ALIAS()`.
+
+   - The platform data is provided to drivers as a C structure. The driver
+     must use the same structure to access the data. Since a driver
+     normally also supports devicetree it must use `#ifdef` to separate
+     out this code, since the structures are only available in SPL. This could
+     be fixed fairly easily by making the structs available outside SPL, so
+     that `IS_ENABLED()` could be used.
+
+   - With CONFIG_OF_PLATDATA_INST all binding happens at build-time, meaning
+     that (by default) it is not possible to call `device_bind()` from C code.
+     This means that all devices must have an associated devicetree node and
+     compatible string. For example if a GPIO device currently creates child
+     devices in its `bind()` method, it will not work with
+     CONFIG_OF_PLATDATA_INST. Arguably this is bad practice anyway and the
+     devicetree binding should be updated to declare compatible strings for
+     the child devices. It is possible to disable OF_PLATDATA_NO_BIND but this
+     is not recommended since it increases code size.
+
+
+Internals
+---------
+
+Generated files
+```````````````
+
+When enabled, dtoc generates the following five files:
+
+include/generated/dt-decl.h (OF_PLATDATA_INST only)
+   Contains declarations for all drivers, devices and uclasses. This allows
+   any `struct udevice`, `struct driver` or `struct uclass` to be located by its
+   name
+
+include/generated/dt-structs-gen.h
+   Contains the struct definitions for the devicetree nodes that are used. This
+   is the same as without OF_PLATDATA_INST
+
+spl/dts/dt-plat.c (only with !OF_PLATDATA_INST)
+   Contains the `U_BOOT_DRVINFO()` declarations that U-Boot uses to bind devices
+   at start-up. See above for an example
+
+spl/dts/dt-device.c (only with OF_PLATDATA_INST)
+   Contains `DM_DEVICE_INST()` declarations for each device that can be used at
+   run-time. These are declared in the file along with any private/platform data
+   that they use. Every device has an idx, as above. Since each device must be
+   part of a double-linked list, the nodes are declared in the code as well.
+
+spl/dts/dt-uclass.c (only with OF_PLATDATA_INST)
+   Contains `DM_UCLASS_INST()` declarations for each uclass that can be used at
+   run-time. These are declared in the file along with any private data
+   associated with the uclass itself (the `.priv_auto` member). Since each
+   uclass must be part of a double-linked list, the nodes are declared in the
+   code as well.
+
+The dt-structs.h file includes the generated file
+`(include/generated/dt-structs.h`) if CONFIG_SPL_OF_PLATDATA is enabled.
+Otherwise (such as in U-Boot proper) these structs are not available. This
+prevents them being used inadvertently. All usage must be bracketed with
+`#if CONFIG_IS_ENABLED(OF_PLATDATA)`.
+
+The dt-plat.c file contains the device declarations and is is built in
+spl/dt-plat.c.
+
+
+CONFIG options
+``````````````
+
+Several CONFIG options are used to control the behaviour of of-platdata, all
+available for both SPL and TPL:
+
+OF_PLATDATA
+   This is the main option which enables the of-platdata feature
+
+OF_PLATDATA_PARENT
+   This allows `device_get_parent()` to work. Without this, all devices exist as
+   direct children of the root node. This option is highly desirable (if not
+   always absolutely essential) for buses such as I2C.
+
+OF_PLATDATA_INST
+   This controls the instantiation of devices at build time. With it disabled,
+   only `U_BOOT_DRVINFO()` records are created, with U-Boot handling the binding
+   in `device_bind()` on start-up. With it enabled, only `DM_DEVICE_INST()` and
+   `DM_UCLASS_INST()` records are created, and `device_bind()` is not needed at
+   runtime.
+
+OF_PLATDATA_NO_BIND
+   This controls whether `device_bind()` is supported. It is enabled by default
+   with OF_PLATDATA_INST since code-size reduction is really the main point of
+   the feature. It can be disabled if needed but is not likely to be supported
+   in the long term.
+
+OF_PLATDATA_DRIVER_RT
+   This controls whether the `struct driver_rt` records are used by U-Boot.
+   Normally when a device is bound, U-Boot stores the device pointer in one of
+   these records. There is one for every `struct driver_info` in the system,
+   i.e. one for every device that is bound from those records. It provides a
+   way to locate a device in the code and is used by
+   `device_get_by_ofplat_idx()`. This option is always enabled with of-platdata,
+   provided OF_PLATDATA_INST is not. In that case the records are useless since
+   we don't have any `struct driver_info` records.
+
+OF_PLATDATA_RT
+   This controls whether the `struct udevice_rt` records are used by U-Boot.
+   It moves the updatable fields from `struct udevice` (currently only `flags`)
+   into a separate structure, allowing the records to be kept in read-only
+   memory. It is generally enabled if OF_PLATDATA_INST is enabled. This option
+   also controls whether the private data is used in situ, or first copied into
+   an allocated region. Again this is to allow the private data declared by
+   dtoc-generated code to be in read-only memory. Note that access to private
+   data must be done via accessor functions, such as `dev_get_priv()`, so that
+   the relocation is handled.
+
+READ_ONLY
+   This indicates that the data generated by dtoc should not be modified. Only
+   a few fields actually do get changed in U-Boot, such as device flags. This
+   option causes those to move into an allocated space (see OF_PLATDATA_RT).
+   Also, since updating doubly linked lists is generally impossible when some of
+   the nodes cannot be updated, OF_PLATDATA_NO_BIND is enabled.
+
+Data structures
+```````````````
+
+A few extra data structures are used with of-platdata:
+
+`struct udevice_rt`
+   Run-time information for devices. When OF_PLATDATA_RT is enabled, this holds
+   the flags for each device, so that `struct udevice` can remain unchanged by
+   U-Boot, and potentially reside in read-only memory. Access to flags is then
+   via functions like `dev_get_flags()` and `dev_or_flags()`. This data
+   structure is allocated on start-up, where the private data is also copied.
+   All flags values start at 0 and any changes are handled by `dev_or_flags()`
+   and `dev_bic_flags()`. It would be more correct for the flags to be set to
+   `DM_FLAG_BOUND`, or perhaps `DM_FLAG_BOUND | DM_FLAG_ALLOC_PDATA`, but since
+   there is no code to bind/unbind devices and no code to allocate/free
+   private data / platform data, it doesn't matter.
+
+`struct driver_rt`
+   Run-time information for `struct driver_info` records. When
+   OF_PLATDATA_DRIVER_RT is enabled, this holds a pointer to the device
+   created by each record. This is needed so that is it possible to locate a
+   device from C code. Specifically, the code can use `DM_DRVINFO_GET(name)` to
+   get a reference to a particular `struct driver_info`, with `name` being the
+   name of the devicetree node. This is very convenient. It is also fast, since
+   no    searching or string comparison is needed. This data structure is
+   allocated    on start-up, filled out by `device_bind()` and used by
+   `device_get_by_ofplat_idx()`.
+
+Other changes
+`````````````
+
+Some other changes are made with of-platdata:
+
+Accessor functions
+   Accessing private / platform data via functions such as `dev_get_priv()` has
+   always been encouraged. With OF_PLATDATA_RT this is essential, since the
+   `priv_` and `plat_`  (etc.) values point to the data generated by dtoc, not
+   the read-write copy that is sometimes made on start-up. Changing the
+   private / platform data  pointers has always been discouraged (the API is
+   marked internal) but with OF_PLATDATA_RT this is not currently supported in
+   general, since it assumes that all such pointers point to the relocated data.
+   Note also that the renaming of struct members to have a trailing underscore
+   was partly done to make people aware that they should not be accessed
+   directly.
+
+`gd->uclass_root_s`
+   Normally U-Boot sets up the head of the uclass list here and makes
+   `gd->uclass_root` point to it. With OF_PLATDATA_INST, dtoc generates a
+   declaration of `uclass_head` in `dt-uclass.c` since it needs to link the
+   head node into the list. In that case, `gd->uclass_root_s` is not used and
+   U-Boot just makes `gd->uclass_root` point to `uclass_head`.
+
+`gd->dm_driver_rt`
+   This holds a pointer to a list of `struct driver_rt` records, one for each
+   `struct driver_info`. The list is in alphabetical order by the name used
+   in `U_BOOT_DRVINFO(name)` and indexed by idx, with the first record having
+   an index of 0. It is only used if OF_PLATDATA_INST is not enabled. This is
+   accessed via macros so that it can be used inside IS_ENABLED(), rather than
+   requiring #ifdefs in the C code when it is not present.
+
+`gd->dm_udevice_rt`
+   This holds a pointer to a list of `struct udevice_rt` records, one for each
+   `struct udevice`. The list is in alphabetical order by the name used
+   in `DM_DEVICE_INST(name)` (a C version of the devicetree node) and indexed by
+   idx, with the first record having an index of 0. It is only used if
+   OF_PLATDATA_INST is enabled. This is accessed via macros so that it can be
+   used inside `IS_ENABLED()`, rather than requiring #ifdefs in the C code when
+   it is not present.
+
+`gd->dm_priv_base`
+   When OF_PLATDATA_RT is enabled, the private/platform data for each device is
+   copied into an allocated region by U-Boot on start-up. This points to that
+   region. All calls to accessor functions (e.g. `dev_get_priv()`) then
+   translate from the pointer provided by the caller (assumed to lie between
+   `__priv_data_start` and `__priv_data_end`) to the new allocated region. This
+   member is accessed via macros so that it can be used inside IS_ENABLED(),
+   rather than required #ifdefs in the C code when it is not present.
+
+`struct udevice->flags_`
+   When OF_PLATDATA_RT is enabled, device flags are no-longer part of
+   `struct udevice`, but are instead kept in `struct udevice_rt`, as described
+   above. Flags are accessed via functions, such as `dev_get_flags()` and
+   `dev_or_flags()`.
+
+`struct udevice->node_`
+   When OF_PLATDATA is enabled, there is no devicetree at runtime, so no need
+   for this field. It is removed, just to save space.
+
+`DM_PHASE`
+   This macro is used to indicate which phase of U-Boot a driver is intended
+   for. See above for details.
+
+`DM_HDR`
+   This macro is used to indicate which header file dtoc should use to allow
+   a driver declaration to compile correctly. See above for details.
+
+`device_get_by_ofplat_idx()`
+   There used to be a function called `device_get_by_driver_info()` which
+   looked up a `struct driver_info` pointer and returned the `struct udevice`
+   that was created from it. It was only available for use with of-platdata.
+   This has been removed in favour of `device_get_by_ofplat_idx()` which uses
+   `idx`, the index of the `struct driver_info` or `struct udevice` in the
+   linker_list. Similarly, the `struct phandle_0_arg` (etc.) structs have been
+   updated to use this index instead of a pointer to `struct driver_info`.
+
+`DM_DRVINFO_GET`
+   This has been removed since we now use indexes to obtain a driver from
+   `struct phandle_0_arg` and the like.
+
+Two-pass binding
+   The original of-platdata tried to order `U_BOOT_DRVINFO()` in the generated
+   files so as to have parents declared ahead of children. This was convenient
+   as it avoided any special code in U-Boot. With OF_PLATDATA_INST this does
+   not work as the idx value relies on using alphabetical order for everything,
+   so that dtoc and U-Boot's linker_lists agree on the idx value. Devices are
+   then bound in order of idx, having no regard to parent/child relationships.
+   For this reason, device binding now hapens in multiple passes, with parents
+   being bound before their children. This is important so that children can
+   find their parents in the bind() method if needed.
+
+Root device
+   The root device is generally bound by U-Boot but with OF_PLATDATA_INST it
+   cannot be, since binding needs to be done at build time. So in this case
+   dtoc sets up a root device using `DM_DEVICE_INST()` in `dt-device.c` and
+   U-Boot makes use of that. When OF_PLATDATA_INST is not enabled, U-Boot
+   generally ignores the root node and does not create a `U_BOOT_DRVINFO()`
+   record for it. This means that the idx numbers used by `struct driver_info`
+   (when OF_PLATDATA_INST is disabled) and the idx numbers used by
+   `struct udevice` (when OF_PLATDATA_INST is enabled) differ, since one has a
+   root node and the other does not. This does not actually matter, since only
+   one of them is actually used for any particular build, but it is worth
+   keeping in mind if comparing index values and switching OF_PLATDATA_INST on
+   and off.
+
+`__priv_data_start` and `__priv_data_end`
+   The private/platform data declared by dtoc is all collected together in
+   a linker section and these symbols mark the start and end of it. This allows
+   U-Boot to relocate the area to a new location if needed (with
+   OF_PLATDATA_RT)
+
+`dm_priv_to_rw()`
+   This function converts a private- or platform-data pointer value generated by
+   dtoc into one that can be used by U-Boot. It is a NOP unless OF_PLATDATA_RT
+   is enabled, in which case it translates the address to the relocated
+   region. See above for more information.
+
+The dm_populate_phandle_data() function that was previous needed has now been
+removed, since dtoc can address the drivers directly from dt-plat.c and does
+not need to fix up things at runtime.
+
+The pylibfdt Python module is used to access the devicetree.
+
+
+Credits
+-------
+
+This is an implementation of an idea by Tom Rini <trini@konsulko.com>.
+
+
+Future work
+-----------
+- Consider programmatically reading binding files instead of devicetree
+  contents
+- Allow IS_ENABLED() to be used in the C code instead of #if
+
+
+.. Simon Glass <sjg@chromium.org>
+.. Google, Inc
+.. 6/6/16
+.. Updated Independence Day 2016
+.. Updated 1st October 2020
+.. Updated 5th February 2021
diff --git a/doc/driver-model/pci-info.rst b/doc/develop/driver-model/pci-info.rst
similarity index 99%
rename from doc/driver-model/pci-info.rst
rename to doc/develop/driver-model/pci-info.rst
index 8b9faa1..251601a 100644
--- a/doc/driver-model/pci-info.rst
+++ b/doc/develop/driver-model/pci-info.rst
@@ -125,6 +125,7 @@
 		compatible = "sandbox,pci-emul-parent";
 		emul_1f: emul@1f,0 {
 			compatible = "sandbox,swap-case";
+			#emul-cells = <0>;
 		};
 	};
 
diff --git a/doc/driver-model/pmic-framework.rst b/doc/develop/driver-model/pmic-framework.rst
similarity index 100%
rename from doc/driver-model/pmic-framework.rst
rename to doc/develop/driver-model/pmic-framework.rst
diff --git a/doc/driver-model/remoteproc-framework.rst b/doc/develop/driver-model/remoteproc-framework.rst
similarity index 100%
rename from doc/driver-model/remoteproc-framework.rst
rename to doc/develop/driver-model/remoteproc-framework.rst
diff --git a/doc/driver-model/serial-howto.rst b/doc/develop/driver-model/serial-howto.rst
similarity index 100%
rename from doc/driver-model/serial-howto.rst
rename to doc/develop/driver-model/serial-howto.rst
diff --git a/doc/driver-model/soc-framework.rst b/doc/develop/driver-model/soc-framework.rst
similarity index 100%
rename from doc/driver-model/soc-framework.rst
rename to doc/develop/driver-model/soc-framework.rst
diff --git a/doc/driver-model/spi-howto.rst b/doc/develop/driver-model/spi-howto.rst
similarity index 100%
rename from doc/driver-model/spi-howto.rst
rename to doc/develop/driver-model/spi-howto.rst
diff --git a/doc/driver-model/usb-info.rst b/doc/develop/driver-model/usb-info.rst
similarity index 100%
rename from doc/driver-model/usb-info.rst
rename to doc/develop/driver-model/usb-info.rst
diff --git a/doc/develop/index.rst b/doc/develop/index.rst
index ac57fdb..3edffbc 100644
--- a/doc/develop/index.rst
+++ b/doc/develop/index.rst
@@ -10,9 +10,11 @@
    :maxdepth: 1
 
    commands
+   driver-model/index
    global_data
    logging
    menus
+   uefi/index
    version
 
 Debugging
@@ -24,6 +26,14 @@
    crash_dumps
    trace
 
+Packaging
+---------
+
+.. toctree::
+   :maxdepth: 1
+
+   package/index
+
 Testing
 -------
 
@@ -33,3 +43,5 @@
    coccinelle
    testing
    py_testing
+   tests_writing
+   tests_sandbox
diff --git a/doc/develop/logging.rst b/doc/develop/logging.rst
index 60c18c5..f4e9250 100644
--- a/doc/develop/logging.rst
+++ b/doc/develop/logging.rst
@@ -96,16 +96,45 @@
 as the category, so you should #define this right at the top of the source
 file to ensure the category is correct.
 
+Generally each log format_string ends with a newline. If it does not, then the
+next log statement will have the LOGRECF_CONT flag set. This can be used to
+continue the statement on the same line as the previous one without emitting
+new header information (such as category/level). This behaviour is implemented
+with log_console. Here is an example that prints a list all on one line with
+the tags at the start:
+
+.. code-block:: c
+
+   log_debug("Here is a list:");
+   for (i = 0; i < count; i++)
+      log_debug(" item %d", i);
+   log_debug("\n");
+
+Also see the special category LOGL_CONT and level LOGC_CONT.
+
 You can also define CONFIG_LOG_ERROR_RETURN to enable the log_ret() macro. This
 can be used whenever your function returns an error value:
 
 .. code-block:: c
 
-   return log_ret(uclass_first_device(UCLASS_MMC, &dev));
+   return log_ret(uclass_first_device_err(UCLASS_MMC, &dev));
 
 This will write a log record when an error code is detected (a value < 0). This
 can make it easier to trace errors that are generated deep in the call stack.
 
+The log_msg_ret() variant will print a short string if CONFIG_LOG_ERROR_RETURN
+is enabled. So long as the string is unique within the function you can normally
+determine exactly which call failed:
+
+.. code-block:: c
+
+   ret = gpio_request_by_name(dev, "cd-gpios", 0, &desc, GPIOD_IS_IN);
+   if (ret)
+      return log_msg_ret("gpio", ret);
+
+Some functions return 0 for success and any other value is an error. For these,
+log_retz() and log_msg_retz() are available.
+
 Convenience functions
 ~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/doc/develop/package/binman.rst b/doc/develop/package/binman.rst
new file mode 120000
index 0000000..2e26e84
--- /dev/null
+++ b/doc/develop/package/binman.rst
@@ -0,0 +1 @@
+../../../tools/binman/binman.rst
\ No newline at end of file
diff --git a/doc/develop/package/entries.rst b/doc/develop/package/entries.rst
new file mode 120000
index 0000000..ecedceb
--- /dev/null
+++ b/doc/develop/package/entries.rst
@@ -0,0 +1 @@
+../../../tools/binman/entries.rst
\ No newline at end of file
diff --git a/doc/develop/package/index.rst b/doc/develop/package/index.rst
new file mode 100644
index 0000000..9374be2
--- /dev/null
+++ b/doc/develop/package/index.rst
@@ -0,0 +1,19 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Package U-Boot
+==============
+
+U-Boot uses Flat Image Tree (FIT) as a standard file format for packaging
+images that it it reads and boots. Documentation about FIT is available at
+doc/uImage.FIT
+
+U-Boot also provides binman for cases not covered by FIT. Examples include
+initial execution (since FIT itself does not have an executable header) and
+dealing with device boundaries, such as the read-only/read-write separation in
+SPI flash.
+
+
+.. toctree::
+   :maxdepth: 2
+
+   binman
diff --git a/doc/develop/py_testing.rst b/doc/develop/py_testing.rst
index 7f01858..c4cecc0 100644
--- a/doc/develop/py_testing.rst
+++ b/doc/develop/py_testing.rst
@@ -13,7 +13,8 @@
   U-Boot; there can be no disconnect.
 - There is no need to write or embed test-related code into U-Boot itself.
   It is asserted that writing test-related code in Python is simpler and more
-  flexible than writing it all in C.
+  flexible than writing it all in C. But see :doc:`tests_writing` for caveats
+  and more discussion / analysis.
 - It is reasonably simple to interact with U-Boot in this way.
 
 Requirements
diff --git a/doc/develop/testing.rst b/doc/develop/testing.rst
index 4bc9ca3..ced13ac 100644
--- a/doc/develop/testing.rst
+++ b/doc/develop/testing.rst
@@ -8,17 +8,27 @@
 Running tests
 -------------
 
-To run most tests on sandbox, type this:
+To run most tests on sandbox, type this::
 
     make check
 
 in the U-Boot directory. Note that only the pytest suite is run using this
 command.
 
-Some tests take ages to run. To run just the quick ones, type this:
+Some tests take ages to run and are marked with @pytest.mark.slow. To run just
+the quick ones, type this::
 
     make qcheck
 
+It is also possible to run just the tests for tools (patman, binman, etc.).
+Such tests are included with those tools, i.e. no actual U-Boot unit tests are
+run. Type this::
+
+    make tcheck
+
+All of the above use the test/run script with a paremeter to select which tests
+are run.
+
 
 Sandbox
 -------
@@ -26,6 +36,7 @@
 allows test to be executed without needing target hardware. The 'sandbox'
 target provides this feature and it is widely used in tests.
 
+See :doc:`tests_sandbox` for more information.
 
 Pytest Suite
 ------------
@@ -35,14 +46,27 @@
 inject test commands and check the result. It is slower to run than C code,
 but provides the ability to unify lots of tests and summarise their results.
 
-You can run the tests on sandbox with:
+You can run the tests on sandbox with::
 
-	./test/py/test.py --bd sandbox --build
+   ./test/py/test.py --bd sandbox --build
 
 This will produce HTML output in build-sandbox/test-log.html
 
+Some tests run with other versions of sandbox. For example sandbox_flattree
+runs the tests with livetree (the hierachical devicetree) disabled. You can
+also select particular tests with -k::
+
+   ./test/py/test.py --bd sandbox_flattree --build -k hello
+
+There are some special tests that run in SPL. For this you need the sandbox_spl
+build::
+
+   ./test/py/test.py --bd sandbox_spl --build -k test_spl
+
 See test/py/README.md for more information about the pytest suite.
 
+See :doc:`tests_sandbox` for how to run tests directly (not through pytest).
+
 
 tbot
 ----
@@ -58,10 +82,14 @@
 
 There are several ad-hoc tests which run outside the pytest environment:
 
-   test/fs	- File system test (shell script)
-   test/image	- FIT and legacy image tests (shell script and Python)
-   test/stdint	- A test that stdint.h can be used in U-Boot (shell script)
-   trace	- Test for the tracing feature (shell script)
+test/fs
+   File system test (shell script)
+test/image
+   FIT and legacy image tests (shell script and Python)
+test/stdint
+   A test that stdint.h can be used in U-Boot (shell script)
+trace
+   Test for the tracing feature (shell script)
 
 TODO: Move these into pytest.
 
@@ -89,6 +117,8 @@
   is much easier to add onto a test - writing a new large test can seem
   daunting to most contributors.
 
+See doc:`tests_writing` for how to write tests.
+
 
 Future work
 -----------
diff --git a/doc/develop/tests_sandbox.rst b/doc/develop/tests_sandbox.rst
new file mode 100644
index 0000000..84608dc
--- /dev/null
+++ b/doc/develop/tests_sandbox.rst
@@ -0,0 +1,209 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Sandbox tests
+=============
+
+Test Design
+-----------
+
+Most uclasses and many functions of U-Boot have sandbox tests. This allows much
+of the code to be checked in an developer-friendly environment.
+
+Sandbox provides a way to write and run unit tests. The traditional approach to
+unit tests is to build lots of little executables, one for each test or
+category of tests. With sandbox, so far as possible, all the tests share a
+small number of executables (e.g. 'u-boot' for sandbox, 'u-boot-spl' and
+'u-boot' for sandbox_spl) and can be run very quickly. The vast majority of
+tests can run on the 'sandbox' build,
+
+Available tests
+---------------
+
+Some of the available tests are:
+
+  - command_ut: Unit tests for command parsing and handling
+  - compression: Unit tests for U-Boot's compression algorithms, useful for
+      security checking. It supports gzip, bzip2, lzma and lzo.
+  - image: Unit tests for images:
+
+     - test/image/test-imagetools.sh - multi-file images
+     - test/py/tests/test-fit.py     - FIT images
+  - tracing: test/trace/test-trace.sh tests the tracing system (see
+      README.trace)
+  - verified boot: test/py/tests/test_vboot.py
+
+If you change or enhance any U-Boot subsystem, you should write or expand a
+test and include it with your patch series submission. Test coverage in some
+older areas of U-Boot is still somewhat limited and we need to work to improve
+it.
+
+Note that many of these tests are implemented as commands which you can
+run natively on your board if desired (and enabled).
+
+To run all tests, use 'make check'.
+
+
+Running sandbox tests directly
+------------------------------
+
+Typically tests are run using the pytest suite. Running pytests on sandbox is
+easy and always gets things right. For example some tests require files to be
+set up before they can work.
+
+But it is also possible to run some sandbox tests directly. For example, this
+runs the dm_test_gpio() test which you can find in test/dm/gpio.c::
+
+   $ ./u-boot -T -c "ut dm gpio"
+
+
+   U-Boot 2021.01
+
+   Model: sandbox
+   DRAM:  128 MiB
+   WDT:   Started with servicing (60s timeout)
+   MMC:   mmc2: 2 (SD), mmc1: 1 (SD), mmc0: 0 (SD)
+   In:    serial
+   Out:   vidconsole
+   Err:   vidconsole
+   Model: sandbox
+   SCSI:
+   Net:   eth0: eth@10002000, eth5: eth@10003000, eth3: sbe5, eth6: eth@10004000
+   Test: dm_test_gpio: gpio.c
+   Test: dm_test_gpio: gpio.c (flat tree)
+   Failures: 0
+
+The -T option tells the U-Boot sandbox to run with the 'test' devicetree
+(test.dts) instead of -D which selects the normal sandbox.dts - this is
+necessary because many tests rely on nodes or properties in the test devicetree.
+If you try running tests without -T then you may see failures, like::
+
+   $ ./u-boot -c "ut dm gpio"
+
+
+   U-Boot 2021.01
+
+   DRAM:  128 MiB
+   WDT:   Not found!
+   MMC:
+   In:    serial
+   Out:   serial
+   Err:   serial
+   SCSI:
+   Net:   No ethernet found.
+   Please run with test device tree:
+       ./u-boot -d arch/sandbox/dts/test.dtb
+   Test: dm_test_gpio: gpio.c
+   test/dm/gpio.c:37, dm_test_gpio(): 0 == gpio_lookup_name("b4", &dev, &offset, &gpio): Expected 0x0 (0), got 0xffffffea (-22)
+   Test: dm_test_gpio: gpio.c (flat tree)
+   test/dm/gpio.c:37, dm_test_gpio(): 0 == gpio_lookup_name("b4", &dev, &offset, &gpio): Expected 0x0 (0), got 0xffffffea (-22)
+   Failures: 2
+
+The message above should provide a hint if you forget to use the -T flag. Even
+running with -D will produce different results.
+
+You can easily use gdb on these tests, without needing --gdbserver::
+
+   $ gdb u-boot --args -T -c "ut dm gpio"
+   ...
+   (gdb) break dm_test_gpio
+   Breakpoint 1 at 0x1415bd: file test/dm/gpio.c, line 37.
+   (gdb) run -T -c "ut dm gpio"
+   Starting program: u-boot -T -c "ut dm gpio"
+   Test: dm_test_gpio: gpio.c
+
+   Breakpoint 1, dm_test_gpio (uts=0x5555558029a0 <global_dm_test_state>)
+       at files/test/dm/gpio.c:37
+   37		ut_assertok(gpio_lookup_name("b4", &dev, &offset, &gpio));
+   (gdb)
+
+You can then single-step and look at variables as needed.
+
+
+Running sandbox_spl tests directly
+----------------------------------
+
+SPL is the phase before U-Boot proper. It is present in the sandbox_spl build,
+so you can run SPL like this::
+
+   ./spl/u-boot-spl
+
+SPL tests are special in that they run (only in the SPL phase, of course) if the
+-u flag is given::
+
+   ./spl/u-boot-spl -u
+
+   U-Boot SPL 2021.01-00723-g43c77b51be5-dirty (Jan 24 2021 - 16:38:24 -0700)
+   Running 5 driver model tests
+   Test: dm_test_of_plat_base: of_platdata.c (flat tree)
+   Test: dm_test_of_plat_dev: of_platdata.c (flat tree)
+   Test: dm_test_of_plat_parent: of_platdata.c (flat tree)
+   Test: dm_test_of_plat_phandle: of_platdata.c (flat tree)
+   Test: dm_test_of_plat_props: of_platdata.c (flat tree)
+   Failures: 0
+
+
+   U-Boot 2021.01-00723-g43c77b51be5-dirty (Jan 24 2021 - 16:38:24 -0700)
+
+   DRAM:  128 MiB
+   ...
+
+It is not possible to run SPL tests in U-Boot proper, firstly because they are
+not built into U-Boot proper and secondly because the environment is very
+different, e.g. some SPL tests rely on of-platdata which is only available in
+SPL.
+
+Note that after running, SPL continues to boot into U-Boot proper. You can add
+'-c exit' to make U-Boot quit without doing anything further. It is not
+currently possible to run SPL tests and then stop, since the pytests require
+that U-Boot produces the expected banner.
+
+You can use the -k flag to select which tests run::
+
+   ./spl/u-boot-spl -u -k dm_test_of_plat_parent
+
+Of course you can use gdb with sandbox_spl, just as with sandbox.
+
+
+Running all tests directly
+--------------------------
+
+A fast way to run all sandbox tests is::
+
+   ./u-boot -T -c "ut all"
+
+It typically runs single-thread in 6 seconds on 2021 hardware, with 2s of that
+to the delays in the time test.
+
+This should not be considered a substitute for 'make check', but can be helpful
+for git bisect, etc.
+
+
+What tests are built in?
+------------------------
+
+Whatever sandbox build is used, which tests are present is determined by which
+source files are built. For sandbox_spl, the of_platdata tests are built
+because of the build rule in test/dm/Makefile::
+
+   ifeq ($(CONFIG_SPL_BUILD),y)
+   obj-$(CONFIG_SPL_OF_PLATDATA) += of_platdata.o
+   else
+   ...other tests for non-spl
+   endif
+
+You can get a list of tests in a U-Boot ELF file by looking for the
+linker_list::
+
+   $ nm /tmp/b/sandbox_spl/spl/u-boot-spl |grep 2_dm_test
+   000000000001f200 D _u_boot_list_2_dm_test_2_dm_test_of_plat_base
+   000000000001f220 D _u_boot_list_2_dm_test_2_dm_test_of_plat_dev
+   000000000001f240 D _u_boot_list_2_dm_test_2_dm_test_of_plat_parent
+   000000000001f260 D _u_boot_list_2_dm_test_2_dm_test_of_plat_phandle
+   000000000001f280 D _u_boot_list_2_dm_test_2_dm_test_of_plat_props
+
+
+Writing tests
+-------------
+
+See :doc:`tests_writing` for how to write new tests.
+
diff --git a/doc/develop/tests_writing.rst b/doc/develop/tests_writing.rst
new file mode 100644
index 0000000..1ddf7a3
--- /dev/null
+++ b/doc/develop/tests_writing.rst
@@ -0,0 +1,346 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2021 Google LLC
+.. sectionauthor:: Simon Glass <sjg@chromium.org>
+
+Writing Tests
+=============
+
+This describes how to write tests in U-Boot and describes the possible options.
+
+Test types
+----------
+
+There are two basic types of test in U-Boot:
+
+  - Python tests, in test/py/tests
+  - C tests, in test/ and its subdirectories
+
+(there are also UEFI tests in lib/efi_selftest/ not considered here.)
+
+Python tests talk to U-Boot via the command line. They support both sandbox and
+real hardware. They typically do not require building test code into U-Boot
+itself. They are fairly slow to run, due to the command-line interface and there
+being two separate processes. Python tests are fairly easy to write. They can
+be a little tricky to debug sometimes due to the voluminous output of pytest.
+
+C tests are written directly in U-Boot. While they can be used on boards, they
+are more commonly used with sandbox, as they obviously add to U-Boot code size.
+C tests are easy to write so long as the required facilities exist. Where they
+do not it can involve refactoring or adding new features to sandbox. They are
+fast to run and easy to debug.
+
+Regardless of which test type is used, all tests are collected and run by the
+pytest framework, so there is typically no need to run them separately. This
+means that C tests can be used when it makes sense, and Python tests when it
+doesn't.
+
+
+This table shows how to decide whether to write a C or Python test:
+
+=====================  ===========================  =============================
+Attribute              C test                       Python test
+=====================  ===========================  =============================
+Fast to run?           Yes                          No (two separate processes)
+Easy to write?         Yes, if required test        Yes
+                       features exist in sandbox
+                       or the target system
+Needs code in U-Boot?  Yes                          No, provided the test can be
+                                                    executed and the result
+                                                    determined using the command
+                                                    line
+Easy to debug?         Yes                          No, since access to the U-Boot
+                                                    state is not available and the
+                                                    amount of output can
+                                                    sometimes require a bit of
+                                                    digging
+Can use gdb?           Yes, directly                Yes, with --gdbserver
+Can run on boards?     Some can, but only if        Some
+                       compiled in and not
+                       dependent on sandboxau
+=====================  ===========================  =============================
+
+
+Python or C
+-----------
+
+Typically in U-Boot we encourage C test using sandbox for all features. This
+allows fast testing, easy development and allows contributors to make changes
+without needing dozens of boards to test with.
+
+When a test requires setup or interaction with the running host (such as to
+generate images and then running U-Boot to check that they can be loaded), or
+cannot be run on sandbox, Python tests should be used. These should typically
+NOT rely on running with sandbox, but instead should function correctly on any
+board supported by U-Boot.
+
+
+How slow are Python tests?
+--------------------------
+
+Under the hood, when running on sandbox, Python tests work by starting a sandbox
+test and connecting to it via a pipe. Each interaction with the U-Boot process
+requires at least a context switch to handle the pipe interaction. The test
+sends a command to U-Boot, which then reacts and shows some output, then the
+test sees that and continues. Of course on real hardware, communications delays
+(e.g. with a serial console) make this slower.
+
+For comparison, consider a test that checks the 'md' (memory dump). All times
+below are approximate, as measured on an AMD 2950X system. Here is is the test
+in Python::
+
+   @pytest.mark.buildconfigspec('cmd_memory')
+   def test_md(u_boot_console):
+       """Test that md reads memory as expected, and that memory can be modified
+       using the mw command."""
+
+       ram_base = u_boot_utils.find_ram_base(u_boot_console)
+       addr = '%08x' % ram_base
+       val = 'a5f09876'
+       expected_response = addr + ': ' + val
+       u_boot_console.run_command('mw ' + addr + ' 0 10')
+       response = u_boot_console.run_command('md ' + addr + ' 10')
+       assert(not (expected_response in response))
+       u_boot_console.run_command('mw ' + addr + ' ' + val)
+       response = u_boot_console.run_command('md ' + addr + ' 10')
+       assert(expected_response in response)
+
+This runs a few commands and checks the output. Note that it runs a command,
+waits for the response and then checks it agains what is expected. If run by
+itself it takes around 800ms, including test collection. For 1000 runs it takes
+19 seconds, or 19ms per run. Of course 1000 runs it not that useful since we
+only want to run it once.
+
+There is no exactly equivalent C test, but here is a similar one that tests 'ms'
+(memory search)::
+
+   /* Test 'ms' command with bytes */
+   static int mem_test_ms_b(struct unit_test_state *uts)
+   {
+      u8 *buf;
+
+      buf = map_sysmem(0, BUF_SIZE + 1);
+      memset(buf, '\0', BUF_SIZE);
+      buf[0x0] = 0x12;
+      buf[0x31] = 0x12;
+      buf[0xff] = 0x12;
+      buf[0x100] = 0x12;
+      ut_assertok(console_record_reset_enable());
+      run_command("ms.b 1 ff 12", 0);
+      ut_assert_nextline("00000030: 00 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................");
+      ut_assert_nextline("--");
+      ut_assert_nextline("000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12    ................");
+      ut_assert_nextline("2 matches");
+      ut_assert_console_end();
+
+      ut_asserteq(2, env_get_hex("memmatches", 0));
+      ut_asserteq(0xff, env_get_hex("memaddr", 0));
+      ut_asserteq(0xfe, env_get_hex("mempos", 0));
+
+      unmap_sysmem(buf);
+
+      return 0;
+   }
+   MEM_TEST(mem_test_ms_b, UT_TESTF_CONSOLE_REC);
+
+This runs the command directly in U-Boot, then checks the console output, also
+directly in U-Boot. If run by itself this takes 100ms. For 1000 runs it takes
+660ms, or 0.66ms per run.
+
+So overall running a C test is perhaps 8 times faster individually and the
+interactions are perhaps 25 times faster.
+
+It should also be noted that the C test is fairly easy to debug. You can set a
+breakpoint on do_mem_search(), which is what implements the 'ms' command,
+single step to see what might be wrong, etc. That is also possible with the
+pytest, but requires two terminals and --gdbserver.
+
+
+Why does speed matter?
+----------------------
+
+Many development activities rely on running tests:
+
+  - 'git bisect run make qcheck' can be used to find a failing commit
+  - test-driven development relies on quick iteration of build/test
+  - U-Boot's continuous integration (CI) systems make use of tests. Running
+      all sandbox tests typically takes 90 seconds and running each qemu test
+      takes about 30 seconds. This is currently dwarfed by the time taken to
+      build all boards
+
+As U-Boot continues to grow its feature set, fast and reliable tests are a
+critical factor factor in developer productivity and happiness.
+
+
+Writing C tests
+---------------
+
+C tests are arranged into suites which are typically executed by the 'ut'
+command. Each suite is in its own file. This section describes how to accomplish
+some common test tasks.
+
+(there are also UEFI C tests in lib/efi_selftest/ not considered here.)
+
+Add a new driver model test
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Use this when adding a test for a new or existing uclass, adding new operations
+or features to a uclass, adding new ofnode or dev_read_() functions, or anything
+else related to driver model.
+
+Find a suitable place for your test, perhaps near other test functions in
+existing code, or in a new file. Each uclass should have its own test file.
+
+Declare the test with::
+
+   /* Test that ... */
+   static int dm_test_uclassname_what(struct unit_test_state *uts)
+   {
+      /* test code here */
+
+      return 0;
+   }
+   DM_TEST(dm_test_uclassname_what, UT_TESTF_SCAN_FDT);
+
+Replace 'uclassname' with the name of your uclass, if applicable. Replace 'what'
+with what you are testing.
+
+The flags for DM_TEST() are defined in test/test.h and you typically want
+UT_TESTF_SCAN_FDT so that the devicetree is scanned and all devices are bound
+and ready for use. The DM_TEST macro adds UT_TESTF_DM automatically so that
+the test runner knows it is a driver model test.
+
+Driver model tests are special in that the entire driver model state is
+recreated anew for each test. This ensures that if a previous test deletes a
+device, for example, it does not affect subsequent tests. Driver model tests
+also run both with livetree and flattree, to ensure that both devicetree
+implementations work as expected.
+
+Example commit: c48cb7ebfb4 ("sandbox: add ADC unit tests") [1]
+
+[1] https://gitlab.denx.de/u-boot/u-boot/-/commit/c48cb7ebfb4
+
+
+Add a C test to an existing suite
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Use this when you are adding to or modifying an existing feature outside driver
+model. An example is bloblist.
+
+Add a new function in the same file as the rest of the suite and register it
+with the suite. For example, to add a new mem_search test::
+
+   /* Test 'ms' command with 32-bit values */
+   static int mem_test_ms_new_thing(struct unit_test_state *uts)
+   {
+         /* test code here*/
+
+         return 0;
+   }
+   MEM_TEST(mem_test_ms_new_thing, UT_TESTF_CONSOLE_REC);
+
+Note that the MEM_TEST() macros is defined at the top of the file.
+
+Example commit: 9fe064646d2 ("bloblist: Support relocating to a larger space") [1]
+
+[1] https://gitlab.denx.de/u-boot/u-boot/-/commit/9fe064646d2
+
+
+Add a new test suite
+~~~~~~~~~~~~~~~~~~~~
+
+Each suite should focus on one feature or subsystem, so if you are writing a
+new one of those, you should add a new suite.
+
+Create a new file in test/ or a subdirectory and define a macro to register the
+suite. For example::
+
+   #include <common.h>
+   #include <console.h>
+   #include <mapmem.h>
+   #include <dm/test.h>
+   #include <test/ut.h>
+
+   /* Declare a new wibble test */
+   #define WIBBLE_TEST(_name, _flags)   UNIT_TEST(_name, _flags, wibble_test)
+
+   /* Tetss go here */
+
+   /* At the bottom of the file: */
+
+   int do_ut_wibble(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+   {
+     struct unit_test *tests = UNIT_TEST_SUITE_START(wibble_test);
+     const int n_ents = UNIT_TEST_SUITE_COUNT(wibble_test);
+
+     return cmd_ut_category("cmd_wibble", "wibble_test_", tests, n_ents, argc, argv);
+   }
+
+Then add new tests to it as above.
+
+Register this new suite in test/cmd_ut.c by adding to cmd_ut_sub[]::
+
+  /* Within cmd_ut_sub[]... */
+
+  U_BOOT_CMD_MKENT(wibble, CONFIG_SYS_MAXARGS, 1, do_ut_wibble, "", ""),
+
+and adding new help to ut_help_text[]::
+
+  "ut wibble - Test the wibble feature\n"
+
+If your feature is conditional on a particular Kconfig, then you can use #ifdef
+to control that.
+
+Finally, add the test to the build by adding to the Makefile in the same
+directory::
+
+  obj-$(CONFIG_$(SPL_)CMDLINE) += wibble.o
+
+Note that CMDLINE is never enabled in SPL, so this test will only be present in
+U-Boot proper. See below for how to do SPL tests.
+
+As before, you can add an extra Kconfig check if needed::
+
+  ifneq ($(CONFIG_$(SPL_)WIBBLE),)
+  obj-$(CONFIG_$(SPL_)CMDLINE) += wibble.o
+  endif
+
+
+Example commit: 919e7a8fb64 ("test: Add a simple test for bloblist") [1]
+
+[1] https://gitlab.denx.de/u-boot/u-boot/-/commit/919e7a8fb64
+
+
+Making the test run from pytest
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+All C tests must run from pytest. Typically this is automatic, since pytest
+scans the U-Boot executable for available tests to run. So long as you have a
+'ut' subcommand for your test suite, it will run. The same applies for driver
+model tests since they use the 'ut dm' subcommand.
+
+See test/py/tests/test_ut.py for how unit tests are run.
+
+
+Add a C test for SPL
+~~~~~~~~~~~~~~~~~~~~
+
+Note: C tests are only available for sandbox_spl at present. There is currently
+no mechanism in other boards to existing SPL tests even if they are built into
+the image.
+
+SPL tests cannot be run from the 'ut' command since there are no commands
+available in SPL. Instead, sandbox (only) calls ut_run_list() on start-up, when
+the -u flag is given. This runs the available unit tests, no matter what suite
+they are in.
+
+To create a new SPL test, follow the same rules as above, either adding to an
+existing suite or creating a new one.
+
+An example SPL test is spl_test_load().
+
+
+Writing Python tests
+--------------------
+
+See :doc:`py_testing` for brief notes how to write Python tests. You
+should be able to use the existing tests in test/py/tests as examples.
diff --git a/doc/develop/uefi/index.rst b/doc/develop/uefi/index.rst
new file mode 100644
index 0000000..7e65dbc
--- /dev/null
+++ b/doc/develop/uefi/index.rst
@@ -0,0 +1,15 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Unified Extensible Firmware (UEFI)
+==================================
+
+U-Boot provides an implementation of the UEFI API allowing to run UEFI
+compliant software like Linux, GRUB, and iPXE. Furthermore U-Boot itself
+can be run an UEFI payload.
+
+.. toctree::
+   :maxdepth: 2
+
+   uefi.rst
+   u-boot_on_efi.rst
+   iscsi.rst
diff --git a/doc/uefi/iscsi.rst b/doc/develop/uefi/iscsi.rst
similarity index 100%
rename from doc/uefi/iscsi.rst
rename to doc/develop/uefi/iscsi.rst
diff --git a/doc/uefi/u-boot_on_efi.rst b/doc/develop/uefi/u-boot_on_efi.rst
similarity index 100%
rename from doc/uefi/u-boot_on_efi.rst
rename to doc/develop/uefi/u-boot_on_efi.rst
diff --git a/doc/uefi/uefi.rst b/doc/develop/uefi/uefi.rst
similarity index 99%
rename from doc/uefi/uefi.rst
rename to doc/develop/uefi/uefi.rst
index 5a67737..b3494c2 100644
--- a/doc/uefi/uefi.rst
+++ b/doc/develop/uefi/uefi.rst
@@ -178,7 +178,7 @@
 
 Set up boot parameters on your board::
 
-    efidebug boot add 1 HELLO mmc 0:1 /helloworld.efi.signed ""
+    efidebug boot add -b 1 HELLO mmc 0:1 /helloworld.efi.signed ""
 
 Now your board can run the signed image via the boot manager (see below).
 You can also try this sequence by running Pytest, test_efi_secboot,
diff --git a/doc/device-tree-bindings/pinctrl/atmel,at91-pio4-pinctrl.txt b/doc/device-tree-bindings/pinctrl/atmel,at91-pio4-pinctrl.txt
index 9252dc1..6e936a0 100644
--- a/doc/device-tree-bindings/pinctrl/atmel,at91-pio4-pinctrl.txt
+++ b/doc/device-tree-bindings/pinctrl/atmel,at91-pio4-pinctrl.txt
@@ -25,9 +25,10 @@
 right representation of the pin.
 
 Optional properties:
-- GENERIC_PINCONFIG: generic pinconfig options to use, bias-disable,
-bias-pull-down, bias-pull-up, drive-open-drain, input-schmitt-enable,
-input-debounce.
+- GENERIC_PINCONFIG: generic pinconfig options to use:
+	- bias-disable, bias-pull-down, bias-pull-up, drive-open-drain,
+	  input-schmitt-enable, input-debounce
+	- slew-rate: 0 - disabled, 1 - enabled (default)
 - atmel,drive-strength: 0 or 1 for low drive, 2 for medium drive and 3 for
 high drive. The default value is low drive.
 
diff --git a/doc/device-tree-bindings/sysinfo/google,coral.txt b/doc/device-tree-bindings/sysinfo/google,coral.txt
new file mode 100644
index 0000000..d8a1a79
--- /dev/null
+++ b/doc/device-tree-bindings/sysinfo/google,coral.txt
@@ -0,0 +1,37 @@
+Google Coral sysinfo information
+================================
+
+This binding allows information about the board to be described. It includes
+the SMBIOS binding as well.
+
+Required properties:
+
+  - compatible: "google,coral"
+  - recovery-gpios: GPIO to use for recovery button (-1 if none)
+  - wite-protect-gpios: GPIO to use for write-protect screw
+  - phase-enforce-gpios: GPIO to indicate the board is in final ship mode
+  - memconfig-gpios: 4 GPIOs to use to read memory config (as base2 int)
+
+Optional properties:
+  - skuconfig-gpios: 2 GPIOs to use to read SKU ID. If not present, the
+       Chromium OS EC SKU_ID is used instead
+
+Example:
+
+board: board {
+	compatible = "google,coral";
+	recovery-gpios = <&gpio_nw (-1) GPIO_ACTIVE_LOW>;
+	write-protect-gpios = <&gpio_nw GPIO_75 GPIO_ACTIVE_HIGH>;
+	phase-enforce-gpios = <&gpio_n GPIO_10 GPIO_ACTIVE_HIGH>;
+	memconfig-gpios = <&gpio_nw GPIO_101 GPIO_ACTIVE_HIGH
+		&gpio_nw GPIO_102 GPIO_ACTIVE_HIGH
+		&gpio_n GPIO_38 GPIO_ACTIVE_HIGH
+		&gpio_n GPIO_45 GPIO_ACTIVE_HIGH>;
+
+	/*
+	 * This is used for reef only:
+	 *
+	 * skuconfig-gpios = <&gpio_nw GPIO_16 GPIO_ACTIVE_HIGH
+	 *	&gpio_nw GPIO_17 GPIO_ACTIVE_HIGH>;
+	 */
+ };
diff --git a/doc/driver-model/of-plat.rst b/doc/driver-model/of-plat.rst
deleted file mode 100644
index 4ef2fe6..0000000
--- a/doc/driver-model/of-plat.rst
+++ /dev/null
@@ -1,359 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-
-Compiled-in Device Tree / Platform Data
-=======================================
-
-
-Introduction
-------------
-
-Device tree is the standard configuration method in U-Boot. It is used to
-define what devices are in the system and provide configuration information
-to these devices.
-
-The overhead of adding device tree access to U-Boot is fairly modest,
-approximately 3KB on Thumb 2 (plus the size of the DT itself). This means
-that in most cases it is best to use device tree for configuration.
-
-However there are some very constrained environments where U-Boot needs to
-work. These include SPL with severe memory limitations. For example, some
-SoCs require a 16KB SPL image which must include a full MMC stack. In this
-case the overhead of device tree access may be too great.
-
-It is possible to create platform data manually by defining C structures
-for it, and reference that data in a U_BOOT_DRVINFO() declaration. This
-bypasses the use of device tree completely, effectively creating a parallel
-configuration mechanism. But it is an available option for SPL.
-
-As an alternative, a new 'of-platdata' feature is provided. This converts the
-device tree contents into C code which can be compiled into the SPL binary.
-This saves the 3KB of code overhead and perhaps a few hundred more bytes due
-to more efficient storage of the data.
-
-Note: Quite a bit of thought has gone into the design of this feature.
-However it still has many rough edges and comments and suggestions are
-strongly encouraged! Quite possibly there is a much better approach.
-
-
-Caveats
--------
-
-There are many problems with this features. It should only be used when
-strictly necessary. Notable problems include:
-
-   - Device tree does not describe data types. But the C code must define a
-     type for each property. These are guessed using heuristics which
-     are wrong in several fairly common cases. For example an 8-byte value
-     is considered to be a 2-item integer array, and is byte-swapped. A
-     boolean value that is not present means 'false', but cannot be
-     included in the structures since there is generally no mention of it
-     in the device tree file.
-
-   - Naming of nodes and properties is automatic. This means that they follow
-     the naming in the device tree, which may result in C identifiers that
-     look a bit strange.
-
-   - It is not possible to find a value given a property name. Code must use
-     the associated C member variable directly in the code. This makes
-     the code less robust in the face of device-tree changes. It also
-     makes it very unlikely that your driver code will be useful for more
-     than one SoC. Even if the code is common, each SoC will end up with
-     a different C struct name, and a likely a different format for the
-     platform data.
-
-   - The platform data is provided to drivers as a C structure. The driver
-     must use the same structure to access the data. Since a driver
-     normally also supports device tree it must use #ifdef to separate
-     out this code, since the structures are only available in SPL.
-
-
-How it works
-------------
-
-The feature is enabled by CONFIG OF_PLATDATA. This is only available in
-SPL/TPL and should be tested with:
-
-.. code-block:: c
-
-    #if CONFIG_IS_ENABLED(OF_PLATDATA)
-
-A new tool called 'dtoc' converts a device tree file either into a set of
-struct declarations, one for each compatible node, and a set of
-U_BOOT_DRVINFO() declarations along with the actual platform data for each
-device. As an example, consider this MMC node:
-
-.. code-block:: none
-
-    sdmmc: dwmmc@ff0c0000 {
-            compatible = "rockchip,rk3288-dw-mshc";
-            clock-freq-min-max = <400000 150000000>;
-            clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
-                     <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
-            clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
-            fifo-depth = <0x100>;
-            interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
-            reg = <0xff0c0000 0x4000>;
-            bus-width = <4>;
-            cap-mmc-highspeed;
-            cap-sd-highspeed;
-            card-detect-delay = <200>;
-            disable-wp;
-            num-slots = <1>;
-            pinctrl-names = "default";
-            pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>;
-                vmmc-supply = <&vcc_sd>;
-                status = "okay";
-                u-boot,dm-pre-reloc;
-        };
-
-
-Some of these properties are dropped by U-Boot under control of the
-CONFIG_OF_SPL_REMOVE_PROPS option. The rest are processed. This will produce
-the following C struct declaration:
-
-.. code-block:: c
-
-    struct dtd_rockchip_rk3288_dw_mshc {
-            fdt32_t         bus_width;
-            bool            cap_mmc_highspeed;
-            bool            cap_sd_highspeed;
-            fdt32_t         card_detect_delay;
-            fdt32_t         clock_freq_min_max[2];
-            struct phandle_1_arg clocks[4];
-            bool            disable_wp;
-            fdt32_t         fifo_depth;
-            fdt32_t         interrupts[3];
-            fdt32_t         num_slots;
-            fdt32_t         reg[2];
-            fdt32_t         vmmc_supply;
-    };
-
-and the following device declarations:
-
-.. code-block:: c
-
-    /* Node /clock-controller@ff760000 index 0 */
-    ...
-
-    /* Node /dwmmc@ff0c0000 index 2 */
-    static struct dtd_rockchip_rk3288_dw_mshc dtv_dwmmc_at_ff0c0000 = {
-            .fifo_depth             = 0x100,
-            .cap_sd_highspeed       = true,
-            .interrupts             = {0x0, 0x20, 0x4},
-            .clock_freq_min_max     = {0x61a80, 0x8f0d180},
-            .vmmc_supply            = 0xb,
-            .num_slots              = 0x1,
-            .clocks                 = {{0, 456},
-                                       {0, 68},
-                                       {0, 114},
-                                       {0, 118}},
-            .cap_mmc_highspeed      = true,
-            .disable_wp             = true,
-            .bus_width              = 0x4,
-            .u_boot_dm_pre_reloc    = true,
-            .reg                    = {0xff0c0000, 0x4000},
-            .card_detect_delay      = 0xc8,
-    };
-
-    U_BOOT_DRVINFO(dwmmc_at_ff0c0000) = {
-            .name           = "rockchip_rk3288_dw_mshc",
-            .plat       = &dtv_dwmmc_at_ff0c0000,
-            .plat_size  = sizeof(dtv_dwmmc_at_ff0c0000),
-            .parent_idx     = -1,
-    };
-
-The device is then instantiated at run-time and the platform data can be
-accessed using:
-
-.. code-block:: c
-
-    struct udevice *dev;
-    struct dtd_rockchip_rk3288_dw_mshc *plat = dev_get_plat(dev);
-
-This avoids the code overhead of converting the device tree data to
-platform data in the driver. The of_to_plat() method should
-therefore do nothing in such a driver.
-
-Note that for the platform data to be matched with a driver, the 'name'
-property of the U_BOOT_DRVINFO() declaration has to match a driver declared
-via U_BOOT_DRIVER(). This effectively means that a U_BOOT_DRIVER() with a
-'name' corresponding to the devicetree 'compatible' string (after converting
-it to a valid name for C) is needed, so a dedicated driver is required for
-each 'compatible' string.
-
-In order to make this a bit more flexible DM_DRIVER_ALIAS macro can be
-used to declare an alias for a driver name, typically a 'compatible' string.
-This macro produces no code, but it is by dtoc tool.
-
-The parent_idx is the index of the parent driver_info structure within its
-linker list (instantiated by the U_BOOT_DRVINFO() macro). This is used to support
-dev_get_parent().
-
-During the build process dtoc parses both U_BOOT_DRIVER and DM_DRIVER_ALIAS
-to build a list of valid driver names and driver aliases. If the 'compatible'
-string used for a device does not not match a valid driver name, it will be
-checked against the list of driver aliases in order to get the right driver
-name to use. If in this step there is no match found a warning is issued to
-avoid run-time failures.
-
-Where a node has multiple compatible strings, a #define is used to make them
-equivalent, e.g.:
-
-.. code-block:: c
-
-    #define dtd_rockchip_rk3299_dw_mshc dtd_rockchip_rk3288_dw_mshc
-
-
-Converting of-platdata to a useful form
----------------------------------------
-
-Of course it would be possible to use the of-platdata directly in your driver
-whenever configuration information is required. However this means that the
-driver will not be able to support device tree, since the of-platdata
-structure is not available when device tree is used. It would make no sense
-to use this structure if device tree were available, since the structure has
-all the limitations metioned in caveats above.
-
-Therefore it is recommended that the of-platdata structure should be used
-only in the probe() method of your driver. It cannot be used in the
-of_to_plat() method since this is not called when platform data is
-already present.
-
-
-How to structure your driver
-----------------------------
-
-Drivers should always support device tree as an option. The of-platdata
-feature is intended as a add-on to existing drivers.
-
-Your driver should convert the plat struct in its probe() method. The
-existing device tree decoding logic should be kept in the
-of_to_plat() method and wrapped with #if.
-
-For example:
-
-.. code-block:: c
-
-    #include <dt-structs.h>
-
-    struct mmc_plat {
-    #if CONFIG_IS_ENABLED(OF_PLATDATA)
-            /* Put this first since driver model will copy the data here */
-            struct dtd_mmc dtplat;
-    #endif
-            /*
-             * Other fields can go here, to be filled in by decoding from
-             * the device tree (or the C structures when of-platdata is used).
-             */
-            int fifo_depth;
-    };
-
-    static int mmc_of_to_plat(struct udevice *dev)
-    {
-    #if !CONFIG_IS_ENABLED(OF_PLATDATA)
-            /* Decode the device tree data */
-            struct mmc_plat *plat = dev_get_plat(dev);
-            const void *blob = gd->fdt_blob;
-            int node = dev_of_offset(dev);
-
-            plat->fifo_depth = fdtdec_get_int(blob, node, "fifo-depth", 0);
-    #endif
-
-            return 0;
-    }
-
-    static int mmc_probe(struct udevice *dev)
-    {
-            struct mmc_plat *plat = dev_get_plat(dev);
-
-    #if CONFIG_IS_ENABLED(OF_PLATDATA)
-            /* Decode the of-platdata from the C structures */
-            struct dtd_mmc *dtplat = &plat->dtplat;
-
-            plat->fifo_depth = dtplat->fifo_depth;
-    #endif
-            /* Set up the device from the plat data */
-            writel(plat->fifo_depth, ...)
-    }
-
-    static const struct udevice_id mmc_ids[] = {
-            { .compatible = "vendor,mmc" },
-            { }
-    };
-
-    U_BOOT_DRIVER(mmc_drv) = {
-            .name           = "mmc_drv",
-            .id             = UCLASS_MMC,
-            .of_match       = mmc_ids,
-            .of_to_plat = mmc_of_to_plat,
-            .probe          = mmc_probe,
-            .priv_auto = sizeof(struct mmc_priv),
-            .plat_auto = sizeof(struct mmc_plat),
-    };
-
-    DM_DRIVER_ALIAS(mmc_drv, vendor_mmc) /* matches compatible string */
-
-Note that struct mmc_plat is defined in the C file, not in a header. This
-is to avoid needing to include dt-structs.h in a header file. The idea is to
-keep the use of each of-platdata struct to the smallest possible code area.
-There is just one driver C file for each struct, that can convert from the
-of-platdata struct to the standard one used by the driver.
-
-In the case where SPL_OF_PLATDATA is enabled, plat_auto is
-still used to allocate space for the platform data. This is different from
-the normal behaviour and is triggered by the use of of-platdata (strictly
-speaking it is a non-zero plat_size which triggers this).
-
-The of-platdata struct contents is copied from the C structure data to the
-start of the newly allocated area. In the case where device tree is used,
-the platform data is allocated, and starts zeroed. In this case the
-of_to_plat() method should still set up the platform data (and the
-of-platdata struct will not be present).
-
-SPL must use either of-platdata or device tree. Drivers cannot use both at
-the same time, but they must support device tree. Supporting of-platdata is
-optional.
-
-The device tree becomes in accessible when CONFIG_SPL_OF_PLATDATA is enabled,
-since the device-tree access code is not compiled in. A corollary is that
-a board can only move to using of-platdata if all the drivers it uses support
-it. There would be little point in having some drivers require the device
-tree data, since then libfdt would still be needed for those drivers and
-there would be no code-size benefit.
-
-Internals
----------
-
-The dt-structs.h file includes the generated file
-(include/generated//dt-structs.h) if CONFIG_SPL_OF_PLATDATA is enabled.
-Otherwise (such as in U-Boot proper) these structs are not available. This
-prevents them being used inadvertently. All usage must be bracketed with
-#if CONFIG_IS_ENABLED(OF_PLATDATA).
-
-The dt-plat.c file contains the device declarations and is is built in
-spl/dt-plat.c.
-
-The dm_populate_phandle_data() function that was previous needed has now been
-removed, since dtoc can address the drivers directly from dt-plat.c and does
-not need to fix up things at runtime.
-
-The pylibfdt Python module is used to access the devicetree.
-
-
-Credits
--------
-
-This is an implementation of an idea by Tom Rini <trini@konsulko.com>.
-
-
-Future work
------------
-- Consider programmatically reading binding files instead of device tree
-  contents
-
-
-.. Simon Glass <sjg@chromium.org>
-.. Google, Inc
-.. 6/6/16
-.. Updated Independence Day 2016
-.. Updated 1st October 2020
diff --git a/doc/imx/habv4/guides/mx6_mx7_secure_boot.txt b/doc/imx/habv4/guides/mx6_mx7_secure_boot.txt
index 20fff93..53f71fb 100644
--- a/doc/imx/habv4/guides/mx6_mx7_secure_boot.txt
+++ b/doc/imx/habv4/guides/mx6_mx7_secure_boot.txt
@@ -213,6 +213,30 @@
   HAB Configuration: 0xf0, HAB State: 0x66
   No HAB Events Found!
 
+1.6.1 Verifying HAB events in i.MX7ULP
+---------------------------------------
+
+When booting i.MX7ULP in low power or dual boot modes the M4 binary is
+authenticated by an independent HAB in M4 ROM code using a
+different SRK key set.
+
+The U-Boot provides a M4 option in hab_status command so users can retrieve
+M4 HAB failure and warning events.
+
+- Verify HAB M4 events:
+
+  => hab_status m4
+
+  Secure boot disabled
+
+  HAB Configuration: 0xf0, HAB State: 0x66
+  No HAB Events Found!
+
+As HAB M4 API cannot be called from A7 core the command is parsing the M4 HAB
+persistent memory region, M4 software should not modify this reserved region.
+
+Details about HAB persistent memory region can be found in AN12263[2].
+
 1.7 Closing the device
 -----------------------
 
@@ -400,3 +424,4 @@
 References:
 [1] AN4581: "Secure Boot on i.MX 50, i.MX 53, i.MX 6 and i.MX 7 Series using
  HABv4" - Rev 2.
+[2] AN12263: "HABv4 RVT Guidelines and Recommendations" - Rev 0.
diff --git a/doc/imx/index.rst b/doc/imx/index.rst
new file mode 100644
index 0000000..b225b1d
--- /dev/null
+++ b/doc/imx/index.rst
@@ -0,0 +1,9 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+NXP i.MX Machine-specific doc
+=============================
+
+.. toctree::
+   :maxdepth: 2
+
+   misc/index
diff --git a/doc/imx/misc/index.rst b/doc/imx/misc/index.rst
new file mode 100644
index 0000000..85fbdb6
--- /dev/null
+++ b/doc/imx/misc/index.rst
@@ -0,0 +1,9 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Miscellaneous
+=============
+
+.. toctree::
+   :maxdepth: 2
+
+   psb
diff --git a/doc/imx/misc/psb.rst b/doc/imx/misc/psb.rst
new file mode 100644
index 0000000..4d6f001
--- /dev/null
+++ b/doc/imx/misc/psb.rst
@@ -0,0 +1,174 @@
+i.MX7D/i.MX8MM SRC_GPR10 PERSIST_SECONDARY_BOOT for bootloader A/B switching
+============================================================================
+
+Introduction
+------------
+Since at least iMX53 until iMX8MM, it is possible to have two copies of
+bootloader in SD/eMMC and switch between them. The switch is triggered
+either by the BootROM in case the bootloader image is faulty OR can be
+enforced by the user.
+
+Operation
+---------
+ #. Upon Power-On Reset (POR)
+
+    - SRC_GPR10 bit PERSIST_SECONDARY_BOOT is set to 0
+    - BootROM attempts to start bootloader A-copy
+
+      - if A-copy valid
+
+         - BootROM starts A-copy
+         - END
+
+      - if A-copy NOT valid
+
+         - BootROM sets SRC_GPR10 bit PERSIST_SECONDARY_BOOT to 1
+         - BootROM triggers WARM reset, GOTO 1)
+         - END
+
+ #. Upon COLD Reset
+
+    - GOTO 1)
+    - END
+
+ #. Upon WARM Reset
+
+    - SRC_GPR10 bit PERSIST_SECONDARY_BOOT is retained
+
+      - if SRC_GPR10 bit PERSIST_SECONDARY_BOOT is 0
+
+        - BootROM attempts to start bootloader A-copy
+
+          - if A-copy valid
+
+            - BootROM starts A-copy
+            - END
+
+          - if A-copy NOT valid
+
+            - BootROM sets SRC_GPR10 bit PERSIST_SECONDARY_BOOT to 1
+            - BootROM triggers WARM reset. GOTO 1.3)
+            - END
+
+      - if SRC_GPR10 bit PERSIST_SECONDARY_BOOT is 1
+
+        - BootROM attempts to start bootloader B-copy
+
+          - if B-copy valid
+
+            - BootROM starts B-copy
+            - END
+
+          - if B-copy NOT valid
+            - System hangs
+            - END
+
+Setup
+-----
+The bootloader A-copy must be placed at predetermined offset in SD/eMMC. The
+bootloader B-copy area offset is determined by an offset stored in Secondary
+Image Table (SIT). The SIT must be placed at predetermined offset in SD/eMMC.
+
+The following table contains offset of SIT, bootloader A-copy and recommended
+bootloader B-copy offset. The offsets are in 512 Byte sector units (that is
+offset 0x1 means 512 Bytes from the start of SD/eMMC card data partition).
+For details on the addition of two numbers in recommended B-copy offset, see
+SIT format below.
+
++----------+--------------------+-----------------------+-----------------------------+
+|   SoC    | SIT offset (fixed) | A-copy offset (fixed) | B-copy offset (recommended) |
++----------+--------------------+-----------------------+-----------------------------+
+| iMX7D    |         0x1        |          0x2          |          0x800+0x2          |
++----------+--------------------+-----------------------+-----------------------------+
+| iMX8MM   |        0x41        |         0x42          |         0x1000+0x42         |
++----------+--------------------+-----------------------+-----------------------------+
+
+SIT format
+~~~~~~~~~~
+SIT is a 20 byte long structure containing of 5 32-bit words. Those encode
+bootloader B-copy area offset (called "firstSectorNumber"), magic value
+(called "tag") that is always 0x00112233, and three unused words set to 0.
+SIT is documented in [1] and [2]. Example SIT are below::
+
+  $ hexdump -vC sit-mx7d.bin
+    00000000  00 00 00 00
+    00000004  00 00 00 00
+    00000008  33 22 11 00 <--- This is the "tag"
+    0000000c  00 08 00 00 <--- This is the "firstSectorNumber"
+    00000010  00 00 00 00
+
+  $ hexdump -vC sit-mx8mm.bin
+    00000000  00 00 00 00
+    00000004  00 00 00 00
+    00000008  33 22 11 00 <--- This is the "tag"
+    0000000c  00 10 00 00 <--- This is the "firstSectorNumber"
+    00000010  00 00 00 00
+
+B-copy area offset ("firstSectorNumber") is offset, in units of 512 Byte
+sectors, that is added to the start of boot media when switching between
+A-copy and B-copy. For A-copy, this offset is 0x0. For B-copy, this offset
+is determined by SIT (e.g. if firstSectorNumber is 0x1000 as it is above
+in sit-mx8mm.bin, then the B-copy offset is 0x1000 sectors = 2 MiB).
+
+Bootloader A-copy (e.g. u-boot.imx or flash.bin) is placed at fixed offset
+from A-copy area offset (e.g. 0x2 sectors from sector 0x0 for iMX7D, which
+means u-boot.imx A-copy must be written to sector 0x2).
+
+The same applies to bootloader B-copy, which is placed at fixed offset from
+B-copy area offset determined by SIT (e.g. 0x2 sectors from sector 0x800 [see
+sit-mx7d.bin example above, this can be changed in SIT firstSectorNumber] for
+iMX7D, which means u-boot.imx B-copy must be written to sector 0x802)
+
+**WARNING:**
+B-copy area offset ("firstSectorNumber") is NOT equal to bootloader
+(image, which is u-boot.imx or flash.bin) B-copy offset.
+
+To generate SIT, use for example the following bourne shell printf command::
+
+$ printf '\x0\x0\x0\x0\x0\x0\x0\x0\x33\x22\x11\x00\x00\x08\x00\x00\x0\x0\x0\x0' > sit-mx7d.bin
+$ printf '\x0\x0\x0\x0\x0\x0\x0\x0\x33\x22\x11\x00\x00\x10\x00\x00\x0\x0\x0\x0' > sit-mx8mm.bin
+
+Write bootloader A/B copy and SIT to SD/eMMC
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Examples of writing SIT and two copies of bootloader to SD or eMMC:
+
+- iMX8MM, SD card at /dev/sdX, Linux command line
+  ::
+
+    $ dd if=sit-mx8mm.bin of=/dev/sdX bs=512 seek=65
+    $ dd if=flash.bin     of=/dev/sdX bs=512 seek=66
+    $ dd if=flash.bin     of=/dev/sdX bs=512 seek=4162
+
+- iMX8MM, eMMC 1 data partition, U-Boot command line
+  ::
+
+    => mmc partconf 1 0 0 0
+
+    => dhcp ${loadaddr} sit-mx8mm.bin
+    => mmc dev 1
+    => mmc write ${loadaddr} 0x41 0x1
+
+    => dhcp ${loadaddr} flash.bin
+    => setexpr blkcnt ${filesize} + 0x1ff && setexpr blkcnt
+    => mmc dev 1
+    => mmc write ${loadaddr} 0x42   ${blkcnt}
+    => mmc write ${loadaddr} 0x1042 ${blkcnt}
+
+WARM reset into B-copy using WDT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To perform a reboot into B-copy, the PERSIST_SECONDARY_BOOT must be set
+in SRC_GPR0 register. Example on iMX8MM::
+
+  => mw 0x30390098 0x40000000
+
+A WARM reset can be triggered using WDT as follows::
+
+  => mw.w 0x30280000 0x25
+
+References
+----------
+
+.. [1] i.MX 7Dual Applications Processor Reference Manual, Rev. 1, 01/2018 ; section 6.6.5.3.5 Redundant boot support for expansion device
+.. [2] i.MX 8M Mini Applications Processor Reference Manual, Rev. 3, 11/2020 ; section 6.1.5.4.5 Redundant boot support for expansion device
diff --git a/doc/index.rst b/doc/index.rst
index 4c44955..8066fcb 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -38,29 +38,6 @@
 
    develop/index
 
-Unified Extensible Firmware (UEFI)
-----------------------------------
-
-U-Boot provides an implementation of the UEFI API allowing to run UEFI
-compliant software like Linux, GRUB, and iPXE. Furthermore U-Boot itself
-can be run an UEFI payload.
-
-.. toctree::
-   :maxdepth: 2
-
-   uefi/index
-
-Driver-Model documentation
---------------------------
-
-The following holds information on the U-Boot device driver framework:
-driver-model, including the design details of itself and several driver
-subsystems.
-
-.. toctree::
-   :maxdepth: 2
-
-   driver-model/index
 
 U-Boot API documentation
 ------------------------
@@ -87,6 +64,17 @@
 
    arch/index
 
+Machine-specific doc
+--------------------
+
+These books provide programming details about machine-specific
+implementation.
+
+.. toctree::
+   :maxdepth: 2
+
+   imx/index
+
 Board-specific doc
 ------------------
 
@@ -110,6 +98,14 @@
 
    android/index
 
+Chromium OS-specific doc
+------------------------
+
+.. toctree::
+   :maxdepth: 2
+
+   chromium/index
+
 Indices and tables
 ==================
 
diff --git a/doc/uefi/index.rst b/doc/uefi/index.rst
deleted file mode 100644
index b790a91..0000000
--- a/doc/uefi/index.rst
+++ /dev/null
@@ -1,11 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-
-Unified Extensible Firmware (UEFI)
-==================================
-
-.. toctree::
-   :maxdepth: 2
-
-   uefi.rst
-   u-boot_on_efi.rst
-   iscsi.rst
diff --git a/doc/usage/fit.rst b/doc/usage/fit.rst
new file mode 100644
index 0000000..7037434
--- /dev/null
+++ b/doc/usage/fit.rst
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Flat Image Tree (FIT)
+=====================
+
+U-Boot uses Flat Image Tree (FIT) as a standard file format for packaging
+images that it it reads and boots. Documentation about FIT is available at
+doc/uImage.FIT
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 6c59bba..5faf279 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -6,6 +6,7 @@
 
    dfu
    fdt_overlays
+   fit
    netconsole
    partitions
 
@@ -21,6 +22,7 @@
    booti
    bootmenu
    button
+   x86/cbsysinfo
    conitrace
    echo
    exception
@@ -30,7 +32,9 @@
    load
    loady
    mbr
+   md
    pstore
    qfw
    sbi
    true
+   scp03
diff --git a/doc/usage/md.rst b/doc/usage/md.rst
new file mode 100644
index 0000000..4c1073e
--- /dev/null
+++ b/doc/usage/md.rst
@@ -0,0 +1,106 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+md command
+==========
+
+Synopis
+-------
+
+::
+
+    md <address>[<data_size>] [<length>]
+
+Description
+-----------
+
+The md command is used to dump the contents of memory. It uses a standard
+format that includes the address, hex data and ASCII display. It supports
+various data sizes and uses the endianness of the target.
+
+The specified data_size and length become the defaults for future memory
+commands commands.
+
+address
+    start address to display
+
+data_size
+    size of each value to display (defaults to .l):
+
+    =========  ===================
+    data_size  Output size
+    =========  ===================
+    .b         byte
+    .w         word (16 bits)
+    .l         long (32 bits)
+    .q         quadword (64 bits)
+    =========  ===================
+
+length
+    number of values to dump. Defaults to 40 (0d64). Note that this is not
+    the same as the number of bytes, unless .b is used.
+
+Note that the format of 'md.b' can be emulated from linux with::
+
+    # This works but requires using sed to get the extra spaces
+    # <addr> is the address, <f> is the filename
+    xxd -o <addr> -g1 <f> |sed 's/  /    /' >bad
+
+    # This uses a single tool but the offset always starts at 0
+    # <f> is the filename
+    hexdump -v -e '"%08.8_ax: " 16/1 "%02x " "    "' -e '16/1 "%_p" "\n" ' <f>
+
+
+Example
+-------
+
+::
+
+    => md 10000
+    00010000: 00010000 00000000 f0f30f00 00005596    .............U..
+    00010010: 10011010 00000000 10011010 00000000    ................
+    00010020: 10011050 00000000 b96d4cd8 00007fff    P........Lm.....
+    00010030: 00000000 00000000 f0f30f18 00005596    .............U..
+    00010040: 10011040 00000000 10011040 00000000    @.......@.......
+    00010050: b96d4cd8 00007fff 10011020 00000000    .Lm..... .......
+    00010060: 00000003 000000c3 00000000 00000000    ................
+    00010070: 00000000 00000000 f0e892f3 00005596    .............U..
+    00010080: 00000000 000000a1 00000000 00000000    ................
+    00010090: 00000000 00000000 f0e38aa6 00005596    .............U..
+    000100a0: 00000000 000000a6 00000022 00000000    ........".......
+    000100b0: 00000001 00000000 f0e38aa1 00005596    .............U..
+    000100c0: 00000000 000000be 00000000 00000000    ................
+    000100d0: 00000000 00000000 00000000 00000000    ................
+    000100e0: 00000000 00000000 00000000 00000000    ................
+    000100f0: 00000000 00000000 00000000 00000000    ................
+    => md.b 10000
+    00010000: 00 00 01 00 00 00 00 00 00 0f f3 f0 96 55 00 00    .............U..
+    00010010: 10 10 01 10 00 00 00 00 10 10 01 10 00 00 00 00    ................
+    00010020: 50 10 01 10 00 00 00 00 d8 4c 6d b9 ff 7f 00 00    P........Lm.....
+    00010030: 00 00 00 00 00 00 00 00 18 0f f3 f0 96 55 00 00    .............U..
+    => md.b 10000 10
+    00010000: 00 00 01 00 00 00 00 00 00 0f f3 f0 96 55 00 00    .............U..
+    =>
+    00010010: 10 10 01 10 00 00 00 00 10 10 01 10 00 00 00 00    ................
+    =>
+    00010020: 50 10 01 10 00 00 00 00 d8 4c 6d b9 ff 7f 00 00    P........Lm.....
+    =>
+    => md.q 10000
+    00010000: 0000000000010000 00005596f0f30f00    .............U..
+    00010010: 0000000010011010 0000000010011010    ................
+    00010020: 0000000010011050 00007fffb96d4cd8    P........Lm.....
+    00010030: 0000000000000000 00005596f0f30f18    .............U..
+    00010040: 0000000010011040 0000000010011040    @.......@.......
+    00010050: 00007fffb96d4cd8 0000000010011020    .Lm..... .......
+    00010060: 000000c300000003 0000000000000000    ................
+    00010070: 0000000000000000 00005596f0e892f3    .............U..
+
+The empty commands cause a 'repeat', so that md shows the next available data
+in the same format as before.
+
+
+Return value
+------------
+
+The return value $? is always 0 (true).
+
+
diff --git a/doc/usage/scp03.rst b/doc/usage/scp03.rst
new file mode 100644
index 0000000..7ff87ed
--- /dev/null
+++ b/doc/usage/scp03.rst
@@ -0,0 +1,33 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+scp03 command
+=============
+
+Synopsis
+--------
+
+::
+
+    scp03 enable
+    scp03 provision
+
+Description
+-----------
+
+The *scp03* command calls into a Trusted Application executing in a
+Trusted Execution Environment to enable (if present) the Secure
+Channel Protocol 03 stablished between the processor and the secure
+element.
+
+This protocol encrypts all the communication between the processor and
+the secure element using a set of pre-defined keys. These keys can be
+rotated (provisioned) using the *provision* request.
+
+See also
+--------
+
+For some information on the internals implemented in the TEE, please
+check the GlobalPlatform documentation on `Secure Channel Protocol '03'`_
+
+.. _Secure Channel Protocol '03':
+   https://globalplatform.org/wp-content/uploads/2014/07/GPC_2.3_D_SCP03_v1.1.2_PublicRelease.pdf
diff --git a/doc/usage/x86/cbsysinfo.rst b/doc/usage/x86/cbsysinfo.rst
new file mode 100644
index 0000000..8c03a85
--- /dev/null
+++ b/doc/usage/x86/cbsysinfo.rst
@@ -0,0 +1,25 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+cbsysinfo
+=========
+
+Synopis
+-------
+
+::
+
+    cbsysinfo
+
+
+Description
+-----------
+
+This displays information obtained from the coreboot sysinfo table. It is only
+useful when booting U-Boot from coreboot.
+
+Example
+-------
+
+::
+
+    => cbsysinfo
diff --git a/drivers/Makefile b/drivers/Makefile
index c562a71..3510dab 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -38,7 +38,7 @@
 
 obj-$(CONFIG_SPL_BOOTCOUNT_LIMIT) += bootcount/
 obj-$(CONFIG_SPL_CACHE_SUPPORT) += cache/
-obj-$(CONFIG_SPL_CPU_SUPPORT) += cpu/
+obj-$(CONFIG_SPL_CPU) += cpu/
 obj-$(CONFIG_SPL_CRYPTO_SUPPORT) += crypto/
 obj-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/
 obj-$(CONFIG_ARMADA_38X) += ddr/marvell/a38x/
diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c
index e2f229b..1c2c3b4 100644
--- a/drivers/block/sandbox.c
+++ b/drivers/block/sandbox.c
@@ -89,7 +89,7 @@
 }
 
 #ifdef CONFIG_BLK
-int host_dev_bind(int devnum, char *filename)
+int host_dev_bind(int devnum, char *filename, bool removable)
 {
 	struct host_block_dev *host_dev;
 	struct udevice *dev;
@@ -146,7 +146,7 @@
 	}
 
 	desc = blk_get_devnum_by_type(IF_TYPE_HOST, devnum);
-	desc->removable = 1;
+	desc->removable = removable;
 	snprintf(desc->vendor, BLK_VEN_SIZE, "U-Boot");
 	snprintf(desc->product, BLK_PRD_SIZE, "hostfile");
 	snprintf(desc->revision, BLK_REV_SIZE, "1.0");
@@ -160,7 +160,7 @@
 	return ret;
 }
 #else
-int host_dev_bind(int dev, char *filename)
+int host_dev_bind(int dev, char *filename, bool removable)
 {
 	struct host_block_dev *host_dev = find_host_device(dev);
 
@@ -195,7 +195,7 @@
 	blk_dev->block_write = host_block_write;
 	blk_dev->devnum = dev;
 	blk_dev->part_type = PART_TYPE_UNKNOWN;
-	blk_dev->removable = 1;
+	blk_dev->removable = removable;
 	snprintf(blk_dev->vendor, BLK_VEN_SIZE, "U-Boot");
 	snprintf(blk_dev->product, BLK_PRD_SIZE, "hostfile");
 	snprintf(blk_dev->revision, BLK_REV_SIZE, "1.0");
diff --git a/drivers/clk/aspeed/clk_ast2600.c b/drivers/clk/aspeed/clk_ast2600.c
index acb7eca..3a92739 100644
--- a/drivers/clk/aspeed/clk_ast2600.c
+++ b/drivers/clk/aspeed/clk_ast2600.c
@@ -1140,7 +1140,7 @@
 
 		clk_free(&clk);
 
-		if (ret == -ENOTSUPP) {
+		if (ret == -EINVAL) {
 			printf("clk ID %lu not supported yet\n",
 			       aspeed_clk_names[i].id);
 			continue;
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 7e99c5b..bb5351e 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -37,10 +37,10 @@
 	const struct clk_ops *mux_ops = composite->mux_ops;
 	struct clk *mux = composite->mux;
 
-	if (mux && mux_ops)
-		return mux_ops->set_parent(mux, parent);
-	else
-		return -ENOTSUPP;
+	if (!mux || !mux_ops)
+		return -ENOSYS;
+
+	return mux_ops->set_parent(mux, parent);
 }
 
 static unsigned long clk_composite_recalc_rate(struct clk *clk)
diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c
index 449b430..26b0aa9 100644
--- a/drivers/clk/clk-hsdk-cgu.c
+++ b/drivers/clk/clk-hsdk-cgu.c
@@ -718,7 +718,7 @@
 	if (clk->map[sclk->id].set_rate)
 		return clk->map[sclk->id].set_rate(sclk, rate);
 
-	return -ENOTSUPP;
+	return -EINVAL;
 }
 
 static int hsdk_cgu_disable(struct clk *sclk)
@@ -731,7 +731,7 @@
 	if (clk->map[sclk->id].disable)
 		return clk->map[sclk->id].disable(sclk);
 
-	return -ENOTSUPP;
+	return -EINVAL;
 }
 
 static const struct clk_ops hsdk_cgu_ops = {
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index b87288d..4ab3c40 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -39,7 +39,7 @@
 {
 	int ret;
 
-	ret = device_get_by_driver_info_idx(cells->idx, &clk->dev);
+	ret = device_get_by_ofplat_idx(cells->idx, &clk->dev);
 	if (ret)
 		return ret;
 	clk->id = cells->arg[0];
diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c
index 3c5a83c..09f9ef2 100644
--- a/drivers/clk/clk_fixed_rate.c
+++ b/drivers/clk/clk_fixed_rate.c
@@ -25,18 +25,24 @@
 	.enable = dummy_enable,
 };
 
-static int clk_fixed_rate_of_to_plat(struct udevice *dev)
+void clk_fixed_rate_ofdata_to_plat_(struct udevice *dev,
+				    struct clk_fixed_rate *plat)
 {
-	struct clk *clk = &to_clk_fixed_rate(dev)->clk;
+	struct clk *clk = &plat->clk;
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
-	to_clk_fixed_rate(dev)->fixed_rate =
-		dev_read_u32_default(dev, "clock-frequency", 0);
+	plat->fixed_rate = dev_read_u32_default(dev, "clock-frequency", 0);
 #endif
 	/* Make fixed rate clock accessible from higher level struct clk */
 	/* FIXME: This is not allowed */
 	dev_set_uclass_priv(dev, clk);
+
 	clk->dev = dev;
 	clk->enable_count = 0;
+}
+
+static int clk_fixed_rate_of_to_plat(struct udevice *dev)
+{
+	clk_fixed_rate_ofdata_to_plat_(dev, to_clk_fixed_rate(dev));
 
 	return 0;
 }
diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c
index b28b67b..57acf7d 100644
--- a/drivers/clk/clk_sandbox.c
+++ b/drivers/clk/clk_sandbox.c
@@ -9,13 +9,7 @@
 #include <errno.h>
 #include <malloc.h>
 #include <asm/clk.h>
-
-struct sandbox_clk_priv {
-	bool probed;
-	ulong rate[SANDBOX_CLK_ID_COUNT];
-	bool enabled[SANDBOX_CLK_ID_COUNT];
-	bool requested[SANDBOX_CLK_ID_COUNT];
-};
+#include <linux/clk-provider.h>
 
 static ulong sandbox_clk_get_rate(struct clk *clk)
 {
@@ -178,3 +172,35 @@
 		return -EINVAL;
 	return priv->requested[id];
 }
+
+int clk_fixed_rate_of_to_plat(struct udevice *dev)
+{
+	struct clk_fixed_rate *cplat;
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct sandbox_clk_fixed_rate_plat *plat = dev_get_plat(dev);
+
+	cplat = &plat->fixed;
+	cplat->fixed_rate = plat->dtplat.clock_frequency;
+#else
+	cplat = to_clk_fixed_rate(dev);
+#endif
+	clk_fixed_rate_ofdata_to_plat_(dev, cplat);
+
+	return 0;
+}
+
+static const struct udevice_id sandbox_clk_fixed_rate_match[] = {
+	{ .compatible = "sandbox,fixed-clock" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(sandbox_fixed_clock) = {
+	.name = "sandbox_fixed_clock",
+	.id = UCLASS_CLK,
+	.of_match = sandbox_clk_fixed_rate_match,
+	.of_to_plat = clk_fixed_rate_of_to_plat,
+	.plat_auto = sizeof(struct sandbox_clk_fixed_rate_plat),
+	.ops = &clk_fixed_rate_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c
index c4e4481..f665fd3 100644
--- a/drivers/clk/clk_sandbox_test.c
+++ b/drivers/clk/clk_sandbox_test.c
@@ -11,12 +11,6 @@
 #include <dm/device_compat.h>
 #include <linux/err.h>
 
-struct sandbox_clk_test {
-	struct clk clks[SANDBOX_CLK_TEST_NON_DEVM_COUNT];
-	struct clk *clkps[SANDBOX_CLK_TEST_ID_COUNT];
-	struct clk_bulk bulk;
-};
-
 static const char * const sandbox_clk_test_names[] = {
 	[SANDBOX_CLK_TEST_ID_FIXED] = "fixed",
 	[SANDBOX_CLK_TEST_ID_SPI] = "spi",
diff --git a/drivers/clk/clk_zynqmp.c b/drivers/clk/clk_zynqmp.c
index 609d8e3..13a623f 100644
--- a/drivers/clk/clk_zynqmp.c
+++ b/drivers/clk/clk_zynqmp.c
@@ -97,8 +97,7 @@
 #define CLK_CTRL_DIV1_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT)
 #define CLK_CTRL_DIV0_SHIFT	8
 #define CLK_CTRL_DIV0_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT)
-#define CLK_CTRL_SRCSEL_SHIFT	0
-#define CLK_CTRL_SRCSEL_MASK	(0x3 << CLK_CTRL_SRCSEL_SHIFT)
+#define CLK_CTRL_SRCSEL_MASK	0x7
 #define PLLCTRL_FBDIV_MASK	0x7f00
 #define PLLCTRL_FBDIV_SHIFT	8
 #define PLLCTRL_RESET_MASK	1
@@ -132,7 +131,7 @@
 	iou_switch,
 	gem_tsu_ref, gem_tsu,
 	gem0_ref, gem1_ref, gem2_ref, gem3_ref,
-	gem0_rx, gem1_rx, gem2_rx, gem3_rx,
+	gem0_tx, gem1_tx, gem2_tx, gem3_tx,
 	qspi_ref,
 	sdio0_ref, sdio1_ref,
 	uart0_ref, uart1_ref,
@@ -152,7 +151,7 @@
 	"iopll", "rpll", "apll", "dpll",
 	"vpll", "iopll_to_fpd", "rpll_to_fpd",
 	"apll_to_lpd", "dpll_to_lpd", "vpll_to_lpd",
-	"acpu", "acpu_half", "dbf_fpd", "dbf_lpd",
+	"acpu", "acpu_half", "dbg_fpd", "dbg_lpd",
 	"dbg_trace", "dbg_tstmp", "dp_video_ref",
 	"dp_audio_ref", "dp_stc_ref", "gdma_ref",
 	"dpdma_ref", "ddr_ref", "sata_ref", "pcie_ref",
@@ -172,6 +171,38 @@
 	"ams_ref", "pl0", "pl1", "pl2", "pl3", "wdt"
 };
 
+static const u32 pll_src[][4] = {
+	{apll, 0xff, dpll, vpll},		/* acpu */
+	{dpll, vpll, 0xff, 0xff},		/* ddr_ref */
+	{rpll, iopll, 0xff, 0xff},		/* dll_ref */
+	{iopll, 0xff, rpll, dpll_to_lpd},	/* gem_tsu_ref */
+	{iopll, 0xff, rpll, dpll},		/* peripheral */
+	{apll, 0xff, iopll_to_fpd, dpll},	/* wdt */
+	{iopll_to_fpd, 0xff, dpll, apll},	/* dbg_fpd */
+	{iopll, 0xff, rpll, dpll_to_lpd},	/* timestamp_ref */
+	{iopll_to_fpd, 0xff, apll, dpll},	/* sata_ref */
+	{iopll_to_fpd, 0xff, rpll_to_fpd, dpll},/* pcie_ref */
+	{iopll_to_fpd, 0xff, vpll, dpll},	/* gpu_ref */
+	{apll, 0xff, vpll, dpll},		/* topsw_main_ref */
+	{rpll, 0xff, iopll, dpll_to_lpd},	/* cpu_r5_ref */
+};
+
+enum zynqmp_clk_pll_src {
+	ACPU_CLK_SRC = 0,
+	DDR_CLK_SRC,
+	DLL_CLK_SRC,
+	GEM_TSU_CLK_SRC,
+	PERI_CLK_SRC,
+	WDT_CLK_SRC,
+	DBG_FPD_CLK_SRC,
+	TIMESTAMP_CLK_SRC,
+	SATA_CLK_SRC,
+	PCIE_CLK_SRC,
+	GPU_CLK_SRC,
+	TOPSW_MAIN_CLK_SRC,
+	CPU_R5_CLK_SRC
+};
+
 struct zynqmp_clk_priv {
 	unsigned long ps_clk_freq;
 	unsigned long video_clk;
@@ -195,12 +226,38 @@
 		return CRF_APB_VPLL_CTRL;
 	case acpu:
 		return CRF_APB_ACPU_CTRL;
+	case dbg_fpd:
+		return CRF_APB_DBG_FPD_CTRL;
+	case dbg_trace:
+		return CRF_APB_DBG_TRACE_CTRL;
+	case dbg_tstmp:
+		return CRF_APB_DBG_TSTMP_CTRL;
+	case gpu_ref ...  gpu_pp1_ref:
+		return CRF_APB_GPU_REF_CTRL;
 	case ddr_ref:
 		return CRF_APB_DDR_CTRL;
+	case sata_ref:
+		return CRF_APB_SATA_REF_CTRL;
+	case pcie_ref:
+		return CRF_APB_PCIE_REF_CTRL;
+	case gdma_ref:
+		return CRF_APB_GDMA_REF_CTRL;
+	case dpdma_ref:
+		return CRF_APB_DPDMA_REF_CTRL;
+	case topsw_main:
+		return CRF_APB_TOPSW_MAIN_CTRL;
+	case topsw_lsbus:
+		return CRF_APB_TOPSW_LSBUS_CTRL;
+	case lpd_switch:
+		return CRL_APB_LPD_SWITCH_CTRL;
+	case lpd_lsbus:
+		return CRL_APB_LPD_LSBUS_CTRL;
 	case qspi_ref:
 		return CRL_APB_QSPI_REF_CTRL;
 	case usb3_dual_ref:
 		return CRL_APB_USB3_DUAL_REF_CTRL;
+	case gem_tsu_ref:
+		return CRL_APB_GEM_TSU_REF_CTRL;
 	case gem0_ref:
 		return CRL_APB_GEM0_REF_CTRL;
 	case gem1_ref:
@@ -213,6 +270,8 @@
 		return CRL_APB_USB0_BUS_REF_CTRL;
 	case usb1_bus_ref:
 		return CRL_APB_USB1_BUS_REF_CTRL;
+	case cpu_r5:
+		return CRL_APB_CPU_R5_CTRL;
 	case uart0_ref:
 		return CRL_APB_UART0_REF_CTRL;
 	case uart1_ref:
@@ -235,6 +294,14 @@
 		return CRL_APB_CAN0_REF_CTRL;
 	case can1_ref:
 		return CRL_APB_CAN1_REF_CTRL;
+	case dll_ref:
+		return CRL_APB_DLL_REF_CTRL;
+	case adma_ref:
+		return CRL_APB_ADMA_REF_CTRL;
+	case timestamp_ref:
+		return CRL_APB_TIMESTAMP_REF_CTRL;
+	case ams_ref:
+		return CRL_APB_AMS_REF_CTRL;
 	case pl0:
 		return CRL_APB_PL0_REF_CTRL;
 	case pl1:
@@ -253,68 +320,6 @@
 	return 0;
 }
 
-static enum zynqmp_clk zynqmp_clk_get_cpu_pll(u32 clk_ctrl)
-{
-	u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
-		      CLK_CTRL_SRCSEL_SHIFT;
-
-	switch (srcsel) {
-	case 2:
-		return dpll;
-	case 3:
-		return vpll;
-	case 0 ... 1:
-	default:
-		return apll;
-	}
-}
-
-static enum zynqmp_clk zynqmp_clk_get_ddr_pll(u32 clk_ctrl)
-{
-	u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
-		      CLK_CTRL_SRCSEL_SHIFT;
-
-	switch (srcsel) {
-	case 1:
-		return vpll;
-	case 0:
-	default:
-		return dpll;
-	}
-}
-
-static enum zynqmp_clk zynqmp_clk_get_peripheral_pll(u32 clk_ctrl)
-{
-	u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
-		      CLK_CTRL_SRCSEL_SHIFT;
-
-	switch (srcsel) {
-	case 2:
-		return rpll;
-	case 3:
-		return dpll;
-	case 0 ... 1:
-	default:
-		return iopll;
-	}
-}
-
-static enum zynqmp_clk zynqmp_clk_get_wdt_pll(u32 clk_ctrl)
-{
-	u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
-		      CLK_CTRL_SRCSEL_SHIFT;
-
-	switch (srcsel) {
-	case 2:
-		return iopll_to_fpd;
-	case 3:
-		return dpll;
-	case 0 ... 1:
-	default:
-		return apll;
-	}
-}
-
 static ulong zynqmp_clk_get_pll_src(ulong clk_ctrl,
 				    struct zynqmp_clk_priv *priv,
 				    bool is_pre_src)
@@ -378,7 +383,7 @@
 static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
 				     enum zynqmp_clk id)
 {
-	u32 clk_ctrl, div;
+	u32 clk_ctrl, div, srcsel;
 	enum zynqmp_clk pll;
 	int ret;
 	unsigned long pllrate;
@@ -391,7 +396,8 @@
 
 	div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
 
-	pll = zynqmp_clk_get_cpu_pll(clk_ctrl);
+	srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
+	pll = pll_src[ACPU_CLK_SRC][srcsel];
 	pllrate = zynqmp_clk_get_pll_rate(priv, pll);
 	if (IS_ERR_VALUE(pllrate))
 		return pllrate;
@@ -401,7 +407,7 @@
 
 static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
 {
-	u32 clk_ctrl, div;
+	u32 clk_ctrl, div, srcsel;
 	enum zynqmp_clk pll;
 	int ret;
 	ulong pllrate;
@@ -414,7 +420,8 @@
 
 	div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
 
-	pll = zynqmp_clk_get_ddr_pll(clk_ctrl);
+	srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
+	pll = pll_src[DDR_CLK_SRC][srcsel];
 	pllrate = zynqmp_clk_get_pll_rate(priv, pll);
 	if (IS_ERR_VALUE(pllrate))
 		return pllrate;
@@ -422,11 +429,33 @@
 	return DIV_ROUND_CLOSEST(pllrate, div);
 }
 
+static ulong zynqmp_clk_get_dll_rate(struct zynqmp_clk_priv *priv)
+{
+	u32 clk_ctrl, srcsel;
+	enum zynqmp_clk pll;
+	ulong pllrate;
+	int ret;
+
+	ret = zynqmp_mmio_read(CRL_APB_DLL_REF_CTRL, &clk_ctrl);
+	if (ret) {
+		printf("%s mio read fail\n", __func__);
+		return -EIO;
+	}
+
+	srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
+	pll = pll_src[DLL_CLK_SRC][srcsel];
+	pllrate = zynqmp_clk_get_pll_rate(priv, pll);
+	if (IS_ERR_VALUE(pllrate))
+		return pllrate;
+
+	return pllrate;
+}
+
 static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
-					  enum zynqmp_clk id, bool two_divs)
+					    enum zynqmp_clk id, bool two_divs)
 {
 	enum zynqmp_clk pll;
-	u32 clk_ctrl, div0;
+	u32 clk_ctrl, div0, srcsel;
 	u32 div1 = 1;
 	int ret;
 	ulong pllrate;
@@ -446,8 +475,13 @@
 		if (!div1)
 			div1 = 1;
 	}
+	srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
 
-	pll = zynqmp_clk_get_peripheral_pll(clk_ctrl);
+	if (id == gem_tsu_ref)
+		pll = pll_src[GEM_TSU_CLK_SRC][srcsel];
+	else
+		pll = pll_src[PERI_CLK_SRC][srcsel];
+
 	pllrate = zynqmp_clk_get_pll_rate(priv, pll);
 	if (IS_ERR_VALUE(pllrate))
 		return pllrate;
@@ -457,11 +491,11 @@
 			DIV_ROUND_CLOSEST(pllrate, div0), div1);
 }
 
-static ulong zynqmp_clk_get_wdt_rate(struct zynqmp_clk_priv *priv,
-				     enum zynqmp_clk id, bool two_divs)
+static ulong zynqmp_clk_get_crf_crl_rate(struct zynqmp_clk_priv *priv,
+					 enum zynqmp_clk id, bool two_divs)
 {
 	enum zynqmp_clk pll;
-	u32 clk_ctrl, div0;
+	u32 clk_ctrl, div0, srcsel;
 	u32 div1 = 1;
 	int ret;
 	ulong pllrate;
@@ -475,8 +509,45 @@
 	div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
 	if (!div0)
 		div0 = 1;
+	srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
 
-	pll = zynqmp_clk_get_wdt_pll(clk_ctrl);
+	switch (id) {
+	case wdt:
+	case dbg_trace:
+	case topsw_lsbus:
+		pll = pll_src[WDT_CLK_SRC][srcsel];
+		break;
+	case dbg_fpd:
+	case dbg_tstmp:
+		pll = pll_src[DBG_FPD_CLK_SRC][srcsel];
+		break;
+	case timestamp_ref:
+		pll = pll_src[TIMESTAMP_CLK_SRC][srcsel];
+		break;
+	case sata_ref:
+		pll = pll_src[SATA_CLK_SRC][srcsel];
+		break;
+	case pcie_ref:
+		pll = pll_src[PCIE_CLK_SRC][srcsel];
+		break;
+	case gpu_ref ... gpu_pp1_ref:
+		pll = pll_src[GPU_CLK_SRC][srcsel];
+		break;
+	case gdma_ref:
+	case dpdma_ref:
+	case topsw_main:
+		pll = pll_src[TOPSW_MAIN_CLK_SRC][srcsel];
+		break;
+	case cpu_r5:
+	case ams_ref:
+	case adma_ref:
+	case lpd_lsbus:
+	case lpd_switch:
+		pll = pll_src[CPU_R5_CLK_SRC][srcsel];
+		break;
+	default:
+		return -ENXIO;
+	}
 	if (two_divs) {
 		ret = zynqmp_mmio_read(zynqmp_clk_get_register(pll), &clk_ctrl);
 		if (ret) {
@@ -533,7 +604,7 @@
 	enum zynqmp_clk pll;
 	u32 clk_ctrl, div0 = 0, div1 = 0;
 	ulong pll_rate, new_rate;
-	u32 reg;
+	u32 reg, srcsel;
 	int ret;
 	u32 mask;
 
@@ -544,7 +615,8 @@
 		return -EIO;
 	}
 
-	pll = zynqmp_clk_get_peripheral_pll(clk_ctrl);
+	srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
+	pll = pll_src[PERI_CLK_SRC][srcsel];
 	pll_rate = zynqmp_clk_get_pll_rate(priv, pll);
 	if (IS_ERR_VALUE(pll_rate))
 		return pll_rate;
@@ -588,14 +660,31 @@
 		return zynqmp_clk_get_cpu_rate(priv, id);
 	case ddr_ref:
 		return zynqmp_clk_get_ddr_rate(priv);
+	case dll_ref:
+		return zynqmp_clk_get_dll_rate(priv);
+	case gem_tsu_ref:
+	case pl0 ... pl3:
 	case gem0_ref ... gem3_ref:
 	case qspi_ref ... can1_ref:
-	case pl0 ... pl3:
+	case usb0_bus_ref ... usb3_dual_ref:
 		two_divs = true;
 		return zynqmp_clk_get_peripheral_rate(priv, id, two_divs);
 	case wdt:
+	case topsw_lsbus:
+	case sata_ref ... gpu_pp1_ref:
 		two_divs = true;
-		return zynqmp_clk_get_wdt_rate(priv, id, two_divs);
+	case cpu_r5:
+	case dbg_fpd:
+	case ams_ref:
+	case adma_ref:
+	case lpd_lsbus:
+	case dbg_trace:
+	case dbg_tstmp:
+	case lpd_switch:
+	case topsw_main:
+	case timestamp_ref:
+	case gdma_ref ... dpdma_ref:
+		return zynqmp_clk_get_crf_crl_rate(priv, id, two_divs);
 	default:
 		return -ENXIO;
 	}
diff --git a/drivers/clk/imx/clk-imx8.c b/drivers/clk/imx/clk-imx8.c
index 8484613..b3dc138 100644
--- a/drivers/clk/imx/clk-imx8.c
+++ b/drivers/clk/imx/clk-imx8.c
@@ -29,7 +29,7 @@
 
 __weak int __imx8_clk_enable(struct clk *clk, bool enable)
 {
-	return -ENOTSUPP;
+	return -EINVAL;
 }
 
 static int imx8_clk_disable(struct clk *clk)
@@ -70,7 +70,7 @@
 
 		clk_free(&clk);
 
-		if (ret == -ENOTSUPP) {
+		if (ret == -EINVAL) {
 			printf("clk ID %lu not supported yet\n",
 			       imx8_clk_names[i].id);
 			continue;
diff --git a/drivers/clk/imx/clk-imx8qm.c b/drivers/clk/imx/clk-imx8qm.c
index 7e466d6..7759dc6 100644
--- a/drivers/clk/imx/clk-imx8qm.c
+++ b/drivers/clk/imx/clk-imx8qm.c
@@ -133,7 +133,7 @@
 			       __func__, clk->id);
 			return -EINVAL;
 		}
-		return -ENOTSUPP;
+		return -EINVAL;
 	};
 
 	ret = sc_pm_get_clock_rate(-1, resource, pm_clk,
@@ -237,7 +237,7 @@
 			       __func__, clk->id);
 			return -EINVAL;
 		}
-		return -ENOTSUPP;
+		return -EINVAL;
 	};
 
 	ret = sc_pm_set_clock_rate(-1, resource, pm_clk, &new_rate);
@@ -337,7 +337,7 @@
 			       __func__, clk->id);
 			return -EINVAL;
 		}
-		return -ENOTSUPP;
+		return -EINVAL;
 	}
 
 	ret = sc_pm_clock_enable(-1, resource, pm_clk, enable, 0);
diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c
index e6b2fb4..ffa2fce 100644
--- a/drivers/clk/imx/clk-imx8qxp.c
+++ b/drivers/clk/imx/clk-imx8qxp.c
@@ -126,7 +126,7 @@
 			       __func__, clk->id);
 			return -EINVAL;
 		}
-		return -ENOTSUPP;
+		return -EINVAL;
 	};
 
 	ret = sc_pm_get_clock_rate(-1, resource, pm_clk,
@@ -221,7 +221,7 @@
 			       __func__, clk->id);
 			return -EINVAL;
 		}
-		return -ENOTSUPP;
+		return -EINVAL;
 	};
 
 	ret = sc_pm_set_clock_rate(-1, resource, pm_clk, &new_rate);
@@ -311,7 +311,7 @@
 			       __func__, clk->id);
 			return -EINVAL;
 		}
-		return -ENOTSUPP;
+		return -EINVAL;
 	}
 
 	ret = sc_pm_clock_enable(-1, resource, pm_clk, enable, 0);
diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c
index feacaee..b5cbf80 100644
--- a/drivers/clk/imx/clk-pllv3.c
+++ b/drivers/clk/imx/clk-pllv3.c
@@ -290,7 +290,7 @@
 		break;
 	default:
 		kfree(pll);
-		return ERR_PTR(-ENOTSUPP);
+		return ERR_PTR(-EINVAL);
 	}
 
 	pll->base = base;
diff --git a/drivers/clk/kendryte/bypass.c b/drivers/clk/kendryte/bypass.c
index 5f1986f..bbdbd9a 100644
--- a/drivers/clk/kendryte/bypass.c
+++ b/drivers/clk/kendryte/bypass.c
@@ -157,7 +157,7 @@
 	if (ops->set_parent)
 		return ops->set_parent(bypass->bypassee, parent);
 	else
-		return -ENOTSUPP;
+		return -EINVAL;
 }
 
 /*
diff --git a/drivers/clk/kendryte/clk.c b/drivers/clk/kendryte/clk.c
index 4b95940..3b674a9 100644
--- a/drivers/clk/kendryte/clk.c
+++ b/drivers/clk/kendryte/clk.c
@@ -495,7 +495,7 @@
 	 * could fix this, but it's Probably Not Worth It (TM).
 	 */
 	if (probed)
-		return -ENOTSUPP;
+		return -EINVAL;
 
 	base = dev_read_addr_ptr(dev_get_parent(dev));
 	if (!base)
diff --git a/drivers/clk/microchip/mpfs_clk.c b/drivers/clk/microchip/mpfs_clk.c
index 722c79b..05d7647 100644
--- a/drivers/clk/microchip/mpfs_clk.c
+++ b/drivers/clk/microchip/mpfs_clk.c
@@ -120,4 +120,5 @@
 	.ops = &mpfs_clk_ops,
 	.probe = mpfs_clk_probe,
 	.priv_auto = sizeof(struct clk),
+	.flags = DM_FLAG_PRE_RELOC,
 };
diff --git a/drivers/clk/mvebu/armada-37xx-periph.c b/drivers/clk/mvebu/armada-37xx-periph.c
index 0132fcb..b0f47c3 100644
--- a/drivers/clk/mvebu/armada-37xx-periph.c
+++ b/drivers/clk/mvebu/armada-37xx-periph.c
@@ -340,7 +340,7 @@
 		return -EINVAL;
 
 	if (!periph_clk->can_gate)
-		return -ENOTSUPP;
+		return -EINVAL;
 
 	if (enable)
 		clrbits_le32(priv->reg + CLK_DIS, periph_clk->disable_bit);
@@ -408,7 +408,7 @@
 		return old_rate;
 
 	if (!periph_clk->can_gate || !periph_clk->dividers)
-		return -ENOTSUPP;
+		return -EINVAL;
 
 	parent_rate = get_parent_rate(priv, clk->id);
 	if (parent_rate == -EINVAL)
@@ -445,7 +445,7 @@
 		return -EINVAL;
 
 	if (!periph_clk->can_mux || !periph_clk->can_gate)
-		return -ENOTSUPP;
+		return -EINVAL;
 
 	ret = clk_get_by_index(clk->dev, 0, &check_parent);
 	if (ret < 0)
diff --git a/drivers/core/acpi.c b/drivers/core/acpi.c
index 0901b92..2176d8b 100644
--- a/drivers/core/acpi.c
+++ b/drivers/core/acpi.c
@@ -91,7 +91,7 @@
 	path = dev_read_string(dev, "acpi,path");
 	if (path) {
 		if (strlen(path) >= maxlen)
-			return -E2BIG;
+			return -ENOSPC;
 		strcpy(out_path, path);
 		return 0;
 	}
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 81f6880..cb960f8 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -45,6 +45,9 @@
 	bool auto_seq = true;
 	void *ptr;
 
+	if (CONFIG_IS_ENABLED(OF_PLATDATA_NO_BIND))
+		return -ENOSYS;
+
 	if (devp)
 		*devp = NULL;
 	if (!name)
@@ -395,26 +398,31 @@
 	if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID)
 		return 0;
 
-	/* Ensure all parents have ofdata */
-	if (dev->parent) {
-		ret = device_of_to_plat(dev->parent);
+	/*
+	 * This is not needed if binding is disabled, since data is allocated
+	 * at build time.
+	 */
+	if (!CONFIG_IS_ENABLED(OF_PLATDATA_NO_BIND)) {
+		/* Ensure all parents have ofdata */
+		if (dev->parent) {
+			ret = device_of_to_plat(dev->parent);
+			if (ret)
+				goto fail;
+
+			/*
+			 * The device might have already been probed during
+			 * the call to device_probe() on its parent device
+			 * (e.g. PCI bridge devices). Test the flags again
+			 * so that we don't mess up the device.
+			 */
+			if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID)
+				return 0;
+		}
+
+		ret = device_alloc_priv(dev);
 		if (ret)
 			goto fail;
-
-		/*
-		 * The device might have already been probed during
-		 * the call to device_probe() on its parent device
-		 * (e.g. PCI bridge devices). Test the flags again
-		 * so that we don't mess up the device.
-		 */
-		if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID)
-			return 0;
 	}
-
-	ret = device_alloc_priv(dev);
-	if (ret)
-		goto fail;
-
 	drv = dev->driver;
 	assert(drv);
 
@@ -592,7 +600,7 @@
 		return NULL;
 	}
 
-	return dev->plat_;
+	return dm_priv_to_rw(dev->plat_);
 }
 
 void *dev_get_parent_plat(const struct udevice *dev)
@@ -602,7 +610,7 @@
 		return NULL;
 	}
 
-	return dev->parent_plat_;
+	return dm_priv_to_rw(dev->parent_plat_);
 }
 
 void *dev_get_uclass_plat(const struct udevice *dev)
@@ -612,7 +620,7 @@
 		return NULL;
 	}
 
-	return dev->uclass_plat_;
+	return dm_priv_to_rw(dev->uclass_plat_);
 }
 
 void *dev_get_priv(const struct udevice *dev)
@@ -622,7 +630,7 @@
 		return NULL;
 	}
 
-	return dev->priv_;
+	return dm_priv_to_rw(dev->priv_);
 }
 
 void *dev_get_uclass_priv(const struct udevice *dev)
@@ -632,7 +640,7 @@
 		return NULL;
 	}
 
-	return dev->uclass_priv_;
+	return dm_priv_to_rw(dev->uclass_priv_);
 }
 
 void *dev_get_parent_priv(const struct udevice *dev)
@@ -642,7 +650,7 @@
 		return NULL;
 	}
 
-	return dev->parent_priv_;
+	return dm_priv_to_rw(dev->parent_priv_);
 }
 
 static int device_get_device_tail(struct udevice *dev, int ret,
@@ -803,27 +811,19 @@
 }
 
 #if CONFIG_IS_ENABLED(OF_PLATDATA)
-int device_get_by_driver_info(const struct driver_info *info,
-			      struct udevice **devp)
+int device_get_by_ofplat_idx(uint idx, struct udevice **devp)
 {
-	struct driver_info *info_base =
-		ll_entry_start(struct driver_info, driver_info);
-	int idx = info - info_base;
-	struct driver_rt *drt = gd_dm_driver_rt() + idx;
 	struct udevice *dev;
 
-	dev = drt->dev;
-	*devp = NULL;
+	if (CONFIG_IS_ENABLED(OF_PLATDATA_INST)) {
+		struct udevice *base = ll_entry_start(struct udevice, udevice);
 
-	return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
-}
+		dev = base + idx;
+	} else {
+		struct driver_rt *drt = gd_dm_driver_rt() + idx;
 
-int device_get_by_driver_info_idx(uint idx, struct udevice **devp)
-{
-	struct driver_rt *drt = gd_dm_driver_rt() + idx;
-	struct udevice *dev;
-
-	dev = drt->dev;
+		dev = drt->dev;
+	}
 	*devp = NULL;
 
 	return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
@@ -1136,3 +1136,36 @@
 	return lists_bind_fdt(parent, node, NULL, false);
 }
 #endif
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA_RT)
+static struct udevice_rt *dev_get_rt(const struct udevice *dev)
+{
+	struct udevice *base = ll_entry_start(struct udevice, udevice);
+	int idx = dev - base;
+
+	struct udevice_rt *urt = gd_dm_udevice_rt() + idx;
+
+	return urt;
+}
+
+u32 dev_get_flags(const struct udevice *dev)
+{
+	const struct udevice_rt *urt = dev_get_rt(dev);
+
+	return urt->flags_;
+}
+
+void dev_or_flags(const struct udevice *dev, u32 or)
+{
+	struct udevice_rt *urt = dev_get_rt(dev);
+
+	urt->flags_ |= or;
+}
+
+void dev_bic_flags(const struct udevice *dev, u32 bic)
+{
+	struct udevice_rt *urt = dev_get_rt(dev);
+
+	urt->flags_ &= ~bic;
+}
+#endif /* OF_PLATDATA_RT */
diff --git a/drivers/core/of_addr.c b/drivers/core/of_addr.c
index 5bc6ca1..b3e384d 100644
--- a/drivers/core/of_addr.c
+++ b/drivers/core/of_addr.c
@@ -372,7 +372,7 @@
 	bus_node->count_cells(dev, &na, &ns);
 	if (!OF_CHECK_COUNTS(na, ns)) {
 		printf("Bad cell count for %s\n", of_node_full_name(dev));
-		return -EINVAL;
+		ret = -EINVAL;
 		goto out_parent;
 	}
 
@@ -380,7 +380,7 @@
 	bus_node->count_cells(parent, &pna, &pns);
 	if (!OF_CHECK_COUNTS(pna, pns)) {
 		printf("Bad cell count for %s\n", of_node_full_name(parent));
-		return -EINVAL;
+		ret = -EINVAL;
 		goto out_parent;
 	}
 
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 9bc682c..d9a19c5 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -11,6 +11,7 @@
 #include <fdtdec.h>
 #include <log.h>
 #include <malloc.h>
+#include <asm-generic/sections.h>
 #include <asm/global_data.h>
 #include <linux/libfdt.h>
 #include <dm/acpi.h>
@@ -129,6 +130,36 @@
 	}
 }
 
+static int dm_setup_inst(void)
+{
+	DM_ROOT_NON_CONST = DM_DEVICE_GET(root);
+
+	if (CONFIG_IS_ENABLED(OF_PLATDATA_RT)) {
+		struct udevice_rt *urt;
+		void *base;
+		int n_ents;
+		uint size;
+
+		/* Allocate the udevice_rt table */
+		n_ents = ll_entry_count(struct udevice, udevice);
+		urt = calloc(n_ents, sizeof(struct udevice_rt));
+		if (!urt)
+			return log_msg_ret("urt", -ENOMEM);
+		gd_set_dm_udevice_rt(urt);
+
+		/* Now allocate space for the priv/plat data, and copy it in */
+		size = __priv_data_end - __priv_data_start;
+
+		base = calloc(1, size);
+		if (!base)
+			return log_msg_ret("priv", -ENOMEM);
+		memcpy(base, __priv_data_start, size);
+		gd_set_dm_priv_base(base);
+	}
+
+	return 0;
+}
+
 int dm_init(bool of_live)
 {
 	int ret;
@@ -140,8 +171,12 @@
 		dm_warn("Virtual root driver already exists!\n");
 		return -EINVAL;
 	}
-	gd->uclass_root = &DM_UCLASS_ROOT_S_NON_CONST;
-	INIT_LIST_HEAD(DM_UCLASS_ROOT_NON_CONST);
+	if (CONFIG_IS_ENABLED(OF_PLATDATA_INST)) {
+		gd->uclass_root = &uclass_head;
+	} else {
+		gd->uclass_root = &DM_UCLASS_ROOT_S_NON_CONST;
+		INIT_LIST_HEAD(DM_UCLASS_ROOT_NON_CONST);
+	}
 
 	if (IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)) {
 		fix_drivers();
@@ -149,14 +184,23 @@
 		fix_devices();
 	}
 
-	ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
-	if (ret)
-		return ret;
-	if (CONFIG_IS_ENABLED(OF_CONTROL))
-		dev_set_ofnode(DM_ROOT_NON_CONST, ofnode_root());
-	ret = device_probe(DM_ROOT_NON_CONST);
-	if (ret)
-		return ret;
+	if (CONFIG_IS_ENABLED(OF_PLATDATA_INST)) {
+		ret = dm_setup_inst();
+		if (ret) {
+			log_debug("dm_setup_inst() failed: %d\n", ret);
+			return ret;
+		}
+	} else {
+		ret = device_bind_by_name(NULL, false, &root_info,
+					  &DM_ROOT_NON_CONST);
+		if (ret)
+			return ret;
+		if (CONFIG_IS_ENABLED(OF_CONTROL))
+			dev_set_ofnode(DM_ROOT_NON_CONST, ofnode_root());
+		ret = device_probe(DM_ROOT_NON_CONST);
+		if (ret)
+			return ret;
+	}
 
 	return 0;
 }
@@ -185,7 +229,7 @@
 {
 	int ret;
 
-	if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
+	if (CONFIG_IS_ENABLED(OF_PLATDATA_DRIVER_RT)) {
 		struct driver_rt *dyn;
 		int n_ents;
 
@@ -303,6 +347,15 @@
 	return 0;
 }
 
+#if CONFIG_IS_ENABLED(OF_PLATDATA_INST) && CONFIG_IS_ENABLED(READ_ONLY)
+void *dm_priv_to_rw(void *priv)
+{
+	long offset = priv - (void *)__priv_data_start;
+
+	return gd_dm_priv_base() + offset;
+}
+#endif
+
 /**
  * dm_scan() - Scan tables to bind devices
  *
@@ -347,10 +400,12 @@
 		debug("dm_init() failed: %d\n", ret);
 		return ret;
 	}
-	ret = dm_scan(pre_reloc_only);
-	if (ret) {
-		log_debug("dm_scan() failed: %d\n", ret);
-		return ret;
+	if (!CONFIG_IS_ENABLED(OF_PLATDATA_INST)) {
+		ret = dm_scan(pre_reloc_only);
+		if (ret) {
+			log_debug("dm_scan() failed: %d\n", ret);
+			return ret;
+		}
 	}
 
 	return 0;
diff --git a/drivers/core/simple-pm-bus.c b/drivers/core/simple-pm-bus.c
index 7a18953..1bb0d86 100644
--- a/drivers/core/simple-pm-bus.c
+++ b/drivers/core/simple-pm-bus.c
@@ -21,7 +21,7 @@
 		return ret;
 
 	ret = clk_enable_bulk(bulk);
-	if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
+	if (ret && ret != -ENOSYS) {
 		clk_release_bulk(bulk);
 		return ret;
 	}
@@ -34,7 +34,7 @@
 	struct clk_bulk *bulk = dev_get_priv(dev);
 
 	ret = clk_release_bulk(bulk);
-	if (ret && ret != -ENOSYS && ret != -ENOTSUPP)
+	if (ret && ret != -ENOSYS)
 		return ret;
 	else
 		return 0;
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 1a4ea7a..117d35a 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -148,8 +148,11 @@
 
 	*ucp = NULL;
 	uc = uclass_find(id);
-	if (!uc)
+	if (!uc) {
+		if (CONFIG_IS_ENABLED(OF_PLATDATA_INST))
+			return -ENOENT;
 		return uclass_add(id, ucp);
+	}
 	*ucp = uc;
 
 	return 0;
@@ -391,7 +394,7 @@
 	return ret;
 }
 
-#if CONFIG_IS_ENABLED(OF_CONTROL)
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
 int uclass_find_device_by_phandle(enum uclass_id id, struct udevice *parent,
 				  const char *name, struct udevice **devp)
 {
diff --git a/drivers/crypto/fsl/Kconfig b/drivers/crypto/fsl/Kconfig
index 5ed6140..1f5dfb9 100644
--- a/drivers/crypto/fsl/Kconfig
+++ b/drivers/crypto/fsl/Kconfig
@@ -7,6 +7,12 @@
 	  Module (CAAM), also known as the SEC version 4 (SEC4). The driver uses
 	  Job Ring as interface to communicate with CAAM.
 
+config CAAM_64BIT
+	bool
+	default y if PHYS_64BIT && !ARCH_IMX8M
+	help
+	  Select Crypto driver for 64 bits CAAM version
+
 config SYS_FSL_HAS_SEC
 	bool
 	help
diff --git a/drivers/crypto/fsl/Makefile b/drivers/crypto/fsl/Makefile
index a5e8d38..f9c3cce 100644
--- a/drivers/crypto/fsl/Makefile
+++ b/drivers/crypto/fsl/Makefile
@@ -4,7 +4,7 @@
 
 obj-y += sec.o
 obj-$(CONFIG_FSL_CAAM) += jr.o fsl_hash.o jobdesc.o error.o
-obj-$(CONFIG_CMD_BLOB) += fsl_blob.o
-obj-$(CONFIG_CMD_DEKBLOB) += fsl_blob.o
+obj-$(CONFIG_CMD_BLOB)$(CONFIG_IMX_CAAM_DEK_ENCAP) += fsl_blob.o
 obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o
 obj-$(CONFIG_FSL_CAAM_RNG) += rng.o
+obj-$(CONFIG_FSL_MFGPROT) += fsl_mfgprot.o
diff --git a/drivers/crypto/fsl/desc.h b/drivers/crypto/fsl/desc.h
index 3589e6e..5705c4f 100644
--- a/drivers/crypto/fsl/desc.h
+++ b/drivers/crypto/fsl/desc.h
@@ -11,6 +11,8 @@
 #ifndef DESC_H
 #define DESC_H
 
+#include "type.h"
+
 #define KEY_BLOB_SIZE		32
 #define MAC_SIZE			16
 
@@ -693,29 +695,29 @@
 /* Structures for Protocol Data Blocks */
 struct __packed pdb_ecdsa_verify {
 	uint32_t pdb_hdr;
-	dma_addr_t dma_q;	/* Pointer to q (elliptic curve) */
-	dma_addr_t dma_r;	/* Pointer to r (elliptic curve) */
-	dma_addr_t dma_g_xy;	/* Pointer to Gx,y (elliptic curve) */
-	dma_addr_t dma_pkey;	/* Pointer to Wx,y (public key) */
-	dma_addr_t dma_hash;	/* Pointer to hash input */
-	dma_addr_t dma_c;	/* Pointer to C_signature */
-	dma_addr_t dma_d;	/* Pointer to D_signature */
-	dma_addr_t dma_buf;	/* Pointer to 64-byte temp buffer */
-	dma_addr_t dma_ab;	/* Pointer to a,b (elliptic curve ) */
+	caam_dma_addr_t dma_q;	/* Pointer to q (elliptic curve) */
+	caam_dma_addr_t dma_r;	/* Pointer to r (elliptic curve) */
+	caam_dma_addr_t dma_g_xy;	/* Pointer to Gx,y (elliptic curve) */
+	caam_dma_addr_t dma_pkey;	/* Pointer to Wx,y (public key) */
+	caam_dma_addr_t dma_hash;	/* Pointer to hash input */
+	caam_dma_addr_t dma_c;	/* Pointer to C_signature */
+	caam_dma_addr_t dma_d;	/* Pointer to D_signature */
+	caam_dma_addr_t dma_buf;	/* Pointer to 64-byte temp buffer */
+	caam_dma_addr_t dma_ab;	/* Pointer to a,b (elliptic curve ) */
 	uint32_t img_size;	/* Length of Message */
 };
 
 struct __packed pdb_ecdsa_sign {
 	uint32_t pdb_hdr;
-	dma_addr_t dma_q;	/* Pointer to q (elliptic curve) */
-	dma_addr_t dma_r;	/* Pointer to r (elliptic curve) */
-	dma_addr_t dma_g_xy;	/* Pointer to Gx,y (elliptic curve) */
-	dma_addr_t dma_pri_key;	/* Pointer to S (Private key) */
-	dma_addr_t dma_hash;	/* Pointer to hash input */
-	dma_addr_t dma_c;	/* Pointer to C_signature */
-	dma_addr_t dma_d;	/* Pointer to D_signature */
-	dma_addr_t dma_ab;	/* Pointer to a,b (elliptic curve ) */
-	dma_addr_t dma_u;	/* Pointer to Per Message Random */
+	caam_dma_addr_t dma_q;	/* Pointer to q (elliptic curve) */
+	caam_dma_addr_t dma_r;	/* Pointer to r (elliptic curve) */
+	caam_dma_addr_t dma_g_xy;	/* Pointer to Gx,y (elliptic curve) */
+	caam_dma_addr_t dma_pri_key;	/* Pointer to S (Private key) */
+	caam_dma_addr_t dma_hash;	/* Pointer to hash input */
+	caam_dma_addr_t dma_c;	/* Pointer to C_signature */
+	caam_dma_addr_t dma_d;	/* Pointer to D_signature */
+	caam_dma_addr_t dma_ab;	/* Pointer to a,b (elliptic curve ) */
+	caam_dma_addr_t dma_u;	/* Pointer to Per Message Random */
 	uint32_t img_size;	/* Length of Message */
 };
 
@@ -726,20 +728,21 @@
 struct __packed pdb_mp_pub_k {
 	uint32_t pdb_hdr;
 	#define PDB_MP_PUB_K_SGF_SHIFT		31
-	dma_addr_t dma_pkey;	/* Pointer to Wx,y (public key) */
+	caam_dma_addr_t dma_pkey;	/* Pointer to Wx,y (public key) */
 };
 
 struct __packed pdb_mp_sign {
 	uint32_t pdb_hdr;
 	#define PDB_MP_SIGN_SGF_SHIFT		28
-	dma_addr_t dma_addr_msg;	/* Pointer to Message */
-	dma_addr_t dma_addr_hash;	/* Pointer to hash output */
-	dma_addr_t dma_addr_c_sig;	/* Pointer to C_signature */
-	dma_addr_t dma_addr_d_sig;	/* Pointer to D_signature */
+	caam_dma_addr_t dma_addr_msg;	/* Pointer to Message */
+	caam_dma_addr_t dma_addr_hash;	/* Pointer to hash output */
+	caam_dma_addr_t dma_addr_c_sig;	/* Pointer to C_signature */
+	caam_dma_addr_t dma_addr_d_sig;	/* Pointer to D_signature */
 	uint32_t img_size;		/* Length of Message */
 };
 
 #define PDB_MP_CSEL_SHIFT	17
+#define PDB_MP_CSEL_WIDTH	4
 #define PDB_MP_CSEL_P256	0x3 << PDB_MP_CSEL_SHIFT	/* P-256 */
 #define PDB_MP_CSEL_P384	0x4 << PDB_MP_CSEL_SHIFT	/* P-384 */
 #define PDB_MP_CSEL_P521	0x5 << PDB_MP_CSEL_SHIFT	/* P-521 */
diff --git a/drivers/crypto/fsl/desc_constr.h b/drivers/crypto/fsl/desc_constr.h
index b82ba83..209557c 100644
--- a/drivers/crypto/fsl/desc_constr.h
+++ b/drivers/crypto/fsl/desc_constr.h
@@ -12,7 +12,7 @@
 
 #define IMMEDIATE (1 << 23)
 #define CAAM_CMD_SZ sizeof(u32)
-#define CAAM_PTR_SZ sizeof(dma_addr_t)
+#define CAAM_PTR_SZ sizeof(caam_dma_addr_t)
 #define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * MAX_CAAM_DESCSIZE)
 #define DESC_JOB_IO_LEN (CAAM_CMD_SZ * 5 + CAAM_PTR_SZ * 3)
 
@@ -35,7 +35,7 @@
 			       LDST_SRCDST_WORD_DECOCTRL | \
 			       (LDOFF_ENABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
 
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
 struct ptr_addr_t {
 #ifdef CONFIG_SYS_FSL_SEC_LE
 	u32 low;
@@ -49,9 +49,9 @@
 };
 #endif
 
-static inline void pdb_add_ptr(dma_addr_t *offset, dma_addr_t ptr)
+static inline void pdb_add_ptr(caam_dma_addr_t *offset, caam_dma_addr_t ptr)
 {
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
 	/* The Position of low and high part of 64 bit address
 	 * will depend on the endianness of CAAM Block */
 	struct ptr_addr_t *ptr_addr = (struct ptr_addr_t *)offset;
@@ -102,11 +102,11 @@
 		       options);
 }
 
-static inline void append_ptr(u32 *desc, dma_addr_t ptr)
+static inline void append_ptr(u32 *desc, caam_dma_addr_t ptr)
 {
-	dma_addr_t *offset = (dma_addr_t *)desc_end(desc);
+	caam_dma_addr_t *offset = (caam_dma_addr_t *)desc_end(desc);
 
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
 	/* The Position of low and high part of 64 bit address
 	 * will depend on the endianness of CAAM Block */
 	struct ptr_addr_t *ptr_addr = (struct ptr_addr_t *)offset;
@@ -159,7 +159,7 @@
 	return desc + 1;
 }
 
-static inline void append_cmd_ptr(u32 *desc, dma_addr_t ptr, int len,
+static inline void append_cmd_ptr(u32 *desc, caam_dma_addr_t ptr, int len,
 				  u32 command)
 {
 	append_cmd(desc, command | len);
@@ -167,7 +167,7 @@
 }
 
 /* Write length after pointer, rather than inside command */
-static inline void append_cmd_ptr_extlen(u32 *desc, dma_addr_t ptr,
+static inline void append_cmd_ptr_extlen(u32 *desc, caam_dma_addr_t ptr,
 					 unsigned int len, u32 command)
 {
 	append_cmd(desc, command);
@@ -225,7 +225,7 @@
 APPEND_CMD_LEN(seq_fifo_store, SEQ_FIFO_STORE)
 
 #define APPEND_CMD_PTR(cmd, op) \
-static inline void append_##cmd(u32 *desc, dma_addr_t ptr, unsigned int len, \
+static inline void append_##cmd(u32 *desc, caam_dma_addr_t ptr, unsigned int len, \
 				u32 options) \
 { \
 	PRINT_POS; \
@@ -236,7 +236,7 @@
 APPEND_CMD_PTR(fifo_load, FIFO_LOAD)
 APPEND_CMD_PTR(fifo_store, FIFO_STORE)
 
-static inline void append_store(u32 *desc, dma_addr_t ptr, unsigned int len,
+static inline void append_store(u32 *desc, caam_dma_addr_t ptr, unsigned int len,
 				u32 options)
 {
 	u32 cmd_src;
@@ -254,7 +254,7 @@
 }
 
 #define APPEND_SEQ_PTR_INTLEN(cmd, op) \
-static inline void append_seq_##cmd##_ptr_intlen(u32 *desc, dma_addr_t ptr, \
+static inline void append_seq_##cmd##_ptr_intlen(u32 *desc, caam_dma_addr_t ptr, \
 						 unsigned int len, \
 						 u32 options) \
 { \
@@ -278,7 +278,7 @@
 APPEND_CMD_PTR_TO_IMM(fifo_load, FIFO_LOAD);
 
 #define APPEND_CMD_PTR_EXTLEN(cmd, op) \
-static inline void append_##cmd##_extlen(u32 *desc, dma_addr_t ptr, \
+static inline void append_##cmd##_extlen(u32 *desc, caam_dma_addr_t ptr, \
 					 unsigned int len, u32 options) \
 { \
 	PRINT_POS; \
@@ -292,7 +292,7 @@
  * the size of its type
  */
 #define APPEND_CMD_PTR_LEN(cmd, op, type) \
-static inline void append_##cmd(u32 *desc, dma_addr_t ptr, \
+static inline void append_##cmd(u32 *desc, caam_dma_addr_t ptr, \
 				type len, u32 options) \
 { \
 	PRINT_POS; \
diff --git a/drivers/crypto/fsl/fsl_blob.c b/drivers/crypto/fsl/fsl_blob.c
index d6bd861..e8202cc 100644
--- a/drivers/crypto/fsl/fsl_blob.c
+++ b/drivers/crypto/fsl/fsl_blob.c
@@ -65,6 +65,9 @@
 	flush_dcache_range((unsigned long)desc,
 			   (unsigned long)desc + size);
 
+	flush_dcache_range((unsigned long)dst,
+			   (unsigned long)dst + size);
+
 	ret = run_descriptor_jr(desc);
 
 	if (ret) {
@@ -130,6 +133,9 @@
 	flush_dcache_range((unsigned long)desc,
 			   (unsigned long)desc + size);
 
+	flush_dcache_range((unsigned long)dst,
+			   (unsigned long)dst + size);
+
 	ret = run_descriptor_jr(desc);
 
 	if (ret) {
diff --git a/drivers/crypto/fsl/fsl_hash.c b/drivers/crypto/fsl/fsl_hash.c
index 61f953e..8b5c26d 100644
--- a/drivers/crypto/fsl/fsl_hash.c
+++ b/drivers/crypto/fsl/fsl_hash.c
@@ -87,7 +87,7 @@
 			    enum caam_hash_algos caam_algo)
 {
 	uint32_t final;
-	phys_addr_t addr = virt_to_phys((void *)buf);
+	caam_dma_addr_t addr = virt_to_phys((void *)buf);
 	struct sha_ctx *ctx = hash_ctx;
 
 	if (ctx->sg_num >= MAX_SG_32) {
@@ -95,12 +95,12 @@
 		return -EINVAL;
 	}
 
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
 	sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, (uint32_t)(addr >> 32));
 #else
 	sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, 0x0);
 #endif
-	sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_lo, (uint32_t)addr);
+	sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_lo, (caam_dma_addr_t)addr);
 
 	sec_out32(&ctx->sg_tbl[ctx->sg_num].len_flag,
 		  (size & SG_ENTRY_LENGTH_MASK));
diff --git a/drivers/crypto/fsl/fsl_mfgprot.c b/drivers/crypto/fsl/fsl_mfgprot.c
new file mode 100644
index 0000000..29af79f
--- /dev/null
+++ b/drivers/crypto/fsl/fsl_mfgprot.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <fsl_sec.h>
+#include <memalign.h>
+#include "desc.h"
+#include "desc_constr.h"
+#include "jobdesc.h"
+#include "jr.h"
+
+/* Size of MFG descriptor */
+#define MFG_PUBK_DSC_WORDS 4
+#define MFG_SIGN_DSC_WORDS 8
+
+static void mfg_build_sign_dsc(u32 *dsc_ptr, const u8 *m, int size,
+			       u8 *dgst, u8 *c, u8 *d)
+{
+	u32 *dsc = dsc_ptr;
+	struct pdb_mp_sign *pdb;
+
+	init_job_desc_pdb(dsc, 0, sizeof(struct pdb_mp_sign));
+
+	pdb = (struct pdb_mp_sign *)desc_pdb(dsc);
+
+	/* Curve */
+	pdb->pdb_hdr = (PDB_MP_CSEL_P256);
+
+	/* Message Pointer */
+	pdb_add_ptr(&pdb->dma_addr_msg, virt_to_phys((void *)m));
+
+	/* mes-resp Pointer */
+	pdb_add_ptr(&pdb->dma_addr_hash, virt_to_phys((void *)dgst));
+
+	/* C Pointer */
+	pdb_add_ptr(&pdb->dma_addr_c_sig, virt_to_phys((void *)c));
+
+	/* d Pointer */
+	pdb_add_ptr(&pdb->dma_addr_d_sig, virt_to_phys((void *)d));
+
+	/* Message Size */
+	pdb->img_size = size;
+
+	/* MP PubK generate key command */
+	append_cmd(dsc, (CMD_OPERATION | OP_TYPE_DECAP_PROTOCOL |
+			 OP_PCLID_MP_SIGN));
+}
+
+static void mfg_build_pubk_dsc(u32 *dsc_ptr, u8 *dst)
+{
+	u32 *dsc = dsc_ptr;
+	struct pdb_mp_pub_k *pdb;
+
+	init_job_desc_pdb(dsc, 0, sizeof(struct pdb_mp_pub_k));
+
+	pdb = (struct pdb_mp_pub_k *)desc_pdb(dsc);
+
+	/* Curve */
+	pdb->pdb_hdr = (PDB_MP_CSEL_P256);
+
+	/* Message Pointer */
+	pdb_add_ptr(&pdb->dma_pkey, virt_to_phys((void *)dst));
+
+	/* MP Sign key command */
+	append_cmd(dsc, (CMD_OPERATION | OP_TYPE_DECAP_PROTOCOL |
+			 OP_PCLID_MP_PUB_KEY));
+}
+
+int gen_mppubk(u8 *dst)
+{
+	int size, ret;
+	u32 *dsc;
+
+	/* Job Descriptor initialization */
+	dsc = memalign(ARCH_DMA_MINALIGN,
+		       sizeof(uint32_t) * MFG_PUBK_DSC_WORDS);
+	if (!dsc) {
+		debug("Not enough memory for descriptor allocation\n");
+		return -ENOMEM;
+	}
+
+	mfg_build_pubk_dsc(dsc, dst);
+
+	size = roundup(sizeof(uint32_t) * MFG_PUBK_DSC_WORDS,
+		       ARCH_DMA_MINALIGN);
+	flush_dcache_range((unsigned long)dsc, (unsigned long)dsc + size);
+
+	size = roundup(FSL_CAAM_MP_PUBK_BYTES, ARCH_DMA_MINALIGN);
+	flush_dcache_range((unsigned long)dst, (unsigned long)dst + size);
+
+	/* Execute Job Descriptor */
+	puts("\nGenerating Manufacturing Protection Public Key\n");
+
+	ret = run_descriptor_jr(dsc);
+	if (ret) {
+		debug("Error in public key generation %d\n", ret);
+		goto err;
+	}
+
+	size = roundup(FSL_CAAM_MP_PUBK_BYTES, ARCH_DMA_MINALIGN);
+	invalidate_dcache_range((unsigned long)dst, (unsigned long)dst + size);
+err:
+	free(dsc);
+	return ret;
+}
+
+int sign_mppubk(const u8 *m, int data_size, u8 *dgst, u8 *c, u8 *d)
+{
+	int size, ret;
+	u32 *dsc;
+
+	/* Job Descriptor initialization */
+	dsc = memalign(ARCH_DMA_MINALIGN,
+		       sizeof(uint32_t) * MFG_SIGN_DSC_WORDS);
+	if (!dsc) {
+		debug("Not enough memory for descriptor allocation\n");
+		return -ENOMEM;
+	}
+
+	mfg_build_sign_dsc(dsc, m, data_size, dgst, c, d);
+
+	size = roundup(sizeof(uint32_t) * MFG_SIGN_DSC_WORDS,
+		       ARCH_DMA_MINALIGN);
+	flush_dcache_range((unsigned long)dsc, (unsigned long)dsc + size);
+
+	size = roundup(data_size, ARCH_DMA_MINALIGN);
+	flush_dcache_range((unsigned long)m, (unsigned long)m + size);
+
+	size = roundup(FSL_CAAM_MP_MES_DGST_BYTES, ARCH_DMA_MINALIGN);
+	flush_dcache_range((unsigned long)dgst, (unsigned long)dgst + size);
+
+	size = roundup(FSL_CAAM_MP_PRVK_BYTES, ARCH_DMA_MINALIGN);
+	flush_dcache_range((unsigned long)c, (unsigned long)c + size);
+	flush_dcache_range((unsigned long)d, (unsigned long)d + size);
+
+	/* Execute Job Descriptor */
+	puts("\nSigning message with Manufacturing Protection Private Key\n");
+
+	ret = run_descriptor_jr(dsc);
+	if (ret) {
+		debug("Error in public key generation %d\n", ret);
+		goto err;
+	}
+
+	size = roundup(FSL_CAAM_MP_MES_DGST_BYTES, ARCH_DMA_MINALIGN);
+	invalidate_dcache_range((unsigned long)dgst,
+				(unsigned long)dgst + size);
+
+	size = roundup(FSL_CAAM_MP_PRVK_BYTES, ARCH_DMA_MINALIGN);
+	invalidate_dcache_range((unsigned long)c, (unsigned long)c + size);
+	invalidate_dcache_range((unsigned long)d, (unsigned long)d + size);
+
+err:
+	free(dsc);
+	return ret;
+}
diff --git a/drivers/crypto/fsl/jobdesc.c b/drivers/crypto/fsl/jobdesc.c
index fbc1aed..d235415 100644
--- a/drivers/crypto/fsl/jobdesc.c
+++ b/drivers/crypto/fsl/jobdesc.c
@@ -4,6 +4,7 @@
  * Basic job descriptor construction
  *
  * Copyright 2014 Freescale Semiconductor, Inc.
+ * Copyright 2018 NXP
  *
  */
 
@@ -15,7 +16,8 @@
 #include "rsa_caam.h"
 #include <asm/cache.h>
 
-#if defined(CONFIG_MX6) || defined(CONFIG_MX7)
+#if defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_MX7ULP) || \
+		defined(CONFIG_IMX8M)
 /*!
  * Secure memory run command
  *
@@ -163,9 +165,9 @@
 
 	append_u32(desc, aad_w2);
 
-	append_cmd_ptr(desc, (dma_addr_t)SEC_MEM_PAGE1, in_sz, CMD_SEQ_IN_PTR);
+	append_cmd_ptr(desc, (caam_dma_addr_t)SEC_MEM_PAGE1, in_sz, CMD_SEQ_IN_PTR);
 
-	append_cmd_ptr(desc, (dma_addr_t)dek_blob + 8, out_sz, CMD_SEQ_OUT_PTR);
+	append_cmd_ptr(desc, (caam_dma_addr_t)(ulong)(dek_blob + 8), out_sz, CMD_SEQ_OUT_PTR);
 
 	append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB |
 						OP_PCLID_SECMEM);
@@ -181,7 +183,7 @@
 	/* SHA 256 , output is of length 32 words */
 	uint32_t storelen = alg_size;
 	u32 options;
-	dma_addr_t dma_addr_in, dma_addr_out;
+	caam_dma_addr_t dma_addr_in, dma_addr_out;
 
 	dma_addr_in = virt_to_phys((void *)msg);
 	dma_addr_out = virt_to_phys((void *)digest);
@@ -210,7 +212,7 @@
 				     uint8_t *plain_txt, uint8_t *enc_blob,
 				     uint32_t in_sz)
 {
-	dma_addr_t dma_addr_key_idnfr, dma_addr_in, dma_addr_out;
+	caam_dma_addr_t dma_addr_key_idnfr, dma_addr_in, dma_addr_out;
 	uint32_t key_sz = KEY_IDNFR_SZ_BYTES;
 	/* output blob will have 32 bytes key blob in beginning and
 	 * 16 byte HMAC identifier at end of data blob */
@@ -235,7 +237,7 @@
 				     uint8_t *enc_blob, uint8_t *plain_txt,
 				     uint32_t out_sz)
 {
-	dma_addr_t dma_addr_key_idnfr, dma_addr_in, dma_addr_out;
+	caam_dma_addr_t dma_addr_key_idnfr, dma_addr_in, dma_addr_out;
 	uint32_t key_sz = KEY_IDNFR_SZ_BYTES;
 	uint32_t in_sz = out_sz + KEY_BLOB_SIZE + MAC_SIZE;
 
@@ -311,7 +313,7 @@
 				      struct pk_in_params *pkin, uint8_t *out,
 				      uint32_t out_siz)
 {
-	dma_addr_t dma_addr_e, dma_addr_a, dma_addr_n, dma_addr_out;
+	caam_dma_addr_t dma_addr_e, dma_addr_a, dma_addr_n, dma_addr_out;
 
 	dma_addr_e = virt_to_phys((void *)pkin->e);
 	dma_addr_a = virt_to_phys((void *)pkin->a);
diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c
index 44273c3..22b6492 100644
--- a/drivers/crypto/fsl/jr.c
+++ b/drivers/crypto/fsl/jr.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2008-2014 Freescale Semiconductor, Inc.
+ * Copyright 2018 NXP
  *
  * Based on CAAM driver in drivers/crypto/caam in Linux
  */
@@ -21,6 +22,7 @@
 #include <asm/fsl_pamu.h>
 #endif
 #include <dm/lists.h>
+#include <linux/delay.h>
 
 #define CIRC_CNT(head, tail, size)	(((head) - (tail)) & (size - 1))
 #define CIRC_SPACE(head, tail, size)	CIRC_CNT((tail), (head) + 1, (size))
@@ -34,10 +36,10 @@
 };
 
 #define SEC_ADDR(idx)	\
-	((CONFIG_SYS_FSL_SEC_ADDR + sec_offset[idx]))
+	(ulong)((CONFIG_SYS_FSL_SEC_ADDR + sec_offset[idx]))
 
 #define SEC_JR0_ADDR(idx)	\
-	(SEC_ADDR(idx) +	\
+	(ulong)(SEC_ADDR(idx) +	\
 	 (CONFIG_SYS_FSL_JR0_OFFSET - CONFIG_SYS_FSL_SEC_OFFSET))
 
 struct jobring jr0[CONFIG_SYS_FSL_MAX_NUM_OF_SEC];
@@ -82,16 +84,16 @@
 {
 	struct jr_regs *regs = (struct jr_regs *)SEC_JR0_ADDR(sec_idx);
 	struct jobring *jr = &jr0[sec_idx];
-	phys_addr_t ip_base = virt_to_phys((void *)jr->input_ring);
-	phys_addr_t op_base = virt_to_phys((void *)jr->output_ring);
+	caam_dma_addr_t ip_base = virt_to_phys((void *)jr->input_ring);
+	caam_dma_addr_t op_base = virt_to_phys((void *)jr->output_ring);
 
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
 	sec_out32(&regs->irba_h, ip_base >> 32);
 #else
 	sec_out32(&regs->irba_h, 0x0);
 #endif
 	sec_out32(&regs->irba_l, (uint32_t)ip_base);
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
 	sec_out32(&regs->orba_h, op_base >> 32);
 #else
 	sec_out32(&regs->orba_h, 0x0);
@@ -117,8 +119,8 @@
 	jr->liodn = DEFAULT_JR_LIODN;
 #endif
 	jr->size = JR_SIZE;
-	jr->input_ring = (dma_addr_t *)memalign(ARCH_DMA_MINALIGN,
-				JR_SIZE * sizeof(dma_addr_t));
+	jr->input_ring = (caam_dma_addr_t *)memalign(ARCH_DMA_MINALIGN,
+				JR_SIZE * sizeof(caam_dma_addr_t));
 	if (!jr->input_ring)
 		return -1;
 
@@ -129,7 +131,7 @@
 	if (!jr->output_ring)
 		return -1;
 
-	memset(jr->input_ring, 0, JR_SIZE * sizeof(dma_addr_t));
+	memset(jr->input_ring, 0, JR_SIZE * sizeof(caam_dma_addr_t));
 	memset(jr->output_ring, 0, jr->op_size);
 
 	start_jr0(sec_idx);
@@ -148,7 +150,7 @@
 	jr->read_idx = 0;
 	jr->write_idx = 0;
 	memset(jr->info, 0, sizeof(jr->info));
-	memset(jr->input_ring, 0, jr->size * sizeof(dma_addr_t));
+	memset(jr->input_ring, 0, jr->size * sizeof(caam_dma_addr_t));
 	memset(jr->output_ring, 0, jr->size * sizeof(struct op_ring));
 
 	return 0;
@@ -194,7 +196,7 @@
 	uint32_t desc_word;
 	int length = desc_len(desc_addr);
 	int i;
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
 	uint32_t *addr_hi, *addr_lo;
 #endif
 
@@ -208,7 +210,7 @@
 		sec_out32((uint32_t *)&desc_addr[i], desc_word);
 	}
 
-	phys_addr_t desc_phys_addr = virt_to_phys(desc_addr);
+	caam_dma_addr_t desc_phys_addr = virt_to_phys(desc_addr);
 
 	jr->info[head].desc_phys_addr = desc_phys_addr;
 	jr->info[head].callback = (void *)callback;
@@ -221,7 +223,7 @@
 				  sizeof(struct jr_info), ARCH_DMA_MINALIGN);
 	flush_dcache_range(start, end);
 
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
 	/* Write the 64 bit Descriptor address on Input Ring.
 	 * The 32 bit hign and low part of the address will
 	 * depend on endianness of SEC block.
@@ -240,11 +242,11 @@
 #else
 	/* Write the 32 bit Descriptor address on Input Ring. */
 	sec_out32(&jr->input_ring[head], desc_phys_addr);
-#endif /* ifdef CONFIG_PHYS_64BIT */
+#endif /* ifdef CONFIG_CAAM_64BIT */
 
 	start = (unsigned long)&jr->input_ring[head] & ~(ARCH_DMA_MINALIGN - 1);
 	end = ALIGN((unsigned long)&jr->input_ring[head] +
-		     sizeof(dma_addr_t), ARCH_DMA_MINALIGN);
+		     sizeof(caam_dma_addr_t), ARCH_DMA_MINALIGN);
 	flush_dcache_range(start, end);
 
 	jr->head = (head + 1) & (jr->size - 1);
@@ -270,7 +272,7 @@
 	int idx, i, found;
 	void (*callback)(uint32_t status, void *arg);
 	void *arg = NULL;
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
 	uint32_t *addr_hi, *addr_lo;
 #else
 	uint32_t *addr;
@@ -281,8 +283,8 @@
 
 		found = 0;
 
-		phys_addr_t op_desc;
-	#ifdef CONFIG_PHYS_64BIT
+		caam_dma_addr_t op_desc;
+	#ifdef CONFIG_CAAM_64BIT
 		/* Read the 64 bit Descriptor address from Output Ring.
 		 * The 32 bit hign and low part of the address will
 		 * depend on endianness of SEC block.
@@ -302,7 +304,7 @@
 		/* Read the 32 bit Descriptor address from Output Ring. */
 		addr = (uint32_t *)&jr->output_ring[jr->tail].desc;
 		op_desc = sec_in32(addr);
-	#endif /* ifdef CONFIG_PHYS_64BIT */
+	#endif /* ifdef CONFIG_CAAM_64BIT */
 
 		uint32_t status = sec_in32(&jr->output_ring[jr->tail].status);
 
@@ -355,8 +357,8 @@
 
 static inline int run_descriptor_jr_idx(uint32_t *desc, uint8_t sec_idx)
 {
-	unsigned long long timeval = get_ticks();
-	unsigned long long timeout = usec2ticks(CONFIG_SEC_DEQ_TIMEOUT);
+	unsigned long long timeval = 0;
+	unsigned long long timeout = CONFIG_USEC_DEQ_TIMEOUT;
 	struct result op;
 	int ret = 0;
 
@@ -369,9 +371,10 @@
 		goto out;
 	}
 
-	timeval = get_ticks();
-	timeout = usec2ticks(CONFIG_SEC_DEQ_TIMEOUT);
 	while (op.done != 1) {
+		udelay(1);
+		timeval += 1;
+
 		ret = jr_dequeue(sec_idx);
 		if (ret) {
 			debug("Error in SEC deq\n");
@@ -379,7 +382,7 @@
 			goto out;
 		}
 
-		if ((get_ticks() - timeval) > timeout) {
+		if (timeval > timeout) {
 			debug("SEC Dequeue timed out\n");
 			ret = JQ_DEQ_TO_ERR;
 			goto out;
@@ -675,7 +678,7 @@
 	mcr = (mcr & ~MCFGR_AWCACHE_MASK) | (0x2 << MCFGR_AWCACHE_SHIFT);
 #endif
 
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
 	mcr |= (1 << MCFGR_PS_SHIFT);
 #endif
 	sec_out32(&sec->mcfgr, mcr);
diff --git a/drivers/crypto/fsl/jr.h b/drivers/crypto/fsl/jr.h
index ffd3a19..1047aa7 100644
--- a/drivers/crypto/fsl/jr.h
+++ b/drivers/crypto/fsl/jr.h
@@ -8,10 +8,11 @@
 #define __JR_H
 
 #include <linux/compiler.h>
+#include "type.h"
 
 #define JR_SIZE 4
-/* Timeout currently defined as 90 sec */
-#define CONFIG_SEC_DEQ_TIMEOUT	90000000U
+/* Timeout currently defined as 10 sec */
+#define CONFIG_USEC_DEQ_TIMEOUT	10000000U
 
 #define DEFAULT_JR_ID		0
 #define DEFAULT_JR_LIODN	0
@@ -41,13 +42,13 @@
 #define RNG4_MAX_HANDLES	2
 
 struct op_ring {
-	phys_addr_t desc;
+	caam_dma_addr_t desc;
 	uint32_t status;
 } __packed;
 
 struct jr_info {
 	void (*callback)(uint32_t status, void *arg);
-	phys_addr_t desc_phys_addr;
+	caam_dma_addr_t desc_phys_addr;
 	uint32_t desc_len;
 	uint32_t op_done;
 	void *arg;
@@ -83,7 +84,7 @@
 	 * by SEC
 	 */
 	/*Circular  Ring of i/p descriptors */
-	dma_addr_t *input_ring;
+	caam_dma_addr_t *input_ring;
 	/* Circular Ring of o/p descriptors */
 	/* Circula Ring containing info regarding descriptors in i/p
 	 * and o/p ring
diff --git a/drivers/crypto/fsl/type.h b/drivers/crypto/fsl/type.h
new file mode 100644
index 0000000..b7031a6
--- /dev/null
+++ b/drivers/crypto/fsl/type.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2020 NXP
+ *
+ */
+
+#ifndef CRYPTO_FSL_TYPE_H
+#define CRYPTO_FSL_TYPE_H
+
+#ifdef CONFIG_CAAM_64BIT
+typedef unsigned long long caam_dma_addr_t;
+#else
+typedef u32 caam_dma_addr_t;
+#endif
+
+#endif
diff --git a/drivers/ddr/imx/imx8m/Kconfig b/drivers/ddr/imx/imx8m/Kconfig
index a5f5524..a90b7db 100644
--- a/drivers/ddr/imx/imx8m/Kconfig
+++ b/drivers/ddr/imx/imx8m/Kconfig
@@ -36,4 +36,12 @@
 	help
 	  Select this config if you want to use inline ecc feature for
 	  imx8mp-evk board.
+
+config IMX8M_VDD_SOC_850MV
+	bool "imx8mp change the vdd_soc voltage to 850mv"
+	depends on IMX8MP
+
+config IMX8M_LPDDR4_FREQ0_2400MTS
+	bool "imx8m PDDR4 freq0 change from 4000MTS to 2400MTS"
+
 endmenu
diff --git a/drivers/dfu/dfu_sf.c b/drivers/dfu/dfu_sf.c
index 76b629a..8f8c425 100644
--- a/drivers/dfu/dfu_sf.c
+++ b/drivers/dfu/dfu_sf.c
@@ -87,7 +87,23 @@
 
 static void dfu_free_entity_sf(struct dfu_entity *dfu)
 {
-	spi_flash_free(dfu->data.sf.dev);
+	/*
+	 * In the DM case it is not necessary to free the SPI device.
+	 * For the non-DM case we must ensure that the the SPI device is only
+	 * freed once.
+	 */
+	if (!CONFIG_IS_ENABLED(DM_SPI_FLASH)) {
+		struct spi_flash *dev = dfu->data.sf.dev;
+
+		if (!dev)
+			return;
+		dfu->data.sf.dev = NULL;
+		list_for_each_entry(dfu, &dfu_list, list) {
+			if (dfu->data.sf.dev == dev)
+				dfu->data.sf.dev = NULL;
+		}
+		spi_flash_free(dev);
+	}
 }
 
 static struct spi_flash *parse_dev(char *devstr)
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 4a9b74e..f24db87 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2013 Google, Inc
  */
 
+#define LOG_CATEGORY	UCLASS_GPIO
+
 #include <common.h>
 #include <dm.h>
 #include <log.h>
@@ -21,6 +23,7 @@
 #include <dm/device_compat.h>
 #include <linux/bug.h>
 #include <linux/ctype.h>
+#include <linux/delay.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -220,7 +223,7 @@
 static int gpio_find_and_xlate(struct gpio_desc *desc,
 			       struct ofnode_phandle_args *args)
 {
-	struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
+	const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
 
 	if (ops->xlate)
 		return ops->xlate(desc->dev, desc, args);
@@ -353,6 +356,7 @@
 
 int dm_gpio_request(struct gpio_desc *desc, const char *label)
 {
+	const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
 	struct udevice *dev = desc->dev;
 	struct gpio_dev_priv *uc_priv;
 	char *str;
@@ -364,8 +368,8 @@
 	str = strdup(label);
 	if (!str)
 		return -ENOMEM;
-	if (gpio_get_ops(dev)->request) {
-		ret = gpio_get_ops(dev)->request(dev, desc->offset, label);
+	if (ops->request) {
+		ret = ops->request(dev, desc->offset, label);
 		if (ret) {
 			free(str);
 			return ret;
@@ -442,14 +446,15 @@
 
 int _dm_gpio_free(struct udevice *dev, uint offset)
 {
+	const struct dm_gpio_ops *ops = gpio_get_ops(dev);
 	struct gpio_dev_priv *uc_priv;
 	int ret;
 
 	uc_priv = dev_get_uclass_priv(dev);
 	if (!uc_priv->name[offset])
 		return -ENXIO;
-	if (gpio_get_ops(dev)->rfree) {
-		ret = gpio_get_ops(dev)->rfree(dev, offset);
+	if (ops->rfree) {
+		ret = ops->rfree(dev, offset);
 		if (ret)
 			return ret;
 	}
@@ -515,11 +520,8 @@
 	ret = gpio_to_device(gpio, &desc);
 	if (ret)
 		return ret;
-	ret = check_reserved(&desc, "dir_input");
-	if (ret)
-		return ret;
 
-	return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset);
+	return dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, GPIOD_IS_IN);
 }
 
 /**
@@ -534,24 +536,25 @@
 int gpio_direction_output(unsigned gpio, int value)
 {
 	struct gpio_desc desc;
+	ulong flags;
 	int ret;
 
 	ret = gpio_to_device(gpio, &desc);
 	if (ret)
 		return ret;
-	ret = check_reserved(&desc, "dir_output");
-	if (ret)
-		return ret;
 
-	return gpio_get_ops(desc.dev)->direction_output(desc.dev,
-							desc.offset, value);
+	flags = GPIOD_IS_OUT;
+	if (value)
+		flags |= GPIOD_IS_OUT_ACTIVE;
+	return dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, flags);
 }
 
 static int _gpio_get_value(const struct gpio_desc *desc)
 {
+	const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
 	int value;
 
-	value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset);
+	value = ops->get_value(desc->dev, desc->offset);
 
 	return desc->flags & GPIOD_ACTIVE_LOW ? !value : value;
 }
@@ -569,6 +572,7 @@
 
 int dm_gpio_set_value(const struct gpio_desc *desc, int value)
 {
+	const struct dm_gpio_ops *ops;
 	int ret;
 
 	ret = check_reserved(desc, "set_value");
@@ -578,21 +582,33 @@
 	if (desc->flags & GPIOD_ACTIVE_LOW)
 		value = !value;
 
+	/* GPIOD_ are directly managed by driver in set_flags */
+	ops = gpio_get_ops(desc->dev);
+	if (ops->set_flags) {
+		ulong flags = desc->flags;
+
+		if (value)
+			flags |= GPIOD_IS_OUT_ACTIVE;
+		else
+			flags &= ~GPIOD_IS_OUT_ACTIVE;
+		return ops->set_flags(desc->dev, desc->offset, flags);
+	}
+
 	/*
 	 * Emulate open drain by not actively driving the line high or
 	 * Emulate open source by not actively driving the line low
 	 */
 	if ((desc->flags & GPIOD_OPEN_DRAIN && value) ||
 	    (desc->flags & GPIOD_OPEN_SOURCE && !value))
-		return gpio_get_ops(desc->dev)->direction_input(desc->dev,
-								desc->offset);
+		return ops->direction_input(desc->dev, desc->offset);
 	else if (desc->flags & GPIOD_OPEN_DRAIN ||
 		 desc->flags & GPIOD_OPEN_SOURCE)
-		return gpio_get_ops(desc->dev)->direction_output(desc->dev,
-								desc->offset,
-								value);
+		return ops->direction_output(desc->dev, desc->offset, value);
 
-	gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value);
+	ret = ops->set_value(desc->dev, desc->offset, value);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
@@ -620,10 +636,21 @@
 	return 0;
 }
 
-static int _dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
+/**
+ * _dm_gpio_set_flags() - Send flags to the driver
+ *
+ * This uses the best available method to send the given flags to the driver.
+ * Note that if flags & GPIOD_ACTIVE_LOW, the driver sees the opposite value
+ * of GPIOD_IS_OUT_ACTIVE.
+ *
+ * @desc:	GPIO description
+ * @flags:	flags value to set
+ * @return 0 if OK, -ve on error
+ */
+static int _dm_gpio_set_flags(struct gpio_desc *desc, ulong flags)
 {
 	struct udevice *dev = desc->dev;
-	struct dm_gpio_ops *ops = gpio_get_ops(dev);
+	const struct dm_gpio_ops *ops = gpio_get_ops(dev);
 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 	int ret = 0;
 
@@ -638,38 +665,52 @@
 		return ret;
 	}
 
-	/* GPIOD_ are directly managed by driver in set_dir_flags*/
-	if (ops->set_dir_flags) {
-		ret = ops->set_dir_flags(dev, desc->offset, flags);
+	/* If active low, invert the output state */
+	if ((flags & (GPIOD_IS_OUT | GPIOD_ACTIVE_LOW)) ==
+		(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW))
+		flags ^= GPIOD_IS_OUT_ACTIVE;
+
+	/* GPIOD_ are directly managed by driver in set_flags */
+	if (ops->set_flags) {
+		ret = ops->set_flags(dev, desc->offset, flags);
 	} else {
 		if (flags & GPIOD_IS_OUT) {
-			ret = ops->direction_output(dev, desc->offset,
-						    GPIOD_FLAGS_OUTPUT(flags));
+			bool value = flags & GPIOD_IS_OUT_ACTIVE;
+
+			ret = ops->direction_output(dev, desc->offset, value);
 		} else if (flags & GPIOD_IS_IN) {
 			ret = ops->direction_input(dev, desc->offset);
 		}
 	}
 
-	/* save the flags also in descriptor */
-	if (!ret)
-		desc->flags = flags;
-
 	return ret;
 }
 
-int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
+int dm_gpio_clrset_flags(struct gpio_desc *desc, ulong clr, ulong set)
 {
+	ulong flags;
 	int ret;
 
 	ret = check_reserved(desc, "set_dir_flags");
 	if (ret)
 		return ret;
 
-	/* combine the requested flags (for IN/OUT) and the descriptor flags */
-	flags |= desc->flags;
-	ret = _dm_gpio_set_dir_flags(desc, flags);
+	flags = (desc->flags & ~clr) | set;
 
-	return ret;
+	ret = _dm_gpio_set_flags(desc, flags);
+	if (ret)
+		return ret;
+
+	/* save the flags also in descriptor */
+	desc->flags = flags;
+
+	return 0;
+}
+
+int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
+{
+	/* combine the requested flags (for IN/OUT) and the descriptor flags */
+	return dm_gpio_clrset_flags(desc, GPIOD_MASK_DIR, flags);
 }
 
 int dm_gpio_set_dir(struct gpio_desc *desc)
@@ -680,42 +721,57 @@
 	if (ret)
 		return ret;
 
-	return _dm_gpio_set_dir_flags(desc, desc->flags);
+	return _dm_gpio_set_flags(desc, desc->flags);
 }
 
-int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags)
+int dm_gpios_clrset_flags(struct gpio_desc *desc, int count, ulong clr,
+			  ulong set)
+{
+	int ret;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		ret = dm_gpio_clrset_flags(&desc[i], clr, set);
+		if (ret)
+			return log_ret(ret);
+	}
+
+	return 0;
+}
+
+int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp)
 {
 	struct udevice *dev = desc->dev;
 	int ret, value;
-	struct dm_gpio_ops *ops = gpio_get_ops(dev);
-	ulong dir_flags;
+	const struct dm_gpio_ops *ops = gpio_get_ops(dev);
+	ulong flags;
 
-	ret = check_reserved(desc, "get_dir_flags");
+	ret = check_reserved(desc, "get_flags");
 	if (ret)
 		return ret;
 
 	/* GPIOD_ are directly provided by driver except GPIOD_ACTIVE_LOW */
-	if (ops->get_dir_flags) {
-		ret = ops->get_dir_flags(dev, desc->offset, &dir_flags);
+	if (ops->get_flags) {
+		ret = ops->get_flags(dev, desc->offset, &flags);
 		if (ret)
 			return ret;
 
 		/* GPIOD_ACTIVE_LOW is saved in desc->flags */
-		value = dir_flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0;
+		value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0;
 		if (desc->flags & GPIOD_ACTIVE_LOW)
 			value = !value;
-		dir_flags &= ~(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE);
-		dir_flags |= (desc->flags & GPIOD_ACTIVE_LOW);
+		flags &= ~(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE);
+		flags |= (desc->flags & GPIOD_ACTIVE_LOW);
 		if (value)
-			dir_flags |= GPIOD_IS_OUT_ACTIVE;
+			flags |= GPIOD_IS_OUT_ACTIVE;
 	} else {
-		dir_flags = desc->flags;
+		flags = desc->flags;
 		/* only GPIOD_IS_OUT_ACTIVE is provided by uclass */
-		dir_flags &= ~GPIOD_IS_OUT_ACTIVE;
+		flags &= ~GPIOD_IS_OUT_ACTIVE;
 		if ((desc->flags & GPIOD_IS_OUT) && _gpio_get_value(desc))
-			dir_flags |= GPIOD_IS_OUT_ACTIVE;
+			flags |= GPIOD_IS_OUT_ACTIVE;
 	}
-	*flags = dir_flags;
+	*flagsp = flags;
 
 	return 0;
 }
@@ -785,7 +841,7 @@
 			const char **namep)
 {
 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
-	struct dm_gpio_ops *ops = gpio_get_ops(dev);
+	const struct dm_gpio_ops *ops = gpio_get_ops(dev);
 
 	BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
 	if (!device_active(dev))
@@ -822,7 +878,7 @@
 
 int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize)
 {
-	struct dm_gpio_ops *ops = gpio_get_ops(dev);
+	const struct dm_gpio_ops *ops = gpio_get_ops(dev);
 	struct gpio_dev_priv *priv;
 	char *str = buf;
 	int func;
@@ -862,7 +918,7 @@
 #if CONFIG_IS_ENABLED(ACPIGEN)
 int gpio_get_acpi(const struct gpio_desc *desc, struct acpi_gpio *gpio)
 {
-	struct dm_gpio_ops *ops;
+	const struct dm_gpio_ops *ops;
 
 	memset(gpio, '\0', sizeof(*gpio));
 	if (!dm_gpio_is_valid(desc)) {
@@ -949,6 +1005,71 @@
 	return vector;
 }
 
+int dm_gpio_get_values_as_int_base3(struct gpio_desc *desc_list,
+				    int count)
+{
+	static const char tristate[] = "01z";
+	enum {
+		PULLUP,
+		PULLDOWN,
+
+		NUM_OPTIONS,
+	};
+	int vals[NUM_OPTIONS];
+	uint mask;
+	uint vector = 0;
+	int ret, i;
+
+	/*
+	 * Limit to 19 digits which should be plenty. This avoids overflow of a
+	 * 32-bit int
+	 */
+	assert(count < 20);
+
+	for (i = 0; i < NUM_OPTIONS; i++) {
+		uint flags = GPIOD_IS_IN;
+
+		flags |= (i == PULLDOWN) ? GPIOD_PULL_DOWN : GPIOD_PULL_UP;
+		ret = dm_gpios_clrset_flags(desc_list, count, GPIOD_MASK_PULL,
+					    flags);
+		if (ret)
+			return log_msg_ret("pu", ret);
+
+		/* Give the lines time to settle */
+		udelay(10);
+
+		ret = dm_gpio_get_values_as_int(desc_list, count);
+		if (ret < 0)
+			return log_msg_ret("get1", ret);
+		vals[i] = ret;
+	}
+
+	log_debug("values: %x %x, count = %d\n", vals[0], vals[1], count);
+	for (i = count - 1, mask = 1 << i; i >= 0; i--, mask >>= 1) {
+		uint pd = vals[PULLDOWN] & mask ? 1 : 0;
+		uint pu = vals[PULLUP] & mask ? 1 : 0;
+		uint digit;
+
+		/*
+		 * Get value with internal pulldown active. If this is 1 then
+		 * there is a stronger external pullup, which we call 1. If not
+		 * then call it 0.
+		 *
+		 * If the values differ then the pin is floating so we call
+		 * this a 2.
+		 */
+		if (pu == pd)
+			digit = pd;
+		else
+			digit = 2;
+		log_debug("%c ", tristate[digit]);
+		vector = 3 * vector + digit;
+	}
+	log_debug("vector=%d\n", vector);
+
+	return vector;
+}
+
 /**
  * gpio_request_tail: common work for requesting a gpio.
  *
@@ -1011,7 +1132,10 @@
 		debug("%s: dm_gpio_requestf failed\n", __func__);
 		goto err;
 	}
-	ret = dm_gpio_set_dir_flags(desc, flags);
+
+	/* Keep any direction flags provided by the devicetree */
+	ret = dm_gpio_set_dir_flags(desc,
+				    flags | (desc->flags & GPIOD_MASK_DIR));
 	if (ret) {
 		debug("%s: dm_gpio_set_dir failed\n", __func__);
 		goto err;
@@ -1024,6 +1148,7 @@
 	return ret;
 }
 
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 static int _gpio_request_by_name_nodev(ofnode node, const char *list_name,
 				       int index, struct gpio_desc *desc,
 				       int flags, bool add_index)
@@ -1110,6 +1235,7 @@
 
 	return ret;
 }
+#endif /* OF_PLATDATA */
 
 int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc)
 {
@@ -1306,10 +1432,10 @@
 			ops->get_function += gd->reloc_off;
 		if (ops->xlate)
 			ops->xlate += gd->reloc_off;
-		if (ops->set_dir_flags)
-			ops->set_dir_flags += gd->reloc_off;
-		if (ops->get_dir_flags)
-			ops->get_dir_flags += gd->reloc_off;
+		if (ops->set_flags)
+			ops->set_flags += gd->reloc_off;
+		if (ops->get_flags)
+			ops->get_flags += gd->reloc_off;
 
 		reloc_done++;
 	}
diff --git a/drivers/gpio/intel_gpio.c b/drivers/gpio/intel_gpio.c
index eda9548..f15ce7b 100644
--- a/drivers/gpio/intel_gpio.c
+++ b/drivers/gpio/intel_gpio.c
@@ -3,6 +3,8 @@
  * Copyright 2019 Google LLC
  */
 
+#define LOG_CATEGORY	UCLASS_GPIO
+
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
@@ -21,40 +23,9 @@
 #include <asm/pci.h>
 #include <asm/arch/gpio.h>
 #include <dm/acpi.h>
+#include <dm/device-internal.h>
 #include <dt-bindings/gpio/x86-gpio.h>
 
-static int intel_gpio_direction_input(struct udevice *dev, uint offset)
-{
-	struct udevice *pinctrl = dev_get_parent(dev);
-	uint config_offset;
-
-	config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset);
-
-	pcr_clrsetbits32(pinctrl, config_offset,
-			 PAD_CFG0_MODE_MASK | PAD_CFG0_TX_STATE |
-				  PAD_CFG0_RX_DISABLE,
-			 PAD_CFG0_MODE_GPIO | PAD_CFG0_TX_DISABLE);
-
-	return 0;
-}
-
-static int intel_gpio_direction_output(struct udevice *dev, uint offset,
-				       int value)
-{
-	struct udevice *pinctrl = dev_get_parent(dev);
-	uint config_offset;
-
-	config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset);
-
-	pcr_clrsetbits32(pinctrl, config_offset,
-			 PAD_CFG0_MODE_MASK | PAD_CFG0_RX_STATE |
-				  PAD_CFG0_TX_DISABLE | PAD_CFG0_TX_STATE,
-			 PAD_CFG0_MODE_GPIO | PAD_CFG0_RX_DISABLE |
-				  (value ? PAD_CFG0_TX_STATE : 0));
-
-	return 0;
-}
-
 static int intel_gpio_get_value(struct udevice *dev, uint offset)
 {
 	struct udevice *pinctrl = dev_get_parent(dev);
@@ -115,7 +86,7 @@
 
 	/*
 	 * GPIO numbers are global in the device tree so it doesn't matter
-	 * which one is used
+	 * which @orig_dev is used
 	 */
 	gpio = args->args[0];
 	ret = intel_pinctrl_get_pad(gpio, &pinctrl, &desc->offset);
@@ -127,6 +98,52 @@
 	desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
 	desc->dev = dev;
 
+	/*
+	 * Handle the case where the wrong GPIO device was provided, since this
+	 * will not have been probed by the GPIO uclass before calling here
+	 * (see gpio_request_tail()).
+	 */
+	if (orig_dev != dev) {
+		ret = device_probe(dev);
+		if (ret)
+			return log_msg_ret("probe", ret);
+	}
+
+	return 0;
+}
+
+static int intel_gpio_set_flags(struct udevice *dev, unsigned int offset,
+				ulong flags)
+{
+	struct udevice *pinctrl = dev_get_parent(dev);
+	u32 bic0 = 0, bic1 = 0;
+	u32 or0, or1;
+	uint config_offset;
+
+	config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset);
+
+	if (flags & GPIOD_IS_OUT) {
+		bic0 |= PAD_CFG0_MODE_MASK | PAD_CFG0_RX_STATE |
+			PAD_CFG0_TX_DISABLE;
+		or0 |= PAD_CFG0_MODE_GPIO | PAD_CFG0_RX_DISABLE;
+	} else if (flags & GPIOD_IS_IN) {
+		bic0 |= PAD_CFG0_MODE_MASK | PAD_CFG0_TX_STATE |
+			PAD_CFG0_RX_DISABLE;
+		or0 |= PAD_CFG0_MODE_GPIO | PAD_CFG0_TX_DISABLE;
+	}
+	if (flags & GPIOD_PULL_UP) {
+		bic1 |= PAD_CFG1_PULL_MASK;
+		or1 |= PAD_CFG1_PULL_UP_20K;
+	} else if (flags & GPIOD_PULL_DOWN) {
+		bic1 |= PAD_CFG1_PULL_MASK;
+		or1 |= PAD_CFG1_PULL_DN_20K;
+	}
+
+	pcr_clrsetbits32(pinctrl, PAD_CFG0_OFFSET(config_offset), bic0, or0);
+	pcr_clrsetbits32(pinctrl, PAD_CFG1_OFFSET(config_offset), bic1, or1);
+	log_debug("%s: flags=%lx, offset=%x, config_offset=%x, %x/%x %x/%x\n",
+		  dev->name, flags, offset, config_offset, bic0, or0, bic1, or1);
+
 	return 0;
 }
 
@@ -177,12 +194,11 @@
 }
 
 static const struct dm_gpio_ops gpio_intel_ops = {
-	.direction_input	= intel_gpio_direction_input,
-	.direction_output	= intel_gpio_direction_output,
 	.get_value		= intel_gpio_get_value,
 	.set_value		= intel_gpio_set_value,
 	.get_function		= intel_gpio_get_function,
 	.xlate			= intel_gpio_xlate,
+	.set_flags		= intel_gpio_set_flags,
 #if CONFIG_IS_ENABLED(ACPIGEN)
 	.get_acpi		= intel_gpio_get_acpi,
 #endif
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index dc8d506..d008fdd 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -19,42 +19,51 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/gpio/sandbox-gpio.h>
 
-
 struct gpio_state {
 	const char *label;	/* label given by requester */
-	ulong dir_flags;	/* dir_flags (GPIOD_...) */
+	ulong flags;		/* flags (GPIOD_...) */
 };
 
-/* Access routines for GPIO dir flags */
-static ulong *get_gpio_dir_flags(struct udevice *dev, unsigned int offset)
+/* Access routines for GPIO info */
+static struct gpio_state *get_gpio_state(struct udevice *dev, uint offset)
 {
 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 	struct gpio_state *state = dev_get_priv(dev);
 
 	if (offset >= uc_priv->gpio_count) {
-		static ulong invalid_dir_flags;
 		printf("sandbox_gpio: error: invalid gpio %u\n", offset);
-		return &invalid_dir_flags;
+		return NULL;
 	}
 
-	return &state[offset].dir_flags;
+	return &state[offset];
+}
+
+/* Access routines for GPIO flags */
+static ulong *get_gpio_flags(struct udevice *dev, unsigned int offset)
+{
+	struct gpio_state *state = get_gpio_state(dev, offset);
+
+	if (!state)
+		return NULL;
+
+	return &state->flags;
 
 }
 
 static int get_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag)
 {
-	return (*get_gpio_dir_flags(dev, offset) & flag) != 0;
+	return (*get_gpio_flags(dev, offset) & flag) != 0;
 }
 
 static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
 			 int value)
 {
-	ulong *gpio = get_gpio_dir_flags(dev, offset);
+	struct gpio_state *state = get_gpio_state(dev, offset);
 
 	if (value)
-		*gpio |= flag;
+		state->flags |= flag;
 	else
-		*gpio &= ~flag;
+		state->flags &= ~flag;
 
 	return 0;
 }
@@ -65,14 +74,31 @@
 
 int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
 {
+	struct gpio_state *state = get_gpio_state(dev, offset);
+	bool val;
+
 	if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
 		debug("sandbox_gpio: get_value on output gpio %u\n", offset);
-	return get_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE);
+
+	if (state->flags & GPIOD_EXT_DRIVEN) {
+		val = state->flags & GPIOD_EXT_HIGH;
+	} else {
+		if (state->flags & GPIOD_EXT_PULL_UP)
+			val = true;
+		else if (state->flags & GPIOD_EXT_PULL_DOWN)
+			val = false;
+		else
+			val = state->flags & GPIOD_PULL_UP;
+	}
+
+	return val;
 }
 
 int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 {
-	return set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE, value);
+	set_gpio_flag(dev, offset, GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value);
+
+	return 0;
 }
 
 int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
@@ -83,20 +109,23 @@
 int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output)
 {
 	set_gpio_flag(dev, offset, GPIOD_IS_OUT, output);
-	set_gpio_flag(dev, offset, GPIOD_IS_IN, !(output));
+	set_gpio_flag(dev, offset, GPIOD_IS_IN, !output);
 
 	return 0;
 }
 
-ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset)
+ulong sandbox_gpio_get_flags(struct udevice *dev, uint offset)
 {
-	return *get_gpio_dir_flags(dev, offset);
+	ulong flags = *get_gpio_flags(dev, offset);
+
+	return flags & ~GPIOD_SANDBOX_MASK;
 }
 
-int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-			       ulong flags)
+int sandbox_gpio_set_flags(struct udevice *dev, uint offset, ulong flags)
 {
-	*get_gpio_dir_flags(dev, offset) = flags;
+	struct gpio_state *state = get_gpio_state(dev, offset);
+
+	state->flags = flags;
 
 	return 0;
 }
@@ -117,10 +146,19 @@
 static int sb_gpio_direction_output(struct udevice *dev, unsigned offset,
 				    int value)
 {
+	int ret;
+
 	debug("%s: offset:%u, value = %d\n", __func__, offset, value);
 
-	return sandbox_gpio_set_direction(dev, offset, 1) |
-		sandbox_gpio_set_value(dev, offset, value);
+	ret = sandbox_gpio_set_direction(dev, offset, 1);
+	if (ret)
+		return ret;
+	ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE |
+			    GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value);
+	if (ret)
+		return ret;
+
+	return 0;
 }
 
 /* read GPIO IN value of port 'offset' */
@@ -134,6 +172,8 @@
 /* write GPIO OUT value to port 'offset' */
 static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 {
+	int ret;
+
 	debug("%s: offset:%u, value = %d\n", __func__, offset, value);
 
 	if (!sandbox_gpio_get_direction(dev, offset)) {
@@ -142,7 +182,12 @@
 		return -1;
 	}
 
-	return sandbox_gpio_set_value(dev, offset, value);
+	ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE |
+			    GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value);
+	if (ret)
+		return ret;
+
+	return 0;
 }
 
 static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
@@ -177,33 +222,30 @@
 	return 0;
 }
 
-static int sb_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-				 ulong flags)
+static int sb_gpio_set_flags(struct udevice *dev, unsigned int offset,
+			     ulong flags)
 {
-	ulong *dir_flags;
+	debug("%s: offset:%u, flags = %lx\n", __func__, offset, flags);
+	struct gpio_state *state = get_gpio_state(dev, offset);
 
-	debug("%s: offset:%u, dir_flags = %lx\n", __func__, offset, flags);
-
-	dir_flags = get_gpio_dir_flags(dev, offset);
-
-	/*
-	 * For testing purposes keep the output value when switching to input.
-	 * This allows us to manipulate the input value via the gpio command.
-	 */
-	if (flags & GPIOD_IS_IN)
-		*dir_flags = (flags & ~GPIOD_IS_OUT_ACTIVE) |
-			     (*dir_flags & GPIOD_IS_OUT_ACTIVE);
-	else
-		*dir_flags = flags;
+	if (flags & GPIOD_IS_OUT) {
+		flags |= GPIOD_EXT_DRIVEN;
+		if (flags & GPIOD_IS_OUT_ACTIVE)
+			flags |= GPIOD_EXT_HIGH;
+		else
+			flags &= ~GPIOD_EXT_HIGH;
+	} else {
+		flags |= state->flags & GPIOD_SANDBOX_MASK;
+	}
+	state->flags = flags;
 
 	return 0;
 }
 
-static int sb_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
-				 ulong *flags)
+static int sb_gpio_get_flags(struct udevice *dev, uint offset, ulong *flagsp)
 {
 	debug("%s: offset:%u\n", __func__, offset);
-	*flags = *get_gpio_dir_flags(dev, offset);
+	*flagsp = *get_gpio_flags(dev, offset) & ~GPIOD_SANDBOX_MASK;
 
 	return 0;
 }
@@ -272,8 +314,8 @@
 	.set_value		= sb_gpio_set_value,
 	.get_function		= sb_gpio_get_function,
 	.xlate			= sb_gpio_xlate,
-	.set_dir_flags		= sb_gpio_set_dir_flags,
-	.get_dir_flags		= sb_gpio_get_dir_flags,
+	.set_flags		= sb_gpio_set_flags,
+	.get_flags		= sb_gpio_get_flags,
 #if CONFIG_IS_ENABLED(ACPIGEN)
 	.get_acpi		= sb_gpio_get_acpi,
 #endif
@@ -456,7 +498,7 @@
 	return pin_name;
 }
 
-static char *get_dir_flags_string(ulong flags)
+static char *get_flags_string(ulong flags)
 {
 	if (flags & GPIOD_OPEN_DRAIN)
 		return "drive-open-drain";
@@ -475,7 +517,7 @@
 {
 	struct udevice *gpio_dev;
 	unsigned int gpio_idx;
-	ulong dir_flags;
+	ulong flags;
 	int function;
 
 	/* look up for the bank which owns the requested pin */
@@ -484,11 +526,11 @@
 		snprintf(buf, size, "Error");
 	} else {
 		function = sb_gpio_get_function(gpio_dev, gpio_idx);
-		dir_flags = *get_gpio_dir_flags(gpio_dev, gpio_idx);
+		flags = *get_gpio_flags(gpio_dev, gpio_idx);
 
 		snprintf(buf, size, "gpio %s %s",
 			 function == GPIOF_OUTPUT ? "output" : "input",
-			 get_dir_flags_string(dir_flags));
+			 get_flags_string(flags));
 	}
 
 	return 0;
diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c
index 7184db3..125c237 100644
--- a/drivers/gpio/stm32_gpio.c
+++ b/drivers/gpio/stm32_gpio.c
@@ -191,8 +191,8 @@
 	return GPIOF_FUNC;
 }
 
-static int stm32_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-				    ulong flags)
+static int stm32_gpio_set_flags(struct udevice *dev, unsigned int offset,
+				ulong flags)
 {
 	struct stm32_gpio_priv *priv = dev_get_priv(dev);
 	struct stm32_gpio_regs *regs = priv->regs;
@@ -203,12 +203,13 @@
 		return idx;
 
 	if (flags & GPIOD_IS_OUT) {
-		int value = GPIOD_FLAGS_OUTPUT(flags);
+		bool value = flags & GPIOD_IS_OUT_ACTIVE;
 
 		if (flags & GPIOD_OPEN_DRAIN)
 			stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_OD);
 		else
 			stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_PP);
+
 		stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_OUT);
 		writel(BSRR_BIT(idx, value), &regs->bsrr);
 
@@ -223,8 +224,8 @@
 	return 0;
 }
 
-static int stm32_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
-				    ulong *flags)
+static int stm32_gpio_get_flags(struct udevice *dev, unsigned int offset,
+				ulong *flagsp)
 {
 	struct stm32_gpio_priv *priv = dev_get_priv(dev);
 	struct stm32_gpio_regs *regs = priv->regs;
@@ -259,7 +260,7 @@
 	default:
 		break;
 	}
-	*flags = dir_flags;
+	*flagsp = dir_flags;
 
 	return 0;
 }
@@ -270,8 +271,8 @@
 	.get_value		= stm32_gpio_get_value,
 	.set_value		= stm32_gpio_set_value,
 	.get_function		= stm32_gpio_get_function,
-	.set_dir_flags		= stm32_gpio_set_dir_flags,
-	.get_dir_flags		= stm32_gpio_get_dir_flags,
+	.set_flags		= stm32_gpio_set_flags,
+	.get_flags		= stm32_gpio_get_flags,
 };
 
 static int gpio_stm32_probe(struct udevice *dev)
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index acd27ac..8c9f1fc 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -39,9 +39,7 @@
 obj-$(CONFIG_SYS_I2C_RCAR_IIC) += rcar_iic.o
 obj-$(CONFIG_SYS_I2C_ROCKCHIP) += rk_i2c.o
 obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o exynos_hs_i2c.o
-ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o
-endif
 obj-$(CONFIG_SYS_I2C_SH) += sh_i2c.o
 obj-$(CONFIG_SYS_I2C_SOFT) += soft_i2c.o
 obj-$(CONFIG_SYS_I2C_STM32F7) += stm32f7_i2c.o
diff --git a/drivers/i2c/i2c-emul-uclass.c b/drivers/i2c/i2c-emul-uclass.c
index 085b824..7917b63 100644
--- a/drivers/i2c/i2c-emul-uclass.c
+++ b/drivers/i2c/i2c-emul-uclass.c
@@ -7,6 +7,7 @@
 #include <dm.h>
 #include <i2c.h>
 #include <log.h>
+#include <asm/i2c.h>
 #include <dm/device-internal.h>
 #include <dm/uclass-internal.h>
 
@@ -23,18 +24,6 @@
  * uclass so avoid having strange devices on the I2C bus.
  */
 
-/**
- * struct i2c_emul_uc_plat - information about the emulator for this device
- *
- * This is used by devices in UCLASS_I2C_EMUL to record information about the
- * device being emulated. It is accessible with dev_get_uclass_plat()
- *
- * @dev: Device being emulated
- */
-struct i2c_emul_uc_plat {
-	struct udevice *dev;
-};
-
 struct udevice *i2c_emul_get_device(struct udevice *emul)
 {
 	struct i2c_emul_uc_plat *uc_plat = dev_get_uclass_plat(emul);
@@ -42,14 +31,27 @@
 	return uc_plat->dev;
 }
 
+void i2c_emul_set_idx(struct udevice *dev, int emul_idx)
+{
+	struct dm_i2c_chip *plat = dev_get_parent_plat(dev);
+
+	plat->emul_idx = emul_idx;
+}
+
 int i2c_emul_find(struct udevice *dev, struct udevice **emulp)
 {
 	struct i2c_emul_uc_plat *uc_plat;
 	struct udevice *emul;
 	int ret;
 
-	ret = uclass_find_device_by_phandle(UCLASS_I2C_EMUL, dev,
-					    "sandbox,emul", &emul);
+	if (!CONFIG_IS_ENABLED(OF_PLATDATA)) {
+		ret = uclass_find_device_by_phandle(UCLASS_I2C_EMUL, dev,
+						    "sandbox,emul", &emul);
+	} else {
+		struct dm_i2c_chip *plat = dev_get_parent_plat(dev);
+
+		ret = device_get_by_ofplat_idx(plat->emul_idx, &emul);
+	}
 	if (ret) {
 		log_err("No emulators for device '%s'\n", dev->name);
 		return ret;
@@ -85,8 +87,8 @@
 	{ }
 };
 
-U_BOOT_DRIVER(i2c_emul_parent_drv) = {
-	.name		= "i2c_emul_parent_drv",
+U_BOOT_DRIVER(sandbox_i2c_emul_parent) = {
+	.name		= "sandbox_i2c_emul_parent",
 	.id		= UCLASS_I2C_EMUL_PARENT,
 	.of_match	= i2c_emul_parent_ids,
 };
diff --git a/drivers/misc/cbmem_console.c b/drivers/misc/cbmem_console.c
index 5ba0a54..8bbe33d 100644
--- a/drivers/misc/cbmem_console.c
+++ b/drivers/misc/cbmem_console.c
@@ -9,7 +9,7 @@
 #error This driver requires coreboot
 #endif
 
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
 
 struct cbmem_console {
 	u32 buffer_size;
diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c
index cb8adc4..bc01df0 100644
--- a/drivers/misc/cros_ec_sandbox.c
+++ b/drivers/misc/cros_ec_sandbox.c
@@ -153,10 +153,14 @@
 {
 	struct ec_state *ec = g_state;
 
+	if (!g_state)
+		return 0;
+
 	/* We are guaranteed enough space to write basic properties */
 	fdt_setprop_u32(blob, node, "current-image", ec->current_image);
 	fdt_setprop(blob, node, "vbnv-context", ec->vbnv_context,
 		    sizeof(ec->vbnv_context));
+
 	return state_setprop(node, "flash-data", ec->flash_data,
 			     ec->ec_config.flash.length);
 }
diff --git a/drivers/misc/irq-uclass.c b/drivers/misc/irq-uclass.c
index 24b2796..3aa26f6 100644
--- a/drivers/misc/irq-uclass.c
+++ b/drivers/misc/irq-uclass.c
@@ -69,7 +69,7 @@
 {
 	int ret;
 
-	ret = device_get_by_driver_info_idx(cells->idx, &irq->dev);
+	ret = device_get_by_ofplat_idx(cells->idx, &irq->dev);
 	if (ret)
 		return ret;
 	irq->id = cells->arg[0];
diff --git a/drivers/misc/mxc_ocotp.c b/drivers/misc/mxc_ocotp.c
index 926c62c..b1893a5 100644
--- a/drivers/misc/mxc_ocotp.c
+++ b/drivers/misc/mxc_ocotp.c
@@ -335,7 +335,7 @@
 	struct ocotp_regs *regs;
 	int ret;
 
-	if (is_imx8mq() && is_soc_rev(CHIP_REV_2_1)) {
+	if (is_imx8mq() && (soc_rev() >= CHIP_REV_2_1)) {
 		printf("mxc_ocotp %s(): fuse sense is disabled\n", __func__);
 		return -EPERM;
 	}
diff --git a/drivers/misc/p2sb_emul.c b/drivers/misc/p2sb_emul.c
index 973d02d..51f8716 100644
--- a/drivers/misc/p2sb_emul.c
+++ b/drivers/misc/p2sb_emul.c
@@ -7,7 +7,6 @@
  */
 
 #define LOG_CATEGORY UCLASS_MISC
-#define LOG_DEBUG
 
 #include <common.h>
 #include <axi.h>
diff --git a/drivers/misc/test_drv.c b/drivers/misc/test_drv.c
index 827a50e..5d72982 100644
--- a/drivers/misc/test_drv.c
+++ b/drivers/misc/test_drv.c
@@ -86,7 +86,7 @@
 	{ }
 };
 
-U_BOOT_DRIVER(testbus_drv) = {
+U_BOOT_DRIVER(denx_u_boot_test_bus) = {
 	.name	= "testbus_drv",
 	.of_match	= testbus_ids,
 	.id	= UCLASS_TEST_BUS,
@@ -98,6 +98,7 @@
 	.per_child_plat_auto	= sizeof(struct dm_test_parent_plat),
 	.child_pre_probe = testbus_child_pre_probe,
 	.child_post_remove = testbus_child_post_remove,
+	DM_HEADER(<test.h>)
 };
 
 UCLASS_DRIVER(testbus) = {
@@ -106,6 +107,9 @@
 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 	.child_pre_probe = testbus_child_pre_probe_uclass,
 	.child_post_probe = testbus_child_post_probe_uclass,
+
+	/* This is for dtoc testing only */
+	.per_device_plat_auto   = sizeof(struct dm_test_uclass_priv),
 };
 
 static int testfdt_drv_ping(struct udevice *dev, int pingval, int *pingret)
@@ -160,7 +164,9 @@
 	{ }
 };
 
-U_BOOT_DRIVER(testfdt_drv) = {
+DM_DRIVER_ALIAS(denx_u_boot_fdt_test, google_another_fdt_test)
+
+U_BOOT_DRIVER(denx_u_boot_fdt_test) = {
 	.name	= "testfdt_drv",
 	.of_match	= testfdt_ids,
 	.id	= UCLASS_TEST_FDT,
@@ -203,6 +209,7 @@
 	.name		= "testfdt",
 	.id		= UCLASS_TEST_FDT,
 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
+	.priv_auto	= sizeof(struct dm_test_uc_priv),
 };
 
 static const struct udevice_id testfdtm_ids[] = {
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index f8ca52e..197aa82 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -311,6 +311,7 @@
 
 config MMC_PCI
 	bool "Support for MMC controllers on PCI"
+	depends on MMC_SDHCI
 	help
 	  This selects PCI-based MMC controllers.
 	  If you have an MMC controller on a PCI bus, say Y here.
@@ -326,6 +327,15 @@
 
 	  If unsure, say N.
 
+config MVEBU_MMC
+	bool "Kirkwood MMC controller support"
+	depends on DM_MMC && BLK && ARCH_KIRKWOOD
+	help
+	  Support for MMC host controller on Kirkwood SoCs.
+	  If you are on a Kirkwood architecture, say Y here.
+
+	  If unsure, say N.
+
 config PXA_MMC_GENERIC
 	bool "Support for MMC controllers on PXA"
 	help
@@ -812,3 +822,9 @@
 
 config SYS_FSL_ERRATUM_ESDHC_A001
 	bool
+
+config SYS_FSL_ERRATUM_A011334
+	bool
+
+config SYS_FSL_ESDHC_UNRELIABLE_PULSE_DETECTION_WORKAROUND
+	bool
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 6014e1c..7501fdb 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -71,7 +71,8 @@
 	uint	sdtimingctl;	/* SD timing control register */
 	char    reserved8[20];	/* reserved */
 	uint	dllcfg0;	/* DLL config 0 register */
-	char	reserved9[12];	/* reserved */
+	uint	dllcfg1;	/* DLL config 1 register */
+	char	reserved9[8];	/* reserved */
 	uint	dllstat0;	/* DLL status 0 register */
 	char    reserved10[664];/* reserved */
 	uint    esdhcctl;	/* eSDHC control register */
@@ -518,6 +519,24 @@
 	while (sdhc_clk / (div * pre_div) > clock && div < 16)
 		div++;
 
+	if (IS_ENABLED(CONFIG_SYS_FSL_ERRATUM_A011334) &&
+	    clock == 200000000 && mmc->selected_mode == MMC_HS_400) {
+		u32 div_ratio = pre_div * div;
+
+		if (div_ratio <= 4) {
+			pre_div = 4;
+			div = 1;
+		} else if (div_ratio <= 8) {
+			pre_div = 4;
+			div = 2;
+		} else if (div_ratio <= 12) {
+			pre_div = 4;
+			div = 3;
+		} else {
+			printf("unsupported clock division.\n");
+		}
+	}
+
 	mmc->clock = sdhc_clk / pre_div / div;
 	priv->clock = mmc->clock;
 
@@ -749,6 +768,9 @@
 	/* Set timout to the maximum value */
 	esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16);
 
+	if (IS_ENABLED(CONFIG_SYS_FSL_ESDHC_UNRELIABLE_PULSE_DETECTION_WORKAROUND))
+		esdhc_clrbits32(&regs->dllcfg1, DLL_PD_PULSE_STRETCH_SEL);
+
 	return 0;
 }
 
@@ -1063,9 +1085,14 @@
 	struct fsl_esdhc_plat *plat = dev_get_plat(dev);
 	struct fsl_esdhc_priv *priv = dev_get_priv(dev);
 	struct fsl_esdhc *regs = priv->esdhc_regs;
+	struct mmc *mmc = &plat->mmc;
 	u32 val, irqstaten;
 	int i;
 
+	if (IS_ENABLED(CONFIG_SYS_FSL_ERRATUM_A011334) &&
+	    plat->mmc.hs400_tuning)
+		set_sysctl(priv, mmc, mmc->clock);
+
 	esdhc_tuning_block_enable(priv, true);
 	esdhc_setbits32(&regs->autoc12err, EXECUTE_TUNING);
 
@@ -1073,7 +1100,7 @@
 	esdhc_write32(&regs->irqstaten, IRQSTATEN_BRR);
 
 	for (i = 0; i < MAX_TUNING_LOOP; i++) {
-		mmc_send_tuning(&plat->mmc, opcode, NULL);
+		mmc_send_tuning(mmc, opcode, NULL);
 		mdelay(1);
 
 		val = esdhc_read32(&regs->autoc12err);
diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c
index 6a9403d..a467583 100644
--- a/drivers/mmc/fsl_esdhc_imx.c
+++ b/drivers/mmc/fsl_esdhc_imx.c
@@ -146,6 +146,7 @@
  * @start_tuning_tap: the start point for tuning in tuning_ctrl register
  * @strobe_dll_delay_target: settings in strobe_dllctrl
  * @signal_voltage: indicating the current voltage
+ * @signal_voltage_switch_extra_delay_ms: extra delay for IO voltage switch
  * @cd_gpio: gpio for card detection
  * @wp_gpio: gpio for write protection
  */
@@ -170,6 +171,7 @@
 	u32 tuning_start_tap;
 	u32 strobe_dll_delay_target;
 	u32 signal_voltage;
+	u32 signal_voltage_switch_extra_delay_ms;
 #if CONFIG_IS_ENABLED(DM_REGULATOR)
 	struct udevice *vqmmc_dev;
 	struct udevice *vmmc_dev;
@@ -521,15 +523,6 @@
 		goto out;
 	}
 
-	/* Switch voltage to 1.8V if CMD11 succeeded */
-	if (cmd->cmdidx == SD_CMD_SWITCH_UHS18V) {
-		esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT);
-
-		printf("Run CMD11 1.8V switch\n");
-		/* Sleep for 5 ms - max time for card to switch to 1.8V */
-		udelay(5000);
-	}
-
 	/* Workaround for ESDHC errata ENGcm03648 */
 	if (!data && (cmd->resp_type & MMC_RSP_BUSY)) {
 		int timeout = 50000;
@@ -660,7 +653,10 @@
 	clk = (pre_div << 8) | (div << 4);
 
 #ifdef CONFIG_FSL_USDHC
-	esdhc_clrbits32(&regs->vendorspec, VENDORSPEC_CKEN);
+	esdhc_clrbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
+	ret = readx_poll_timeout(esdhc_read32, &regs->prsstat, tmp, tmp & PRSSTAT_SDOFF, 100);
+	if (ret)
+		pr_warn("fsl_esdhc_imx: Internal clock never gate off.\n");
 #else
 	esdhc_clrbits32(&regs->sysctl, SYSCTL_CKEN);
 #endif
@@ -672,7 +668,7 @@
 		pr_warn("fsl_esdhc_imx: Internal clock never stabilised.\n");
 
 #ifdef CONFIG_FSL_USDHC
-	esdhc_setbits32(&regs->vendorspec, VENDORSPEC_PEREN | VENDORSPEC_CKEN);
+	esdhc_setbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
 #else
 	esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_CKEN);
 #endif
@@ -727,8 +723,14 @@
 	struct fsl_esdhc_priv *priv = dev_get_priv(mmc->dev);
 	struct fsl_esdhc *regs = priv->esdhc_regs;
 	u32 val;
+	u32 tmp;
+	int ret;
 
 	if (priv->clock > ESDHC_STROBE_DLL_CLK_FREQ) {
+		esdhc_clrbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
+		ret = readx_poll_timeout(esdhc_read32, &regs->prsstat, tmp, tmp & PRSSTAT_SDOFF, 100);
+		if (ret)
+			pr_warn("fsl_esdhc_imx: Internal clock never gate off.\n");
 		esdhc_write32(&regs->strobe_dllctrl, ESDHC_STROBE_DLL_CTRL_RESET);
 
 		/*
@@ -746,6 +748,7 @@
 			pr_warn("HS400 strobe DLL status REF not lock!\n");
 		if (!(val & ESDHC_STROBE_DLL_STS_SLV_LOCK))
 			pr_warn("HS400 strobe DLL status SLV not lock!\n");
+		esdhc_setbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
 	}
 }
 
@@ -835,6 +838,14 @@
 		}
 #endif
 		esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT);
+		/*
+		 * some board like imx8mm-evk need about 18ms to switch
+		 * the IO voltage from 3.3v to 1.8v, common code only
+		 * delay 10ms, so need to delay extra time to make sure
+		 * the IO voltage change to 1.8v.
+		 */
+		if (priv->signal_voltage_switch_extra_delay_ms)
+			mdelay(priv->signal_voltage_switch_extra_delay_ms);
 		if (esdhc_read32(&regs->vendorspec) & ESDHC_VENDORSPEC_VSELECT)
 			return 0;
 
@@ -969,14 +980,18 @@
 #ifdef MMC_SUPPORTS_TUNING
 	if (mmc->clk_disable) {
 #ifdef CONFIG_FSL_USDHC
-		esdhc_clrbits32(&regs->vendorspec, VENDORSPEC_CKEN);
+		u32 tmp;
+
+		esdhc_clrbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
+		ret = readx_poll_timeout(esdhc_read32, &regs->prsstat, tmp, tmp & PRSSTAT_SDOFF, 100);
+		if (ret)
+			pr_warn("fsl_esdhc_imx: Internal clock never gate off.\n");
 #else
 		esdhc_clrbits32(&regs->sysctl, SYSCTL_CKEN);
 #endif
 	} else {
 #ifdef CONFIG_FSL_USDHC
-		esdhc_setbits32(&regs->vendorspec, VENDORSPEC_PEREN |
-				VENDORSPEC_CKEN);
+		esdhc_setbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
 #else
 		esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_CKEN);
 #endif
@@ -1052,7 +1067,7 @@
 #ifndef CONFIG_FSL_USDHC
 	esdhc_setbits32(&regs->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
 #else
-	esdhc_setbits32(&regs->vendorspec, VENDORSPEC_HCKEN | VENDORSPEC_IPGEN);
+	esdhc_setbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
 #endif
 
 	/* Set the initial clock speed */
@@ -1190,8 +1205,7 @@
 	esdhc_write32(&regs->autoc12err, 0);
 	esdhc_write32(&regs->clktunectrlstatus, 0);
 #else
-	esdhc_setbits32(&regs->vendorspec, VENDORSPEC_PEREN |
-			VENDORSPEC_HCKEN | VENDORSPEC_IPGEN | VENDORSPEC_CKEN);
+	esdhc_setbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
 #endif
 
 	if (priv->vs18_enable)
@@ -1446,6 +1460,8 @@
 	val = fdtdec_get_int(fdt, node, "fsl,strobe-dll-delay-target",
 			     ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_DEFAULT);
 	priv->strobe_dll_delay_target = val;
+	val = fdtdec_get_int(fdt, node, "fsl,signal-voltage-switch-extra-delay-ms", 0);
+	priv->signal_voltage_switch_extra_delay_ms = val;
 
 	if (dev_read_bool(dev, "broken-cd"))
 		priv->broken_cd = 1;
@@ -1530,8 +1546,7 @@
 	if (CONFIG_IS_ENABLED(DM_GPIO) && !priv->non_removable) {
 		struct udevice *gpiodev;
 
-		ret = device_get_by_driver_info_idx(dtplat->cd_gpios->idx,
-						    &gpiodev);
+		ret = device_get_by_ofplat_idx(dtplat->cd_gpios->idx, &gpiodev);
 		if (ret)
 			return ret;
 
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 53eabc9..d36aae3 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -383,18 +383,16 @@
 {
 	struct blk_desc *bdesc;
 	struct udevice *bdev;
-	int ret, devnum = -1;
+	int ret;
 
 	if (!mmc_get_ops(dev))
 		return -ENOSYS;
-#ifndef CONFIG_SPL_BUILD
-	/* Use the fixed index with aliase node's index */
-	ret = dev_read_alias_seq(dev, &devnum);
-	debug("%s: alias ret=%d, devnum=%d\n", __func__, ret, devnum);
-#endif
+
+	/* Use the fixed index with aliases node's index */
+	debug("%s: alias devnum=%d\n", __func__, dev_seq(dev));
 
 	ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC,
-			devnum, 512, 0, &bdev);
+			dev_seq(dev), 512, 0, &bdev);
 	if (ret) {
 		debug("Cannot create block device\n");
 		return ret;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index b4c8e7f..1e83007 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -3052,9 +3052,11 @@
 	struct mmc *m;
 	int ret;
 
-	ret = uclass_get_device(UCLASS_MMC, num, &dev);
-	if (ret)
-		return ret;
+	if (uclass_get_device_by_seq(UCLASS_MMC, num, &dev)) {
+		ret = uclass_get_device(UCLASS_MMC, num, &dev);
+		if (ret)
+			return ret;
+	}
 
 	m = mmc_get_mmc_dev(dev);
 	if (!m)
diff --git a/drivers/mmc/mvebu_mmc.c b/drivers/mmc/mvebu_mmc.c
index 8ec1f57..fea55c6 100644
--- a/drivers/mmc/mvebu_mmc.c
+++ b/drivers/mmc/mvebu_mmc.c
@@ -11,60 +11,67 @@
 #include <errno.h>
 #include <log.h>
 #include <malloc.h>
+#include <dm.h>
+#include <fdtdec.h>
 #include <part.h>
 #include <mmc.h>
-#include <asm/global_data.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>
 #include <mvebu_mmc.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#define DRIVER_NAME "MVEBU_MMC"
+#include <dm/device_compat.h>
 
 #define MVEBU_TARGET_DRAM 0
 
 #define TIMEOUT_DELAY	5*CONFIG_SYS_HZ		/* wait 5 seconds */
 
-static void mvebu_mmc_write(u32 offs, u32 val)
+static inline void *get_regbase(const struct mmc *mmc)
 {
-	writel(val, CONFIG_SYS_MMC_BASE + (offs));
+	struct mvebu_mmc_plat *pdata = mmc->priv;
+
+	return pdata->iobase;
 }
 
-static u32 mvebu_mmc_read(u32 offs)
+static void mvebu_mmc_write(const struct mmc *mmc, u32 offs, u32 val)
 {
-	return readl(CONFIG_SYS_MMC_BASE + (offs));
+	writel(val, get_regbase(mmc) + (offs));
 }
 
-static int mvebu_mmc_setup_data(struct mmc_data *data)
+static u32 mvebu_mmc_read(const struct mmc *mmc, u32 offs)
 {
+	return readl(get_regbase(mmc) + (offs));
+}
+
+static int mvebu_mmc_setup_data(struct udevice *dev, struct mmc_data *data)
+{
+	struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+	struct mmc *mmc = &pdata->mmc;
 	u32 ctrl_reg;
 
-	debug("%s, data %s : blocks=%d blksz=%d\n", DRIVER_NAME,
-	      (data->flags & MMC_DATA_READ) ? "read" : "write",
-	      data->blocks, data->blocksize);
+	dev_dbg(dev, "data %s : blocks=%d blksz=%d\n",
+		(data->flags & MMC_DATA_READ) ? "read" : "write",
+		data->blocks, data->blocksize);
 
 	/* default to maximum timeout */
-	ctrl_reg = mvebu_mmc_read(SDIO_HOST_CTRL);
+	ctrl_reg = mvebu_mmc_read(mmc, SDIO_HOST_CTRL);
 	ctrl_reg |= SDIO_HOST_CTRL_TMOUT(SDIO_HOST_CTRL_TMOUT_MAX);
-	mvebu_mmc_write(SDIO_HOST_CTRL, ctrl_reg);
+	mvebu_mmc_write(mmc, SDIO_HOST_CTRL, ctrl_reg);
 
 	if (data->flags & MMC_DATA_READ) {
-		mvebu_mmc_write(SDIO_SYS_ADDR_LOW, (u32)data->dest & 0xffff);
-		mvebu_mmc_write(SDIO_SYS_ADDR_HI, (u32)data->dest >> 16);
+		mvebu_mmc_write(mmc, SDIO_SYS_ADDR_LOW, (u32)data->dest & 0xffff);
+		mvebu_mmc_write(mmc, SDIO_SYS_ADDR_HI, (u32)data->dest >> 16);
 	} else {
-		mvebu_mmc_write(SDIO_SYS_ADDR_LOW, (u32)data->src & 0xffff);
-		mvebu_mmc_write(SDIO_SYS_ADDR_HI, (u32)data->src >> 16);
+		mvebu_mmc_write(mmc, SDIO_SYS_ADDR_LOW, (u32)data->src & 0xffff);
+		mvebu_mmc_write(mmc, SDIO_SYS_ADDR_HI, (u32)data->src >> 16);
 	}
 
-	mvebu_mmc_write(SDIO_BLK_COUNT, data->blocks);
-	mvebu_mmc_write(SDIO_BLK_SIZE, data->blocksize);
+	mvebu_mmc_write(mmc, SDIO_BLK_COUNT, data->blocks);
+	mvebu_mmc_write(mmc, SDIO_BLK_SIZE, data->blocksize);
 
 	return 0;
 }
 
-static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+static int mvebu_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 			      struct mmc_data *data)
 {
 	ulong start;
@@ -72,12 +79,14 @@
 	ushort resptype = 0;
 	ushort xfertype = 0;
 	ushort resp_indx = 0;
+	struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+	struct mmc *mmc = &pdata->mmc;
 
-	debug("%s: cmdidx [0x%x] resp_type[0x%x] cmdarg[0x%x]\n",
-	      DRIVER_NAME, cmd->cmdidx, cmd->resp_type, cmd->cmdarg);
+	dev_dbg(dev, "cmdidx [0x%x] resp_type[0x%x] cmdarg[0x%x]\n",
+		cmd->cmdidx, cmd->resp_type, cmd->cmdarg);
 
-	debug("%s: cmd %d (hw state 0x%04x)\n", DRIVER_NAME,
-	      cmd->cmdidx, mvebu_mmc_read(SDIO_HW_STATE));
+	dev_dbg(dev, "cmd %d (hw state 0x%04x)\n",
+		cmd->cmdidx, mvebu_mmc_read(mmc, SDIO_HW_STATE));
 
 	/*
 	 * Hardware weirdness.  The FIFO_EMPTY bit of the HW_STATE
@@ -88,26 +97,26 @@
 	 * this bit comes to good sense (which eventually happens by
 	 * itself) then the new transfer simply fails with a timeout.
 	 */
-	if (!(mvebu_mmc_read(SDIO_HW_STATE) & CMD_FIFO_EMPTY)) {
+	if (!(mvebu_mmc_read(mmc, SDIO_HW_STATE) & CMD_FIFO_EMPTY)) {
 		ushort hw_state, count = 0;
 
 		start = get_timer(0);
 		do {
-			hw_state = mvebu_mmc_read(SDIO_HW_STATE);
+			hw_state = mvebu_mmc_read(mmc, SDIO_HW_STATE);
 			if ((get_timer(0) - start) > TIMEOUT_DELAY) {
 				printf("%s : FIFO_EMPTY bit missing\n",
-				       DRIVER_NAME);
+				       dev->name);
 				break;
 			}
 			count++;
 		} while (!(hw_state & CMD_FIFO_EMPTY));
-		debug("%s *** wait for FIFO_EMPTY bit (hw=0x%04x, count=%d, jiffies=%ld)\n",
-		      DRIVER_NAME, hw_state, count, (get_timer(0) - (start)));
+		dev_dbg(dev, "*** wait for FIFO_EMPTY bit (hw=0x%04x, count=%d, jiffies=%ld)\n",
+			hw_state, count, (get_timer(0) - (start)));
 	}
 
 	/* Clear status */
-	mvebu_mmc_write(SDIO_NOR_INTR_STATUS, SDIO_POLL_MASK);
-	mvebu_mmc_write(SDIO_ERR_INTR_STATUS, SDIO_POLL_MASK);
+	mvebu_mmc_write(mmc, SDIO_NOR_INTR_STATUS, SDIO_POLL_MASK);
+	mvebu_mmc_write(mmc, SDIO_ERR_INTR_STATUS, SDIO_POLL_MASK);
 
 	resptype = SDIO_CMD_INDEX(cmd->cmdidx);
 
@@ -133,11 +142,10 @@
 	}
 
 	if (data) {
-		int err = mvebu_mmc_setup_data(data);
+		int err = mvebu_mmc_setup_data(dev, data);
 
 		if (err) {
-			debug("%s: command DATA error :%x\n",
-			      DRIVER_NAME, err);
+			dev_dbg(dev, "command DATA error :%x\n", err);
 			return err;
 		}
 
@@ -154,34 +162,33 @@
 	}
 
 	/* Setting cmd arguments */
-	mvebu_mmc_write(SDIO_ARG_LOW, cmd->cmdarg & 0xffff);
-	mvebu_mmc_write(SDIO_ARG_HI, cmd->cmdarg >> 16);
+	mvebu_mmc_write(mmc, SDIO_ARG_LOW, cmd->cmdarg & 0xffff);
+	mvebu_mmc_write(mmc, SDIO_ARG_HI, cmd->cmdarg >> 16);
 
 	/* Setting Xfer mode */
-	mvebu_mmc_write(SDIO_XFER_MODE, xfertype);
+	mvebu_mmc_write(mmc, SDIO_XFER_MODE, xfertype);
 
 	/* Sending command */
-	mvebu_mmc_write(SDIO_CMD, resptype);
+	mvebu_mmc_write(mmc, SDIO_CMD, resptype);
 
 	start = get_timer(0);
 
-	while (!((mvebu_mmc_read(SDIO_NOR_INTR_STATUS)) & waittype)) {
-		if (mvebu_mmc_read(SDIO_NOR_INTR_STATUS) & SDIO_NOR_ERROR) {
-			debug("%s: error! cmdidx : %d, err reg: %04x\n",
-			      DRIVER_NAME, cmd->cmdidx,
-			      mvebu_mmc_read(SDIO_ERR_INTR_STATUS));
-			if (mvebu_mmc_read(SDIO_ERR_INTR_STATUS) &
+	while (!((mvebu_mmc_read(mmc, SDIO_NOR_INTR_STATUS)) & waittype)) {
+		if (mvebu_mmc_read(mmc, SDIO_NOR_INTR_STATUS) & SDIO_NOR_ERROR) {
+			dev_dbg(dev, "error! cmdidx : %d, err reg: %04x\n",
+				cmd->cmdidx,
+				mvebu_mmc_read(mmc, SDIO_ERR_INTR_STATUS));
+			if (mvebu_mmc_read(mmc, SDIO_ERR_INTR_STATUS) &
 			    (SDIO_ERR_CMD_TIMEOUT | SDIO_ERR_DATA_TIMEOUT)) {
-				debug("%s: command READ timed out\n",
-				      DRIVER_NAME);
+				dev_dbg(dev, "command READ timed out\n");
 				return -ETIMEDOUT;
 			}
-			debug("%s: command READ error\n", DRIVER_NAME);
+			dev_dbg(dev, "command READ error\n");
 			return -ECOMM;
 		}
 
 		if ((get_timer(0) - start) > TIMEOUT_DELAY) {
-			debug("%s: command timed out\n", DRIVER_NAME);
+			dev_dbg(dev, "command timed out\n");
 			return -ETIMEDOUT;
 		}
 	}
@@ -191,8 +198,7 @@
 		uint response[8];
 
 		for (resp_indx = 0; resp_indx < 8; resp_indx++)
-			response[resp_indx]
-				= mvebu_mmc_read(SDIO_RSP(resp_indx));
+			response[resp_indx] = mvebu_mmc_read(mmc, SDIO_RSP(resp_indx));
 
 		cmd->response[0] =	((response[0] & 0x03ff) << 22) |
 					((response[1] & 0xffff) << 6) |
@@ -209,8 +215,7 @@
 		uint response[3];
 
 		for (resp_indx = 0; resp_indx < 3; resp_indx++)
-			response[resp_indx]
-				= mvebu_mmc_read(SDIO_RSP(resp_indx));
+			response[resp_indx] = mvebu_mmc_read(mmc, SDIO_RSP(resp_indx));
 
 		cmd->response[0] =	((response[2] & 0x003f) << (8 - 8)) |
 					((response[1] & 0xffff) << (14 - 8)) |
@@ -225,64 +230,71 @@
 		cmd->response[3] =	0;
 	}
 
-	debug("%s: resp[0x%x] ", DRIVER_NAME, cmd->resp_type);
+	dev_dbg(dev, "resp[0x%x] ", cmd->resp_type);
 	debug("[0x%x] ", cmd->response[0]);
 	debug("[0x%x] ", cmd->response[1]);
 	debug("[0x%x] ", cmd->response[2]);
 	debug("[0x%x] ", cmd->response[3]);
 	debug("\n");
 
-	if (mvebu_mmc_read(SDIO_ERR_INTR_STATUS) &
+	if (mvebu_mmc_read(mmc, SDIO_ERR_INTR_STATUS) &
 		(SDIO_ERR_CMD_TIMEOUT | SDIO_ERR_DATA_TIMEOUT))
 		return -ETIMEDOUT;
 
 	return 0;
 }
 
-static void mvebu_mmc_power_up(void)
+static void mvebu_mmc_power_up(struct udevice *dev)
 {
-	debug("%s: power up\n", DRIVER_NAME);
+	struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+	struct mmc *mmc = &pdata->mmc;
+
+	dev_dbg(dev, "power up\n");
 
 	/* disable interrupts */
-	mvebu_mmc_write(SDIO_NOR_INTR_EN, 0);
-	mvebu_mmc_write(SDIO_ERR_INTR_EN, 0);
+	mvebu_mmc_write(mmc, SDIO_NOR_INTR_EN, 0);
+	mvebu_mmc_write(mmc, SDIO_ERR_INTR_EN, 0);
 
 	/* SW reset */
-	mvebu_mmc_write(SDIO_SW_RESET, SDIO_SW_RESET_NOW);
+	mvebu_mmc_write(mmc, SDIO_SW_RESET, SDIO_SW_RESET_NOW);
 
-	mvebu_mmc_write(SDIO_XFER_MODE, 0);
+	mvebu_mmc_write(mmc, SDIO_XFER_MODE, 0);
 
 	/* enable status */
-	mvebu_mmc_write(SDIO_NOR_STATUS_EN, SDIO_POLL_MASK);
-	mvebu_mmc_write(SDIO_ERR_STATUS_EN, SDIO_POLL_MASK);
+	mvebu_mmc_write(mmc, SDIO_NOR_STATUS_EN, SDIO_POLL_MASK);
+	mvebu_mmc_write(mmc, SDIO_ERR_STATUS_EN, SDIO_POLL_MASK);
 
 	/* enable interrupts status */
-	mvebu_mmc_write(SDIO_NOR_INTR_STATUS, SDIO_POLL_MASK);
-	mvebu_mmc_write(SDIO_ERR_INTR_STATUS, SDIO_POLL_MASK);
+	mvebu_mmc_write(mmc, SDIO_NOR_INTR_STATUS, SDIO_POLL_MASK);
+	mvebu_mmc_write(mmc, SDIO_ERR_INTR_STATUS, SDIO_POLL_MASK);
 }
 
-static void mvebu_mmc_set_clk(unsigned int clock)
+static void mvebu_mmc_set_clk(struct udevice *dev, unsigned int clock)
 {
 	unsigned int m;
+	struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+	struct mmc *mmc = &pdata->mmc;
 
 	if (clock == 0) {
-		debug("%s: clock off\n", DRIVER_NAME);
-		mvebu_mmc_write(SDIO_XFER_MODE, SDIO_XFER_MODE_STOP_CLK);
-		mvebu_mmc_write(SDIO_CLK_DIV, MVEBU_MMC_BASE_DIV_MAX);
+		dev_dbg(dev, "clock off\n");
+		mvebu_mmc_write(mmc, SDIO_XFER_MODE, SDIO_XFER_MODE_STOP_CLK);
+		mvebu_mmc_write(mmc, SDIO_CLK_DIV, MVEBU_MMC_BASE_DIV_MAX);
 	} else {
 		m = MVEBU_MMC_BASE_FAST_CLOCK/(2*clock) - 1;
 		if (m > MVEBU_MMC_BASE_DIV_MAX)
 			m = MVEBU_MMC_BASE_DIV_MAX;
-		mvebu_mmc_write(SDIO_CLK_DIV, m & MVEBU_MMC_BASE_DIV_MAX);
-		debug("%s: clock (%d) div : %d\n", DRIVER_NAME, clock, m);
+		mvebu_mmc_write(mmc, SDIO_CLK_DIV, m & MVEBU_MMC_BASE_DIV_MAX);
+		dev_dbg(dev, "clock (%d) div : %d\n", clock, m);
 	}
 }
 
-static void mvebu_mmc_set_bus(unsigned int bus)
+static void mvebu_mmc_set_bus(struct udevice *dev, unsigned int bus)
 {
+	struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+	struct mmc *mmc = &pdata->mmc;
 	u32 ctrl_reg = 0;
 
-	ctrl_reg = mvebu_mmc_read(SDIO_HOST_CTRL);
+	ctrl_reg = mvebu_mmc_read(mmc, SDIO_HOST_CTRL);
 	ctrl_reg &= ~SDIO_HOST_CTRL_DATA_WIDTH_4_BITS;
 
 	switch (bus) {
@@ -306,23 +318,26 @@
 
 	ctrl_reg |= SDIO_HOST_CTRL_CARD_TYPE_MEM_ONLY;
 
-	debug("%s: ctrl 0x%04x: %s %s %s\n", DRIVER_NAME, ctrl_reg,
-	      (ctrl_reg & SDIO_HOST_CTRL_PUSH_PULL_EN) ?
-	      "push-pull" : "open-drain",
-	      (ctrl_reg & SDIO_HOST_CTRL_DATA_WIDTH_4_BITS) ?
-	      "4bit-width" : "1bit-width",
-	      (ctrl_reg & SDIO_HOST_CTRL_HI_SPEED_EN) ?
-	      "high-speed" : "");
+	dev_dbg(dev, "ctrl 0x%04x: %s %s %s\n", ctrl_reg,
+		(ctrl_reg & SDIO_HOST_CTRL_PUSH_PULL_EN) ?
+		"push-pull" : "open-drain",
+		(ctrl_reg & SDIO_HOST_CTRL_DATA_WIDTH_4_BITS) ?
+		"4bit-width" : "1bit-width",
+		(ctrl_reg & SDIO_HOST_CTRL_HI_SPEED_EN) ?
+		"high-speed" : "");
 
-	mvebu_mmc_write(SDIO_HOST_CTRL, ctrl_reg);
+	mvebu_mmc_write(mmc, SDIO_HOST_CTRL, ctrl_reg);
 }
 
-static int mvebu_mmc_set_ios(struct mmc *mmc)
+static int mvebu_mmc_set_ios(struct udevice *dev)
 {
-	debug("%s: bus[%d] clock[%d]\n", DRIVER_NAME,
-	      mmc->bus_width, mmc->clock);
-	mvebu_mmc_set_bus(mmc->bus_width);
-	mvebu_mmc_set_clk(mmc->clock);
+	struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+	struct mmc *mmc = &pdata->mmc;
+
+	dev_dbg(dev, "bus[%d] clock[%d]\n",
+		mmc->bus_width, mmc->clock);
+	mvebu_mmc_set_bus(dev, mmc->bus_width);
+	mvebu_mmc_set_clk(dev, mmc->clock);
 
 	return 0;
 }
@@ -330,13 +345,13 @@
 /*
  * Set window register.
  */
-static void mvebu_window_setup(void)
+static void mvebu_window_setup(const struct mmc *mmc)
 {
 	int i;
 
 	for (i = 0; i < 4; i++) {
-		mvebu_mmc_write(WINDOW_CTRL(i), 0);
-		mvebu_mmc_write(WINDOW_BASE(i), 0);
+		mvebu_mmc_write(mmc, WINDOW_CTRL(i), 0);
+		mvebu_mmc_write(mmc, WINDOW_BASE(i), 0);
 	}
 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
 		u32 size, base, attrib;
@@ -364,79 +379,119 @@
 		size = gd->bd->bi_dram[i].size;
 		base = gd->bd->bi_dram[i].start;
 		if (size && attrib) {
-			mvebu_mmc_write(WINDOW_CTRL(i),
+			mvebu_mmc_write(mmc, WINDOW_CTRL(i),
 					MVCPU_WIN_CTRL_DATA(size,
 							    MVEBU_TARGET_DRAM,
 							    attrib,
 							    MVCPU_WIN_ENABLE));
 		} else {
-			mvebu_mmc_write(WINDOW_CTRL(i), MVCPU_WIN_DISABLE);
+			mvebu_mmc_write(mmc, WINDOW_CTRL(i), MVCPU_WIN_DISABLE);
 		}
-		mvebu_mmc_write(WINDOW_BASE(i), base);
+		mvebu_mmc_write(mmc, WINDOW_BASE(i), base);
 	}
 }
 
-static int mvebu_mmc_initialize(struct mmc *mmc)
+static int mvebu_mmc_initialize(struct udevice *dev)
 {
-	debug("%s: mvebu_mmc_initialize\n", DRIVER_NAME);
+	struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+	struct mmc *mmc = &pdata->mmc;
+
+	dev_dbg(dev, "%s\n", __func__);
 
 	/*
 	 * Setting host parameters
 	 * Initial Host Ctrl : Timeout : max , Normal Speed mode,
 	 * 4-bit data mode, Big Endian, SD memory Card, Push_pull CMD Line
 	 */
-	mvebu_mmc_write(SDIO_HOST_CTRL,
+	mvebu_mmc_write(mmc, SDIO_HOST_CTRL,
 			SDIO_HOST_CTRL_TMOUT(SDIO_HOST_CTRL_TMOUT_MAX) |
 			SDIO_HOST_CTRL_DATA_WIDTH_4_BITS |
 			SDIO_HOST_CTRL_BIG_ENDIAN |
 			SDIO_HOST_CTRL_PUSH_PULL_EN |
 			SDIO_HOST_CTRL_CARD_TYPE_MEM_ONLY);
 
-	mvebu_mmc_write(SDIO_CLK_CTRL, 0);
+	mvebu_mmc_write(mmc, SDIO_CLK_CTRL, 0);
 
 	/* enable status */
-	mvebu_mmc_write(SDIO_NOR_STATUS_EN, SDIO_POLL_MASK);
-	mvebu_mmc_write(SDIO_ERR_STATUS_EN, SDIO_POLL_MASK);
+	mvebu_mmc_write(mmc, SDIO_NOR_STATUS_EN, SDIO_POLL_MASK);
+	mvebu_mmc_write(mmc, SDIO_ERR_STATUS_EN, SDIO_POLL_MASK);
 
 	/* disable interrupts */
-	mvebu_mmc_write(SDIO_NOR_INTR_EN, 0);
-	mvebu_mmc_write(SDIO_ERR_INTR_EN, 0);
+	mvebu_mmc_write(mmc, SDIO_NOR_INTR_EN, 0);
+	mvebu_mmc_write(mmc, SDIO_ERR_INTR_EN, 0);
 
-	mvebu_window_setup();
+	mvebu_window_setup(mmc);
 
 	/* SW reset */
-	mvebu_mmc_write(SDIO_SW_RESET, SDIO_SW_RESET_NOW);
+	mvebu_mmc_write(mmc, SDIO_SW_RESET, SDIO_SW_RESET_NOW);
 
 	return 0;
 }
 
-static const struct mmc_ops mvebu_mmc_ops = {
-	.send_cmd	= mvebu_mmc_send_cmd,
-	.set_ios	= mvebu_mmc_set_ios,
-	.init		= mvebu_mmc_initialize,
-};
-
-static struct mmc_config mvebu_mmc_cfg = {
-	.name		= DRIVER_NAME,
-	.ops		= &mvebu_mmc_ops,
-	.f_min		= MVEBU_MMC_BASE_FAST_CLOCK / MVEBU_MMC_BASE_DIV_MAX,
-	.f_max		= MVEBU_MMC_CLOCKRATE_MAX,
-	.voltages	= MMC_VDD_32_33 | MMC_VDD_33_34,
-	.host_caps	= MMC_MODE_4BIT | MMC_MODE_HS |
-			  MMC_MODE_HS_52MHz,
-	.part_type	= PART_TYPE_DOS,
-	.b_max		= CONFIG_SYS_MMC_MAX_BLK_COUNT,
-};
-
-int mvebu_mmc_init(struct bd_info *bis)
+static int mvebu_mmc_of_to_plat(struct udevice *dev)
 {
-	struct mmc *mmc;
+	struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+	fdt_addr_t addr;
 
-	mvebu_mmc_power_up();
+	addr = dev_read_addr(dev);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
 
-	mmc = mmc_create(&mvebu_mmc_cfg, bis);
-	if (mmc == NULL)
-		return -1;
+	pdata->iobase = (void *)addr;
 
 	return 0;
 }
+
+static int mvebu_mmc_probe(struct udevice *dev)
+{
+	struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct mmc *mmc = &pdata->mmc;
+	struct mmc_config *cfg = &pdata->cfg;
+
+	cfg->name = dev->name;
+	cfg->f_min = MVEBU_MMC_BASE_FAST_CLOCK / MVEBU_MMC_BASE_DIV_MAX;
+	cfg->f_max = MVEBU_MMC_CLOCKRATE_MAX;
+	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+	cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_HS | MMC_MODE_HS_52MHz;
+	cfg->part_type = PART_TYPE_DOS;
+	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+	mmc->cfg = cfg;
+	mmc->priv = pdata;
+	mmc->dev = dev;
+	upriv->mmc = mmc;
+
+	mvebu_mmc_power_up(dev);
+	mvebu_mmc_initialize(dev);
+
+	return 0;
+}
+
+static const struct dm_mmc_ops mvebu_dm_mmc_ops = {
+	.send_cmd = mvebu_mmc_send_cmd,
+	.set_ios = mvebu_mmc_set_ios,
+};
+
+static int mvebu_mmc_bind(struct udevice *dev)
+{
+	struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+
+	return mmc_bind(dev, &pdata->mmc, &pdata->cfg);
+}
+
+static const struct udevice_id mvebu_mmc_match[] = {
+	{ .compatible = "marvell,orion-sdio" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(mvebu_mmc) = {
+	.name = "mvebu_mmc",
+	.id = UCLASS_MMC,
+	.of_match = mvebu_mmc_match,
+	.ops = &mvebu_dm_mmc_ops,
+	.probe = mvebu_mmc_probe,
+	.bind = mvebu_mmc_bind,
+	.of_to_plat = mvebu_mmc_of_to_plat,
+	.plat_auto = sizeof(struct mvebu_mmc_plat),
+};
diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c
index fd5dd22..b9ab064 100644
--- a/drivers/mmc/pci_mmc.c
+++ b/drivers/mmc/pci_mmc.c
@@ -53,6 +53,7 @@
 	host->ioaddr = (void *)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
 					      PCI_REGION_MEM);
 	host->name = dev->name;
+	host->cd_gpio = priv->cd_gpio;
 	host->mmc = &plat->mmc;
 	host->mmc->dev = dev;
 	ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
@@ -68,8 +69,11 @@
 {
 	if (CONFIG_IS_ENABLED(DM_GPIO)) {
 		struct pci_mmc_priv *priv = dev_get_priv(dev);
+		int ret;
 
-		gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN);
+		ret = gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio,
+					   GPIOD_IS_IN);
+		log_debug("cd-gpio %s done, ret=%d\n", dev->name, ret);
 	}
 
 	return 0;
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index b4512e3..9642d7c 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -218,7 +218,7 @@
 {
 	unsigned int byte_offset = offset * info->portwidth;
 
-	return (void *)(info->start[sect] + byte_offset);
+	return (void *)(info->start[sect] + (byte_offset << info->chip_lsb));
 }
 
 static inline void flash_unmap(flash_info_t *info, flash_sect_t sect,
@@ -1918,12 +1918,27 @@
 			flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP,
 				       sizeof(struct cfi_qry));
 			info->interface	= le16_to_cpu(qry->interface_desc);
+			/* Some flash chips can support multiple bus widths.
+			 * In this case, override the interface width and
+			 * limit it to the port width.
+			 */
+			if ((info->interface == FLASH_CFI_X8X16) &&
+					(info->portwidth == FLASH_CFI_8BIT)) {
+				debug("Overriding 16-bit interface width to"
+						" 8-bit port width\n");
+				info->interface = FLASH_CFI_X8;
+			} else if ((info->interface == FLASH_CFI_X16X32) &&
+					(info->portwidth == FLASH_CFI_16BIT)) {
+				debug("Overriding 16-bit interface width to"
+						" 16-bit port width\n");
+				info->interface = FLASH_CFI_X16;
+			}
 
 			info->cfi_offset = flash_offset_cfi[cfi_offset];
 			debug("device interface is %d\n",
 			      info->interface);
-			debug("found port %d chip %d ",
-			      info->portwidth, info->chipwidth);
+			debug("found port %d chip %d chip_lsb %d ",
+			      info->portwidth, info->chipwidth, info->chip_lsb);
 			debug("port %d bits chip %d bits\n",
 			      info->portwidth << CFI_FLASH_SHIFT_WIDTH,
 			      info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
@@ -1962,9 +1977,23 @@
 	     info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) {
 		for (info->chipwidth = FLASH_CFI_BY8;
 		     info->chipwidth <= info->portwidth;
-		     info->chipwidth <<= 1)
+		     info->chipwidth <<= 1) {
+			/*
+			 * First, try detection without shifting the addresses
+			 * for 8bit devices (16bit wide connection)
+			 */
+			info->chip_lsb = 0;
 			if (__flash_detect_cfi(info, qry))
 				return 1;
+
+			/*
+			 * Not detected, so let's try with shifting
+			 * for 8bit devices
+			 */
+			info->chip_lsb = 1;
+			if (__flash_detect_cfi(info, qry))
+				return 1;
+		}
 	}
 	debug("not found\n");
 	return 0;
diff --git a/drivers/mtd/nand/raw/mxs_nand_spl.c b/drivers/mtd/nand/raw/mxs_nand_spl.c
index 46dc29d..17f46ae 100644
--- a/drivers/mtd/nand/raw/mxs_nand_spl.c
+++ b/drivers/mtd/nand/raw/mxs_nand_spl.c
@@ -282,6 +282,11 @@
 	return 0;
 }
 
+struct mtd_info *nand_get_mtd(void)
+{
+	return mtd;
+}
+
 int nand_default_bbt(struct mtd_info *mtd)
 {
 	return 0;
diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c
index 12d1321..cfce00e 100644
--- a/drivers/mtd/spi/sf-uclass.c
+++ b/drivers/mtd/spi/sf-uclass.c
@@ -31,6 +31,15 @@
 	return log_ret(sf_get_ops(dev)->erase(dev, offset, len));
 }
 
+int spl_flash_get_sw_write_prot(struct udevice *dev)
+{
+	struct dm_spi_flash_ops *ops = sf_get_ops(dev);
+
+	if (!ops->get_sw_write_prot)
+		return -ENOSYS;
+	return log_ret(ops->get_sw_write_prot(dev));
+}
+
 /*
  * TODO(sjg@chromium.org): This is an old-style function. We should remove
  * it when all SPI flash drivers use dm
@@ -46,11 +55,6 @@
 	return dev_get_uclass_priv(dev);
 }
 
-void spi_flash_free(struct spi_flash *flash)
-{
-	device_remove(flash->spi->dev, DM_REMOVE_NORMAL);
-}
-
 int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs,
 			   unsigned int max_hz, unsigned int spi_mode,
 			   struct udevice **devp)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index 9ceff0e..786301b 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -75,6 +75,10 @@
 #define JEDEC_MFR(info)	((info)->id[0])
 #define JEDEC_ID(info)		(((info)->id[1]) << 8 | ((info)->id[2]))
 
+/* Get software write-protect value (BP bits) */
+int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash);
+
+
 #if CONFIG_IS_ENABLED(SPI_FLASH_MTD)
 int spi_flash_mtd_register(struct spi_flash *flash);
 void spi_flash_mtd_unregister(void);
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 6c87434..3befbe9 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -130,6 +130,13 @@
 	return mtd->_erase(mtd, &instr);
 }
 
+static int spi_flash_std_get_sw_write_prot(struct udevice *dev)
+{
+	struct spi_flash *flash = dev_get_uclass_priv(dev);
+
+	return spi_flash_cmd_get_sw_write_prot(flash);
+}
+
 int spi_flash_std_probe(struct udevice *dev)
 {
 	struct spi_slave *slave = dev_get_parent_priv(dev);
@@ -153,6 +160,7 @@
 	.read = spi_flash_std_read,
 	.write = spi_flash_std_write,
 	.erase = spi_flash_std_erase,
+	.get_sw_write_prot = spi_flash_std_get_sw_write_prot,
 };
 
 static const struct udevice_id spi_flash_std_ids[] = {
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index e0efebc..a662553 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -2647,3 +2647,14 @@
 
 	return 0;
 }
+
+/* U-Boot specific functions, need to extend MTD to support these */
+int spi_flash_cmd_get_sw_write_prot(struct spi_nor *nor)
+{
+	int sr = read_sr(nor);
+
+	if (sr < 0)
+		return sr;
+
+	return (sr >> 2) & 7;
+}
diff --git a/drivers/mtd/spi/spi-nor-tiny.c b/drivers/mtd/spi/spi-nor-tiny.c
index 07c8c7b..1d5861d 100644
--- a/drivers/mtd/spi/spi-nor-tiny.c
+++ b/drivers/mtd/spi/spi-nor-tiny.c
@@ -809,3 +809,9 @@
 
 	return 0;
 }
+
+/* U-Boot specific functions, need to extend MTD to support these */
+int spi_flash_cmd_get_sw_write_prot(struct spi_nor *nor)
+{
+	return -ENOTSUPP;
+}
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 0e84c22..cf062fa 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -271,6 +271,14 @@
 	  100Mbit and 1 Gbit operation. You must enable CONFIG_PHYLIB to
 	  provide the PHY (physical media interface).
 
+config ETH_DESIGNWARE_MESON8B
+	bool "Amlogic Meson8b and later glue driver for Synopsys Designware Ethernet MAC"
+	depends on DM_ETH
+	select ETH_DESIGNWARE
+	help
+	  This provides glue layer to use Synopsys Designware Ethernet MAC
+	  present on the Amlogic Meson8b, GX, AXG & G12A SoCs.
+
 config ETH_DESIGNWARE_SOCFPGA
 	select REGMAP
 	select SYSCON
@@ -790,4 +798,18 @@
 	  This driver supports the MDIO bus found on the Fman 10G Ethernet MACs and
 	  on the mEMAC (which supports both Clauses 22 and 45).
 
+config MDIO_MUX_MMIOREG
+	bool "MDIO MUX accessed as a MMIO register access"
+	depends on DM_MDIO_MUX
+	help
+	  This driver is used for MDIO muxes driven by writing to a register in
+	  the MMIO physical memory.
+
+config MDIO_MUX_MESON_G12A
+	bool "MDIO MUX for Amlogic Meson G12A SoCs"
+	depends on DM_MDIO_MUX
+	help
+	  This driver is used for the MDIO mux found on the Amlogic G12A & compatible
+	  SoCs.
+
 endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a19511a..ce7b9e3 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -18,6 +18,7 @@
 obj-$(CONFIG_CS8900) += cs8900.o
 obj-$(CONFIG_TULIP) += dc2114x.o
 obj-$(CONFIG_ETH_DESIGNWARE) += designware.o
+obj-$(CONFIG_ETH_DESIGNWARE_MESON8B) += dwmac_meson8b.o
 obj-$(CONFIG_ETH_DESIGNWARE_SOCFPGA) += dwmac_socfpga.o
 obj-$(CONFIG_ETH_DESIGNWARE_S700) += dwmac_s700.o
 obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o
@@ -43,6 +44,8 @@
 obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
 obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.o
 obj-$(CONFIG_MDIO_MUX_I2CREG) += mdio_mux_i2creg.o
+obj-$(CONFIG_MDIO_MUX_MESON_G12A) += mdio_mux_meson_g12a.o
+obj-$(CONFIG_MDIO_MUX_MMIOREG) += mdio_mux_mmioreg.o
 obj-$(CONFIG_MDIO_MUX_SANDBOX) += mdio_mux_sandbox.o
 obj-$(CONFIG_MPC8XX_FEC) += mpc8xx_fec.o
 obj-$(CONFIG_MT7620_ETH) += mt7620-eth.o
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index 9dba55a..b8ba00b 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -21,7 +21,9 @@
 #include <reset.h>
 #include <asm/cache.h>
 #include <dm/device_compat.h>
+#include <dm/device-internal.h>
 #include <dm/devres.h>
+#include <dm/lists.h>
 #include <linux/compiler.h>
 #include <linux/delay.h>
 #include <linux/err.h>
@@ -122,6 +124,55 @@
 }
 #endif
 
+#if IS_ENABLED(CONFIG_DM_MDIO)
+int designware_eth_mdio_read(struct udevice *mdio_dev, int addr, int devad, int reg)
+{
+	struct mdio_perdev_priv *pdata = dev_get_uclass_priv(mdio_dev);
+
+	return dw_mdio_read(pdata->mii_bus, addr, devad, reg);
+}
+
+int designware_eth_mdio_write(struct udevice *mdio_dev, int addr, int devad, int reg, u16 val)
+{
+	struct mdio_perdev_priv *pdata = dev_get_uclass_priv(mdio_dev);
+
+	return dw_mdio_write(pdata->mii_bus, addr, devad, reg, val);
+}
+
+#if CONFIG_IS_ENABLED(DM_GPIO)
+int designware_eth_mdio_reset(struct udevice *mdio_dev)
+{
+	struct mdio_perdev_priv *pdata = dev_get_uclass_priv(mdio_dev);
+
+	return dw_mdio_reset(pdata->mii_bus);
+}
+#endif
+
+static const struct mdio_ops designware_eth_mdio_ops = {
+	.read = designware_eth_mdio_read,
+	.write = designware_eth_mdio_write,
+#if CONFIG_IS_ENABLED(DM_GPIO)
+	.reset = designware_eth_mdio_reset,
+#endif
+};
+
+static int designware_eth_mdio_probe(struct udevice *dev)
+{
+	/* Use the priv data of parent */
+	dev_set_priv(dev, dev_get_priv(dev->parent));
+
+	return 0;
+}
+
+U_BOOT_DRIVER(designware_eth_mdio) = {
+	.name = "eth_designware_mdio",
+	.id = UCLASS_MDIO,
+	.probe = designware_eth_mdio_probe,
+	.ops = &designware_eth_mdio_ops,
+	.plat_auto = sizeof(struct mdio_perdev_priv),
+};
+#endif
+
 static int dw_mdio_init(const char *name, void *priv)
 {
 	struct mii_dev *bus = mdio_alloc();
@@ -143,6 +194,34 @@
 	return mdio_register(bus);
 }
 
+#if IS_ENABLED(CONFIG_DM_MDIO)
+static int dw_dm_mdio_init(const char *name, void *priv)
+{
+	struct udevice *dev = priv;
+	ofnode node;
+	int ret;
+
+	ofnode_for_each_subnode(node, dev_ofnode(dev)) {
+		const char *subnode_name = ofnode_get_name(node);
+		struct udevice *mdiodev;
+
+		if (strcmp(subnode_name, "mdio"))
+			continue;
+
+		ret = device_bind_driver_to_node(dev, "eth_designware_mdio",
+						 subnode_name, node, &mdiodev);
+		if (ret)
+			debug("%s: not able to bind mdio device node\n", __func__);
+
+		return 0;
+	}
+
+	printf("%s: mdio node is missing, registering legacy mdio bus", __func__);
+
+	return dw_mdio_init(name, priv);
+}
+#endif
+
 static void tx_descs_init(struct dw_eth_dev *priv)
 {
 	struct eth_dma_regs *dma_p = priv->dma_regs_p;
@@ -487,7 +566,14 @@
 static int dw_phy_init(struct dw_eth_dev *priv, void *dev)
 {
 	struct phy_device *phydev;
-	int phy_addr = -1, ret;
+	int ret;
+
+#if IS_ENABLED(CONFIG_DM_MDIO) && IS_ENABLED(CONFIG_DM_ETH)
+	phydev = dm_eth_phy_connect(dev);
+	if (!phydev)
+		return -ENODEV;
+#else
+	int phy_addr = -1;
 
 #ifdef CONFIG_PHY_ADDR
 	phy_addr = CONFIG_PHY_ADDR;
@@ -496,6 +582,7 @@
 	phydev = phy_connect(priv->bus, phy_addr, dev, priv->interface);
 	if (!phydev)
 		return -ENODEV;
+#endif
 
 	phydev->supported &= PHY_GBIT_FEATURES;
 	if (priv->max_speed) {
@@ -759,7 +846,11 @@
 	priv->interface = pdata->phy_interface;
 	priv->max_speed = pdata->max_speed;
 
+#if IS_ENABLED(CONFIG_DM_MDIO)
+	ret = dw_dm_mdio_init(dev->name, dev);
+#else
 	ret = dw_mdio_init(dev->name, dev);
+#endif
 	if (ret) {
 		err = ret;
 		goto mdio_err;
@@ -856,9 +947,6 @@
 static const struct udevice_id designware_eth_ids[] = {
 	{ .compatible = "allwinner,sun7i-a20-gmac" },
 	{ .compatible = "amlogic,meson6-dwmac" },
-	{ .compatible = "amlogic,meson-gx-dwmac" },
-	{ .compatible = "amlogic,meson-gxbb-dwmac" },
-	{ .compatible = "amlogic,meson-axg-dwmac" },
 	{ .compatible = "st,stm32-dwmac" },
 	{ .compatible = "snps,arc-dwmac-3.70a" },
 	{ }
diff --git a/drivers/net/dwmac_meson8b.c b/drivers/net/dwmac_meson8b.c
new file mode 100644
index 0000000..c0b6ef4
--- /dev/null
+++ b/drivers/net/dwmac_meson8b.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021 BayLibre, SAS
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <dm.h>
+#include <phy.h>
+#include "designware.h"
+#include <dm/device_compat.h>
+#include <linux/err.h>
+
+#define ETH_REG_0		0x0
+#define ETH_REG_1		0x4
+#define ETH_REG_2		0x18
+#define ETH_REG_3		0x1c
+
+#define GX_ETH_REG_0_PHY_INTF		BIT(0)
+#define GX_ETH_REG_0_TX_PHASE(x)	(((x) & 3) << 5)
+#define GX_ETH_REG_0_TX_RATIO(x)	(((x) & 7) << 7)
+#define GX_ETH_REG_0_PHY_CLK_EN	BIT(10)
+#define GX_ETH_REG_0_INVERT_RMII_CLK	BIT(11)
+#define GX_ETH_REG_0_CLK_EN		BIT(12)
+
+#define AXG_ETH_REG_0_PHY_INTF_RGMII	BIT(0)
+#define AXG_ETH_REG_0_PHY_INTF_RMII	BIT(2)
+#define AXG_ETH_REG_0_TX_PHASE(x)	(((x) & 3) << 5)
+#define AXG_ETH_REG_0_TX_RATIO(x)	(((x) & 7) << 7)
+#define AXG_ETH_REG_0_PHY_CLK_EN	BIT(10)
+#define AXG_ETH_REG_0_INVERT_RMII_CLK	BIT(11)
+#define AXG_ETH_REG_0_CLK_EN		BIT(12)
+
+struct dwmac_meson8b_plat {
+	struct dw_eth_pdata dw_eth_pdata;
+	int (*dwmac_setup)(struct udevice *dev, struct eth_pdata *edata);
+	void *regs;
+};
+
+static int dwmac_meson8b_of_to_plat(struct udevice *dev)
+{
+	struct dwmac_meson8b_plat *pdata = dev_get_plat(dev);
+
+	pdata->regs = (void *)dev_read_addr_index(dev, 1);
+	if ((fdt_addr_t)pdata->regs == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	pdata->dwmac_setup = (void *)dev_get_driver_data(dev);
+	if (!pdata->dwmac_setup)
+		return -EINVAL;
+
+	return designware_eth_of_to_plat(dev);
+}
+
+static int dwmac_setup_axg(struct udevice *dev, struct eth_pdata *edata)
+{
+	struct dwmac_meson8b_plat *plat = dev_get_plat(dev);
+
+	switch (edata->phy_interface) {
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+		/* Set RGMII mode */
+		setbits_le32(plat->regs + ETH_REG_0, AXG_ETH_REG_0_PHY_INTF_RGMII |
+						     AXG_ETH_REG_0_TX_PHASE(1) |
+						     AXG_ETH_REG_0_TX_RATIO(4) |
+						     AXG_ETH_REG_0_PHY_CLK_EN |
+						     AXG_ETH_REG_0_CLK_EN);
+		break;
+
+	case PHY_INTERFACE_MODE_RMII:
+		/* Set RMII mode */
+		out_le32(plat->regs + ETH_REG_0, AXG_ETH_REG_0_PHY_INTF_RMII |
+						 AXG_ETH_REG_0_INVERT_RMII_CLK |
+						 AXG_ETH_REG_0_CLK_EN);
+		break;
+	default:
+		dev_err(dev, "Unsupported PHY mode\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int dwmac_setup_gx(struct udevice *dev, struct eth_pdata *edata)
+{
+	struct dwmac_meson8b_plat *plat = dev_get_plat(dev);
+
+	switch (edata->phy_interface) {
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+		/* Set RGMII mode */
+		setbits_le32(plat->regs + ETH_REG_0, GX_ETH_REG_0_PHY_INTF |
+						     GX_ETH_REG_0_TX_PHASE(1) |
+						     GX_ETH_REG_0_TX_RATIO(4) |
+						     GX_ETH_REG_0_PHY_CLK_EN |
+						     GX_ETH_REG_0_CLK_EN);
+
+		break;
+
+	case PHY_INTERFACE_MODE_RMII:
+		/* Set RMII mode */
+		out_le32(plat->regs + ETH_REG_0, GX_ETH_REG_0_INVERT_RMII_CLK |
+						 GX_ETH_REG_0_CLK_EN);
+
+		if (!IS_ENABLED(CONFIG_MESON_GXBB))
+			writel(0x10110181, plat->regs + ETH_REG_2);
+
+		break;
+	default:
+		dev_err(dev, "Unsupported PHY mode\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int dwmac_meson8b_probe(struct udevice *dev)
+{
+	struct dwmac_meson8b_plat *pdata = dev_get_plat(dev);
+	struct eth_pdata *edata = &pdata->dw_eth_pdata.eth_pdata;
+	int ret;
+
+	ret = pdata->dwmac_setup(dev, edata);
+	if (ret)
+		return ret;
+
+	return designware_eth_probe(dev);
+}
+
+static const struct udevice_id dwmac_meson8b_ids[] = {
+	{ .compatible = "amlogic,meson-gxbb-dwmac", .data = (ulong)dwmac_setup_gx },
+	{ .compatible = "amlogic,meson-axg-dwmac", .data = (ulong)dwmac_setup_axg },
+	{ }
+};
+
+U_BOOT_DRIVER(dwmac_meson8b) = {
+	.name		= "dwmac_meson8b",
+	.id		= UCLASS_ETH,
+	.of_match	= dwmac_meson8b_ids,
+	.of_to_plat = dwmac_meson8b_of_to_plat,
+	.probe		= dwmac_meson8b_probe,
+	.ops		= &designware_eth_ops,
+	.priv_auto	= sizeof(struct dw_eth_dev),
+	.plat_auto	= sizeof(struct dwmac_meson8b_plat),
+	.flags		= DM_FLAG_ALLOC_PRIV_DMA,
+};
diff --git a/drivers/net/mdio_mux_meson_g12a.c b/drivers/net/mdio_mux_meson_g12a.c
new file mode 100644
index 0000000..b520bf9
--- /dev/null
+++ b/drivers/net/mdio_mux_meson_g12a.c
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2021 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <miiphy.h>
+#include <asm/io.h>
+#include <linux/bitfield.h>
+
+#define ETH_PLL_STS		0x40
+#define ETH_PLL_CTL0		0x44
+#define  PLL_CTL0_LOCK_DIG	BIT(30)
+#define  PLL_CTL0_RST		BIT(29)
+#define  PLL_CTL0_EN		BIT(28)
+#define  PLL_CTL0_SEL		BIT(23)
+#define  PLL_CTL0_N		GENMASK(14, 10)
+#define  PLL_CTL0_M		GENMASK(8, 0)
+#define  PLL_LOCK_TIMEOUT	1000000
+#define  PLL_MUX_NUM_PARENT	2
+#define ETH_PLL_CTL1		0x48
+#define ETH_PLL_CTL2		0x4c
+#define ETH_PLL_CTL3		0x50
+#define ETH_PLL_CTL4		0x54
+#define ETH_PLL_CTL5		0x58
+#define ETH_PLL_CTL6		0x5c
+#define ETH_PLL_CTL7		0x60
+
+#define ETH_PHY_CNTL0		0x80
+#define   EPHY_G12A_ID		0x33010180
+#define ETH_PHY_CNTL1		0x84
+#define  PHY_CNTL1_ST_MODE	GENMASK(2, 0)
+#define  PHY_CNTL1_ST_PHYADD	GENMASK(7, 3)
+#define   EPHY_DFLT_ADD		8
+#define  PHY_CNTL1_MII_MODE	GENMASK(15, 14)
+#define   EPHY_MODE_RMII	0x1
+#define  PHY_CNTL1_CLK_EN	BIT(16)
+#define  PHY_CNTL1_CLKFREQ	BIT(17)
+#define  PHY_CNTL1_PHY_ENB	BIT(18)
+#define ETH_PHY_CNTL2		0x88
+#define  PHY_CNTL2_USE_INTERNAL	BIT(5)
+#define  PHY_CNTL2_SMI_SRC_MAC	BIT(6)
+#define  PHY_CNTL2_RX_CLK_EPHY	BIT(9)
+
+#define MESON_G12A_MDIO_EXTERNAL_ID 0
+#define MESON_G12A_MDIO_INTERNAL_ID 1
+
+struct mdio_mux_meson_g12a_priv {
+	struct udevice *chip;
+	phys_addr_t phys;
+};
+
+static int meson_g12a_ephy_pll_init(struct mdio_mux_meson_g12a_priv *priv)
+{
+	/* Fire up the PHY PLL */
+	writel(0x29c0040a, priv->phys + ETH_PLL_CTL0);
+	writel(0x927e0000, priv->phys + ETH_PLL_CTL1);
+	writel(0xac5f49e5, priv->phys + ETH_PLL_CTL2);
+	writel(0x00000000, priv->phys + ETH_PLL_CTL3);
+	writel(0x00000000, priv->phys + ETH_PLL_CTL4);
+	writel(0x20200000, priv->phys + ETH_PLL_CTL5);
+	writel(0x0000c002, priv->phys + ETH_PLL_CTL6);
+	writel(0x00000023, priv->phys + ETH_PLL_CTL7);
+	writel(0x39c0040a, priv->phys + ETH_PLL_CTL0);
+	writel(0x19c0040a, priv->phys + ETH_PLL_CTL0);
+
+	return 0;
+}
+
+static int meson_g12a_enable_internal_mdio(struct mdio_mux_meson_g12a_priv *priv)
+{
+	/* Initialize ephy control */
+	writel(EPHY_G12A_ID, priv->phys + ETH_PHY_CNTL0);
+	writel(FIELD_PREP(PHY_CNTL1_ST_MODE, 3) |
+	       FIELD_PREP(PHY_CNTL1_ST_PHYADD, EPHY_DFLT_ADD) |
+	       FIELD_PREP(PHY_CNTL1_MII_MODE, EPHY_MODE_RMII) |
+	       PHY_CNTL1_CLK_EN |
+	       PHY_CNTL1_CLKFREQ |
+	       PHY_CNTL1_PHY_ENB,
+	       priv->phys + ETH_PHY_CNTL1);
+	writel(PHY_CNTL2_USE_INTERNAL |
+	       PHY_CNTL2_SMI_SRC_MAC |
+	       PHY_CNTL2_RX_CLK_EPHY,
+	       priv->phys + ETH_PHY_CNTL2);
+
+	return 0;
+}
+
+static int meson_g12a_enable_external_mdio(struct mdio_mux_meson_g12a_priv *priv)
+{
+	/* Reset the mdio bus mux */
+	writel(0x0, priv->phys + ETH_PHY_CNTL2);
+
+	return 0;
+}
+
+static int mdio_mux_meson_g12a_select(struct udevice *mux, int cur, int sel)
+{
+	struct mdio_mux_meson_g12a_priv *priv = dev_get_priv(mux);
+
+	debug("%s: %x -> %x\n", __func__, (u32)cur, (u32)sel);
+
+	/* if last selection didn't change we're good to go */
+	if (cur == sel)
+		return 0;
+
+	switch (sel) {
+	case MESON_G12A_MDIO_EXTERNAL_ID:
+		return meson_g12a_enable_external_mdio(priv);
+	case MESON_G12A_MDIO_INTERNAL_ID:
+		return meson_g12a_enable_internal_mdio(priv);
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct mdio_mux_ops mdio_mux_meson_g12a_ops = {
+	.select = mdio_mux_meson_g12a_select,
+};
+
+static int mdio_mux_meson_g12a_probe(struct udevice *dev)
+{
+	struct mdio_mux_meson_g12a_priv *priv = dev_get_priv(dev);
+
+	priv->phys = dev_read_addr(dev);
+
+	meson_g12a_ephy_pll_init(priv);
+
+	return 0;
+}
+
+static const struct udevice_id mdio_mux_meson_g12a_ids[] = {
+	{ .compatible = "amlogic,g12a-mdio-mux" },
+	{ }
+};
+
+U_BOOT_DRIVER(mdio_mux_meson_g12a) = {
+	.name		= "mdio_mux_meson_g12a",
+	.id		= UCLASS_MDIO_MUX,
+	.of_match	= mdio_mux_meson_g12a_ids,
+	.probe		= mdio_mux_meson_g12a_probe,
+	.ops		= &mdio_mux_meson_g12a_ops,
+	.priv_auto	= sizeof(struct mdio_mux_meson_g12a_priv),
+};
diff --git a/drivers/net/mdio_mux_mmioreg.c b/drivers/net/mdio_mux_mmioreg.c
new file mode 100644
index 0000000..e1a23e4
--- /dev/null
+++ b/drivers/net/mdio_mux_mmioreg.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2021 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Based on linux/drivers/net/phy/mdio-mux-mmioreg.c :
+ *   Copyright 2012 Freescale Semiconductor, Inc.
+ */
+
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <miiphy.h>
+#include <linux/io.h>
+
+struct mdio_mux_mmioreg_priv {
+	struct udevice *chip;
+	phys_addr_t phys;
+	unsigned int iosize;
+	unsigned int mask;
+};
+
+static int mdio_mux_mmioreg_select(struct udevice *mux, int cur, int sel)
+{
+	struct mdio_mux_mmioreg_priv *priv = dev_get_priv(mux);
+
+	debug("%s: %x -> %x\n", __func__, (u32)cur, (u32)sel);
+
+	/* if last selection didn't change we're good to go */
+	if (cur == sel)
+		return 0;
+
+	switch (priv->iosize) {
+	case sizeof(u8): {
+		u8 x, y;
+
+		x = ioread8((void *)priv->phys);
+		y = (x & ~priv->mask) | (u32)sel;
+		if (x != y) {
+			iowrite8((x & ~priv->mask) | sel, (void *)priv->phys);
+			debug("%s: %02x -> %02x\n", __func__, x, y);
+		}
+
+		break;
+	}
+	case sizeof(u16): {
+		u16 x, y;
+
+		x = ioread16((void *)priv->phys);
+		y = (x & ~priv->mask) | (u32)sel;
+		if (x != y) {
+			iowrite16((x & ~priv->mask) | sel, (void *)priv->phys);
+			debug("%s: %04x -> %04x\n", __func__, x, y);
+		}
+
+		break;
+	}
+	case sizeof(u32): {
+		u32 x, y;
+
+		x = ioread32((void *)priv->phys);
+		y = (x & ~priv->mask) | (u32)sel;
+		if (x != y) {
+			iowrite32((x & ~priv->mask) | sel, (void *)priv->phys);
+			debug("%s: %08x -> %08x\n", __func__, x, y);
+		}
+
+		break;
+	}
+	}
+
+	return 0;
+}
+
+static const struct mdio_mux_ops mdio_mux_mmioreg_ops = {
+	.select = mdio_mux_mmioreg_select,
+};
+
+static int mdio_mux_mmioreg_probe(struct udevice *dev)
+{
+	struct mdio_mux_mmioreg_priv *priv = dev_get_priv(dev);
+	phys_addr_t reg_base, reg_size;
+	u32 reg_mask;
+	int err;
+
+	reg_base = ofnode_get_addr_size_index(dev_ofnode(dev), 0, &reg_size);
+	if (reg_base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	if (reg_size != sizeof(u8) &&
+	    reg_size != sizeof(u16) &&
+	    reg_size != sizeof(u32)) {
+		printf("%s: only 8/16/32-bit registers are supported\n", __func__);
+		return -EINVAL;
+	}
+
+	err = dev_read_u32(dev, "mux-mask", &reg_mask);
+	if (err) {
+		debug("%s: error reading mux-mask property\n", __func__);
+		return err;
+	}
+
+	if (reg_mask >= BIT(reg_size * 8)) {
+		printf("%s: mask doesn't fix in register width\n", __func__);
+		return -EINVAL;
+	}
+
+	priv->phys = reg_base;
+	priv->iosize = reg_size;
+	priv->mask = reg_mask;
+
+	debug("%s: %llx@%lld / %x\n", __func__, reg_base, reg_size, reg_mask);
+
+	return 0;
+}
+
+static const struct udevice_id mdio_mux_mmioreg_ids[] = {
+	{ .compatible = "mdio-mux-mmioreg" },
+	{ }
+};
+
+U_BOOT_DRIVER(mdio_mux_mmioreg) = {
+	.name		= "mdio_mux_mmioreg",
+	.id		= UCLASS_MDIO_MUX,
+	.of_match	= mdio_mux_mmioreg_ids,
+	.probe		= mdio_mux_mmioreg_probe,
+	.ops		= &mdio_mux_mmioreg_ops,
+	.priv_auto	= sizeof(struct mdio_mux_mmioreg_priv),
+};
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index baf06a2..ff59982 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -454,14 +454,6 @@
 	    priv->int_pcs) {
 		nwconfig |= ZYNQ_GEM_NWCFG_SGMII_ENBL |
 			    ZYNQ_GEM_NWCFG_PCS_SEL;
-#ifdef CONFIG_ARM64
-	if (priv->phydev->phy_id != PHY_FIXED_ID)
-		writel(readl(&regs->pcscntrl) | ZYNQ_GEM_PCS_CTL_ANEG_ENBL,
-		       &regs->pcscntrl);
-	else
-		writel(readl(&regs->pcscntrl) & ~ZYNQ_GEM_PCS_CTL_ANEG_ENBL,
-		       &regs->pcscntrl);
-#endif
 	}
 
 	switch (priv->phydev->speed) {
@@ -480,6 +472,23 @@
 		break;
 	}
 
+#ifdef CONFIG_ARM64
+	if (priv->interface == PHY_INTERFACE_MODE_SGMII &&
+	    priv->int_pcs) {
+		/*
+		 * Disable AN for fixed link configuration, enable otherwise.
+		 * Must be written after PCS_SEL is set in nwconfig,
+		 * otherwise writes will not take effect.
+		 */
+		if (priv->phydev->phy_id != PHY_FIXED_ID)
+			writel(readl(&regs->pcscntrl) | ZYNQ_GEM_PCS_CTL_ANEG_ENBL,
+			       &regs->pcscntrl);
+		else
+			writel(readl(&regs->pcscntrl) & ~ZYNQ_GEM_PCS_CTL_ANEG_ENBL,
+			       &regs->pcscntrl);
+	}
+#endif
+
 	ret = clk_set_rate(&priv->tx_clk, clk_rate);
 	if (IS_ERR_VALUE(ret)) {
 		dev_err(dev, "failed to set tx clock rate\n");
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
index a14a4db..7bad4c8 100644
--- a/drivers/pci/pci_rom.c
+++ b/drivers/pci/pci_rom.c
@@ -349,13 +349,10 @@
 	}
 
 	/* Use double buffering if enabled */
-	if (IS_ENABLED(CONFIG_VIDEO_COPY)) {
-		if (!plat->base)
-			return log_msg_ret("copy", -ENFILE);
+	if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->base)
 		plat->copy_base = vesa->phys_base_ptr;
-	} else {
+	else
 		plat->base = vesa->phys_base_ptr;
-	}
 	log_debug("base = %lx, copy_base = %lx\n", plat->base, plat->copy_base);
 	plat->size = vesa->bytes_per_scanline * vesa->y_resolution;
 
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7629.c b/drivers/pinctrl/mediatek/pinctrl-mt7629.c
index 7ce64fd..5d4bec2 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt7629.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt7629.c
@@ -201,6 +201,10 @@
 static int mt7629_wf5g_led_pins[] = { 18, };
 static int mt7629_wf5g_led_funcs[] = { 1, };
 
+/* LED for EPHY used as JTAG */
+static int mt7629_ephy_leds_jtag_pins[] = { 12, 13, 14, 15, 16, };
+static int mt7629_ephy_leds_jtag_funcs[] = { 7, 7, 7, 7, 7, };
+
 /* Watchdog */
 static int mt7629_watchdog_pins[] = { 11, };
 static int mt7629_watchdog_funcs[] = { 1, };
@@ -297,6 +301,7 @@
 	PINCTRL_PIN_GROUP("ephy_led2", mt7629_ephy_led2),
 	PINCTRL_PIN_GROUP("ephy_led3", mt7629_ephy_led3),
 	PINCTRL_PIN_GROUP("ephy_led4", mt7629_ephy_led4),
+	PINCTRL_PIN_GROUP("ephy_leds_jtag", mt7629_ephy_leds_jtag),
 	PINCTRL_PIN_GROUP("wf2g_led", mt7629_wf2g_led),
 	PINCTRL_PIN_GROUP("wf5g_led", mt7629_wf5g_led),
 	PINCTRL_PIN_GROUP("watchdog", mt7629_watchdog),
@@ -364,6 +369,7 @@
 static const char *const mt7629_wdt_groups[] = { "watchdog", };
 static const char *const mt7629_wifi_groups[] = { "wf0_5g", "wf0_2g", };
 static const char *const mt7629_flash_groups[] = { "snfi", "spi_nor" };
+static const char *const mt7629_jtag_groups[] = { "ephy_leds_jtag" };
 
 static const struct mtk_function_desc mt7629_functions[] = {
 	{"eth",	mt7629_ethernet_groups, ARRAY_SIZE(mt7629_ethernet_groups)},
@@ -376,6 +382,7 @@
 	{"watchdog", mt7629_wdt_groups, ARRAY_SIZE(mt7629_wdt_groups)},
 	{"wifi", mt7629_wifi_groups, ARRAY_SIZE(mt7629_wifi_groups)},
 	{"flash", mt7629_flash_groups, ARRAY_SIZE(mt7629_flash_groups)},
+	{"jtag", mt7629_jtag_groups, ARRAY_SIZE(mt7629_jtag_groups)},
 };
 
 static struct mtk_pinctrl_soc mt7629_data = {
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index 4dd3f73..3bd23be 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -219,7 +219,7 @@
 {
 	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
 
-	if (!priv->soc->grps[selector].name)
+	if (!priv->soc->pins[selector].name)
 		return mtk_pinctrl_dummy_name;
 
 	return priv->soc->pins[selector].name;
@@ -232,6 +232,19 @@
 	return priv->soc->npins;
 }
 
+static int mtk_get_pin_muxing(struct udevice *dev, unsigned int selector,
+			      char *buf, int size)
+{
+	int val, err;
+
+	err = mtk_hw_get_value(dev, selector, PINCTRL_PIN_REG_MODE, &val);
+	if (err)
+		return err;
+
+	snprintf(buf, size, "Aux Func.%d", val);
+	return 0;
+}
+
 static const char *mtk_get_group_name(struct udevice *dev,
 				      unsigned int selector)
 {
@@ -512,6 +525,7 @@
 const struct pinctrl_ops mtk_pinctrl_ops = {
 	.get_pins_count = mtk_get_pins_count,
 	.get_pin_name = mtk_get_pin_name,
+	.get_pin_muxing = mtk_get_pin_muxing,
 	.get_groups_count = mtk_get_groups_count,
 	.get_group_name = mtk_get_group_name,
 	.get_functions_count = mtk_get_functions_count,
@@ -526,6 +540,8 @@
 	.set_state = pinctrl_generic_set_state,
 };
 
+#if CONFIG_IS_ENABLED(DM_GPIO) || \
+    (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_GPIO_SUPPORT))
 static int mtk_gpio_get(struct udevice *dev, unsigned int off)
 {
 	int val, err;
@@ -633,12 +649,13 @@
 
 	return 0;
 }
+#endif
 
 int mtk_pinctrl_common_probe(struct udevice *dev,
 			     struct mtk_pinctrl_soc *soc)
 {
 	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
-	int ret;
+	int ret = 0;
 
 	priv->base = dev_read_addr_ptr(dev);
 	if (!priv->base)
@@ -646,9 +663,10 @@
 
 	priv->soc = soc;
 
+#if CONFIG_IS_ENABLED(DM_GPIO) || \
+    (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_GPIO_SUPPORT))
 	ret = mtk_gpiochip_register(dev);
-	if (ret)
-		return ret;
+#endif
 
-	return 0;
+	return ret;
 }
diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
index b7ae2f6..26fb5d6 100644
--- a/drivers/pinctrl/pinctrl-at91-pio4.c
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -25,6 +25,7 @@
 
 struct atmel_pio4_plat {
 	struct atmel_pio4_port *reg_base;
+	unsigned int slew_rate_support;
 };
 
 static const struct pinconf_param conf_params[] = {
@@ -36,9 +37,11 @@
 	{ "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
 	{ "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
 	{ "atmel,drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
+	{ "slew-rate", PIN_CONFIG_SLEW_RATE, 0},
 };
 
-static u32 atmel_pinctrl_get_pinconf(struct udevice *config)
+static u32 atmel_pinctrl_get_pinconf(struct udevice *config,
+				     struct atmel_pio4_plat *plat)
 {
 	const struct pinconf_param *params;
 	u32 param, arg, conf = 0;
@@ -53,6 +56,10 @@
 		param = params->param;
 		arg = params->default_value;
 
+		/* Keep slew rate enabled by default. */
+		if (plat->slew_rate_support)
+			conf |= ATMEL_PIO_SR;
+
 		switch (param) {
 		case PIN_CONFIG_BIAS_DISABLE:
 			conf &= (~ATMEL_PIO_PUEN_MASK);
@@ -91,6 +98,15 @@
 			conf |= (val << ATMEL_PIO_DRVSTR_OFFSET)
 				& ATMEL_PIO_DRVSTR_MASK;
 			break;
+		case PIN_CONFIG_SLEW_RATE:
+			if (!plat->slew_rate_support)
+				break;
+
+			dev_read_u32(config, params->property, &val);
+			/* And disable it if requested. */
+			if (val == 0)
+				conf &= ~ATMEL_PIO_SR;
+			break;
 		default:
 			printf("%s: Unsupported configuration parameter: %u\n",
 			       __func__, param);
@@ -116,6 +132,7 @@
 
 static int atmel_pinctrl_set_state(struct udevice *dev, struct udevice *config)
 {
+	struct atmel_pio4_plat *plat = dev_get_plat(dev);
 	struct atmel_pio4_port *bank_base;
 	const void *blob = gd->fdt_blob;
 	int node = dev_of_offset(config);
@@ -124,7 +141,7 @@
 	u32 i, conf;
 	int count;
 
-	conf = atmel_pinctrl_get_pinconf(config);
+	conf = atmel_pinctrl_get_pinconf(config, plat);
 
 	count = fdtdec_get_int_array_count(blob, node, "pinmux",
 					   cells, ARRAY_SIZE(cells));
@@ -164,6 +181,7 @@
 static int atmel_pinctrl_probe(struct udevice *dev)
 {
 	struct atmel_pio4_plat *plat = dev_get_plat(dev);
+	ulong priv = dev_get_driver_data(dev);
 	fdt_addr_t addr_base;
 
 	dev = dev_get_parent(dev);
@@ -172,13 +190,15 @@
 		return -EINVAL;
 
 	plat->reg_base = (struct atmel_pio4_port *)addr_base;
+	plat->slew_rate_support = priv;
 
 	return 0;
 }
 
 static const struct udevice_id atmel_pinctrl_match[] = {
 	{ .compatible = "atmel,sama5d2-pinctrl" },
-	{ .compatible = "microchip,sama7g5-pinctrl" },
+	{ .compatible = "microchip,sama7g5-pinctrl",
+	  .data = (ulong)1, },
 	{}
 };
 
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
index 1a8d0a3..fe7a59d 100644
--- a/drivers/pinctrl/pinctrl-stmfx.c
+++ b/drivers/pinctrl/pinctrl-stmfx.c
@@ -163,12 +163,14 @@
 	return stmfx_write_reg(dev, STMFX_REG_GPIO_DIR, offset, 1);
 }
 
-static int stmfx_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
-				    ulong flags)
+static int stmfx_gpio_set_flags(struct udevice *dev, unsigned int offset,
+				ulong flags)
 {
 	int ret = -ENOTSUPP;
 
 	if (flags & GPIOD_IS_OUT) {
+		bool value = flags & GPIOD_IS_OUT_ACTIVE;
+
 		if (flags & GPIOD_OPEN_SOURCE)
 			return -ENOTSUPP;
 		if (flags & GPIOD_OPEN_DRAIN)
@@ -177,8 +179,7 @@
 			ret = stmfx_conf_set_type(dev, offset, 1);
 		if (ret)
 			return ret;
-		ret = stmfx_gpio_direction_output(dev, offset,
-						  GPIOD_FLAGS_OUTPUT(flags));
+		ret = stmfx_gpio_direction_output(dev, offset, value);
 	} else if (flags & GPIOD_IS_IN) {
 		ret = stmfx_gpio_direction_input(dev, offset);
 		if (ret)
@@ -199,8 +200,8 @@
 	return ret;
 }
 
-static int stmfx_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
-				    ulong *flags)
+static int stmfx_gpio_get_flags(struct udevice *dev, unsigned int offset,
+				ulong *flagsp)
 {
 	ulong dir_flags = 0;
 	int ret;
@@ -233,7 +234,7 @@
 				dir_flags |= GPIOD_PULL_DOWN;
 		}
 	}
-	*flags = dir_flags;
+	*flagsp = dir_flags;
 
 	return 0;
 }
@@ -266,8 +267,8 @@
 	.get_function = stmfx_gpio_get_function,
 	.direction_input = stmfx_gpio_direction_input,
 	.direction_output = stmfx_gpio_direction_output,
-	.set_dir_flags = stmfx_gpio_set_dir_flags,
-	.get_dir_flags = stmfx_gpio_get_dir_flags,
+	.set_flags = stmfx_gpio_set_flags,
+	.get_flags = stmfx_gpio_get_flags,
 };
 
 U_BOOT_DRIVER(stmfx_gpio) = {
diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c
index b0f30aa..6e68e52 100644
--- a/drivers/pinctrl/pinctrl-uclass.c
+++ b/drivers/pinctrl/pinctrl-uclass.c
@@ -235,8 +235,9 @@
 		return ret;
 
 	ops = pinctrl_get_ops(pctldev);
-	if (!ops || !ops->gpio_request_enable)
-		return -ENOTSUPP;
+	assert(ops);
+	if (!ops->gpio_request_enable)
+		return -ENOSYS;
 
 	return ops->gpio_request_enable(pctldev, pin_selector);
 }
@@ -261,8 +262,9 @@
 		return ret;
 
 	ops = pinctrl_get_ops(pctldev);
-	if (!ops || !ops->gpio_disable_free)
-		return -ENOTSUPP;
+	assert(ops);
+	if (!ops->gpio_disable_free)
+		return -ENOSYS;
 
 	return ops->gpio_disable_free(pctldev, pin_selector);
 }
diff --git a/drivers/pinctrl/renesas/Kconfig b/drivers/pinctrl/renesas/Kconfig
index d2be4c8..8fb9cba 100644
--- a/drivers/pinctrl/renesas/Kconfig
+++ b/drivers/pinctrl/renesas/Kconfig
@@ -77,6 +77,16 @@
           the GPIO definitions and pin control functions for each available
           multiplex function.
 
+config PINCTRL_PFC_R8A774C0
+        bool "Renesas RZ/G2 R8A774C0 pin control driver"
+        depends on PINCTRL_PFC
+        help
+          Support pin multiplexing control on Renesas RZ/G2E R8A774C0 SoCs.
+
+          The driver is controlled by a device tree node which contains both
+          the GPIO definitions and pin control functions for each available
+          multiplex function.
+
 config PINCTRL_PFC_R8A774E1
         bool "Renesas RZ/G2 R8A774E1 pin control driver"
         depends on PINCTRL_PFC
diff --git a/drivers/pinctrl/renesas/Makefile b/drivers/pinctrl/renesas/Makefile
index 1d00752..0e2ac3c 100644
--- a/drivers/pinctrl/renesas/Makefile
+++ b/drivers/pinctrl/renesas/Makefile
@@ -1,6 +1,7 @@
 obj-$(CONFIG_PINCTRL_PFC) += pfc.o
 obj-$(CONFIG_PINCTRL_PFC_R8A774A1) += pfc-r8a7796.o
 obj-$(CONFIG_PINCTRL_PFC_R8A774B1) += pfc-r8a77965.o
+obj-$(CONFIG_PINCTRL_PFC_R8A774C0) += pfc-r8a77990.o
 obj-$(CONFIG_PINCTRL_PFC_R8A774E1) += pfc-r8a7795.o
 obj-$(CONFIG_PINCTRL_PFC_R8A7790) += pfc-r8a7790.o
 obj-$(CONFIG_PINCTRL_PFC_R8A7791) += pfc-r8a7791.o
diff --git a/drivers/pinctrl/renesas/pfc-r8a77990.c b/drivers/pinctrl/renesas/pfc-r8a77990.c
index b13fc0b..572b041 100644
--- a/drivers/pinctrl/renesas/pfc-r8a77990.c
+++ b/drivers/pinctrl/renesas/pfc-r8a77990.c
@@ -1603,6 +1603,7 @@
 	CANFD1_TX_MARK, CANFD1_RX_MARK,
 };
 
+#ifdef CONFIG_PINCTRL_PFC_R8A77990
 /* - DRIF0 --------------------------------------------------------------- */
 static const unsigned int drif0_ctrl_a_pins[] = {
 	/* CLK, SYNC */
@@ -1795,6 +1796,7 @@
 static const unsigned int drif3_data1_b_mux[] = {
 	RIF3_D1_B_MARK,
 };
+#endif /* CONFIG_PINCTRL_PFC_R8A77990 */
 
 /* - DU --------------------------------------------------------------------- */
 static const unsigned int du_rgb666_pins[] = {
@@ -2818,6 +2820,57 @@
 	PWM6_B_MARK,
 };
 
+/* - QSPI0 ------------------------------------------------------------------ */
+static const unsigned int qspi0_ctrl_pins[] = {
+	/* QSPI0_SPCLK, QSPI0_SSL */
+	RCAR_GP_PIN(2, 0), RCAR_GP_PIN(2, 5),
+};
+static const unsigned int qspi0_ctrl_mux[] = {
+	QSPI0_SPCLK_MARK, QSPI0_SSL_MARK,
+};
+static const unsigned int qspi0_data2_pins[] = {
+	/* QSPI0_MOSI_IO0, QSPI0_MISO_IO1 */
+	RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 2),
+};
+static const unsigned int qspi0_data2_mux[] = {
+	QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK,
+};
+static const unsigned int qspi0_data4_pins[] = {
+	/* QSPI0_MOSI_IO0, QSPI0_MISO_IO1 */
+	RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 2),
+	/* QSPI0_IO2, QSPI0_IO3 */
+	RCAR_GP_PIN(2, 3), RCAR_GP_PIN(2, 4),
+};
+static const unsigned int qspi0_data4_mux[] = {
+	QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK,
+	QSPI0_IO2_MARK, QSPI0_IO3_MARK,
+};
+/* - QSPI1 ------------------------------------------------------------------ */
+static const unsigned int qspi1_ctrl_pins[] = {
+	/* QSPI1_SPCLK, QSPI1_SSL */
+	RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 11),
+};
+static const unsigned int qspi1_ctrl_mux[] = {
+	QSPI1_SPCLK_MARK, QSPI1_SSL_MARK,
+};
+static const unsigned int qspi1_data2_pins[] = {
+	/* QSPI1_MOSI_IO0, QSPI1_MISO_IO1 */
+	RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 8),
+};
+static const unsigned int qspi1_data2_mux[] = {
+	QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK,
+};
+static const unsigned int qspi1_data4_pins[] = {
+	/* QSPI1_MOSI_IO0, QSPI1_MISO_IO1 */
+	RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 8),
+	/* QSPI1_IO2, QSPI1_IO3 */
+	RCAR_GP_PIN(2, 9), RCAR_GP_PIN(2, 10),
+};
+static const unsigned int qspi1_data4_mux[] = {
+	QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK,
+	QSPI1_IO2_MARK, QSPI1_IO3_MARK,
+};
+
 /* - SCIF0 ------------------------------------------------------------------ */
 static const unsigned int scif0_data_a_pins[] = {
 	/* RX, TX */
@@ -3770,8 +3823,10 @@
 };
 
 static const struct {
-	struct sh_pfc_pin_group common[247];
+	struct sh_pfc_pin_group common[253];
+#ifdef CONFIG_PINCTRL_PFC_R8A77990
 	struct sh_pfc_pin_group automotive[21];
+#endif
 } pinmux_groups = {
 	.common = {
 		SH_PFC_PIN_GROUP(audio_clk_a),
@@ -3916,6 +3971,12 @@
 		SH_PFC_PIN_GROUP(pwm5_b),
 		SH_PFC_PIN_GROUP(pwm6_a),
 		SH_PFC_PIN_GROUP(pwm6_b),
+		SH_PFC_PIN_GROUP(qspi0_ctrl),
+		SH_PFC_PIN_GROUP(qspi0_data2),
+		SH_PFC_PIN_GROUP(qspi0_data4),
+		SH_PFC_PIN_GROUP(qspi1_ctrl),
+		SH_PFC_PIN_GROUP(qspi1_data2),
+		SH_PFC_PIN_GROUP(qspi1_data4),
 		SH_PFC_PIN_GROUP(scif0_data_a),
 		SH_PFC_PIN_GROUP(scif0_clk_a),
 		SH_PFC_PIN_GROUP(scif0_ctrl_a),
@@ -4022,6 +4083,7 @@
 		SH_PFC_PIN_GROUP(vin5_clk_a),
 		SH_PFC_PIN_GROUP(vin5_clk_b),
 	},
+#ifdef CONFIG_PINCTRL_PFC_R8A77990
 	.automotive = {
 		SH_PFC_PIN_GROUP(drif0_ctrl_a),
 		SH_PFC_PIN_GROUP(drif0_data0_a),
@@ -4045,6 +4107,7 @@
 		SH_PFC_PIN_GROUP(drif3_data0_b),
 		SH_PFC_PIN_GROUP(drif3_data1_b),
 	}
+#endif /* CONFIG_PINCTRL_PFC_R8A77990 */
 };
 
 static const char * const audio_clk_groups[] = {
@@ -4098,6 +4161,7 @@
 	"canfd1_data",
 };
 
+#ifdef CONFIG_PINCTRL_PFC_R8A77990
 static const char * const drif0_groups[] = {
 	"drif0_ctrl_a",
 	"drif0_data0_a",
@@ -4130,6 +4194,7 @@
 	"drif3_data0_b",
 	"drif3_data1_b",
 };
+#endif /* CONFIG_PINCTRL_PFC_R8A77990 */
 
 static const char * const du_groups[] = {
 	"du_rgb666",
@@ -4315,6 +4380,18 @@
 	"pwm6_b",
 };
 
+static const char * const qspi0_groups[] = {
+	"qspi0_ctrl",
+	"qspi0_data2",
+	"qspi0_data4",
+};
+
+static const char * const qspi1_groups[] = {
+	"qspi1_ctrl",
+	"qspi1_data2",
+	"qspi1_data4",
+};
+
 static const char * const scif0_groups[] = {
 	"scif0_data_a",
 	"scif0_clk_a",
@@ -4469,8 +4546,10 @@
 };
 
 static const struct {
-	struct sh_pfc_function common[47];
+	struct sh_pfc_function common[49];
+#ifdef CONFIG_PINCTRL_PFC_R8A77990
 	struct sh_pfc_function automotive[4];
+#endif
 } pinmux_functions = {
 	.common = {
 		SH_PFC_FUNCTION(audio_clk),
@@ -4504,6 +4583,8 @@
 		SH_PFC_FUNCTION(pwm4),
 		SH_PFC_FUNCTION(pwm5),
 		SH_PFC_FUNCTION(pwm6),
+		SH_PFC_FUNCTION(qspi0),
+		SH_PFC_FUNCTION(qspi1),
 		SH_PFC_FUNCTION(scif0),
 		SH_PFC_FUNCTION(scif1),
 		SH_PFC_FUNCTION(scif2),
@@ -4521,12 +4602,14 @@
 		SH_PFC_FUNCTION(vin4),
 		SH_PFC_FUNCTION(vin5),
 	},
+#ifdef CONFIG_PINCTRL_PFC_R8A77990
 	.automotive = {
 		SH_PFC_FUNCTION(drif0),
 		SH_PFC_FUNCTION(drif1),
 		SH_PFC_FUNCTION(drif2),
 		SH_PFC_FUNCTION(drif3),
 	}
+#endif /* CONFIG_PINCTRL_PFC_R8A77990 */
 };
 
 static const struct pinmux_cfg_reg pinmux_config_regs[] = {
diff --git a/drivers/pinctrl/renesas/pfc.c b/drivers/pinctrl/renesas/pfc.c
index 6ff9484..07fcc3d 100644
--- a/drivers/pinctrl/renesas/pfc.c
+++ b/drivers/pinctrl/renesas/pfc.c
@@ -34,6 +34,7 @@
 	SH_PFC_R8A7796,
 	SH_PFC_R8A774A1,
 	SH_PFC_R8A774B1,
+	SH_PFC_R8A774C0,
 	SH_PFC_R8A774E1,
 	SH_PFC_R8A77965,
 	SH_PFC_R8A77970,
@@ -927,6 +928,10 @@
 	if (model == SH_PFC_R8A774B1)
 		priv->pfc.info = &r8a774b1_pinmux_info;
 #endif
+#ifdef CONFIG_PINCTRL_PFC_R8A774C0
+	if (model == SH_PFC_R8A774C0)
+		priv->pfc.info = &r8a774c0_pinmux_info;
+#endif
 #ifdef CONFIG_PINCTRL_PFC_R8A774E1
 	if (model == SH_PFC_R8A774E1)
 		priv->pfc.info = &r8a774e1_pinmux_info;
@@ -1014,6 +1019,12 @@
 		.data = SH_PFC_R8A774B1,
 	},
 #endif
+#ifdef CONFIG_PINCTRL_PFC_R8A774C0
+	{
+		.compatible = "renesas,pfc-r8a774c0",
+		.data = SH_PFC_R8A774C0,
+	},
+#endif
 #ifdef CONFIG_PINCTRL_PFC_R8A774E1
 	{
 		.compatible = "renesas,pfc-r8a774e1",
diff --git a/drivers/pinctrl/renesas/sh_pfc.h b/drivers/pinctrl/renesas/sh_pfc.h
index 22cc860..f563916 100644
--- a/drivers/pinctrl/renesas/sh_pfc.h
+++ b/drivers/pinctrl/renesas/sh_pfc.h
@@ -295,6 +295,7 @@
 
 extern const struct sh_pfc_soc_info r8a774a1_pinmux_info;
 extern const struct sh_pfc_soc_info r8a774b1_pinmux_info;
+extern const struct sh_pfc_soc_info r8a774c0_pinmux_info;
 extern const struct sh_pfc_soc_info r8a774e1_pinmux_info;
 extern const struct sh_pfc_soc_info r8a7790_pinmux_info;
 extern const struct sh_pfc_soc_info r8a7791_pinmux_info;
diff --git a/drivers/power/pmic/pmic_pca9450.c b/drivers/power/pmic/pmic_pca9450.c
index d4f2742..8c4d0a9 100644
--- a/drivers/power/pmic/pmic_pca9450.c
+++ b/drivers/power/pmic/pmic_pca9450.c
@@ -11,7 +11,7 @@
 
 static const char pca9450_name[] = "PCA9450";
 
-int power_pca9450_init(unsigned char bus)
+int power_pca9450_init(unsigned char bus, unsigned char addr)
 {
 	struct pmic *p = pmic_alloc();
 
@@ -23,7 +23,7 @@
 	p->name = pca9450_name;
 	p->interface = PMIC_I2C;
 	p->number_of_regs = PCA9450_REG_NUM;
-	p->hw.i2c.addr = 0x25;
+	p->hw.i2c.addr = addr;
 	p->hw.i2c.tx_num = 1;
 	p->bus = bus;
 
diff --git a/drivers/ram/sifive/Kconfig b/drivers/ram/sifive/Kconfig
index 6aca22a..08de692 100644
--- a/drivers/ram/sifive/Kconfig
+++ b/drivers/ram/sifive/Kconfig
@@ -8,6 +8,6 @@
 config SIFIVE_FU540_DDR
 	bool "SiFive FU540 DDR driver"
 	depends on RAM_SIFIVE
-	default y if TARGET_SIFIVE_FU540
+	default y if TARGET_SIFIVE_UNLEASHED
 	help
 	  This enables DDR support for the platforms based on SiFive FU540 SoC.
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index f5b3f88..019565f 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -166,7 +166,7 @@
 
 config RESET_SIFIVE
 	bool "Reset Driver for SiFive SoC's"
-	depends on DM_RESET && CLK_SIFIVE_FU540_PRCI && TARGET_SIFIVE_FU540
+	depends on DM_RESET && CLK_SIFIVE_FU540_PRCI && TARGET_SIFIVE_UNLEASHED
 	default y
 	help
 	  PRCI module within SiFive SoC's provides mechanism to reset
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index aa6d901..dafba35 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -38,6 +38,13 @@
 	   Some real-time clocks support the output of 32kHz square waves (such as ds3231),
 	   the config symbol choose Real Time Clock device 32Khz output feature.
 
+config RTC_ARMADA38X
+	bool "Enable Armada 38x Marvell SoC RTC"
+	depends on DM_RTC && ARCH_MVEBU
+	help
+	  This adds support for the in-chip RTC that can be found in the
+	  Armada 38x Marvell's SoC devices.
+
 config RTC_PCF2127
 	bool "Enable PCF2127 driver"
 	depends on DM_RTC
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 6a45a9c..15609e7 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -8,6 +8,7 @@
 
 obj-$(CONFIG_RTC_AT91SAM9_RTT) += at91sam9_rtt.o
 obj-y += rtc-lib.o
+obj-$(CONFIG_RTC_ARMADA38X) += armada38x.o
 obj-$(CONFIG_RTC_DAVINCI) += davinci.o
 obj-$(CONFIG_RTC_DS1302) += ds1302.o
 obj-$(CONFIG_RTC_DS1306) += ds1306.o
diff --git a/drivers/rtc/armada38x.c b/drivers/rtc/armada38x.c
new file mode 100644
index 0000000..2d264ac
--- /dev/null
+++ b/drivers/rtc/armada38x.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * RTC driver for the Armada 38x Marvell SoCs
+ *
+ * Copyright (C) 2021 Marek Behun <marek.behun@nic.cz>
+ *
+ * Based on Linux' driver by Gregory Clement and Marvell
+ */
+
+#include <asm/io.h>
+#include <dm.h>
+#include <linux/delay.h>
+#include <rtc.h>
+
+#define RTC_STATUS			0x0
+#define RTC_TIME			0xC
+#define RTC_CONF_TEST			0x1C
+
+/* Armada38x SoC registers  */
+#define RTC_38X_BRIDGE_TIMING_CTL	0x0
+#define RTC_38X_PERIOD_OFFS		0
+#define RTC_38X_PERIOD_MASK		(0x3FF << RTC_38X_PERIOD_OFFS)
+#define RTC_38X_READ_DELAY_OFFS		26
+#define RTC_38X_READ_DELAY_MASK		(0x1F << RTC_38X_READ_DELAY_OFFS)
+
+#define SAMPLE_NR			100
+
+struct armada38x_rtc {
+	void __iomem *regs;
+	void __iomem *regs_soc;
+};
+
+/*
+ * According to Erratum RES-3124064 we have to do some configuration in MBUS.
+ * To read an RTC register we need to read it 100 times and return the most
+ * frequent value.
+ * To write an RTC register we need to write 2x zero into STATUS register,
+ * followed by the proper write. Linux adds an 5 us delay after this, so we do
+ * it here as well.
+ */
+static void update_38x_mbus_timing_params(struct armada38x_rtc *rtc)
+{
+	u32 reg;
+
+	reg = readl(rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL);
+	reg &= ~RTC_38X_PERIOD_MASK;
+	reg |= 0x3FF << RTC_38X_PERIOD_OFFS; /* Maximum value */
+	reg &= ~RTC_38X_READ_DELAY_MASK;
+	reg |= 0x1F << RTC_38X_READ_DELAY_OFFS; /* Maximum value */
+	writel(reg, rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL);
+}
+
+static void armada38x_rtc_write(u32 val, struct armada38x_rtc *rtc, u8 reg)
+{
+	writel(0, rtc->regs + RTC_STATUS);
+	writel(0, rtc->regs + RTC_STATUS);
+	writel(val, rtc->regs + reg);
+	udelay(5);
+}
+
+static u32 armada38x_rtc_read(struct armada38x_rtc *rtc, u8 reg)
+{
+	u8 counts[SAMPLE_NR], max_idx;
+	u32 samples[SAMPLE_NR], max;
+	int i, j, last;
+
+	for (i = 0, last = 0; i < SAMPLE_NR; ++i) {
+		u32 sample = readl(rtc->regs + reg);
+
+		/* find if this value was already read */
+		for (j = 0; j < last; ++j) {
+			if (samples[j] == sample)
+				break;
+		}
+
+		if (j < last) {
+			/* if yes, increment count */
+			++counts[j];
+		} else {
+			/* if not, add */
+			samples[last] = sample;
+			counts[last] = 1;
+			++last;
+		}
+	}
+
+	/* finally find the sample that was read the most */
+	max = 0;
+	max_idx = 0;
+
+	for (i = 0; i < last; ++i) {
+		if (counts[i] > max) {
+			max = counts[i];
+			max_idx = i;
+		}
+	}
+
+	return samples[max_idx];
+}
+
+static int armada38x_rtc_get(struct udevice *dev, struct rtc_time *tm)
+{
+	struct armada38x_rtc *rtc = dev_get_priv(dev);
+	u32 time;
+
+	time = armada38x_rtc_read(rtc, RTC_TIME);
+
+	rtc_to_tm(time, tm);
+
+	return 0;
+}
+
+static int armada38x_rtc_reset(struct udevice *dev)
+{
+	struct armada38x_rtc *rtc = dev_get_priv(dev);
+	u32 reg;
+
+	reg = armada38x_rtc_read(rtc, RTC_CONF_TEST);
+
+	if (reg & 0xff) {
+		armada38x_rtc_write(0, rtc, RTC_CONF_TEST);
+		mdelay(500);
+		armada38x_rtc_write(0, rtc, RTC_TIME);
+		armada38x_rtc_write(BIT(0) | BIT(1), 0, RTC_STATUS);
+	}
+
+	return 0;
+}
+
+static int armada38x_rtc_set(struct udevice *dev, const struct rtc_time *tm)
+{
+	struct armada38x_rtc *rtc = dev_get_priv(dev);
+	unsigned long time;
+
+	time = rtc_mktime(tm);
+
+	if (time > U32_MAX)
+		printf("%s: requested time to set will overflow\n", dev->name);
+
+	armada38x_rtc_reset(dev);
+	armada38x_rtc_write(time, rtc, RTC_TIME);
+
+	return 0;
+}
+
+static int armada38x_probe(struct udevice *dev)
+{
+	struct armada38x_rtc *rtc = dev_get_priv(dev);
+
+	rtc->regs = dev_remap_addr_name(dev, "rtc");
+	if (!rtc->regs)
+		goto err;
+
+	rtc->regs_soc = dev_remap_addr_name(dev, "rtc-soc");
+	if (!rtc->regs_soc)
+		goto err;
+
+	update_38x_mbus_timing_params(rtc);
+
+	return 0;
+err:
+	printf("%s: io address missing\n", dev->name);
+	return -ENODEV;
+}
+
+static const struct rtc_ops armada38x_rtc_ops = {
+	.get = armada38x_rtc_get,
+	.set = armada38x_rtc_set,
+	.reset = armada38x_rtc_reset,
+};
+
+static const struct udevice_id armada38x_rtc_ids[] = {
+	{ .compatible = "marvell,armada-380-rtc", .data = 0 },
+	{ }
+};
+
+U_BOOT_DRIVER(rtc_armada38x) = {
+	.name		= "rtc-armada38x",
+	.id		= UCLASS_RTC,
+	.of_match	= armada38x_rtc_ids,
+	.probe		= armada38x_probe,
+	.priv_auto	= sizeof(struct armada38x_rtc),
+	.ops		= &armada38x_rtc_ops,
+};
diff --git a/drivers/rtc/i2c_rtc_emul.c b/drivers/rtc/i2c_rtc_emul.c
index f25b976..ba418c2 100644
--- a/drivers/rtc/i2c_rtc_emul.c
+++ b/drivers/rtc/i2c_rtc_emul.c
@@ -28,25 +28,6 @@
 #define debug_buffer(x, ...)
 #endif
 
-/**
- * struct sandbox_i2c_rtc_plat_data - platform data for the RTC
- *
- * @base_time:		Base system time when RTC device was bound
- * @offset:		RTC offset from current system time
- * @use_system_time:	true to use system time, false to use @base_time
- * @reg:		Register values
- */
-struct sandbox_i2c_rtc_plat_data {
-	long base_time;
-	long offset;
-	bool use_system_time;
-	u8 reg[REG_COUNT];
-};
-
-struct sandbox_i2c_rtc {
-	unsigned int offset_secs;
-};
-
 long sandbox_i2c_rtc_set_offset(struct udevice *dev, bool use_system_time,
 				int offset)
 {
@@ -223,7 +204,7 @@
 }
 
 static const struct udevice_id sandbox_i2c_rtc_ids[] = {
-	{ .compatible = "sandbox,i2c-rtc" },
+	{ .compatible = "sandbox,i2c-rtc-emul" },
 	{ }
 };
 
diff --git a/drivers/rtc/sandbox_rtc.c b/drivers/rtc/sandbox_rtc.c
index d0864b1..657e5c7 100644
--- a/drivers/rtc/sandbox_rtc.c
+++ b/drivers/rtc/sandbox_rtc.c
@@ -79,6 +79,18 @@
 };
 #endif
 
+static int sandbox_rtc_bind(struct udevice *dev)
+{
+#if CONFIG_IS_ENABLED(PLATDATA)
+	struct sandbox_i2c_rtc_plat_data *plat = dev_get_plat(dev);
+
+	/* Set up the emul_idx for i2c_emul_find() */
+	i2c_emul_set_idx(dev, plat->dtplat.sandbox_emul->idx);
+#endif
+
+	return 0;
+}
+
 static const struct rtc_ops sandbox_rtc_ops = {
 	.get = sandbox_rtc_get,
 	.set = sandbox_rtc_set,
@@ -97,5 +109,6 @@
 	.id	= UCLASS_RTC,
 	.of_match = sandbox_rtc_ids,
 	.ops	= &sandbox_rtc_ops,
+	.bind	= sandbox_rtc_bind,
 	ACPI_OPS_PTR(&sandbox_rtc_acpi_ops)
 };
diff --git a/drivers/serial/serial_coreboot.c b/drivers/serial/serial_coreboot.c
index 88c8209..de09c86 100644
--- a/drivers/serial/serial_coreboot.c
+++ b/drivers/serial/serial_coreboot.c
@@ -9,7 +9,7 @@
 #include <dm.h>
 #include <ns16550.h>
 #include <serial.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
 
 static int coreboot_of_to_plat(struct udevice *dev)
 {
diff --git a/drivers/serial/serial_mtk.c b/drivers/serial/serial_mtk.c
index 6d41602..4145d9f 100644
--- a/drivers/serial/serial_mtk.c
+++ b/drivers/serial/serial_mtk.c
@@ -73,74 +73,64 @@
 struct mtk_serial_priv {
 	struct mtk_serial_regs __iomem *regs;
 	u32 clock;
+	bool force_highspeed;
 };
 
 static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud)
 {
-	bool support_clk12m_baud115200;
-	u32 quot, samplecount, realbaud;
+	u32 quot, realbaud, samplecount = 1;
 
-	if ((baud <= 115200) && (priv->clock == 12000000))
-		support_clk12m_baud115200 = true;
-	else
-		support_clk12m_baud115200 = false;
+	/* Special case for low baud clock */
+	if (baud <= 115200 && priv->clock <= 12000000) {
+		writel(3, &priv->regs->highspeed);
+
+		quot = DIV_ROUND_CLOSEST(priv->clock, 256 * baud);
+		if (quot == 0)
+			quot = 1;
+
+		samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
+
+		realbaud = priv->clock / samplecount / quot;
+		if (realbaud > BAUD_ALLOW_MAX(baud) ||
+		    realbaud < BAUD_ALLOW_MIX(baud)) {
+			pr_info("baud %d can't be handled\n", baud);
+		}
+
+		goto set_baud;
+	}
+
+	if (priv->force_highspeed)
+		goto use_hs3;
 
 	if (baud <= 115200) {
 		writel(0, &priv->regs->highspeed);
 		quot = DIV_ROUND_CLOSEST(priv->clock, 16 * baud);
-
-		if (support_clk12m_baud115200) {
-			writel(3, &priv->regs->highspeed);
-			quot = DIV_ROUND_CLOSEST(priv->clock, 256 * baud);
-			if (quot == 0)
-				quot = 1;
-
-			samplecount = DIV_ROUND_CLOSEST(priv->clock,
-							quot * baud);
-			if (samplecount != 0) {
-				realbaud = priv->clock / samplecount / quot;
-				if ((realbaud > BAUD_ALLOW_MAX(baud)) ||
-				    (realbaud < BAUD_ALLOW_MIX(baud))) {
-					pr_info("baud %d can't be handled\n",
-						baud);
-				}
-			} else {
-				pr_info("samplecount is 0\n");
-			}
-		}
 	} else if (baud <= 576000) {
 		writel(2, &priv->regs->highspeed);
 
 		/* Set to next lower baudrate supported */
 		if ((baud == 500000) || (baud == 576000))
 			baud = 460800;
+
 		quot = DIV_ROUND_UP(priv->clock, 4 * baud);
 	} else {
+use_hs3:
 		writel(3, &priv->regs->highspeed);
+
 		quot = DIV_ROUND_UP(priv->clock, 256 * baud);
+		samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
 	}
 
+set_baud:
 	/* set divisor */
 	writel(UART_LCR_WLS_8 | UART_LCR_DLAB, &priv->regs->lcr);
 	writel(quot & 0xff, &priv->regs->dll);
 	writel((quot >> 8) & 0xff, &priv->regs->dlm);
 	writel(UART_LCR_WLS_8, &priv->regs->lcr);
 
-	if (baud > 460800) {
-		u32 tmp;
-
-		tmp = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
-		writel(tmp - 1, &priv->regs->sample_count);
-		writel((tmp - 2) >> 1, &priv->regs->sample_point);
-	} else {
-		writel(0, &priv->regs->sample_count);
-		writel(0xff, &priv->regs->sample_point);
-	}
-
-	if (support_clk12m_baud115200) {
-		writel(samplecount - 1, &priv->regs->sample_count);
-		writel((samplecount - 2) >> 1, &priv->regs->sample_point);
-	}
+	/* set highspeed mode sample count & point */
+	writel(samplecount - 1, &priv->regs->sample_count);
+	writel((samplecount - 2) >> 1, &priv->regs->sample_point);
 }
 
 static int _mtk_serial_putc(struct mtk_serial_priv *priv, const char ch)
@@ -248,6 +238,8 @@
 		return -EINVAL;
 	}
 
+	priv->force_highspeed = dev_read_bool(dev, "mediatek,force-highspeed");
+
 	return 0;
 }
 
diff --git a/drivers/sound/tegra_i2s.c b/drivers/sound/tegra_i2s.c
index 5cf8225..932f737 100644
--- a/drivers/sound/tegra_i2s.c
+++ b/drivers/sound/tegra_i2s.c
@@ -4,7 +4,6 @@
  * Written by Simon Glass <sjg@chromium.org>
  */
 #define LOG_CATEGORY UCLASS_I2S
-#define LOG_DEBUG
 
 #include <common.h>
 #include <dm.h>
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 7155d4a..ee30110 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -11,6 +11,7 @@
 #include <log.h>
 #include <malloc.h>
 #include <spi.h>
+#include <spi-mem.h>
 #include <dm/device_compat.h>
 #include <asm/global_data.h>
 #include <dm/device-internal.h>
@@ -199,6 +200,16 @@
 			ops->set_mode += gd->reloc_off;
 		if (ops->cs_info)
 			ops->cs_info += gd->reloc_off;
+		if (ops->mem_ops) {
+			struct spi_controller_mem_ops *mem_ops =
+				(struct spi_controller_mem_ops *)ops->mem_ops;
+			if (mem_ops->adjust_op_size)
+				mem_ops->adjust_op_size += gd->reloc_off;
+			if (mem_ops->supports_op)
+				mem_ops->supports_op += gd->reloc_off;
+			if (mem_ops->exec_op)
+				mem_ops->exec_op += gd->reloc_off;
+		}
 		reloc_done++;
 	}
 #endif
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 0274afd..b892cda 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -314,8 +314,7 @@
 
 	priv->freq = speed;
 
-	debug("xilinx_spi_set_speed: regs=%p, speed=%d\n", priv->regs,
-	      priv->freq);
+	debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq);
 
 	return 0;
 }
@@ -324,7 +323,7 @@
 {
 	struct xilinx_spi_priv *priv = dev_get_priv(bus);
 	struct xilinx_spi_regs *regs = priv->regs;
-	uint32_t spicr;
+	u32 spicr;
 
 	spicr = readl(&regs->spicr);
 	if (mode & SPI_LSB_FIRST)
@@ -339,8 +338,7 @@
 	writel(spicr, &regs->spicr);
 	priv->mode = mode;
 
-	debug("xilinx_spi_set_mode: regs=%p, mode=%d\n", priv->regs,
-	      priv->mode);
+	debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
 
 	return 0;
 }
diff --git a/drivers/sysreset/sysreset-uclass.c b/drivers/sysreset/sysreset-uclass.c
index 6c9dc7a..9512f68 100644
--- a/drivers/sysreset/sysreset-uclass.c
+++ b/drivers/sysreset/sysreset-uclass.c
@@ -113,7 +113,7 @@
 /**
  * reset_cpu() - calls sysreset_walk(SYSRESET_WARM)
  */
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	sysreset_walk_halt(SYSRESET_WARM);
 }
diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig
index 65622f3..d030280 100644
--- a/drivers/tee/optee/Kconfig
+++ b/drivers/tee/optee/Kconfig
@@ -31,6 +31,12 @@
 	  permits to test reverse RPC calls to TEE supplicant. Should
 	  be used only in sandbox env.
 
+config OPTEE_TA_SCP03
+	bool "Support SCP03 TA"
+	default y
+	help
+	  Enables support for controlling (enabling, provisioning) the
+	  Secure Channel Protocol 03 operation in the OP-TEE SCP03 TA.
 endmenu
 
 endif
diff --git a/drivers/tee/sandbox.c b/drivers/tee/sandbox.c
index 3a1d34d..35e8542 100644
--- a/drivers/tee/sandbox.c
+++ b/drivers/tee/sandbox.c
@@ -8,6 +8,7 @@
 #include <tee.h>
 #include <tee/optee_ta_avb.h>
 #include <tee/optee_ta_rpc_test.h>
+#include <tee/optee_ta_scp03.h>
 
 #include "optee/optee_msg.h"
 #include "optee/optee_private.h"
@@ -68,6 +69,7 @@
 	return NULL;
 }
 
+#if defined(CONFIG_OPTEE_TA_SCP03) || defined(CONFIG_OPTEE_TA_AVB)
 static u32 get_attr(uint n, uint num_params, struct tee_param *params)
 {
 	if (n >= num_params)
@@ -79,7 +81,7 @@
 static u32 check_params(u8 p0, u8 p1, u8 p2, u8 p3, uint num_params,
 			struct tee_param *params)
 {
-	u8 p[] = { p0, p1, p2, p3};
+	u8 p[] = { p0, p1, p2, p3 };
 	uint n;
 
 	for (n = 0; n < ARRAY_SIZE(p); n++)
@@ -97,6 +99,50 @@
 
 	return TEE_ERROR_BAD_PARAMETERS;
 }
+#endif
+
+#ifdef CONFIG_OPTEE_TA_SCP03
+static u32 pta_scp03_open_session(struct udevice *dev, uint num_params,
+				  struct tee_param *params)
+{
+	/*
+	 * We don't expect additional parameters when opening a session to
+	 * this TA.
+	 */
+	return check_params(TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
+			    TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
+			    num_params, params);
+}
+
+static u32 pta_scp03_invoke_func(struct udevice *dev, u32 func, uint num_params,
+				 struct tee_param *params)
+{
+	u32 res;
+	static bool enabled;
+
+	switch (func) {
+	case PTA_CMD_ENABLE_SCP03:
+		res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
+				   TEE_PARAM_ATTR_TYPE_NONE,
+				   TEE_PARAM_ATTR_TYPE_NONE,
+				   TEE_PARAM_ATTR_TYPE_NONE,
+				   num_params, params);
+		if (res)
+			return res;
+
+		if (!enabled) {
+			enabled = true;
+		} else {
+		}
+
+		if (params[0].u.value.a)
+
+		return TEE_SUCCESS;
+	default:
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+}
+#endif
 
 #ifdef CONFIG_OPTEE_TA_AVB
 static u32 ta_avb_open_session(struct udevice *dev, uint num_params,
@@ -357,6 +403,12 @@
 	  .invoke_func = ta_rpc_test_invoke_func,
 	},
 #endif
+#ifdef CONFIG_OPTEE_TA_SCP03
+	{ .uuid = PTA_SCP03_UUID,
+	  .open_session = pta_scp03_open_session,
+	  .invoke_func = pta_scp03_invoke_func,
+	},
+#endif
 };
 
 static void sandbox_tee_get_version(struct udevice *dev,
diff --git a/drivers/timer/sandbox_timer.c b/drivers/timer/sandbox_timer.c
index 2075cd4..c846bfb 100644
--- a/drivers/timer/sandbox_timer.c
+++ b/drivers/timer/sandbox_timer.c
@@ -38,7 +38,8 @@
 {
 	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 
-	if (dev_read_bool(dev, "sandbox,timebase-frequency-fallback"))
+	if (CONFIG_IS_ENABLED(CPU) &&
+	    dev_read_bool(dev, "sandbox,timebase-frequency-fallback"))
 		return timer_timebase_fallback(dev);
 	else if (!uc_priv->clock_rate)
 		uc_priv->clock_rate = SANDBOX_TIMER_RATE;
diff --git a/drivers/timer/sifive_clint_timer.c b/drivers/timer/sifive_clint_timer.c
index de7b4b9..939b99d 100644
--- a/drivers/timer/sifive_clint_timer.c
+++ b/drivers/timer/sifive_clint_timer.c
@@ -54,6 +54,7 @@
 
 static const struct udevice_id sifive_clint_ids[] = {
 	{ .compatible = "riscv,clint0" },
+	{ .compatible = "sifive,clint0" },
 	{ }
 };
 
diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c
index 6f00a5d..73b4a5c 100644
--- a/drivers/timer/timer-uclass.c
+++ b/drivers/timer/timer-uclass.c
@@ -83,11 +83,7 @@
 	return 0;
 }
 
-/*
- * TODO: should be CONFIG_IS_ENABLED(CPU), but the SPL config has _SUPPORT on
- * the end...
- */
-#if defined(CONFIG_CPU) || defined(CONFIG_SPL_CPU_SUPPORT)
+#if CONFIG_IS_ENABLED(CPU)
 int timer_timebase_fallback(struct udevice *dev)
 {
 	struct udevice *cpu;
diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile
index 8f075b9..f64d200 100644
--- a/drivers/tpm/Makefile
+++ b/drivers/tpm/Makefile
@@ -10,7 +10,7 @@
 obj-$(CONFIG_TPM_ST33ZP24_I2C) += tpm_tis_st33zp24_i2c.o
 obj-$(CONFIG_TPM_ST33ZP24_SPI) += tpm_tis_st33zp24_spi.o
 
-obj-$(CONFIG_TPM2_CR50_I2C) += cr50_i2c.o
+obj-$(CONFIG_$(SPL_TPL_)TPM2_CR50_I2C) += cr50_i2c.o
 obj-$(CONFIG_TPM2_TIS_SANDBOX) += tpm2_tis_sandbox.o
 obj-$(CONFIG_TPM2_TIS_SPI) += tpm2_tis_spi.o
 obj-$(CONFIG_TPM2_FTPM_TEE) += tpm2_ftpm_tee.o
diff --git a/drivers/tpm/cr50_i2c.c b/drivers/tpm/cr50_i2c.c
index b103a6f..76432bd 100644
--- a/drivers/tpm/cr50_i2c.c
+++ b/drivers/tpm/cr50_i2c.c
@@ -309,7 +309,7 @@
 	int status;
 	int ret;
 
-	log_debug("%s: len=%x\n", __func__, buf_len);
+	log_debug("%s: buf_len=%x\n", __func__, buf_len);
 	if (buf_len < TPM_HEADER_SIZE)
 		return -E2BIG;
 
@@ -386,7 +386,7 @@
 	ulong timeout;
 	int ret;
 
-	log_debug("%s: len=%x\n", __func__, len);
+	log_debug("len=%x\n", len);
 	timeout = timer_get_us() + TIMEOUT_LONG_US;
 	do {
 		ret = cr50_i2c_status(dev);
diff --git a/drivers/tpm/tpm-uclass.c b/drivers/tpm/tpm-uclass.c
index beb0fa3..35774a6 100644
--- a/drivers/tpm/tpm-uclass.c
+++ b/drivers/tpm/tpm-uclass.c
@@ -4,6 +4,8 @@
  * Written by Simon Glass <sjg@chromium.org>
  */
 
+#define LOG_CATEGORY UCLASS_TPM
+
 #include <common.h>
 #include <dm.h>
 #include <log.h>
@@ -87,15 +89,15 @@
 	ordinal = get_unaligned_be32(sendbuf + TPM_CMD_ORDINAL_BYTE);
 
 	if (count == 0) {
-		debug("no data\n");
+		log_debug("no data\n");
 		return -ENODATA;
 	}
 	if (count > send_size) {
-		debug("invalid count value %x %zx\n", count, send_size);
+		log_debug("invalid count value %x %zx\n", count, send_size);
 		return -E2BIG;
 	}
 
-	debug("%s: Calling send\n", __func__);
+	log_debug("%s: Calling send\n", __func__);
 	ret = ops->send(dev, sendbuf, send_size);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
index c74bacf..24c804a 100644
--- a/drivers/tpm/tpm2_tis_sandbox.c
+++ b/drivers/tpm/tpm2_tis_sandbox.c
@@ -285,7 +285,7 @@
 	length = get_unaligned_be32(sent);
 	sent += sizeof(length);
 	if (length != send_size) {
-		printf("TPM2: Unmatching length, received: %ld, expected: %d\n",
+		printf("TPM2: Unmatching length, received: %zd, expected: %d\n",
 		       send_size, length);
 		rc = TPM2_RC_SIZE;
 		sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
diff --git a/drivers/usb/gadget/udc/udc-uclass.c b/drivers/usb/gadget/udc/udc-uclass.c
index 3053ccf..dbc354e 100644
--- a/drivers/usb/gadget/udc/udc-uclass.c
+++ b/drivers/usb/gadget/udc/udc-uclass.c
@@ -45,7 +45,7 @@
 		dev_array[index] = NULL;
 	return ret;
 #else
-	return -ENOTSUPP;
+	return -ENOSYS;
 #endif
 }
 
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 83147d5..1c11c2e 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -434,9 +434,9 @@
 	BUG_ON((type != XHCI_CTX_TYPE_DEVICE) && (type != XHCI_CTX_TYPE_INPUT));
 	ctx->type = type;
 	ctx->size = (MAX_EP_CTX_NUM + 1) *
-			CTX_SIZE(readl(&ctrl->hccr->cr_hccparams));
+			CTX_SIZE(xhci_readl(&ctrl->hccr->cr_hccparams));
 	if (type == XHCI_CTX_TYPE_INPUT)
-		ctx->size += CTX_SIZE(readl(&ctrl->hccr->cr_hccparams));
+		ctx->size += CTX_SIZE(xhci_readl(&ctrl->hccr->cr_hccparams));
 
 	ctx->bytes = xhci_malloc(ctx->size);
 
@@ -636,7 +636,7 @@
 		return (struct xhci_slot_ctx *)ctx->bytes;
 
 	return (struct xhci_slot_ctx *)
-		(ctx->bytes + CTX_SIZE(readl(&ctrl->hccr->cr_hccparams)));
+		(ctx->bytes + CTX_SIZE(xhci_readl(&ctrl->hccr->cr_hccparams)));
 }
 
 /**
@@ -658,7 +658,7 @@
 
 	return (struct xhci_ep_ctx *)
 		(ctx->bytes +
-		(ep_index * CTX_SIZE(readl(&ctrl->hccr->cr_hccparams))));
+		(ep_index * CTX_SIZE(xhci_readl(&ctrl->hccr->cr_hccparams))));
 }
 
 /**
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 46c137f..35bd5cd 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -849,12 +849,9 @@
 		}
 	}
 
-	debug("req->requesttype = %d, req->request = %d,"
-		"le16_to_cpu(req->value) = %d,"
-		"le16_to_cpu(req->index) = %d,"
-		"le16_to_cpu(req->length) = %d\n",
-		req->requesttype, req->request, le16_to_cpu(req->value),
-		le16_to_cpu(req->index), le16_to_cpu(req->length));
+	debug("req->requesttype = %d, req->request = %d, req->value = %d, req->index = %d, req->length = %d\n",
+	      req->requesttype, req->request, le16_to_cpu(req->value),
+	      le16_to_cpu(req->index), le16_to_cpu(req->length));
 
 	trb_fields[0] = req->requesttype | req->request << 8 |
 				le16_to_cpu(req->value) << 16;
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 667157c..63ae2ba 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -241,7 +241,7 @@
 
 config VIDEO_COREBOOT
 	bool "Enable coreboot framebuffer driver support"
-	depends on X86 && SYS_COREBOOT
+	depends on X86
 	help
 	  Turn on this option to enable a framebuffer driver when U-Boot is
 	  loaded by coreboot where the graphics device is configured by
diff --git a/drivers/video/coreboot.c b/drivers/video/coreboot.c
index 0a5fb08..7237542 100644
--- a/drivers/video/coreboot.c
+++ b/drivers/video/coreboot.c
@@ -5,9 +5,10 @@
 
 #include <common.h>
 #include <dm.h>
+#include <init.h>
 #include <vbe.h>
 #include <video.h>
-#include <asm/arch/sysinfo.h>
+#include <asm/cb_sysinfo.h>
 
 static int save_vesa_mode(struct cb_framebuffer *fb,
 			  struct vesa_mode_info *vesa)
@@ -17,7 +18,7 @@
 	 * running on the serial console.
 	 */
 	if (!fb)
-		return -ENXIO;
+		return log_msg_ret("save", -ENXIO);
 
 	vesa->x_resolution = fb->x_resolution;
 	vesa->y_resolution = fb->y_resolution;
@@ -44,16 +45,23 @@
 	struct vesa_mode_info *vesa = &mode_info.vesa;
 	int ret;
 
+	if (ll_boot_init())
+		return log_msg_ret("ll", -ENODEV);
+
 	printf("Video: ");
 
 	/* Initialize vesa_mode_info structure */
 	ret = save_vesa_mode(fb, vesa);
-	if (ret)
+	if (ret) {
+		ret = log_msg_ret("save", ret);
 		goto err;
+	}
 
 	ret = vbe_setup_video_priv(vesa, uc_priv, plat);
-	if (ret)
+	if (ret) {
+		ret = log_msg_ret("setup", ret);
 		goto err;
+	}
 
 	printf("%dx%dx%d\n", uc_priv->xsize, uc_priv->ysize,
 	       vesa->bits_per_pixel);
@@ -61,7 +69,7 @@
 	return 0;
 
 err:
-	printf("No video mode configured in coreboot!\n");
+	printf("No video mode configured in coreboot (err=%d)\n", ret);
 	return ret;
 }
 
diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c
index f52aba4..4361a58 100644
--- a/drivers/video/sunxi/sunxi_display.c
+++ b/drivers/video/sunxi/sunxi_display.c
@@ -7,6 +7,8 @@
  */
 
 #include <common.h>
+#include <display.h>
+#include <dm.h>
 #include <cpu_func.h>
 #include <efi_loader.h>
 #include <init.h>
@@ -28,7 +30,9 @@
 #include <fdt_support.h>
 #include <i2c.h>
 #include <malloc.h>
+#include <video.h>
 #include <video_fb.h>
+#include <dm/uclass-internal.h>
 #include "../videomodes.h"
 #include "../anx9804.h"
 #include "../hitachi_tx18d42vm_lcd.h"
@@ -45,6 +49,11 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/* Maximum LCD size we support */
+#define LCD_MAX_WIDTH		3840
+#define LCD_MAX_HEIGHT		2160
+#define LCD_MAX_LOG2_BPP	VIDEO_BPP32
+
 enum sunxi_monitor {
 	sunxi_monitor_none,
 	sunxi_monitor_dvi,
@@ -58,13 +67,12 @@
 };
 #define SUNXI_MONITOR_LAST sunxi_monitor_composite_pal_nc
 
-struct sunxi_display {
-	GraphicDevice graphic_device;
+struct sunxi_display_priv {
 	enum sunxi_monitor monitor;
 	unsigned int depth;
 	unsigned int fb_addr;
 	unsigned int fb_size;
-} sunxi_display;
+};
 
 const struct ctfb_res_modes composite_video_modes[2] = {
 	/*  x     y  hz  pixclk ps/kHz   le   ri  up  lo   hs vs  s  vmode */
@@ -214,7 +222,8 @@
 	return r;
 }
 
-static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode,
+static int sunxi_hdmi_edid_get_mode(struct sunxi_display_priv *sunxi_display,
+				    struct ctfb_res_modes *mode,
 				    bool verbose_mode)
 {
 	struct edid1_info edid1;
@@ -291,14 +300,14 @@
 	}
 
 	/* Check for basic audio support, if found enable hdmi output */
-	sunxi_display.monitor = sunxi_monitor_dvi;
+	sunxi_display->monitor = sunxi_monitor_dvi;
 	for (i = 0; i < ext_blocks; i++) {
 		if (cea681[i].extension_tag != EDID_CEA861_EXTENSION_TAG ||
 		    cea681[i].revision < 2)
 			continue;
 
 		if (EDID_CEA861_SUPPORTS_BASIC_AUDIO(cea681[i]))
-			sunxi_display.monitor = sunxi_monitor_hdmi;
+			sunxi_display->monitor = sunxi_monitor_hdmi;
 	}
 
 	return 0;
@@ -414,9 +423,9 @@
 static void sunxi_frontend_enable(void) {}
 #endif
 
-static bool sunxi_is_composite(void)
+static bool sunxi_is_composite(enum sunxi_monitor monitor)
 {
-	switch (sunxi_display.monitor) {
+	switch (monitor) {
 	case sunxi_monitor_none:
 	case sunxi_monitor_dvi:
 	case sunxi_monitor_hdmi:
@@ -473,7 +482,8 @@
 };
 
 static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode,
-				    unsigned int address)
+				    unsigned int address,
+				    enum sunxi_monitor monitor)
 {
 	struct sunxi_de_be_reg * const de_be =
 		(struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
@@ -502,7 +512,7 @@
 #endif
 			     SUNXI_DE_BE_MODE_INTERLACE_ENABLE);
 
-	if (sunxi_is_composite()) {
+	if (sunxi_is_composite(monitor)) {
 		writel(SUNXI_DE_BE_OUTPUT_COLOR_CTRL_ENABLE,
 		       &de_be->output_color_ctrl);
 		for (i = 0; i < 12; i++)
@@ -616,7 +626,8 @@
 		gpio_direction_output(pin, PWM_ON);
 }
 
-static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
+static void sunxi_lcdc_tcon0_mode_set(struct sunxi_display_priv *sunxi_display,
+				      const struct ctfb_res_modes *mode,
 				      bool for_ext_vga_dac)
 {
 	struct sunxi_lcdc_reg * const lcdc =
@@ -643,17 +654,18 @@
 	}
 
 	lcdc_pll_set(ccm, 0, mode->pixclock_khz, &clk_div, &clk_double,
-		     sunxi_is_composite());
+		     sunxi_is_composite(sunxi_display->monitor));
 
 	video_ctfb_mode_to_display_timing(mode, &timing);
 	lcdc_tcon0_mode_set(lcdc, &timing, clk_div, for_ext_vga_dac,
-			    sunxi_display.depth, CONFIG_VIDEO_LCD_DCLK_PHASE);
+			    sunxi_display->depth, CONFIG_VIDEO_LCD_DCLK_PHASE);
 }
 
 #if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
 static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
 				      int *clk_div, int *clk_double,
-				      bool use_portd_hvsync)
+				      bool use_portd_hvsync,
+				      enum sunxi_monitor monitor)
 {
 	struct sunxi_lcdc_reg * const lcdc =
 		(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
@@ -663,7 +675,7 @@
 
 	video_ctfb_mode_to_display_timing(mode, &timing);
 	lcdc_tcon1_mode_set(lcdc, &timing, use_portd_hvsync,
-			    sunxi_is_composite());
+			    sunxi_is_composite(monitor));
 
 	if (use_portd_hvsync) {
 		sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD_LCD0);
@@ -671,7 +683,7 @@
 	}
 
 	lcdc_pll_set(ccm, 1, mode->pixclock_khz, clk_div, clk_double,
-		     sunxi_is_composite());
+		     sunxi_is_composite(monitor));
 }
 #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
 
@@ -725,7 +737,8 @@
 }
 
 static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
-				int clk_div, int clk_double)
+				int clk_div, int clk_double,
+				enum sunxi_monitor monitor)
 {
 	struct sunxi_hdmi_reg * const hdmi =
 		(struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
@@ -734,7 +747,7 @@
 	/* Write clear interrupt status bits */
 	writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
 
-	if (sunxi_display.monitor == sunxi_monitor_hdmi)
+	if (monitor == sunxi_monitor_hdmi)
 		sunxi_hdmi_setup_info_frames(mode);
 
 	/* Set input sync enable */
@@ -789,7 +802,7 @@
 
 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
 
-static void sunxi_tvencoder_mode_set(void)
+static void sunxi_tvencoder_mode_set(enum sunxi_monitor monitor)
 {
 	struct sunxi_ccm_reg * const ccm =
 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
@@ -801,7 +814,7 @@
 	/* Clock on */
 	setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
 
-	switch (sunxi_display.monitor) {
+	switch (monitor) {
 	case sunxi_monitor_vga:
 		tvencoder_mode_set(tve, tve_mode_vga);
 		break;
@@ -896,26 +909,28 @@
 	sunxi_drc_init();
 }
 
-static void sunxi_mode_set(const struct ctfb_res_modes *mode,
+static void sunxi_mode_set(struct sunxi_display_priv *sunxi_display,
+			   const struct ctfb_res_modes *mode,
 			   unsigned int address)
 {
+	enum sunxi_monitor monitor = sunxi_display->monitor;
 	int __maybe_unused clk_div, clk_double;
 	struct sunxi_lcdc_reg * const lcdc =
 		(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
 	struct sunxi_tve_reg * __maybe_unused const tve =
 		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
 
-	switch (sunxi_display.monitor) {
+	switch (sunxi_display->monitor) {
 	case sunxi_monitor_none:
 		break;
 	case sunxi_monitor_dvi:
 	case sunxi_monitor_hdmi:
 #ifdef CONFIG_VIDEO_HDMI
-		sunxi_composer_mode_set(mode, address);
-		sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
-		sunxi_hdmi_mode_set(mode, clk_div, clk_double);
+		sunxi_composer_mode_set(mode, address, monitor);
+		sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0, monitor);
+		sunxi_hdmi_mode_set(mode, clk_div, clk_double, monitor);
 		sunxi_composer_enable();
-		lcdc_enable(lcdc, sunxi_display.depth);
+		lcdc_enable(lcdc, sunxi_display->depth);
 		sunxi_hdmi_enable();
 #endif
 		break;
@@ -930,7 +945,7 @@
 			axp_set_eldo(3, 1800);
 			anx9804_init(CONFIG_VIDEO_LCD_I2C_BUS, 4,
 				     ANX9804_DATA_RATE_1620M,
-				     sunxi_display.depth);
+				     sunxi_display->depth);
 		}
 		if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) {
 			mdelay(50); /* Wait for lcd controller power on */
@@ -942,10 +957,10 @@
 			i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */
 			i2c_set_bus_num(orig_i2c_bus);
 		}
-		sunxi_composer_mode_set(mode, address);
-		sunxi_lcdc_tcon0_mode_set(mode, false);
+		sunxi_composer_mode_set(mode, address, monitor);
+		sunxi_lcdc_tcon0_mode_set(sunxi_display, mode, false);
 		sunxi_composer_enable();
-		lcdc_enable(lcdc, sunxi_display.depth);
+		lcdc_enable(lcdc, sunxi_display->depth);
 #ifdef CONFIG_VIDEO_LCD_SSD2828
 		sunxi_ssd2828_init(mode);
 #endif
@@ -953,17 +968,17 @@
 		break;
 	case sunxi_monitor_vga:
 #ifdef CONFIG_VIDEO_VGA
-		sunxi_composer_mode_set(mode, address);
-		sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1);
-		sunxi_tvencoder_mode_set();
+		sunxi_composer_mode_set(mode, address, monitor);
+		sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1, monitor);
+		sunxi_tvencoder_mode_set(monitor);
 		sunxi_composer_enable();
-		lcdc_enable(lcdc, sunxi_display.depth);
+		lcdc_enable(lcdc, sunxi_display->depth);
 		tvencoder_enable(tve);
 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
-		sunxi_composer_mode_set(mode, address);
-		sunxi_lcdc_tcon0_mode_set(mode, true);
+		sunxi_composer_mode_set(mode, address, monitor);
+		sunxi_lcdc_tcon0_mode_set(sunxi_display, mode, true);
 		sunxi_composer_enable();
-		lcdc_enable(lcdc, sunxi_display.depth);
+		lcdc_enable(lcdc, sunxi_display->depth);
 		sunxi_vga_external_dac_enable();
 #endif
 		break;
@@ -972,11 +987,11 @@
 	case sunxi_monitor_composite_pal_m:
 	case sunxi_monitor_composite_pal_nc:
 #ifdef CONFIG_VIDEO_COMPOSITE
-		sunxi_composer_mode_set(mode, address);
-		sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
-		sunxi_tvencoder_mode_set();
+		sunxi_composer_mode_set(mode, address, monitor);
+		sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0, monitor);
+		sunxi_tvencoder_mode_set(monitor);
 		sunxi_composer_enable();
-		lcdc_enable(lcdc, sunxi_display.depth);
+		lcdc_enable(lcdc, sunxi_display->depth);
 		tvencoder_enable(tve);
 #endif
 		break;
@@ -999,11 +1014,6 @@
 	}
 }
 
-ulong board_get_usable_ram_top(ulong total_size)
-{
-	return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
-}
-
 static bool sunxi_has_hdmi(void)
 {
 #ifdef CONFIG_VIDEO_HDMI
@@ -1052,9 +1062,11 @@
 		return sunxi_monitor_none;
 }
 
-void *video_hw_init(void)
+static int sunxi_de_probe(struct udevice *dev)
 {
-	static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
+	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct video_uc_plat *plat = dev_get_uclass_plat(dev);
+	struct sunxi_display_priv *sunxi_display = dev_get_priv(dev);
 	const struct ctfb_res_modes *mode;
 	struct ctfb_res_modes custom;
 	const char *options;
@@ -1067,10 +1079,8 @@
 	char mon[16];
 	char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
 
-	memset(&sunxi_display, 0, sizeof(struct sunxi_display));
-
 	video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
-				 &sunxi_display.depth, &options);
+				 &sunxi_display->depth, &options);
 #ifdef CONFIG_VIDEO_HDMI
 	hpd = video_get_option_int(options, "hpd", 1);
 	hpd_delay = video_get_option_int(options, "hpd_delay", 500);
@@ -1078,35 +1088,35 @@
 #endif
 	overscan_x = video_get_option_int(options, "overscan_x", -1);
 	overscan_y = video_get_option_int(options, "overscan_y", -1);
-	sunxi_display.monitor = sunxi_get_default_mon(true);
+	sunxi_display->monitor = sunxi_get_default_mon(true);
 	video_get_option_string(options, "monitor", mon, sizeof(mon),
-				sunxi_get_mon_desc(sunxi_display.monitor));
+				sunxi_get_mon_desc(sunxi_display->monitor));
 	for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
 		if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) {
-			sunxi_display.monitor = i;
+			sunxi_display->monitor = i;
 			break;
 		}
 	}
 	if (i > SUNXI_MONITOR_LAST)
 		printf("Unknown monitor: '%s', falling back to '%s'\n",
-		       mon, sunxi_get_mon_desc(sunxi_display.monitor));
+		       mon, sunxi_get_mon_desc(sunxi_display->monitor));
 
 #ifdef CONFIG_VIDEO_HDMI
 	/* If HDMI/DVI is selected do HPD & EDID, and handle fallback */
-	if (sunxi_display.monitor == sunxi_monitor_dvi ||
-	    sunxi_display.monitor == sunxi_monitor_hdmi) {
+	if (sunxi_display->monitor == sunxi_monitor_dvi ||
+	    sunxi_display->monitor == sunxi_monitor_hdmi) {
 		/* Always call hdp_detect, as it also enables clocks, etc. */
 		hdmi_present = (sunxi_hdmi_hpd_detect(hpd_delay) == 1);
 		if (hdmi_present && edid) {
 			printf("HDMI connected: ");
-			if (sunxi_hdmi_edid_get_mode(&custom, true) == 0)
+			if (sunxi_hdmi_edid_get_mode(sunxi_display, &custom, true) == 0)
 				mode = &custom;
 			else
 				hdmi_present = false;
 		}
 		/* Fall back to EDID in case HPD failed */
 		if (edid && !hdmi_present) {
-			if (sunxi_hdmi_edid_get_mode(&custom, false) == 0) {
+			if (sunxi_hdmi_edid_get_mode(sunxi_display, &custom, false) == 0) {
 				mode = &custom;
 				hdmi_present = true;
 			}
@@ -1114,38 +1124,39 @@
 		/* Shut down when display was not found */
 		if ((hpd || edid) && !hdmi_present) {
 			sunxi_hdmi_shutdown();
-			sunxi_display.monitor = sunxi_get_default_mon(false);
+			sunxi_display->monitor = sunxi_get_default_mon(false);
 		} /* else continue with hdmi/dvi without a cable connected */
 	}
 #endif
 
-	switch (sunxi_display.monitor) {
+	switch (sunxi_display->monitor) {
 	case sunxi_monitor_none:
-		return NULL;
+		printf("Unknown monitor\n");
+		return -EINVAL;
 	case sunxi_monitor_dvi:
 	case sunxi_monitor_hdmi:
 		if (!sunxi_has_hdmi()) {
 			printf("HDMI/DVI not supported on this board\n");
-			sunxi_display.monitor = sunxi_monitor_none;
-			return NULL;
+			sunxi_display->monitor = sunxi_monitor_none;
+			return -EINVAL;
 		}
 		break;
 	case sunxi_monitor_lcd:
 		if (!sunxi_has_lcd()) {
 			printf("LCD not supported on this board\n");
-			sunxi_display.monitor = sunxi_monitor_none;
-			return NULL;
+			sunxi_display->monitor = sunxi_monitor_none;
+			return -EINVAL;
 		}
-		sunxi_display.depth = video_get_params(&custom, lcd_mode);
+		sunxi_display->depth = video_get_params(&custom, lcd_mode);
 		mode = &custom;
 		break;
 	case sunxi_monitor_vga:
 		if (!sunxi_has_vga()) {
 			printf("VGA not supported on this board\n");
-			sunxi_display.monitor = sunxi_monitor_none;
-			return NULL;
+			sunxi_display->monitor = sunxi_monitor_none;
+			return -EINVAL;
 		}
-		sunxi_display.depth = 18;
+		sunxi_display->depth = 18;
 		break;
 	case sunxi_monitor_composite_pal:
 	case sunxi_monitor_composite_ntsc:
@@ -1153,85 +1164,99 @@
 	case sunxi_monitor_composite_pal_nc:
 		if (!sunxi_has_composite()) {
 			printf("Composite video not supported on this board\n");
-			sunxi_display.monitor = sunxi_monitor_none;
-			return NULL;
+			sunxi_display->monitor = sunxi_monitor_none;
+			return -EINVAL;
 		}
-		if (sunxi_display.monitor == sunxi_monitor_composite_pal ||
-		    sunxi_display.monitor == sunxi_monitor_composite_pal_nc)
+		if (sunxi_display->monitor == sunxi_monitor_composite_pal ||
+		    sunxi_display->monitor == sunxi_monitor_composite_pal_nc)
 			mode = &composite_video_modes[0];
 		else
 			mode = &composite_video_modes[1];
-		sunxi_display.depth = 24;
+		sunxi_display->depth = 24;
 		break;
 	}
 
 	/* Yes these defaults are quite high, overscan on composite sucks... */
 	if (overscan_x == -1)
-		overscan_x = sunxi_is_composite() ? 32 : 0;
+		overscan_x = sunxi_is_composite(sunxi_display->monitor) ? 32 : 0;
 	if (overscan_y == -1)
-		overscan_y = sunxi_is_composite() ? 20 : 0;
+		overscan_y = sunxi_is_composite(sunxi_display->monitor) ? 20 : 0;
 
-	sunxi_display.fb_size =
-		(mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
+	sunxi_display->fb_size = plat->size;
 	overscan_offset = (overscan_y * mode->xres + overscan_x) * 4;
 	/* We want to keep the fb_base for simplefb page aligned, where as
 	 * the sunxi dma engines will happily accept an unaligned address. */
 	if (overscan_offset)
-		sunxi_display.fb_size += 0x1000;
-
-	if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
-		printf("Error need %dkB for fb, but only %dkB is reserved\n",
-		       sunxi_display.fb_size >> 10,
-		       CONFIG_SUNXI_MAX_FB_SIZE >> 10);
-		return NULL;
-	}
+		sunxi_display->fb_size += 0x1000;
 
 	printf("Setting up a %dx%d%s %s console (overscan %dx%d)\n",
 	       mode->xres, mode->yres,
 	       (mode->vmode == FB_VMODE_INTERLACED) ? "i" : "",
-	       sunxi_get_mon_desc(sunxi_display.monitor),
+	       sunxi_get_mon_desc(sunxi_display->monitor),
 	       overscan_x, overscan_y);
 
-	gd->fb_base = gd->bd->bi_dram[0].start +
-		      gd->bd->bi_dram[0].size - sunxi_display.fb_size;
+	sunxi_display->fb_addr = plat->base;
 	sunxi_engines_init();
 
 #ifdef CONFIG_EFI_LOADER
-	efi_add_memory_map(gd->fb_base, sunxi_display.fb_size,
+	efi_add_memory_map(sunxi_display->fb_addr, sunxi_display->fb_size,
 			   EFI_RESERVED_MEMORY_TYPE);
 #endif
 
-	fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
-	sunxi_display.fb_addr = gd->fb_base;
+	fb_dma_addr = sunxi_display->fb_addr - CONFIG_SYS_SDRAM_BASE;
 	if (overscan_offset) {
 		fb_dma_addr += 0x1000 - (overscan_offset & 0xfff);
-		sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff;
-		memset((void *)gd->fb_base, 0, sunxi_display.fb_size);
-		flush_cache(gd->fb_base, sunxi_display.fb_size);
+		sunxi_display->fb_addr += ALIGN(overscan_offset, 0x1000);
+		memset((void *)sunxi_display->fb_addr, 0, sunxi_display->fb_size);
+		flush_cache(sunxi_display->fb_addr, sunxi_display->fb_size);
 	}
-	sunxi_mode_set(mode, fb_dma_addr);
+	sunxi_mode_set(sunxi_display, mode, fb_dma_addr);
 
-	/*
-	 * These are the only members of this structure that are used. All the
-	 * others are driver specific. The pitch is stored in plnSizeX.
-	 */
-	graphic_device->frameAdrs = sunxi_display.fb_addr;
-	graphic_device->gdfIndex = GDF_32BIT_X888RGB;
-	graphic_device->gdfBytesPP = 4;
-	graphic_device->winSizeX = mode->xres - 2 * overscan_x;
-	graphic_device->winSizeY = mode->yres - 2 * overscan_y;
-	graphic_device->plnSizeX = mode->xres * graphic_device->gdfBytesPP;
+	/* The members of struct video_priv to be set by the driver. */
+	uc_priv->bpix = VIDEO_BPP32;
+	uc_priv->xsize = mode->xres;
+	uc_priv->ysize = mode->yres;
 
-	return graphic_device;
+	video_set_flush_dcache(dev, true);
+
+	return 0;
 }
 
+static int sunxi_de_bind(struct udevice *dev)
+{
+	struct video_uc_plat *plat = dev_get_uclass_plat(dev);
+
+	plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT * VNBYTES(LCD_MAX_LOG2_BPP);
+
+	return 0;
+}
+
+static const struct video_ops sunxi_de_ops = {
+};
+
+U_BOOT_DRIVER(sunxi_de) = {
+	.name	= "sunxi_de",
+	.id	= UCLASS_VIDEO,
+	.ops	= &sunxi_de_ops,
+	.bind	= sunxi_de_bind,
+	.probe	= sunxi_de_probe,
+	.priv_auto = sizeof(struct sunxi_display_priv),
+	.flags	= DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRVINFO(sunxi_de) = {
+	.name = "sunxi_de"
+};
+
 /*
  * Simplefb support.
  */
 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB)
 int sunxi_simplefb_setup(void *blob)
 {
-	static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
+	struct sunxi_display_priv *sunxi_display;
+	struct video_priv *uc_priv;
+	struct udevice *de;
 	int offset, ret;
 	u64 start, size;
 	const char *pipeline = NULL;
@@ -1242,7 +1267,19 @@
 #define PIPELINE_PREFIX
 #endif
 
-	switch (sunxi_display.monitor) {
+	ret = uclass_find_device_by_name(UCLASS_VIDEO, "sunxi_de", &de);
+	if (ret) {
+		printf("DE not present\n");
+		return 0;
+	} else if (!device_active(de)) {
+		printf("DE is present but not probed\n");
+		return 0;
+	}
+
+	uc_priv = dev_get_uclass_priv(de);
+	sunxi_display = dev_get_priv(de);
+
+	switch (sunxi_display->monitor) {
 	case sunxi_monitor_none:
 		return 0;
 	case sunxi_monitor_dvi:
@@ -1280,16 +1317,17 @@
 	 * linux/arch/arm/mm/ioremap.c around line 301.
 	 */
 	start = gd->bd->bi_dram[0].start;
-	size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
+	size = sunxi_display->fb_addr - start;
 	ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
 	if (ret) {
 		eprintf("Cannot setup simplefb: Error reserving memory\n");
 		return ret;
 	}
 
-	ret = fdt_setup_simplefb_node(blob, offset, sunxi_display.fb_addr,
-			graphic_device->winSizeX, graphic_device->winSizeY,
-			graphic_device->plnSizeX, "x8r8g8b8");
+	ret = fdt_setup_simplefb_node(blob, offset, sunxi_display->fb_addr,
+				      uc_priv->xsize, uc_priv->ysize,
+				      VNBYTES(uc_priv->bpix) * uc_priv->xsize,
+				      "x8r8g8b8");
 	if (ret)
 		eprintf("Cannot setup simplefb: Error setting properties\n");
 
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 602ccbe..aa76a8f 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -9,6 +9,19 @@
 	  this option if you want to service enabled watchdog by U-Boot. Disable
 	  this option if you want U-Boot to start watchdog but never service it.
 
+config WATCHDOG_AUTOSTART
+	bool "Automatically start watchdog timer"
+	depends on WDT
+	default y
+	help
+	  Automatically start watchdog timer and start servicing it during
+	  init phase. Enabled by default. Disable this option if you want
+	  to compile U-Boot with CONFIG_WDT support but do not want to
+	  activate watchdog, like when CONFIG_WDT option is disabled. You
+	  would be able to start watchdog manually by 'wdt' command. Useful
+	  when you want to have support for 'wdt' command but do not want
+	  to have watchdog enabled by default.
+
 config WATCHDOG_TIMEOUT_MSECS
 	int "Watchdog timeout in msec"
 	default 128000 if ARCH_MX25 || ARCH_MX31 || ARCH_MX5 || ARCH_MX6
diff --git a/drivers/watchdog/designware_wdt.c b/drivers/watchdog/designware_wdt.c
index c020324..9e54871 100644
--- a/drivers/watchdog/designware_wdt.c
+++ b/drivers/watchdog/designware_wdt.c
@@ -9,7 +9,6 @@
 #include <reset.h>
 #include <wdt.h>
 #include <asm/io.h>
-#include <asm/utils.h>
 #include <linux/bitops.h>
 
 #define DW_WDT_CR	0x00
@@ -35,7 +34,7 @@
 	signed int i;
 
 	/* calculate the timeout range value */
-	i = log_2_n_round_up(timeout * clk_khz) - 16;
+	i = fls(timeout * clk_khz - 1) - 16;
 	i = clamp(i, 0, 15);
 
 	writel(i | (i << 4), base + DW_WDT_TORR);
@@ -130,27 +129,39 @@
 	if (ret)
 		return ret;
 
+	ret = clk_enable(&clk);
+	if (ret)
+		goto err;
+
 	priv->clk_khz = clk_get_rate(&clk) / 1000;
-	if (!priv->clk_khz)
-		return -EINVAL;
+	if (!priv->clk_khz) {
+		ret = -EINVAL;
+		goto err;
+	}
 #else
 	priv->clk_khz = CONFIG_DW_WDT_CLOCK_KHZ;
 #endif
 
-#if CONFIG_IS_ENABLED(DM_RESET)
-	struct reset_ctl_bulk resets;
+	if (CONFIG_IS_ENABLED(DM_RESET)) {
+		struct reset_ctl_bulk resets;
 
-	ret = reset_get_bulk(dev, &resets);
-	if (ret)
-		return ret;
+		ret = reset_get_bulk(dev, &resets);
+		if (ret)
+			goto err;
 
-	ret = reset_deassert_bulk(&resets);
-	if (ret)
-		return ret;
-#endif
+		ret = reset_deassert_bulk(&resets);
+		if (ret)
+			goto err;
+	}
 
 	/* reset to disable the watchdog */
 	return designware_wdt_stop(dev);
+
+err:
+#if CONFIG_IS_ENABLED(CLK)
+	clk_free(&clk);
+#endif
+	return ret;
 }
 
 static const struct wdt_ops designware_wdt_ops = {
diff --git a/drivers/watchdog/imx_watchdog.c b/drivers/watchdog/imx_watchdog.c
index 5e0a096..3586246 100644
--- a/drivers/watchdog/imx_watchdog.c
+++ b/drivers/watchdog/imx_watchdog.c
@@ -44,7 +44,7 @@
 
 #if !defined(CONFIG_IMX_WATCHDOG) || \
     (defined(CONFIG_IMX_WATCHDOG) && !CONFIG_IS_ENABLED(WDT))
-void __attribute__((weak)) reset_cpu(ulong addr)
+void __attribute__((weak)) reset_cpu(void)
 {
 	struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
 
diff --git a/drivers/watchdog/ulp_wdog.c b/drivers/watchdog/ulp_wdog.c
index 7533fc6..6f63b11 100644
--- a/drivers/watchdog/ulp_wdog.c
+++ b/drivers/watchdog/ulp_wdog.c
@@ -77,7 +77,7 @@
 	hw_watchdog_reset();
 }
 
-void reset_cpu(ulong addr)
+void reset_cpu(void)
 {
 	struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
 
diff --git a/drivers/watchdog/wdt-uclass.c b/drivers/watchdog/wdt-uclass.c
index 28f7918..0603ffb 100644
--- a/drivers/watchdog/wdt-uclass.c
+++ b/drivers/watchdog/wdt-uclass.c
@@ -27,6 +27,7 @@
 int initr_watchdog(void)
 {
 	u32 timeout = WATCHDOG_TIMEOUT_SECS;
+	int ret;
 
 	/*
 	 * Init watchdog: This will call the probe function of the
@@ -50,8 +51,17 @@
 						    4 * reset_period) / 4;
 	}
 
-	wdt_start(gd->watchdog_dev, timeout * 1000, 0);
-	gd->flags |= GD_FLG_WDT_READY;
+	if (!CONFIG_IS_ENABLED(WATCHDOG_AUTOSTART)) {
+		printf("WDT:   Not starting\n");
+		return 0;
+	}
+
+	ret = wdt_start(gd->watchdog_dev, timeout * 1000, 0);
+	if (ret != 0) {
+		printf("WDT:   Failed to start\n");
+		return 0;
+	}
+
 	printf("WDT:   Started with%s servicing (%ds timeout)\n",
 	       IS_ENABLED(CONFIG_WATCHDOG) ? "" : "out", timeout);
 
@@ -61,21 +71,31 @@
 int wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
 {
 	const struct wdt_ops *ops = device_get_ops(dev);
+	int ret;
 
 	if (!ops->start)
 		return -ENOSYS;
 
-	return ops->start(dev, timeout_ms, flags);
+	ret = ops->start(dev, timeout_ms, flags);
+	if (ret == 0)
+		gd->flags |= GD_FLG_WDT_READY;
+
+	return ret;
 }
 
 int wdt_stop(struct udevice *dev)
 {
 	const struct wdt_ops *ops = device_get_ops(dev);
+	int ret;
 
 	if (!ops->stop)
 		return -ENOSYS;
 
-	return ops->stop(dev);
+	ret = ops->stop(dev);
+	if (ret == 0)
+		gd->flags &= ~GD_FLG_WDT_READY;
+
+	return ret;
 }
 
 int wdt_reset(struct udevice *dev)
diff --git a/dts/Kconfig b/dts/Kconfig
index 00ac29a..99ce75e 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -338,6 +338,7 @@
 	bool "Generate platform data for use in SPL"
 	depends on SPL_OF_CONTROL
 	select DTOC
+	select SPL_OF_PLATDATA_DRIVER_RT if !SPL_OF_PLATDATA_INST
 	help
 	  For very constrained SPL environments the overhead of decoding
 	  device tree nodes and converting their contents into platform data
@@ -355,19 +356,58 @@
 	  compatible string, then adding platform data and U_BOOT_DRVINFO
 	  declarations for each node. See of-plat.txt for more information.
 
+if SPL_OF_PLATDATA
+
 config SPL_OF_PLATDATA_PARENT
 	bool "Support parent information in devices"
-	depends on SPL_OF_PLATDATA
 	default y
 	help
 	  Generally it is useful to be able to access the parent of a device
 	  with of-platdata. To save space this can be disabled, but in that
 	  case dev_get_parent() will always return NULL;
 
+config SPL_OF_PLATDATA_INST
+	bool "Declare devices at build time"
+	help
+	  Declare devices as udevice instances so that they do not need to be
+	  bound when U-Boot starts. This can save time and code space.
+
+config SPL_OF_PLATDATA_NO_BIND
+	bool "Don't allow run-time binding of devices"
+	depends on SPL_OF_PLATDATA_INST
+	default y
+	help
+	  This removes the ability to bind devices at run time, thus saving
+	  some code space in U-Boot. This can be disabled if binding is needed,
+	  at the code of some code size increase.
+
+config SPL_OF_PLATDATA_RT
+	bool "Use a separate struct for device runtime data"
+	depends on SPL_OF_PLATDATA_INST
+	default y
+	help
+	  For systems running SPL from read-only memory it is convenient to
+	  separate out the runtime information, so that the devices don't need
+	  to be copied before being used. This moves the read-write parts of
+	  struct udevice (at present just the flags) into a separate struct,
+	  which is allocated at runtime.
+
+config SPL_OF_PLATDATA_DRIVER_RT
+	bool
+	help
+	  Use a separate struct for driver runtime data.
+
+	  This enables the driver_rt information, used with of-platdata when
+	  of-platdata-inst is not used. It allows finding devices by their
+	  driver data.
+
+endif
+
 config TPL_OF_PLATDATA
 	bool "Generate platform data for use in TPL"
 	depends on TPL_OF_CONTROL
 	select DTOC
+	select TPL_OF_PLATDATA_DRIVER_RT if !TPL_OF_PLATDATA_INST
 	help
 	  For very constrained SPL environments the overhead of decoding
 	  device tree nodes and converting their contents into platform data
@@ -385,13 +425,52 @@
 	  compatible string, then adding platform data and U_BOOT_DRVINFO
 	  declarations for each node. See of-plat.txt for more information.
 
+if TPL_OF_PLATDATA
+
 config TPL_OF_PLATDATA_PARENT
 	bool "Support parent information in devices"
-	depends on TPL_OF_PLATDATA
 	default y
 	help
 	  Generally it is useful to be able to access the parent of a device
 	  with of-platdata. To save space this can be disabled, but in that
 	  case dev_get_parent() will always return NULL;
 
+config TPL_OF_PLATDATA_INST
+	bool "Declare devices at build time"
+
+	help
+	  Declare devices as udevice instances so that they do not need to be
+	  bound when U-Boot starts. This can save time and code space.
+
+config TPL_OF_PLATDATA_NO_BIND
+	bool "Don't allow run-time binding of devices"
+	depends on TPL_OF_PLATDATA_INST
+	default y
+	help
+	  This removes the ability to bind devices at run time, thus saving
+	  some code space in U-Boot. This can be disabled if binding is needed,
+	  at the code of some code size increase.
+
+config TPL_OF_PLATDATA_RT
+	bool "Use a separate struct for device runtime data"
+	depends on TPL_OF_PLATDATA_INST
+	default y
+	help
+	  For systems running TPL from read-only memory it is convenient to
+	  separate out the runtime information, so that the devices don't need
+	  to be copied before being used. This moves the read-write parts of
+	  struct udevice (at present just the flags) into a separate struct,
+	  which is allocated at runtime.
+
+config TPL_OF_PLATDATA_DRIVER_RT
+	bool
+	help
+	  Use a separate struct for driver runtime data.
+
+	  This enables the driver_rt information, used with of-platdata when
+	  of-platdata-inst is not used. It allows finding devices by their
+	  driver data.
+
+endif
+
 endmenu
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c
index 9007aa7..415ea28 100644
--- a/fs/cbfs/cbfs.c
+++ b/fs/cbfs/cbfs.c
@@ -79,6 +79,57 @@
 	dest->offset = be32_to_cpu(src->offset);
 }
 
+/**
+ * fill_node() - Fill a node struct with information from the CBFS
+ *
+ * @node: Node to fill
+ * @start: Pointer to the start of the CBFS file in memory
+ * @header: Pointer to the header information (in our enddianess)
+ * @return 0 if OK, -EBADF if the header is too small
+ */
+static int fill_node(struct cbfs_cachenode *node, void *start,
+		     struct cbfs_fileheader *header)
+{
+	uint name_len;
+	uint offset;
+
+	/* Check the header is large enough */
+	if (header->offset < sizeof(struct cbfs_fileheader))
+		return -EBADF;
+
+	node->next = NULL;
+	node->type = header->type;
+	node->data = start + header->offset;
+	node->data_length = header->len;
+	name_len = header->offset - sizeof(struct cbfs_fileheader);
+	node->name = start + sizeof(struct cbfs_fileheader);
+	node->name_length = name_len;
+	node->attr_offset = header->attributes_offset;
+	node->comp_algo = CBFS_COMPRESS_NONE;
+	node->decomp_size = 0;
+
+	for (offset = node->attr_offset; offset < header->offset;) {
+		const struct cbfs_file_attribute *attr;
+		uint tag, len;
+
+		attr = start + offset;
+		tag = be32_to_cpu(attr->tag);
+		len = be32_to_cpu(attr->len);
+		if (tag == CBFS_FILE_ATTR_TAG_COMPRESSION) {
+			struct cbfs_file_attr_compression *comp;
+
+			comp = start + offset;
+			node->comp_algo = be32_to_cpu(comp->compression);
+			node->decomp_size =
+				be32_to_cpu(comp->decompressed_size);
+		}
+
+		offset += len;
+	}
+
+	return 0;
+}
+
 /*
  * Given a starting position in memory, scan forward, bounded by a size, and
  * find the next valid CBFS file. No memory is allocated by this function. The
@@ -87,7 +138,7 @@
  * @param start		The location in memory to start from.
  * @param size		The size of the memory region to search.
  * @param align		The alignment boundaries to check on.
- * @param new_node	A pointer to the file structure to load.
+ * @param node	A pointer to the file structure to load.
  * @param used		A pointer to the count of of bytes scanned through,
  *			including the file if one is found.
  *
@@ -95,7 +146,7 @@
  *	is found.
  */
 static int file_cbfs_next_file(struct cbfs_priv *priv, void *start, int size,
-			       int align, struct cbfs_cachenode *new_node,
+			       int align, struct cbfs_cachenode *node,
 			       int *used)
 {
 	struct cbfs_fileheader header;
@@ -104,8 +155,7 @@
 
 	while (size >= align) {
 		const struct cbfs_fileheader *file_header = start;
-		u32 name_len;
-		u32 step;
+		int ret;
 
 		/* Check if there's a file here. */
 		if (memcmp(good_file_magic, &file_header->magic,
@@ -117,25 +167,13 @@
 		}
 
 		swap_file_header(&header, file_header);
-		if (header.offset < sizeof(struct cbfs_fileheader)) {
+		ret = fill_node(node, start, &header);
+		if (ret) {
 			priv->result = CBFS_BAD_FILE;
-			return -EBADF;
+			return log_msg_ret("fill", ret);
 		}
-		new_node->next = NULL;
-		new_node->type = header.type;
-		new_node->data = start + header.offset;
-		new_node->data_length = header.len;
-		name_len = header.offset - sizeof(struct cbfs_fileheader);
-		new_node->name = (char *)file_header +
-				sizeof(struct cbfs_fileheader);
-		new_node->name_length = name_len;
-		new_node->attributes_offset = header.attributes_offset;
 
-		step = header.len;
-		if (step % align)
-			step = step + align - step % align;
-
-		*used += step;
+		*used += ALIGN(header.len, align);
 		return 0;
 	}
 
@@ -146,7 +184,7 @@
 static int file_cbfs_fill_cache(struct cbfs_priv *priv, int size, int align)
 {
 	struct cbfs_cachenode *cache_node;
-	struct cbfs_cachenode *new_node;
+	struct cbfs_cachenode *node;
 	struct cbfs_cachenode **cache_tail = &priv->file_cache;
 	void *start;
 
@@ -164,21 +202,20 @@
 		int used;
 		int ret;
 
-		new_node = (struct cbfs_cachenode *)
-				malloc(sizeof(struct cbfs_cachenode));
-		if (!new_node)
+		node = malloc(sizeof(struct cbfs_cachenode));
+		if (!node)
 			return -ENOMEM;
-		ret = file_cbfs_next_file(priv, start, size, align, new_node,
+		ret = file_cbfs_next_file(priv, start, size, align, node,
 					  &used);
 
 		if (ret < 0) {
-			free(new_node);
+			free(node);
 			if (ret == -ENOENT)
 				break;
 			return ret;
 		}
-		*cache_tail = new_node;
-		cache_tail = &new_node->next;
+		*cache_tail = node;
+		cache_tail = &node->next;
 
 		size -= used;
 		start += used;
@@ -276,18 +313,26 @@
 	return cbfs_init(&cbfs_s, end_of_rom);
 }
 
-int cbfs_init_mem(ulong base, struct cbfs_priv **privp)
+int cbfs_init_mem(ulong base, ulong size, bool require_hdr,
+		  struct cbfs_priv **privp)
 {
 	struct cbfs_priv priv_s, *priv = &priv_s;
 	int ret;
 
 	/*
-	 * Use a local variable to start with until we know that the CBFS is
-	 * valid.
+	 * Use a local variable to start with until we know that the * CBFS is
+	 * valid. Note that size is detected from the header, if present,
+	 * meaning the parameter is ignored.
 	 */
 	ret = cbfs_load_header_ptr(priv, base);
-	if (ret)
-		return ret;
+	if (ret) {
+		if (require_hdr || size == CBFS_SIZE_UNKNOWN)
+			return ret;
+		memset(priv, '\0', sizeof(struct cbfs_priv));
+		priv->header.rom_size = size;
+		priv->header.align = CBFS_ALIGN_SIZE;
+		priv->start = (void *)base;
+	}
 
 	ret = file_cbfs_fill_cache(priv, priv->header.rom_size,
 				   priv->header.align);
@@ -317,6 +362,17 @@
 	}
 }
 
+const struct cbfs_cachenode *cbfs_get_first(const struct cbfs_priv *priv)
+{
+	return priv->file_cache;
+}
+
+void cbfs_get_next(const struct cbfs_cachenode **filep)
+{
+	if (*filep)
+		*filep = (*filep)->next;
+}
+
 const struct cbfs_cachenode *file_cbfs_get_first(void)
 {
 	struct cbfs_priv *priv = &cbfs_s;
diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c
index a98745c..1818e81 100644
--- a/fs/jffs2/jffs2_1pass.c
+++ b/fs/jffs2/jffs2_1pass.c
@@ -180,6 +180,7 @@
 	struct mtd_info *mtd;
 	u32 bytes_read = 0;
 	size_t retlen;
+	size_t toread;
 	int cpy_bytes;
 
 	mtd = get_nand_dev_by_index(id->num);
@@ -187,8 +188,12 @@
 		return -1;
 
 	while (bytes_read < size) {
+		retlen = NAND_CACHE_SIZE;
+		if( nand_cache_off + retlen > mtd->size )
+			retlen = mtd->size - nand_cache_off;
+
 		if ((off + bytes_read < nand_cache_off) ||
-		    (off + bytes_read >= nand_cache_off+NAND_CACHE_SIZE)) {
+		    (off + bytes_read >= nand_cache_off + retlen)) {
 			nand_cache_off = (off + bytes_read) & NAND_PAGE_MASK;
 			if (!nand_cache) {
 				/* This memory never gets freed but 'cause
@@ -201,16 +206,20 @@
 				}
 			}
 
-			retlen = NAND_CACHE_SIZE;
+			toread = NAND_CACHE_SIZE;
+			if( nand_cache_off + toread > mtd->size )
+				toread = mtd->size - nand_cache_off;
+
+			retlen = toread;
 			if (nand_read(mtd, nand_cache_off,
 				      &retlen, nand_cache) < 0 ||
-					retlen != NAND_CACHE_SIZE) {
+					retlen != toread) {
 				printf("read_nand_cached: error reading nand off %#x size %d bytes\n",
-						nand_cache_off, NAND_CACHE_SIZE);
+						nand_cache_off, toread);
 				return -1;
 			}
 		}
-		cpy_bytes = nand_cache_off + NAND_CACHE_SIZE - (off + bytes_read);
+		cpy_bytes = nand_cache_off + retlen - (off + bytes_read);
 		if (cpy_bytes > size - bytes_read)
 			cpy_bytes = size - bytes_read;
 		memcpy(buf + bytes_read,
@@ -283,11 +292,16 @@
 {
 	u32 bytes_read = 0;
 	size_t retlen;
+	size_t toread;
 	int cpy_bytes;
 
 	while (bytes_read < size) {
+		retlen = ONENAND_CACHE_SIZE;
+		if( onenand_cache_off + retlen > onenand_mtd.size )
+			retlen = onenand_mtd.size - onenand_cache_off;
+
 		if ((off + bytes_read < onenand_cache_off) ||
-		    (off + bytes_read >= onenand_cache_off + ONENAND_CACHE_SIZE)) {
+		    (off + bytes_read >= onenand_cache_off + retlen)) {
 			onenand_cache_off = (off + bytes_read) & ONENAND_PAGE_MASK;
 			if (!onenand_cache) {
 				/* This memory never gets freed but 'cause
@@ -300,16 +314,19 @@
 				}
 			}
 
-			retlen = ONENAND_CACHE_SIZE;
+			toread = ONENAND_CACHE_SIZE;
+			if( onenand_cache_off + toread > onenand_mtd.size )
+				toread = onenand_mtd.size - onenand_cache_off;
+			retlen = toread;
 			if (onenand_read(&onenand_mtd, onenand_cache_off, retlen,
 						&retlen, onenand_cache) < 0 ||
-					retlen != ONENAND_CACHE_SIZE) {
+					retlen != toread) {
 				printf("read_onenand_cached: error reading nand off %#x size %d bytes\n",
-					onenand_cache_off, ONENAND_CACHE_SIZE);
+					onenand_cache_off, toread);
 				return -1;
 			}
 		}
-		cpy_bytes = onenand_cache_off + ONENAND_CACHE_SIZE - (off + bytes_read);
+		cpy_bytes = onenand_cache_off + retlen - (off + bytes_read);
 		if (cpy_bytes > size - bytes_read)
 			cpy_bytes = size - bytes_read;
 		memcpy(buf + bytes_read,
@@ -1276,6 +1293,7 @@
 							&spi->version);
 						b->ino = sum_get_unaligned32(
 							&spi->inode);
+						b->datacrc = CRC_UNKNOWN;
 					}
 
 					sp += JFFS2_SUMMARY_INODE_SIZE;
@@ -1297,6 +1315,7 @@
 							&spd->version);
 						b->pino = sum_get_unaligned32(
 							&spd->pino);
+						b->datacrc = CRC_UNKNOWN;
 					}
 
 					sp += JFFS2_SUMMARY_DIRENT_SIZE(
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index b6a9991..e1a5f4b 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -215,10 +215,20 @@
 	 * @uclass_root_s.
 	 */
 	struct list_head *uclass_root;
-# if CONFIG_IS_ENABLED(OF_PLATDATA)
+# if CONFIG_IS_ENABLED(OF_PLATDATA_DRIVER_RT)
 	/** @dm_driver_rt: Dynamic info about the driver */
 	struct driver_rt *dm_driver_rt;
 # endif
+#if CONFIG_IS_ENABLED(OF_PLATDATA_RT)
+	/** @dm_udevice_rt: Dynamic info about the udevice */
+	struct udevice_rt *dm_udevice_rt;
+	/**
+	 * @dm_priv_base: Base address of the priv/plat region used when
+	 * udevices and uclasses are in read-only memory. This is NULL if not
+	 * used
+	 */
+	void *dm_priv_base;
+# endif
 #endif
 #ifdef CONFIG_TIMER
 	/**
@@ -410,6 +420,12 @@
 	 * This value is used as logging level for continuation messages.
 	 */
 	int logl_prev;
+	/**
+	 * @log_cont: Previous log line did not finished wtih \n
+	 *
+	 * This allows for chained log messages on the same line
+	 */
+	bool log_cont;
 #endif
 #if CONFIG_IS_ENABLED(BLOBLIST)
 	/**
@@ -477,7 +493,7 @@
 #define gd_set_of_root(_root)
 #endif
 
-#if CONFIG_IS_ENABLED(OF_PLATDATA)
+#if CONFIG_IS_ENABLED(OF_PLATDATA_DRIVER_RT)
 #define gd_set_dm_driver_rt(dyn)	gd->dm_driver_rt = dyn
 #define gd_dm_driver_rt()		gd->dm_driver_rt
 #else
@@ -485,6 +501,18 @@
 #define gd_dm_driver_rt()		NULL
 #endif
 
+#if CONFIG_IS_ENABLED(OF_PLATDATA_RT)
+#define gd_set_dm_udevice_rt(dyn)	gd->dm_udevice_rt = dyn
+#define gd_dm_udevice_rt()		gd->dm_udevice_rt
+#define gd_set_dm_priv_base(dyn)	gd->dm_priv_base = dyn
+#define gd_dm_priv_base()		gd->dm_priv_base
+#else
+#define gd_set_dm_udevice_rt(dyn)
+#define gd_dm_udevice_rt()		NULL
+#define gd_set_dm_priv_base(dyn)
+#define gd_dm_priv_base()		NULL
+#endif
+
 #ifdef CONFIG_GENERATE_ACPI_TABLE
 #define gd_acpi_ctx()		gd->acpi_ctx
 #else
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 82294cb..2cb0500 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -128,6 +128,12 @@
 #define GPIOD_PULL_UP		BIT(7)	/* GPIO has pull-up enabled */
 #define GPIOD_PULL_DOWN		BIT(8)	/* GPIO has pull-down enabled */
 
+/* Flags for updating the above */
+#define GPIOD_MASK_DIR		(GPIOD_IS_OUT | GPIOD_IS_IN | \
+					GPIOD_IS_OUT_ACTIVE)
+#define GPIOD_MASK_DSTYPE	(GPIOD_OPEN_DRAIN | GPIOD_OPEN_SOURCE)
+#define GPIOD_MASK_PULL		(GPIOD_PULL_UP | GPIOD_PULL_DOWN)
+
 	uint offset;		/* GPIO offset within the device */
 	/*
 	 * We could consider adding the GPIO label in here. Possibly we could
@@ -135,12 +141,6 @@
 	 */
 };
 
-/* helper to compute the value of the gpio output */
-#define GPIOD_FLAGS_OUTPUT_MASK (GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE)
-#define GPIOD_FLAGS_OUTPUT(flags) \
-	(((((flags) & GPIOD_FLAGS_OUTPUT_MASK) == GPIOD_IS_OUT_ACTIVE) || \
-	  (((flags) & GPIOD_FLAGS_OUTPUT_MASK) == GPIOD_ACTIVE_LOW)))
-
 /**
  * dm_gpio_is_valid() - Check if a GPIO is valid
  *
@@ -260,10 +260,32 @@
 struct dm_gpio_ops {
 	int (*request)(struct udevice *dev, unsigned offset, const char *label);
 	int (*rfree)(struct udevice *dev, unsigned int offset);
+
+	/**
+	 * direction_input() - deprecated
+	 *
+	 * Equivalent to set_flags(...GPIOD_IS_IN)
+	 */
 	int (*direction_input)(struct udevice *dev, unsigned offset);
+
+	/**
+	 * direction_output() - deprecated
+	 *
+	 * Equivalent to set_flags(...GPIOD_IS_OUT) with GPIOD_IS_OUT_ACTIVE
+	 * also set if @value
+	 */
 	int (*direction_output)(struct udevice *dev, unsigned offset,
 				int value);
+
 	int (*get_value)(struct udevice *dev, unsigned offset);
+
+	/**
+	 * set_value() - Sets the GPIO value of an output
+	 *
+	 * If the driver provides an @set_flags() method then that is used
+	 * in preference to this, with GPIOD_IS_OUT_ACTIVE set according to
+	 * @value.
+	 */
 	int (*set_value)(struct udevice *dev, unsigned offset, int value);
 	/**
 	 * get_function() Get the GPIO function
@@ -301,35 +323,54 @@
 		     struct ofnode_phandle_args *args);
 
 	/**
-	 * set_dir_flags() - Set GPIO dir flags
+	 * set_flags() - Adjust GPIO flags
 	 *
 	 * This function should set up the GPIO configuration according to the
-	 * information provide by the direction flags bitfield.
+	 * information provided by @flags.
 	 *
-	 * This method is optional.
+	 * If any flags cannot be set (e.g. the driver or hardware does not
+	 * support them or this particular GPIO does not have the requested
+	 * feature), the driver should return -EINVAL.
+	 *
+	 * The uclass checks that flags do not obviously conflict (e.g. input
+	 * and output). If the driver finds other conflicts it should return
+	 * -ERECALLCONFLICT
+	 *
+	 * Note that GPIOD_ACTIVE_LOW should be ignored, since the uclass
+	 * adjusts for it automatically. For example, for an output GPIO,
+	 * GPIOD_ACTIVE_LOW causes GPIOD_IS_OUT_ACTIVE to be inverted by the
+	 * uclass, so the driver always sees the value that should be set at the
+	 * pin (1=high, 0=low).
+	 *
+	 * This method is required and should be implemented by new drivers. At
+	 * some point, it will supersede direction_input() and
+	 * direction_output(), which wil be removed.
 	 *
 	 * @dev:	GPIO device
 	 * @offset:	GPIO offset within that device
-	 * @flags:	GPIO configuration to use
-	 * @return 0 if OK, -ve on error
+	 * @flags:	New flags value (GPIOD_...)
+	 *
+	 * @return 0 if OK, -EINVAL if unsupported, -ERECALLCONFLICT if flags
+	 *	conflict in some *	non-obvious way and were not applied,
+	 *	other -ve on error
 	 */
-	int (*set_dir_flags)(struct udevice *dev, unsigned int offset,
-			     ulong flags);
+	int (*set_flags)(struct udevice *dev, unsigned int offset, ulong flags);
 
 	/**
-	 * get_dir_flags() - Get GPIO dir flags
+	 * get_flags() - Get GPIO flags
 	 *
-	 * This function return the GPIO direction flags used.
+	 * This function return the GPIO flags used. It should read this from
+	 * the hardware directly.
 	 *
 	 * This method is optional.
 	 *
 	 * @dev:	GPIO device
 	 * @offset:	GPIO offset within that device
-	 * @flags:	place to put the used direction flags by GPIO
+	 * @flagsp:	place to put the current flags value
 	 * @return 0 if OK, -ve on error
 	 */
-	int (*get_dir_flags)(struct udevice *dev, unsigned int offset,
-			     ulong *flags);
+	int (*get_flags)(struct udevice *dev, unsigned int offset,
+			 ulong *flagsp);
 
 #if CONFIG_IS_ENABLED(ACPIGEN)
 	/**
@@ -457,6 +498,31 @@
 int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count);
 
 /**
+ * dm_gpio_get_values_as_int_base3() - Create a base-3 int from a list of GPIOs
+ *
+ * This uses pull-ups/pull-downs to figure out whether a GPIO line is externally
+ * pulled down, pulled up or floating. This allows three different strap values
+ * for each pin:
+ *    0 : external pull-down
+ *    1 : external pull-up
+ *    2 : floating
+ *
+ * With this it is possible to obtain more combinations from the same number of
+ * strapping pins, when compared to dm_gpio_get_values_as_int(). The external
+ * pull resistors should be made stronger that the internal SoC pull resistors,
+ * for this to work.
+ *
+ * With 2 pins, 6 combinations are possible, compared with 4
+ * With 3 pins, 27 are possible, compared with 8
+ *
+ * @desc_list: List of GPIOs to collect
+ * @count: Number of GPIOs
+ * @return resulting integer value, or -ve on error
+ */
+int dm_gpio_get_values_as_int_base3(struct gpio_desc *desc_list,
+				    int count);
+
+/**
  * gpio_claim_vector() - claim a number of GPIOs for input
  *
  * @gpio_num_array:	array of gpios to claim, terminated by -1
@@ -652,6 +718,25 @@
 int dm_gpio_set_dir(struct gpio_desc *desc);
 
 /**
+ * dm_gpio_clrset_flags() - Update flags
+ *
+ * This updates the flags as directled. Note that desc->flags is updated by this
+ * function on success. If any changes cannot be made, best efforts are made.
+ *
+ * By use of @clr and @set any of flags can be individually updated, or left
+ * alone
+ *
+ * @desc:	GPIO description containing device, offset and flags,
+ *		previously returned by gpio_request_by_name()
+ * @clr:	Flags to clear (GPIOD_...)
+ * @set:	Flags to set (GPIOD_...)
+ * @return 0 if OK, -EINVAL if the flags had obvious conflicts,
+ * -ERECALLCONFLICT if there was a non-obvious hardware conflict when attempting
+ * to set the flags
+ */
+int dm_gpio_clrset_flags(struct gpio_desc *desc, ulong clr, ulong set);
+
+/**
  * dm_gpio_set_dir_flags() - Set direction using description and added flags
  *
  * This sets up the direction according to the provided flags and the GPIO
@@ -666,16 +751,31 @@
 int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags);
 
 /**
- * dm_gpio_get_dir_flags() - Get direction flags
+ * dm_gpios_clrset_flags() - Sets flags for a set of GPIOs
  *
- * read the current direction flags
+ * This clears and sets flags individually for each GPIO.
+ *
+ * @desc:	List of GPIOs to update
+ * @count:	Number of GPIOs in the list
+ * @clr:	Flags to clear (GPIOD_...), e.g. GPIOD_MASK_DIR if you are
+ *		changing the direction
+ * @set:	Flags to set (GPIOD_...)
+ * @return 0 if OK, -ve on error
+ */
+int dm_gpios_clrset_flags(struct gpio_desc *desc, int count, ulong clr,
+			  ulong set);
+
+/**
+ * dm_gpio_get_flags() - Get flags
+ *
+ * Read the current flags
  *
  * @desc:	GPIO description containing device, offset and flags,
  *		previously returned by gpio_request_by_name()
  * @flags:	place to put the used flags
  * @return 0 if OK, -ve on error, in which case desc->flags is not updated
  */
-int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags);
+int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flags);
 
 /**
  * gpio_get_number() - Get the global GPIO number of a GPIO
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 0577238..267f1db 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -28,6 +28,9 @@
 extern char __efi_var_file_begin[];
 extern char __efi_var_file_end[];
 
+/* Private data used by of-platdata devices/uclasses */
+extern char __priv_data_start[], __priv_data_end[];
+
 /* Start and end of .ctors section - used for constructor calls. */
 extern char __ctors_start[], __ctors_end[];
 
diff --git a/include/cbfs.h b/include/cbfs.h
index 5f296d6..ae94f1d 100644
--- a/include/cbfs.h
+++ b/include/cbfs.h
@@ -9,6 +9,8 @@
 #include <compiler.h>
 #include <linux/compiler.h>
 
+struct cbfs_priv;
+
 enum cbfs_result {
 	CBFS_SUCCESS = 0,
 	CBFS_NOT_INITIALIZED,
@@ -42,6 +44,8 @@
 
 enum {
 	CBFS_HEADER_MAGIC	= 0x4f524243,
+	CBFS_SIZE_UNKNOWN	= 0xffffffff,
+	CBFS_ALIGN_SIZE		= 0x40,
 };
 
 /**
@@ -68,6 +72,52 @@
 	/* offset to struct cbfs_file_attribute or 0 */
 	u32 attributes_offset;
 	u32 offset;
+	char filename[];
+} __packed;
+
+/**
+ * These are standard values for the known compression alogrithms that coreboot
+ * knows about for stages and payloads.  Of course, other CBFS users can use
+ * whatever values they want, as long as they understand them.
+ */
+#define CBFS_COMPRESS_NONE  0
+#define CBFS_COMPRESS_LZMA  1
+#define CBFS_COMPRESS_LZ4   2
+
+/*
+ * Depending on how the header was initialized, it may be backed with 0x00 or
+ * 0xff, so support both
+ */
+#define CBFS_FILE_ATTR_TAG_UNUSED 0
+#define CBFS_FILE_ATTR_TAG_UNUSED2 0xffffffff
+#define CBFS_FILE_ATTR_TAG_COMPRESSION 0x42435a4c
+#define CBFS_FILE_ATTR_TAG_HASH 0x68736148
+
+/*
+ * The common fields of extended cbfs file attributes. Attributes are expected
+ * to start with tag/len, then append their specific fields
+ */
+struct cbfs_file_attribute {
+	u32 tag;
+	/* len covers the whole structure, incl. tag and len */
+	u32 len;
+	u8 data[0];
+} __packed;
+
+struct cbfs_file_attr_compression {
+	u32 tag;
+	u32 len;
+	/* whole file compression format. 0 if no compression. */
+	u32 compression;
+	u32 decompressed_size;
+} __packed;
+
+struct cbfs_file_attr_hash {
+	u32 tag;
+	u32 len;
+	u32 hash_type;
+	/* hash_data is len - sizeof(struct) bytes */
+	u8  hash_data[];
 } __packed;
 
 struct cbfs_cachenode {
@@ -77,7 +127,9 @@
 	u32 type;
 	u32 data_length;
 	u32 name_length;
-	u32 attributes_offset;
+	u32 attr_offset;
+	u32 comp_algo;
+	u32 decomp_size;
 };
 
 /**
@@ -111,6 +163,21 @@
 const struct cbfs_header *file_cbfs_get_header(void);
 
 /**
+ * cbfs_get_first() - Get the first file in a CBFS
+ *
+ * @return pointer to first file, or NULL if it is empty
+ */
+const struct cbfs_cachenode *cbfs_get_first(const struct cbfs_priv *priv);
+
+/**
+ * cbfs_get_next() - Get the next file in a CBFS
+ *
+ * @filep: Pointer to current file; updated to point to the next file, if any,
+ *	else NULL
+ */
+void cbfs_get_next(const struct cbfs_cachenode **filep);
+
+/**
  * file_cbfs_get_first() - Get a handle for the first file in CBFS.
  *
  * @return A handle for the first file in CBFS, NULL on error.
@@ -133,8 +200,6 @@
  */
 const struct cbfs_cachenode *file_cbfs_find(const char *name);
 
-struct cbfs_priv;
-
 /**
  * cbfs_find_file() - Find a file in a given CBFS
  *
@@ -149,11 +214,13 @@
  * cbfs_init_mem() - Set up a new CBFS
  *
  * @base: Base address of CBFS
+ * @size: Size of CBFS if known, else CBFS_SIZE_UNKNOWN
+ * @require_header: true to read a header at the start, false to not require one
  * @cbfsp: Returns a pointer to CBFS on success
  * @return 0 if OK, -ve on error
  */
-int cbfs_init_mem(ulong base, struct cbfs_priv **privp);
-
+int cbfs_init_mem(ulong base, ulong size, bool require_hdr,
+		  struct cbfs_priv **privp);
 
 /***************************************************************************/
 /* All of the functions below can be used without first initializing CBFS. */
diff --git a/include/command.h b/include/command.h
index 747f8f8..137cfbc 100644
--- a/include/command.h
+++ b/include/command.h
@@ -389,6 +389,14 @@
 		return 0;						\
 	}
 
+#define _CMD_REMOVE_REP(_name, _cmd)					\
+	int __remove_ ## _name(void)					\
+	{								\
+		if (0)							\
+			_cmd(NULL, 0, 0, NULL, NULL);			\
+		return 0;						\
+	}
+
 #define U_BOOT_CMDREP_MKENT_COMPLETE(_name, _maxargs, _cmd_rep,		\
 				     _usage, _help, _comp)		\
 		{ #_name, _maxargs, 0 ? _cmd_rep : NULL, NULL, _usage,	\
@@ -405,7 +413,7 @@
 
 #define U_BOOT_CMDREP_COMPLETE(_name, _maxargs, _cmd_rep, _usage,	\
 			       _help, _comp)				\
-	_CMD_REMOVE(sub_ ## _name, _cmd_rep)
+	_CMD_REMOVE_REP(sub_ ## _name, _cmd_rep)
 
 #endif /* CONFIG_CMDLINE */
 
diff --git a/include/configs/MPC8349ITX.h b/include/configs/MPC8349ITX.h
index f50cdd7..586c1e9 100644
--- a/include/configs/MPC8349ITX.h
+++ b/include/configs/MPC8349ITX.h
@@ -39,8 +39,6 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
-#define CONFIG_MISC_INIT_F
-
 /*
  * On-board devices
  */
diff --git a/include/configs/apalis_imx6.h b/include/configs/apalis_imx6.h
index 0e81ef9..12de010 100644
--- a/include/configs/apalis_imx6.h
+++ b/include/configs/apalis_imx6.h
@@ -163,10 +163,7 @@
 		"source ${loadaddr}\0" \
 	"splashpos=m,m\0" \
 	"splashimage=" __stringify(CONFIG_LOADADDR) "\0" \
-	"vidargs=mxc_hdmi.only_cea=1 " \
-		"video=mxcfb0:dev=hdmi,1920x1080M@60,if=RGB24 " \
-		"video=mxcfb1:off video=mxcfb2:off video=mxcfb3:off " \
-		"fbmem=32M\0 "
+	"vidargs=mxc_hdmi.only_cea=1 fbmem=32M\0"
 
 /* Miscellaneous configurable options */
 #undef CONFIG_SYS_CBSIZE
diff --git a/include/configs/chromebook_coral.h b/include/configs/chromebook_coral.h
index 6e8e8ec..00760b8 100644
--- a/include/configs/chromebook_coral.h
+++ b/include/configs/chromebook_coral.h
@@ -12,13 +12,13 @@
 
 #define CONFIG_BOOTCOMMAND	\
 	"tpm init; tpm startup TPM2_SU_CLEAR; " \
-	"read mmc 2:2 100000 0 80; setexpr loader *001004f0; " \
+	"read mmc 0:2 100000 0 80; setexpr loader *001004f0; " \
 	"setexpr size *00100518; setexpr blocks $size / 200; " \
-	"read mmc 2:2 100000 80 $blocks; setexpr setup $loader - 1000; " \
+	"read mmc 0:2 100000 80 $blocks; setexpr setup $loader - 1000; " \
 	"setexpr cmdline_ptr $loader - 2000; " \
 	"setexpr.s cmdline *$cmdline_ptr; " \
 	"setexpr cmdline gsub %U \\\\${uuid}; " \
-	"if part uuid mmc 2:2 uuid; then " \
+	"if part uuid mmc 0:2 uuid; then " \
 	"zboot start 100000 0 0 0 $setup cmdline; " \
 	"zboot load; zboot setup; zboot dump; zboot go;" \
 	"fi"
diff --git a/include/configs/clearfog.h b/include/configs/clearfog.h
index 5441da8..c9852a7 100644
--- a/include/configs/clearfog.h
+++ b/include/configs/clearfog.h
@@ -19,11 +19,6 @@
  */
 #define CONFIG_SYS_TCLK		250000000	/* 250MHz */
 
-/*
- * SDIO/MMC Card Configuration
- */
-#define CONFIG_SYS_MMC_BASE		MVEBU_SDIO_BASE
-
 /* USB/EHCI configuration */
 #define CONFIG_EHCI_IS_TDI
 
diff --git a/include/configs/colibri-imx6ull.h b/include/configs/colibri-imx6ull.h
index 2827c17..22ee2ba 100644
--- a/include/configs/colibri-imx6ull.h
+++ b/include/configs/colibri-imx6ull.h
@@ -63,7 +63,7 @@
 		"ubi.fm_autoconvert=1\0" \
 	"ubiboot=run setup; " \
 		"setenv bootargs ${defargs} ${ubiargs} " \
-		"${setupargs} ${vidargs}; echo Booting from NAND...; " \
+		"${setupargs} ${vidargs} ${tdxargs}; echo Booting from NAND...; " \
 		"ubi part ubi &&" \
 		"ubi read ${kernel_addr_r} kernel && " \
 		"ubi read ${fdt_addr_r} dtb && " \
diff --git a/include/configs/colibri_imx6.h b/include/configs/colibri_imx6.h
index c014d6b..804a144 100644
--- a/include/configs/colibri_imx6.h
+++ b/include/configs/colibri_imx6.h
@@ -72,7 +72,6 @@
 
 #ifndef CONFIG_SPL_BUILD
 #define BOOT_TARGET_DEVICES(func) \
-	func(MMC, mmc, 0) \
 	func(MMC, mmc, 1) \
 	func(MMC, mmc, 0) \
 	func(USB, usb, 0) \
@@ -144,8 +143,7 @@
 		"source ${loadaddr}\0" \
 	"splashpos=m,m\0" \
 	"splashimage=" __stringify(CONFIG_LOADADDR) "\0" \
-	"vidargs=video=mxcfb0:dev=lcd,640x480M@60,if=RGB666 " \
-		"video=mxcfb1:off fbmem=8M\0 "
+	"vidargs=fbmem=8M\0"
 
 /* Miscellaneous configurable options */
 #undef CONFIG_SYS_CBSIZE
diff --git a/include/configs/colibri_imx7.h b/include/configs/colibri_imx7.h
index 85dd891..2fffaa3 100644
--- a/include/configs/colibri_imx7.h
+++ b/include/configs/colibri_imx7.h
@@ -110,7 +110,7 @@
 		"ubi.fm_autoconvert=1\0" \
 	"ubiboot=run setup; " \
 		"setenv bootargs ${defargs} ${ubiargs} " \
-		"${setupargs} ${vidargs}; echo Booting from NAND...; " \
+		"${setupargs} ${vidargs} ${tdxargs}; echo Booting from NAND...; " \
 		"ubi part ubi && run m4boot && " \
 		"ubi read ${kernel_addr_r} kernel && " \
 		"ubi read ${fdt_addr_r} dtb && " \
diff --git a/include/configs/controlcenterdc.h b/include/configs/controlcenterdc.h
index f53d48d..869b94b 100644
--- a/include/configs/controlcenterdc.h
+++ b/include/configs/controlcenterdc.h
@@ -25,11 +25,6 @@
 #define CONFIG_LOADADDR 		1000000
 
 /*
- * SDIO/MMC Card Configuration
- */
-#define CONFIG_SYS_MMC_BASE		MVEBU_SDIO_BASE
-
-/*
  * SATA/SCSI/AHCI configuration
  */
 #define CONFIG_SCSI_AHCI_PLAT
diff --git a/include/configs/db-88f6820-gp.h b/include/configs/db-88f6820-gp.h
index d4207be..ed851bc 100644
--- a/include/configs/db-88f6820-gp.h
+++ b/include/configs/db-88f6820-gp.h
@@ -20,11 +20,6 @@
 #define CONFIG_SYS_I2C_SPEED		100000
 
 /*
- * SDIO/MMC Card Configuration
- */
-#define CONFIG_SYS_MMC_BASE		MVEBU_SDIO_BASE
-
-/*
  * SATA/SCSI/AHCI configuration
  */
 #define CONFIG_SCSI_AHCI_PLAT
diff --git a/include/configs/ds109.h b/include/configs/ds109.h
index 1f033ab..35d8536 100644
--- a/include/configs/ds109.h
+++ b/include/configs/ds109.h
@@ -44,7 +44,8 @@
 	"x_bootcmd_kernel=fatload usb 0 0x6400000 uImage\0" \
 	"x_bootargs=console=ttyS0,115200\0"	\
 	"x_bootargs_root=root=/dev/sda2 rootdelay=10\0" \
-	"ipaddr=192.168.1.5\0"
+	"ipaddr=192.168.1.5\0"		\
+	"usb0Mode=host\0"
 
 /*
  * Ethernet Driver configuration
diff --git a/include/configs/ds414.h b/include/configs/ds414.h
index 8aa2d47..c8b4506 100644
--- a/include/configs/ds414.h
+++ b/include/configs/ds414.h
@@ -6,6 +6,9 @@
 #ifndef _CONFIG_SYNOLOGY_DS414_H
 #define _CONFIG_SYNOLOGY_DS414_H
 
+/* Vendor kernel expects this MACH_TYPE */
+#define CONFIG_MACH_TYPE	3036
+
 /*
  * High Level Configuration Options (easy to change)
  */
@@ -74,8 +77,23 @@
 #define CONFIG_DDR_32BIT
 
 /* Default Environment */
-#define CONFIG_BOOTCOMMAND	"sf read ${loadaddr} 0xd0000 0x700000; bootm"
 #define CONFIG_LOADADDR		0x80000
+#define CONFIG_BOOTCOMMAND					\
+	"sf probe; "						\
+	"sf read ${loadaddr} 0xd0000 0x2d0000; "		\
+	"sf read ${ramdisk_addr_r} 0x3a0000 0x430000; "		\
+	"bootm ${loadaddr} ${ramdisk_addr_r}"
+
+#define CONFIG_EXTRA_ENV_SETTINGS				\
+	"initrd_high=0xffffffff\0"				\
+	"ramdisk_addr_r=0x8000000\0"				\
+	"usb0Mode=host\0usb1Mode=host\0usb2Mode=device\0"	\
+	"ethmtu=1500\0eth1mtu=1500\0"				\
+	"update_uboot=sf probe; dhcp; "				\
+		"mw.b ${loadaddr} 0x0 0xd0000; "		\
+		"tftpboot ${loadaddr} u-boot-spl.kwb; "		\
+		"sf update ${loadaddr} 0x0 0xd0000\0"
+
 
 /* increase autoneg timeout, my NIC sucks */
 #define PHY_ANEG_TIMEOUT	16000
diff --git a/include/configs/embestmx6boards.h b/include/configs/embestmx6boards.h
index ff3a849..a29eec0 100644
--- a/include/configs/embestmx6boards.h
+++ b/include/configs/embestmx6boards.h
@@ -29,7 +29,6 @@
 #define CONFIG_SYS_I2C_SPEED		100000
 
 /* USB Configs */
-#define CONFIG_USB_MAX_CONTROLLER_COUNT 2
 #define CONFIG_EHCI_HCD_INIT_AFTER_RESET	/* For OTG port */
 #define CONFIG_MXC_USB_PORTSC	(PORT_PTS_UTMI | PORT_PTS_PTW)
 #define CONFIG_MXC_USB_FLAGS	0
@@ -37,12 +36,6 @@
 /* MMC Configs */
 #define CONFIG_SYS_FSL_ESDHC_ADDR      0
 
-#define CONFIG_FEC_MXC
-#define IMX_FEC_BASE			ENET_BASE_ADDR
-#define CONFIG_FEC_XCV_TYPE		RGMII
-#define CONFIG_ETHPRIME			"FEC"
-#define CONFIG_FEC_MXC_PHYADDR		4
-
 #define CONFIG_ARP_TIMEOUT     200UL
 
 /* Physical Memory Map */
diff --git a/include/configs/gw_ventana.h b/include/configs/gw_ventana.h
index 7c8abda..5754b6a 100644
--- a/include/configs/gw_ventana.h
+++ b/include/configs/gw_ventana.h
@@ -35,18 +35,8 @@
 /* Serial */
 #define CONFIG_MXC_UART_BASE	       UART2_BASE
 
-#if !defined(CONFIG_SPI_FLASH) && defined(CONFIG_SPL_NAND_SUPPORT)
-/* Enable NAND support */
-#ifdef CONFIG_CMD_NAND
-  #define CONFIG_SYS_MAX_NAND_DEVICE	1
-  #define CONFIG_SYS_NAND_BASE		0x40000000
-  #define CONFIG_SYS_NAND_5_ADDR_CYCLE
-  #define CONFIG_SYS_NAND_ONFI_DETECTION
-
-  /* DMA stuff, needed for GPMI/MXS NAND support */
-#endif
-
-#endif /* CONFIG_SPI_FLASH */
+/* NAND */
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
 
 /* I2C Configs */
 #define CONFIG_SYS_I2C
@@ -100,7 +90,6 @@
 #define CONFIG_ARP_TIMEOUT       200UL
 
 /* USB Configs */
-#define CONFIG_USB_MAX_CONTROLLER_COUNT 2
 #define CONFIG_EHCI_HCD_INIT_AFTER_RESET  /* For OTG port */
 #define CONFIG_MXC_USB_PORTSC     (PORT_PTS_UTMI | PORT_PTS_PTW)
 #define CONFIG_MXC_USB_FLAGS      0
diff --git a/include/configs/helios4.h b/include/configs/helios4.h
index 396870a..2cda05c 100644
--- a/include/configs/helios4.h
+++ b/include/configs/helios4.h
@@ -19,11 +19,6 @@
  */
 #define CONFIG_SYS_TCLK		250000000	/* 250MHz */
 
-/*
- * SDIO/MMC Card Configuration
- */
-#define CONFIG_SYS_MMC_BASE		MVEBU_SDIO_BASE
-
 /* USB/EHCI configuration */
 #define CONFIG_EHCI_IS_TDI
 
diff --git a/include/configs/hihope-rzg2.h b/include/configs/hihope-rzg2.h
new file mode 100644
index 0000000..68a5117
--- /dev/null
+++ b/include/configs/hihope-rzg2.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * include/configs/hihope-rzg2.h
+ *     This file is HOPERUN HiHope RZ/G2 board configuration.
+ *
+ * Copyright (C) 2020 Renesas Electronics Corporation
+ */
+
+#ifndef __HIHOPE_RZG2_H
+#define __HIHOPE_RZG2_H
+
+#include "rcar-gen3-common.h"
+
+/* Ethernet RAVB */
+#define CONFIG_BITBANGMII_MULTI
+
+/* Generic Timer Definitions (use in assembler source) */
+#define COUNTER_FREQUENCY	0xFE502A	/* 16.66MHz from CPclk */
+
+#endif /* __HIHOPE_RZG2_H */
diff --git a/include/configs/imx8mm_evk.h b/include/configs/imx8mm_evk.h
index fd9a6cb..8f3dd8f 100644
--- a/include/configs/imx8mm_evk.h
+++ b/include/configs/imx8mm_evk.h
@@ -44,13 +44,13 @@
 /* Initial environment variables */
 #define CONFIG_EXTRA_ENV_SETTINGS		\
 	BOOTENV \
-	"scriptaddr=0x43500000\0" \
-	"kernel_addr_r=0x40880000\0" \
+	"scriptaddr=" __stringify(CONFIG_LOADADDR) "\0" \
+	"kernel_addr_r=" __stringify(CONFIG_LOADADDR) "\0" \
 	"image=Image\0" \
 	"console=ttymxc1,115200\0" \
-	"fdt_addr=0x43000000\0"			\
+	"fdt_addr_r=0x43000000\0"			\
 	"boot_fit=no\0" \
-	"fdt_file=imx8mm-evk.dtb\0" \
+	"fdtfile=imx8mm-evk.dtb\0" \
 	"initrd_addr=0x43800000\0"		\
 	"bootm_size=0x10000000\0" \
 	"mmcpart=" __stringify(CONFIG_SYS_MMC_IMG_LOAD_PART) "\0" \
diff --git a/include/configs/imx8mm_venice.h b/include/configs/imx8mm_venice.h
index a406e91..9166925 100644
--- a/include/configs/imx8mm_venice.h
+++ b/include/configs/imx8mm_venice.h
@@ -19,9 +19,9 @@
 #ifdef CONFIG_SPL_BUILD
 #define CONFIG_SPL_STACK		0x920000
 #define CONFIG_SPL_BSS_START_ADDR	0x910000
-#define CONFIG_SPL_BSS_MAX_SIZE		SZ_8K	/* 8 KB */
+#define CONFIG_SPL_BSS_MAX_SIZE		SZ_8K
 #define CONFIG_SYS_SPL_MALLOC_START	0x42200000
-#define CONFIG_SYS_SPL_MALLOC_SIZE	SZ_512K	/* 512 KB */
+#define CONFIG_SYS_SPL_MALLOC_SIZE	SZ_1M
 
 /* malloc f used before GD_FLG_FULL_MALLOC_INIT set */
 #define CONFIG_MALLOC_F_ADDR		0x930000
diff --git a/include/configs/imx8mp_evk.h b/include/configs/imx8mp_evk.h
index 61a5c6f..d1bc09e 100644
--- a/include/configs/imx8mp_evk.h
+++ b/include/configs/imx8mp_evk.h
@@ -68,13 +68,13 @@
 /* Initial environment variables */
 #define CONFIG_EXTRA_ENV_SETTINGS		\
 	BOOTENV \
-	"scriptaddr=0x43500000\0" \
-	"kernel_addr_r=0x40880000\0" \
+	"scriptaddr=" __stringify(CONFIG_LOADADDR) "\0" \
+	"kernel_addr_r=" __stringify(CONFIG_LOADADDR) "\0" \
 	"image=Image\0" \
 	"console=ttymxc1,115200 earlycon=ec_imx6q,0x30890000,115200\0" \
-	"fdt_addr=0x43000000\0"			\
+	"fdt_addr_r=0x43000000\0"			\
 	"boot_fdt=try\0" \
-	"fdt_file=" CONFIG_DEFAULT_FDT_FILE "\0" \
+	"fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" \
 	"initrd_addr=0x43800000\0"		\
 	"bootm_size=0x10000000\0" \
 	"mmcpart=" __stringify(CONFIG_SYS_MMC_IMG_LOAD_PART) "\0" \
diff --git a/include/configs/kmp204x.h b/include/configs/kmp204x.h
index 90e3702..af3b03b 100644
--- a/include/configs/kmp204x.h
+++ b/include/configs/kmp204x.h
@@ -177,8 +177,6 @@
 #define CONFIG_SYS_BR1_PRELIM  CONFIG_SYS_QRIO_BR_PRELIM /* QRIO Base Address */
 #define CONFIG_SYS_OR1_PRELIM  CONFIG_SYS_QRIO_OR_PRELIM /* QRIO Options */
 
-#define CONFIG_MISC_INIT_F
-
 #define CONFIG_HWCONFIG
 
 /* define to use L1 as initial stack */
diff --git a/include/configs/mt8183.h b/include/configs/mt8183.h
new file mode 100644
index 0000000..8e7afbb
--- /dev/null
+++ b/include/configs/mt8183.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Configuration for MT8183 based boards
+ *
+ * Copyright (C) 2021 BayLibre, SAS
+ * Author: Fabien Parent <fparent@baylibre.com
+ */
+
+#ifndef __MT8183_H
+#define __MT8183_H
+
+#include <linux/sizes.h>
+
+#define CONFIG_SYS_LOAD_ADDR		CONFIG_SYS_TEXT_BASE
+#define CONFIG_SYS_MALLOC_LEN		SZ_4M
+
+#define CONFIG_CPU_ARMV8
+#define COUNTER_FREQUENCY		13000000
+
+#define CONFIG_SYS_NS16550_SERIAL
+#define CONFIG_SYS_NS16550_REG_SIZE	-4
+#define CONFIG_SYS_NS16550_MEM32
+#define CONFIG_SYS_NS16550_COM1		0x11005200
+#define CONFIG_SYS_NS16550_CLK		26000000
+
+#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_TEXT_BASE + SZ_2M - \
+						 GENERATED_GBL_DATA_SIZE)
+
+#define CONFIG_SYS_BOOTM_LEN		SZ_64M
+
+/* Environment settings */
+#include <config_distro_bootcmd.h>
+
+#define BOOT_TARGET_DEVICES(func) \
+	func(MMC, mmc, 0)
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"scriptaddr=0x40000000\0" \
+	BOOTENV
+
+#endif
diff --git a/include/configs/mt8516.h b/include/configs/mt8516.h
new file mode 100644
index 0000000..a1c5d81
--- /dev/null
+++ b/include/configs/mt8516.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Configuration for Pumpkin board
+ *
+ * Copyright (C) 2019 BayLibre, SAS
+ * Author: Fabien Parent <fparent@baylibre.com
+ */
+
+#ifndef __MT8516_H
+#define __MT8516_H
+
+#include <linux/sizes.h>
+
+#define CONFIG_SYS_LOAD_ADDR		CONFIG_SYS_TEXT_BASE
+#define CONFIG_SYS_MALLOC_LEN		SZ_4M
+
+#define CONFIG_CPU_ARMV8
+#define COUNTER_FREQUENCY		13000000
+
+#define CONFIG_SYS_NS16550_SERIAL
+#define CONFIG_SYS_NS16550_REG_SIZE	-4
+#define CONFIG_SYS_NS16550_MEM32
+#define CONFIG_SYS_NS16550_COM1		0x11005000
+#define CONFIG_SYS_NS16550_CLK		26000000
+
+#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_TEXT_BASE + SZ_2M - \
+						 GENERATED_GBL_DATA_SIZE)
+
+#define CONFIG_SYS_BOOTM_LEN		SZ_64M
+
+/* Environment settings */
+#include <config_distro_bootcmd.h>
+
+#define BOOT_TARGET_DEVICES(func) \
+	func(MMC, mmc, 0)
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"scriptaddr=0x40000000\0" \
+	BOOTENV
+
+#endif
diff --git a/include/configs/openrd.h b/include/configs/openrd.h
index e9fd0fc..03b9393 100644
--- a/include/configs/openrd.h
+++ b/include/configs/openrd.h
@@ -74,9 +74,4 @@
 #define CONFIG_SYS_ATA_IDE1_OFFSET	MV_SATA_PORT1_OFFSET
 #endif /*CONFIG_MVSATA_IDE*/
 
-#ifdef CONFIG_CMD_MMC
-#define CONFIG_MVEBU_MMC
-#define CONFIG_SYS_MMC_BASE KW_SDIO_BASE
-#endif /* CONFIG_CMD_MMC */
-
 #endif /* _CONFIG_OPENRD_BASE_H */
diff --git a/include/configs/pcm058.h b/include/configs/pcm058.h
index 4f03699..bc48e80 100644
--- a/include/configs/pcm058.h
+++ b/include/configs/pcm058.h
@@ -19,6 +19,7 @@
 
 /* Enable NAND support */
 #define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define CONFIG_SYS_NAND_ONFI_DETECTION
 
 /* Physical Memory Map */
 #define PHYS_SDRAM                     MMDC0_ARB_BASE_ADDR
diff --git a/include/configs/pumpkin.h b/include/configs/pumpkin.h
deleted file mode 100644
index 9c52cae..0000000
--- a/include/configs/pumpkin.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Configuration for Pumpkin board
- *
- * Copyright (C) 2019 BayLibre, SAS
- * Author: Fabien Parent <fparent@baylibre.com
- */
-
-#ifndef __PUMPKIN_H
-#define __PUMPKIN_H
-
-#include <linux/sizes.h>
-
-#define CONFIG_SYS_LOAD_ADDR		CONFIG_SYS_TEXT_BASE
-#define CONFIG_SYS_MALLOC_LEN		SZ_4M
-
-#define CONFIG_CPU_ARMV8
-#define COUNTER_FREQUENCY		13000000
-
-#define CONFIG_SYS_NS16550_SERIAL
-#define CONFIG_SYS_NS16550_REG_SIZE	-4
-#define CONFIG_SYS_NS16550_MEM32
-#define CONFIG_SYS_NS16550_COM1		0x11005000
-#define CONFIG_SYS_NS16550_CLK		26000000
-
-#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_TEXT_BASE + SZ_2M - \
-						 GENERATED_GBL_DATA_SIZE)
-
-#define CONFIG_SYS_BOOTM_LEN		SZ_64M
-
-/* Environment settings */
-#include <config_distro_bootcmd.h>
-
-#define MMCBOOT \
-	"mmcdev=0\0" \
-	"kernel_partition=2\0" \
-	"rootfs_partition=3\0" \
-	"mmc_discover_partition=" \
-		"part start mmc ${mmcdev} ${kernel_partition} kernel_part_addr;" \
-		"part size mmc ${mmcdev} ${kernel_partition} kernel_part_size;\0" \
-	"mmcboot=" \
-		"mmc dev ${mmcdev};" \
-		"run mmc_discover_partition;" \
-		"mmc read ${kerneladdr} ${kernel_part_addr} ${kernel_part_size};" \
-		"setenv bootargs ${bootargs} root=/dev/mmcblk${mmcdev}p${rootfs_partition} rootwait; " \
-		"bootm ${kerneladdr}; \0"
-
-#define CONFIG_EXTRA_ENV_SETTINGS \
-	"kerneladdr=0x4A000000\0" \
-	MMCBOOT \
-	"bootcmd=run mmcboot;\0"
-
-#endif
diff --git a/include/configs/rk3368_common.h b/include/configs/rk3368_common.h
index f178a06..fbbb8cf 100644
--- a/include/configs/rk3368_common.h
+++ b/include/configs/rk3368_common.h
@@ -24,13 +24,15 @@
 #define CONFIG_IRAM_BASE		0xff8c0000
 
 #define CONFIG_SYS_INIT_SP_ADDR		0x00300000
-#define CONFIG_SYS_LOAD_ADDR		0x00280000
+#define CONFIG_SYS_LOAD_ADDR		0x00800800
 
 #define CONFIG_SPL_MAX_SIZE             0x40000
 #define CONFIG_SPL_BSS_START_ADDR       0x400000
 #define CONFIG_SPL_BSS_MAX_SIZE         0x20000
 #define CONFIG_SPL_STACK                0x00188000
 
+#define CONFIG_SYS_BOOTM_LEN	(64 << 20)	/* 64M */
+
 #ifndef CONFIG_SPL_BUILD
 #define ENV_MEM_LAYOUT_SETTINGS \
 	"scriptaddr=0x00500000\0" \
diff --git a/include/configs/rk3399_common.h b/include/configs/rk3399_common.h
index d0fc598..b37ed5c 100644
--- a/include/configs/rk3399_common.h
+++ b/include/configs/rk3399_common.h
@@ -75,6 +75,4 @@
 
 #endif
 
-/* enable usb config for usb ether */
-
 #endif
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index e0708fe..bbb7d12 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -130,6 +130,4 @@
 
 #define CONFIG_SYS_SATA_MAX_DEVICE	2
 
-#define CONFIG_MISC_INIT_F
-
 #endif
diff --git a/include/configs/sheevaplug.h b/include/configs/sheevaplug.h
index e1f8fb8..abe8418 100644
--- a/include/configs/sheevaplug.h
+++ b/include/configs/sheevaplug.h
@@ -51,14 +51,6 @@
 #endif /* CONFIG_CMD_NET */
 
 /*
- * SDIO/MMC Card Configuration
- */
-#ifdef CONFIG_CMD_MMC
-#define CONFIG_MVEBU_MMC
-#define CONFIG_SYS_MMC_BASE KW_SDIO_BASE
-#endif /* CONFIG_CMD_MMC */
-
-/*
  * SATA driver configuration
  */
 #ifdef CONFIG_IDE
diff --git a/include/configs/sifive-fu540.h b/include/configs/sifive-unleashed.h
similarity index 100%
rename from include/configs/sifive-fu540.h
rename to include/configs/sifive-unleashed.h
diff --git a/include/configs/silinux-ek874.h b/include/configs/silinux-ek874.h
new file mode 100644
index 0000000..25c0cd2
--- /dev/null
+++ b/include/configs/silinux-ek874.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * include/configs/silinux-ek874.h
+ *     This file is Silicon Linux EK874 board configuration.
+ *
+ * Copyright (C) 2021 Renesas Electronics Corporation
+ */
+
+#ifndef __SILINUX_EK874_H
+#define __SILINUX_EK874_H
+
+#include "rcar-gen3-common.h"
+
+/* Ethernet RAVB */
+#define CONFIG_BITBANGMII_MULTI
+
+/* Generic Timer Definitions (use in assembler source) */
+#define COUNTER_FREQUENCY	0xFE502A	/* 16.66MHz from CPclk */
+
+#endif /* __SILINUX_EK874_H */
diff --git a/include/configs/sipeed-maix.h b/include/configs/sipeed-maix.h
index 08acb25..4c1ff98 100644
--- a/include/configs/sipeed-maix.h
+++ b/include/configs/sipeed-maix.h
@@ -18,9 +18,6 @@
 /* Don't relocate into AI ram since it isn't set up yet */
 #define CONFIG_SYS_SDRAM_SIZE (SZ_4M + SZ_2M)
 
-/* For early init */
-#define K210_SYSCTL_BASE 0x50440000
-
 #ifndef CONFIG_EXTRA_ENV_SETTINGS
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	"loadaddr=0x80060000\0" \
diff --git a/include/configs/socfpga_soc64_common.h b/include/configs/socfpga_soc64_common.h
index 1cfa190..5afdb10 100644
--- a/include/configs/socfpga_soc64_common.h
+++ b/include/configs/socfpga_soc64_common.h
@@ -8,7 +8,7 @@
 #define __CONFIG_SOCFPGA_SOC64_COMMON_H__
 
 #include <asm/arch/base_addr_s10.h>
-#include <asm/arch/handoff_s10.h>
+#include <asm/arch/handoff_soc64.h>
 #include <linux/stringify.h>
 
 /*
@@ -43,7 +43,7 @@
 #ifdef CONFIG_SPL_BUILD
 #define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_INIT_RAM_ADDR  \
 					+ CONFIG_SYS_INIT_RAM_SIZE \
-					- S10_HANDOFF_SIZE)
+					- SOC64_HANDOFF_SIZE)
 #else
 #define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_TEXT_BASE \
 					+ 0x100000)
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index 7b602dd..33a4d7b 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -223,23 +223,6 @@
 #define CONFIG_VIDEO_LCD_I2C_BUS	-1 /* NA, but necessary to compile */
 #endif
 
-#ifdef CONFIG_VIDEO_SUNXI
-/*
- * The amount of RAM to keep free at the top of RAM when relocating u-boot,
- * to use as framebuffer. This must be a multiple of 4096.
- */
-#define CONFIG_SUNXI_MAX_FB_SIZE (16 << 20)
-
-#define CONFIG_VIDEO_LOGO
-#define CONFIG_VIDEO_STD_TIMINGS
-#define CONFIG_I2C_EDID
-#define VIDEO_LINE_LEN (pGD->plnSizeX)
-
-/* allow both serial and cfb console. */
-/* stop x86 thinking in cfbconsole from trying to init a pc keyboard */
-
-#endif /* CONFIG_VIDEO_SUNXI */
-
 /* Ethernet support */
 
 #ifdef CONFIG_USB_EHCI_HCD
@@ -401,11 +384,7 @@
 	"stdin=serial\0"
 #endif
 
-#ifdef CONFIG_VIDEO
-#define CONSOLE_STDOUT_SETTINGS \
-	"stdout=serial,vga\0" \
-	"stderr=serial,vga\0"
-#elif CONFIG_DM_VIDEO
+#ifdef CONFIG_DM_VIDEO
 #define CONSOLE_STDOUT_SETTINGS \
 	"stdout=serial,vidconsole\0" \
 	"stderr=serial,vidconsole\0"
diff --git a/include/configs/udoo.h b/include/configs/udoo.h
index b4fbf8c..2983693 100644
--- a/include/configs/udoo.h
+++ b/include/configs/udoo.h
@@ -21,21 +21,7 @@
 #define CONFIG_MXC_UART_BASE		UART2_BASE
 
 /* SATA Configs */
-
-#ifdef CONFIG_CMD_SATA
-#define CONFIG_SYS_SATA_MAX_DEVICE	1
-#define CONFIG_DWC_AHSATA_PORT_ID	0
-#define CONFIG_DWC_AHSATA_BASE_ADDR	SATA_ARB_BASE_ADDR
 #define CONFIG_LBA48
-#endif
-
-/* Network support */
-
-#define CONFIG_FEC_MXC
-#define IMX_FEC_BASE                    ENET_BASE_ADDR
-#define CONFIG_FEC_XCV_TYPE             RGMII
-#define CONFIG_ETHPRIME                 "FEC"
-#define CONFIG_FEC_MXC_PHYADDR          6
 
 /* MMC Configuration */
 #define CONFIG_SYS_FSL_ESDHC_ADDR	0
diff --git a/include/cpu_func.h b/include/cpu_func.h
index 8aa825d..c3a66f0 100644
--- a/include/cpu_func.h
+++ b/include/cpu_func.h
@@ -84,6 +84,6 @@
  */
 int cleanup_before_linux_select(int flags);
 
-void reset_cpu(ulong addr);
-;
+void reset_cpu(void);
+
 #endif
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
index 39406c3..e6b71cb 100644
--- a/include/dm/device-internal.h
+++ b/include/dm/device-internal.h
@@ -10,11 +10,86 @@
 #ifndef _DM_DEVICE_INTERNAL_H
 #define _DM_DEVICE_INTERNAL_H
 
+#include <linker_lists.h>
 #include <dm/ofnode.h>
 
 struct device_node;
 struct udevice;
 
+/*
+ * These two macros DM_DEVICE_INST and DM_DEVICE_REF are only allowed in code
+ * generated by dtoc, because the ordering is important and if other instances
+ * creep in then they may mess up the ordering expected by dtoc.
+ *
+ * It is OK to use them with 'extern' though, since that does not actually
+ * add a new record to the linker_list.
+ */
+
+/**
+ * DM_DEVICE_INST() - Declare a bound device ready for run-time use
+ *
+ * This adds an actual struct udevice to a list which is found by driver model
+ * on start-up.
+ *
+ * For example:
+ *
+ * extern U_BOOT_DRIVER(sandbox_fixed_clock);
+ * extern DM_UCLASS_INST(clk);
+ *
+ * DM_DEVICE_INST(clk_fixed) = {
+ *	.driver		= DM_DRIVER_REF(sandbox_fixed_clock),
+ *	.name		= "sandbox_fixed_clock",
+ *	.plat_		= &_sandbox_fixed_clock_plat_clk_fixed,
+ *	.uclass		= DM_UCLASS_REF(clk),
+ *	...
+ *	.seq_		= 0,
+ * };
+ *
+ * @_name: Name of the udevice. This must be a valid C identifier, used by the
+ *	linker_list.
+ */
+#define DM_DEVICE_INST(_name)						\
+	ll_entry_declare(struct udevice, _name, udevice)
+
+/**
+ * DM_DEVICE_REF() - Get a reference to a device
+ *
+ * This is useful in data structures and code for referencing a udevice at
+ * build time. Before this is used, an extern DM_DEVICE_INST() must have been
+ * declared.
+ *
+ * For example:
+ *
+ * extern DM_DEVICE_INST(clk_fixed);
+ *
+ * struct udevice *devs[] = {
+ *	DM_DEVICE_REF(clk_fixed),
+ * };
+ *
+ * @_name: Name of the udevice. This must be a valid C identifier, used by the
+ *	linker_list
+ * @returns struct udevice * for the device
+ */
+#define DM_DEVICE_REF(_name)						\
+	ll_entry_ref(struct udevice, _name, udevice)
+
+/**
+ * DM_DEVICE_GET() - Get a pointer to a given device
+ *
+ * This is similar to DM_DEVICE_REF() except that it does not need the extern
+ * declaration before it. However it cannot be used in a data structures, only
+ * in code within a function.
+ *
+ * For example:
+ *
+ * void some_function() {
+ *	struct udevice *dev = DM_DEVICE_GET(clk_fixed);
+ * ...
+ * }
+ */
+#define DM_DEVICE_GET(__name)						\
+	ll_entry_get(struct udevice, __name, udevice)
+
 /**
  * device_bind() - Create a device and bind it to a driver
  *
@@ -209,6 +284,9 @@
  * Use this function to override normal operation for special situations, such
  * as needing to allocate a variable amount of data.
  *
+ * If OF_PLATDATA_RT is enabled, this function cannot be used out of core driver
+ * model code, since the pointer must be within the gd->dm_priv_base region.
+ *
  * @dev		Device to check
  * @priv	New private-data pointer
  */
@@ -223,6 +301,9 @@
  * Use this function to override normal operation for special situations, such
  * as needing to allocate a variable amount of data.
  *
+ * If OF_PLATDATA_RT is enabled, this function cannot be used out of core driver
+ * model code, since the pointer must be within the gd->dm_priv_base region.
+ *
  * @dev:	Device to update
  * @parent_priv: New parent-private data
  */
@@ -237,6 +318,9 @@
  * Use this function to override normal operation for special situations, such
  * as needing to allocate a variable amount of data.
  *
+ * If OF_PLATDATA_RT is enabled, this function cannot be used out of core driver
+ * model code, since the pointer must be within the gd->dm_priv_base region.
+ *
  * @dev:	Device to update
  * @uclass_priv: New uclass private data
  */
@@ -251,6 +335,9 @@
  * Use this function to override normal operation for special situations, such
  * as needing to allocate a variable amount of data.
  *
+ * If OF_PLATDATA_RT is enabled, this function cannot be used out of core driver
+ * model code, since the pointer must be within the gd->dm_priv_base region.
+ *
  * @dev		Device to check
  * @plat	New platform-data pointer
  */
@@ -265,6 +352,9 @@
  * Use this function to override normal operation for special situations, such
  * as needing to allocate a variable amount of data.
  *
+ * If OF_PLATDATA_RT is enabled, this function cannot be used out of core driver
+ * model code, since the pointer must be within the gd->dm_priv_base region.
+ *
  * @dev:	Device to update
  * @parent_plat: New parent platform data
  */
@@ -279,6 +369,9 @@
  * Use this function to override normal operation for special situations, such
  * as needing to allocate a variable amount of data.
  *
+ * If OF_PLATDATA_RT is enabled, this function cannot be used out of core driver
+ * model code, since the pointer must be within the gd->dm_priv_base region.
+ *
  * @dev:	Device to update
  * @uclass_plat: New uclass platform data
  */
diff --git a/include/dm/device.h b/include/dm/device.h
index bb9faa0..0a9718a 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -177,7 +177,9 @@
 	struct list_head uclass_node;
 	struct list_head child_head;
 	struct list_head sibling_node;
+#if !CONFIG_IS_ENABLED(OF_PLATDATA_RT)
 	u32 flags_;
+#endif
 	int seq_;
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	ofnode node_;
@@ -190,12 +192,32 @@
 #endif
 };
 
+/**
+ * udevice_rt - runtime information set up by U-Boot
+ *
+ * This is only used with OF_PLATDATA_RT
+ *
+ * There is one of these for every udevice in the linker list, indexed by
+ * the udevice_info idx value.
+ *
+ * @flags_: Flags for this device DM_FLAG_... (do not access outside driver
+ *	model)
+ */
+struct udevice_rt {
+	u32 flags_;
+};
+
 /* Maximum sequence number supported */
 #define DM_MAX_SEQ	999
 
 /* Returns the operations for a device */
 #define device_get_ops(dev)	(dev->driver->ops)
 
+#if CONFIG_IS_ENABLED(OF_PLATDATA_RT)
+u32 dev_get_flags(const struct udevice *dev);
+void dev_or_flags(const struct udevice *dev, u32 or);
+void dev_bic_flags(const struct udevice *dev, u32 bic);
+#else
 static inline u32 dev_get_flags(const struct udevice *dev)
 {
 	return dev->flags_;
@@ -210,6 +232,7 @@
 {
 	dev->flags_ &= ~bic;
 }
+#endif /* OF_PLATDATA_RT */
 
 /**
  * dev_ofnode() - get the DT node reference associated with a udevice
@@ -363,6 +386,28 @@
 	ll_entry_get(struct driver, __name, driver)
 
 /**
+ * DM_DRIVER_REF() - Get a reference to a driver
+ *
+ * This is useful in data structures and code for referencing a driver at
+ * build time. Before this is used, an extern U_BOOT_DRIVER() must have been
+ * declared.
+ *
+ * For example:
+ *
+ * extern U_BOOT_DRIVER(sandbox_fixed_clock);
+ *
+ * struct driver *drvs[] = {
+ *	DM_DRIVER_REF(sandbox_fixed_clock),
+ * };
+ *
+ * @_name: Name of the driver. This must be a valid C identifier, used by the
+ *	linker_list
+ * @returns struct driver * for the driver
+ */
+#define DM_DRIVER_REF(_name)					\
+	ll_entry_ref(struct driver, _name, driver)
+
+/**
  * Declare a macro to state a alias for a driver name. This macro will
  * produce no code but its information will be parsed by tools like
  * dtoc
@@ -370,6 +415,40 @@
 #define DM_DRIVER_ALIAS(__name, __alias)
 
 /**
+ * Declare a macro to indicate which phase of U-Boot this driver is fore.
+ *
+ *
+ * This macro produces no code but its information will be parsed by dtoc. The
+ * macro can be only be used once in a driver. Put it within the U_BOOT_DRIVER()
+ * declaration, e.g.:
+ *
+ * U_BOOT_DRIVER(cpu) = {
+ *	.name = ...
+ *	...
+ *	DM_PHASE(tpl)
+ * };
+ */
+#define DM_PHASE(_phase)
+
+/**
+ * Declare a macro to declare a header needed for a driver. Often the correct
+ * header can be found automatically, but only for struct declarations. For
+ * enums and #defines used in the driver declaration and declared in a different
+ * header from the structs, this macro must be used.
+ *
+ * This macro produces no code but its information will be parsed by dtoc. The
+ * macro can be used multiple times with different headers, for the same driver.
+ * Put it within the U_BOOT_DRIVER() declaration, e.g.:
+ *
+ * U_BOOT_DRIVER(cpu) = {
+ *	.name = ...
+ *	...
+ *	DM_HEADER(<asm/cpu.h>)
+ * };
+ */
+#define DM_HEADER(_hdr)
+
+/**
  * dev_get_plat() - Get the platform data for a device
  *
  * This checks that dev is not NULL, but no other checks for now
@@ -611,33 +690,24 @@
 int device_get_global_by_ofnode(ofnode node, struct udevice **devp);
 
 /**
- * device_get_by_driver_info() - Get a device based on driver_info
+ * device_get_by_ofplat_idx() - Get a device based on of-platdata index
  *
- * Locates a device by its struct driver_info, by using its reference which
- * is updated during the bind process.
+ * Locates a device by either its struct driver_info index, or its
+ * struct udevice index. The latter is used with OF_PLATDATA_INST, since we have
+ * a list of build-time instantiated struct udevice records, The former is used
+ * with !OF_PLATDATA_INST since in that case we have a list of
+ * struct driver_info records.
+ *
+ * The index number is written into the idx field of struct phandle_1_arg, etc.
+ * It is the position of this driver_info/udevice in its linker list.
  *
  * The device is probed to activate it ready for use.
  *
- * @info: Struct driver_info
+ * @idx: Index number of the driver_info/udevice structure (0=first)
  * @devp: Returns pointer to device if found, otherwise this is set to NULL
  * @return 0 if OK, -ve on error
  */
-int device_get_by_driver_info(const struct driver_info *info,
-			      struct udevice **devp);
-
-/**
- * device_get_by_driver_info_idx() - Get a device based on driver_info index
- *
- * Locates a device by its struct driver_info, by using its index number which
- * is written into the idx field of struct phandle_1_arg, etc.
- *
- * The device is probed to activate it ready for use.
- *
- * @idx: Index number of the driver_info structure (0=first)
- * @devp: Returns pointer to device if found, otherwise this is set to NULL
- * @return 0 if OK, -ve on error
- */
-int device_get_by_driver_info_idx(uint idx, struct udevice **devp);
+int device_get_by_ofplat_idx(uint idx, struct udevice **devp);
 
 /**
  * device_find_first_child() - Find the first child of a device
diff --git a/include/dm/of_extra.h b/include/dm/of_extra.h
index ca15df2..fc4f974 100644
--- a/include/dm/of_extra.h
+++ b/include/dm/of_extra.h
@@ -11,7 +11,11 @@
 
 enum fmap_compress_t {
 	FMAP_COMPRESS_NONE,
+	FMAP_COMPRESS_LZMA,
 	FMAP_COMPRESS_LZ4,
+
+	FMAP_COMPRESS_COUNT,
+	FMAP_COMPRESS_UNKNOWN,
 };
 
 enum fmap_hash_t {
@@ -30,6 +34,10 @@
 	enum fmap_hash_t hash_algo;		/* Hash algorithm */
 	const uint8_t *hash;			/* Hash value */
 	int hash_size;				/* Hash size */
+	/* Node pointer if CBFS, else NULL */
+	const struct cbfs_cachenode *cbfs_node;
+	/* Hash node pointer if CBFS, else NULL */
+	const struct cbfs_cachenode *cbfs_hash_node;
 };
 
 /**
diff --git a/include/dm/platdata.h b/include/dm/platdata.h
index 3821a56..4efb1df 100644
--- a/include/dm/platdata.h
+++ b/include/dm/platdata.h
@@ -71,19 +71,4 @@
 #define U_BOOT_DRVINFOS(__name)						\
 	ll_entry_declare_list(struct driver_info, __name, driver_info)
 
-/**
- * Get a pointer to a given device info given its name
- *
- * With the declaration U_BOOT_DRVINFO(name), DM_DRVINFO_GET(name) will return a
- * pointer to the struct driver_info created by that declaration.
- *
- * if OF_PLATDATA is enabled, from this it is possible to use the @dev member of
- * struct driver_info to find the device pointer itself.
- *
- * @__name: Driver name (C identifier, not a string. E.g. gpio7_at_ff7e0000)
- * @return struct driver_info * to the driver that created the device
- */
-#define DM_DRVINFO_GET(__name)						\
-	ll_entry_get(struct driver_info, __name, driver_info)
-
 #endif
diff --git a/include/dm/root.h b/include/dm/root.h
index 89afbee..42510b1 100644
--- a/include/dm/root.h
+++ b/include/dm/root.h
@@ -11,6 +11,9 @@
 
 struct udevice;
 
+/* Head of the uclass list if CONFIG_OF_PLATDATA_INST is enabled */
+extern struct list_head uclass_head;
+
 /**
  * dm_root() - Return pointer to the top of the driver tree
  *
diff --git a/include/dm/test.h b/include/dm/test.h
index c5a9610..a9562b2 100644
--- a/include/dm/test.h
+++ b/include/dm/test.h
@@ -73,6 +73,11 @@
 	int uclass_postp;
 };
 
+/* struct dm_test_uc_priv - private data for the testdrv uclass */
+struct dm_test_uc_priv {
+	int dummy;
+};
+
 /**
  * struct dm_test_perdev_class_priv - private per-device data for test uclass
  */
@@ -127,25 +132,9 @@
 
 extern struct unit_test_state global_dm_test_state;
 
-/*
- * struct dm_test_state - Entire state of dm test system
- *
- * This is often abreviated to dms.
- *
- * @root: Root device
- * @testdev: Test device
- * @force_fail_alloc: Force all memory allocs to fail
- * @skip_post_probe: Skip uclass post-probe processing
- */
-struct dm_test_state {
-	struct udevice *root;
-	struct udevice *testdev;
-	int force_fail_alloc;
-	int skip_post_probe;
-};
-
 /* Declare a new driver model test */
-#define DM_TEST(_name, _flags)	UNIT_TEST(_name, _flags, dm_test)
+#define DM_TEST(_name, _flags) \
+	UNIT_TEST(_name, UT_TESTF_DM | UT_TESTF_CONSOLE_REC | (_flags), dm_test)
 
 /*
  * struct sandbox_sdl_plat - Platform data for the SDL video driver
diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h
index c5a464b..57c664c 100644
--- a/include/dm/uclass-internal.h
+++ b/include/dm/uclass-internal.h
@@ -11,6 +11,55 @@
 
 #include <dm/ofnode.h>
 
+/*
+ * These next two macros DM_UCLASS_INST() and DM_UCLASS_REF() are only allowed
+ * in code generated by dtoc, because the ordering is important and if other
+ * instances creep in then they may mess up the ordering expected by dtoc.
+ *
+ * It is OK to use them with 'extern' though, since that does not actually
+ * add a new record to the linker_list.
+ */
+
+/**
+ * DM_UCLASS_INST() - Declare a uclass ready for run-time use
+ *
+ * This adds an actual struct uclass to a list which is found by driver model
+ * on start-up.
+ *
+ * For example:
+ *
+ * DM_UCLASS_INST(clk) = {
+ *	.uc_drv		= DM_UCLASS_DRIVER_REF(clk),
+ * ...
+ * };
+ *
+ * @_name: Name of the uclass. This must be a valid C identifier, used by the
+ *	linker_list.
+ */
+#define DM_UCLASS_INST(_name)						\
+	ll_entry_declare(struct uclass, _name, uclass)
+
+/**
+ * DM_UCLASS_REF() - Get a reference to a uclass
+ *
+ * This is useful for referencing a uclass at build time. Before this is used,
+ * an extern DM_UCLASS_INST() must have been declared.
+ *
+ * For example:
+ *
+ * extern DM_UCLASS_INST(clk);
+ *
+ * struct uclass *ucs[] = {
+ *	DM_UCLASS_REF(clk),
+ * }
+ *
+ * @_name: Name of the uclass. This must be a valid C identifier, used by the
+ *	linker_list
+ * @returns struct uclass * for the device
+ */
+#define DM_UCLASS_REF(_name)						\
+	ll_entry_ref(struct uclass, _name, uclass)
+
 /**
  * uclass_set_priv() - Set the private data for a uclass
  *
@@ -20,6 +69,9 @@
  * Use this function to override normal operation for special situations, such
  * as needing to allocate a variable amount of data.
  *
+ * If OF_PLATDATA_RT is enabled, this function cannot be used out of core driver
+ * model code, since the pointer must be within the gd->dm_priv_base region.
+ *
  * @uc		Uclass to update
  * @priv	New private-data pointer
  */
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index d956837..6752d8e 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -114,6 +114,37 @@
 #define UCLASS_DRIVER(__name)						\
 	ll_entry_declare(struct uclass_driver, __name, uclass_driver)
 
+/*
+ * These two macros DM_UCLASS_DRIVER_REF and DM_UCLASS_DRIVER_REF are only
+ * allowed in code generated by dtoc, because the ordering is important and if
+ * other instances creep in then they may mess up the ordering expected by dtoc.
+ *
+ * It is OK to use them with 'extern' though, since that does not actually
+ * add a new record to the linker_list.
+ */
+
+/**
+ * DM_UCLASS_DRIVER_REF() - Get a reference to a uclass driver
+ *
+ * This is useful in data structures and code for referencing a uclass_driver at
+ * build time. Before this is used, an extern UCLASS_DRIVER() must have been
+ * declared.
+ *
+ * For example:
+ *
+ * extern UCLASS_DRIVER(clk);
+ *
+ * struct uclass_driver *drvs[] = {
+ *	DM_UCLASS_DRIVER_REF(clk),
+ * };
+ *
+ * @_name: Name of the uclass_driver. This must be a valid C identifier, used by
+ *	the linker_list.
+ * @returns struct uclass_driver * for the uclass driver
+ */
+#define DM_UCLASS_DRIVER_REF(_name)					\
+	ll_entry_ref(struct uclass_driver, _name, uclass_driver)
+
 /**
  * uclass_get_priv() - Get the private data for a uclass
  *
diff --git a/include/dm/util.h b/include/dm/util.h
index 01a0449..138893c 100644
--- a/include/dm/util.h
+++ b/include/dm/util.h
@@ -49,3 +49,12 @@
 void dm_dump_static_driver_info(void);
 
 #endif
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA_INST) && CONFIG_IS_ENABLED(READ_ONLY)
+void *dm_priv_to_rw(void *priv);
+#else
+static inline void *dm_priv_to_rw(void *priv)
+{
+	return priv;
+}
+#endif
diff --git a/include/dt-bindings/clock/rk3368-cru.h b/include/dt-bindings/clock/rk3368-cru.h
index 9c5dd9b..0a06c5f 100644
--- a/include/dt-bindings/clock/rk3368-cru.h
+++ b/include/dt-bindings/clock/rk3368-cru.h
@@ -1,15 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 /*
  * Copyright (c) 2015 Heiko Stuebner <heiko@sntech.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3368_H
@@ -44,13 +35,12 @@
 #define SCLK_I2S_8CH		82
 #define SCLK_SPDIF_8CH		83
 #define SCLK_I2S_2CH		84
-#define SCLK_TIMER0		85
-#define SCLK_TIMER1		86
-#define SCLK_TIMER2		87
-#define SCLK_TIMER3		88
-#define SCLK_TIMER4		89
-#define SCLK_TIMER5		90
-#define SCLK_TIMER6		91
+#define SCLK_TIMER00		85
+#define SCLK_TIMER01		86
+#define SCLK_TIMER02		87
+#define SCLK_TIMER03		88
+#define SCLK_TIMER04		89
+#define SCLK_TIMER05		90
 #define SCLK_OTGPHY0		93
 #define SCLK_OTG_ADP		96
 #define SCLK_HSICPHY480M	97
@@ -82,6 +72,12 @@
 #define SCLK_SFC		126
 #define SCLK_MAC		127
 #define SCLK_MACREF_OUT		128
+#define SCLK_TIMER10		133
+#define SCLK_TIMER11		134
+#define SCLK_TIMER12		135
+#define SCLK_TIMER13		136
+#define SCLK_TIMER14		137
+#define SCLK_TIMER15		138
 
 #define DCLK_VOP		190
 #define MCLK_CRYPTO		191
@@ -151,6 +147,7 @@
 #define PCLK_ISP		366
 #define PCLK_VIP		367
 #define PCLK_WDT		368
+#define PCLK_EFUSE256		369
 
 /* hclk gates */
 #define HCLK_SFC		448
diff --git a/include/dt-bindings/display/tda998x.h b/include/dt-bindings/display/tda998x.h
new file mode 100644
index 0000000..746831f
--- /dev/null
+++ b/include/dt-bindings/display/tda998x.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _DT_BINDINGS_TDA998X_H
+#define _DT_BINDINGS_TDA998X_H
+
+#define TDA998x_SPDIF	1
+#define TDA998x_I2S	2
+
+#endif /*_DT_BINDINGS_TDA998X_H */
diff --git a/include/dt-bindings/dma/xlnx-zynqmp-dpdma.h b/include/dt-bindings/dma/xlnx-zynqmp-dpdma.h
new file mode 100644
index 0000000..3719cda
--- /dev/null
+++ b/include/dt-bindings/dma/xlnx-zynqmp-dpdma.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Copyright 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+
+#ifndef __DT_BINDINGS_DMA_XLNX_ZYNQMP_DPDMA_H__
+#define __DT_BINDINGS_DMA_XLNX_ZYNQMP_DPDMA_H__
+
+#define ZYNQMP_DPDMA_VIDEO0		0
+#define ZYNQMP_DPDMA_VIDEO1		1
+#define ZYNQMP_DPDMA_VIDEO2		2
+#define ZYNQMP_DPDMA_GRAPHICS		3
+#define ZYNQMP_DPDMA_AUDIO0		4
+#define ZYNQMP_DPDMA_AUDIO1		5
+
+#endif /* __DT_BINDINGS_DMA_XLNX_ZYNQMP_DPDMA_H__ */
diff --git a/include/dt-bindings/media/tda1997x.h b/include/dt-bindings/media/tda1997x.h
new file mode 100644
index 0000000..bd9fbd7
--- /dev/null
+++ b/include/dt-bindings/media/tda1997x.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2017 Gateworks Corporation
+ */
+#ifndef _DT_BINDINGS_MEDIA_TDA1997X_H
+#define _DT_BINDINGS_MEDIA_TDA1997X_H
+
+/* TDA19973 36bit Video Port control registers */
+#define TDA1997X_VP36_35_32	0
+#define TDA1997X_VP36_31_28	1
+#define TDA1997X_VP36_27_24	2
+#define TDA1997X_VP36_23_20	3
+#define TDA1997X_VP36_19_16	4
+#define TDA1997X_VP36_15_12	5
+#define TDA1997X_VP36_11_08	6
+#define TDA1997X_VP36_07_04	7
+#define TDA1997X_VP36_03_00	8
+
+/* TDA19971 24bit Video Port control registers */
+#define TDA1997X_VP24_V23_20	0
+#define TDA1997X_VP24_V19_16	1
+#define TDA1997X_VP24_V15_12	3
+#define TDA1997X_VP24_V11_08	4
+#define TDA1997X_VP24_V07_04	6
+#define TDA1997X_VP24_V03_00	7
+
+/* Pin groups */
+#define TDA1997X_VP_OUT_EN        0x80	/* enable output group */
+#define TDA1997X_VP_HIZ           0x40	/* hi-Z output group when not used */
+#define TDA1997X_VP_SWP           0x10	/* pin-swap output group */
+#define TDA1997X_R_CR_CBCR_3_0    (0 | TDA1997X_VP_OUT_EN | TDA1997X_VP_HIZ)
+#define TDA1997X_R_CR_CBCR_7_4    (1 | TDA1997X_VP_OUT_EN | TDA1997X_VP_HIZ)
+#define TDA1997X_R_CR_CBCR_11_8   (2 | TDA1997X_VP_OUT_EN | TDA1997X_VP_HIZ)
+#define TDA1997X_B_CB_3_0         (3 | TDA1997X_VP_OUT_EN | TDA1997X_VP_HIZ)
+#define TDA1997X_B_CB_7_4         (4 | TDA1997X_VP_OUT_EN | TDA1997X_VP_HIZ)
+#define TDA1997X_B_CB_11_8        (5 | TDA1997X_VP_OUT_EN | TDA1997X_VP_HIZ)
+#define TDA1997X_G_Y_3_0          (6 | TDA1997X_VP_OUT_EN | TDA1997X_VP_HIZ)
+#define TDA1997X_G_Y_7_4          (7 | TDA1997X_VP_OUT_EN | TDA1997X_VP_HIZ)
+#define TDA1997X_G_Y_11_8         (8 | TDA1997X_VP_OUT_EN | TDA1997X_VP_HIZ)
+/* pinswapped groups */
+#define TDA1997X_R_CR_CBCR_3_0_S  (TDA1997X_R_CR_CBCR_3_0 | TDA1997X_VP_SWAP)
+#define TDA1997X_R_CR_CBCR_7_4_S  (TDA1997X_R_CR_CBCR_7_4 | TDA1997X_VP_SWAP)
+#define TDA1997X_R_CR_CBCR_11_8_S (TDA1997X_R_CR_CBCR_11_8 | TDA1997X_VP_SWAP)
+#define TDA1997X_B_CB_3_0_S       (TDA1997X_B_CB_3_0 | TDA1997X_VP_SWAP)
+#define TDA1997X_B_CB_7_4_S       (TDA1997X_B_CB_7_4 | TDA1997X_VP_SWAP)
+#define TDA1997X_B_CB_11_8_S      (TDA1997X_B_CB_11_8 | TDA1997X_VP_SWAP)
+#define TDA1997X_G_Y_3_0_S        (TDA1997X_G_Y_3_0 | TDA1997X_VP_SWAP)
+#define TDA1997X_G_Y_7_4_S        (TDA1997X_G_Y_7_4 | TDA1997X_VP_SWAP)
+#define TDA1997X_G_Y_11_8_S       (TDA1997X_G_Y_11_8 | TDA1997X_VP_SWAP)
+
+/* Audio bus DAI format */
+#define TDA1997X_I2S16			1 /* I2S 16bit */
+#define TDA1997X_I2S32			2 /* I2S 32bit */
+#define TDA1997X_SPDIF			3 /* SPDIF */
+#define TDA1997X_OBA			4 /* One Bit Audio */
+#define TDA1997X_DST			5 /* Direct Stream Transfer */
+#define TDA1997X_I2S16_HBR		6 /* HBR straight in I2S 16bit mode */
+#define TDA1997X_I2S16_HBR_DEMUX	7 /* HBR demux in I2S 16bit mode */
+#define TDA1997X_I2S32_HBR_DEMUX	8 /* HBR demux in I2S 32bit mode */
+#define TDA1997X_SPDIF_HBR_DEMUX	9 /* HBR demux in SPDIF mode */
+
+/* Audio bus channel layout */
+#define TDA1997X_LAYOUT0	0	/* 2-channel */
+#define TDA1997X_LAYOUT1	1	/* 8-channel */
+
+/* Audio bus clock */
+#define TDA1997X_ACLK_16FS	0
+#define TDA1997X_ACLK_32FS	1
+#define TDA1997X_ACLK_64FS	2
+#define TDA1997X_ACLK_128FS	3
+#define TDA1997X_ACLK_256FS	4
+#define TDA1997X_ACLK_512FS	5
+
+#endif /* _DT_BINDINGS_MEDIA_TDA1997X_H */
diff --git a/include/dt-structs.h b/include/dt-structs.h
index f0e1c9c..f9ccaf5 100644
--- a/include/dt-structs.h
+++ b/include/dt-structs.h
@@ -24,7 +24,9 @@
 	uint idx;
 	int arg[2];
 };
+
 #include <generated/dt-structs-gen.h>
+#include <generated/dt-decl.h>
 #endif
 
 #endif
diff --git a/include/efi_api.h b/include/efi_api.h
index 4ccde1d..18a1adf 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -1732,6 +1732,23 @@
 					 void *buffer);
 };
 
+struct efi_system_resource_entry {
+	efi_guid_t fw_class;
+	u32 fw_type;
+	u32 fw_version;
+	u32 lowest_supported_fw_version;
+	u32 capsule_flags;
+	u32 last_attempt_version;
+	u32 last_attempt_status;
+} __packed;
+
+struct efi_system_resource_table {
+	u32 fw_resource_count;
+	u32 fw_resource_count_max;
+	u64 fw_resource_version;
+	struct efi_system_resource_entry entries[];
+} __packed;
+
 /* Boot manager load options */
 #define LOAD_OPTION_ACTIVE		0x00000001
 #define LOAD_OPTION_FORCE_RECONNECT	0x00000002
@@ -1750,6 +1767,10 @@
 #define ESRT_FW_TYPE_DEVICEFIRMWARE	0x00000002
 #define ESRT_FW_TYPE_UEFIDRIVER		0x00000003
 
+#define EFI_SYSTEM_RESOURCE_TABLE_GUID\
+	EFI_GUID(0xb122a263, 0x3661, 0x4f68,\
+		0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80)
+
 /* Last Attempt Status Values */
 #define LAST_ATTEMPT_STATUS_SUCCESS			0x00000000
 #define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL		0x00000001
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 68daa1a..de1a496 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -214,6 +214,8 @@
 extern const efi_guid_t efi_guid_capsule_report;
 /* GUID of firmware management protocol */
 extern const efi_guid_t efi_guid_firmware_management_protocol;
+/* GUID for the ESRT */
+extern const efi_guid_t efi_esrt_guid;
 
 extern unsigned int __efi_runtime_start, __efi_runtime_stop;
 extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop;
@@ -437,6 +439,7 @@
 /* Called by bootefi to make the watchdog available */
 efi_status_t efi_watchdog_register(void);
 efi_status_t efi_initrd_register(void);
+void efi_initrd_deregister(void);
 /* Called by bootefi to make SMBIOS tables available */
 /**
  * efi_acpi_register() - write out ACPI tables
@@ -558,6 +561,15 @@
 /* open file from device-path: */
 struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp);
 
+/* Registers a callback function for a notification event. */
+efi_status_t EFIAPI efi_register_protocol_notify(const efi_guid_t *protocol,
+						 struct efi_event *event,
+						 void **registration);
+efi_status_t efi_file_size(struct efi_file_handle *fh, efi_uintn_t *size);
+
+/* get a device path from a Boot#### option */
+struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid);
+
 /**
  * efi_size_in_pages() - convert size in bytes to size in pages
  *
@@ -723,6 +735,8 @@
 			u64 *remaining_variable_storage_size,
 			u64 *maximum_variable_size);
 
+void *efi_get_var(u16 *name, const efi_guid_t *vendor, efi_uintn_t *size);
+
 /*
  * See section 3.1.3 in the v2.7 UEFI spec for more details on
  * the layout of EFI_LOAD_OPTION.  In short it is:
@@ -744,6 +758,10 @@
 	const u8 *optional_data;
 };
 
+struct efi_device_path *efi_dp_from_lo(struct efi_load_option *lo,
+				       efi_uintn_t *size, efi_guid_t guid);
+struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1,
+				      const struct efi_device_path *dp2);
 efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
 					 efi_uintn_t *size);
 unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data);
@@ -890,4 +908,22 @@
 
 #endif /* CONFIG_IS_ENABLED(EFI_LOADER) */
 
+/**
+ * Install the ESRT system table.
+ *
+ * @return	status code
+ */
+efi_status_t efi_esrt_register(void);
+
+/**
+ * efi_esrt_populate() - Populates the ESRT entries from the FMP instances
+ * present in the system.
+ * If an ESRT already exists, the old ESRT is replaced in the system table.
+ * The memory of the old ESRT is deallocated.
+ *
+ * Return:
+ * - EFI_SUCCESS if the ESRT is correctly created
+ * - error code otherwise.
+ */
+efi_status_t efi_esrt_populate(void);
 #endif /* _EFI_LOADER_H */
diff --git a/include/efi_selftest.h b/include/efi_selftest.h
index 1515fda..07b6199 100644
--- a/include/efi_selftest.h
+++ b/include/efi_selftest.h
@@ -66,11 +66,10 @@
 	 */
 	EFI_SETUP_BEFORE_BOOTTIME_EXIT,
 	/**
-	 * @EFI_SETUP_AFTER_BOOTTIME_EXIT: - setup after ExitBootServices
-	 *
-	 * Setup, execute, and teardown are executed after ExitBootServices().
+	 * @EFI_SETTING_VIRTUAL_ADDRESS_MAP - calls SetVirtualAddressMap()
+	 * Execute calls SetVirtualAddressMap().
 	 */
-	EFI_SETUP_AFTER_BOOTTIME_EXIT,
+	EFI_SETTING_VIRTUAL_ADDRESS_MAP,
 };
 
 extern struct efi_simple_text_output_protocol *con_out;
diff --git a/include/flash.h b/include/flash.h
index 3bf6b22..42b18a6 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -24,6 +24,8 @@
 #ifdef CONFIG_SYS_FLASH_CFI
 	uchar	portwidth;		/* the width of the port		*/
 	uchar	chipwidth;		/* the width of the chip		*/
+	uchar	chip_lsb;		/* extra Least Significant Bit in the */
+					/* address of chip	*/
 	ushort	buffer_size;		/* # of bytes in write buffer		*/
 	ulong	erase_blk_tout;		/* maximum block erase timeout		*/
 	ulong	write_tout;		/* maximum write timeout		*/
diff --git a/include/fsl_esdhc.h b/include/fsl_esdhc.h
index 850a304..f86afe5 100644
--- a/include/fsl_esdhc.h
+++ b/include/fsl_esdhc.h
@@ -190,6 +190,9 @@
 #define DLL_RESET		0x40000000
 #define DLL_FREQ_SEL		0x08000000
 
+/* DLL config 1 register */
+#define DLL_PD_PULSE_STRETCH_SEL 0x80000000
+
 /* DLL status 0 register */
 #define DLL_STS_SLV_LOCK	0x08000000
 
diff --git a/include/fsl_esdhc_imx.h b/include/fsl_esdhc_imx.h
index 45ed635..b092034 100644
--- a/include/fsl_esdhc_imx.h
+++ b/include/fsl_esdhc_imx.h
@@ -39,6 +39,7 @@
 #define VENDORSPEC_HCKEN	0x00001000
 #define VENDORSPEC_IPGEN	0x00000800
 #define VENDORSPEC_INIT		0x20007809
+#define VENDORSPEC_FRC_SDCLK_ON 0x00000100
 
 #define IRQSTAT			0x0002e030
 #define IRQSTAT_DMAE		(0x10000000)
@@ -96,6 +97,7 @@
 #define PRSSTAT_CINS		(0x00010000)
 #define PRSSTAT_BREN		(0x00000800)
 #define PRSSTAT_BWEN		(0x00000400)
+#define PRSSTAT_SDOFF		(0x00000080)
 #define PRSSTAT_SDSTB		(0X00000008)
 #define PRSSTAT_DLA		(0x00000004)
 #define PRSSTAT_CICHB		(0x00000002)
diff --git a/include/fsl_sec.h b/include/fsl_sec.h
index 1c6f1eb..c412169 100644
--- a/include/fsl_sec.h
+++ b/include/fsl_sec.h
@@ -3,6 +3,7 @@
  * Common internal memory map for some Freescale SoCs
  *
  * Copyright 2014 Freescale Semiconductor, Inc.
+ * Copyright 2018 NXP
  */
 
 #ifndef __FSL_SEC_H
@@ -12,8 +13,8 @@
 #include <asm/io.h>
 
 #ifdef CONFIG_SYS_FSL_SEC_LE
-#define sec_in32(a)       in_le32(a)
-#define sec_out32(a, v)   out_le32(a, v)
+#define sec_in32(a)       in_le32((ulong *)(ulong)a)
+#define sec_out32(a, v)   out_le32((ulong *)(ulong)a, v)
 #define sec_in16(a)       in_le16(a)
 #define sec_clrbits32     clrbits_le32
 #define sec_setbits32     setbits_le32
@@ -27,6 +28,8 @@
 #error Neither CONFIG_SYS_FSL_SEC_LE nor CONFIG_SYS_FSL_SEC_BE is defined
 #endif
 
+#define BLOB_SIZE(x)		((x) + 32 + 16) /* Blob buffer size */
+
 /* Security Engine Block (MS = Most Sig., LS = Least Sig.) */
 #if CONFIG_SYS_FSL_SEC_COMPAT >= 4
 /* RNG4 TRNG test registers */
@@ -195,7 +198,8 @@
 
 struct jr_regs {
 #if defined(CONFIG_SYS_FSL_SEC_LE) && \
-	!(defined(CONFIG_MX6) || defined(CONFIG_MX7))
+	!(defined(CONFIG_MX6) || defined(CONFIG_MX7) || \
+	  defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8M))
 	u32 irba_l;
 	u32 irba_h;
 #else
@@ -209,7 +213,8 @@
 	u32 rsvd3;
 	u32 irja;
 #if defined(CONFIG_SYS_FSL_SEC_LE) && \
-	!(defined(CONFIG_MX6) || defined(CONFIG_MX7))
+	!(defined(CONFIG_MX6) || defined(CONFIG_MX7) || \
+	  defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8M))
 	u32 orba_l;
 	u32 orba_h;
 #else
@@ -242,7 +247,8 @@
  */
 struct sg_entry {
 #if defined(CONFIG_SYS_FSL_SEC_LE) && \
-	!(defined(CONFIG_MX6) || defined(CONFIG_MX7))
+	!(defined(CONFIG_MX6) || defined(CONFIG_MX7) || \
+	  defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8M))
 	uint32_t addr_lo;	/* Memory Address - lo */
 	uint32_t addr_hi;	/* Memory Address of start of buffer - hi */
 #else
@@ -261,9 +267,8 @@
 #define SG_ENTRY_OFFSET_SHIFT	0
 };
 
-#define BLOB_SIZE(x)		((x) + 32 + 16) /* Blob buffer size */
-
-#if defined(CONFIG_MX6) || defined(CONFIG_MX7)
+#if defined(CONFIG_MX6) || defined(CONFIG_MX7) || \
+	defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8M)
 /* Job Ring Base Address */
 #define JR_BASE_ADDR(x) (CONFIG_SYS_FSL_SEC_ADDR + 0x1000 * (x + 1))
 /* Secure Memory Offset varies accross versions */
@@ -271,7 +276,8 @@
 #define SM_V2_OFFSET 0xa00
 /*Secure Memory Versioning */
 #define SMVID_V2 0x20105
-#define SM_VERSION(x)  (x < SMVID_V2 ? 1 : 2)
+#define SM_VERSION(x)  ({typeof(x) _x = x; \
+		_x < SMVID_V2 ? 1 : (_x < 0x20300 ? 2 : 3); })
 #define SM_OFFSET(x)  (x == 1 ? SM_V1_OFFSET : SM_V2_OFFSET)
 /* CAAM Job Ring 0 Registers */
 /* Secure Memory Partition Owner register */
@@ -298,8 +304,10 @@
 #define SM_CMD(v)		(v == 1 ? 0x0 : 0x1E4)
 #define SM_STATUS(v)		(v == 1 ? 0x8 : 0x1EC)
 #define SM_PERM(v)		(v == 1 ?  0x10 : 0x4)
-#define SM_GROUP2(v)		(v == 1 ? 0x14 : 0x8)
-#define SM_GROUP1(v)		(v == 1 ? 0x18 : 0xC)
+#define SM_GROUP2(v)		({typeof(v) _v = v; \
+		_v == 1 ? 0x14 : (_v == 2 ? 0x8 : 0xC); })
+#define SM_GROUP1(v)		({typeof(v) _v = v; \
+		_v == 1 ? 0x18 : (_v == 2 ? 0xC : 0x8); })
 #define CMD_PAGE_ALLOC		0x1
 #define CMD_PAGE_DEALLOC	0x2
 #define CMD_PART_DEALLOC	0x3
@@ -317,10 +325,15 @@
 #define SEC_MEM_PAGE2		(CAAM_ARB_BASE_ADDR + 0x2000)
 #define SEC_MEM_PAGE3		(CAAM_ARB_BASE_ADDR + 0x3000)
 
-#define JR_MID			2               /* Matches ROM configuration */
-#define KS_G1			(1 << JR_MID)   /* CAAM only */
-#define PERM			0x0000B008      /* Clear on release, lock SMAP
-						 * lock SMAG group 1 Blob */
+#ifdef CONFIG_IMX8M
+#define JR_MID    (1)         /* Matches ATF configuration */
+#define KS_G1     (0x10000 << JR_MID) /* CAAM only */
+#define PERM      (0xB080)    /* CSP, SMAP_LCK, SMAG_LCK, G1_BLOB */
+#else
+#define JR_MID    (2)         /* Matches ROM configuration */
+#define KS_G1     BIT(JR_MID) /* CAAM only */
+#define PERM      (0xB008)    /* CSP, SMAP_LCK, SMAG_LCK, G1_BLOB */
+#endif /* CONFIG_IMX8M */
 
 /* HAB WRAPPED KEY header */
 #define WRP_HDR_SIZE		0x08
@@ -340,6 +353,13 @@
 
 #endif
 
+#define FSL_CAAM_MP_PUBK_BYTES		    64
+#define FSL_CAAM_MP_PRVK_BYTES		    32
+#define FSL_CAAM_MP_MES_DGST_BYTES	    32
+
+#define FSL_CAAM_ORSR_JRa_OFFSET	0x102c
+#define FSL_CAAM_MAX_JR_SIZE		4
+
 /* blob_dek:
  * Encapsulates the src in a secure blob and stores it dst
  * @src: reference to the plaintext
@@ -349,6 +369,10 @@
  */
 int blob_dek(const u8 *src, u8 *dst, u8 len);
 
+int gen_mppubk(u8 *dst);
+
+int sign_mppubk(const u8 *m, int data_size, u8 *dgst, u8 *c, u8 *d);
+
 #if defined(CONFIG_ARCH_C29X)
 int sec_init_idx(uint8_t);
 #endif
diff --git a/include/i2c.h b/include/i2c.h
index 7ae0c42..c0fe94c 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -93,6 +93,8 @@
  *			   datasheet explains it's usage of this addressing
  *			   mode.
  * @emul: Emulator for this chip address (only used for emulation)
+ * @emul_idx: Emulator index, used for of-platdata and set by each i2c chip's
+ *	bind() method. This allows i2c_emul_find() to work with of-platdata.
  */
 struct dm_i2c_chip {
 	uint chip_addr;
@@ -102,6 +104,7 @@
 #ifdef CONFIG_SANDBOX
 	struct udevice *emul;
 	bool test_mode;
+	int emul_idx;
 #endif
 };
 
@@ -555,6 +558,18 @@
 int i2c_emul_find(struct udevice *dev, struct udevice **emulp);
 
 /**
+ * i2c_emul_set_idx() - Set the emulator index for an i2c sandbox device
+ *
+ * With of-platdata we cannot find the emulator using the device tree, so rely
+ * on the bind() method of each i2c driver calling this function to tell us
+ * the of-platdata idx of the emulator
+ *
+ * @dev: i2c device to set the emulator for
+ * @emul_idx: of-platdata index for that emulator
+ */
+void i2c_emul_set_idx(struct udevice *dev, int emul_idx);
+
+/**
  * i2c_emul_get_device() - Find the device being emulated
  *
  * Given an emulator this returns the associated device
diff --git a/include/image.h b/include/image.h
index b4b284d..aeb0d37 100644
--- a/include/image.h
+++ b/include/image.h
@@ -886,6 +886,11 @@
 }
 static inline int image_check_arch(const image_header_t *hdr, uint8_t arch)
 {
+#ifndef USE_HOSTCC
+	/* Let's assume that sandbox can load any architecture */
+	if (IS_ENABLED(CONFIG_SANDBOX))
+		return true;
+#endif
 	return (image_get_arch(hdr) == arch) ||
 		(image_get_arch(hdr) == IH_ARCH_ARM && arch == IH_ARCH_ARM64);
 }
diff --git a/include/linker_lists.h b/include/linker_lists.h
index fd98ecd..81a280a 100644
--- a/include/linker_lists.h
+++ b/include/linker_lists.h
@@ -212,6 +212,18 @@
 	})
 
 /**
+ * ll_entry_ref() - Get a reference to a linker-generated array entry
+ *
+ * Once an extern ll_entry_declare() has been used to declare the reference,
+ * this macro allows the entry to be accessed.
+ *
+ * This is like ll_entry_get(), but without the extra code, so it is suitable
+ * for putting into data structures.
+ */
+#define ll_entry_ref(_type, _name, _list)				\
+	((_type *)&_u_boot_list_2_##_list##_2_##_name)
+
+/**
  * ll_start() - Point to first entry of first linker-generated array
  * @_type:	Data type of the entry
  *
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index cc9c430..6fda14f 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -192,6 +192,8 @@
 	unsigned int	div;
 };
 
+extern const struct clk_ops clk_fixed_rate_ops;
+
 #define to_clk_fixed_factor(_clk) container_of(_clk, struct clk_fixed_factor,\
 					       clk)
 
@@ -202,6 +204,9 @@
 
 #define to_clk_fixed_rate(dev)	((struct clk_fixed_rate *)dev_get_plat(dev))
 
+void clk_fixed_rate_ofdata_to_plat_(struct udevice *dev,
+				    struct clk_fixed_rate *plat);
+
 struct clk_composite {
 	struct clk	clk;
 	struct clk_ops	ops;
diff --git a/include/linux/intel-smc.h b/include/linux/intel-smc.h
index cacb410..a54eff4 100644
--- a/include/linux/intel-smc.h
+++ b/include/linux/intel-smc.h
@@ -519,55 +519,21 @@
 	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_MBOX_SEND_CMD)
 
 /*
- * Request INTEL_SIP_SMC_HPS_SET_PHYINTF
+ * Request INTEL_SIP_SMC_GET_USERCODE
  *
- * Select EMACx PHY interface
+ * Send mailbox command to get usercode from SDM
  *
  * Call register usage:
- * a0 INTEL_SIP_SMC_HPS_SET_PHYINTF
- * a1 EMAC number:
- *      0 - EMAC0
- *      1 - EMAC1
- *      2 - EMAC2
- * a2 Type of PHY interface:
- *      0 - GMII_MII
- *      1 - RGMII
- *      2 - RMII
- *      3 - RESET
- * a3-7 not used
+ * a0 INTEL_SIP_SMC_GET_USERCODE
+ * a1-7 not used.
  *
  * Return status
  * a0 INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_STATUS_ERROR
+ * a1 User code
+ * a2-3 not used.
  */
-#define INTEL_SIP_SMC_FUNCID_HPS_SET_PHYINTF	61
-#define INTEL_SIP_SMC_HPS_SET_PHYINTF \
-	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_HPS_SET_PHYINTF)
-
-/*
- * Request INTEL_SIP_SMC_HPS_SET_SDMMC_CCLK
- *
- * Select which phase shift of the clocks (drvsel & smplsel) for SDMMC
- *
- * Call register usage:
- * a0 INTEL_SIP_SMC_HPS_SET_SDMMC_CCLK
- * a1 Select which phase shift of the clock for cclk_in_drv (drvsel):
- *      0 - 0 degree
- *      1 - 45 degrees
- *      2 - 90 degrees
- *      3 - 135 degrees
- *      4 - 180 degrees
- *      5 - 225 degrees
- *      6 - 270 degrees
- *      7 - 315 degrees
- * a2 Select which phase shift of the clock for cclk_in_sample (smplsel):
- *      (Same as above)
- * a3-7 not used
- *
- * Return status
- * a0 INTEL_SIP_SMC_STATUS_OK
- */
-#define INTEL_SIP_SMC_FUNCID_HPS_SET_SDMMC_CCLK	62
-#define INTEL_SIP_SMC_HPS_SET_SDMMC_CCLK \
-	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_HPS_SET_SDMMC_CCLK)
+#define INTEL_SIP_SMC_FUNCID_GET_USERCODE	61
+#define INTEL_SIP_SMC_GET_USERCODE \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_GET_USERCODE)
 
 #endif
diff --git a/include/log.h b/include/log.h
index 2d27f9f..add3a1e 100644
--- a/include/log.h
+++ b/include/log.h
@@ -222,11 +222,14 @@
 #define _SPL_BUILD	0
 #endif
 
-#if !_DEBUG && CONFIG_IS_ENABLED(LOG)
+#if CONFIG_IS_ENABLED(LOG)
 
-#define debug_cond(cond, fmt, args...)			\
-({							\
-	log(LOG_CATEGORY, LOGL_DEBUG, fmt, ##args);	\
+#define debug_cond(cond, fmt, args...)					\
+({									\
+	if (cond)							\
+		log(LOG_CATEGORY,					\
+		    (enum log_level_t)(LOGL_FORCE_DEBUG | _LOG_DEBUG),	\
+		    fmt, ##args);					\
 })
 
 #else /* _DEBUG */
@@ -316,12 +319,40 @@
 		    __ret); \
 	__ret; \
 	})
+
+/*
+ * Similar to the above, but any non-zero value is consider an error, not just
+ * values less than 0.
+ */
+#define log_retz(_ret) ({ \
+	int __ret = (_ret); \
+	if (__ret) \
+		log(LOG_CATEGORY, LOGL_ERR, "returning err=%d\n", __ret); \
+	__ret; \
+	})
+#define log_msg_retz(_msg, _ret) ({ \
+	int __ret = (_ret); \
+	if (__ret) \
+		log(LOG_CATEGORY, LOGL_ERR, "%s: returning err=%d\n", _msg, \
+		    __ret); \
+	__ret; \
+	})
 #else
 /* Non-logging versions of the above which just return the error code */
 #define log_ret(_ret) (_ret)
 #define log_msg_ret(_msg, _ret) ((void)(_msg), _ret)
+#define log_retz(_ret) (_ret)
+#define log_msg_retz(_msg, _ret) ((void)(_msg), _ret)
 #endif
 
+/** * enum log_rec_flags - Flags for a log record */
+enum log_rec_flags {
+	/** @LOGRECF_FORCE_DEBUG: Force output of debug record */
+	LOGRECF_FORCE_DEBUG	= BIT(0),
+	/** @LOGRECF_CONT: Continuation of previous log record */
+	LOGRECF_CONT		= BIT(1),
+};
+
 /**
  * struct log_rec - a single log record
  *
@@ -337,18 +368,18 @@
  *
  * @cat: Category, representing a uclass or part of U-Boot
  * @level: Severity level, less severe is higher
- * @force_debug: Force output of debug
- * @file: Name of file where the log record was generated (not allocated)
  * @line: Line number where the log record was generated
+ * @flags: Flags for log record (enum log_rec_flags)
+ * @file: Name of file where the log record was generated (not allocated)
  * @func: Function where the log record was generated (not allocated)
  * @msg: Log message (allocated)
  */
 struct log_rec {
 	enum log_category_t cat;
 	enum log_level_t level;
-	bool force_debug;
+	u16 line;
+	u8 flags;
 	const char *file;
-	int line;
 	const char *func;
 	const char *msg;
 };
diff --git a/include/malloc.h b/include/malloc.h
index e15e528..024b18b 100644
--- a/include/malloc.h
+++ b/include/malloc.h
@@ -880,6 +880,8 @@
 
 #else
 
+void malloc_simple_info(void);
+
 #if CONFIG_IS_ENABLED(SYS_MALLOC_SIMPLE)
 #define malloc malloc_simple
 #define realloc realloc_simple
@@ -887,7 +889,6 @@
 static inline void free(void *ptr) {}
 void *calloc(size_t nmemb, size_t size);
 void *realloc_simple(void *ptr, size_t size);
-void malloc_simple_info(void);
 #else
 
 # ifdef USE_DL_PREFIX
diff --git a/include/mvebu_mmc.h b/include/mvebu_mmc.h
index a35e5a1..e75c3fa 100644
--- a/include/mvebu_mmc.h
+++ b/include/mvebu_mmc.h
@@ -258,17 +258,10 @@
 /* Hardware reset */
 #define MMC_CAP_HW_RESET			(1 << 31)
 
-struct mvebu_mmc_cfg {
-	u32	mvebu_mmc_base;
-	u32	mvebu_mmc_clk;
-	u8	max_bus_width;
+struct mvebu_mmc_plat {
+	void *iobase;
 	struct mmc_config cfg;
+	struct mmc mmc;
 };
 
-/*
- * Functions prototypes
- */
-
-int mvebu_mmc_init(struct bd_info *bis);
-
 #endif /* __MVEBU_MMC_H__ */
diff --git a/include/os.h b/include/os.h
index 65bcb23..bd1096e 100644
--- a/include/os.h
+++ b/include/os.h
@@ -114,7 +114,7 @@
  * os_malloc() - aquires some memory from the underlying os.
  *
  * @length:	Number of bytes to be allocated
- * Return:	Pointer to length bytes or NULL on error
+ * Return:	Pointer to length bytes or NULL if @length is 0 or on error
  */
 void *os_malloc(size_t length);
 
@@ -123,11 +123,24 @@
  *
  * This returns the memory to the OS.
  *
- * @ptr:	Pointer to memory block to free
+ * @ptr:	Pointer to memory block to free. If this is NULL then this
+ *		function does nothing
  */
 void os_free(void *ptr);
 
 /**
+ * os_realloc() - reallocate memory
+ *
+ * This follows the semantics of realloc(), so can perform an os_malloc() or
+ * os_free() depending on @ptr and @length.
+ *
+ * @ptr:	pointer to previously allocated memory of NULL
+ * @length:	number of bytes to allocate
+ * Return:	pointer to reallocated memory or NULL if @length is 0
+ */
+void *os_realloc(void *ptr, size_t length);
+
+/**
  * os_usleep() - access to the usleep function of the os
  *
  * @usec:	time to sleep in micro seconds
@@ -313,9 +326,10 @@
  *
  * @fname:	place to put full path to U-Boot
  * @maxlen:	maximum size of @fname
+ * @use_img:	select the 'u-boot.img' file instead of the 'u-boot' ELF file
  * Return:	0 if OK, -NOSPC if the filename is too large, -ENOENT if not found
  */
-int os_find_u_boot(char *fname, int maxlen);
+int os_find_u_boot(char *fname, int maxlen, bool use_img);
 
 /**
  * os_spl_to_uboot() - Run U-Boot proper
diff --git a/include/power/pca9450.h b/include/power/pca9450.h
index 5a9a697..27703bb 100644
--- a/include/power/pca9450.h
+++ b/include/power/pca9450.h
@@ -54,6 +54,6 @@
 	PCA9450_REG_NUM,
 };
 
-int power_pca9450_init(unsigned char bus);
+int power_pca9450_init(unsigned char bus, unsigned char addr);
 
 #endif
diff --git a/include/sandboxblockdev.h b/include/sandboxblockdev.h
index c1f0afb..4006e94 100644
--- a/include/sandboxblockdev.h
+++ b/include/sandboxblockdev.h
@@ -14,6 +14,13 @@
 	int fd;
 };
 
-int host_dev_bind(int dev, char *filename);
+/**
+ * host_dev_bind() - Bind or unbind a device
+ *
+ * @dev: Device number (0=first slot)
+ * @filename: Host filename to use, or NULL to unbind
+ * @removable: true if the block device should mark itself as removable
+ */
+int host_dev_bind(int dev, char *filename, bool removable);
 
 #endif
diff --git a/include/scp03.h b/include/scp03.h
new file mode 100644
index 0000000..729667c
--- /dev/null
+++ b/include/scp03.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2021, Foundries.IO
+ *
+ */
+
+#ifndef _SCP03_H
+#define _SCP03_H
+
+/*
+ * Requests to OPTEE to enable or provision the Secure Channel Protocol on its
+ * Secure Element
+ *
+ *  If key provisioning is requested, OPTEE shall generate new SCP03 keys and
+ *  write them to the Secure Element.
+ *
+ *  Both functions return < 0 on error else 0.
+ */
+int tee_enable_scp03(void);
+int tee_provision_scp03(void);
+#endif /* _SCP03_H */
diff --git a/include/smbios.h b/include/smbios.h
index ecc4fd1..ffeefb4 100644
--- a/include/smbios.h
+++ b/include/smbios.h
@@ -14,6 +14,10 @@
 #define SMBIOS_MAJOR_VER	3
 #define SMBIOS_MINOR_VER	0
 
+enum {
+	SMBIOS_STR_MAX	= 64,	/* Maximum length allowed for a string */
+};
+
 /* SMBIOS structure types */
 enum {
 	SMBIOS_BIOS_INFORMATION = 0,
@@ -269,4 +273,20 @@
  */
 int smbios_update_version(const char *version);
 
+/**
+ * smbios_update_version_full() - Update the version string
+ *
+ * This can be called after the SMBIOS tables are written (e.g. after the U-Boot
+ * main loop has started) to update the BIOS version string (SMBIOS table 0).
+ * It scans for the correct place to put the version, so does not need U-Boot
+ * to have actually written the tables itself (e.g. if a previous bootloader
+ * did it).
+ *
+ * @smbios_tab: Start of SMBIOS tables
+ * @version: New version string to use
+ * @return 0 if OK, -ENOENT if no version string was previously written,
+ *	-ENOSPC if the new string is too large to fit
+ */
+int smbios_update_version_full(void *smbios_tab, const char *version);
+
 #endif /* _SMBIOS_H_ */
diff --git a/include/spi-mem.h b/include/spi-mem.h
index 8be3e2b..e354c38 100644
--- a/include/spi-mem.h
+++ b/include/spi-mem.h
@@ -222,7 +222,7 @@
 				   const struct spi_mem_op *op,
 				   struct sg_table *sg)
 {
-	return -ENOTSUPP;
+	return -ENOSYS;
 }
 
 static inline void
diff --git a/include/spi_flash.h b/include/spi_flash.h
index 85cae32..3d747c9 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -35,6 +35,19 @@
 	int (*write)(struct udevice *dev, u32 offset, size_t len,
 		     const void *buf);
 	int (*erase)(struct udevice *dev, u32 offset, size_t len);
+	/**
+	 * get_sw_write_prot() - Check state of software write-protect feature
+	 *
+	 * SPI flash chips can lock a region of the flash defined by a
+	 * 'protected area'. This function checks if this protected area is
+	 * defined.
+	 *
+	 * @dev:	SPI flash device
+	 * @return 0 if no region is write-protected, 1 if a region is
+	 *	write-protected, -ENOSYS if the driver does not implement this,
+	 *	other -ve value on error
+	 */
+	int (*get_sw_write_prot)(struct udevice *dev);
 };
 
 /* Access the serial operations for a device */
@@ -77,6 +90,20 @@
 int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len);
 
 /**
+ * spl_flash_get_sw_write_prot() - Check state of software write-protect feature
+ *
+ * SPI flash chips can lock a region of the flash defined by a
+ * 'protected area'. This function checks if this protected area is
+ * defined.
+ *
+ * @dev:	SPI flash device
+ * @return 0 if no region is write-protected, 1 if a region is
+ *	write-protected, -ENOSYS if the driver does not implement this,
+ *	other -ve value on error
+ */
+int spl_flash_get_sw_write_prot(struct udevice *dev);
+
+/**
  * spi_flash_std_probe() - Probe a SPI flash device
  *
  * This is the standard internal method for probing a SPI flash device to
@@ -97,7 +124,9 @@
 				  unsigned int max_hz, unsigned int spi_mode);
 
 /* Compatibility function - this is the old U-Boot API */
-void spi_flash_free(struct spi_flash *flash);
+static inline void spi_flash_free(struct spi_flash *flash)
+{
+}
 
 static inline int spi_flash_read(struct spi_flash *flash, u32 offset,
 				 size_t len, void *buf)
diff --git a/include/spl.h b/include/spl.h
index 0d13458..4f6e0e5 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -222,6 +222,15 @@
 	void *priv;
 	int bl_len;
 	const char *filename;
+	/**
+	 * read() - Read from device
+	 *
+	 * @load: Information about the load state
+	 * @sector: Sector number to read from (each @load->bl_len bytes)
+	 * @count: Number of sectors to read
+	 * @buf: Buffer to read into
+	 * @return number of sectors read, 0 on error
+	 */
 	ulong (*read)(struct spl_load_info *load, ulong sector, ulong count,
 		      void *buf);
 };
diff --git a/include/sysinfo.h b/include/sysinfo.h
index 270ac1b..68fad25 100644
--- a/include/sysinfo.h
+++ b/include/sysinfo.h
@@ -37,9 +37,13 @@
 enum sysinfo_id {
 	SYSINFO_ID_NONE,
 
+	/* For SMBIOS tables */
 	SYSINFO_ID_SMBIOS_SYSTEM_VERSION,
 	SYSINFO_ID_SMBIOS_BASEBOARD_VERSION,
 
+	/* For show_board_info() */
+	SYSINFO_ID_BOARD_MODEL,
+
 	/* First value available for downstream/board used */
 	SYSINFO_ID_USER = 0x1000,
 };
diff --git a/include/sysreset.h b/include/sysreset.h
index 8bb094d..701e4f5 100644
--- a/include/sysreset.h
+++ b/include/sysreset.h
@@ -116,6 +116,6 @@
 /**
  * reset_cpu() - calls sysreset_walk(SYSRESET_WARM)
  */
-void reset_cpu(ulong addr);
+void reset_cpu(void);
 
 #endif
diff --git a/include/tee/optee_ta_scp03.h b/include/tee/optee_ta_scp03.h
new file mode 100644
index 0000000..13f9956
--- /dev/null
+++ b/include/tee/optee_ta_scp03.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * (C) Copyright 2021, Foundries.IO
+ *
+ */
+#ifndef __TA_SCP03_H
+#define __TA_SCP03_H
+
+#define PTA_SCP03_UUID { 0xbe0e5821, 0xe718, 0x4f77, \
+			{ 0xab, 0x3e, 0x8e, 0x6c, 0x73, 0xa9, 0xc7, 0x35 } }
+
+/*
+ * Enable Secure Channel Protocol functionality (SCP03) on the Secure Element.
+ *   Setting the operation value to something different than NULL will trigger
+ *   the SCP03 provisioning request.
+ *
+ *   in	params[0].a = operation
+ */
+#define PTA_CMD_ENABLE_SCP03	0
+
+#endif /*__TA_SCP03_H*/
diff --git a/include/test/test.h b/include/test/test.h
index 3fdaa2b..bf7d785 100644
--- a/include/test/test.h
+++ b/include/test/test.h
@@ -14,16 +14,24 @@
  *
  * @fail_count: Number of tests that failed
  * @start: Store the starting mallinfo when doing leak test
- * @priv: A pointer to some other info some suites want to track
+ * @of_live: true to use livetree if available, false to use flattree
  * @of_root: Record of the livetree root node (used for setting up tests)
+ * @root: Root device
+ * @testdev: Test device
+ * @force_fail_alloc: Force all memory allocs to fail
+ * @skip_post_probe: Skip uclass post-probe processing
  * @expect_str: Temporary string used to hold expected string value
  * @actual_str: Temporary string used to hold actual string value
  */
 struct unit_test_state {
 	int fail_count;
 	struct mallinfo start;
-	void *priv;
 	struct device_node *of_root;
+	bool of_live;
+	struct udevice *root;
+	struct udevice *testdev;
+	int force_fail_alloc;
+	int skip_post_probe;
 	char expect_str[256];
 	char actual_str[256];
 };
@@ -36,6 +44,8 @@
 	UT_TESTF_FLAT_TREE	= BIT(3),	/* test needs flat DT */
 	UT_TESTF_LIVE_TREE	= BIT(4),	/* needs live device tree */
 	UT_TESTF_CONSOLE_REC	= BIT(5),	/* needs console recording */
+	/* do extra driver model init and uninit */
+	UT_TESTF_DM		= BIT(6),
 };
 
 /**
@@ -76,13 +86,24 @@
  * @_suite:	name of the test suite concatenated with "_test"
  */
 #define UNIT_TEST(_name, _flags, _suite)				\
-	ll_entry_declare(struct unit_test, _name, _suite) = {		\
+	ll_entry_declare(struct unit_test, _name, ut_ ## _suite) = {	\
 		.file = __FILE__,					\
 		.name = #_name,						\
 		.flags = _flags,					\
 		.func = _name,						\
 	}
 
+/* Get the start of a list of unit tests for a particular suite */
+#define UNIT_TEST_SUITE_START(_suite) \
+	ll_entry_start(struct unit_test, ut_ ## _suite)
+#define UNIT_TEST_SUITE_COUNT(_suite) \
+	ll_entry_count(struct unit_test, ut_ ## _suite)
+
+/* Use ! and ~ so that all tests will be sorted between these two values */
+#define UNIT_TEST_ALL_START()	ll_entry_start(struct unit_test, ut_!)
+#define UNIT_TEST_ALL_END()	ll_entry_start(struct unit_test, ut_~)
+#define UNIT_TEST_ALL_COUNT()	(UNIT_TEST_ALL_END() - UNIT_TEST_ALL_START())
+
 /* Sizes for devres tests */
 enum {
 	TEST_DEVRES_SIZE	= 100,
@@ -103,15 +124,13 @@
  */
 struct udevice *testbus_get_clear_removed(void);
 
-/**
- * dm_test_main() - Run driver model tests
- *
- * Run all the available driver model tests, or a selection
- *
- * @test_name: Name of single test to run (e.g. "dm_test_fdt_pre_reloc" or just
- *	"fdt_pre_reloc"), or NULL to run all
- * @return 0 if all tests passed, 1 if not
- */
-int dm_test_main(const char *test_name);
+static inline void arch_reset_for_test(void)
+{
+#ifdef CONFIG_SANDBOX
+#include <asm/state.h>
+
+	state_reset_for_test(state_get_current());
+#endif
+}
 
 #endif /* __TEST_TEST_H */
diff --git a/include/test/ut.h b/include/test/ut.h
index 17400c7..fbbba28 100644
--- a/include/test/ut.h
+++ b/include/test/ut.h
@@ -356,4 +356,49 @@
  */
 void ut_unsilence_console(struct unit_test_state *uts);
 
+/**
+ * ut_set_skip_delays() - Sets whether delays should be skipped
+ *
+ * Normally functions like mdelay() cause U-Boot to wait for a while. This
+ * allows all such delays to be skipped on sandbox, to speed up tests
+ *
+ * @uts: Test state (in case in future we want to keep state here)
+ * @skip_delays: true to skip delays, false to process them normally
+ */
+void ut_set_skip_delays(struct unit_test_state *uts, bool skip_delays);
+
+/**
+ * test_get_state() - Get the active test state
+ *
+ * @return the currently active test state, or NULL if none
+ */
+struct unit_test_state *test_get_state(void);
+
+/**
+ * test_set_state() - Set the active test state
+ *
+ * @uts: Test state to use as currently active test state, or NULL if none
+ */
+void test_set_state(struct unit_test_state *uts);
+
+/**
+ * ut_run_tests() - Run a set of tests
+ *
+ * This runs the test, handling any preparation and clean-up needed. It prints
+ * the name of each test before running it.
+ *
+ * @category: Category of these tests. This is a string printed at the start to
+ *	announce the the number of tests
+ * @prefix: String prefix for the tests. Any tests that have this prefix will be
+ *	printed without the prefix, so that it is easier to see the unique part
+ *	of the test name. If NULL, no prefix processing is done
+ * @tests: List of tests to run
+ * @count: Number of tests to run
+ * @select_name: Name of a single test to run (from the list provided). If NULL
+ *	then all tests are run
+ * @return 0 if all tests passed, -1 if any failed
+ */
+int ut_run_list(const char *name, const char *prefix, struct unit_test *tests,
+		int count, const char *select_name);
+
 #endif
diff --git a/include/tlv_eeprom.h b/include/tlv_eeprom.h
index 1de2fe2..a2c333e 100644
--- a/include/tlv_eeprom.h
+++ b/include/tlv_eeprom.h
@@ -114,19 +114,19 @@
 
 static inline int read_tlv_eeprom(void *eeprom, int offset, int len, int dev)
 {
-	return -ENOTSUPP;
+	return -ENOSYS;
 }
 
 static inline int write_tlv_eeprom(void *eeprom, int len)
 {
-	return -ENOTSUPP;
+	return -ENOSYS;
 }
 
 static inline int
 read_tlvinfo_tlv_eeprom(void *eeprom, struct tlvinfo_header **hdr,
 			struct tlvinfo_tlv **first_entry, int dev)
 {
-	return -ENOTSUPP;
+	return -ENOSYS;
 }
 
 #endif /* CONFIG_IS_ENABLED(CMD_TLV_EEPROM) */
diff --git a/include/tpm-common.h b/include/tpm-common.h
index c1309a2..998b4fb 100644
--- a/include/tpm-common.h
+++ b/include/tpm-common.h
@@ -55,6 +55,8 @@
  * @buf:		Buffer used during the exchanges with the chip
  * @pcr_count:		Number of PCR per bank
  * @pcr_select_min:	Minimum size in bytes of the pcrSelect array
+ * @plat_hier_disabled:	Platform hierarchy has been disabled (TPM is locked
+ *			down until next reboot)
  */
 struct tpm_chip_priv {
 	enum tpm_version version;
@@ -66,6 +68,7 @@
 	/* TPM v2 specific data */
 	uint pcr_count;
 	uint pcr_select_min;
+	bool plat_hier_disabled;
 };
 
 /**
diff --git a/include/tpm-v1.h b/include/tpm-v1.h
index 8f6cc28..fcfe1f0 100644
--- a/include/tpm-v1.h
+++ b/include/tpm-v1.h
@@ -289,7 +289,7 @@
  * @param mode		TPM startup mode
  * @return return code of the operation
  */
-u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode);
+u32 tpm1_startup(struct udevice *dev, enum tpm_startup_type mode);
 
 /**
  * Issue a TPM_SelfTestFull command.
@@ -297,7 +297,7 @@
  * @param dev		TPM device
  * @return return code of the operation
  */
-u32 tpm_self_test_full(struct udevice *dev);
+u32 tpm1_self_test_full(struct udevice *dev);
 
 /**
  * Issue a TPM_ContinueSelfTest command.
@@ -305,7 +305,7 @@
  * @param dev		TPM device
  * @return return code of the operation
  */
-u32 tpm_continue_self_test(struct udevice *dev);
+u32 tpm1_continue_self_test(struct udevice *dev);
 
 /**
  * Issue a TPM_NV_DefineSpace command.  The implementation is limited
@@ -318,7 +318,7 @@
  * @param size		size of the area
  * @return return code of the operation
  */
-u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size);
+u32 tpm1_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size);
 
 /**
  * Issue a TPM_NV_ReadValue command.  This implementation is limited
@@ -331,7 +331,7 @@
  * @param count		size of output buffer
  * @return return code of the operation
  */
-u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count);
+u32 tpm1_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count);
 
 /**
  * Issue a TPM_NV_WriteValue command.  This implementation is limited
@@ -344,8 +344,8 @@
  * @param length	length of data bytes of input buffer
  * @return return code of the operation
  */
-u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
-		       u32 length);
+u32 tpm1_nv_write_value(struct udevice *dev, u32 index, const void *data,
+			u32 length);
 
 /**
  * Issue a TPM_Extend command.
@@ -358,8 +358,8 @@
  *			command
  * @return return code of the operation
  */
-u32 tpm_extend(struct udevice *dev, u32 index, const void *in_digest,
-	       void *out_digest);
+u32 tpm1_extend(struct udevice *dev, u32 index, const void *in_digest,
+		void *out_digest);
 
 /**
  * Issue a TPM_PCRRead command.
@@ -370,7 +370,7 @@
  * @param count		size of output buffer
  * @return return code of the operation
  */
-u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count);
+u32 tpm1_pcr_read(struct udevice *dev, u32 index, void *data, size_t count);
 
 /**
  * Issue a TSC_PhysicalPresence command.  TPM physical presence flag
@@ -380,7 +380,7 @@
  * @param presence	TPM physical presence flag
  * @return return code of the operation
  */
-u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence);
+u32 tpm1_tsc_physical_presence(struct udevice *dev, u16 presence);
 
 /**
  * Issue a TPM_ReadPubek command.
@@ -390,7 +390,7 @@
  * @param count		size of output buffer
  * @return return code of the operation
  */
-u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count);
+u32 tpm1_read_pubek(struct udevice *dev, void *data, size_t count);
 
 /**
  * Issue a TPM_ForceClear command.
@@ -398,7 +398,7 @@
  * @param dev		TPM device
  * @return return code of the operation
  */
-u32 tpm_force_clear(struct udevice *dev);
+u32 tpm1_force_clear(struct udevice *dev);
 
 /**
  * Issue a TPM_PhysicalEnable command.
@@ -406,7 +406,7 @@
  * @param dev		TPM device
  * @return return code of the operation
  */
-u32 tpm_physical_enable(struct udevice *dev);
+u32 tpm1_physical_enable(struct udevice *dev);
 
 /**
  * Issue a TPM_PhysicalDisable command.
@@ -414,7 +414,7 @@
  * @param dev		TPM device
  * @return return code of the operation
  */
-u32 tpm_physical_disable(struct udevice *dev);
+u32 tpm1_physical_disable(struct udevice *dev);
 
 /**
  * Issue a TPM_PhysicalSetDeactivated command.
@@ -423,7 +423,7 @@
  * @param state		boolean state of the deactivated flag
  * @return return code of the operation
  */
-u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state);
+u32 tpm1_physical_set_deactivated(struct udevice *dev, u8 state);
 
 /**
  * Issue a TPM_GetCapability command.  This implementation is limited
@@ -437,8 +437,8 @@
  * @param count		size of output buffer
  * @return return code of the operation
  */
-u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
-		       void *cap, size_t count);
+u32 tpm1_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
+			void *cap, size_t count);
 
 /**
  * Issue a TPM_FlushSpecific command for a AUTH resource.
@@ -447,7 +447,7 @@
  * @param auth_handle	handle of the auth session
  * @return return code of the operation
  */
-u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle);
+u32 tpm1_terminate_auth_session(struct udevice *dev, u32 auth_handle);
 
 /**
  * Issue a TPM_OIAP command to setup an object independent authorization
@@ -460,7 +460,7 @@
  * @param auth_handle	pointer to the (new) auth handle or NULL.
  * @return return code of the operation
  */
-u32 tpm_oiap(struct udevice *dev, u32 *auth_handle);
+u32 tpm1_oiap(struct udevice *dev, u32 *auth_handle);
 
 /**
  * Ends an active OIAP session.
@@ -468,7 +468,7 @@
  * @param dev		TPM device
  * @return return code of the operation
  */
-u32 tpm_end_oiap(struct udevice *dev);
+u32 tpm1_end_oiap(struct udevice *dev);
 
 /**
  * Issue a TPM_LoadKey2 (Auth1) command using an OIAP session for authenticating
@@ -482,9 +482,9 @@
  * @param key_handle	pointer to the key handle
  * @return return code of the operation
  */
-u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
-		       size_t key_length, const void *parent_key_usage_auth,
-		       u32 *key_handle);
+u32 tpm1_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
+			size_t key_length, const void *parent_key_usage_auth,
+			u32 *key_handle);
 
 /**
  * Issue a TPM_GetPubKey (Auth1) command using an OIAP session for
@@ -500,9 +500,9 @@
  *			of the stored TPM_PUBKEY structure (iff pubkey != NULL).
  * @return return code of the operation
  */
-u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
-			 const void *usage_auth, void *pubkey,
-			 size_t *pubkey_len);
+u32 tpm1_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
+			  const void *usage_auth, void *pubkey,
+			  size_t *pubkey_len);
 
 /**
  * Get the TPM permanent flags value
@@ -511,8 +511,8 @@
  * @param pflags	Place to put permanent flags
  * @return return code of the operation
  */
-u32 tpm_get_permanent_flags(struct udevice *dev,
-			    struct tpm_permanent_flags *pflags);
+u32 tpm1_get_permanent_flags(struct udevice *dev,
+			     struct tpm_permanent_flags *pflags);
 
 /**
  * Get the TPM permissions
@@ -521,7 +521,7 @@
  * @param perm		Returns permissions value
  * @return return code of the operation
  */
-u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm);
+u32 tpm1_get_permissions(struct udevice *dev, u32 index, u32 *perm);
 
 /**
  * Flush a resource with a given handle and type from the TPM
@@ -531,7 +531,7 @@
  * @param resource_type                type of the resource
  * @return return code of the operation
  */
-u32 tpm_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type);
+u32 tpm1_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type);
 
 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
 /**
@@ -543,8 +543,8 @@
  * @param[out] handle	The handle of the key (Non-null iff found)
  * @return 0 if key was found in TPM; != 0 if not.
  */
-u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20],
-		      const u8 pubkey_digest[20], u32 *handle);
+u32 tpm1_find_key_sha1(struct udevice *dev, const u8 auth[20],
+		       const u8 pubkey_digest[20], u32 *handle);
 #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
 
 /**
@@ -557,7 +557,7 @@
  * @param count		size of output buffer
  * @return return code of the operation
  */
-u32 tpm_get_random(struct udevice *dev, void *data, u32 count);
+u32 tpm1_get_random(struct udevice *dev, void *data, u32 count);
 
 /**
  * tpm_finalise_physical_presence() - Finalise physical presence
@@ -565,15 +565,15 @@
  * @param dev		TPM device
  * @return return code of the operation (0 = success)
  */
-u32 tpm_finalise_physical_presence(struct udevice *dev);
+u32 tpm1_finalise_physical_presence(struct udevice *dev);
 
 /**
- * tpm_nv_set_locked() - lock the non-volatile space
+ * tpm_nv_enable_locking() - lock the non-volatile space
  *
  * @param dev		TPM device
  * @return return code of the operation (0 = success)
  */
-u32 tpm_nv_set_locked(struct udevice *dev);
+u32 tpm1_nv_set_locked(struct udevice *dev);
 
 /**
  * tpm_set_global_lock() - set the global lock
@@ -589,6 +589,6 @@
  * @param dev		TPM device
  * @return return code of the operation (0 = success)
  */
-u32 tpm_resume(struct udevice *dev);
+u32 tpm1_resume(struct udevice *dev);
 
 #endif /* __TPM_V1_H */
diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 56eaa65..df67a19 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -237,10 +237,14 @@
 enum tpm2_command_codes {
 	TPM2_CC_STARTUP		= 0x0144,
 	TPM2_CC_SELF_TEST	= 0x0143,
+	TPM2_CC_HIER_CONTROL	= 0x0121,
 	TPM2_CC_CLEAR		= 0x0126,
 	TPM2_CC_CLEARCONTROL	= 0x0127,
 	TPM2_CC_HIERCHANGEAUTH	= 0x0129,
+	TPM2_CC_NV_DEFINE_SPACE	= 0x012a,
 	TPM2_CC_PCR_SETAUTHPOL	= 0x012C,
+	TPM2_CC_NV_WRITE	= 0x0137,
+	TPM2_CC_NV_WRITELOCK	= 0x0138,
 	TPM2_CC_DAM_RESET	= 0x0139,
 	TPM2_CC_DAM_PARAMETERS	= 0x013A,
 	TPM2_CC_NV_READ         = 0x014E,
@@ -271,6 +275,7 @@
 	TPM2_RC_COMMAND_CODE	= TPM2_RC_VER1 + 0x0043,
 	TPM2_RC_AUTHSIZE	= TPM2_RC_VER1 + 0x0044,
 	TPM2_RC_AUTH_CONTEXT	= TPM2_RC_VER1 + 0x0045,
+	TPM2_RC_NV_DEFINED	= TPM2_RC_VER1 + 0x004c,
 	TPM2_RC_NEEDS_TEST	= TPM2_RC_VER1 + 0x0053,
 	TPM2_RC_WARN		= 0x0900,
 	TPM2_RC_TESTING		= TPM2_RC_WARN + 0x000A,
@@ -355,6 +360,20 @@
 	TPM_MAX_BUF_SIZE	= 1260,
 };
 
+enum {
+	/* Secure storage for firmware settings */
+	TPM_HT_PCR = 0,
+	TPM_HT_NV_INDEX,
+	TPM_HT_HMAC_SESSION,
+	TPM_HT_POLICY_SESSION,
+
+	HR_SHIFT		= 24,
+	HR_PCR			= TPM_HT_PCR << HR_SHIFT,
+	HR_HMAC_SESSION		= TPM_HT_HMAC_SESSION << HR_SHIFT,
+	HR_POLICY_SESSION	= TPM_HT_POLICY_SESSION << HR_SHIFT,
+	HR_NV_INDEX		= TPM_HT_NV_INDEX << HR_SHIFT,
+};
+
 /**
  * Issue a TPM2_Startup command.
  *
@@ -389,6 +408,23 @@
 	       const ssize_t pw_sz);
 
 /**
+ * Issue a TPM_NV_DefineSpace command
+ *
+ * This allows a space to be defined with given attributes and policy
+ *
+ * @dev			TPM device
+ * @space_index		index of the area
+ * @space_size		size of area in bytes
+ * @nv_attributes	TPM_NV_ATTRIBUTES of the area
+ * @nv_policy		policy to use
+ * @nv_policy_size	size of the policy
+ * @return return code of the operation
+ */
+u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
+			 size_t space_size, u32 nv_attributes,
+			 const u8 *nv_policy, size_t nv_policy_size);
+
+/**
  * Issue a TPM2_PCR_Extend command.
  *
  * @dev		TPM device
@@ -403,6 +439,29 @@
 		    const u8 *digest, u32 digest_len);
 
 /**
+ * Read data from the secure storage
+ *
+ * @dev		TPM device
+ * @index	Index of data to read
+ * @data	Place to put data
+ * @count	Number of bytes of data
+ * @return code of the operation
+ */
+u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count);
+
+/**
+ * Write data to the secure storage
+ *
+ * @dev		TPM device
+ * @index	Index of data to write
+ * @data	Data to write
+ * @count	Number of bytes of data
+ * @return code of the operation
+ */
+u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
+			u32 count);
+
+/**
  * Issue a TPM2_PCR_Read command.
  *
  * @dev		TPM device
@@ -516,4 +575,26 @@
  */
 u32 tpm2_get_random(struct udevice *dev, void *data, u32 count);
 
+/**
+ * Lock data in the TPM
+ *
+ * Once locked the data cannot be written until after a reboot
+ *
+ * @dev		TPM device
+ * @index	Index of data to lock
+ * @return code of the operation
+ */
+u32 tpm2_write_lock(struct udevice *dev, u32 index);
+
+/**
+ * Disable access to any platform data
+ *
+ * This can be called to close off access to the firmware data in the data,
+ * before calling the kernel.
+ *
+ * @dev		TPM device
+ * @return code of the operation
+ */
+u32 tpm2_disable_platform_hierarchy(struct udevice *dev);
+
 #endif /* __TPM_V2_H */
diff --git a/include/tpm_api.h b/include/tpm_api.h
new file mode 100644
index 0000000..f13d98c
--- /dev/null
+++ b/include/tpm_api.h
@@ -0,0 +1,322 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2013 The Chromium OS Authors.
+ * Coypright (c) 2013 Guntermann & Drunck GmbH
+ */
+
+#ifndef __TPM_API_H
+#define __TPM_API_H
+
+#include <tpm-common.h>
+#include <tpm-v1.h>
+#include <tpm-v2.h>
+
+/**
+ * Issue a TPM_Startup command.
+ *
+ * @param dev		TPM device
+ * @param mode		TPM startup mode
+ * @return return code of the operation
+ */
+u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode);
+
+/**
+ * Issue a TPM_SelfTestFull command.
+ *
+ * @param dev		TPM device
+ * @return return code of the operation
+ */
+u32 tpm_self_test_full(struct udevice *dev);
+
+/**
+ * Issue a TPM_ContinueSelfTest command.
+ *
+ * @param dev		TPM device
+ * @return return code of the operation
+ */
+u32 tpm_continue_self_test(struct udevice *dev);
+
+/**
+ * Issue a TPM_NV_DefineSpace command.  The implementation is limited
+ * to specify TPM_NV_ATTRIBUTES and size of the area.  The area index
+ * could be one of the special value listed in enum tpm_nv_index.
+ *
+ * @param dev		TPM device
+ * @param index		index of the area
+ * @param perm		TPM_NV_ATTRIBUTES of the area
+ * @param size		size of the area
+ * @return return code of the operation
+ */
+u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size);
+
+/**
+ * Issue a TPM_NV_ReadValue command.  This implementation is limited
+ * to read the area from offset 0.  The area index could be one of
+ * the special value listed in enum tpm_nv_index.
+ *
+ * @param dev		TPM device
+ * @param index		index of the area
+ * @param data		output buffer of the area contents
+ * @param count		size of output buffer
+ * @return return code of the operation
+ */
+u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count);
+
+/**
+ * Issue a TPM_NV_WriteValue command.  This implementation is limited
+ * to write the area from offset 0.  The area index could be one of
+ * the special value listed in enum tpm_nv_index.
+ *
+ * @param dev		TPM device
+ * @param index		index of the area
+ * @param data		input buffer to be wrote to the area
+ * @param length	length of data bytes of input buffer
+ * @return return code of the operation
+ */
+u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
+		       u32 length);
+
+/**
+ * Issue a TPM_Extend command.
+ *
+ * @param dev		TPM device
+ * @param index		index of the PCR
+ * @param in_digest	160-bit value representing the event to be
+ *			recorded
+ * @param out_digest	160-bit PCR value after execution of the
+ *			command
+ * @return return code of the operation
+ */
+u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest,
+		   void *out_digest);
+
+/**
+ * Issue a TPM_PCRRead command.
+ *
+ * @param dev		TPM device
+ * @param index		index of the PCR
+ * @param data		output buffer for contents of the named PCR
+ * @param count		size of output buffer
+ * @return return code of the operation
+ */
+u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count);
+
+/**
+ * Issue a TSC_PhysicalPresence command.  TPM physical presence flag
+ * is bit-wise OR'ed of flags listed in enum tpm_physical_presence.
+ *
+ * @param dev		TPM device
+ * @param presence	TPM physical presence flag
+ * @return return code of the operation
+ */
+u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence);
+
+/**
+ * Issue a TPM_ReadPubek command.
+ *
+ * @param dev		TPM device
+ * @param data		output buffer for the public endorsement key
+ * @param count		size of output buffer
+ * @return return code of the operation
+ */
+u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count);
+
+/**
+ * Issue a TPM_ForceClear command.
+ *
+ * @param dev		TPM device
+ * @return return code of the operation
+ */
+u32 tpm_force_clear(struct udevice *dev);
+
+/**
+ * Issue a TPM_PhysicalEnable command.
+ *
+ * @param dev		TPM device
+ * @return return code of the operation
+ */
+u32 tpm_physical_enable(struct udevice *dev);
+
+/**
+ * Issue a TPM_PhysicalDisable command.
+ *
+ * @param dev		TPM device
+ * @return return code of the operation
+ */
+u32 tpm_physical_disable(struct udevice *dev);
+
+/**
+ * Issue a TPM_PhysicalSetDeactivated command.
+ *
+ * @param dev		TPM device
+ * @param state		boolean state of the deactivated flag
+ * @return return code of the operation
+ */
+u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state);
+
+/**
+ * Issue a TPM_GetCapability command.  This implementation is limited
+ * to query sub_cap index that is 4-byte wide.
+ *
+ * @param dev		TPM device
+ * @param cap_area	partition of capabilities
+ * @param sub_cap	further definition of capability, which is
+ *			limited to be 4-byte wide
+ * @param cap		output buffer for capability information
+ * @param count		size of output buffer
+ * @return return code of the operation
+ */
+u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
+		       void *cap, size_t count);
+
+/**
+ * Issue a TPM_FlushSpecific command for a AUTH resource.
+ *
+ * @param dev		TPM device
+ * @param auth_handle	handle of the auth session
+ * @return return code of the operation
+ */
+u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle);
+
+/**
+ * Issue a TPM_OIAP command to setup an object independent authorization
+ * session.
+ * Information about the session is stored internally.
+ * If there was already an OIAP session active it is terminated and a new
+ * session is set up.
+ *
+ * @param dev		TPM device
+ * @param auth_handle	pointer to the (new) auth handle or NULL.
+ * @return return code of the operation
+ */
+u32 tpm_oiap(struct udevice *dev, u32 *auth_handle);
+
+/**
+ * Ends an active OIAP session.
+ *
+ * @param dev		TPM device
+ * @return return code of the operation
+ */
+u32 tpm_end_oiap(struct udevice *dev);
+
+/**
+ * Issue a TPM_LoadKey2 (Auth1) command using an OIAP session for authenticating
+ * the usage of the parent key.
+ *
+ * @param dev		TPM device
+ * @param parent_handle	handle of the parent key.
+ * @param key		pointer to the key structure (TPM_KEY or TPM_KEY12).
+ * @param key_length	size of the key structure
+ * @param parent_key_usage_auth	usage auth for the parent key
+ * @param key_handle	pointer to the key handle
+ * @return return code of the operation
+ */
+u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
+		       size_t key_length, const void *parent_key_usage_auth,
+		       u32 *key_handle);
+
+/**
+ * Issue a TPM_GetPubKey (Auth1) command using an OIAP session for
+ * authenticating the usage of the key.
+ *
+ * @param dev		TPM device
+ * @param key_handle	handle of the key
+ * @param usage_auth	usage auth for the key
+ * @param pubkey	pointer to the pub key buffer; may be NULL if the pubkey
+ *			should not be stored.
+ * @param pubkey_len	pointer to the pub key buffer len. On entry: the size of
+ *			the provided pubkey buffer. On successful exit: the size
+ *			of the stored TPM_PUBKEY structure (iff pubkey != NULL).
+ * @return return code of the operation
+ */
+u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
+			 const void *usage_auth, void *pubkey,
+			 size_t *pubkey_len);
+
+/**
+ * Get the TPM permissions
+ *
+ * @param dev		TPM device
+ * @param perm		Returns permissions value
+ * @return return code of the operation
+ */
+u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm);
+
+/**
+ * Flush a resource with a given handle and type from the TPM
+ *
+ * @param dev		TPM device
+ * @param key_handle           handle of the resource
+ * @param resource_type                type of the resource
+ * @return return code of the operation
+ */
+u32 tpm_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type);
+
+#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
+/**
+ * Search for a key by usage AuthData and the hash of the parent's pub key.
+ *
+ * @param dev		TPM device
+ * @param auth	        Usage auth of the key to search for
+ * @param pubkey_digest	SHA1 hash of the pub key structure of the key
+ * @param[out] handle	The handle of the key (Non-null iff found)
+ * @return 0 if key was found in TPM; != 0 if not.
+ */
+u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20],
+		      const u8 pubkey_digest[20], u32 *handle);
+#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
+
+/**
+ * Read random bytes from the TPM RNG. The implementation deals with the fact
+ * that the TPM may legally return fewer bytes than requested by retrying
+ * until @p count bytes have been received.
+ *
+ * @param dev		TPM device
+ * @param data		output buffer for the random bytes
+ * @param count		size of output buffer
+ * @return return code of the operation
+ */
+u32 tpm_get_random(struct udevice *dev, void *data, u32 count);
+
+/**
+ * tpm_finalise_physical_presence() - Finalise physical presence
+ *
+ * @param dev		TPM device
+ * @return return code of the operation (0 = success)
+ */
+u32 tpm_finalise_physical_presence(struct udevice *dev);
+
+/**
+ * tpm_nv_enable_locking() - lock the non-volatile space
+ *
+ * @param dev		TPM device
+ * @return return code of the operation (0 = success)
+ */
+u32 tpm_nv_enable_locking(struct udevice *dev);
+
+/**
+ * tpm_set_global_lock() - set the global lock
+ *
+ * @param dev		TPM device
+ * @return return code of the operation (0 = success)
+ */
+u32 tpm_set_global_lock(struct udevice *dev);
+
+/**
+ * tpm_write_lock() - lock the non-volatile space
+ *
+ * @param dev		TPM device
+ * @param index		Index of space to lock
+ * @return return code of the operation (0 = success)
+ */
+u32 tpm_write_lock(struct udevice *dev, u32 index);
+
+/**
+ * tpm_resume() - start up the TPM from resume (after suspend)
+ *
+ * @param dev		TPM device
+ * @return return code of the operation (0 = success)
+ */
+u32 tpm_resume(struct udevice *dev);
+
+#endif /* __TPM_API_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index 7288340..80ff244 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -642,7 +642,7 @@
 
 config BLOBLIST_TABLES
 	bool "Put tables in a bloblist"
-	depends on X86
+	depends on X86 && BLOBLIST
 	help
 	  Normally tables are placed at address 0xf0000 and can be up to 64KB
 	  long. With this option, tables are instead placed in the bloblist
diff --git a/lib/Makefile b/lib/Makefile
index edc1c3d..c42d4e1 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -53,6 +53,7 @@
 obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm-common.o
 ifeq ($(CONFIG_$(SPL_TPL_)TPM),y)
 obj-y += crc8.o
+obj-$(CONFIG_TPM) += tpm_api.o
 obj-$(CONFIG_TPM_V1) += tpm-v1.o
 obj-$(CONFIG_TPM_V2) += tpm-v2.o
 endif
diff --git a/lib/binman.c b/lib/binman.c
index 6040ec8..530df6a 100644
--- a/lib/binman.c
+++ b/lib/binman.c
@@ -128,8 +128,8 @@
 	if (!ofnode_valid(node))
 		return log_msg_ret("node", -ENOENT);
 	binman->image = node;
-	log_debug("binman: Selected image subnode '%s'\n",
-		  ofnode_get_name(binman->image));
+	log_info("binman: Selected image subnode '%s'\n",
+		 ofnode_get_name(binman->image));
 
 	return 0;
 }
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 634d3b1..e44f004 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -315,18 +315,13 @@
 
 config EFI_LOAD_FILE2_INITRD
 	bool "EFI_FILE_LOAD2_PROTOCOL for Linux initial ramdisk"
-	default n
+	default y
 	help
-	  Expose a EFI_FILE_LOAD2_PROTOCOL that the Linux UEFI stub can
-	  use to load the initial ramdisk. Once this is enabled using
-	  initrd=<ramdisk> will stop working.
-
-config EFI_INITRD_FILESPEC
-	string "initramfs path"
-	default "host 0:1 initrd"
-	depends on EFI_LOAD_FILE2_INITRD
-	help
-	  Full path of the initramfs file, e.g. mmc 0:2 initramfs.cpio.gz.
+	  Linux v5.7 and later can make use of this option. If the boot option
+	  selected by the UEFI boot manager specifies an existing file to be used
+	  as initial RAM disk, a Linux specific Load File2 protocol will be
+	  installed and Linux 5.7+ will ignore any initrd=<ramdisk> command line
+	  argument.
 
 config EFI_SECURE_BOOT
 	bool "Enable EFI secure boot support"
@@ -347,4 +342,11 @@
 	  it is signed with a trusted key. To do that, you need to install,
 	  at least, PK, KEK and db.
 
+config EFI_ESRT
+	bool "Enable the UEFI ESRT generation"
+	depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT
+	default y
+	help
+	  Enabling this option creates the ESRT UEFI system table.
+
 endif
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 10b42e8..8bd343e 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -23,6 +23,7 @@
 obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o
 obj-$(CONFIG_CMD_BOOTEFI_BOOTMGR) += efi_bootmgr.o
 obj-y += efi_boottime.o
+obj-y += efi_helper.o
 obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o
 obj-$(CONFIG_EFI_CAPSULE_FIRMWARE) += efi_firmware.o
 obj-y += efi_console.o
@@ -52,6 +53,7 @@
 obj-$(CONFIG_EFI_VARIABLES_PRESEED) += efi_var_seed.o
 endif
 obj-y += efi_watchdog.o
+obj-$(CONFIG_EFI_ESRT) += efi_esrt.o
 obj-$(CONFIG_LCD) += efi_gop.o
 obj-$(CONFIG_DM_VIDEO) += efi_gop.o
 obj-$(CONFIG_PARTITIONS) += efi_disk.o
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index 25f5ceb..46c8011 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -118,11 +118,13 @@
 		ret = efi_set_variable_int(L"BootCurrent",
 					   &efi_global_variable_guid,
 					   attributes, sizeof(n), &n, false);
-		if (ret != EFI_SUCCESS) {
-			if (EFI_CALL(efi_unload_image(*handle))
-			    != EFI_SUCCESS)
-				log_err("Unloading image failed\n");
-			goto error;
+		if (ret != EFI_SUCCESS)
+			goto unload;
+		/* try to register load file2 for initrd's */
+		if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD)) {
+			ret = efi_initrd_register();
+			if (ret != EFI_SUCCESS)
+				goto unload;
 		}
 
 		log_info("Booting: %ls\n", lo.label);
@@ -147,6 +149,13 @@
 	free(load_option);
 
 	return ret;
+
+unload:
+	if (EFI_CALL(efi_unload_image(*handle)) != EFI_SUCCESS)
+		log_err("Unloading image failed\n");
+	free(load_option);
+
+	return ret;
 }
 
 /**
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 41b8949..4777b35 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -1406,10 +1406,9 @@
  *
  * Return: status code
  */
-static efi_status_t EFIAPI efi_register_protocol_notify(
-						const efi_guid_t *protocol,
-						struct efi_event *event,
-						void **registration)
+efi_status_t EFIAPI efi_register_protocol_notify(const efi_guid_t *protocol,
+						 struct efi_event *event,
+						 void **registration)
 {
 	struct efi_register_notify_event *item;
 	efi_status_t ret = EFI_SUCCESS;
@@ -1877,7 +1876,6 @@
 efi_status_t efi_load_image_from_file(struct efi_device_path *file_path,
 				      void **buffer, efi_uintn_t *size)
 {
-	struct efi_file_info *info = NULL;
 	struct efi_file_handle *f;
 	efi_status_t ret;
 	u64 addr;
@@ -1888,18 +1886,7 @@
 	if (!f)
 		return EFI_NOT_FOUND;
 
-	/* Get file size */
-	bs = 0;
-	EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid,
-				  &bs, info));
-	if (ret != EFI_BUFFER_TOO_SMALL) {
-		ret =  EFI_DEVICE_ERROR;
-		goto error;
-	}
-
-	info = malloc(bs);
-	EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid, &bs,
-				  info));
+	ret = efi_file_size(f, &bs);
 	if (ret != EFI_SUCCESS)
 		goto error;
 
@@ -1909,7 +1896,6 @@
 	 * allocate a buffer as EFI_BOOT_SERVICES_DATA. The caller has to
 	 * update the reservation according to the image type.
 	 */
-	bs = info->file_size;
 	ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
 				 EFI_BOOT_SERVICES_DATA,
 				 efi_size_in_pages(bs), &addr);
@@ -1926,7 +1912,6 @@
 	*size = bs;
 error:
 	EFI_CALL(f->close(f));
-	free(info);
 	return ret;
 }
 
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 7ba1ced..9df9c35 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -482,6 +482,14 @@
 			goto out;
 	}
 out:
+
+	if (IS_ENABLED(CONFIG_EFI_ESRT)) {
+		/* Rebuild the ESRT to reflect any updated FW images. */
+		ret = efi_esrt_populate();
+		if (ret != EFI_SUCCESS)
+			log_warning("EFI Capsule: failed to update ESRT\n");
+	}
+
 	return EFI_EXIT(ret);
 }
 
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index 398dbc6..4b20859 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -282,11 +282,31 @@
 	return ndp;
 }
 
-struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
-				      const struct efi_device_path *dp2)
+/**
+ * efi_dp_append_or_concatenate() - Append or concatenate two device paths.
+ *				    Concatenated device path will be separated
+ *				    by a sub-type 0xff end node
+ *
+ * @dp1:	First device path
+ * @dp2:	Second device path
+ * @concat:	If true the two device paths will be concatenated and separated
+ *		by an end of entrire device path sub-type 0xff end node.
+ *		If true the second device path will be appended to the first and
+ *		terminated by an end node
+ *
+ * Return:
+ * concatenated device path or NULL. Caller must free the returned value
+ */
+static struct
+efi_device_path *efi_dp_append_or_concatenate(const struct efi_device_path *dp1,
+					      const struct efi_device_path *dp2,
+					      bool concat)
 {
 	struct efi_device_path *ret;
+	size_t end_size = sizeof(END);
 
+	if (concat)
+		end_size = 2 * sizeof(END);
 	if (!dp1 && !dp2) {
 		/* return an end node */
 		ret = efi_dp_dup(&END);
@@ -298,18 +318,58 @@
 		/* both dp1 and dp2 are non-null */
 		unsigned sz1 = efi_dp_size(dp1);
 		unsigned sz2 = efi_dp_size(dp2);
-		void *p = dp_alloc(sz1 + sz2 + sizeof(END));
+		void *p = dp_alloc(sz1 + sz2 + end_size);
 		if (!p)
 			return NULL;
-		memcpy(p, dp1, sz1);
-		/* the end node of the second device path has to be retained */
-		memcpy(p + sz1, dp2, sz2 + sizeof(END));
 		ret = p;
+		memcpy(p, dp1, sz1);
+		p += sz1;
+
+		if (concat) {
+			memcpy(p, &END, sizeof(END));
+			p += sizeof(END);
+		}
+
+		/* the end node of the second device path has to be retained */
+		memcpy(p, dp2, sz2);
+		p += sz2;
+		memcpy(p, &END, sizeof(END));
 	}
 
 	return ret;
 }
 
+/**
+ * efi_dp_append() - Append a device to an existing device path.
+ *
+ * @dp1:	First device path
+ * @dp2:	Second device path
+ *
+ * Return:
+ * concatenated device path or NULL. Caller must free the returned value
+ */
+struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
+				      const struct efi_device_path *dp2)
+{
+	return efi_dp_append_or_concatenate(dp1, dp2, false);
+}
+
+/**
+ * efi_dp_concat() - Concatenate 2 device paths. The final device path will
+ *                   contain two device paths separated by and end node (0xff).
+ *
+ * @dp1:	First device path
+ * @dp2:	Second device path
+ *
+ * Return:
+ * concatenated device path or NULL. Caller must free the returned value
+ */
+struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1,
+				      const struct efi_device_path *dp2)
+{
+	return efi_dp_append_or_concatenate(dp1, dp2, true);
+}
+
 struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
 					   const struct efi_device_path *node)
 {
@@ -1183,3 +1243,43 @@
 		dp = (const struct efi_device_path *)((const u8 *)dp + len);
 	}
 }
+
+/**
+ * efi_dp_from_lo() - Get the instance of a VenMedia node in a
+ *                    multi-instance device path that matches
+ *                    a specific GUID. This kind of device paths
+ *                    is found in Boot#### options describing an
+ *                    initrd location
+ *
+ * @lo:		EFI_LOAD_OPTION containing a valid device path
+ * @size:	size of the discovered device path
+ * @guid:	guid to search for
+ *
+ * Return:
+ * device path including the VenMedia node or NULL.
+ * Caller must free the returned value.
+ */
+struct
+efi_device_path *efi_dp_from_lo(struct efi_load_option *lo,
+				efi_uintn_t *size, efi_guid_t guid)
+{
+	struct efi_device_path *fp = lo->file_path;
+	struct efi_device_path_vendor *vendor;
+	int lo_len = lo->file_path_length;
+
+	for (; lo_len >=  sizeof(struct efi_device_path);
+	     lo_len -= fp->length, fp = (void *)fp + fp->length) {
+		if (lo_len < 0 || efi_dp_check_length(fp, lo_len) < 0)
+			break;
+		if (fp->type != DEVICE_PATH_TYPE_MEDIA_DEVICE ||
+		    fp->sub_type != DEVICE_PATH_SUB_TYPE_VENDOR_PATH)
+			continue;
+
+		vendor = (struct efi_device_path_vendor *)fp;
+		if (!guidcmp(&vendor->guid, &guid))
+			return efi_dp_dup(fp);
+	}
+	log_debug("VenMedia(%pUl) not found in %ls\n", &guid, lo->label);
+
+	return NULL;
+}
diff --git a/lib/efi_loader/efi_esrt.c b/lib/efi_loader/efi_esrt.c
new file mode 100644
index 0000000..947bdb5
--- /dev/null
+++ b/lib/efi_loader/efi_esrt.c
@@ -0,0 +1,510 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *  EFI application ESRT tables support
+ *
+ *  Copyright (C) 2021 Arm Ltd.
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <log.h>
+#include <efi_api.h>
+#include <malloc.h>
+
+const efi_guid_t efi_esrt_guid = EFI_SYSTEM_RESOURCE_TABLE_GUID;
+
+static struct efi_system_resource_table *esrt;
+
+#define EFI_ESRT_VERSION 1
+
+/**
+ * efi_esrt_image_info_to_entry() - copy the information present in a fw image
+ * descriptor to a ESRT entry.
+ * The function ensures the ESRT entry matches the image_type_id in @img_info.
+ * In case of a mismatch we leave the entry unchanged.
+ *
+ * @img_info:     the source image info descriptor
+ * @entry:        pointer to the ESRT entry to be filled
+ * @desc_version: the version of the elements in img_info
+ * @image_type:   the image type value to be set in the ESRT entry
+ * @flags:        the capsule flags value to be set in the ESRT entry
+ *
+ * Return:
+ * - EFI_SUCCESS if the entry is correctly updated
+ * - EFI_INVALID_PARAMETER if entry does not match image_type_id in @img_info.
+ */
+static efi_status_t
+efi_esrt_image_info_to_entry(struct efi_firmware_image_descriptor *img_info,
+			     struct efi_system_resource_entry *entry,
+			     u32 desc_version, u32 image_type, u32 flags)
+{
+	if (guidcmp(&entry->fw_class, &img_info->image_type_id)) {
+		EFI_PRINT("ESRT entry %pUL mismatches img_type_id %pUL\n",
+			  &entry->fw_class, &img_info->image_type_id);
+		return EFI_INVALID_PARAMETER;
+	}
+
+	entry->fw_version = img_info->version;
+
+	entry->fw_type = image_type;
+	entry->capsule_flags = flags;
+
+	/*
+	 * The field lowest_supported_image_version is only present
+	 * on image info structure of version 2 or greater.
+	 * See the EFI_FIRMWARE_IMAGE_DESCRIPTOR definition in UEFI.
+	 */
+	if (desc_version >= 2)
+		entry->lowest_supported_fw_version =
+			img_info->lowest_supported_image_version;
+	else
+		entry->lowest_supported_fw_version = 0;
+
+	/*
+	 * The fields last_attempt_version and last_attempt_status
+	 * are only present on image info structure of version 3 or
+	 * greater.
+	 * See the EFI_FIRMWARE_IMAGE_DESCRIPTOR definition in UEFI.
+	 */
+	if (desc_version >= 3) {
+		entry->last_attempt_version =
+			img_info->last_attempt_version;
+
+		entry->last_attempt_status =
+			img_info->last_attempt_status;
+	} else {
+		entry->last_attempt_version = 0;
+		entry->last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS;
+	}
+
+	return EFI_SUCCESS;
+}
+
+/**
+ * efi_esrt_entries_to_size() - Obtain the bytes used by an ESRT
+ * datastructure with @num_entries.
+ *
+ * @num_entries: the number of entries in the ESRT.
+ *
+ * Return: the number of bytes an ESRT with @num_entries occupies in memory.
+ */
+static
+inline u32 efi_esrt_entries_to_size(u32 num_entries)
+{
+	u32 esrt_size = sizeof(struct efi_system_resource_table) +
+		num_entries * sizeof(struct efi_system_resource_entry);
+
+	return esrt_size;
+}
+
+/**
+ * efi_esrt_allocate_install() - Allocates @num_entries for the ESRT and
+ * performs basic ESRT initialization.
+ *
+ * @num_entries: the number of entries that the ESRT will hold.
+ *
+ * Return:
+ * - pointer to the ESRT if successful.
+ * - NULL otherwise.
+ */
+static
+efi_status_t efi_esrt_allocate_install(u32 num_entries)
+{
+	efi_status_t ret;
+	struct efi_system_resource_table *new_esrt;
+	u32 size = efi_esrt_entries_to_size(num_entries);
+	efi_guid_t esrt_guid = efi_esrt_guid;
+
+	/* Reserve num_pages for ESRT */
+	ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, size,
+				(void **)&new_esrt);
+
+	if (ret != EFI_SUCCESS) {
+		EFI_PRINT("ESRT cannot allocate memory for %d entries (%d bytes)\n",
+			  num_entries, efi_esrt_entries_to_size(num_entries));
+
+		return ret;
+	}
+
+	new_esrt->fw_resource_count_max = num_entries;
+	new_esrt->fw_resource_count = 0;
+	new_esrt->fw_resource_version = EFI_ESRT_VERSION;
+
+	/* Install the ESRT in the system configuration table. */
+	ret = efi_install_configuration_table(&esrt_guid, (void *)new_esrt);
+	if (ret != EFI_SUCCESS) {
+		EFI_PRINT("ESRT failed to install the ESRT in the system table\n");
+		return ret;
+	}
+
+	/* If there was a previous ESRT, deallocate its memory now. */
+	if (esrt)
+		ret = EFI_CALL(efi_free_pool(esrt));
+
+	esrt = new_esrt;
+
+	return EFI_SUCCESS;
+}
+
+/**
+ * esrt_find_entry() - Obtain the ESRT entry for the image with GUID
+ * @img_fw_class.
+ *
+ * If the img_fw_class is not yet present in the ESRT, this function
+ * reserves the tail element of the current ESRT as the entry for that fw_class.
+ * The number of elements in the ESRT is updated in that case.
+ *
+ * @img_fw_class: the GUID of the FW image which ESRT entry we want to obtain.
+ *
+ * Return:
+ *  - A pointer to the ESRT entry for the image with GUID img_fw_class,
+ *  - NULL if:
+ *   - there is no more space in the ESRT,
+ *   - ESRT is not initialized,
+ */
+static
+struct efi_system_resource_entry *esrt_find_entry(efi_guid_t *img_fw_class)
+{
+	u32 filled_entries;
+	u32 max_entries;
+	struct efi_system_resource_entry *entry;
+
+	if (!esrt) {
+		EFI_PRINT("ESRT access before initialized\n");
+		return NULL;
+	}
+
+	filled_entries = esrt->fw_resource_count;
+	entry = esrt->entries;
+
+	/* Check if the image with img_fw_class is already in the ESRT. */
+	for (u32 idx = 0; idx < filled_entries; idx++) {
+		if (!guidcmp(&entry[idx].fw_class, img_fw_class)) {
+			EFI_PRINT("ESRT found entry for image %pUl at index %d\n",
+				  img_fw_class, idx);
+			return &entry[idx];
+		}
+	}
+
+	max_entries = esrt->fw_resource_count_max;
+	/*
+	 * Since the image with img_fw_class is not present in the ESRT, check
+	 * if ESRT is full before appending the new entry to it.
+	 */
+	if (filled_entries == max_entries) {
+		EFI_PRINT("ESRT full, this should not happen\n");
+		return NULL;
+	}
+
+	/*
+	 * This is a new entry for a fw image, increment the element
+	 * number in the table and set the fw_class field.
+	 */
+	esrt->fw_resource_count++;
+	entry[filled_entries].fw_class = *img_fw_class;
+	EFI_PRINT("ESRT allocated new entry for image %pUl at index %d\n",
+		  img_fw_class, filled_entries);
+
+	return &entry[filled_entries];
+}
+
+/**
+ * efi_esrt_add_from_fmp() - Populates a sequence of ESRT entries from the FW
+ * images in the FMP.
+ *
+ * @fmp: the FMP instance from which FW images are added to the ESRT
+ *
+ * Return:
+ * - EFI_SUCCESS if all the FW images in the FMP are added to the ESRT
+ * - Error status otherwise
+ */
+static
+efi_status_t efi_esrt_add_from_fmp(struct efi_firmware_management_protocol *fmp)
+{
+	struct efi_system_resource_entry *entry = NULL;
+	size_t info_size = 0;
+	struct efi_firmware_image_descriptor *img_info = NULL;
+	u32 desc_version;
+	u8 desc_count;
+	size_t desc_size;
+	u32 package_version;
+	u16 *package_version_name;
+	efi_status_t ret = EFI_SUCCESS;
+
+	/*
+	 * TODO: set the field image_type depending on the FW image type
+	 * defined in a platform basis.
+	 */
+	u32 image_type = ESRT_FW_TYPE_UNKNOWN;
+
+	/* TODO: set the capsule flags as a function of the FW image type. */
+	u32 flags = 0;
+
+	ret = EFI_CALL(fmp->get_image_info(fmp, &info_size, img_info,
+					   &desc_version, &desc_count,
+					   &desc_size, NULL, NULL));
+
+	if (ret != EFI_BUFFER_TOO_SMALL) {
+		/*
+		 * An input of info_size=0 should always lead
+		 * fmp->get_image_info to return BUFFER_TO_SMALL.
+		 */
+		EFI_PRINT("Erroneous FMP implementation\n");
+		return EFI_INVALID_PARAMETER;
+	}
+
+	ret = EFI_CALL(efi_allocate_pool(EFI_BOOT_SERVICES_DATA, info_size,
+					 (void **)&img_info));
+	if (ret != EFI_SUCCESS) {
+		EFI_PRINT("ESRT failed to allocate memory for image info.\n");
+		return ret;
+	}
+
+	ret = EFI_CALL(fmp->get_image_info(fmp, &info_size, img_info,
+					   &desc_version, &desc_count,
+					   &desc_size, &package_version,
+					   &package_version_name));
+	if (ret != EFI_SUCCESS) {
+		EFI_PRINT("ESRT failed to obtain the FMP image info\n");
+		goto out;
+	}
+
+	/*
+	 * Iterate over all the FW images in the FMP.
+	 */
+	for (u32 desc_idx = 0; desc_idx < desc_count; desc_idx++) {
+		struct efi_firmware_image_descriptor *cur_img_info =
+			(struct efi_firmware_image_descriptor *)
+			((uintptr_t)img_info + desc_idx * desc_size);
+
+		/*
+		 * Obtain the ESRT entry for the FW image with fw_class
+		 * equal to cur_img_info->image_type_id.
+		 */
+		entry = esrt_find_entry(&cur_img_info->image_type_id);
+
+		if (entry) {
+			ret = efi_esrt_image_info_to_entry(cur_img_info, entry,
+							   desc_version,
+							   image_type, flags);
+			if (ret != EFI_SUCCESS)
+				EFI_PRINT("ESRT entry mismatches image_type\n");
+
+		} else {
+			EFI_PRINT("ESRT failed to add entry for %pUl\n",
+				  &cur_img_info->image_type_id);
+			continue;
+		}
+	}
+
+out:
+	EFI_CALL(efi_free_pool(img_info));
+	return EFI_SUCCESS;
+}
+
+/**
+ * efi_esrt_populate() - Populates the ESRT entries from the FMP instances
+ * present in the system.
+ * If an ESRT already exists, the old ESRT is replaced in the system table.
+ * The memory of the old ESRT is deallocated.
+ *
+ * Return:
+ * - EFI_SUCCESS if the ESRT is correctly created
+ * - error code otherwise.
+ */
+efi_status_t efi_esrt_populate(void)
+{
+	efi_handle_t *base_handle = NULL;
+	efi_handle_t *it_handle;
+	size_t no_handles = 0;
+	struct efi_firmware_management_protocol *fmp;
+	efi_status_t ret;
+	u32 num_entries = 0;
+	struct efi_handler *handler;
+
+	/*
+	 * Obtain the number of registered FMP handles.
+	 */
+	ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL,
+						&efi_guid_firmware_management_protocol,
+						NULL, &no_handles,
+						(efi_handle_t **)&base_handle));
+
+	if (ret != EFI_SUCCESS) {
+		EFI_PRINT("ESRT There are no FMP instances\n");
+
+		ret = efi_esrt_allocate_install(0);
+		if (ret != EFI_SUCCESS) {
+			EFI_PRINT("ESRT failed to create table with 0 entries\n");
+			return ret;
+		}
+		return EFI_SUCCESS;
+	}
+
+	EFI_PRINT("ESRT populate esrt from (%ld) available FMP handles\n",
+		  no_handles);
+
+	/*
+	 * Iterate over all FMPs to determine an upper bound on the number of
+	 * ESRT entries.
+	 */
+	it_handle = base_handle;
+	for (u32 idx = 0; idx < no_handles; idx++, it_handle++) {
+		struct efi_firmware_image_descriptor *img_info = NULL;
+		size_t info_size = 0;
+		u32 desc_version = 0;
+		u8 desc_count = 0;
+		size_t desc_size = 0;
+		u32 package_version;
+		u16 *package_version_name;
+
+		ret = efi_search_protocol(*it_handle,
+					  &efi_guid_firmware_management_protocol,
+					  &handler);
+
+		if (ret != EFI_SUCCESS) {
+			EFI_PRINT("ESRT Unable to find FMP handle (%d)\n",
+				  idx);
+			goto out;
+		}
+		fmp = handler->protocol_interface;
+
+		ret = EFI_CALL(fmp->get_image_info(fmp, &info_size, NULL,
+						   &desc_version, &desc_count,
+						   &desc_size, &package_version,
+						   &package_version_name));
+
+		if (ret != EFI_BUFFER_TOO_SMALL) {
+			/*
+			 * An input of info_size=0 should always lead
+			 * fmp->get_image_info to return BUFFER_TO_SMALL.
+			 */
+			EFI_PRINT("ESRT erroneous FMP implementation\n");
+			ret = EFI_INVALID_PARAMETER;
+			goto out;
+		}
+
+		ret = EFI_CALL(efi_allocate_pool(EFI_BOOT_SERVICES_DATA, info_size,
+						 (void **)&img_info));
+		if (ret != EFI_SUCCESS) {
+			EFI_PRINT("ESRT failed to allocate memory for image info\n");
+			goto out;
+		}
+
+		/*
+		 * Calls to a FMP get_image_info method do not return the
+		 * desc_count value if the return status differs from EFI_SUCCESS.
+		 * We need to repeat the call to get_image_info with a properly
+		 * sized buffer in order to obtain the real number of images
+		 * handled by the FMP.
+		 */
+		ret = EFI_CALL(fmp->get_image_info(fmp, &info_size, img_info,
+						   &desc_version, &desc_count,
+						   &desc_size, &package_version,
+						   &package_version_name));
+
+		if (ret != EFI_SUCCESS) {
+			EFI_PRINT("ESRT failed to obtain image info from FMP\n");
+			EFI_CALL(efi_free_pool(img_info));
+			goto out;
+		}
+
+		num_entries += desc_count;
+
+		EFI_CALL(efi_free_pool(img_info));
+	}
+
+	EFI_PRINT("ESRT create table with %d entries\n", num_entries);
+	/*
+	 * Allocate an ESRT with the sufficient number of entries to accommodate
+	 * all the FMPs in the system.
+	 */
+	ret = efi_esrt_allocate_install(num_entries);
+	if (ret != EFI_SUCCESS) {
+		EFI_PRINT("ESRT failed to initialize table\n");
+		goto out;
+	}
+
+	/*
+	 * Populate the ESRT entries with all existing FMP.
+	 */
+	it_handle = base_handle;
+	for (u32 idx = 0; idx < no_handles; idx++, it_handle++) {
+		ret = EFI_CALL(efi_search_protocol(*it_handle,
+						   &efi_guid_firmware_management_protocol,
+						   &handler));
+
+		if (ret != EFI_SUCCESS) {
+			EFI_PRINT("ESRT unable to find FMP handle (%d)\n",
+				  idx);
+			break;
+		}
+		fmp = handler->protocol_interface;
+
+		ret = efi_esrt_add_from_fmp(fmp);
+		if (ret != EFI_SUCCESS)
+			EFI_PRINT("ESRT failed to add FMP to the table\n");
+	}
+
+out:
+
+	EFI_CALL(efi_free_pool(base_handle));
+
+	return ret;
+}
+
+/**
+ * efi_esrt_new_fmp_notify() - Callback for the EVT_NOTIFY_SIGNAL event raised
+ * when a new FMP protocol instance is registered in the system.
+ */
+static void EFIAPI efi_esrt_new_fmp_notify(struct efi_event *event,
+					   void *context)
+{
+	efi_status_t ret;
+
+	EFI_ENTRY();
+
+	ret = efi_esrt_populate();
+	if (ret != EFI_SUCCESS)
+		EFI_PRINT("ESRT failed to populate ESRT entry\n");
+
+	EFI_EXIT(ret);
+}
+
+/**
+ * efi_esrt_register() - Install the ESRT system table.
+ *
+ * Return: status code
+ */
+efi_status_t efi_esrt_register(void)
+{
+	struct efi_event *ev = NULL;
+	void *registration;
+	efi_status_t ret;
+
+	EFI_PRINT("ESRT creation start\n");
+
+	ret = efi_esrt_populate();
+	if (ret != EFI_SUCCESS) {
+		EFI_PRINT("ESRT failed to initiate the table\n");
+		return ret;
+	}
+
+	ret = EFI_CALL(efi_create_event(EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
+					efi_esrt_new_fmp_notify, NULL, NULL, &ev));
+	if (ret != EFI_SUCCESS) {
+		EFI_PRINT("ESRT failed to create event\n");
+		return ret;
+	}
+
+	ret = EFI_CALL(efi_register_protocol_notify(&efi_guid_firmware_management_protocol,
+						    ev, &registration));
+	if (ret != EFI_SUCCESS) {
+		EFI_PRINT("ESRT failed to register FMP callback\n");
+		return ret;
+	}
+
+	EFI_PRINT("ESRT table created\n");
+
+	return ret;
+}
diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
index 8ece8e7..204105e 100644
--- a/lib/efi_loader/efi_file.c
+++ b/lib/efi_loader/efi_file.c
@@ -409,6 +409,45 @@
 	return EFI_SUCCESS;
 }
 
+/**
+ * efi_file_size() - Get the size of a file using an EFI file handle
+ *
+ * @fh:		EFI file handle
+ * @size:	buffer to fill in the discovered size
+ *
+ * Return:	size of the file
+ */
+efi_status_t efi_file_size(struct efi_file_handle *fh, efi_uintn_t *size)
+{
+	struct efi_file_info *info = NULL;
+	efi_uintn_t bs = 0;
+	efi_status_t ret;
+
+	*size = 0;
+	ret = EFI_CALL(fh->getinfo(fh, (efi_guid_t *)&efi_file_info_guid, &bs,
+				   info));
+	if (ret != EFI_BUFFER_TOO_SMALL) {
+		ret = EFI_DEVICE_ERROR;
+		goto out;
+	}
+
+	info = malloc(bs);
+	if (!info) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+	ret = EFI_CALL(fh->getinfo(fh, (efi_guid_t *)&efi_file_info_guid, &bs,
+				   info));
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	*size = info->file_size;
+
+out:
+	free(info);
+	return ret;
+}
+
 static efi_status_t file_read(struct file_handle *fh, u64 *buffer_size,
 		void *buffer)
 {
diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c
new file mode 100644
index 0000000..d03a736
--- /dev/null
+++ b/lib/efi_loader/efi_helper.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020, Linaro Limited
+ */
+
+#define LOG_CATEGORY LOGC_EFI
+#include <common.h>
+#include <env.h>
+#include <malloc.h>
+#include <dm.h>
+#include <fs.h>
+#include <efi_load_initrd.h>
+#include <efi_loader.h>
+#include <efi_variable.h>
+
+/**
+ * efi_create_current_boot_var() - Return Boot#### name were #### is replaced by
+ *			           the value of BootCurrent
+ *
+ * @var_name:		variable name
+ * @var_name_size:	size of var_name
+ *
+ * Return:	Status code
+ */
+static efi_status_t efi_create_current_boot_var(u16 var_name[],
+						size_t var_name_size)
+{
+	efi_uintn_t boot_current_size;
+	efi_status_t ret;
+	u16 boot_current;
+	u16 *pos;
+
+	boot_current_size = sizeof(boot_current);
+	ret = efi_get_variable_int(L"BootCurrent",
+				   &efi_global_variable_guid, NULL,
+				   &boot_current_size, &boot_current, NULL);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	pos = efi_create_indexed_name(var_name, var_name_size, "Boot",
+				      boot_current);
+	if (!pos) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+
+out:
+	return ret;
+}
+
+/**
+ * efi_get_dp_from_boot() - Retrieve and return a device path from an EFI
+ *			    Boot### variable.
+ *			    A boot option may contain an array of device paths.
+ *			    We use a VenMedia() with a specific GUID to identify
+ *			    the usage of the array members. This function is
+ *			    used to extract a specific device path
+ *
+ * @guid:	vendor GUID of the VenMedia() device path node identifying the
+ *		device path
+ *
+ * Return:	device path or NULL. Caller must free the returned value
+ */
+struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid)
+{
+	struct efi_device_path *file_path = NULL;
+	struct efi_device_path *tmp = NULL;
+	struct efi_load_option lo;
+	void *var_value = NULL;
+	efi_uintn_t size;
+	efi_status_t ret;
+	u16 var_name[16];
+
+	ret = efi_create_current_boot_var(var_name, sizeof(var_name));
+	if (ret != EFI_SUCCESS)
+		return NULL;
+
+	var_value = efi_get_var(var_name, &efi_global_variable_guid, &size);
+	if (!var_value)
+		return NULL;
+
+	ret = efi_deserialize_load_option(&lo, var_value, &size);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	tmp = efi_dp_from_lo(&lo, &size, guid);
+	if (!tmp)
+		goto out;
+
+	/* efi_dp_dup will just return NULL if efi_dp_next is NULL */
+	file_path = efi_dp_dup(efi_dp_next(tmp));
+
+out:
+	efi_free_pool(tmp);
+	free(var_value);
+
+	return file_path;
+}
diff --git a/lib/efi_loader/efi_load_initrd.c b/lib/efi_loader/efi_load_initrd.c
index b9ee883..e2a8063 100644
--- a/lib/efi_loader/efi_load_initrd.c
+++ b/lib/efi_loader/efi_load_initrd.c
@@ -3,9 +3,11 @@
  * Copyright (c) 2020, Linaro Limited
  */
 
+#define LOG_CATEGORY LOGC_EFI
 #include <common.h>
 #include <efi_loader.h>
 #include <efi_load_initrd.h>
+#include <efi_variable.h>
 #include <fs.h>
 #include <malloc.h>
 #include <mapmem.h>
@@ -23,57 +25,56 @@
  * Device path defined by Linux to identify the handle providing the
  * EFI_LOAD_FILE2_PROTOCOL used for loading the initial ramdisk.
  */
-static const struct efi_initrd_dp dp = {
+static const struct efi_initrd_dp dp_lf2_handle = {
 	.vendor = {
 		{
 		   DEVICE_PATH_TYPE_MEDIA_DEVICE,
 		   DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
-		   sizeof(dp.vendor),
+		   sizeof(dp_lf2_handle.vendor),
 		},
 		EFI_INITRD_MEDIA_GUID,
 	},
 	.end = {
 		DEVICE_PATH_TYPE_END,
 		DEVICE_PATH_SUB_TYPE_END,
-		sizeof(dp.end),
+		sizeof(dp_lf2_handle.end),
 	}
 };
 
+static efi_handle_t efi_initrd_handle;
+
 /**
- * get_file_size() - retrieve the size of initramfs, set efi status on error
+ * get_initrd_fp() - Get initrd device path from a FilePathList device path
  *
- * @dev:			device to read from, e.g. "mmc"
- * @part:			device partition, e.g. "0:1"
- * @file:			name of file
- * @status:			EFI exit code in case of failure
+ * @initrd_fp:	the final initrd filepath
  *
- * Return:			size of file
+ * Return:	status code. Caller must free initrd_fp
  */
-static loff_t get_file_size(const char *dev, const char *part, const char *file,
-			    efi_status_t *status)
+static efi_status_t get_initrd_fp(struct efi_device_path **initrd_fp)
 {
-	loff_t sz = 0;
-	int ret;
+	const efi_guid_t lf2_initrd_guid = EFI_INITRD_MEDIA_GUID;
+	struct efi_device_path *dp = NULL;
 
-	ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY);
-	if (ret) {
-		*status = EFI_NO_MEDIA;
-		goto out;
-	}
+	/*
+	 * if bootmgr is setup with and initrd, the device path will be
+	 * in the FilePathList[] of our load options in Boot####.
+	 * The first device path of the multi instance device path will
+	 * start with a VenMedia and the initrds will follow.
+	 *
+	 * If the device path is not found return EFI_INVALID_PARAMETER.
+	 * We can then use this specific return value and not install the
+	 * protocol, while allowing the boot to continue
+	 */
+	dp = efi_get_dp_from_boot(lf2_initrd_guid);
+	if (!dp)
+		return EFI_INVALID_PARAMETER;
 
-	ret = fs_size(file, &sz);
-	if (ret) {
-		sz = 0;
-		*status = EFI_NOT_FOUND;
-		goto out;
-	}
-
-out:
-	return sz;
+	*initrd_fp = dp;
+	return EFI_SUCCESS;
 }
 
 /**
- * efi_load_file2initrd() - load initial RAM disk
+ * efi_load_file2_initrd() - load initial RAM disk
  *
  * This function implements the LoadFile service of the EFI_LOAD_FILE2_PROTOCOL
  * in order to load an initial RAM disk requested by the Linux kernel stub.
@@ -93,102 +94,125 @@
 		      struct efi_device_path *file_path, bool boot_policy,
 		      efi_uintn_t *buffer_size, void *buffer)
 {
-	char *filespec;
-	efi_status_t status = EFI_NOT_FOUND;
-	loff_t file_sz = 0, read_sz = 0;
-	char *dev, *part, *file;
-	char *pos;
-	int ret;
+	struct efi_device_path *initrd_fp = NULL;
+	efi_status_t ret = EFI_NOT_FOUND;
+	struct efi_file_handle *f = NULL;
+	efi_uintn_t bs;
 
 	EFI_ENTRY("%p, %p, %d, %p, %p", this, file_path, boot_policy,
 		  buffer_size, buffer);
 
-	filespec = strdup(CONFIG_EFI_INITRD_FILESPEC);
-	if (!filespec)
-		goto out;
-	pos = filespec;
-
 	if (!this || this != &efi_lf2_protocol ||
 	    !buffer_size) {
-		status = EFI_INVALID_PARAMETER;
+		ret = EFI_INVALID_PARAMETER;
 		goto out;
 	}
 
-	if (file_path->type != dp.end.type ||
-	    file_path->sub_type != dp.end.sub_type) {
-		status = EFI_INVALID_PARAMETER;
+	if (file_path->type != dp_lf2_handle.end.type ||
+	    file_path->sub_type != dp_lf2_handle.end.sub_type) {
+		ret = EFI_INVALID_PARAMETER;
 		goto out;
 	}
 
 	if (boot_policy) {
-		status = EFI_UNSUPPORTED;
+		ret = EFI_UNSUPPORTED;
 		goto out;
 	}
 
-	/*
-	 * expect a string with three space separated parts:
-	 *
-	 * * a block device type, e.g. "mmc"
-	 * * a device and partition identifier, e.g. "0:1"
-	 * * a file path on the block device, e.g. "/boot/initrd.cpio.gz"
-	 */
-	dev = strsep(&pos, " ");
-	if (!dev)
-		goto out;
-	part = strsep(&pos, " ");
-	if (!part)
-		goto out;
-	file = strsep(&pos, " ");
-	if (!file)
+	ret = get_initrd_fp(&initrd_fp);
+	if (ret != EFI_SUCCESS)
 		goto out;
 
-	file_sz = get_file_size(dev, part, file, &status);
-	if (!file_sz)
+	/* Open file */
+	f = efi_file_from_path(initrd_fp);
+	if (!f) {
+		log_err("Can't find initrd specified in Boot####\n");
+		ret = EFI_NOT_FOUND;
+		goto out;
+	}
+
+	/* Get file size */
+	ret = efi_file_size(f, &bs);
+	if (ret != EFI_SUCCESS)
 		goto out;
 
-	if (!buffer || *buffer_size < file_sz) {
-		status = EFI_BUFFER_TOO_SMALL;
-		*buffer_size = file_sz;
+	if (!buffer || *buffer_size < bs) {
+		ret = EFI_BUFFER_TOO_SMALL;
+		*buffer_size = bs;
 	} else {
-		ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY);
-		if (ret) {
-			status = EFI_NO_MEDIA;
-			goto out;
-		}
-
-		ret = fs_read(file, map_to_sysmem(buffer), 0, *buffer_size,
-			      &read_sz);
-		if (ret || read_sz != file_sz)
-			goto out;
-		*buffer_size = read_sz;
-
-		status = EFI_SUCCESS;
+		ret = EFI_CALL(f->read(f, &bs, (void *)(uintptr_t)buffer));
+		*buffer_size = bs;
 	}
 
 out:
-	free(filespec);
-	return EFI_EXIT(status);
+	efi_free_pool(initrd_fp);
+	if (f)
+		EFI_CALL(f->close(f));
+	return EFI_EXIT(ret);
+}
+
+/**
+ * check_initrd() - Determine if the file defined as an initrd in Boot####
+ *		    load_options device path is present
+ *
+ * Return:	status code
+ */
+static efi_status_t check_initrd(void)
+{
+	struct efi_device_path *initrd_fp = NULL;
+	struct efi_file_handle *f;
+	efi_status_t ret;
+
+	ret = get_initrd_fp(&initrd_fp);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	/*
+	 * If the file is not found, but the file path is set, return an error
+	 * and trigger the bootmgr fallback
+	 */
+	f = efi_file_from_path(initrd_fp);
+	if (!f) {
+		log_err("Can't find initrd specified in Boot####\n");
+		ret = EFI_NOT_FOUND;
+		goto out;
+	}
+
+	EFI_CALL(f->close(f));
+
+out:
+	efi_free_pool(initrd_fp);
+	return ret;
 }
 
 /**
  * efi_initrd_register() - create handle for loading initial RAM disk
  *
  * This function creates a new handle and installs a Linux specific vendor
- * device path and an EFI_LOAD_FILE_2_PROTOCOL. Linux uses the device path
+ * device path and an EFI_LOAD_FILE2_PROTOCOL. Linux uses the device path
  * to identify the handle and then calls the LoadFile service of the
- * EFI_LOAD_FILE_2_PROTOCOL to read the initial RAM disk.
+ * EFI_LOAD_FILE2_PROTOCOL to read the initial RAM disk.
  *
  * Return:	status code
  */
 efi_status_t efi_initrd_register(void)
 {
-	efi_handle_t efi_initrd_handle = NULL;
 	efi_status_t ret;
 
+	/*
+	 * Allow the user to continue if Boot#### file path is not set for
+	 * an initrd
+	 */
+	ret = check_initrd();
+	if (ret == EFI_INVALID_PARAMETER)
+		return EFI_SUCCESS;
+	if (ret != EFI_SUCCESS)
+		return ret;
+
 	ret = EFI_CALL(efi_install_multiple_protocol_interfaces
 		       (&efi_initrd_handle,
 			/* initramfs */
-			&efi_guid_device_path, &dp,
+			&efi_guid_device_path, &dp_lf2_handle,
 			/* LOAD_FILE2 */
 			&efi_guid_load_file2_protocol,
 			(void *)&efi_lf2_protocol,
@@ -196,3 +220,17 @@
 
 	return ret;
 }
+
+/**
+ * efi_initrd_deregister() - delete the handle for loading initial RAM disk
+ *
+ * This will delete the handle containing the Linux specific vendor device
+ * path and EFI_LOAD_FILE2_PROTOCOL for loading an initrd
+ *
+ * Return:	status code
+ */
+void efi_initrd_deregister(void)
+{
+	efi_delete_handle(efi_initrd_handle);
+	efi_initrd_handle = NULL;
+}
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index b1c5125..3c5cf9a 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -227,6 +227,12 @@
 	if (ret != EFI_SUCCESS)
 		goto out;
 
+	if (IS_ENABLED(CONFIG_EFI_ESRT)) {
+		ret = efi_esrt_register();
+		if (ret != EFI_SUCCESS)
+			goto out;
+	}
+
 	if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) {
 		ret = efi_tcg2_register();
 		if (ret != EFI_SUCCESS)
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index 797d6eb..0904684 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -13,6 +13,7 @@
 #include <efi_loader.h>
 #include <efi_tcg2.h>
 #include <log.h>
+#include <version.h>
 #include <tpm-v2.h>
 #include <u-boot/sha1.h>
 #include <u-boot/sha256.h>
@@ -958,6 +959,23 @@
 }
 
 /**
+ * tcg2_uninit - remove the final event table and free efi memory on failures
+ */
+void tcg2_uninit(void)
+{
+	efi_status_t ret;
+
+	ret = efi_install_configuration_table(&efi_guid_final_events, NULL);
+	if (ret != EFI_SUCCESS)
+		log_err("Failed to delete final events config table\n");
+
+	efi_free_pool(event_log.buffer);
+	event_log.buffer = NULL;
+	efi_free_pool(event_log.final_buffer);
+	event_log.final_buffer = NULL;
+}
+
+/**
  * create_final_event() - Create the final event and install the config
  *			defined by the TCG EFI spec
  */
@@ -983,10 +1001,6 @@
 	event_log.final_pos = sizeof(*final_event);
 	ret = efi_install_configuration_table(&efi_guid_final_events,
 					      final_event);
-	if (ret != EFI_SUCCESS)
-		goto out;
-
-	return EFI_SUCCESS;
 out:
 	return ret;
 }
@@ -1041,6 +1055,40 @@
 	event_log.last_event_size = event_log.pos;
 
 	ret = create_final_event();
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	return EFI_SUCCESS;
+out:
+	tcg2_uninit();
+	return ret;
+}
+
+/**
+ * efi_append_scrtm_version - Append an S-CRTM EV_S_CRTM_VERSION event on the
+ *			      eventlog and extend the PCRs
+ *
+ * @dev:	TPM device
+ *
+ * @Return:	status code
+ */
+static efi_status_t efi_append_scrtm_version(struct udevice *dev)
+{
+	struct tpml_digest_values digest_list;
+	u8 ver[] = U_BOOT_VERSION_STRING;
+	const int pcr_index = 0;
+	efi_status_t ret;
+
+	ret = tcg2_create_digest(ver, sizeof(ver), &digest_list);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	ret = tcg2_pcr_extend(dev, pcr_index, &digest_list);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	ret = tcg2_agile_log_append(pcr_index, EV_S_CRTM_VERSION, &digest_list,
+				    sizeof(ver), ver);
 
 out:
 	return ret;
@@ -1055,23 +1103,34 @@
  */
 efi_status_t efi_tcg2_register(void)
 {
-	efi_status_t ret;
+	efi_status_t ret = EFI_SUCCESS;
 	struct udevice *dev;
 
 	ret = platform_get_tpm2_device(&dev);
 	if (ret != EFI_SUCCESS) {
 		log_warning("Unable to find TPMv2 device\n");
-		return EFI_SUCCESS;
+		ret = EFI_SUCCESS;
+		goto out;
 	}
 
 	ret = efi_init_event_log();
 	if (ret != EFI_SUCCESS)
-		return ret;
+		goto fail;
+
+	ret = efi_append_scrtm_version(dev);
+	if (ret != EFI_SUCCESS)
+		goto out;
 
 	ret = efi_add_protocol(efi_root, &efi_guid_tcg2_protocol,
 			       (void *)&efi_tcg2_protocol);
-	if (ret != EFI_SUCCESS)
+	if (ret != EFI_SUCCESS) {
 		log_err("Cannot install EFI_TCG2_PROTOCOL\n");
+		goto fail;
+	}
 
+out:
+	return ret;
+fail:
+	tcg2_uninit();
 	return ret;
 }
diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c
index 1c74592..b11ed91 100644
--- a/lib/efi_loader/efi_var_common.c
+++ b/lib/efi_loader/efi_var_common.c
@@ -9,6 +9,7 @@
 #include <common.h>
 #include <efi_loader.h>
 #include <efi_variable.h>
+#include <stdlib.h>
 
 enum efi_secure_mode {
 	EFI_MODE_SETUP,
@@ -343,3 +344,35 @@
 	}
 	return EFI_AUTH_VAR_NONE;
 }
+
+/**
+ * efi_get_var() - read value of an EFI variable
+ *
+ * @name:	variable name
+ * @start:	vendor GUID
+ * @size:	size of allocated buffer
+ *
+ * Return:	buffer with variable data or NULL
+ */
+void *efi_get_var(u16 *name, const efi_guid_t *vendor, efi_uintn_t *size)
+{
+	efi_status_t ret;
+	void *buf = NULL;
+
+	*size = 0;
+	ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL);
+	if (ret == EFI_BUFFER_TOO_SMALL) {
+		buf = malloc(*size);
+		if (!buf)
+			return NULL;
+		ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL);
+	}
+
+	if (ret != EFI_SUCCESS) {
+		free(buf);
+		*size = 0;
+		return NULL;
+	}
+
+	return buf;
+}
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
index 50de581..aa71d09 100644
--- a/lib/efi_selftest/Makefile
+++ b/lib/efi_selftest/Makefile
@@ -71,6 +71,8 @@
 obj-y += efi_selftest_block_device.o
 endif
 
+obj-$(CONFIG_EFI_ESRT) += efi_selftest_esrt.o
+
 targets += \
 efi_miniapp_file_image_exception.h \
 efi_miniapp_file_image_exit.h \
diff --git a/lib/efi_selftest/efi_selftest.c b/lib/efi_selftest/efi_selftest.c
index b8eed04..39ee2ed 100644
--- a/lib/efi_selftest/efi_selftest.c
+++ b/lib/efi_selftest/efi_selftest.c
@@ -160,7 +160,7 @@
 		if (testname && efi_st_strcmp_16_8(testname, test->name))
 			continue;
 		if (test->phase == EFI_SETUP_BEFORE_BOOTTIME_EXIT ||
-		    test->phase == EFI_SETUP_AFTER_BOOTTIME_EXIT)
+		    test->phase == EFI_SETTING_VIRTUAL_ADDRESS_MAP)
 			return true;
 	}
 	return false;
@@ -327,15 +327,16 @@
 	/* Execute mixed tests */
 	efi_st_do_tests(testname, EFI_SETUP_BEFORE_BOOTTIME_EXIT,
 			EFI_ST_SETUP, &failures);
+	efi_st_do_tests(testname, EFI_SETTING_VIRTUAL_ADDRESS_MAP,
+			EFI_ST_SETUP, &failures);
 
 	efi_st_exit_boot_services();
 
 	efi_st_do_tests(testname, EFI_SETUP_BEFORE_BOOTTIME_EXIT,
 			EFI_ST_EXECUTE | EFI_ST_TEARDOWN, &failures);
-
-	/* Execute runtime tests */
-	efi_st_do_tests(testname, EFI_SETUP_AFTER_BOOTTIME_EXIT,
-			EFI_ST_SETUP | EFI_ST_EXECUTE | EFI_ST_TEARDOWN,
+	/* Execute test setting the virtual address map */
+	efi_st_do_tests(testname, EFI_SETTING_VIRTUAL_ADDRESS_MAP,
+			EFI_ST_EXECUTE | EFI_ST_TEARDOWN,
 			&failures);
 
 	/* Give feedback */
diff --git a/lib/efi_selftest/efi_selftest_esrt.c b/lib/efi_selftest/efi_selftest_esrt.c
new file mode 100644
index 0000000..99251f2
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_esrt.c
@@ -0,0 +1,291 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *  Test ESRT tables support
+ *
+ *  Copyright (C) 2021 Arm Ltd.
+ */
+#include <common.h>
+#include <efi_loader.h>
+#include <efi_selftest.h>
+
+// This value must not exceed 255.
+// An FMP cannot contain more than 255 FW images.
+#define TEST_ESRT_NUM_ENTRIES 255
+
+static
+struct efi_firmware_image_descriptor static_img_info[TEST_ESRT_NUM_ENTRIES];
+
+static const struct efi_system_table *local_systable;
+
+static efi_handle_t fmp_handle;
+
+static const efi_guid_t efi_fmp_guid =
+		EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID;
+
+static void efi_test_esrt_init_info(void)
+{
+	for (int idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++) {
+		static_img_info[idx].image_index = idx;
+
+		// Note: the 16 byte value present in
+		// static_img_info[idx].image_type_id is not strictly a GUID.
+		// The value is used for the sake of code testing.
+		static_img_info[idx].image_type_id.b[0] = idx;
+
+		static_img_info[idx].image_id = 0;
+		static_img_info[idx].image_id_name = NULL;
+		static_img_info[idx].version = 0;
+		static_img_info[idx].version_name = NULL;
+		static_img_info[idx].size = 0;
+		static_img_info[idx].lowest_supported_image_version = 1;
+		static_img_info[idx].last_attempt_version = 2;
+		static_img_info[idx].last_attempt_status = 3;
+		static_img_info[idx].hardware_instance = 1;
+	}
+}
+
+static efi_status_t
+EFIAPI efi_test_fmp_get_image_info(struct efi_firmware_management_protocol *this,
+				   efi_uintn_t *image_info_size,
+				   struct efi_firmware_image_descriptor *image_info,
+				   u32 *descriptor_version,
+				   u8 *descriptor_count,
+				   efi_uintn_t *descriptor_size,
+				   u32 *package_version,
+				   u16 **package_version_name)
+{
+	efi_status_t ret = EFI_SUCCESS;
+
+	if (!image_info_size)
+		return EFI_INVALID_PARAMETER;
+
+	if (descriptor_version)
+		*descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
+	if (descriptor_count)
+		*descriptor_count = TEST_ESRT_NUM_ENTRIES;
+	if (descriptor_size)
+		*descriptor_size = sizeof(*image_info);
+	if (package_version)
+		*package_version = 0xffffffff;
+	if (package_version_name)
+		*package_version_name = NULL;
+
+	if (*image_info_size < sizeof(*image_info)) {
+		*image_info_size = *descriptor_size * *descriptor_count;
+		return EFI_BUFFER_TOO_SMALL;
+	}
+
+	for (int idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++)
+		image_info[idx] = static_img_info[idx];
+
+	return ret;
+}
+
+static struct efi_firmware_management_protocol efi_test_fmp = {
+	.get_image_info = efi_test_fmp_get_image_info,
+	.get_image = NULL,
+	.set_image = NULL,
+	.check_image = NULL,
+	.get_package_info = NULL,
+	.set_package_info = NULL,
+};
+
+static void *lib_test_get_esrt(void)
+{
+	for (int idx = 0; idx < local_systable->nr_tables; idx++)
+		if (!guidcmp(&efi_esrt_guid, &local_systable->tables[idx].guid))
+			return local_systable->tables[idx].table;
+
+	return NULL;
+}
+
+/**
+ * lib_test_check_uuid_entry: Find an ESRT entry for which the fw_calss field matches
+ * the image_type_id in the @img_info.
+ * Ensure that all of the field in the ESRT entry have the same value as the corresponding
+ * fields in the @img_info.
+ *
+ * @esrt: pointer to the ESRT
+ * @img_info: an image_info_descriptor output by the FMP get_image_info
+ *
+ * @return: true if matching ESRT entry is found and if all the ESRT entry fields match the
+ * corresponding @img_info fields.
+ */
+static bool lib_test_check_uuid_entry(struct efi_system_resource_table *esrt,
+				      struct efi_firmware_image_descriptor
+				      *img_info)
+{
+	const u32 filled_entries = esrt->fw_resource_count;
+	struct efi_system_resource_entry *entry = esrt->entries;
+
+	for (u32 idx = 0; idx < filled_entries; idx++) {
+		if (!guidcmp(&entry[idx].fw_class, &img_info->image_type_id)) {
+			if (entry[idx].fw_version != img_info->version) {
+				efi_st_error("ESRT field mismatch for entry with fw_class=%pUl\n",
+					     &img_info->image_type_id);
+				return false;
+			}
+
+			if (entry[idx].lowest_supported_fw_version !=
+				img_info->lowest_supported_image_version) {
+				efi_st_error("ESRT field mismatch for entry with fw_class=%pUl\n",
+					     &img_info->image_type_id);
+				return false;
+			}
+
+			if (entry[idx].last_attempt_version !=
+				img_info->last_attempt_version) {
+				efi_st_error("ESRT field mismatch for entry with fw_class=%pUl\n",
+					     &img_info->image_type_id);
+				return false;
+			}
+
+			if (entry[idx].last_attempt_status !=
+				img_info->last_attempt_status) {
+				efi_st_error("ESRT field mismatch for entry with fw_class=%pUl\n",
+					     &img_info->image_type_id);
+				return false;
+			}
+
+			/*
+			 * The entry with fw_class = img_uuid matches with the
+			 * remainder fmp input.
+			 */
+			return true;
+		}
+	}
+
+	/* There exists no entry with fw_class equal to img_uuid in the ESRT. */
+	efi_st_error("ESRT no entry with fw_class= %pUl\n", &img_info->image_type_id);
+
+	return false;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Initialize the test FMP datastructure.
+ *
+ * @handle:	handle of the loaded image
+ * @systable:	system table
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+		 const struct efi_system_table *systable)
+{
+	local_systable = systable;
+
+	efi_test_esrt_init_info();
+
+	return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * Uninstall the test FMP.
+ *
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+	efi_status_t ret = EFI_SUCCESS;
+	struct efi_boot_services *bt;
+
+	bt = local_systable->boottime;
+
+	if (!bt) {
+		efi_st_error("Cannot find boottime services structure\n");
+		return EFI_ST_FAILURE;
+	}
+
+	ret = bt->uninstall_multiple_protocol_interfaces
+		(fmp_handle, &efi_fmp_guid,
+		 &efi_test_fmp, NULL);
+
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to uninstall FMP\n");
+		return EFI_ST_FAILURE;
+	}
+
+	return EFI_ST_SUCCESS;
+}
+
+/*
+ * Perform the test
+ *
+ * The test consists of the following steps:
+ *
+ * 1) Obtain the ESRT
+ * 2) Record the number of ESRT entries prior to test start
+ * 3) Install the test FMP
+ * 4) Re-obtain the ESRT (the ESRT pointer may have changed with the FMP install)
+ * 5) verify that the ESRT entries have increased by the number of entries in the
+ *     test FMP.
+ * 6) Traverse all the elements used as the test FMP input and verify that each
+ *     has a corresponding ESRT entry and that the fields are correctly set.
+ *
+ * The failure of any of the above steps results in a test failure.
+ *
+ */
+static int execute(void)
+{
+	struct efi_system_resource_table *esrt;
+	efi_status_t ret = EFI_SUCCESS;
+	u32 base_entry_count;
+	u32 entry_delta;
+	struct efi_boot_services *bt;
+
+	bt = local_systable->boottime;
+
+	if (!bt) {
+		efi_st_error("Cannot find boottime services structure\n");
+		return EFI_ST_FAILURE;
+	}
+
+	esrt = lib_test_get_esrt();
+	if (!esrt) {
+		efi_st_error("ESRT table not present\n");
+		return EFI_ST_FAILURE;
+	}
+	base_entry_count = esrt->fw_resource_count;
+
+	ret = bt->install_multiple_protocol_interfaces(&fmp_handle,
+						       &efi_fmp_guid,
+						       &efi_test_fmp,
+						       NULL);
+
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to install FMP\n");
+		return EFI_ST_FAILURE;
+	}
+
+	esrt = lib_test_get_esrt();
+	if (!esrt) {
+		efi_st_error("ESRT table not present\n");
+		return EFI_ST_FAILURE;
+	}
+
+	entry_delta = esrt->fw_resource_count - base_entry_count;
+	if (entry_delta != TEST_ESRT_NUM_ENTRIES) {
+		efi_st_error("ESRT mismatch in new entry count (%d), expected (%d).\n",
+			     entry_delta, TEST_ESRT_NUM_ENTRIES);
+		return EFI_ST_FAILURE;
+	}
+
+	for (u32 idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++)
+		if (!lib_test_check_uuid_entry(esrt, &static_img_info[idx])) {
+			efi_st_error("ESRT entry mismatch\n");
+			return EFI_ST_FAILURE;
+		}
+
+	return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(esrt) = {
+	.name = "esrt",
+	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+	.setup = setup,
+	.execute = execute,
+	.teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_set_virtual_address_map.c b/lib/efi_selftest/efi_selftest_set_virtual_address_map.c
index b097a81..8e2e8ba 100644
--- a/lib/efi_selftest/efi_selftest_set_virtual_address_map.c
+++ b/lib/efi_selftest/efi_selftest_set_virtual_address_map.c
@@ -201,7 +201,7 @@
 
 EFI_UNIT_TEST(virtaddrmap) = {
 	.name = "virtual address map",
-	.phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
+	.phase = EFI_SETTING_VIRTUAL_ADDRESS_MAP,
 	.setup = setup,
 	.execute = execute,
 };
diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c
index b89f988..34203f9 100644
--- a/lib/smbios-parser.c
+++ b/lib/smbios-parser.c
@@ -3,6 +3,8 @@
  * Copyright (C) 2020, Bachmann electronic GmbH
  */
 
+#define LOG_CATEGORY	LOGC_BOOT
+
 #include <common.h>
 #include <smbios.h>
 
@@ -94,3 +96,39 @@
 
 	return string_from_smbios_table(header, index);
 }
+
+int smbios_update_version_full(void *smbios_tab, const char *version)
+{
+	const struct smbios_header *hdr;
+	struct smbios_type0 *bios;
+	uint old_len, len;
+	char *ptr;
+
+	log_info("Updating SMBIOS table at %p\n", smbios_tab);
+	hdr = smbios_header(smbios_tab, SMBIOS_BIOS_INFORMATION);
+	if (!hdr)
+		return log_msg_ret("tab", -ENOENT);
+	bios = (struct smbios_type0 *)hdr;
+	ptr = (char *)smbios_string(hdr, bios->bios_ver);
+	if (!ptr)
+		return log_msg_ret("str", -ENOMEDIUM);
+
+	/*
+	 * This string is supposed to have at least enough bytes and is
+	 * padded with spaces. Update it, taking care not to move the
+	 * \0 terminator, so that other strings in the string table
+	 * are not disturbed. See smbios_add_string()
+	 */
+	old_len = strnlen(ptr, SMBIOS_STR_MAX);
+	len = strnlen(version, SMBIOS_STR_MAX);
+	if (len > old_len)
+		return log_ret(-ENOSPC);
+
+	log_debug("Replacing SMBIOS type 0 version string '%s'\n", ptr);
+	memcpy(ptr, version, len);
+#ifdef LOG_DEBUG
+	print_buffer((ulong)ptr, ptr, 1, old_len + 1, 0);
+#endif
+
+	return 0;
+}
diff --git a/lib/smbios.c b/lib/smbios.c
index 7d463c8..9eb226e 100644
--- a/lib/smbios.c
+++ b/lib/smbios.c
@@ -20,10 +20,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-enum {
-	SMBIOS_STR_MAX	= 64,	/* Maximum length allowed for a string */
-};
-
 /**
  * struct smbios_ctx - context for writing SMBIOS tables
  *
diff --git a/lib/tpm-common.c b/lib/tpm-common.c
index e4af87f..4277846 100644
--- a/lib/tpm-common.c
+++ b/lib/tpm-common.c
@@ -166,6 +166,7 @@
 	u8 response_buffer[COMMAND_BUFFER_SIZE];
 	size_t response_length;
 	int i;
+	uint size;
 
 	if (response) {
 		response_length = *size_ptr;
@@ -174,8 +175,13 @@
 		response_length = sizeof(response_buffer);
 	}
 
-	err = tpm_xfer(dev, command, tpm_command_size(command),
-		       response, &response_length);
+	size = tpm_command_size(command);
+	log_debug("TPM request [size:%d]: ", size);
+	for (i = 0; i < size; i++)
+		log_debug("%02x ", ((u8 *)command)[i]);
+	log_debug("\n");
+
+	err = tpm_xfer(dev, command, size, response, &response_length);
 
 	if (err < 0)
 		return err;
diff --git a/lib/tpm-v1.c b/lib/tpm-v1.c
index a846fe0..8dc1440 100644
--- a/lib/tpm-v1.c
+++ b/lib/tpm-v1.c
@@ -32,7 +32,7 @@
 
 #endif /* CONFIG_TPM_AUTH_SESSIONS */
 
-u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
+u32 tpm1_startup(struct udevice *dev, enum tpm_startup_type mode)
 {
 	const u8 command[12] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
@@ -48,12 +48,12 @@
 	return tpm_sendrecv_command(dev, buf, NULL, NULL);
 }
 
-u32 tpm_resume(struct udevice *dev)
+u32 tpm1_resume(struct udevice *dev)
 {
-	return tpm_startup(dev, TPM_ST_STATE);
+	return tpm1_startup(dev, TPM_ST_STATE);
 }
 
-u32 tpm_self_test_full(struct udevice *dev)
+u32 tpm1_self_test_full(struct udevice *dev)
 {
 	const u8 command[10] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
@@ -61,7 +61,7 @@
 	return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_continue_self_test(struct udevice *dev)
+u32 tpm1_continue_self_test(struct udevice *dev)
 {
 	const u8 command[10] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
@@ -69,35 +69,33 @@
 	return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_clear_and_reenable(struct udevice *dev)
+u32 tpm1_clear_and_reenable(struct udevice *dev)
 {
 	u32 ret;
 
 	log_info("TPM: Clear and re-enable\n");
-	ret = tpm_force_clear(dev);
+	ret = tpm1_force_clear(dev);
 	if (ret != TPM_SUCCESS) {
 		log_err("Can't initiate a force clear\n");
 		return ret;
 	}
 
-	if (tpm_get_version(dev) == TPM_V1) {
-		ret = tpm_physical_enable(dev);
-		if (ret != TPM_SUCCESS) {
-			log_err("TPM: Can't set enabled state\n");
-			return ret;
-		}
+	ret = tpm1_physical_enable(dev);
+	if (ret != TPM_SUCCESS) {
+		log_err("TPM: Can't set enabled state\n");
+		return ret;
+	}
 
-		ret = tpm_physical_set_deactivated(dev, 0);
-		if (ret != TPM_SUCCESS) {
-			log_err("TPM: Can't set deactivated state\n");
-			return ret;
-		}
+	ret = tpm1_physical_set_deactivated(dev, 0);
+	if (ret != TPM_SUCCESS) {
+		log_err("TPM: Can't set deactivated state\n");
+		return ret;
 	}
 
 	return TPM_SUCCESS;
 }
 
-u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size)
+u32 tpm1_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size)
 {
 	const u8 command[101] = {
 		0x0, 0xc1,		/* TPM_TAG */
@@ -140,12 +138,12 @@
 	return tpm_sendrecv_command(dev, buf, NULL, NULL);
 }
 
-u32 tpm_nv_set_locked(struct udevice *dev)
+u32 tpm1_nv_set_locked(struct udevice *dev)
 {
-	return tpm_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
+	return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
 }
 
-u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
+u32 tpm1_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
 {
 	const u8 command[22] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
@@ -179,8 +177,8 @@
 	return 0;
 }
 
-u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
-		       u32 length)
+u32 tpm1_nv_write_value(struct udevice *dev, u32 index, const void *data,
+			u32 length)
 {
 	const u8 command[256] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
@@ -210,13 +208,8 @@
 	return 0;
 }
 
-uint32_t tpm_set_global_lock(struct udevice *dev)
-{
-	return tpm_nv_write_value(dev, TPM_NV_INDEX_0, NULL, 0);
-}
-
-u32 tpm_extend(struct udevice *dev, u32 index, const void *in_digest,
-	       void *out_digest)
+u32 tpm1_extend(struct udevice *dev, u32 index, const void *in_digest,
+		void *out_digest)
 {
 	const u8 command[34] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
@@ -247,7 +240,7 @@
 	return 0;
 }
 
-u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
+u32 tpm1_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
 {
 	const u8 command[14] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
@@ -275,7 +268,7 @@
 	return 0;
 }
 
-u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence)
+u32 tpm1_tsc_physical_presence(struct udevice *dev, u16 presence)
 {
 	const u8 command[12] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
@@ -291,7 +284,7 @@
 	return tpm_sendrecv_command(dev, buf, NULL, NULL);
 }
 
-u32 tpm_finalise_physical_presence(struct udevice *dev)
+u32 tpm1_finalise_physical_presence(struct udevice *dev)
 {
 	const u8 command[12] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0,
@@ -300,7 +293,7 @@
 	return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count)
+u32 tpm1_read_pubek(struct udevice *dev, void *data, size_t count)
 {
 	const u8 command[30] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
@@ -331,7 +324,7 @@
 	return 0;
 }
 
-u32 tpm_force_clear(struct udevice *dev)
+u32 tpm1_force_clear(struct udevice *dev)
 {
 	const u8 command[10] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
@@ -340,7 +333,7 @@
 	return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_physical_enable(struct udevice *dev)
+u32 tpm1_physical_enable(struct udevice *dev)
 {
 	const u8 command[10] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
@@ -349,7 +342,7 @@
 	return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_physical_disable(struct udevice *dev)
+u32 tpm1_physical_disable(struct udevice *dev)
 {
 	const u8 command[10] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
@@ -358,7 +351,7 @@
 	return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state)
+u32 tpm1_physical_set_deactivated(struct udevice *dev, u8 state)
 {
 	const u8 command[11] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
@@ -374,8 +367,8 @@
 	return tpm_sendrecv_command(dev, buf, NULL, NULL);
 }
 
-u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
-		       void *cap, size_t count)
+u32 tpm1_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
+			void *cap, size_t count)
 {
 	const u8 command[22] = {
 		0x0, 0xc1,		/* TPM_TAG */
@@ -414,8 +407,8 @@
 	return 0;
 }
 
-u32 tpm_get_permanent_flags(struct udevice *dev,
-			    struct tpm_permanent_flags *pflags)
+u32 tpm1_get_permanent_flags(struct udevice *dev,
+			     struct tpm_permanent_flags *pflags)
 {
 	const u8 command[22] = {
 		0x0, 0xc1,		/* TPM_TAG */
@@ -453,7 +446,7 @@
 	return 0;
 }
 
-u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm)
+u32 tpm1_get_permissions(struct udevice *dev, u32 index, u32 *perm)
 {
 	const u8 command[22] = {
 		0x0, 0xc1,		/* TPM_TAG */
@@ -482,7 +475,7 @@
 }
 
 #ifdef CONFIG_TPM_FLUSH_RESOURCES
-u32 tpm_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type)
+u32 tpm1_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type)
 {
 	const u8 command[18] = {
 		0x00, 0xc1,             /* TPM_TAG */
@@ -641,7 +634,7 @@
 	return TPM_SUCCESS;
 }
 
-u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle)
+u32 tpm1_terminate_auth_session(struct udevice *dev, u32 auth_handle)
 {
 	const u8 command[18] = {
 		0x00, 0xc1,		/* TPM_TAG */
@@ -663,16 +656,16 @@
 	return tpm_sendrecv_command(dev, request, NULL, NULL);
 }
 
-u32 tpm_end_oiap(struct udevice *dev)
+u32 tpm1_end_oiap(struct udevice *dev)
 {
 	u32 err = TPM_SUCCESS;
 
 	if (oiap_session.valid)
-		err = tpm_terminate_auth_session(dev, oiap_session.handle);
+		err = tpm1_terminate_auth_session(dev, oiap_session.handle);
 	return err;
 }
 
-u32 tpm_oiap(struct udevice *dev, u32 *auth_handle)
+u32 tpm1_oiap(struct udevice *dev, u32 *auth_handle)
 {
 	const u8 command[10] = {
 		0x00, 0xc1,		/* TPM_TAG */
@@ -686,7 +679,7 @@
 	u32 err;
 
 	if (oiap_session.valid)
-		tpm_terminate_auth_session(dev, oiap_session.handle);
+		tpm1_terminate_auth_session(dev, oiap_session.handle);
 
 	err = tpm_sendrecv_command(dev, command, response, &response_length);
 	if (err)
@@ -702,9 +695,9 @@
 	return 0;
 }
 
-u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
-		       size_t key_length, const void *parent_key_usage_auth,
-		       u32 *key_handle)
+u32 tpm1_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
+			size_t key_length, const void *parent_key_usage_auth,
+			u32 *key_handle)
 {
 	const u8 command[14] = {
 		0x00, 0xc2,		/* TPM_TAG */
@@ -723,7 +716,7 @@
 	u32 err;
 
 	if (!oiap_session.valid) {
-		err = tpm_oiap(dev, NULL);
+		err = tpm1_oiap(dev, NULL);
 		if (err)
 			return err;
 	}
@@ -768,9 +761,9 @@
 	return 0;
 }
 
-u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
-			 const void *usage_auth, void *pubkey,
-			 size_t *pubkey_len)
+u32 tpm1_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
+			  const void *usage_auth, void *pubkey,
+			  size_t *pubkey_len)
 {
 	const u8 command[14] = {
 		0x00, 0xc2,		/* TPM_TAG */
@@ -788,7 +781,7 @@
 	u32 err;
 
 	if (!oiap_session.valid) {
-		err = tpm_oiap(dev, NULL);
+		err = tpm1_oiap(dev, NULL);
 		if (err)
 			return err;
 	}
@@ -834,8 +827,8 @@
 }
 
 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
-u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20],
-		      const u8 pubkey_digest[20], u32 *handle)
+u32 tpm1_find_key_sha1(struct udevice *dev, const u8 auth[20],
+		       const u8 pubkey_digest[20], u32 *handle)
 {
 	u16 key_count;
 	u32 key_handles[10];
@@ -876,7 +869,7 @@
 
 #endif /* CONFIG_TPM_AUTH_SESSIONS */
 
-u32 tpm_get_random(struct udevice *dev, void *data, u32 count)
+u32 tpm1_get_random(struct udevice *dev, void *data, u32 count)
 {
 	const u8 command[14] = {
 		0x0, 0xc1,		/* TPM_TAG */
diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
index 1f3deb0..235f8c2 100644
--- a/lib/tpm-v2.c
+++ b/lib/tpm-v2.c
@@ -47,9 +47,11 @@
 u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
 	       const ssize_t pw_sz)
 {
+	/* Length of the message header, up to start of password */
+	uint offset = 27;
 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
-		tpm_u32(27 + pw_sz),		/* Length */
+		tpm_u32(offset + pw_sz),	/* Length */
 		tpm_u32(TPM2_CC_CLEAR),		/* Command code */
 
 		/* HANDLE */
@@ -64,7 +66,6 @@
 		tpm_u16(pw_sz),			/* Size of <hmac/password> */
 		/* STRING(pw)			   <hmac/password> (if any) */
 	};
-	unsigned int offset = 27;
 	int ret;
 
 	/*
@@ -80,12 +81,61 @@
 	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
 }
 
+u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
+			 size_t space_size, u32 nv_attributes,
+			 const u8 *nv_policy, size_t nv_policy_size)
+{
+	/*
+	 * Calculate the offset of the nv_policy piece by adding each of the
+	 * chunks below.
+	 */
+	uint offset = 10 + 8 + 13 + 14;
+	u8 command_v2[COMMAND_BUFFER_SIZE] = {
+		/* header 10 bytes */
+		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
+		tpm_u32(offset + nv_policy_size),/* Length */
+		tpm_u32(TPM2_CC_NV_DEFINE_SPACE),/* Command code */
+
+		/* handles 8 bytes */
+		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
+
+		/* session header 13 bytes */
+		tpm_u32(9),			/* Header size */
+		tpm_u32(TPM2_RS_PW),		/* Password authorisation */
+		tpm_u16(0),			/* nonce_size */
+		0,				/* session_attrs */
+		tpm_u16(0),			/* auth_size */
+
+		/* message 14 bytes + policy */
+		tpm_u16(12 + nv_policy_size),	/* size */
+		tpm_u32(space_index),
+		tpm_u16(TPM2_ALG_SHA256),
+		tpm_u32(nv_attributes),
+		tpm_u16(nv_policy_size),
+		/* nv_policy */
+	};
+	int ret;
+
+	/*
+	 * Fill the command structure starting from the first buffer:
+	 *     - the password (if any)
+	 */
+	ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
+			       offset, nv_policy, nv_policy_size);
+	if (ret)
+		return TPM_LIB_ERROR;
+
+	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
+}
+
 u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
 		    const u8 *digest, u32 digest_len)
 {
+	/* Length of the message header, up to start of digest */
+	uint offset = 33;
 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
-		tpm_u32(33 + digest_len),	/* Length */
+		tpm_u32(offset + digest_len),	/* Length */
 		tpm_u32(TPM2_CC_PCR_EXTEND),	/* Command code */
 
 		/* HANDLE */
@@ -99,11 +149,12 @@
 		0,				/* Attributes: Cont/Excl/Rst */
 		tpm_u16(0),			/* Size of <hmac/password> */
 						/* <hmac/password> (if any) */
+
+		/* hashes */
 		tpm_u32(1),			/* Count (number of hashes) */
 		tpm_u16(algorithm),	/* Algorithm of the hash */
 		/* STRING(digest)		   Digest */
 	};
-	unsigned int offset = 33;
 	int ret;
 
 	/*
@@ -112,13 +163,96 @@
 	 */
 	ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
 			       offset, digest, digest_len);
-	offset += digest_len;
 	if (ret)
 		return TPM_LIB_ERROR;
 
 	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
 }
 
+u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
+{
+	u8 command_v2[COMMAND_BUFFER_SIZE] = {
+		/* header 10 bytes */
+		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
+		tpm_u32(10 + 8 + 4 + 9 + 4),	/* Length */
+		tpm_u32(TPM2_CC_NV_READ),	/* Command code */
+
+		/* handles 8 bytes */
+		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
+		tpm_u32(HR_NV_INDEX + index),	/* Password authorisation */
+
+		/* AUTH_SESSION */
+		tpm_u32(9),			/* Authorization size */
+		tpm_u32(TPM2_RS_PW),		/* Session handle */
+		tpm_u16(0),			/* Size of <nonce> */
+						/* <nonce> (if any) */
+		0,				/* Attributes: Cont/Excl/Rst */
+		tpm_u16(0),			/* Size of <hmac/password> */
+						/* <hmac/password> (if any) */
+
+		tpm_u16(count),			/* Number of bytes */
+		tpm_u16(0),			/* Offset */
+	};
+	size_t response_len = COMMAND_BUFFER_SIZE;
+	u8 response[COMMAND_BUFFER_SIZE];
+	int ret;
+	u16 tag;
+	u32 size, code;
+
+	ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
+	if (ret)
+		return log_msg_ret("read", ret);
+	if (unpack_byte_string(response, response_len, "wdds",
+			       0, &tag, 2, &size, 6, &code,
+			       16, data, count))
+		return TPM_LIB_ERROR;
+
+	return 0;
+}
+
+u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
+			u32 count)
+{
+	struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
+	uint offset = 10 + 8 + 4 + 9 + 2;
+	uint len = offset + count + 2;
+	/* Use empty password auth if platform hierarchy is disabled */
+	u32 auth = priv->plat_hier_disabled ? HR_NV_INDEX + index :
+		TPM2_RH_PLATFORM;
+	u8 command_v2[COMMAND_BUFFER_SIZE] = {
+		/* header 10 bytes */
+		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
+		tpm_u32(len),			/* Length */
+		tpm_u32(TPM2_CC_NV_WRITE),	/* Command code */
+
+		/* handles 8 bytes */
+		tpm_u32(auth),			/* Primary platform seed */
+		tpm_u32(HR_NV_INDEX + index),	/* Password authorisation */
+
+		/* AUTH_SESSION */
+		tpm_u32(9),			/* Authorization size */
+		tpm_u32(TPM2_RS_PW),		/* Session handle */
+		tpm_u16(0),			/* Size of <nonce> */
+						/* <nonce> (if any) */
+		0,				/* Attributes: Cont/Excl/Rst */
+		tpm_u16(0),			/* Size of <hmac/password> */
+						/* <hmac/password> (if any) */
+
+		tpm_u16(count),
+	};
+	size_t response_len = COMMAND_BUFFER_SIZE;
+	u8 response[COMMAND_BUFFER_SIZE];
+	int ret;
+
+	ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
+			       offset, data, count,
+			       offset + count, 0);
+	if (ret)
+		return TPM_LIB_ERROR;
+
+	return tpm_sendrecv_command(dev, command_v2, response, &response_len);
+}
+
 u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
 		  void *data, unsigned int *updates)
 {
@@ -467,3 +601,61 @@
 
 	return 0;
 }
+
+u32 tpm2_write_lock(struct udevice *dev, u32 index)
+{
+	u8 command_v2[COMMAND_BUFFER_SIZE] = {
+		/* header 10 bytes */
+		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
+		tpm_u32(10 + 8 + 13), /* Length */
+		tpm_u32(TPM2_CC_NV_WRITELOCK), /* Command code */
+
+		/* handles 8 bytes */
+		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
+		tpm_u32(HR_NV_INDEX + index),	/* Password authorisation */
+
+		/* session header 9 bytes */
+		tpm_u32(9),			/* Header size */
+		tpm_u32(TPM2_RS_PW),		/* Password authorisation */
+		tpm_u16(0),			/* nonce_size */
+		0,				/* session_attrs */
+		tpm_u16(0),			/* auth_size */
+	};
+
+	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
+}
+
+u32 tpm2_disable_platform_hierarchy(struct udevice *dev)
+{
+	struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
+	u8 command_v2[COMMAND_BUFFER_SIZE] = {
+		/* header 10 bytes */
+		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
+		tpm_u32(10 + 4 + 13 + 5),	/* Length */
+		tpm_u32(TPM2_CC_HIER_CONTROL),	/* Command code */
+
+		/* 4 bytes */
+		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
+
+		/* session header 9 bytes */
+		tpm_u32(9),			/* Header size */
+		tpm_u32(TPM2_RS_PW),		/* Password authorisation */
+		tpm_u16(0),			/* nonce_size */
+		0,				/* session_attrs */
+		tpm_u16(0),			/* auth_size */
+
+		/* payload 5 bytes */
+		tpm_u32(TPM2_RH_PLATFORM),	/* Hierarchy to disable */
+		0,				/* 0=disable */
+	};
+	int ret;
+
+	ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
+	log_info("ret=%s, %x\n", dev->name, ret);
+	if (ret)
+		return ret;
+
+	priv->plat_hier_disabled = true;
+
+	return 0;
+}
diff --git a/lib/tpm_api.c b/lib/tpm_api.c
new file mode 100644
index 0000000..4c66264
--- /dev/null
+++ b/lib/tpm_api.c
@@ -0,0 +1,285 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <tpm_api.h>
+#include <tpm-v1.h>
+#include <tpm-v2.h>
+#include <tpm_api.h>
+
+static bool is_tpm1(struct udevice *dev)
+{
+	return IS_ENABLED(CONFIG_TPM_V1) && tpm_get_version(dev) == TPM_V1;
+}
+
+static bool is_tpm2(struct udevice *dev)
+{
+	return IS_ENABLED(CONFIG_TPM_V2) && tpm_get_version(dev) == TPM_V2;
+}
+
+u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
+{
+	if (is_tpm1(dev)) {
+		return tpm1_startup(dev, mode);
+	} else if (is_tpm2(dev)) {
+		enum tpm2_startup_types type;
+
+		switch (mode) {
+		case TPM_ST_CLEAR:
+			type = TPM2_SU_CLEAR;
+			break;
+		case TPM_ST_STATE:
+			type = TPM2_SU_STATE;
+			break;
+		default:
+		case TPM_ST_DEACTIVATED:
+			return -EINVAL;
+		}
+		return tpm2_startup(dev, type);
+	} else {
+		return -ENOSYS;
+	}
+}
+
+u32 tpm_resume(struct udevice *dev)
+{
+	if (is_tpm1(dev))
+		return tpm1_startup(dev, TPM_ST_STATE);
+	else if (is_tpm2(dev))
+		return tpm2_startup(dev, TPM2_SU_STATE);
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_self_test_full(struct udevice *dev)
+{
+	if (is_tpm1(dev))
+		return tpm1_self_test_full(dev);
+	else if (is_tpm2(dev))
+		return tpm2_self_test(dev, TPMI_YES);
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_continue_self_test(struct udevice *dev)
+{
+	if (is_tpm1(dev))
+		return tpm1_continue_self_test(dev);
+	else if (is_tpm2(dev))
+		return tpm2_self_test(dev, TPMI_NO);
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_clear_and_reenable(struct udevice *dev)
+{
+	u32 ret;
+
+	log_info("TPM: Clear and re-enable\n");
+	ret = tpm_force_clear(dev);
+	if (ret != TPM_SUCCESS) {
+		log_err("Can't initiate a force clear\n");
+		return ret;
+	}
+
+	if (is_tpm1(dev)) {
+		ret = tpm1_physical_enable(dev);
+		if (ret != TPM_SUCCESS) {
+			log_err("TPM: Can't set enabled state\n");
+			return ret;
+		}
+
+		ret = tpm1_physical_set_deactivated(dev, 0);
+		if (ret != TPM_SUCCESS) {
+			log_err("TPM: Can't set deactivated state\n");
+			return ret;
+		}
+	}
+
+	return TPM_SUCCESS;
+}
+
+u32 tpm_nv_enable_locking(struct udevice *dev)
+{
+	if (is_tpm1(dev))
+		return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
+	else if (is_tpm2(dev))
+		return -ENOSYS;
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
+{
+	if (is_tpm1(dev))
+		return tpm1_nv_read_value(dev, index, data, count);
+	else if (is_tpm2(dev))
+		return tpm2_nv_read_value(dev, index, data, count);
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
+		       u32 count)
+{
+	if (is_tpm1(dev))
+		return tpm1_nv_write_value(dev, index, data, count);
+	else if (is_tpm2(dev))
+		return tpm2_nv_write_value(dev, index, data, count);
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_set_global_lock(struct udevice *dev)
+{
+	return tpm_nv_write_value(dev, TPM_NV_INDEX_0, NULL, 0);
+}
+
+u32 tpm_write_lock(struct udevice *dev, u32 index)
+{
+	if (is_tpm1(dev))
+		return -ENOSYS;
+	else if (is_tpm2(dev))
+		return tpm2_write_lock(dev, index);
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest,
+		   void *out_digest)
+{
+	if (is_tpm1(dev))
+		return tpm1_extend(dev, index, in_digest, out_digest);
+	else if (is_tpm2(dev))
+		return tpm2_pcr_extend(dev, index, TPM2_ALG_SHA256, in_digest,
+				       TPM2_DIGEST_LEN);
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
+{
+	if (is_tpm1(dev))
+		return tpm1_pcr_read(dev, index, data, count);
+	else if (is_tpm2(dev))
+		return -ENOSYS;
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence)
+{
+	if (is_tpm1(dev))
+		return tpm1_tsc_physical_presence(dev, presence);
+
+	/*
+	 * Nothing to do on TPM2 for this; use platform hierarchy availability
+	 * instead.
+	 */
+	else if (is_tpm2(dev))
+		return 0;
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_finalise_physical_presence(struct udevice *dev)
+{
+	if (is_tpm1(dev))
+		return tpm1_finalise_physical_presence(dev);
+
+	/* Nothing needs to be done with tpm2 */
+	else if (is_tpm2(dev))
+		return 0;
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count)
+{
+	if (is_tpm1(dev))
+		return tpm1_read_pubek(dev, data, count);
+	else if (is_tpm2(dev))
+		return -ENOSYS; /* not implemented yet */
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_force_clear(struct udevice *dev)
+{
+	if (is_tpm1(dev))
+		return tpm1_force_clear(dev);
+	else if (is_tpm2(dev))
+		return tpm2_clear(dev, TPM2_RH_PLATFORM, NULL, 0);
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_physical_enable(struct udevice *dev)
+{
+	if (is_tpm1(dev))
+		return tpm1_physical_enable(dev);
+
+	/* Nothing needs to be done with tpm2 */
+	else if (is_tpm2(dev))
+		return 0;
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_physical_disable(struct udevice *dev)
+{
+	if (is_tpm1(dev))
+		return tpm1_physical_disable(dev);
+
+	/* Nothing needs to be done with tpm2 */
+	else if (is_tpm2(dev))
+		return 0;
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state)
+{
+	if (is_tpm1(dev))
+		return tpm1_physical_set_deactivated(dev, state);
+	/* Nothing needs to be done with tpm2 */
+	else if (is_tpm2(dev))
+		return 0;
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
+		       void *cap, size_t count)
+{
+	if (is_tpm1(dev))
+		return tpm1_get_capability(dev, cap_area, sub_cap, cap, count);
+	else if (is_tpm2(dev))
+		return tpm2_get_capability(dev, cap_area, sub_cap, cap, count);
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm)
+{
+	if (is_tpm1(dev))
+		return tpm1_get_permissions(dev, index, perm);
+	else if (is_tpm2(dev))
+		return -ENOSYS; /* not implemented yet */
+	else
+		return -ENOSYS;
+}
+
+u32 tpm_get_random(struct udevice *dev, void *data, u32 count)
+{
+	if (is_tpm1(dev))
+		return tpm1_get_random(dev, data, count);
+	else if (is_tpm2(dev))
+		return -ENOSYS; /* not implemented yet */
+	else
+		return -ENOSYS;
+}
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index 1fd63ef..ca98822 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -120,10 +120,25 @@
 u-boot-spl-init := $(head-y)
 u-boot-spl-main := $(libs-y)
 ifdef CONFIG_$(SPL_TPL_)OF_PLATDATA
-u-boot-spl-platdata := $(obj)/dts/dt-plat.o
-u-boot-spl-platdata_c := $(patsubst %.o,%.c,$(u-boot-spl-platdata))
+platdata-hdr := include/generated/dt-structs-gen.h include/generated/dt-decl.h
+platdata-inst := $(obj)/dts/dt-uclass.o $(obj)/dts/dt-device.o
+platdata-noinst := $(obj)/dts/dt-plat.o
+
+ifdef CONFIG_$(SPL_TPL_)OF_PLATDATA_INST
+u-boot-spl-platdata := $(platdata-inst)
+u-boot-spl-old-platdata := $(platdata-noinst)
+else
+u-boot-spl-platdata := $(platdata-noinst)
+u-boot-spl-old-platdata := $(platdata-inst)
 endif
 
+# Files we need to generate
+u-boot-spl-platdata_c := $(patsubst %.o,%.c,$(u-boot-spl-platdata))
+
+# Files we won't generate and should remove
+u-boot-spl-old-platdata_c := $(patsubst %.o,%.c,$(u-boot-spl-old-platdata))
+endif  # OF_PLATDATA
+
 # Linker Script
 # First test whether there's a linker-script for the specific stage defined...
 ifneq ($(CONFIG_$(SPL_TPL_)LDSCRIPT),)
@@ -311,7 +326,11 @@
 pythonpath = PYTHONPATH=scripts/dtc/pylibfdt
 
 DTOC_ARGS := $(pythonpath) $(srctree)/tools/dtoc/dtoc \
-	-d $(obj)/$(SPL_BIN).dtb
+	-d $(obj)/$(SPL_BIN).dtb -p $(SPL_NAME)
+
+ifneq ($(CONFIG_$(SPL_TPL_)OF_PLATDATA_INST),)
+DTOC_ARGS += -i
+endif
 
 quiet_cmd_dtoc = DTOC    $@
 cmd_dtoc = $(DTOC_ARGS) -c $(obj)/dts -C include/generated all
@@ -319,18 +338,17 @@
 quiet_cmd_plat = PLAT    $@
 cmd_plat = $(CC) $(c_flags) -c $< -o $(filter-out $(PHONY),$@)
 
-targets += $(u-boot-spl-platdata)
-
-$(obj)/dts/dt-%.o: $(obj)/dts/dt-%.c \
-		include/generated/dt-structs-gen.h prepare FORCE
+$(obj)/dts/dt-%.o: $(obj)/dts/dt-%.c $(platdata-hdr)
 	$(call if_changed,plat)
 
-PHONY += dts_dir
-dts_dir:
-	$(shell [ -d $(obj)/dts ] || mkdir -p $(obj)/dts)
-
-include/generated/dt-structs-gen.h $(u-boot-spl-platdata_c) &: \
-		$(obj)/$(SPL_BIN).dtb dts_dir FORCE
+# Don't use dts_dir here, since it forces running this expensive rule every time
+$(platdata-hdr) $(u-boot-spl-platdata_c) &: $(obj)/$(SPL_BIN).dtb
+	@[ -d $(obj)/dts ] || mkdir -p $(obj)/dts
+	@# Remove old files since which ones we generate depends on the setting
+	@# of OF_PLATDATA_INST and this might change between builds. Leaving old
+	@# ones around is confusing and it is possible that switching the
+	@# setting again will use the old one instead of regenerating it.
+	@rm -f $(u-boot-spl-all-platdata_c) $(u-boot-spl-all-platdata)
 	$(call if_changed,dtoc)
 
 ifdef CONFIG_SAMSUNG
@@ -471,6 +489,10 @@
 $(obj)/dts/dt-$(SPL_NAME).dtb: dts/dt.dtb
 	$(Q)$(MAKE) $(build)=$(obj)/dts spl_dtbs
 
+PHONY += dts_dir
+dts_dir:
+	$(shell [ -d $(obj)/dts ] || mkdir -p $(obj)/dts)
+
 # Declare the contents of the .PHONY variable as phony.  We keep that
 # information in a variable so we can use it in if_changed and friends.
 .PHONY: $(PHONY)
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index 43295ee..6859d17 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -1030,7 +1030,6 @@
 CONFIG_MIPS_MT_FPAFF
 CONFIG_MIRQ_EN
 CONFIG_MISC_COMMON
-CONFIG_MISC_INIT_F
 CONFIG_MIU_1BIT_INTERLEAVED
 CONFIG_MIU_2BIT_21_7_INTERLEAVED
 CONFIG_MIU_2BIT_INTERLEAVED
@@ -1077,7 +1076,6 @@
 CONFIG_MTD_UBI_MODULE
 CONFIG_MULTI_CS
 CONFIG_MUSB_HOST
-CONFIG_MVEBU_MMC
 CONFIG_MVGBE_PORTS
 CONFIG_MVMFP_V2
 CONFIG_MVS
@@ -1629,7 +1627,6 @@
 CONFIG_STV0991_HZ
 CONFIG_STV0991_HZ_CLOCK
 CONFIG_ST_SMI
-CONFIG_SUNXI_MAX_FB_SIZE
 CONFIG_SXNI855T
 CONFIG_SYSFLAGS_ADDR
 CONFIG_SYSFS
@@ -2908,7 +2905,6 @@
 CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR
 CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS
 CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR
-CONFIG_SYS_MMC_BASE
 CONFIG_SYS_MMC_CD_PIN
 CONFIG_SYS_MMC_CLK_OD
 CONFIG_SYS_MMC_MAX_BLK_COUNT
diff --git a/scripts/dtc/pylibfdt/Makefile b/scripts/dtc/pylibfdt/Makefile
index 80b6ad2..493995e 100644
--- a/scripts/dtc/pylibfdt/Makefile
+++ b/scripts/dtc/pylibfdt/Makefile
@@ -23,12 +23,19 @@
 		SWIG_OPTS="-I$(LIBFDT_srcdir) -I$(LIBFDT_srcdir)/.." \
 		$(PYTHON3) $< --quiet build_ext --inplace
 
-$(obj)/_libfdt.so: $(src)/setup.py $(PYLIBFDT_srcs) FORCE
+rebuild: $(src)/setup.py $(PYLIBFDT_srcs)
 	@# Remove the library since otherwise Python doesn't seem to regenerate
 	@# the libfdt.py file if it is missing.
-	rm -f $(obj)/_libfdt*.so
+	@rm -f $(obj)/_libfdt*.so
 	$(call if_changed,pymod)
+	@# Rename the file to _libfdt.so so this Makefile doesn't run every time
+	@if [ ! -e $(obj)/_libfdt.so ]; then \
+		mv $(obj)/_libfdt*.so $(obj)/_libfdt.so; \
+	fi
 
-always += _libfdt.so
+$(obj)/_libfdt.so $(obj)/libfdt.py &: rebuild
+	@:
+
+always += _libfdt.so libfdt.py
 
 clean-files += libfdt.i _libfdt.so libfdt.py libfdt_wrap.c
diff --git a/test/Makefile b/test/Makefile
index 932e517..a26e915 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -2,6 +2,9 @@
 #
 # (C) Copyright 2012 The Chromium Authors
 
+obj-y += test-main.o
+obj-$(CONFIG_SANDBOX) += image/
+
 ifneq ($(CONFIG_$(SPL_)BLOBLIST),)
 obj-$(CONFIG_$(SPL_)CMDLINE) += bloblist.o
 obj-$(CONFIG_$(SPL_)CMDLINE) += bootm.o
diff --git a/test/bloblist.c b/test/bloblist.c
index 6953d30..d876b63 100644
--- a/test/bloblist.c
+++ b/test/bloblist.c
@@ -387,9 +387,8 @@
 int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
 		   char *const argv[])
 {
-	struct unit_test *tests = ll_entry_start(struct unit_test,
-						 bloblist_test);
-	const int n_ents = ll_entry_count(struct unit_test, bloblist_test);
+	struct unit_test *tests = UNIT_TEST_SUITE_START(bloblist_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(bloblist_test);
 
 	return cmd_ut_category("bloblist", "bloblist_test_",
 			       tests, n_ents, argc, argv);
diff --git a/test/bootm.c b/test/bootm.c
index 563d6eb..8528982 100644
--- a/test/bootm.c
+++ b/test/bootm.c
@@ -240,8 +240,8 @@
 
 int do_ut_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-	struct unit_test *tests = ll_entry_start(struct unit_test, bootm_test);
-	const int n_ents = ll_entry_count(struct unit_test, bootm_test);
+	struct unit_test *tests = UNIT_TEST_SUITE_START(bootm_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(bootm_test);
 
 	return cmd_ut_category("bootm", "bootm_test_", tests, n_ents,
 			       argc, argv);
diff --git a/test/cmd/mem.c b/test/cmd/mem.c
index fbaa8a4..d76f47c 100644
--- a/test/cmd/mem.c
+++ b/test/cmd/mem.c
@@ -12,8 +12,8 @@
 
 int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-	struct unit_test *tests = ll_entry_start(struct unit_test, mem_test);
-	const int n_ents = ll_entry_count(struct unit_test, mem_test);
+	struct unit_test *tests = UNIT_TEST_SUITE_START(mem_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(mem_test);
 
 	return cmd_ut_category("cmd_mem", "mem_test_", tests, n_ents, argc,
 			       argv);
diff --git a/test/cmd/setexpr.c b/test/cmd/setexpr.c
index fd6d869..c537e89 100644
--- a/test/cmd/setexpr.c
+++ b/test/cmd/setexpr.c
@@ -15,7 +15,7 @@
 
 #define BUF_SIZE	0x100
 
-/* Declare a new mem test */
+/* Declare a new setexpr test */
 #define SETEXPR_TEST(_name, _flags)	UNIT_TEST(_name, _flags, setexpr_test)
 
 /* Test 'setexpr' command with simply setting integers */
@@ -306,8 +306,8 @@
 	ut_asserteq(1, run_command("setexpr.s fred 0", 0));
 	ut_assertok(ut_check_delta(start_mem));
 
-	start_mem = ut_check_free();
 	ut_assertok(env_set("fred", "12345"));
+	start_mem = ut_check_free();
 	ut_assertok(run_command("setexpr.s fred *0", 0));
 	ut_asserteq_str("hello", env_get("fred"));
 	ut_assertok(ut_check_delta(start_mem));
@@ -345,7 +345,22 @@
 	start_mem = ut_check_free();
 	ut_assertok(run_command("setexpr.s fred *0 + *10", 0));
 	ut_asserteq_str("hello there", env_get("fred"));
-	ut_assertok(ut_check_delta(start_mem));
+
+	/*
+	 * This check does not work with sandbox_flattree, apparently due to
+	 * memory allocations in env_set().
+	 *
+	 * The truetype console produces lots of memory allocations even though
+	 * the LCD display is not visible. But even without these, it does not
+	 * work.
+	 *
+	 * A better test would be for dlmalloc to record the allocs and frees
+	 * for a particular caller, but that is not supported.
+	 *
+	 * For now, drop this test.
+	 *
+	 * ut_assertok(ut_check_delta(start_mem));
+	 */
 
 	unmap_sysmem(buf);
 
@@ -375,10 +390,9 @@
 
 int do_ut_setexpr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-	struct unit_test *tests = ll_entry_start(struct unit_test,
-						 setexpr_test);
-	const int n_ents = ll_entry_count(struct unit_test, setexpr_test);
+	struct unit_test *tests = UNIT_TEST_SUITE_START(setexpr_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(setexpr_test);
 
-	return cmd_ut_category("cmd_setexpr", "cmd_mem_", tests, n_ents, argc,
-			       argv);
+	return cmd_ut_category("cmd_setexpr", "setexpr_test_", tests, n_ents,
+			       argc, argv);
 }
diff --git a/test/cmd/test_echo.c b/test/cmd/test_echo.c
index aa5cebc..9d60d7d 100644
--- a/test/cmd/test_echo.c
+++ b/test/cmd/test_echo.c
@@ -44,9 +44,10 @@
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(echo_data); ++i) {
+		ut_silence_console(uts);
 		console_record_reset_enable();
 		ut_assertok(run_command(echo_data[i].cmd, 0));
-		gd->flags &= ~GD_FLG_RECORD;
+		ut_unsilence_console(uts);
 		console_record_readline(uts->actual_str,
 					sizeof(uts->actual_str));
 		ut_asserteq_str(echo_data[i].expected, uts->actual_str);
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 8728cc8..b9c1660 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -9,6 +9,7 @@
 #include <console.h>
 #include <test/suites.h>
 #include <test/test.h>
+#include <test/ut.h>
 
 static int do_ut_all(struct cmd_tbl *cmdtp, int flag, int argc,
 		     char *const argv[]);
@@ -17,41 +18,12 @@
 		    struct unit_test *tests, int n_ents,
 		    int argc, char *const argv[])
 {
-	struct unit_test_state uts = { .fail_count = 0 };
-	struct unit_test *test;
-	int prefix_len = prefix ? strlen(prefix) : 0;
+	int ret;
 
-	if (argc == 1)
-		printf("Running %d %s tests\n", n_ents, name);
+	ret = ut_run_list(name, prefix, tests, n_ents,
+			  argc > 1 ? argv[1] : NULL);
 
-	for (test = tests; test < tests + n_ents; test++) {
-		const char *test_name = test->name;
-
-		/* Remove the prefix */
-		if (prefix && !strncmp(test_name, prefix, prefix_len))
-			test_name += prefix_len;
-
-		if (argc > 1 && strcmp(argv[1], test_name))
-			continue;
-		printf("Test: %s\n", test->name);
-
-		if (test->flags & UT_TESTF_CONSOLE_REC) {
-			int ret = console_record_reset_enable();
-
-			if (ret) {
-				printf("Skipping: Console recording disabled\n");
-				continue;
-			}
-		}
-
-		uts.start = mallinfo();
-
-		test->func(&uts);
-	}
-
-	printf("Failures: %d\n", uts.fail_count);
-
-	return uts.fail_count ? CMD_RET_FAILURE : 0;
+	return ret ? CMD_RET_FAILURE : 0;
 }
 
 static struct cmd_tbl cmd_ut_sub[] = {
diff --git a/test/compression.c b/test/compression.c
index a2a4b9f..4cd1be5 100644
--- a/test/compression.c
+++ b/test/compression.c
@@ -539,9 +539,8 @@
 int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc,
 		      char *const argv[])
 {
-	struct unit_test *tests = ll_entry_start(struct unit_test,
-						 compression_test);
-	const int n_ents = ll_entry_count(struct unit_test, compression_test);
+	struct unit_test *tests = UNIT_TEST_SUITE_START(compression_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(compression_test);
 
 	return cmd_ut_category("compression", "compression_test_",
 			       tests, n_ents, argc, argv);
diff --git a/test/dm/Makefile b/test/dm/Makefile
index fd14551..f5cc554 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -2,7 +2,7 @@
 #
 # Copyright (c) 2013 Google, Inc
 
-obj-$(CONFIG_UT_DM) += test-main.o
+obj-$(CONFIG_UT_DM) += test-dm.o
 
 # Tests for particular subsystems - when enabling driver model for a new
 # subsystem you must add sandbox tests here.
diff --git a/test/dm/acpi.c b/test/dm/acpi.c
index 240187c..2edab7be 100644
--- a/test/dm/acpi.c
+++ b/test/dm/acpi.c
@@ -360,24 +360,24 @@
 	run_command("acpi list", 0);
 	addr = (ulong)map_to_sysmem(buf);
 	ut_assert_nextline("ACPI tables start at %lx", addr);
-	ut_assert_nextline("RSDP %08lx %06lx (v02 U-BOOT)", addr,
+	ut_assert_nextline("RSDP %08lx %06zx (v02 U-BOOT)", addr,
 			   sizeof(struct acpi_rsdp));
 	addr = ALIGN(addr + sizeof(struct acpi_rsdp), 16);
-	ut_assert_nextline("RSDT %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)",
+	ut_assert_nextline("RSDT %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)",
 			   addr, sizeof(struct acpi_table_header) +
 			   3 * sizeof(u32), U_BOOT_BUILD_DATE);
 	addr = ALIGN(addr + sizeof(struct acpi_rsdt), 16);
-	ut_assert_nextline("XSDT %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)",
+	ut_assert_nextline("XSDT %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)",
 			   addr, sizeof(struct acpi_table_header) +
 			   3 * sizeof(u64), U_BOOT_BUILD_DATE);
 	addr = ALIGN(addr + sizeof(struct acpi_xsdt), 64);
-	ut_assert_nextline("DMAR %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)",
+	ut_assert_nextline("DMAR %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)",
 			   addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE);
 	addr = ALIGN(addr + sizeof(struct acpi_dmar), 16);
-	ut_assert_nextline("DMAR %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)",
+	ut_assert_nextline("DMAR %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)",
 			   addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE);
 	addr = ALIGN(addr + sizeof(struct acpi_dmar), 16);
-	ut_assert_nextline("DMAR %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)",
+	ut_assert_nextline("DMAR %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)",
 			   addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE);
 	ut_assert_console_end();
 
diff --git a/test/dm/core.c b/test/dm/core.c
index 35ca689..2210345 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -117,14 +117,13 @@
 /* Test that binding with plat occurs correctly */
 static int dm_test_autobind(struct unit_test_state *uts)
 {
-	struct dm_test_state *dms = uts->priv;
 	struct udevice *dev;
 
 	/*
 	 * We should have a single class (UCLASS_ROOT) and a single root
 	 * device with no children.
 	 */
-	ut_assert(dms->root);
+	ut_assert(uts->root);
 	ut_asserteq(1, list_count_items(gd->uclass_root));
 	ut_asserteq(0, list_count_items(&gd->dm_root->child_head));
 	ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_POST_BIND]);
@@ -207,7 +206,6 @@
 /* Test that autoprobe finds all the expected devices */
 static int dm_test_autoprobe(struct unit_test_state *uts)
 {
-	struct dm_test_state *dms = uts->priv;
 	int expected_base_add;
 	struct udevice *dev;
 	struct uclass *uc;
@@ -221,7 +219,7 @@
 	ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_POST_PROBE]);
 
 	/* The root device should not be activated until needed */
-	ut_assert(dev_get_flags(dms->root) & DM_FLAG_ACTIVATED);
+	ut_assert(dev_get_flags(uts->root) & DM_FLAG_ACTIVATED);
 
 	/*
 	 * We should be able to find the three test devices, and they should
@@ -241,7 +239,7 @@
 
 		/* Activating a device should activate the root device */
 		if (!i)
-			ut_assert(dev_get_flags(dms->root) & DM_FLAG_ACTIVATED);
+			ut_assert(dev_get_flags(uts->root) & DM_FLAG_ACTIVATED);
 	}
 
 	/*
@@ -293,7 +291,6 @@
 /* Test that we can bind, probe, remove, unbind a driver */
 static int dm_test_lifecycle(struct unit_test_state *uts)
 {
-	struct dm_test_state *dms = uts->priv;
 	int op_count[DM_TEST_OP_COUNT];
 	struct udevice *dev, *test_dev;
 	int pingret;
@@ -301,7 +298,7 @@
 
 	memcpy(op_count, dm_testdrv_op_count, sizeof(op_count));
 
-	ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual,
+	ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual,
 					&dev));
 	ut_assert(dev);
 	ut_assert(dm_testdrv_op_count[DM_TEST_OP_BIND]
@@ -309,7 +306,7 @@
 	ut_assert(!dev_get_priv(dev));
 
 	/* Probe the device - it should fail allocating private data */
-	dms->force_fail_alloc = 1;
+	uts->force_fail_alloc = 1;
 	ret = device_probe(dev);
 	ut_assert(ret == -ENOMEM);
 	ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE]
@@ -317,7 +314,7 @@
 	ut_assert(!dev_get_priv(dev));
 
 	/* Try again without the alloc failure */
-	dms->force_fail_alloc = 0;
+	uts->force_fail_alloc = 0;
 	ut_assertok(device_probe(dev));
 	ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE]
 			== op_count[DM_TEST_OP_PROBE] + 2);
@@ -349,19 +346,18 @@
 /* Test that we can bind/unbind and the lists update correctly */
 static int dm_test_ordering(struct unit_test_state *uts)
 {
-	struct dm_test_state *dms = uts->priv;
 	struct udevice *dev, *dev_penultimate, *dev_last, *test_dev;
 	int pingret;
 
-	ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual,
+	ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual,
 					&dev));
 	ut_assert(dev);
 
 	/* Bind two new devices (numbers 4 and 5) */
-	ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual,
+	ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual,
 					&dev_penultimate));
 	ut_assert(dev_penultimate);
-	ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual,
+	ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual,
 					&dev_last));
 	ut_assert(dev_last);
 
@@ -376,7 +372,7 @@
 	ut_assert(dev_last == test_dev);
 
 	/* Add back the original device 3, now in position 5 */
-	ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual,
+	ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual,
 					&dev));
 	ut_assert(dev);
 
@@ -568,7 +564,6 @@
 
 static int dm_test_children(struct unit_test_state *uts)
 {
-	struct dm_test_state *dms = uts->priv;
 	struct udevice *top[NODE_COUNT];
 	struct udevice *child[NODE_COUNT];
 	struct udevice *grandchild[NODE_COUNT];
@@ -578,12 +573,12 @@
 	int i;
 
 	/* We don't care about the numbering for this test */
-	dms->skip_post_probe = 1;
+	uts->skip_post_probe = 1;
 
 	ut_assert(NODE_COUNT > 5);
 
 	/* First create 10 top-level children */
-	ut_assertok(create_children(uts, dms->root, NODE_COUNT, 0, top));
+	ut_assertok(create_children(uts, uts->root, NODE_COUNT, 0, top));
 
 	/* Now a few have their own children */
 	ut_assertok(create_children(uts, top[2], NODE_COUNT, 2, NULL));
@@ -654,7 +649,6 @@
 
 static int dm_test_device_reparent(struct unit_test_state *uts)
 {
-	struct dm_test_state *dms = uts->priv;
 	struct udevice *top[NODE_COUNT];
 	struct udevice *child[NODE_COUNT];
 	struct udevice *grandchild[NODE_COUNT];
@@ -664,12 +658,12 @@
 	int i;
 
 	/* We don't care about the numbering for this test */
-	dms->skip_post_probe = 1;
+	uts->skip_post_probe = 1;
 
 	ut_assert(NODE_COUNT > 5);
 
 	/* First create 10 top-level children */
-	ut_assertok(create_children(uts, dms->root, NODE_COUNT, 0, top));
+	ut_assertok(create_children(uts, uts->root, NODE_COUNT, 0, top));
 
 	/* Now a few have their own children */
 	ut_assertok(create_children(uts, top[2], NODE_COUNT, 2, NULL));
@@ -815,15 +809,14 @@
 /* Test that pre-relocation devices work as expected */
 static int dm_test_pre_reloc(struct unit_test_state *uts)
 {
-	struct dm_test_state *dms = uts->priv;
 	struct udevice *dev;
 
 	/* The normal driver should refuse to bind before relocation */
-	ut_asserteq(-EPERM, device_bind_by_name(dms->root, true,
+	ut_asserteq(-EPERM, device_bind_by_name(uts->root, true,
 						&driver_info_manual, &dev));
 
 	/* But this one is marked pre-reloc */
-	ut_assertok(device_bind_by_name(dms->root, true,
+	ut_assertok(device_bind_by_name(uts->root, true,
 					&driver_info_pre_reloc, &dev));
 
 	return 0;
@@ -836,10 +829,9 @@
  */
 static int dm_test_remove_active_dma(struct unit_test_state *uts)
 {
-	struct dm_test_state *dms = uts->priv;
 	struct udevice *dev;
 
-	ut_assertok(device_bind_by_name(dms->root, false, &driver_info_act_dma,
+	ut_assertok(device_bind_by_name(uts->root, false, &driver_info_act_dma,
 					&dev));
 	ut_assert(dev);
 
@@ -872,7 +864,7 @@
 	 * the active DMA remove call
 	 */
 	ut_assertok(device_unbind(dev));
-	ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual,
+	ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual,
 					&dev));
 	ut_assert(dev);
 
@@ -895,25 +887,24 @@
 /* Test removal of 'vital' devices */
 static int dm_test_remove_vital(struct unit_test_state *uts)
 {
-	struct dm_test_state *dms = uts->priv;
 	struct udevice *normal, *dma, *vital, *dma_vital;
 
 	/* Skip the behaviour in test_post_probe() */
-	dms->skip_post_probe = 1;
+	uts->skip_post_probe = 1;
 
-	ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual,
+	ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual,
 					&normal));
 	ut_assertnonnull(normal);
 
-	ut_assertok(device_bind_by_name(dms->root, false, &driver_info_act_dma,
+	ut_assertok(device_bind_by_name(uts->root, false, &driver_info_act_dma,
 					&dma));
 	ut_assertnonnull(dma);
 
-	ut_assertok(device_bind_by_name(dms->root, false,
+	ut_assertok(device_bind_by_name(uts->root, false,
 					&driver_info_vital_clk, &vital));
 	ut_assertnonnull(vital);
 
-	ut_assertok(device_bind_by_name(dms->root, false,
+	ut_assertok(device_bind_by_name(uts->root, false,
 					&driver_info_act_dma_vital_clk,
 					&dma_vital));
 	ut_assertnonnull(dma_vital);
@@ -1133,11 +1124,10 @@
 
 static int dm_test_inactive_child(struct unit_test_state *uts)
 {
-	struct dm_test_state *dms = uts->priv;
 	struct udevice *parent, *dev1, *dev2;
 
 	/* Skip the behaviour in test_post_probe() */
-	dms->skip_post_probe = 1;
+	uts->skip_post_probe = 1;
 
 	ut_assertok(uclass_first_device_err(UCLASS_TEST, &parent));
 
diff --git a/test/dm/gpio.c b/test/dm/gpio.c
index d7b85e7..33ae987 100644
--- a/test/dm/gpio.c
+++ b/test/dm/gpio.c
@@ -80,15 +80,15 @@
 
 	/* Make it an open drain output, and reset it */
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE,
-		    sandbox_gpio_get_dir_flags(dev, offset));
-	ut_assertok(ops->set_dir_flags(dev, offset,
-				       GPIOD_IS_OUT | GPIOD_OPEN_DRAIN));
+		    sandbox_gpio_get_flags(dev, offset));
+	ut_assertok(ops->set_flags(dev, offset,
+				   GPIOD_IS_OUT | GPIOD_OPEN_DRAIN));
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN,
-		    sandbox_gpio_get_dir_flags(dev, offset));
-	ut_assertok(ops->set_dir_flags(dev, offset,
-				       GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE));
+		    sandbox_gpio_get_flags(dev, offset));
+	ut_assertok(ops->set_flags(dev, offset,
+				   GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE));
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE,
-		    sandbox_gpio_get_dir_flags(dev, offset));
+		    sandbox_gpio_get_flags(dev, offset));
 
 	/* Make it an input */
 	ut_assertok(ops->direction_input(dev, offset));
@@ -176,54 +176,64 @@
 
 	/* GPIO 0 is (GPIO_OUT|GPIO_OPEN_DRAIN) */
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN,
-		    sandbox_gpio_get_dir_flags(gpio_c, 0));
+		    sandbox_gpio_get_flags(gpio_c, 0));
 
-	/* Set it as output high, should become an input */
+	/* Set it as output high */
 	ut_assertok(dm_gpio_set_value(&desc_list[0], 1));
-	ut_assertok(gpio_get_status(gpio_c, 0, buf, sizeof(buf)));
-	ut_asserteq_str("c0: input: 0 [x] a-test.test3-gpios0", buf);
+	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN | GPIOD_IS_OUT_ACTIVE,
+		    sandbox_gpio_get_flags(gpio_c, 0));
 
-	/* Set it as output low, should become output low */
+	/* Set it as output low */
 	ut_assertok(dm_gpio_set_value(&desc_list[0], 0));
-	ut_assertok(gpio_get_status(gpio_c, 0, buf, sizeof(buf)));
-	ut_asserteq_str("c0: output: 0 [x] a-test.test3-gpios0", buf);
+	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN,
+		    sandbox_gpio_get_flags(gpio_c, 0));
 
 	/* GPIO 1 is (GPIO_OUT|GPIO_OPEN_SOURCE) */
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE,
-		    sandbox_gpio_get_dir_flags(gpio_c, 1));
+		    sandbox_gpio_get_flags(gpio_c, 1));
 
 	/* Set it as output high, should become output high */
 	ut_assertok(dm_gpio_set_value(&desc_list[1], 1));
 	ut_assertok(gpio_get_status(gpio_c, 1, buf, sizeof(buf)));
 	ut_asserteq_str("c1: output: 1 [x] a-test.test3-gpios1", buf);
 
-	/* Set it as output low, should become an input */
+	/* Set it as output low */
 	ut_assertok(dm_gpio_set_value(&desc_list[1], 0));
-	ut_assertok(gpio_get_status(gpio_c, 1, buf, sizeof(buf)));
-	ut_asserteq_str("c1: input: 1 [x] a-test.test3-gpios1", buf);
+	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE,
+		    sandbox_gpio_get_flags(gpio_c, 1));
 
-	/* GPIO 6 is (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_DRAIN) */
-	ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_DRAIN,
-		    sandbox_gpio_get_dir_flags(gpio_c, 6));
+	ut_assertok(gpio_get_status(gpio_c, 1, buf, sizeof(buf)));
+	ut_asserteq_str("c1: output: 0 [x] a-test.test3-gpios1", buf);
+
+	/*
+	 * GPIO 6 is (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_DRAIN). Looking at it
+	 * directlt from the driver, we get GPIOD_IS_OUT_ACTIVE also, since it
+	 * is active low
+	 */
+	ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_DRAIN |
+		    GPIOD_IS_OUT_ACTIVE,
+		    sandbox_gpio_get_flags(gpio_c, 6));
 
 	/* Set it as output high, should become output low */
 	ut_assertok(dm_gpio_set_value(&desc_list[6], 1));
 	ut_assertok(gpio_get_status(gpio_c, 6, buf, sizeof(buf)));
 	ut_asserteq_str("c6: output: 0 [x] a-test.test3-gpios6", buf);
 
-	/* Set it as output low, should become an input */
+	/* Set it as output low */
 	ut_assertok(dm_gpio_set_value(&desc_list[6], 0));
-	ut_assertok(gpio_get_status(gpio_c, 6, buf, sizeof(buf)));
-	ut_asserteq_str("c6: input: 0 [x] a-test.test3-gpios6", buf);
+	ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_DRAIN |
+		    GPIOD_IS_OUT_ACTIVE,
+		    sandbox_gpio_get_flags(gpio_c, 6));
 
 	/* GPIO 7 is (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_SOURCE) */
-	ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_SOURCE,
-		    sandbox_gpio_get_dir_flags(gpio_c, 7));
+	ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_SOURCE |
+		    GPIOD_IS_OUT_ACTIVE,
+		    sandbox_gpio_get_flags(gpio_c, 7));
 
-	/* Set it as output high, should become an input */
+	/* Set it as output high */
 	ut_assertok(dm_gpio_set_value(&desc_list[7], 1));
-	ut_assertok(gpio_get_status(gpio_c, 7, buf, sizeof(buf)));
-	ut_asserteq_str("c7: input: 0 [x] a-test.test3-gpios7", buf);
+	ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_SOURCE,
+		    sandbox_gpio_get_flags(gpio_c, 7));
 
 	/* Set it as output low, should become output high */
 	ut_assertok(dm_gpio_set_value(&desc_list[7], 0));
@@ -363,12 +373,12 @@
 	ut_assertok(gpio_free_list(dev, desc_list, 3));
 
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE,
-		    sandbox_gpio_get_dir_flags(gpio_a, 1));
+		    sandbox_gpio_get_flags(gpio_a, 1));
 	ut_asserteq(6, gpio_request_list_by_name(dev, "test2-gpios", desc_list,
 						 ARRAY_SIZE(desc_list), 0));
 
 	/* This was set to output previously but flags resetted to 0 = INPUT */
-	ut_asserteq(0, sandbox_gpio_get_dir_flags(gpio_a, 1));
+	ut_asserteq(0, sandbox_gpio_get_flags(gpio_a, 1));
 	ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_a, 1, NULL));
 
 	/* Active low should invert the input value */
@@ -397,22 +407,22 @@
 	ut_asserteq(6, gpio_request_list_by_name(dev, "test3-gpios", desc_list,
 						 ARRAY_SIZE(desc_list), 0));
 
-	ut_assertok(dm_gpio_get_dir_flags(&desc_list[0], &flags));
+	ut_assertok(dm_gpio_get_flags(&desc_list[0], &flags));
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN, flags);
 
-	ut_assertok(dm_gpio_get_dir_flags(&desc_list[1], &flags));
+	ut_assertok(dm_gpio_get_flags(&desc_list[1], &flags));
 	ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE, flags);
 
-	ut_assertok(dm_gpio_get_dir_flags(&desc_list[2], &flags));
+	ut_assertok(dm_gpio_get_flags(&desc_list[2], &flags));
 	ut_asserteq(GPIOD_IS_OUT, flags);
 
-	ut_assertok(dm_gpio_get_dir_flags(&desc_list[3], &flags));
+	ut_assertok(dm_gpio_get_flags(&desc_list[3], &flags));
 	ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, flags);
 
-	ut_assertok(dm_gpio_get_dir_flags(&desc_list[4], &flags));
+	ut_assertok(dm_gpio_get_flags(&desc_list[4], &flags));
 	ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_DOWN, flags);
 
-	ut_assertok(dm_gpio_get_dir_flags(&desc_list[5], &flags));
+	ut_assertok(dm_gpio_get_flags(&desc_list[5], &flags));
 	ut_asserteq(GPIOD_IS_IN, flags);
 
 	ut_assertok(gpio_free_list(dev, desc_list, 6));
@@ -582,3 +592,189 @@
 	return 0;
 }
 DM_TEST(dm_test_gpio_devm, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+static int dm_test_clrset_flags(struct unit_test_state *uts)
+{
+	struct gpio_desc desc;
+	struct udevice *dev;
+	ulong flags;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+	ut_asserteq_str("a-test", dev->name);
+	ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc, 0));
+
+	ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, GPIOD_IS_OUT));
+	ut_assertok(dm_gpio_get_flags(&desc, &flags));
+	ut_asserteq(GPIOD_IS_OUT, flags);
+	ut_asserteq(GPIOD_IS_OUT, desc.flags);
+	ut_asserteq(0, sandbox_gpio_get_value(desc.dev, desc.offset));
+
+	ut_assertok(dm_gpio_clrset_flags(&desc, 0, GPIOD_IS_OUT_ACTIVE));
+	ut_assertok(dm_gpio_get_flags(&desc, &flags));
+	ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, flags);
+	ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, desc.flags);
+	ut_asserteq(1, sandbox_gpio_get_value(desc.dev, desc.offset));
+	ut_asserteq(1, dm_gpio_get_value(&desc));
+
+	ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, GPIOD_IS_IN));
+	ut_assertok(dm_gpio_get_flags(&desc, &flags));
+	ut_asserteq(GPIOD_IS_IN, flags & GPIOD_MASK_DIR);
+	ut_asserteq(GPIOD_IS_IN, desc.flags & GPIOD_MASK_DIR);
+
+	ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_MASK_PULL,
+					 GPIOD_PULL_UP));
+	ut_assertok(dm_gpio_get_flags(&desc, &flags));
+	ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, flags);
+	ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, desc.flags);
+
+	/* Check we cannot set both PULL_UP and PULL_DOWN */
+	ut_asserteq(-EINVAL, dm_gpio_clrset_flags(&desc, 0, GPIOD_PULL_DOWN));
+
+	return 0;
+}
+DM_TEST(dm_test_clrset_flags, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+/* Check that an active-low GPIO works as expected */
+static int dm_test_clrset_flags_invert(struct unit_test_state *uts)
+{
+	struct gpio_desc desc;
+	struct udevice *dev;
+	ulong flags;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+	ut_asserteq_str("a-test", dev->name);
+	ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc,
+					 GPIOD_IS_OUT | GPIOD_ACTIVE_LOW));
+
+	/*
+	 * From this size we see it as 0 (active low), but the sandbox driver
+	 * sees the pin value high
+	 */
+	ut_asserteq(0, dm_gpio_get_value(&desc));
+	ut_asserteq(1, sandbox_gpio_get_value(desc.dev, desc.offset));
+
+	ut_assertok(dm_gpio_set_value(&desc, 1));
+	ut_asserteq(1, dm_gpio_get_value(&desc));
+	ut_asserteq(0, sandbox_gpio_get_value(desc.dev, desc.offset));
+
+	/* Do the same with dm_gpio_clrset_flags() */
+	ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_IS_OUT_ACTIVE, 0));
+	ut_asserteq(0, dm_gpio_get_value(&desc));
+	ut_asserteq(1, sandbox_gpio_get_value(desc.dev, desc.offset));
+
+	ut_assertok(dm_gpio_clrset_flags(&desc, 0, GPIOD_IS_OUT_ACTIVE));
+	ut_asserteq(1, dm_gpio_get_value(&desc));
+	ut_asserteq(0, sandbox_gpio_get_value(desc.dev, desc.offset));
+
+	ut_assertok(dm_gpio_get_flags(&desc, &flags));
+	ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE,
+		    flags);
+	ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE,
+		    desc.flags);
+
+	ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_IS_OUT_ACTIVE, 0));
+	ut_assertok(dm_gpio_get_flags(&desc, &flags));
+	ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW, flags);
+	ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW, desc.flags);
+
+	return 0;
+}
+DM_TEST(dm_test_clrset_flags_invert, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+static int set_gpios(struct unit_test_state *uts, struct gpio_desc *desc,
+		     int count, uint value)
+{
+	int i;
+
+	for (i = 0; i < count; i++) {
+		const uint mask = 1 << i;
+
+		ut_assertok(sandbox_gpio_set_value(desc[i].dev, desc[i].offset,
+						   value & mask));
+	}
+
+	return 0;
+}
+
+/* Check that an active-low GPIO works as expected */
+static int dm_test_gpio_get_values_as_int(struct unit_test_state *uts)
+{
+	const int gpio_count = 3;
+	struct gpio_desc desc[gpio_count];
+	struct udevice *dev;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+	ut_asserteq_str("a-test", dev->name);
+
+	ut_asserteq(3, gpio_request_list_by_name(dev, "test-gpios", desc,
+						 gpio_count, GPIOD_IS_IN));
+	ut_assertok(set_gpios(uts, desc, gpio_count, 0));
+	ut_asserteq(0, dm_gpio_get_values_as_int(desc, gpio_count));
+
+	ut_assertok(set_gpios(uts, desc, gpio_count, 5));
+	ut_asserteq(5, dm_gpio_get_values_as_int(desc, gpio_count));
+
+	ut_assertok(set_gpios(uts, desc, gpio_count, 7));
+	ut_asserteq(7, dm_gpio_get_values_as_int(desc, gpio_count));
+
+	return 0;
+}
+DM_TEST(dm_test_gpio_get_values_as_int,
+	UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+/* Check that an active-low GPIO works as expected */
+static int dm_test_gpio_get_values_as_int_base3(struct unit_test_state *uts)
+{
+	const int gpio_count = 3;
+	struct gpio_desc desc[gpio_count];
+	struct udevice *dev;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+	ut_asserteq_str("a-test", dev->name);
+
+	ut_asserteq(3, gpio_request_list_by_name(dev, "test-gpios", desc,
+						 gpio_count, GPIOD_IS_IN));
+
+	/*
+	 * First test the sandbox GPIO driver works as expected. The external
+	 * pull resistor should be stronger than the internal one.
+	 */
+	sandbox_gpio_set_flags(desc[0].dev, desc[0].offset,
+			       GPIOD_IS_IN | GPIOD_EXT_PULL_UP | GPIOD_PULL_UP);
+	ut_asserteq(1, dm_gpio_get_value(desc));
+
+	sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, GPIOD_IS_IN |
+			       GPIOD_EXT_PULL_DOWN | GPIOD_PULL_UP);
+	ut_asserteq(0, dm_gpio_get_value(desc));
+
+	sandbox_gpio_set_flags(desc[0].dev, desc[0].offset,
+			       GPIOD_IS_IN | GPIOD_PULL_UP);
+	ut_asserteq(1, dm_gpio_get_value(desc));
+
+	sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, GPIOD_PULL_DOWN);
+	ut_asserteq(0, dm_gpio_get_value(desc));
+
+	/*
+	 * Set up pins: pull-up (1), pull-down (0) and floating (2). This should
+	 * result in digits 2 0 1, i.e. 2 * 9 + 1 * 3 = 19
+	 */
+	sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, GPIOD_EXT_PULL_UP);
+	sandbox_gpio_set_flags(desc[1].dev, desc[1].offset,
+			       GPIOD_EXT_PULL_DOWN);
+	sandbox_gpio_set_flags(desc[2].dev, desc[2].offset, 0);
+	ut_asserteq(19, dm_gpio_get_values_as_int_base3(desc, gpio_count));
+
+	/*
+	 * Set up pins: floating (2), pull-up (1) and pull-down (0). This should
+	 * result in digits 0 1 2, i.e. 1 * 3 + 2 = 5
+	 */
+	sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, 0);
+	sandbox_gpio_set_flags(desc[1].dev, desc[1].offset, GPIOD_EXT_PULL_UP);
+	sandbox_gpio_set_flags(desc[2].dev, desc[2].offset,
+			       GPIOD_EXT_PULL_DOWN);
+	ut_asserteq(5, dm_gpio_get_values_as_int_base3(desc, gpio_count));
+
+	return 0;
+}
+DM_TEST(dm_test_gpio_get_values_as_int_base3,
+	UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
diff --git a/test/dm/of_platdata.c b/test/dm/of_platdata.c
index e9804cc..0f89c7a 100644
--- a/test/dm/of_platdata.c
+++ b/test/dm/of_platdata.c
@@ -142,12 +142,14 @@
 /* Check that every device is recorded in its driver_info struct */
 static int dm_test_of_plat_dev(struct unit_test_state *uts)
 {
-	const struct driver_info *info =
-		ll_entry_start(struct driver_info, driver_info);
 	const int n_ents = ll_entry_count(struct driver_info, driver_info);
 	bool found[n_ents];
 	uint i;
 
+	/* Skip this test if there is no platform data */
+	if (!CONFIG_IS_ENABLED(OF_PLATDATA_DRIVER_RT))
+		return 0;
+
 	/* Record the indexes that are found */
 	memset(found, '\0', sizeof(found));
 	ut_assertok(find_driver_info(uts, gd->dm_root, found));
@@ -155,18 +157,16 @@
 	/* Make sure that the driver entries without devices have no ->dev */
 	for (i = 0; i < n_ents; i++) {
 		const struct driver_rt *drt = gd_dm_driver_rt() + i;
-		const struct driver_info *entry = info + i;
 		struct udevice *dev;
 
 		if (found[i]) {
 			/* Make sure we can find it */
 			ut_assertnonnull(drt->dev);
-			ut_assertok(device_get_by_driver_info(entry, &dev));
+			ut_assertok(device_get_by_ofplat_idx(i, &dev));
 			ut_asserteq_ptr(dev, drt->dev);
 		} else {
 			ut_assertnull(drt->dev);
-			ut_asserteq(-ENOENT,
-				    device_get_by_driver_info(entry, &dev));
+			ut_asserteq(-ENOENT, device_get_by_ofplat_idx(i, &dev));
 		}
 	}
 
@@ -184,22 +184,22 @@
 	ut_asserteq_str("sandbox_clk_test", dev->name);
 	plat = dev_get_plat(dev);
 
-	ut_assertok(device_get_by_driver_info_idx(plat->clocks[0].idx, &clk));
-	ut_asserteq_str("fixed_clock", clk->name);
+	ut_assertok(device_get_by_ofplat_idx(plat->clocks[0].idx, &clk));
+	ut_asserteq_str("sandbox_fixed_clock", clk->name);
 
-	ut_assertok(device_get_by_driver_info_idx(plat->clocks[1].idx, &clk));
+	ut_assertok(device_get_by_ofplat_idx(plat->clocks[1].idx, &clk));
 	ut_asserteq_str("sandbox_clk", clk->name);
 	ut_asserteq(1, plat->clocks[1].arg[0]);
 
-	ut_assertok(device_get_by_driver_info_idx(plat->clocks[2].idx, &clk));
+	ut_assertok(device_get_by_ofplat_idx(plat->clocks[2].idx, &clk));
 	ut_asserteq_str("sandbox_clk", clk->name);
 	ut_asserteq(0, plat->clocks[2].arg[0]);
 
-	ut_assertok(device_get_by_driver_info_idx(plat->clocks[3].idx, &clk));
+	ut_assertok(device_get_by_ofplat_idx(plat->clocks[3].idx, &clk));
 	ut_asserteq_str("sandbox_clk", clk->name);
 	ut_asserteq(3, plat->clocks[3].arg[0]);
 
-	ut_assertok(device_get_by_driver_info_idx(plat->clocks[4].idx, &clk));
+	ut_assertok(device_get_by_ofplat_idx(plat->clocks[4].idx, &clk));
 	ut_asserteq_str("sandbox_clk", clk->name);
 	ut_asserteq(2, plat->clocks[4].arg[0]);
 
@@ -211,11 +211,11 @@
 /* Test that device parents are correctly set up */
 static int dm_test_of_plat_parent(struct unit_test_state *uts)
 {
-	struct udevice *dev, *bus;
+	struct udevice *rtc, *i2c;
 
-	ut_assertok(uclass_first_device_err(UCLASS_SIMPLE_BUS, &bus));
-	ut_assertok(device_first_child_err(bus, &dev));
-	ut_asserteq_ptr(bus, dev_get_parent(dev));
+	ut_assertok(uclass_first_device_err(UCLASS_RTC, &rtc));
+	ut_assertok(uclass_first_device_err(UCLASS_I2C, &i2c));
+	ut_asserteq_ptr(i2c, dev_get_parent(rtc));
 
 	return 0;
 }
diff --git a/test/dm/sf.c b/test/dm/sf.c
index cc1fc4d..17d43fe 100644
--- a/test/dm/sf.c
+++ b/test/dm/sf.c
@@ -21,7 +21,7 @@
 /* Simple test of sandbox SPI flash */
 static int dm_test_spi_flash(struct unit_test_state *uts)
 {
-	struct udevice *dev;
+	struct udevice *dev, *emul;
 	int full_size = 0x200000;
 	int size = 0x10000;
 	u8 *src, *dst;
@@ -51,6 +51,14 @@
 	ut_assertok(spi_flash_read_dm(dev, 0, size, dst));
 	ut_asserteq_mem(src, dst, size);
 
+	/* Try the write-protect stuff */
+	ut_assertok(uclass_first_device_err(UCLASS_SPI_EMUL, &emul));
+	ut_asserteq(0, spl_flash_get_sw_write_prot(dev));
+	sandbox_sf_set_block_protect(emul, 1);
+	ut_asserteq(1, spl_flash_get_sw_write_prot(dev));
+	sandbox_sf_set_block_protect(emul, 0);
+	ut_asserteq(0, spl_flash_get_sw_write_prot(dev));
+
 	/* Check mapping */
 	ut_assertok(dm_spi_get_mmap(dev, &map_base, &map_size, &offset));
 	ut_asserteq(0x1000, map_base);
diff --git a/test/dm/test-dm.c b/test/dm/test-dm.c
new file mode 100644
index 0000000..9ba2ba2
--- /dev/null
+++ b/test/dm/test-dm.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013 Google, Inc
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/global_data.h>
+#include <asm/state.h>
+#include <dm/root.h>
+#include <dm/uclass-internal.h>
+#include <test/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * dm_test_run() - Run driver model tests
+ *
+ * Run all the available driver model tests, or a selection
+ *
+ * @test_name: Name of single test to run (e.g. "dm_test_fdt_pre_reloc" or just
+ *	"fdt_pre_reloc"), or NULL to run all
+ * @return 0 if all tests passed, 1 if not
+ */
+static int dm_test_run(const char *test_name)
+{
+	struct unit_test *tests = UNIT_TEST_SUITE_START(dm_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(dm_test);
+	int ret;
+
+	ret = ut_run_list("driver model", "dm_test_", tests, n_ents, test_name);
+
+	return ret ? CMD_RET_FAILURE : 0;
+}
+
+int do_ut_dm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	const char *test_name = NULL;
+
+	if (argc > 1)
+		test_name = argv[1];
+
+	return dm_test_run(test_name);
+}
diff --git a/test/dm/test-driver.c b/test/dm/test-driver.c
index ca7626a..02cb974 100644
--- a/test/dm/test-driver.c
+++ b/test/dm/test-driver.c
@@ -18,7 +18,6 @@
 #include <test/ut.h>
 
 int dm_testdrv_op_count[DM_TEST_OP_COUNT];
-static struct unit_test_state *uts = &global_dm_test_state;
 
 static int testdrv_ping(struct udevice *dev, int pingval, int *pingret)
 {
@@ -37,6 +36,8 @@
 
 static int test_bind(struct udevice *dev)
 {
+	struct unit_test_state *uts = test_get_state();
+
 	/* Private data should not be allocated */
 	ut_assert(!dev_get_priv(dev));
 
@@ -46,6 +47,7 @@
 
 static int test_probe(struct udevice *dev)
 {
+	struct unit_test_state *uts = test_get_state();
 	struct dm_test_priv *priv = dev_get_priv(dev);
 
 	/* Private data should be allocated */
@@ -58,6 +60,8 @@
 
 static int test_remove(struct udevice *dev)
 {
+	struct unit_test_state *uts = test_get_state();
+
 	/* Private data should still be allocated */
 	ut_assert(dev_get_priv(dev));
 
@@ -67,6 +71,8 @@
 
 static int test_unbind(struct udevice *dev)
 {
+	struct unit_test_state *uts = test_get_state();
+
 	/* Private data should not be allocated */
 	ut_assert(!dev_get_priv(dev));
 
@@ -116,10 +122,10 @@
 
 static int test_manual_probe(struct udevice *dev)
 {
-	struct dm_test_state *dms = uts->priv;
+	struct unit_test_state *uts = test_get_state();
 
 	dm_testdrv_op_count[DM_TEST_OP_PROBE]++;
-	if (!dms->force_fail_alloc)
+	if (!uts->force_fail_alloc)
 		dev_set_priv(dev, calloc(1, sizeof(struct dm_test_priv)));
 	if (!dev_get_priv(dev))
 		return -ENOMEM;
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index 6e83aee..6552d09 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -330,7 +330,7 @@
 
 	/* Check creating a device with an alias */
 	node = ofnode_path("/some-bus/c-test@1");
-	ut_assertok(device_bind(dm_root(), DM_DRIVER_GET(testfdt_drv),
+	ut_assertok(device_bind(dm_root(), DM_DRIVER_GET(denx_u_boot_fdt_test),
 				"c-test@1", NULL, node, &dev));
 	ut_asserteq(12, dev_seq(dev));
 	ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 12, &dev));
@@ -350,11 +350,11 @@
 	 *
 	 * So next available is 19
 	 */
-	ut_assertok(device_bind(dm_root(), DM_DRIVER_GET(testfdt_drv),
+	ut_assertok(device_bind(dm_root(), DM_DRIVER_GET(denx_u_boot_fdt_test),
 				"fred", NULL, ofnode_null(), &dev));
 	ut_asserteq(19, dev_seq(dev));
 
-	ut_assertok(device_bind(dm_root(), DM_DRIVER_GET(testfdt_drv),
+	ut_assertok(device_bind(dm_root(), DM_DRIVER_GET(denx_u_boot_fdt_test),
 				"fred2", NULL, ofnode_null(), &dev));
 	ut_asserteq(20, dev_seq(dev));
 
diff --git a/test/dm/test-main.c b/test/dm/test-main.c
deleted file mode 100644
index 560f8d6..0000000
--- a/test/dm/test-main.c
+++ /dev/null
@@ -1,230 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 2013 Google, Inc
- */
-
-#include <common.h>
-#include <command.h>
-#include <console.h>
-#include <dm.h>
-#include <errno.h>
-#include <log.h>
-#include <malloc.h>
-#include <asm/global_data.h>
-#include <asm/state.h>
-#include <dm/test.h>
-#include <dm/root.h>
-#include <dm/uclass-internal.h>
-#include <test/test.h>
-#include <test/test.h>
-#include <test/ut.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-struct unit_test_state global_dm_test_state;
-static struct dm_test_state _global_priv_dm_test_state;
-
-/* Get ready for testing */
-static int dm_test_init(struct unit_test_state *uts, bool of_live)
-{
-	struct dm_test_state *dms = uts->priv;
-
-	memset(dms, '\0', sizeof(*dms));
-	gd->dm_root = NULL;
-	if (!CONFIG_IS_ENABLED(OF_PLATDATA))
-		memset(dm_testdrv_op_count, '\0', sizeof(dm_testdrv_op_count));
-	state_reset_for_test(state_get_current());
-
-	/* Determine whether to make the live tree available */
-	gd_set_of_root(of_live ? uts->of_root : NULL);
-	ut_assertok(dm_init(of_live));
-	dms->root = dm_root();
-
-	return 0;
-}
-
-/* Ensure all the test devices are probed */
-static int do_autoprobe(struct unit_test_state *uts)
-{
-	struct udevice *dev;
-	int ret;
-
-	/* Scanning the uclass is enough to probe all the devices */
-	for (ret = uclass_first_device(UCLASS_TEST, &dev);
-	     dev;
-	     ret = uclass_next_device(&dev))
-		;
-
-	return ret;
-}
-
-static int dm_test_destroy(struct unit_test_state *uts)
-{
-	int id;
-
-	for (id = 0; id < UCLASS_COUNT; id++) {
-		struct uclass *uc;
-
-		/*
-		 * If the uclass doesn't exist we don't want to create it. So
-		 * check that here before we call uclass_find_device().
-		 */
-		uc = uclass_find(id);
-		if (!uc)
-			continue;
-		ut_assertok(uclass_destroy(uc));
-	}
-
-	return 0;
-}
-
-static int dm_do_test(struct unit_test_state *uts, struct unit_test *test,
-		      bool of_live)
-{
-	struct sandbox_state *state = state_get_current();
-	const char *fname = strrchr(test->file, '/') + 1;
-
-	printf("Test: %s: %s%s\n", test->name, fname,
-	       !of_live ? " (flat tree)" : "");
-	ut_assertok(dm_test_init(uts, of_live));
-
-	uts->start = mallinfo();
-	if (test->flags & UT_TESTF_SCAN_PDATA)
-		ut_assertok(dm_scan_plat(false));
-	if (test->flags & UT_TESTF_PROBE_TEST)
-		ut_assertok(do_autoprobe(uts));
-	if (!CONFIG_IS_ENABLED(OF_PLATDATA) &&
-	    (test->flags & UT_TESTF_SCAN_FDT))
-		ut_assertok(dm_extended_scan(false));
-
-	/*
-	 * Silence the console and rely on console recording to get
-	 * our output.
-	 */
-	console_record_reset_enable();
-	if (!state->show_test_output)
-		gd->flags |= GD_FLG_SILENT;
-	test->func(uts);
-	gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
-	state_set_skip_delays(false);
-
-	ut_assertok(dm_test_destroy(uts));
-
-	return 0;
-}
-
-/**
- * dm_test_run_on_flattree() - Check if we should run a test with flat DT
- *
- * This skips long/slow tests where there is not much value in running a flat
- * DT test in addition to a live DT test.
- *
- * @return true to run the given test on the flat device tree
- */
-static bool dm_test_run_on_flattree(struct unit_test *test)
-{
-	const char *fname = strrchr(test->file, '/') + 1;
-
-	return !strstr(fname, "video") || strstr(test->name, "video_base");
-}
-
-static bool test_matches(const char *test_name, const char *find_name)
-{
-	if (!find_name)
-		return true;
-
-	if (!strcmp(test_name, find_name))
-		return true;
-
-	/* All tests have this prefix */
-	if (!strncmp(test_name, "dm_test_", 8))
-		test_name += 8;
-
-	if (!strcmp(test_name, find_name))
-		return true;
-
-	return false;
-}
-
-int dm_test_main(const char *test_name)
-{
-	struct unit_test *tests = ll_entry_start(struct unit_test, dm_test);
-	const int n_ents = ll_entry_count(struct unit_test, dm_test);
-	struct unit_test_state *uts = &global_dm_test_state;
-	struct unit_test *test;
-	int found;
-
-	uts->priv = &_global_priv_dm_test_state;
-	uts->fail_count = 0;
-
-	if (!CONFIG_IS_ENABLED(OF_PLATDATA)) {
-		/*
-		 * If we have no device tree, or it only has a root node, then
-		 * these * tests clearly aren't going to work...
-		 */
-		if (!gd->fdt_blob || fdt_next_node(gd->fdt_blob, 0, NULL) < 0) {
-			puts("Please run with test device tree:\n"
-			     "    ./u-boot -d arch/sandbox/dts/test.dtb\n");
-			ut_assert(gd->fdt_blob);
-		}
-	}
-
-	if (!test_name)
-		printf("Running %d driver model tests\n", n_ents);
-	else
-
-	found = 0;
-	uts->of_root = gd_of_root();
-	for (test = tests; test < tests + n_ents; test++) {
-		const char *name = test->name;
-		int runs;
-
-		if (!test_matches(name, test_name))
-			continue;
-
-		/* Run with the live tree if possible */
-		runs = 0;
-		if (CONFIG_IS_ENABLED(OF_LIVE)) {
-			if (!(test->flags & UT_TESTF_FLAT_TREE)) {
-				ut_assertok(dm_do_test(uts, test, true));
-				runs++;
-			}
-		}
-
-		/*
-		 * Run with the flat tree if we couldn't run it with live tree,
-		 * or it is a core test.
-		 */
-		if (!(test->flags & UT_TESTF_LIVE_TREE) &&
-		    (!runs || dm_test_run_on_flattree(test))) {
-			ut_assertok(dm_do_test(uts, test, false));
-			runs++;
-		}
-		found++;
-	}
-
-	if (test_name && !found)
-		printf("Test '%s' not found\n", test_name);
-	else
-		printf("Failures: %d\n", uts->fail_count);
-
-	/* Put everything back to normal so that sandbox works as expected */
-	gd_set_of_root(uts->of_root);
-	gd->dm_root = NULL;
-	ut_assertok(dm_init(CONFIG_IS_ENABLED(OF_LIVE)));
-	dm_scan_plat(false);
-	if (!CONFIG_IS_ENABLED(OF_PLATDATA))
-		dm_scan_fdt(false);
-
-	return uts->fail_count ? CMD_RET_FAILURE : 0;
-}
-
-int do_ut_dm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
-{
-	const char *test_name = NULL;
-
-	if (argc > 1)
-		test_name = argv[1];
-
-	return dm_test_main(test_name);
-}
diff --git a/test/dm/test-uclass.c b/test/dm/test-uclass.c
index f1b7aaa..0677017 100644
--- a/test/dm/test-uclass.c
+++ b/test/dm/test-uclass.c
@@ -17,8 +17,6 @@
 #include <test/test.h>
 #include <test/ut.h>
 
-static struct unit_test_state *uts = &global_dm_test_state;
-
 int test_ping(struct udevice *dev, int pingval, int *pingret)
 {
 	const struct test_ops *ops = device_get_ops(dev);
@@ -31,6 +29,7 @@
 
 static int test_post_bind(struct udevice *dev)
 {
+	struct unit_test_state *uts = test_get_state();
 	struct dm_test_perdev_uc_pdata *uc_pdata;
 
 	dm_testdrv_op_count[DM_TEST_OP_POST_BIND]++;
@@ -56,6 +55,7 @@
 static int test_pre_probe(struct udevice *dev)
 {
 	struct dm_test_uclass_perdev_priv *priv = dev_get_uclass_priv(dev);
+	struct unit_test_state *uts = test_get_state();
 
 	dm_testdrv_op_count[DM_TEST_OP_PRE_PROBE]++;
 	ut_assert(priv);
@@ -66,18 +66,18 @@
 
 static int test_post_probe(struct udevice *dev)
 {
+	struct unit_test_state *uts = test_get_state();
 	struct udevice *prev = list_entry(dev->uclass_node.prev,
 					    struct udevice, uclass_node);
 
 	struct dm_test_uclass_perdev_priv *priv = dev_get_uclass_priv(dev);
 	struct uclass *uc = dev->uclass;
-	struct dm_test_state *dms = uts->priv;
 
 	dm_testdrv_op_count[DM_TEST_OP_POST_PROBE]++;
 	ut_assert(priv);
 	ut_assert(device_active(dev));
 	priv->base_add = 0;
-	if (dms->skip_post_probe)
+	if (uts->skip_post_probe)
 		return 0;
 	if (&prev->uclass_node != &uc->dev_head) {
 		struct dm_test_uclass_perdev_priv *prev_uc_priv
@@ -101,6 +101,8 @@
 
 static int test_init(struct uclass *uc)
 {
+	struct unit_test_state *uts = test_get_state();
+
 	dm_testdrv_op_count[DM_TEST_OP_INIT]++;
 	ut_assert(uclass_get_priv(uc));
 
diff --git a/test/env/cmd_ut_env.c b/test/env/cmd_ut_env.c
index a440b1b..d65a321 100644
--- a/test/env/cmd_ut_env.c
+++ b/test/env/cmd_ut_env.c
@@ -12,8 +12,8 @@
 
 int do_ut_env(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-	struct unit_test *tests = ll_entry_start(struct unit_test, env_test);
-	const int n_ents = ll_entry_count(struct unit_test, env_test);
+	struct unit_test *tests = UNIT_TEST_SUITE_START(env_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(env_test);
 
 	return cmd_ut_category("environment", "env_test_",
 			       tests, n_ents, argc, argv);
diff --git a/test/image/Makefile b/test/image/Makefile
new file mode 100644
index 0000000..c4039df
--- /dev/null
+++ b/test/image/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2021 Google LLC
+
+obj-$(CONFIG_SPL_BUILD) += spl_load.o
diff --git a/test/image/spl_load.c b/test/image/spl_load.c
new file mode 100644
index 0000000..851603d
--- /dev/null
+++ b/test/image/spl_load.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <image.h>
+#include <mapmem.h>
+#include <os.h>
+#include <spl.h>
+#include <test/ut.h>
+
+/* Declare a new SPL test */
+#define SPL_TEST(_name, _flags)		UNIT_TEST(_name, _flags, spl_test)
+
+/* Context used for this test */
+struct text_ctx {
+	int fd;
+};
+
+static ulong read_fit_image(struct spl_load_info *load, ulong sector,
+			    ulong count, void *buf)
+{
+	struct text_ctx *text_ctx = load->priv;
+	off_t offset, ret;
+	ssize_t res;
+
+	offset = sector * load->bl_len;
+	ret = os_lseek(text_ctx->fd, offset, OS_SEEK_SET);
+	if (ret != offset) {
+		printf("Failed to seek to %zx, got %zx (errno=%d)\n", offset,
+		       ret, errno);
+		return 0;
+	}
+
+	res = os_read(text_ctx->fd, buf, count * load->bl_len);
+	if (res == -1) {
+		printf("Failed to read %lx bytes, got %ld (errno=%d)\n",
+		       count * load->bl_len, res, errno);
+		return 0;
+	}
+
+	return count;
+}
+
+int board_fit_config_name_match(const char *name)
+{
+	return 0;
+}
+
+struct image_header *spl_get_load_buffer(ssize_t offset, size_t size)
+{
+	return map_sysmem(0x100000, 0);
+}
+
+static int spl_test_load(struct unit_test_state *uts)
+{
+	struct spl_image_info image;
+	struct image_header *header;
+	struct text_ctx text_ctx;
+	struct spl_load_info load;
+	char fname[256];
+	int ret;
+	int fd;
+
+	memset(&load, '\0', sizeof(load));
+	load.bl_len = 512;
+	load.read = read_fit_image;
+
+	ret = os_find_u_boot(fname, sizeof(fname), true);
+	if (ret) {
+		printf("(%s not found, error %d)\n", fname, ret);
+		return ret;
+	}
+	load.filename = fname;
+
+	header = spl_get_load_buffer(-sizeof(*header), sizeof(*header));
+
+	fd = os_open(fname, OS_O_RDONLY);
+	ut_assert(fd >= 0);
+	ut_asserteq(512, os_read(fd, header, 512));
+	text_ctx.fd = fd;
+
+	load.priv = &text_ctx;
+
+	ut_assertok(spl_load_simple_fit(&image, &load, 0, header));
+
+	return 0;
+}
+SPL_TEST(spl_test_load, 0);
diff --git a/test/lib/Makefile b/test/lib/Makefile
index 97c11e3..a30f615 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -7,6 +7,7 @@
 obj-$(CONFIG_EFI_SECURE_BOOT) += efi_image_region.o
 obj-y += hexdump.o
 obj-y += lmb.o
+obj-y += longjmp.o
 obj-$(CONFIG_CONSOLE_RECORD) += test_print.o
 obj-$(CONFIG_SSCANF) += sscanf.o
 obj-y += string.o
diff --git a/test/lib/cmd_ut_lib.c b/test/lib/cmd_ut_lib.c
index f5c7bf3..f1ac015 100644
--- a/test/lib/cmd_ut_lib.c
+++ b/test/lib/cmd_ut_lib.c
@@ -13,8 +13,8 @@
 
 int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-	struct unit_test *tests = ll_entry_start(struct unit_test, lib_test);
-	const int n_ents = ll_entry_count(struct unit_test, lib_test);
+	struct unit_test *tests = UNIT_TEST_SUITE_START(lib_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(lib_test);
 
 	return cmd_ut_category("lib", "lib_test_", tests, n_ents, argc, argv);
 }
diff --git a/test/lib/longjmp.c b/test/lib/longjmp.c
new file mode 100644
index 0000000..201367a
--- /dev/null
+++ b/test/lib/longjmp.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test setjmp(), longjmp()
+ *
+ * Copyright (c) 2021, Heinrich Schuchardt <xypron.glpk@gmx.de>
+ */
+
+#include <common.h>
+#include <test/lib.h>
+#include <test/test.h>
+#include <test/ut.h>
+#include <asm/setjmp.h>
+
+struct test_jmp_buf {
+	jmp_buf env;
+	int val;
+};
+
+/**
+ * test_longjmp() - test longjmp function
+ *
+ * @i is passed to longjmp.
+ * @i << 8 is set in the environment structure.
+ *
+ * @env:	environment
+ * @i:		value passed to longjmp()
+ */
+static noinline void test_longjmp(struct test_jmp_buf *env, int i)
+{
+	env->val = i << 8;
+	longjmp(env->env, i);
+}
+
+/**
+ * test_setjmp() - test setjmp function
+ *
+ * setjmp() will return the value @i passed to longjmp() if @i is non-zero.
+ * For @i == 0 we expect return value 1.
+ *
+ * @i << 8 will be set by test_longjmp in the environment structure.
+ * This value can be used to check that the stack frame is restored.
+ *
+ * We return the XORed values to allow simply check both at once.
+ *
+ * @i:		value passed to longjmp()
+ * Return:	values return by longjmp()
+ */
+static int test_setjmp(int i)
+{
+	struct test_jmp_buf env;
+	int ret;
+
+	env.val = -1;
+	ret = setjmp(env.env);
+	if (ret)
+		return ret ^ env.val;
+	test_longjmp(&env, i);
+	/* We should not arrive here */
+	return 0x1000;
+}
+
+static int lib_test_longjmp(struct unit_test_state *uts)
+{
+	int i;
+
+	for (i = -3; i < 0; ++i)
+		ut_asserteq(i ^ (i << 8), test_setjmp(i));
+	ut_asserteq(1, test_setjmp(0));
+	for (i = 1; i < 4; ++i)
+		ut_asserteq(i ^ (i << 8), test_setjmp(i));
+	return 0;
+}
+LIB_TEST(lib_test_longjmp, 0);
diff --git a/test/lib/test_print.c b/test/lib/test_print.c
index 12972f1..a60a5a5 100644
--- a/test/lib/test_print.c
+++ b/test/lib/test_print.c
@@ -18,12 +18,14 @@
 static int test_print_freq(struct unit_test_state *uts,
 			   uint64_t freq, char *expected)
 {
+	ut_silence_console(uts);
 	console_record_reset_enable();
 	print_freq(freq, ";\n");
-	gd->flags &= ~GD_FLG_RECORD;
+	ut_unsilence_console(uts);
 	console_record_readline(uts->actual_str, sizeof(uts->actual_str));
 	ut_asserteq_str(expected, uts->actual_str);
 	ut_assertok(ut_check_console_end(uts));
+
 	return 0;
 }
 
@@ -46,12 +48,14 @@
 static int test_print_size(struct unit_test_state *uts,
 			   uint64_t freq, char *expected)
 {
+	ut_silence_console(uts);
 	console_record_reset_enable();
 	print_size(freq, ";\n");
-	gd->flags &= ~GD_FLG_RECORD;
+	ut_unsilence_console(uts);
 	console_record_readline(uts->actual_str, sizeof(uts->actual_str));
 	ut_asserteq_str(expected, uts->actual_str);
 	ut_assertok(ut_check_console_end(uts));
+
 	return 0;
 }
 
diff --git a/test/log/Makefile b/test/log/Makefile
index 3f09deb..a3dedac 100644
--- a/test/log/Makefile
+++ b/test/log/Makefile
@@ -7,7 +7,7 @@
 
 ifdef CONFIG_UT_LOG
 
-obj-y += test-main.o
+obj-y += log_ut.o
 
 ifdef CONFIG_SANDBOX
 obj-$(CONFIG_LOG_SYSLOG) += syslog_test.o
diff --git a/test/log/cont_test.c b/test/log/cont_test.c
index 16379a7..de7b7f0 100644
--- a/test/log/cont_test.c
+++ b/test/log/cont_test.c
@@ -15,8 +15,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#define BUFFSIZE 64
-
 static int log_test_cont(struct unit_test_state *uts)
 {
 	int log_fmt;
@@ -29,12 +27,13 @@
 	gd->log_fmt = (1 << LOGF_CAT) | (1 << LOGF_LEVEL) | (1 << LOGF_MSG);
 	gd->default_log_level = LOGL_INFO;
 	console_record_reset_enable();
-	log(LOGC_ARCH, LOGL_ERR, "ea%d ", 1);
+	log(LOGC_ARCH, LOGL_ERR, "ea%d\n", 1);
 	log(LOGC_CONT, LOGL_CONT, "cc%d\n", 2);
 	gd->default_log_level = log_level;
 	gd->log_fmt = log_fmt;
 	gd->flags &= ~GD_FLG_RECORD;
-	ut_assertok(ut_check_console_line(uts, "ERR.arch, ea1 ERR.arch, cc2"));
+	ut_assertok(ut_check_console_line(uts, "ERR.arch, ea1"));
+	ut_assertok(ut_check_console_line(uts, "ERR.arch, cc2"));
 	ut_assertok(ut_check_console_end(uts));
 
 	/* Write a third message which is not a continuation */
@@ -48,6 +47,18 @@
 	ut_assertok(ut_check_console_line(uts, "INFO.efi, ie3"));
 	ut_assertok(ut_check_console_end(uts));
 
+	/* Write two messages without a newline between them */
+	gd->log_fmt = (1 << LOGF_CAT) | (1 << LOGF_LEVEL) | (1 << LOGF_MSG);
+	gd->default_log_level = LOGL_INFO;
+	console_record_reset_enable();
+	log(LOGC_ARCH, LOGL_ERR, "ea%d ", 1);
+	log(LOGC_CONT, LOGL_CONT, "cc%d\n", 2);
+	gd->default_log_level = log_level;
+	gd->log_fmt = log_fmt;
+	gd->flags &= ~GD_FLG_RECORD;
+	ut_assertok(ut_check_console_line(uts, "ERR.arch, ea1 cc2"));
+	ut_assertok(ut_check_console_end(uts));
+
 	return 0;
 }
 LOG_TEST(log_test_cont);
diff --git a/test/log/test-main.c b/test/log/log_ut.c
similarity index 75%
rename from test/log/test-main.c
rename to test/log/log_ut.c
index c534add..5aa3a18 100644
--- a/test/log/test-main.c
+++ b/test/log/log_ut.c
@@ -13,8 +13,8 @@
 
 int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
 {
-	struct unit_test *tests = ll_entry_start(struct unit_test, log_test);
-	const int n_ents = ll_entry_count(struct unit_test, log_test);
+	struct unit_test *tests = UNIT_TEST_SUITE_START(log_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(log_test);
 
 	return cmd_ut_category("log", "log_test_",
 			       tests, n_ents, argc, argv);
diff --git a/test/optee/cmd_ut_optee.c b/test/optee/cmd_ut_optee.c
index 9fa4c91..c3887ab 100644
--- a/test/optee/cmd_ut_optee.c
+++ b/test/optee/cmd_ut_optee.c
@@ -94,9 +94,8 @@
 
 int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-	struct unit_test *tests = ll_entry_start(struct unit_test,
-						 optee_test);
-	const int n_ents = ll_entry_count(struct unit_test, optee_test);
+	struct unit_test *tests = UNIT_TEST_SUITE_START(optee_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(optee_test);
 	struct unit_test_state *uts;
 	void *fdt_optee = &__dtb_test_optee_optee_begin;
 	void *fdt_no_optee = &__dtb_test_optee_no_optee_begin;
diff --git a/test/overlay/cmd_ut_overlay.c b/test/overlay/cmd_ut_overlay.c
index c001fb1..56a3df1 100644
--- a/test/overlay/cmd_ut_overlay.c
+++ b/test/overlay/cmd_ut_overlay.c
@@ -213,9 +213,8 @@
 
 int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-	struct unit_test *tests = ll_entry_start(struct unit_test,
-						 overlay_test);
-	const int n_ents = ll_entry_count(struct unit_test, overlay_test);
+	struct unit_test *tests = UNIT_TEST_SUITE_START(overlay_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(overlay_test);
 	struct unit_test_state *uts;
 	void *fdt_base = &__dtb_test_fdt_base_begin;
 	void *fdt_overlay = &__dtb_test_fdt_overlay_begin;
diff --git a/test/py/conftest.py b/test/py/conftest.py
index 9bfd926..1b909cd 100644
--- a/test/py/conftest.py
+++ b/test/py/conftest.py
@@ -226,7 +226,7 @@
         import u_boot_console_exec_attach
         console = u_boot_console_exec_attach.ConsoleExecAttach(log, ubconfig)
 
-re_ut_test_list = re.compile(r'_u_boot_list_2_(.*)_test_2_\1_test_(.*)\s*$')
+re_ut_test_list = re.compile(r'_u_boot_list_2_ut_(.*)_test_2_\1_test_(.*)\s*$')
 def generate_ut_subtest(metafunc, fixture_name, sym_path):
     """Provide parametrization for a ut_subtest fixture.
 
diff --git a/test/py/requirements.txt b/test/py/requirements.txt
index 926bcca..89ca259 100644
--- a/test/py/requirements.txt
+++ b/test/py/requirements.txt
@@ -11,7 +11,7 @@
 pluggy==0.13.0
 py==1.8.0
 pyelftools==0.27
-pygit2==1.4.0
+pygit2==0.28.2
 pyparsing==2.4.2
 pytest==5.2.1
 python-mimeparse==1.6.0
diff --git a/test/py/tests/test_efi_capsule/test_capsule_firmware.py b/test/py/tests/test_efi_capsule/test_capsule_firmware.py
index f006fa9..160a64a 100644
--- a/test/py/tests/test_efi_capsule/test_capsule_firmware.py
+++ b/test/py/tests/test_efi_capsule/test_capsule_firmware.py
@@ -39,7 +39,7 @@
         with u_boot_console.log.section('Test Case 1-a, before reboot'):
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
-                'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi ""',
                 'efidebug boot order 1',
                 'env set -e OsIndications',
                 'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
@@ -114,7 +114,7 @@
         with u_boot_console.log.section('Test Case 2-a, before reboot'):
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
-                'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi ""',
                 'efidebug boot order 1',
                 'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
                 'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
@@ -188,7 +188,7 @@
         with u_boot_console.log.section('Test Case 3-a, before reboot'):
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
-                'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi ""',
                 'efidebug boot order 1',
                 'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
                 'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
@@ -229,6 +229,14 @@
                 output = u_boot_console.run_command(
                     'env print -e -all Capsule0000')
 
+            output = u_boot_console.run_command_list(['efidebug capsule esrt'])
+
+            # ensure that EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID is in the ESRT.
+            assert 'AE13FF2D-9AD4-4E25-9AC8-6D80B3B22147' in ''.join(output)
+
+            # ensure that  EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID is in the ESRT.
+            assert 'E2BB9C06-70E9-4B14-97A3-5A7913176E3F' in ''.join(output)
+
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
                 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
diff --git a/test/py/tests/test_efi_secboot/test_signed.py b/test/py/tests/test_efi_secboot/test_signed.py
index 863685e..75f5ea7 100644
--- a/test/py/tests/test_efi_secboot/test_signed.py
+++ b/test/py/tests/test_efi_secboot/test_signed.py
@@ -28,7 +28,7 @@
             # Test Case 1a, run signed image if no PK
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
-                'efidebug boot add 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
+                'efidebug boot add -b 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
             assert 'Hello, world!' in ''.join(output)
@@ -36,7 +36,7 @@
         with u_boot_console.log.section('Test Case 1b'):
             # Test Case 1b, run unsigned image if no PK
             output = u_boot_console.run_command_list([
-                'efidebug boot add 2 HELLO2 host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 2 HELLO2 host 0:1 /helloworld.efi ""',
                 'efidebug boot next 2',
                 'bootefi bootmgr'])
             assert 'Hello, world!' in ''.join(output)
@@ -58,13 +58,13 @@
                 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
             assert 'Failed to set EFI variable' not in ''.join(output)
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
+                'efidebug boot add -b 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
             assert('\'HELLO1\' failed' in ''.join(output))
             assert('efi_start_image() returned: 26' in ''.join(output))
             output = u_boot_console.run_command_list([
-                'efidebug boot add 2 HELLO2 host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 2 HELLO2 host 0:1 /helloworld.efi ""',
                 'efidebug boot next 2',
                 'efidebug test bootmgr'])
             assert '\'HELLO2\' failed' in ''.join(output)
@@ -104,7 +104,7 @@
                 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
             assert 'Failed to set EFI variable' not in ''.join(output)
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed ""',
+                'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed ""',
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
             assert '\'HELLO\' failed' in ''.join(output)
@@ -142,7 +142,7 @@
                 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
             assert 'Failed to set EFI variable' not in ''.join(output)
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed ""',
+                'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed ""',
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
             assert '\'HELLO\' failed' in ''.join(output)
@@ -169,7 +169,7 @@
                 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
             assert 'Failed to set EFI variable' not in ''.join(output)
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed_2sigs ""',
+                'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed_2sigs ""',
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
             assert 'Hello, world!' in ''.join(output)
@@ -227,7 +227,7 @@
                 'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
             assert 'Failed to set EFI variable' not in ''.join(output)
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed ""',
+                'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
             assert 'Hello, world!' in ''.join(output)
diff --git a/test/py/tests/test_efi_secboot/test_signed_intca.py b/test/py/tests/test_efi_secboot/test_signed_intca.py
index 70d6be0..0849572 100644
--- a/test/py/tests/test_efi_secboot/test_signed_intca.py
+++ b/test/py/tests/test_efi_secboot/test_signed_intca.py
@@ -39,7 +39,7 @@
             assert 'Failed to set EFI variable' not in ''.join(output)
 
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO_a host 0:1 /helloworld.efi.signed_a ""',
+                'efidebug boot add -b 1 HELLO_a host 0:1 /helloworld.efi.signed_a ""',
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
             assert '\'HELLO_a\' failed' in ''.join(output)
@@ -48,7 +48,7 @@
         with u_boot_console.log.section('Test Case 1b'):
             # Test Case 1b, signed and authenticated by root CA
             output = u_boot_console.run_command_list([
-                'efidebug boot add 2 HELLO_ab host 0:1 /helloworld.efi.signed_ab ""',
+                'efidebug boot add -b 2 HELLO_ab host 0:1 /helloworld.efi.signed_ab ""',
                 'efidebug boot next 2',
                 'bootefi bootmgr'])
             assert 'Hello, world!' in ''.join(output)
@@ -70,7 +70,7 @@
             assert 'Failed to set EFI variable' not in ''.join(output)
 
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO_abc host 0:1 /helloworld.efi.signed_abc ""',
+                'efidebug boot add -b 1 HELLO_abc host 0:1 /helloworld.efi.signed_abc ""',
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
             assert '\'HELLO_abc\' failed' in ''.join(output)
@@ -116,7 +116,7 @@
             assert 'Failed to set EFI variable' not in ''.join(output)
 
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO_abc host 0:1 /helloworld.efi.signed_abc ""',
+                'efidebug boot add -b 1 HELLO_abc host 0:1 /helloworld.efi.signed_abc ""',
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
             assert 'Hello, world!' in ''.join(output)
diff --git a/test/py/tests/test_efi_secboot/test_unsigned.py b/test/py/tests/test_efi_secboot/test_unsigned.py
index 56f56e1..8e026f7 100644
--- a/test/py/tests/test_efi_secboot/test_unsigned.py
+++ b/test/py/tests/test_efi_secboot/test_unsigned.py
@@ -35,7 +35,7 @@
             assert 'Failed to set EFI variable' not in ''.join(output)
 
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
             assert '\'HELLO\' failed' in ''.join(output)
@@ -64,7 +64,7 @@
             assert 'Failed to set EFI variable' not in ''.join(output)
 
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
             assert 'Hello, world!' in ''.join(output)
@@ -88,7 +88,7 @@
             assert 'Failed to set EFI variable' not in ''.join(output)
 
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
             assert '\'HELLO\' failed' in ''.join(output)
@@ -106,7 +106,7 @@
             assert 'Failed to set EFI variable' not in ''.join(output)
 
             output = u_boot_console.run_command_list([
-                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
+                'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
             assert '\'HELLO\' failed' in ''.join(output)
diff --git a/test/py/tests/test_log.py b/test/py/tests/test_log.py
index f889120..140dcb9 100644
--- a/test/py/tests/test_log.py
+++ b/test/py/tests/test_log.py
@@ -45,5 +45,4 @@
     cons = u_boot_console
     cons.restart_uboot()
     output = cons.get_spawn_output().replace('\r', '')
-    assert 'sandbox: starting...' in output
     assert (not 'debug: main' in output)
diff --git a/test/py/tests/test_ofplatdata.py b/test/py/tests/test_ofplatdata.py
index 92d09b7..e9cce4d 100644
--- a/test/py/tests/test_ofplatdata.py
+++ b/test/py/tests/test_ofplatdata.py
@@ -4,7 +4,7 @@
 import pytest
 import u_boot_utils as util
 
-@pytest.mark.boardspec('sandbox')
+@pytest.mark.boardspec('sandbox_spl')
 @pytest.mark.buildconfigspec('spl_of_platdata')
 def test_spl_devicetree(u_boot_console):
     """Test content of spl device-tree"""
diff --git a/test/py/tests/test_scp03.py b/test/py/tests/test_scp03.py
new file mode 100644
index 0000000..1f68925
--- /dev/null
+++ b/test/py/tests/test_scp03.py
@@ -0,0 +1,27 @@
+# Copyright (c) 2021 Foundries.io Ltd
+#
+# SPDX-License-Identifier:  GPL-2.0+
+#
+# SCP03 command test
+
+"""
+This tests SCP03 command in U-boot.
+
+For additional details check doc/usage/scp03.rst
+"""
+
+import pytest
+import u_boot_utils as util
+
+@pytest.mark.buildconfigspec('cmd_scp03')
+def test_scp03(u_boot_console):
+    """Enable and provision keys with SCP03
+    """
+
+    success_str1 = "SCP03 is enabled"
+    success_str2 = "SCP03 is provisioned"
+
+    response = u_boot_console.run_command('scp03 enable')
+    assert success_str1 in response
+    response = u_boot_console.run_command('scp03 provision')
+    assert success_str2 in response
diff --git a/test/run b/test/run
index 735628e..869406c 100755
--- a/test/run
+++ b/test/run
@@ -30,6 +30,10 @@
 run_test "sandbox_spl" ./test/py/test.py --bd sandbox_spl --build \
 		-k 'test_ofplatdata or test_handoff or test_spl'
 
+# Run the sane tests with sandbox_noinst (i.e. without OF_PLATDATA_INST)
+run_test "sandbox_spl" ./test/py/test.py --bd sandbox_noinst --build \
+		-k 'test_ofplatdata or test_handoff or test_spl'
+
 if [ -z "$tools_only" ]; then
 	# Run tests for the flat-device-tree version of sandbox. This is a special
 	# build which does not enable CONFIG_OF_LIVE for the live device tree, so we can
diff --git a/test/str_ut.c b/test/str_ut.c
index cd50455..359d7d4 100644
--- a/test/str_ut.c
+++ b/test/str_ut.c
@@ -107,9 +107,8 @@
 
 int do_ut_str(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-	struct unit_test *tests = ll_entry_start(struct unit_test,
-						 str_test);
-	const int n_ents = ll_entry_count(struct unit_test, str_test);
+	struct unit_test *tests = UNIT_TEST_SUITE_START(str_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(str_test);
 
 	return cmd_ut_category("str", "str_", tests, n_ents, argc, argv);
 }
diff --git a/test/test-main.c b/test/test-main.c
new file mode 100644
index 0000000..8c852d7
--- /dev/null
+++ b/test/test-main.c
@@ -0,0 +1,433 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <console.h>
+#include <dm.h>
+#include <dm/root.h>
+#include <dm/test.h>
+#include <dm/uclass-internal.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* This is valid when a test is running, NULL otherwise */
+static struct unit_test_state *cur_test_state;
+
+struct unit_test_state *test_get_state(void)
+{
+	return cur_test_state;
+}
+
+void test_set_state(struct unit_test_state *uts)
+{
+	cur_test_state = uts;
+}
+
+/**
+ * dm_test_pre_run() - Get ready to run a driver model test
+ *
+ * This clears out the driver model data structures. For sandbox it resets the
+ * state structure
+ *
+ * @uts: Test state
+ */
+static int dm_test_pre_run(struct unit_test_state *uts)
+{
+	bool of_live = uts->of_live;
+
+	uts->root = NULL;
+	uts->testdev = NULL;
+	uts->force_fail_alloc = false;
+	uts->skip_post_probe = false;
+	gd->dm_root = NULL;
+	if (IS_ENABLED(CONFIG_UT_DM) && !CONFIG_IS_ENABLED(OF_PLATDATA))
+		memset(dm_testdrv_op_count, '\0', sizeof(dm_testdrv_op_count));
+	arch_reset_for_test();
+
+	/* Determine whether to make the live tree available */
+	gd_set_of_root(of_live ? uts->of_root : NULL);
+	ut_assertok(dm_init(of_live));
+	uts->root = dm_root();
+
+	return 0;
+}
+
+static int dm_test_post_run(struct unit_test_state *uts)
+{
+	int id;
+
+	/*
+	 * With of-platdata-inst the uclasses are created at build time. If we
+	 * destroy them we cannot get them back since uclass_add() is not
+	 * supported. So skip this.
+	 */
+	if (!CONFIG_IS_ENABLED(OF_PLATDATA_INST)) {
+		for (id = 0; id < UCLASS_COUNT; id++) {
+			struct uclass *uc;
+
+			/*
+			 * If the uclass doesn't exist we don't want to create
+			 * it. So check that here before we call
+			 * uclass_find_device().
+			 */
+			uc = uclass_find(id);
+			if (!uc)
+				continue;
+			ut_assertok(uclass_destroy(uc));
+		}
+	}
+
+	return 0;
+}
+
+/* Ensure all the test devices are probed */
+static int do_autoprobe(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	int ret;
+
+	/* Scanning the uclass is enough to probe all the devices */
+	for (ret = uclass_first_device(UCLASS_TEST, &dev);
+	     dev;
+	     ret = uclass_next_device(&dev))
+		;
+
+	return ret;
+}
+
+/*
+ * ut_test_run_on_flattree() - Check if we should run a test with flat DT
+ *
+ * This skips long/slow tests where there is not much value in running a flat
+ * DT test in addition to a live DT test.
+ *
+ * @return true to run the given test on the flat device tree
+ */
+static bool ut_test_run_on_flattree(struct unit_test *test)
+{
+	const char *fname = strrchr(test->file, '/') + 1;
+
+	if (!(test->flags & UT_TESTF_DM))
+		return false;
+
+	return !strstr(fname, "video") || strstr(test->name, "video_base");
+}
+
+/**
+ * test_matches() - Check if a test should be run
+ *
+ * This checks if the a test should be run. In the normal case of running all
+ * tests, @select_name is NULL.
+ *
+ * @prefix: String prefix for the tests. Any tests that have this prefix will be
+ *	printed without the prefix, so that it is easier to see the unique part
+ *	of the test name. If NULL, any suite name (xxx_test) is considered to be
+ *	a prefix.
+ * @test_name: Name of current test
+ * @select_name: Name of test to run (or NULL for all)
+ * @return true to run this test, false to skip it
+ */
+static bool test_matches(const char *prefix, const char *test_name,
+			 const char *select_name)
+{
+	if (!select_name)
+		return true;
+
+	if (!strcmp(test_name, select_name))
+		return true;
+
+	if (!prefix) {
+		const char *p = strstr(test_name, "_test_");
+
+		/* convert xxx_test_yyy to yyy, i.e. remove the suite name */
+		if (p)
+			test_name = p + 6;
+	} else {
+		/* All tests have this prefix */
+		if (!strncmp(test_name, prefix, strlen(prefix)))
+			test_name += strlen(prefix);
+	}
+
+	if (!strcmp(test_name, select_name))
+		return true;
+
+	return false;
+}
+
+/**
+ * ut_list_has_dm_tests() - Check if a list of tests has driver model ones
+ *
+ * @tests: List of tests to run
+ * @count: Number of tests to ru
+ * @return true if any of the tests have the UT_TESTF_DM flag
+ */
+static bool ut_list_has_dm_tests(struct unit_test *tests, int count)
+{
+	struct unit_test *test;
+
+	for (test = tests; test < tests + count; test++) {
+		if (test->flags & UT_TESTF_DM)
+			return true;
+	}
+
+	return false;
+}
+
+/**
+ * dm_test_restore() Put things back to normal so sandbox works as expected
+ *
+ * @of_root: Value to set for of_root
+ * @return 0 if OK, -ve on error
+ */
+static int dm_test_restore(struct device_node *of_root)
+{
+	int ret;
+
+	gd_set_of_root(of_root);
+	gd->dm_root = NULL;
+	ret = dm_init(CONFIG_IS_ENABLED(OF_LIVE));
+	if (ret)
+		return ret;
+	dm_scan_plat(false);
+	if (!CONFIG_IS_ENABLED(OF_PLATDATA))
+		dm_scan_fdt(false);
+
+	return 0;
+}
+
+/**
+ * test_pre_run() - Handle any preparation needed to run a test
+ *
+ * @uts: Test state
+ * @test: Test to prepare for
+ * @return 0 if OK, -EAGAIN to skip this test since some required feature is not
+ *	available, other -ve on error (meaning that testing cannot likely
+ *	continue)
+ */
+static int test_pre_run(struct unit_test_state *uts, struct unit_test *test)
+{
+	if (test->flags & UT_TESTF_DM)
+		ut_assertok(dm_test_pre_run(uts));
+
+	ut_set_skip_delays(uts, false);
+
+	uts->start = mallinfo();
+
+	if (test->flags & UT_TESTF_SCAN_PDATA)
+		ut_assertok(dm_scan_plat(false));
+
+	if (test->flags & UT_TESTF_PROBE_TEST)
+		ut_assertok(do_autoprobe(uts));
+
+	if (!CONFIG_IS_ENABLED(OF_PLATDATA) &&
+	    (test->flags & UT_TESTF_SCAN_FDT))
+		ut_assertok(dm_extended_scan(false));
+
+	if (test->flags & UT_TESTF_CONSOLE_REC) {
+		int ret = console_record_reset_enable();
+
+		if (ret) {
+			printf("Skipping: Console recording disabled\n");
+			return -EAGAIN;
+		}
+	}
+	ut_silence_console(uts);
+
+	return 0;
+}
+
+/**
+ * test_post_run() - Handle cleaning up after a test
+ *
+ * @uts: Test state
+ * @test: Test to clean up after
+ * @return 0 if OK, -ve on error (meaning that testing cannot likely continue)
+ */
+static int test_post_run(struct unit_test_state *uts, struct unit_test *test)
+{
+	ut_unsilence_console(uts);
+	if (test->flags & UT_TESTF_DM)
+		ut_assertok(dm_test_post_run(uts));
+
+	return 0;
+}
+
+/**
+ * ut_run_test() - Run a single test
+ *
+ * This runs the test, handling any preparation and clean-up needed. It prints
+ * the name of each test before running it.
+ *
+ * @uts: Test state to update. The caller should ensure that this is zeroed for
+ *	the first call to this function. On exit, @uts->fail_count is
+ *	incremented by the number of failures (0, one hopes)
+ * @test_name: Test to run
+ * @name: Name of test, possibly skipping a prefix that should not be displayed
+ * @return 0 if all tests passed, -EAGAIN if the test should be skipped, -1 if
+ *	any failed
+ */
+static int ut_run_test(struct unit_test_state *uts, struct unit_test *test,
+		       const char *test_name)
+{
+	const char *fname = strrchr(test->file, '/') + 1;
+	const char *note = "";
+	int ret;
+
+	if ((test->flags & UT_TESTF_DM) && !uts->of_live)
+		note = " (flat tree)";
+	printf("Test: %s: %s%s\n", test_name, fname, note);
+
+	/* Allow access to test state from drivers */
+	test_set_state(uts);
+
+	ret = test_pre_run(uts, test);
+	if (ret == -EAGAIN)
+		return -EAGAIN;
+	if (ret)
+		return ret;
+
+	test->func(uts);
+
+	ret = test_post_run(uts, test);
+	if (ret)
+		return ret;
+
+	test_set_state( NULL);
+
+	return 0;
+}
+
+/**
+ * ut_run_test_live_flat() - Run a test with both live and flat tree
+ *
+ * This calls ut_run_test() with livetree enabled, which is the standard setup
+ * for runnig tests. Then, for driver model test, it calls it again with
+ * livetree disabled. This allows checking of flattree being used when OF_LIVE
+ * is enabled, as is the case in U-Boot proper before relocation, as well as in
+ * SPL.
+ *
+ * @uts: Test state to update. The caller should ensure that this is zeroed for
+ *	the first call to this function. On exit, @uts->fail_count is
+ *	incremented by the number of failures (0, one hopes)
+ * @test: Test to run
+ * @name: Name of test, possibly skipping a prefix that should not be displayed
+ * @return 0 if all tests passed, -EAGAIN if the test should be skipped, -1 if
+ *	any failed
+ */
+static int ut_run_test_live_flat(struct unit_test_state *uts,
+				 struct unit_test *test, const char *name)
+{
+	int runs;
+
+	/* Run with the live tree if possible */
+	runs = 0;
+	if (CONFIG_IS_ENABLED(OF_LIVE)) {
+		if (!(test->flags & UT_TESTF_FLAT_TREE)) {
+			uts->of_live = true;
+			ut_assertok(ut_run_test(uts, test, test->name));
+			runs++;
+		}
+	}
+
+	/*
+	 * Run with the flat tree if we couldn't run it with live tree,
+	 * or it is a core test.
+	 */
+	if (!(test->flags & UT_TESTF_LIVE_TREE) &&
+	    (!runs || ut_test_run_on_flattree(test))) {
+		uts->of_live = false;
+		ut_assertok(ut_run_test(uts, test, test->name));
+		runs++;
+	}
+
+	return 0;
+}
+
+/**
+ * ut_run_tests() - Run a set of tests
+ *
+ * This runs the tests, handling any preparation and clean-up needed. It prints
+ * the name of each test before running it.
+ *
+ * @uts: Test state to update. The caller should ensure that this is zeroed for
+ *	the first call to this function. On exit, @uts->fail_count is
+ *	incremented by the number of failures (0, one hopes)
+ * @prefix: String prefix for the tests. Any tests that have this prefix will be
+ *	printed without the prefix, so that it is easier to see the unique part
+ *	of the test name. If NULL, no prefix processing is done
+ * @tests: List of tests to run
+ * @count: Number of tests to run
+ * @select_name: Name of a single test to run (from the list provided). If NULL
+ *	then all tests are run
+ * @return 0 if all tests passed, -ENOENT if test @select_name was not found,
+ *	-EBADF if any failed
+ */
+static int ut_run_tests(struct unit_test_state *uts, const char *prefix,
+			struct unit_test *tests, int count,
+			const char *select_name)
+{
+	struct unit_test *test;
+	int found = 0;
+
+	for (test = tests; test < tests + count; test++) {
+		const char *test_name = test->name;
+		int ret;
+
+		if (!test_matches(prefix, test_name, select_name))
+			continue;
+		ret = ut_run_test_live_flat(uts, test, select_name);
+		found++;
+		if (ret == -EAGAIN)
+			continue;
+		if (ret)
+			return ret;
+	}
+	if (select_name && !found)
+		return -ENOENT;
+
+	return uts->fail_count ? -EBADF : 0;
+}
+
+int ut_run_list(const char *category, const char *prefix,
+		struct unit_test *tests, int count, const char *select_name)
+{
+	struct unit_test_state uts = { .fail_count = 0 };
+	bool has_dm_tests = false;
+	int ret;
+
+	if (!CONFIG_IS_ENABLED(OF_PLATDATA) &&
+	    ut_list_has_dm_tests(tests, count)) {
+		has_dm_tests = true;
+		/*
+		 * If we have no device tree, or it only has a root node, then
+		 * these * tests clearly aren't going to work...
+		 */
+		if (!gd->fdt_blob || fdt_next_node(gd->fdt_blob, 0, NULL) < 0) {
+			puts("Please run with test device tree:\n"
+			     "    ./u-boot -d arch/sandbox/dts/test.dtb\n");
+			return CMD_RET_FAILURE;
+		}
+	}
+
+	if (!select_name)
+		printf("Running %d %s tests\n", count, category);
+
+	uts.of_root = gd_of_root();
+	ret = ut_run_tests(&uts, prefix, tests, count, select_name);
+
+	if (ret == -ENOENT)
+		printf("Test '%s' not found\n", select_name);
+	else
+		printf("Failures: %d\n", uts.fail_count);
+
+	/* Best efforts only...ignore errors */
+	if (has_dm_tests)
+		dm_test_restore(uts.of_root);
+
+	return ret;
+}
diff --git a/test/unicode_ut.c b/test/unicode_ut.c
index 6f6aea5..617eed8 100644
--- a/test/unicode_ut.c
+++ b/test/unicode_ut.c
@@ -729,8 +729,8 @@
 
 int do_ut_unicode(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-	struct unit_test *tests = ll_entry_start(struct unit_test, unicode_test);
-	const int n_ents = ll_entry_count(struct unit_test, unicode_test);
+	struct unit_test *tests = UNIT_TEST_SUITE_START(unicode_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(unicode_test);
 
 	return cmd_ut_category("Unicode", "unicode_test_",
 			       tests, n_ents, argc, argv);
diff --git a/test/ut.c b/test/ut.c
index 7328338..ea0af15 100644
--- a/test/ut.c
+++ b/test/ut.c
@@ -133,3 +133,10 @@
 {
 	gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
 }
+
+void ut_set_skip_delays(struct unit_test_state *uts, bool skip_delays)
+{
+#ifdef CONFIG_SANDBOX
+	state_set_skip_delays(skip_delays);
+#endif
+}
diff --git a/tools/binman/README.rst b/tools/binman/README.rst
new file mode 120000
index 0000000..b734f54
--- /dev/null
+++ b/tools/binman/README.rst
@@ -0,0 +1 @@
+binman.rst
\ No newline at end of file
diff --git a/tools/binman/README b/tools/binman/binman.rst
similarity index 62%
rename from tools/binman/README
rename to tools/binman/binman.rst
index a00c902..1aa2459 100644
--- a/tools/binman/README
+++ b/tools/binman/binman.rst
@@ -1,47 +1,51 @@
-# SPDX-License-Identifier: GPL-2.0+
-# Copyright (c) 2016 Google, Inc
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright (c) 2016 Google, Inc
 
 Introduction
-------------
+============
 
 Firmware often consists of several components which must be packaged together.
 For example, we may have SPL, U-Boot, a device tree and an environment area
 grouped together and placed in MMC flash. When the system starts, it must be
 able to find these pieces.
 
-So far U-Boot has not provided a way to handle creating such images in a
-general way. Each SoC does what it needs to build an image, often packing or
-concatenating images in the U-Boot build system.
-
-Binman aims to provide a mechanism for building images, from simple
-SPL + U-Boot combinations, to more complex arrangements with many parts.
+Building firmware should be separate from packaging it. Many of the complexities
+of modern firmware build systems come from trying to do both at once. With
+binman, you build all the pieces that are needed, using whatever assortment of
+projects and build systems are needed, then use binman to stitch everything
+together.
 
 
 What it does
 ------------
 
 Binman reads your board's device tree and finds a node which describes the
-required image layout. It uses this to work out what to place where. The
-output file normally contains the device tree, so it is in principle possible
-to read an image and extract its constituent parts.
+required image layout. It uses this to work out what to place where.
+
+Binman provides a mechanism for building images, from simple SPL + U-Boot
+combinations, to more complex arrangements with many parts. It also allows
+users to inspect images, extract and replace binaries within them, repacking if
+needed.
 
 
 Features
 --------
 
-So far binman is pretty simple. It supports binary blobs, such as 'u-boot',
-'spl' and 'fdt'. It supports empty entries (such as setting to 0xff). It can
-place entries at a fixed location in the image, or fit them together with
-suitable padding and alignment. It provides a way to process binaries before
-they are included, by adding a Python plug-in. The device tree is available
-to U-Boot at run-time so that the images can be interpreted.
+Apart from basic padding, alignment and positioning features, Binman supports
+hierarchical images, compression, hashing and dealing with the binary blobs
+which are a sad trend in open-source firmware at present.
 
-Binman can update the device tree with the final location of everything when it
-is done. Entry positions can be provided to U-Boot SPL as run-time symbols,
-avoiding device-tree code overhead.
+Executable binaries can access the location of other binaries in an image by
+using special linker symbols (zero-overhead but somewhat limited) or by reading
+the devicetree description of the image.
 
-Binman can also support incorporating filesystems in the image if required.
-For example x86 platforms may use CBFS in some cases.
+Binman is designed primarily for use with U-Boot and associated binaries such
+as ARM Trusted Firmware, but it is suitable for use with other projects, such
+as Zephyr. Binman also provides facilities useful in Chromium OS, such as CBFS,
+vblocks and and the like.
+
+Binman provides a way to process binaries before they are included, by adding a
+Python plug-in.
 
 Binman is intended for use with U-Boot but is designed to be general enough
 to be useful in other image-packaging situations.
@@ -50,11 +54,11 @@
 Motivation
 ----------
 
-Packaging of firmware is quite a different task from building the various
-parts. In many cases the various binaries which go into the image come from
-separate build systems. For example, ARM Trusted Firmware is used on ARMv8
-devices but is not built in the U-Boot tree. If a Linux kernel is included
-in the firmware image, it is built elsewhere.
+As mentioned above, packaging of firmware is quite a different task from
+building the various parts. In many cases the various binaries which go into
+the image come from separate build systems. For example, ARM Trusted Firmware
+is used on ARMv8 devices but is not built in the U-Boot tree. If a Linux kernel
+is included in the firmware image, it is built elsewhere.
 
 It is of course possible to add more and more build rules to the U-Boot
 build system to cover these cases. It can shell out to other Makefiles and
@@ -67,18 +71,19 @@
 manual effort, lots of READMEs, etc.
 
 Benefits:
-- Each binary can have its own build system and tool chain without creating
-any dependencies between them
-- Avoids the need for a single-shot build: individual parts can be updated
-and brought in as needed
-- Provides for a standard image description available in the build and at
-run-time
-- SoC-specific image-signing tools can be accommodated
-- Avoids cluttering the U-Boot build system with image-building code
-- The image description is automatically available at run-time in U-Boot,
-SPL. It can be made available to other software also
-- The image description is easily readable (it's a text file in device-tree
-format) and permits flexible packing of binaries
+
+  - Each binary can have its own build system and tool chain without creating
+    any dependencies between them
+  - Avoids the need for a single-shot build: individual parts can be updated
+    and brought in as needed
+  - Provides for a standard image description available in the build and at
+    run-time
+  - SoC-specific image-signing tools can be accommodated
+  - Avoids cluttering the U-Boot build system with image-building code
+  - The image description is automatically available at run-time in U-Boot,
+    SPL. It can be made available to other software also
+  - The image description is easily readable (it's a text file in device-tree
+    format) and permits flexible packing of binaries
 
 
 Terminology
@@ -136,6 +141,9 @@
 into a final image (binman).
 
 
+Using binman
+============
+
 Example use of binman in U-Boot
 -------------------------------
 
@@ -144,14 +152,14 @@
 
 Consider sunxi. It has the following steps:
 
-1. It uses a custom mksunxiboot tool to build an SPL image called
-sunxi-spl.bin. This should probably move into mkimage.
+  #. It uses a custom mksunxiboot tool to build an SPL image called
+     sunxi-spl.bin. This should probably move into mkimage.
 
-2. It uses mkimage to package U-Boot into a legacy image file (so that it can
-hold the load and execution address) called u-boot.img.
+  #. It uses mkimage to package U-Boot into a legacy image file (so that it can
+     hold the load and execution address) called u-boot.img.
 
-3. It builds a final output image called u-boot-sunxi-with-spl.bin which
-consists of sunxi-spl.bin, some padding and u-boot.img.
+  #. It builds a final output image called u-boot-sunxi-with-spl.bin which
+     consists of sunxi-spl.bin, some padding and u-boot.img.
 
 Binman is intended to replace the last step. The U-Boot build system builds
 u-boot.bin and sunxi-spl.bin. Binman can then take over creation of
@@ -180,22 +188,22 @@
 Running binman
 --------------
 
-First install prerequisites, e.g.
+First install prerequisites, e.g::
 
-	sudo apt-get install python-pyelftools python3-pyelftools lzma-alone \
-		liblz4-tool
+    sudo apt-get install python-pyelftools python3-pyelftools lzma-alone \
+        liblz4-tool
 
-Type:
+Type::
 
-	binman build -b <board_name>
+    binman build -b <board_name>
 
 to build an image for a board. The board name is the same name used when
 configuring U-Boot (e.g. for sandbox_defconfig the board name is 'sandbox').
 Binman assumes that the input files for the build are in ../b/<board_name>.
 
-Or you can specify this explicitly:
+Or you can specify this explicitly::
 
-	binman build -I <build_path>
+    binman build -I <build_path>
 
 where <build_path> is the build directory containing the output of the U-Boot
 build.
@@ -211,17 +219,12 @@
 Enabling binman for a board
 ---------------------------
 
-At present binman is invoked from a rule in the main Makefile. Typically you
-will have a rule like:
+At present binman is invoked from a rule in the main Makefile. You should be
+able to enable CONFIG_BINMAN to enable this rule.
 
-ifneq ($(CONFIG_ARCH_<something>),)
-u-boot-<your_suffix>.bin: <input_file_1> <input_file_2> checkbinman FORCE
-	$(call if_changed,binman)
-endif
-
-This assumes that u-boot-<your_suffix>.bin is a target, and is the final file
-that you need to produce. You can make it a target by adding it to INPUTS-y
-either in the main Makefile or in a config.mk file in your arch subdirectory.
+The output file is typically named image.bin and is located in the output
+directory. If input files are needed to you add these to INPUTS-y either in the
+main Makefile or in a config.mk file in your arch subdirectory.
 
 Once binman is executed it will pick up its instructions from a device-tree
 file, typically <soc>-u-boot.dtsi, where <soc> is your CONFIG_SYS_SOC value.
@@ -229,22 +232,125 @@
 inclusion' below.
 
 
+Access to binman entry offsets at run time (symbols)
+----------------------------------------------------
+
+Binman assembles images and determines where each entry is placed in the image.
+This information may be useful to U-Boot at run time. For example, in SPL it
+is useful to be able to find the location of U-Boot so that it can be executed
+when SPL is finished.
+
+Binman allows you to declare symbols in the SPL image which are filled in
+with their correct values during the build. For example::
+
+    binman_sym_declare(ulong, u_boot_any, image_pos);
+
+declares a ulong value which will be assigned to the image-pos of any U-Boot
+image (u-boot.bin, u-boot.img, u-boot-nodtb.bin) that is present in the image.
+You can access this value with something like::
+
+    ulong u_boot_offset = binman_sym(ulong, u_boot_any, image_pos);
+
+Thus u_boot_offset will be set to the image-pos of U-Boot in memory, assuming
+that the whole image has been loaded, or is available in flash. You can then
+jump to that address to start U-Boot.
+
+At present this feature is only supported in SPL and TPL. In principle it is
+possible to fill in such symbols in U-Boot proper, as well, but a future C
+library is planned for this instead, to read from the device tree.
+
+As well as image-pos, it is possible to read the size of an entry and its
+offset (which is the start position of the entry within its parent).
+
+A small technical note: Binman automatically adds the base address of the image
+(i.e. __image_copy_start) to the value of the image-pos symbol, so that when the
+image is loaded to its linked address, the value will be correct and actually
+point into the image.
+
+For example, say SPL is at the start of the image and linked to start at address
+80108000. If U-Boot's image-pos is 0x8000 then binman will write an image-pos
+for U-Boot of 80110000 into the SPL binary, since it assumes the image is loaded
+to 80108000, with SPL at 80108000 and U-Boot at 80110000.
+
+For x86 devices (with the end-at-4gb property) this base address is not added
+since it is assumed that images are XIP and the offsets already include the
+address.
+
+
+Access to binman entry offsets at run time (fdt)
+------------------------------------------------
+
+Binman can update the U-Boot FDT to include the final position and size of
+each entry in the images it processes. The option to enable this is -u and it
+causes binman to make sure that the 'offset', 'image-pos' and 'size' properties
+are set correctly for every entry. Since it is not necessary to specify these in
+the image definition, binman calculates the final values and writes these to
+the device tree. These can be used by U-Boot at run-time to find the location
+of each entry.
+
+Alternatively, an FDT map entry can be used to add a special FDT containing
+just the information about the image. This is preceded by a magic string so can
+be located anywhere in the image. An image header (typically at the start or end
+of the image) can be used to point to the FDT map. See fdtmap and image-header
+entries for more information.
+
+
+Map files
+---------
+
+The -m option causes binman to output a .map file for each image that it
+generates. This shows the offset and size of each entry. For example::
+
+      Offset      Size  Name
+    00000000  00000028  main-section
+     00000000  00000010  section@0
+      00000000  00000004  u-boot
+     00000010  00000010  section@1
+      00000000  00000004  u-boot
+
+This shows a hierarchical image with two sections, each with a single entry. The
+offsets of the sections are absolute hex byte offsets within the image. The
+offsets of the entries are relative to their respective sections. The size of
+each entry is also shown, in bytes (hex). The indentation shows the entries
+nested inside their sections.
+
+
+Passing command-line arguments to entries
+-----------------------------------------
+
+Sometimes it is useful to pass binman the value of an entry property from the
+command line. For example some entries need access to files and it is not
+always convenient to put these filenames in the image definition (device tree).
+
+The-a option supports this::
+
+    -a<prop>=<value>
+
+where::
+
+    <prop> is the property to set
+    <value> is the value to set it to
+
+Not all properties can be provided this way. Only some entries support it,
+typically for filenames.
+
+
 Image description format
-------------------------
+========================
 
 The binman node is called 'binman'. An example image description is shown
-below:
+below::
 
-	binman {
-		filename = "u-boot-sunxi-with-spl.bin";
-		pad-byte = <0xff>;
-		blob {
-			filename = "spl/sunxi-spl.bin";
-		};
-		u-boot {
-			offset = <CONFIG_SPL_PAD_TO>;
-		};
-	};
+    binman {
+        filename = "u-boot-sunxi-with-spl.bin";
+        pad-byte = <0xff>;
+        blob {
+            filename = "spl/sunxi-spl.bin";
+        };
+        u-boot {
+            offset = <CONFIG_SPL_PAD_TO>;
+        };
+    };
 
 
 This requests binman to create an image file called u-boot-sunxi-with-spl.bin
@@ -270,184 +376,198 @@
 The attributes supported for entries are described below.
 
 offset:
-	This sets the offset of an entry within the image or section containing
-	it. The first byte of the image is normally at offset 0. If 'offset' is
-	not provided, binman sets it to the end of the previous region, or the
-	start of the image's entry area (normally 0) if there is no previous
-	region.
+    This sets the offset of an entry within the image or section containing
+    it. The first byte of the image is normally at offset 0. If 'offset' is
+    not provided, binman sets it to the end of the previous region, or the
+    start of the image's entry area (normally 0) if there is no previous
+    region.
 
 align:
-	This sets the alignment of the entry. The entry offset is adjusted
-	so that the entry starts on an aligned boundary within the containing
-	section or image. For example 'align = <16>' means that the entry will
-	start on a 16-byte boundary. This may mean that padding is added before
-	the entry. The padding is part of the containing section but is not
-	included in the entry, meaning that an empty space may be created before
-	the entry starts. Alignment should be a power of 2. If 'align' is not
-	provided, no alignment is performed.
+    This sets the alignment of the entry. The entry offset is adjusted
+    so that the entry starts on an aligned boundary within the containing
+    section or image. For example 'align = <16>' means that the entry will
+    start on a 16-byte boundary. This may mean that padding is added before
+    the entry. The padding is part of the containing section but is not
+    included in the entry, meaning that an empty space may be created before
+    the entry starts. Alignment should be a power of 2. If 'align' is not
+    provided, no alignment is performed.
 
 size:
-	This sets the size of the entry. The contents will be padded out to
-	this size. If this is not provided, it will be set to the size of the
-	contents.
+    This sets the size of the entry. The contents will be padded out to
+    this size. If this is not provided, it will be set to the size of the
+    contents.
 
 pad-before:
-	Padding before the contents of the entry. Normally this is 0, meaning
-	that the contents start at the beginning of the entry. This can be used
-	to offset the entry contents a little. While this does not affect the
-	contents of the entry within binman itself (the padding is performed
-	only when its parent section is assembled), the end result will be that
-	the entry starts with the padding bytes, so may grow. Defaults to 0.
+    Padding before the contents of the entry. Normally this is 0, meaning
+    that the contents start at the beginning of the entry. This can be used
+    to offset the entry contents a little. While this does not affect the
+    contents of the entry within binman itself (the padding is performed
+    only when its parent section is assembled), the end result will be that
+    the entry starts with the padding bytes, so may grow. Defaults to 0.
 
 pad-after:
-	Padding after the contents of the entry. Normally this is 0, meaning
-	that the entry ends at the last byte of content (unless adjusted by
-	other properties). This allows room to be created in the image for
-	this entry to expand later. While this does not affect the contents of
-	the entry within binman itself (the padding is performed only when its
-	parent section is assembled), the end result will be that the entry ends
-	with the padding bytes, so may grow. Defaults to 0.
+    Padding after the contents of the entry. Normally this is 0, meaning
+    that the entry ends at the last byte of content (unless adjusted by
+    other properties). This allows room to be created in the image for
+    this entry to expand later. While this does not affect the contents of
+    the entry within binman itself (the padding is performed only when its
+    parent section is assembled), the end result will be that the entry ends
+    with the padding bytes, so may grow. Defaults to 0.
 
 align-size:
-	This sets the alignment of the entry size. For example, to ensure
-	that the size of an entry is a multiple of 64 bytes, set this to 64.
-	While this does not affect the contents of the entry within binman
-	itself (the padding is performed only when its parent section is
-	assembled), the end result is that the entry ends with the padding
-	bytes, so may grow. If 'align-size' is not provided, no alignment is
-	performed.
+    This sets the alignment of the entry size. For example, to ensure
+    that the size of an entry is a multiple of 64 bytes, set this to 64.
+    While this does not affect the contents of the entry within binman
+    itself (the padding is performed only when its parent section is
+    assembled), the end result is that the entry ends with the padding
+    bytes, so may grow. If 'align-size' is not provided, no alignment is
+    performed.
 
 align-end:
-	This sets the alignment of the end of an entry with respect to the
-	containing section. Some entries require that they end on an alignment
-	boundary, regardless of where they start. This does not move the start
-	of the entry, so the contents of the entry will still start at the
-	beginning. But there may be padding at the end. While this does not
-	affect the contents of the entry within binman itself (the padding is
-	performed only when its parent section is assembled), the end result
-	is that the entry ends with the padding bytes, so may grow.
-	If 'align-end' is not provided, no alignment is performed.
+    This sets the alignment of the end of an entry with respect to the
+    containing section. Some entries require that they end on an alignment
+    boundary, regardless of where they start. This does not move the start
+    of the entry, so the contents of the entry will still start at the
+    beginning. But there may be padding at the end. While this does not
+    affect the contents of the entry within binman itself (the padding is
+    performed only when its parent section is assembled), the end result
+    is that the entry ends with the padding bytes, so may grow.
+    If 'align-end' is not provided, no alignment is performed.
 
 filename:
-	For 'blob' types this provides the filename containing the binary to
-	put into the entry. If binman knows about the entry type (like
-	u-boot-bin), then there is no need to specify this.
+    For 'blob' types this provides the filename containing the binary to
+    put into the entry. If binman knows about the entry type (like
+    u-boot-bin), then there is no need to specify this.
 
 type:
-	Sets the type of an entry. This defaults to the entry name, but it is
-	possible to use any name, and then add (for example) 'type = "u-boot"'
-	to specify the type.
+    Sets the type of an entry. This defaults to the entry name, but it is
+    possible to use any name, and then add (for example) 'type = "u-boot"'
+    to specify the type.
 
 offset-unset:
-	Indicates that the offset of this entry should not be set by placing
-	it immediately after the entry before. Instead, is set by another
-	entry which knows where this entry should go. When this boolean
-	property is present, binman will give an error if another entry does
-	not set the offset (with the GetOffsets() method).
+    Indicates that the offset of this entry should not be set by placing
+    it immediately after the entry before. Instead, is set by another
+    entry which knows where this entry should go. When this boolean
+    property is present, binman will give an error if another entry does
+    not set the offset (with the GetOffsets() method).
 
 image-pos:
-	This cannot be set on entry (or at least it is ignored if it is), but
-	with the -u option, binman will set it to the absolute image position
-	for each entry. This makes it easy to find out exactly where the entry
-	ended up in the image, regardless of parent sections, etc.
+    This cannot be set on entry (or at least it is ignored if it is), but
+    with the -u option, binman will set it to the absolute image position
+    for each entry. This makes it easy to find out exactly where the entry
+    ended up in the image, regardless of parent sections, etc.
 
 expand-size:
-	Expand the size of this entry to fit available space. This space is only
-	limited by the size of the image/section and the position of the next
-	entry.
+    Expand the size of this entry to fit available space. This space is only
+    limited by the size of the image/section and the position of the next
+    entry.
 
 compress:
-	Sets the compression algortihm to use (for blobs only). See the entry
-	documentation for details.
+    Sets the compression algortihm to use (for blobs only). See the entry
+    documentation for details.
 
 missing-msg:
-	Sets the tag of the message to show if this entry is missing. This is
-	used for external blobs. When they are missing it is helpful to show
-	information about what needs to be fixed. See missing-blob-help for the
-	message for each tag.
+    Sets the tag of the message to show if this entry is missing. This is
+    used for external blobs. When they are missing it is helpful to show
+    information about what needs to be fixed. See missing-blob-help for the
+    message for each tag.
+
+no-expanded:
+    By default binman substitutes entries with expanded versions if available,
+    so that a `u-boot` entry type turns into `u-boot-expanded`, for example. The
+    `--no-expanded` command-line option disables this globally. The
+    `no-expanded` property disables this just for a single entry. Put the
+    `no-expanded` boolean property in the node to select this behaviour.
 
 The attributes supported for images and sections are described below. Several
 are similar to those for entries.
 
 size:
-	Sets the image size in bytes, for example 'size = <0x100000>' for a
-	1MB image.
+    Sets the image size in bytes, for example 'size = <0x100000>' for a
+    1MB image.
 
 offset:
-	This is similar to 'offset' in entries, setting the offset of a section
-	within the image or section containing it. The first byte of the section
-	is normally at offset 0. If 'offset' is not provided, binman sets it to
-	the end of the previous region, or the start of the image's entry area
-	(normally 0) if there is no previous region.
+    This is similar to 'offset' in entries, setting the offset of a section
+    within the image or section containing it. The first byte of the section
+    is normally at offset 0. If 'offset' is not provided, binman sets it to
+    the end of the previous region, or the start of the image's entry area
+    (normally 0) if there is no previous region.
 
 align-size:
-	This sets the alignment of the image size. For example, to ensure
-	that the image ends on a 512-byte boundary, use 'align-size = <512>'.
-	If 'align-size' is not provided, no alignment is performed.
+    This sets the alignment of the image size. For example, to ensure
+    that the image ends on a 512-byte boundary, use 'align-size = <512>'.
+    If 'align-size' is not provided, no alignment is performed.
 
 pad-before:
-	This sets the padding before the image entries. The first entry will
-	be positioned after the padding. This defaults to 0.
+    This sets the padding before the image entries. The first entry will
+    be positioned after the padding. This defaults to 0.
 
 pad-after:
-	This sets the padding after the image entries. The padding will be
-	placed after the last entry. This defaults to 0.
+    This sets the padding after the image entries. The padding will be
+    placed after the last entry. This defaults to 0.
 
 pad-byte:
-	This specifies the pad byte to use when padding in the image. It
-	defaults to 0. To use 0xff, you would add 'pad-byte = <0xff>'.
+    This specifies the pad byte to use when padding in the image. It
+    defaults to 0. To use 0xff, you would add 'pad-byte = <0xff>'.
 
 filename:
-	This specifies the image filename. It defaults to 'image.bin'.
+    This specifies the image filename. It defaults to 'image.bin'.
 
 sort-by-offset:
-	This causes binman to reorder the entries as needed to make sure they
-	are in increasing positional order. This can be used when your entry
-	order may not match the positional order. A common situation is where
-	the 'offset' properties are set by CONFIG options, so their ordering is
-	not known a priori.
+    This causes binman to reorder the entries as needed to make sure they
+    are in increasing positional order. This can be used when your entry
+    order may not match the positional order. A common situation is where
+    the 'offset' properties are set by CONFIG options, so their ordering is
+    not known a priori.
 
-	This is a boolean property so needs no value. To enable it, add a
-	line 'sort-by-offset;' to your description.
+    This is a boolean property so needs no value. To enable it, add a
+    line 'sort-by-offset;' to your description.
 
 multiple-images:
-	Normally only a single image is generated. To create more than one
-	image, put this property in the binman node. For example, this will
-	create image1.bin containing u-boot.bin, and image2.bin containing
-	both spl/u-boot-spl.bin and u-boot.bin:
+    Normally only a single image is generated. To create more than one
+    image, put this property in the binman node. For example, this will
+    create image1.bin containing u-boot.bin, and image2.bin containing
+    both spl/u-boot-spl.bin and u-boot.bin::
 
-	binman {
-		multiple-images;
-		image1 {
-			u-boot {
-			};
-		};
+        binman {
+            multiple-images;
+            image1 {
+                u-boot {
+                };
+            };
 
-		image2 {
-			spl {
-			};
-			u-boot {
-			};
-		};
-	};
+            image2 {
+                spl {
+                };
+                u-boot {
+                };
+            };
+        };
 
 end-at-4gb:
-	For x86 machines the ROM offsets start just before 4GB and extend
-	up so that the image finished at the 4GB boundary. This boolean
-	option can be enabled to support this. The image size must be
-	provided so that binman knows when the image should start. For an
-	8MB ROM, the offset of the first entry would be 0xfff80000 with
-	this option, instead of 0 without this option.
+    For x86 machines the ROM offsets start just before 4GB and extend
+    up so that the image finished at the 4GB boundary. This boolean
+    option can be enabled to support this. The image size must be
+    provided so that binman knows when the image should start. For an
+    8MB ROM, the offset of the first entry would be 0xfff80000 with
+    this option, instead of 0 without this option.
 
 skip-at-start:
-	This property specifies the entry offset of the first entry.
+    This property specifies the entry offset of the first entry.
 
-	For PowerPC mpc85xx based CPU, CONFIG_SYS_TEXT_BASE is the entry
-	offset of the first entry. It can be 0xeff40000 or 0xfff40000 for
-	nor flash boot, 0x201000 for sd boot etc.
+    For PowerPC mpc85xx based CPU, CONFIG_SYS_TEXT_BASE is the entry
+    offset of the first entry. It can be 0xeff40000 or 0xfff40000 for
+    nor flash boot, 0x201000 for sd boot etc.
 
-	'end-at-4gb' property is not applicable where CONFIG_SYS_TEXT_BASE +
-	Image size != 4gb.
+    'end-at-4gb' property is not applicable where CONFIG_SYS_TEXT_BASE +
+    Image size != 4gb.
+
+align-default:
+    Specifies the default alignment for entries in this section, if they do
+    not specify an alignment. Note that this only applies to top-level entries
+    in the section (direct subentries), not any subentries of those entries.
+    This means that each section must specify its own default alignment, if
+    required.
 
 Examples of the above options can be found in the tests. See the
 tools/binman/test directory.
@@ -470,23 +590,23 @@
 is an example image with two copies of U-Boot. One is read-only (ro), intended
 to be written only in the factory. Another is read-write (rw), so that it can be
 upgraded in the field. The sizes are fixed so that the ro/rw boundary is known
-and can be programmed:
+and can be programmed::
 
-	binman {
-		section@0 {
-			read-only;
-			name-prefix = "ro-";
-			size = <0x100000>;
-			u-boot {
-			};
-		};
-		section@1 {
-			name-prefix = "rw-";
-			size = <0x100000>;
-			u-boot {
-			};
-		};
-	};
+    binman {
+        section@0 {
+            read-only;
+            name-prefix = "ro-";
+            size = <0x100000>;
+            u-boot {
+            };
+        };
+        section@1 {
+            name-prefix = "rw-";
+            size = <0x100000>;
+            u-boot {
+            };
+        };
+    };
 
 This image could be placed into a SPI flash chip, with the protection boundary
 set at 1MB.
@@ -494,14 +614,14 @@
 A few special properties are provided for sections:
 
 read-only:
-	Indicates that this section is read-only. This has no impact on binman's
-	operation, but his property can be read at run time.
+    Indicates that this section is read-only. This has no impact on binman's
+    operation, but his property can be read at run time.
 
 name-prefix:
-	This string is prepended to all the names of the binaries in the
-	section. In the example above, the 'u-boot' binaries which actually be
-	renamed to 'ro-u-boot' and 'rw-u-boot'. This can be useful to
-	distinguish binaries with otherwise identical names.
+    This string is prepended to all the names of the binaries in the
+    section. In the example above, the 'u-boot' binaries which actually be
+    renamed to 'ro-u-boot' and 'rw-u-boot'. This can be useful to
+    distinguish binaries with otherwise identical names.
 
 
 Image Properties
@@ -510,37 +630,196 @@
 Image nodes act like sections but also have a few extra properties:
 
 filename:
-	Output filename for the image. This defaults to image.bin (or in the
-	case of multiple images <nodename>.bin where <nodename> is the name of
-	the image node.
+    Output filename for the image. This defaults to image.bin (or in the
+    case of multiple images <nodename>.bin where <nodename> is the name of
+    the image node.
 
 allow-repack:
-	Create an image that can be repacked. With this option it is possible
-	to change anything in the image after it is created, including updating
-	the position and size of image components. By default this is not
-	permitted since it is not possibly to know whether this might violate a
-	constraint in the image description. For example, if a section has to
-	increase in size to hold a larger binary, that might cause the section
-	to fall out of its allow region (e.g. read-only portion of flash).
+    Create an image that can be repacked. With this option it is possible
+    to change anything in the image after it is created, including updating
+    the position and size of image components. By default this is not
+    permitted since it is not possibly to know whether this might violate a
+    constraint in the image description. For example, if a section has to
+    increase in size to hold a larger binary, that might cause the section
+    to fall out of its allow region (e.g. read-only portion of flash).
 
-	Adding this property causes the original offset and size values in the
-	image description to be stored in the FDT and fdtmap.
+    Adding this property causes the original offset and size values in the
+    image description to be stored in the FDT and fdtmap.
+
+
+Hashing Entries
+---------------
+
+It is possible to ask binman to hash the contents of an entry and write that
+value back to the device-tree node. For example::
+
+    binman {
+        u-boot {
+            hash {
+                algo = "sha256";
+            };
+        };
+    };
+
+Here, a new 'value' property will be written to the 'hash' node containing
+the hash of the 'u-boot' entry. Only SHA256 is supported at present. Whole
+sections can be hased if desired, by adding the 'hash' node to the section.
+
+The has value can be chcked at runtime by hashing the data actually read and
+comparing this has to the value in the device tree.
+
+
+Expanded entries
+----------------
+
+Binman automatically replaces 'u-boot' with an expanded version of that, i.e.
+'u-boot-expanded'. This means that when you write::
+
+    u-boot {
+    };
+
+you actually get::
+
+    u-boot {
+        type = "u-boot-expanded';
+    };
+
+which in turn expands to::
+
+    u-boot {
+        type = "section";
+
+        u-boot-nodtb {
+        };
+
+        u-boot-dtb {
+        };
+    };
+
+U-Boot's various phase binaries actually comprise two or three pieces.
+For example, u-boot.bin has the executable followed by a devicetree.
+
+With binman we want to be able to update that devicetree with full image
+information so that it is accessible to the executable. This is tricky
+if it is not clear where the devicetree starts.
+
+The above feature ensures that the devicetree is clearly separated from the
+U-Boot executable and can be updated separately by binman as needed. It can be
+disabled with the --no-expanded flag if required.
+
+The same applies for u-boot-spl and u-boot-spl. In those cases, the expansion
+includes the BSS padding, so for example::
+
+    spl {
+        type = "u-boot-spl"
+    };
+
+you actually get::
+
+    spl {
+        type = "u-boot-expanded';
+    };
+
+which in turn expands to::
+
+    spl {
+        type = "section";
+
+        u-boot-spl-nodtb {
+        };
+
+        u-boot-spl-bss-pad {
+        };
+
+        u-boot-spl-dtb {
+        };
+    };
+
+Of course we should not expand SPL if it has no devicetree. Also if the BSS
+padding is not needed (because BSS is in RAM as with CONFIG_SPL_SEPARATE_BSS),
+the 'u-boot-spl-bss-pad' subnode should not be created. The use of the expaned
+entry type is controlled by the UseExpanded() method. In the SPL case it checks
+the 'spl-dtb' entry arg, which is 'y' or '1' if SPL has a devicetree.
+
+For the BSS case, a 'spl-bss-pad' entry arg controls whether it is present. All
+entry args are provided by the U-Boot Makefile.
+
+
+Compression
+-----------
+
+Binman support compression for 'blob' entries (those of type 'blob' and
+derivatives). To enable this for an entry, add a 'compress' property::
+
+    blob {
+        filename = "datafile";
+        compress = "lz4";
+    };
+
+The entry will then contain the compressed data, using the 'lz4' compression
+algorithm. Currently this is the only one that is supported. The uncompressed
+size is written to the node in an 'uncomp-size' property, if -u is used.
+
+Compression is also supported for sections. In that case the entire section is
+compressed in one block, including all its contents. This means that accessing
+an entry from the section required decompressing the entire section. Also, the
+size of a section indicates the space that it consumes in its parent section
+(and typically the image). With compression, the section may contain more data,
+and the uncomp-size property indicates that, as above. The contents of the
+section is compressed first, before any padding is added. This ensures that the
+padding itself is not compressed, which would be a waste of time.
+
+
+Automatic .dtsi inclusion
+-------------------------
+
+It is sometimes inconvenient to add a 'binman' node to the .dts file for each
+board. This can be done by using #include to bring in a common file. Another
+approach supported by the U-Boot build system is to automatically include
+a common header. You can then put the binman node (and anything else that is
+specific to U-Boot, such as u-boot,dm-pre-reloc properies) in that header
+file.
+
+Binman will search for the following files in arch/<arch>/dts::
+
+   <dts>-u-boot.dtsi where <dts> is the base name of the .dts file
+   <CONFIG_SYS_SOC>-u-boot.dtsi
+   <CONFIG_SYS_CPU>-u-boot.dtsi
+   <CONFIG_SYS_VENDOR>-u-boot.dtsi
+   u-boot.dtsi
+
+U-Boot will only use the first one that it finds. If you need to include a
+more general file you can do that from the more specific file using #include.
+If you are having trouble figuring out what is going on, you can uncomment
+the 'warning' line in scripts/Makefile.lib to see what it has found::
+
+   # Uncomment for debugging
+   # This shows all the files that were considered and the one that we chose.
+   # u_boot_dtsi_options_debug = $(u_boot_dtsi_options_raw)
 
 
 Entry Documentation
--------------------
+===================
 
 For details on the various entry types supported by binman and how to use them,
-see README.entries. This is generated from the source code using:
+see entries.rst which is generated from the source code using:
 
-	binman entry-docs >tools/binman/README.entries
+    binman entry-docs >tools/binman/entries.rst
 
+.. toctree::
+   :maxdepth: 2
+
+   entries
+
+
+Managing images
+===============
 
 Listing images
 --------------
 
 It is possible to list the entries in an existing firmware image created by
-binman, provided that there is an 'fdtmap' entry in the image. For example:
+binman, provided that there is an 'fdtmap' entry in the image. For example::
 
     $ binman ls -i image.bin
     Name              Image-pos  Size  Entry-type    Offset  Uncomp-size
@@ -559,7 +838,7 @@
 entry, the offset of each entry within its parent and the uncompressed size if
 the entry is compressed.
 
-It is also possible to list just some files in an image, e.g.
+It is also possible to list just some files in an image, e.g.::
 
     $ binman ls -i image.bin section/cbfs
     Name              Image-pos  Size  Entry-type  Offset  Uncomp-size
@@ -568,7 +847,7 @@
           u-boot            138     4  u-boot          38
           u-boot-dtb        180   108  u-boot-dtb      80          3b5
 
-or with wildcards:
+or with wildcards::
 
     $ binman ls -i image.bin "*cb*" "*head*"
     Name              Image-pos  Size  Entry-type    Offset  Uncomp-size
@@ -583,22 +862,22 @@
 ----------------------------
 
 You can extract files from an existing firmware image created by binman,
-provided that there is an 'fdtmap' entry in the image. For example:
+provided that there is an 'fdtmap' entry in the image. For example::
 
     $ binman extract -i image.bin section/cbfs/u-boot
 
 which will write the uncompressed contents of that entry to the file 'u-boot' in
 the current directory. You can also extract to a particular file, in this case
-u-boot.bin:
+u-boot.bin::
 
     $ binman extract -i image.bin section/cbfs/u-boot -f u-boot.bin
 
 It is possible to extract all files into a destination directory, which will
-put files in subdirectories matching the entry hierarchy:
+put files in subdirectories matching the entry hierarchy::
 
     $ binman extract -i image.bin -O outdir
 
-or just a selection:
+or just a selection::
 
     $ binman extract -i image.bin "*u-boot*" -O outdir
 
@@ -616,18 +895,18 @@
 add the 'allow-repack' property to the original image before generating it (see
 above), otherwise you will get an error.
 
-You can also use a particular file, in this case u-boot.bin:
+You can also use a particular file, in this case u-boot.bin::
 
     $ binman replace -i image.bin section/cbfs/u-boot -f u-boot.bin
 
 It is possible to replace all files from a source directory which uses the same
-hierarchy as the entries:
+hierarchy as the entries::
 
     $ binman replace -i image.bin -I indir
 
 Files that are missing will generate a warning.
 
-You can also replace just a selection of entries:
+You can also replace just a selection of entries::
 
     $ binman replace -i image.bin "*u-boot*" -I indir
 
@@ -637,7 +916,8 @@
 
 Binman normally operates silently unless there is an error, in which case it
 just displays the error. The -D/--debug option can be used to create a full
-backtrace when errors occur.
+backtrace when errors occur. You can use BINMAN_DEBUG=1 when building to select
+this.
 
 Internally binman logs some output while it is running. This can be displayed
 by increasing the -v/--verbosity from the default of 1:
@@ -649,28 +929,11 @@
    4: detailed information about each operation
    5: debug (all output)
 
+You can use BINMAN_VERBOSE=5 (for example) when building to select this.
 
-Hashing Entries
----------------
 
-It is possible to ask binman to hash the contents of an entry and write that
-value back to the device-tree node. For example:
-
-	binman {
-		u-boot {
-			hash {
-				algo = "sha256";
-			};
-		};
-	};
-
-Here, a new 'value' property will be written to the 'hash' node containing
-the hash of the 'u-boot' entry. Only SHA256 is supported at present. Whole
-sections can be hased if desired, by adding the 'hash' node to the section.
-
-The has value can be chcked at runtime by hashing the data actually read and
-comparing this has to the value in the device tree.
-
+Technical details
+=================
 
 Order of image creation
 -----------------------
@@ -747,162 +1010,6 @@
 final step.
 
 
-Automatic .dtsi inclusion
--------------------------
-
-It is sometimes inconvenient to add a 'binman' node to the .dts file for each
-board. This can be done by using #include to bring in a common file. Another
-approach supported by the U-Boot build system is to automatically include
-a common header. You can then put the binman node (and anything else that is
-specific to U-Boot, such as u-boot,dm-pre-reloc properies) in that header
-file.
-
-Binman will search for the following files in arch/<arch>/dts:
-
-   <dts>-u-boot.dtsi where <dts> is the base name of the .dts file
-   <CONFIG_SYS_SOC>-u-boot.dtsi
-   <CONFIG_SYS_CPU>-u-boot.dtsi
-   <CONFIG_SYS_VENDOR>-u-boot.dtsi
-   u-boot.dtsi
-
-U-Boot will only use the first one that it finds. If you need to include a
-more general file you can do that from the more specific file using #include.
-If you are having trouble figuring out what is going on, you can uncomment
-the 'warning' line in scripts/Makefile.lib to see what it has found:
-
-   # Uncomment for debugging
-   # This shows all the files that were considered and the one that we chose.
-   # u_boot_dtsi_options_debug = $(u_boot_dtsi_options_raw)
-
-
-Access to binman entry offsets at run time (symbols)
-----------------------------------------------------
-
-Binman assembles images and determines where each entry is placed in the image.
-This information may be useful to U-Boot at run time. For example, in SPL it
-is useful to be able to find the location of U-Boot so that it can be executed
-when SPL is finished.
-
-Binman allows you to declare symbols in the SPL image which are filled in
-with their correct values during the build. For example:
-
-    binman_sym_declare(ulong, u_boot_any, image_pos);
-
-declares a ulong value which will be assigned to the image-pos of any U-Boot
-image (u-boot.bin, u-boot.img, u-boot-nodtb.bin) that is present in the image.
-You can access this value with something like:
-
-    ulong u_boot_offset = binman_sym(ulong, u_boot_any, image_pos);
-
-Thus u_boot_offset will be set to the image-pos of U-Boot in memory, assuming
-that the whole image has been loaded, or is available in flash. You can then
-jump to that address to start U-Boot.
-
-At present this feature is only supported in SPL and TPL. In principle it is
-possible to fill in such symbols in U-Boot proper, as well, but a future C
-library is planned for this instead, to read from the device tree.
-
-As well as image-pos, it is possible to read the size of an entry and its
-offset (which is the start position of the entry within its parent).
-
-A small technical note: Binman automatically adds the base address of the image
-(i.e. __image_copy_start) to the value of the image-pos symbol, so that when the
-image is loaded to its linked address, the value will be correct and actually
-point into the image.
-
-For example, say SPL is at the start of the image and linked to start at address
-80108000. If U-Boot's image-pos is 0x8000 then binman will write an image-pos
-for U-Boot of 80110000 into the SPL binary, since it assumes the image is loaded
-to 80108000, with SPL at 80108000 and U-Boot at 80110000.
-
-For x86 devices (with the end-at-4gb property) this base address is not added
-since it is assumed that images are XIP and the offsets already include the
-address.
-
-
-Access to binman entry offsets at run time (fdt)
-------------------------------------------------
-
-Binman can update the U-Boot FDT to include the final position and size of
-each entry in the images it processes. The option to enable this is -u and it
-causes binman to make sure that the 'offset', 'image-pos' and 'size' properties
-are set correctly for every entry. Since it is not necessary to specify these in
-the image definition, binman calculates the final values and writes these to
-the device tree. These can be used by U-Boot at run-time to find the location
-of each entry.
-
-Alternatively, an FDT map entry can be used to add a special FDT containing
-just the information about the image. This is preceded by a magic string so can
-be located anywhere in the image. An image header (typically at the start or end
-of the image) can be used to point to the FDT map. See fdtmap and image-header
-entries for more information.
-
-
-Compression
------------
-
-Binman support compression for 'blob' entries (those of type 'blob' and
-derivatives). To enable this for an entry, add a 'compress' property:
-
-    blob {
-        filename = "datafile";
-        compress = "lz4";
-    };
-
-The entry will then contain the compressed data, using the 'lz4' compression
-algorithm. Currently this is the only one that is supported. The uncompressed
-size is written to the node in an 'uncomp-size' property, if -u is used.
-
-Compression is also supported for sections. In that case the entire section is
-compressed in one block, including all its contents. This means that accessing
-an entry from the section required decompressing the entire section. Also, the
-size of a section indicates the space that it consumes in its parent section
-(and typically the image). With compression, the section may contain more data,
-and the uncomp-size property indicates that, as above. The contents of the
-section is compressed first, before any padding is added. This ensures that the
-padding itself is not compressed, which would be a waste of time.
-
-
-Map files
----------
-
-The -m option causes binman to output a .map file for each image that it
-generates. This shows the offset and size of each entry. For example:
-
-      Offset      Size  Name
-    00000000  00000028  main-section
-     00000000  00000010  section@0
-      00000000  00000004  u-boot
-     00000010  00000010  section@1
-      00000000  00000004  u-boot
-
-This shows a hierarchical image with two sections, each with a single entry. The
-offsets of the sections are absolute hex byte offsets within the image. The
-offsets of the entries are relative to their respective sections. The size of
-each entry is also shown, in bytes (hex). The indentation shows the entries
-nested inside their sections.
-
-
-Passing command-line arguments to entries
------------------------------------------
-
-Sometimes it is useful to pass binman the value of an entry property from the
-command line. For example some entries need access to files and it is not
-always convenient to put these filenames in the image definition (device tree).
-
-The-a option supports this:
-
-    -a<prop>=<value>
-
-where
-
-    <prop> is the property to set
-    <value> is the value to set it to
-
-Not all properties can be provided this way. Only some entries support it,
-typically for filenames.
-
-
 External tools
 --------------
 
@@ -925,7 +1032,7 @@
 Binman is a critical tool and is designed to be very testable. Entry
 implementations target 100% test coverage. Run 'binman test -T' to check this.
 
-To enable Python test coverage on Debian-type distributions (e.g. Ubuntu):
+To enable Python test coverage on Debian-type distributions (e.g. Ubuntu)::
 
    $ sudo apt-get install python-coverage python3-coverage python-pytest
 
@@ -936,7 +1043,7 @@
 Binman tries to run tests concurrently. This means that the tests make use of
 all available CPUs to run.
 
- To enable this:
+ To enable this::
 
    $ sudo apt-get install python-subunit python3-subunit
 
@@ -959,19 +1066,19 @@
 x86-like host and there hasn't been an attempt to make them portable yet.
 However, it's possible to run the tests by cross-compiling to x86.
 
-To install an x86 cross-compiler on Debian-type distributions (e.g. Ubuntu):
+To install an x86 cross-compiler on Debian-type distributions (e.g. Ubuntu)::
 
   $ sudo apt-get install gcc-x86-64-linux-gnu
 
-Then, you can run the tests under cross-compilation:
+Then, you can run the tests under cross-compilation::
 
   $ CROSS_COMPILE=x86_64-linux-gnu- binman test -T
 
 You can also use gcc-i686-linux-gnu similar to the above.
 
 
-Advanced Features / Technical docs
-----------------------------------
+Writing new entries and debugging
+---------------------------------
 
 The behaviour of entries is defined by the Entry class. All other entries are
 a subclass of this. An important subclass is Entry_blob which takes binary
@@ -999,13 +1106,13 @@
 old.
 
 To enable a full backtrace and other debugging features in binman, pass
-BINMAN_DEBUG=1 to your build:
+BINMAN_DEBUG=1 to your build::
 
    make qemu-x86_defconfig
    make BINMAN_DEBUG=1
 
 To enable verbose logging from binman, base BINMAN_VERBOSE to your build, which
-adds a -v<level> option to the call to binman:
+adds a -v<level> option to the call to binman::
 
    make qemu-x86_defconfig
    make BINMAN_VERBOSE=5
@@ -1045,8 +1152,10 @@
 -----
 
 Some ideas:
+
 - Use of-platdata to make the information available to code that is unable
-  to use device tree (such as a very small SPL image)
+  to use device tree (such as a very small SPL image). For now, limited info is
+  available via linker symbols
 - Allow easy building of images by specifying just the board name
 - Support building an image for a board (-b) more completely, with a
   configurable build directory
diff --git a/tools/binman/cmdline.py b/tools/binman/cmdline.py
index c007d0a..95f9ba2 100644
--- a/tools/binman/cmdline.py
+++ b/tools/binman/cmdline.py
@@ -56,6 +56,9 @@
         default=False, help='Output a map file for each image')
     build_parser.add_argument('-M', '--allow-missing', action='store_true',
         default=False, help='Allow external blobs to be missing')
+    build_parser.add_argument('-n', '--no-expanded', action='store_true',
+            help="Don't use 'expanded' versions of entries where available; "
+                 "normally 'u-boot' becomes 'u-boot-expanded', for example")
     build_parser.add_argument('-O', '--outdir', type=str,
         action='store', help='Path to directory to use for intermediate and '
         'output files')
@@ -66,7 +69,7 @@
         default=False, help='Update the binman node with offset/size info')
 
     entry_parser = subparsers.add_parser('entry-docs',
-        help='Write out entry documentation (see README.entries)')
+        help='Write out entry documentation (see entries.rst)')
 
     list_parser = subparsers.add_parser('ls', help='List files in an image')
     list_parser.add_argument('-i', '--image', type=str, required=True,
diff --git a/tools/binman/control.py b/tools/binman/control.py
index 1952b2a..f57e34d 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -28,7 +28,7 @@
 #    value: Text for the help
 missing_blob_help = {}
 
-def _ReadImageDesc(binman_node):
+def _ReadImageDesc(binman_node, use_expanded):
     """Read the image descriptions from the /binman node
 
     This normally produces a single Image object called 'image'. But if
@@ -36,15 +36,17 @@
 
     Args:
         binman_node: Node object of the /binman node
+        use_expanded: True if the FDT will be updated with the entry information
     Returns:
         OrderedDict of Image objects, each of which describes an image
     """
     images = OrderedDict()
     if 'multiple-images' in binman_node.props:
         for node in binman_node.subnodes:
-            images[node.name] = Image(node.name, node)
+            images[node.name] = Image(node.name, node,
+                                      use_expanded=use_expanded)
     else:
-        images['image'] = Image('image', binman_node)
+        images['image'] = Image('image', binman_node, use_expanded=use_expanded)
     return images
 
 def _FindBinmanNode(dtb):
@@ -241,7 +243,7 @@
         # If this entry has children, create a directory for it and put its
         # data in a file called 'root' in that directory
         if entry.GetEntries():
-            if not os.path.exists(fname):
+            if fname and not os.path.exists(fname):
                 os.makedirs(fname)
             fname = os.path.join(fname, 'root')
         tout.Notice("Write entry '%s' size %x to '%s'" %
@@ -399,7 +401,7 @@
     return image
 
 
-def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt):
+def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt, use_expanded):
     """Prepare the images to be processed and select the device tree
 
     This function:
@@ -413,6 +415,9 @@
         dtb_fname: Filename of the device tree file to use (.dts or .dtb)
         selected_images: List of images to output, or None for all
         update_fdt: True to update the FDT wth entry offsets, etc.
+        use_expanded: True to use expanded versions of entries, if available.
+            So if 'u-boot' is called for, we use 'u-boot-expanded' instead. This
+            is needed if update_fdt is True (although tests may disable it)
 
     Returns:
         OrderedDict of images:
@@ -438,7 +443,7 @@
         raise ValueError("Device tree '%s' does not have a 'binman' "
                             "node" % dtb_fname)
 
-    images = _ReadImageDesc(node)
+    images = _ReadImageDesc(node, use_expanded)
 
     if select_images:
         skip = []
@@ -564,7 +569,7 @@
         if not pager:
             pager = 'more'
         fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
-                            'README')
+                            'README.rst')
         command.Run(pager, fname)
         return 0
 
@@ -611,6 +616,13 @@
         elf.debug = args.debug
         cbfs_util.VERBOSE = args.verbosity > 2
         state.use_fake_dtb = args.fake_dtb
+
+        # Normally we replace the 'u-boot' etype with 'u-boot-expanded', etc.
+        # When running tests this can be disabled using this flag. When not
+        # updating the FDT in image, it is not needed by binman, but we use it
+        # for consistency, so that the images look the same to U-Boot at
+        # runtime.
+        use_expanded = not args.no_expanded
         try:
             tools.SetInputDirs(args.indir)
             tools.PrepareOutputDir(args.outdir, args.preserve)
@@ -618,7 +630,7 @@
             state.SetEntryArgs(args.entry_arg)
 
             images = PrepareImagesAndDtbs(dtb_fname, args.image,
-                                          args.update_fdt)
+                                          args.update_fdt, use_expanded)
             missing = False
             for image in images.values():
                 missing |= ProcessImage(image, args.update_fdt, args.map,
diff --git a/tools/binman/README.entries b/tools/binman/entries.rst
similarity index 80%
rename from tools/binman/README.entries
rename to tools/binman/entries.rst
index 999b776..a91211e 100644
--- a/tools/binman/README.entries
+++ b/tools/binman/entries.rst
@@ -11,8 +11,8 @@
 
 
 
-Entry: atf-bl31: Entry containing an ARM Trusted Firmware (ATF) BL31 blob
--------------------------------------------------------------------------
+Entry: atf-bl31: ARM Trusted Firmware (ATF) BL31 blob
+-----------------------------------------------------
 
 Properties / Entry arguments:
     - atf-bl31-path: Filename of file to read into entry. This is typically
@@ -25,8 +25,8 @@
 
 
 
-Entry: blob: Entry containing an arbitrary binary blob
-------------------------------------------------------
+Entry: blob: Arbitrary binary blob
+----------------------------------
 
 Note: This should not be used by itself. It is normally used as a parent
 class by other entry types.
@@ -39,7 +39,7 @@
 
 This entry reads data from a file and places it in the entry. The
 default filename is often specified specified by the subclass. See for
-example the 'u_boot' entry which provides the filename 'u-boot.bin'.
+example the 'u-boot' entry which provides the filename 'u-boot.bin'.
 
 If compression is enabled, an extra 'uncomp-size' property is written to
 the node (if enabled with -u) which provides the uncompressed size of the
@@ -56,8 +56,8 @@
 
 
 
-Entry: blob-ext: Entry containing an externally built binary blob
------------------------------------------------------------------
+Entry: blob-ext: Externally built binary blob
+---------------------------------------------
 
 Note: This should not be used by itself. It is normally used as a parent
 class by other entry types.
@@ -87,8 +87,17 @@
 
 
 
-Entry: cbfs: Entry containing a Coreboot Filesystem (CBFS)
-----------------------------------------------------------
+Entry: blob-phase: Section that holds a phase binary
+----------------------------------------------------
+
+This is a base class that should not normally be used directly. It is used
+when converting a 'u-boot' entry automatically into a 'u-boot-expanded'
+entry; similarly for SPL.
+
+
+
+Entry: cbfs: Coreboot Filesystem (CBFS)
+---------------------------------------
 
 A CBFS provides a way to group files into a group. It has a simple directory
 structure and allows the position of individual files to be set, since it is
@@ -97,7 +106,7 @@
 
 CBFS is used by coreboot as its way of orgnanising SPI-flash contents.
 
-The contents of the CBFS are defined by subnodes of the cbfs entry, e.g.:
+The contents of the CBFS are defined by subnodes of the cbfs entry, e.g.::
 
     cbfs {
         size = <0x100000>;
@@ -113,7 +122,7 @@
 Note that the size is required since binman does not support calculating it.
 The contents of each entry is just what binman would normally provide if it
 were not a CBFS node. A blob type can be used to import arbitrary files as
-with the second subnode below:
+with the second subnode below::
 
     cbfs {
         size = <0x100000>;
@@ -159,7 +168,7 @@
         This is an ELF file that has been loaded (i.e. mapped to memory), so
         appears in the CBFS as a flat binary. The input file must be an ELF
         image, for example this puts "u-boot" (the ELF image) into a 'stage'
-        entry:
+        entry::
 
             cbfs {
                 size = <0x100000>;
@@ -169,7 +178,7 @@
                 };
             };
 
-        You can use your own ELF file with something like:
+        You can use your own ELF file with something like::
 
             cbfs {
                 size = <0x100000>;
@@ -202,7 +211,7 @@
 particular offset in the CBFS and a few other things.
 
 Of course binman can create images containing multiple CBFSs, simply by
-defining these in the binman config:
+defining these in the binman config::
 
 
     binman {
@@ -239,6 +248,19 @@
 
 
 
+Entry: collection: An entry which contains a collection of other entries
+------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - content: List of phandles to entries to include
+
+This allows reusing the contents of other entries. The contents of the
+listed entries are combined to form this entry. This serves as a useful
+base class for entry types which need to process data from elsewhere in
+the image, not necessarily child entries.
+
+
+
 Entry: cros-ec-rw: A blob entry which contains a Chromium OS read-write EC image
 --------------------------------------------------------------------------------
 
@@ -270,38 +292,39 @@
 Note that the -u option must be provided to ensure that binman updates the
 FDT with the position of each entry.
 
-Example output for a simple image with U-Boot and an FDT map:
+Example output for a simple image with U-Boot and an FDT map::
 
-/ {
-    image-name = "binman";
-    size = <0x00000112>;
-    image-pos = <0x00000000>;
-    offset = <0x00000000>;
-    u-boot {
-        size = <0x00000004>;
+    / {
+        image-name = "binman";
+        size = <0x00000112>;
         image-pos = <0x00000000>;
         offset = <0x00000000>;
+        u-boot {
+            size = <0x00000004>;
+            image-pos = <0x00000000>;
+            offset = <0x00000000>;
+        };
+        fdtmap {
+            size = <0x0000010e>;
+            image-pos = <0x00000004>;
+            offset = <0x00000004>;
+        };
     };
-    fdtmap {
-        size = <0x0000010e>;
-        image-pos = <0x00000004>;
-        offset = <0x00000004>;
-    };
-};
 
 If allow-repack is used then 'orig-offset' and 'orig-size' properties are
 added as necessary. See the binman README.
 
 
 
-Entry: files: Entry containing a set of files
----------------------------------------------
+Entry: files: A set of files arranged in a section
+--------------------------------------------------
 
 Properties / Entry arguments:
     - pattern: Filename pattern to match the files to include
     - files-compress: Compression algorithm to use:
         none: No compression
         lz4: Use lz4 compression (via 'lz4' command-line utility)
+    - files-align: Align each file to the given alignment
 
 This entry reads a number of files and places each in a separate sub-entry
 within this entry. To access these you need to enable device-tree updates
@@ -325,8 +348,8 @@
 
 
 
-Entry: fit: Entry containing a FIT
-----------------------------------
+Entry: fit: Flat Image Tree (FIT)
+---------------------------------
 
 This calls mkimage to create a FIT (U-Boot Flat Image Tree) based on the
 input provided.
@@ -334,7 +357,7 @@
 Nodes for the FIT should be written out in the binman configuration just as
 they would be in a file passed to mkimage.
 
-For example, this creates an image containing a FIT with U-Boot SPL:
+For example, this creates an image containing a FIT with U-Boot SPL::
 
     binman {
         fit {
@@ -364,7 +387,7 @@
 The fit,fdt-list property (see above) indicates that of-list should be used.
 If the property is missing you will get an error.
 
-Then add a 'generator node', a node with a name starting with '@':
+Then add a 'generator node', a node with a name starting with '@'::
 
     images {
         @fdt-SEQ {
@@ -379,7 +402,7 @@
 node acts like a template to generate the nodes. The generator node itself
 does not appear in the output - it is replaced with what binman generates.
 
-You can create config nodes in a similar way:
+You can create config nodes in a similar way::
 
     configurations {
         default = "@config-DEFAULT-SEQ";
@@ -396,8 +419,10 @@
 
 Available substitutions for '@' nodes are:
 
-    SEQ    Sequence number of the generated fdt (1, 2, ...)
-    NAME   Name of the dtb as provided (i.e. without adding '.dtb')
+SEQ:
+    Sequence number of the generated fdt (1, 2, ...)
+NAME
+    Name of the dtb as provided (i.e. without adding '.dtb')
 
 Note that if no devicetree files are provided (with '-a of-list' as above)
 then no nodes will be generated.
@@ -406,10 +431,11 @@
 if of configuration whose devicetree matches the 'default-dt' entry
 argument, e.g. with '-a default-dt=sun50i-a64-pine64-lts'.
 
-Available substitutions for '@' property values are:
+Available substitutions for '@' property values are
 
-    DEFAULT-SEQ  Sequence number of the default fdt,as provided by the
-                 'default-dt' entry argument
+DEFAULT-SEQ:
+    Sequence number of the default fdt,as provided by the 'default-dt' entry
+    argument
 
 Properties (in the 'fit' node itself):
     fit,external-offset: Indicates that the contents of the FIT are external
@@ -478,8 +504,8 @@
 
 
 
-Entry: intel-cmc: Entry containing an Intel Chipset Micro Code (CMC) file
--------------------------------------------------------------------------
+Entry: intel-cmc: Intel Chipset Micro Code (CMC) file
+-----------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -531,8 +557,8 @@
 
 
 
-Entry: intel-fsp: Entry containing an Intel Firmware Support Package (FSP) file
--------------------------------------------------------------------------------
+Entry: intel-fsp: Intel Firmware Support Package (FSP) file
+-----------------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -548,8 +574,8 @@
 
 
 
-Entry: intel-fsp-m: Entry containing Intel Firmware Support Package (FSP) memory init
--------------------------------------------------------------------------------------
+Entry: intel-fsp-m: Intel Firmware Support Package (FSP) memory init
+--------------------------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -565,8 +591,8 @@
 
 
 
-Entry: intel-fsp-s: Entry containing Intel Firmware Support Package (FSP) silicon init
---------------------------------------------------------------------------------------
+Entry: intel-fsp-s: Intel Firmware Support Package (FSP) silicon init
+---------------------------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -582,8 +608,8 @@
 
 
 
-Entry: intel-fsp-t: Entry containing Intel Firmware Support Package (FSP) temp ram init
----------------------------------------------------------------------------------------
+Entry: intel-fsp-t: Intel Firmware Support Package (FSP) temp ram init
+----------------------------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -598,8 +624,8 @@
 
 
 
-Entry: intel-ifwi: Entry containing an Intel Integrated Firmware Image (IFWI) file
-----------------------------------------------------------------------------------
+Entry: intel-ifwi: Intel Integrated Firmware Image (IFWI) file
+--------------------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry. This is either the
@@ -623,17 +649,17 @@
 sub-partition (and optional entry name).
 
 Properties for subnodes:
-    ifwi-subpart - sub-parition to put this entry into, e.g. "IBBP"
-    ifwi-entry - entry name t use, e.g. "IBBL"
-    ifwi-replace - if present, indicates that the item should be replaced
-        in the IFWI. Otherwise it is added.
+    - ifwi-subpart: sub-parition to put this entry into, e.g. "IBBP"
+    - ifwi-entry: entry name t use, e.g. "IBBL"
+    - ifwi-replace: if present, indicates that the item should be replaced
+      in the IFWI. Otherwise it is added.
 
 See README.x86 for information about x86 binary blobs.
 
 
 
-Entry: intel-me: Entry containing an Intel Management Engine (ME) file
-----------------------------------------------------------------------
+Entry: intel-me: Intel Management Engine (ME) file
+--------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -652,8 +678,8 @@
 
 
 
-Entry: intel-mrc: Entry containing an Intel Memory Reference Code (MRC) file
-----------------------------------------------------------------------------
+Entry: intel-mrc: Intel Memory Reference Code (MRC) file
+--------------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -666,8 +692,8 @@
 
 
 
-Entry: intel-refcode: Entry containing an Intel Reference Code file
--------------------------------------------------------------------
+Entry: intel-refcode: Intel Reference Code file
+-----------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -680,8 +706,8 @@
 
 
 
-Entry: intel-vbt: Entry containing an Intel Video BIOS Table (VBT) file
------------------------------------------------------------------------
+Entry: intel-vbt: Intel Video BIOS Table (VBT) file
+---------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -693,8 +719,8 @@
 
 
 
-Entry: intel-vga: Entry containing an Intel Video Graphics Adaptor (VGA) file
------------------------------------------------------------------------------
+Entry: intel-vga: Intel Video Graphics Adaptor (VGA) file
+---------------------------------------------------------
 
 Properties / Entry arguments:
     - filename: Filename of file to read into entry
@@ -708,15 +734,15 @@
 
 
 
-Entry: mkimage: Entry containing a binary produced by mkimage
--------------------------------------------------------------
+Entry: mkimage: Binary produced by mkimage
+------------------------------------------
 
 Properties / Entry arguments:
     - datafile: Filename for -d argument
     - args: Other arguments to pass
 
 The data passed to mkimage is collected from subnodes of the mkimage node,
-e.g.:
+e.g.::
 
     mkimage {
         args = "-n test -T imximage";
@@ -743,8 +769,8 @@
 
 
 
-Entry: scp: Entry containing a System Control Processor (SCP) firmware blob
----------------------------------------------------------------------------
+Entry: scp: System Control Processor (SCP) firmware blob
+--------------------------------------------------------
 
 Properties / Entry arguments:
     - scp-path: Filename of file to read into the entry, typically scp.bin
@@ -756,11 +782,13 @@
 Entry: section: Entry that contains other entries
 -------------------------------------------------
 
-Properties / Entry arguments: (see binman README for more information)
+Properties / Entry arguments: (see binman README for more information):
     pad-byte: Pad byte to use when padding
     sort-by-offset: True if entries should be sorted by offset, False if
-        they must be in-order in the device tree description
+    they must be in-order in the device tree description
+
     end-at-4gb: Used to build an x86 ROM which ends at 4GB (2^32)
+
     skip-at-start: Number of bytes before the first entry starts. These
         effectively adjust the starting offset of entries. For example,
         if this is 16, then the first entry would start at 16. An entry
@@ -768,6 +796,8 @@
         file, since the first 16 bytes are skipped when writing.
     name-prefix: Adds a prefix to the name of every entry in the section
         when writing out the map
+    align_default: Default alignment for this section, if no alignment is
+        given in the entry
 
 Properties:
     allow_missing: True if this section permits external blobs to be
@@ -798,7 +828,7 @@
     <text>: The text to place in the entry (overrides the above mechanism).
         This is useful when the text is constant.
 
-Example node:
+Example node::
 
     text {
         size = <50>;
@@ -811,7 +841,7 @@
 
 and binman will insert that string into the entry.
 
-It is also possible to put the string directly in the node:
+It is also possible to put the string directly in the node::
 
     text {
         size = <8>;
@@ -819,7 +849,7 @@
         message = "a message directly in the node"
     };
 
-or just:
+or just::
 
     text {
         size = <8>;
@@ -839,8 +869,7 @@
 
 This is the U-Boot binary, containing relocation information to allow it
 to relocate itself at runtime. The binary typically includes a device tree
-blob at the end of it. Use u_boot_nodtb if you want to package the device
-tree separately.
+blob at the end of it.
 
 U-Boot can access binman symbols at runtime. See:
 
@@ -848,6 +877,9 @@
 
 in the binman README for more information.
 
+Note that this entry is automatically replaced with u-boot-expanded unless
+--no-expanded is used or the node has a 'no-expanded' property.
+
 
 
 Entry: u-boot-dtb: U-Boot device tree
@@ -875,9 +907,9 @@
 this process. This entry provides the U-Boot device-tree file, which
 contains the microcode. If the microcode is not being collated into one
 place then the offset and size of the microcode is recorded by this entry,
-for use by u_boot_with_ucode_ptr. If it is being collated, then this
+for use by u-boot-with-ucode_ptr. If it is being collated, then this
 entry deletes the microcode from the device tree (to save space) and makes
-it available to u_boot_ucode.
+it available to u-boot-ucode.
 
 
 
@@ -901,6 +933,21 @@
 
 
 
+Entry: u-boot-expanded: U-Boot flat binary broken out into its component parts
+------------------------------------------------------------------------------
+
+This is a section containing the U-Boot binary and a devicetree. Using this
+entry type automatically creates this section, with the following entries
+in it:
+
+   u-boot-nodtb
+   u-boot-dtb
+
+Having the devicetree separate allows binman to update it in the final
+image, so that the entries positions are provided to the running U-Boot.
+
+
+
 Entry: u-boot-img: U-Boot legacy image
 --------------------------------------
 
@@ -919,13 +966,13 @@
 --------------------------------------------------------------------
 
 Properties / Entry arguments:
-    - filename: Filename of u-boot.bin (default 'u-boot-nodtb.bin')
+    - filename: Filename to include (default 'u-boot-nodtb.bin')
 
 This is the U-Boot binary, containing relocation information to allow it
 to relocate itself at runtime. It does not include a device tree blob at
-the end of it so normally cannot work without it. You can add a u_boot_dtb
-entry after this one, or use a u_boot entry instead (which contains both
-U-Boot and the device tree).
+the end of it so normally cannot work without it. You can add a u-boot-dtb
+entry after this one, or use a u-boot entry instead, normally expands to a
+section containing u-boot and u-boot-dtb
 
 
 
@@ -951,6 +998,9 @@
 The ELF file 'spl/u-boot-spl' must also be available for this to work, since
 binman uses that to look up symbols to write into the SPL binary.
 
+Note that this entry is automatically replaced with u-boot-spl-expanded
+unless --no-expanded is used or the node has a 'no-expanded' property.
+
 
 
 Entry: u-boot-spl-bss-pad: U-Boot SPL binary padded with a BSS region
@@ -959,13 +1009,16 @@
 Properties / Entry arguments:
     None
 
-This is similar to u_boot_spl except that padding is added after the SPL
-binary to cover the BSS (Block Started by Symbol) region. This region holds
-the various used by SPL. It is set to 0 by SPL when it starts up. If you
-want to append data to the SPL image (such as a device tree file), you must
-pad out the BSS region to avoid the data overlapping with U-Boot variables.
-This entry is useful in that case. It automatically pads out the entry size
-to cover both the code, data and BSS.
+This holds the padding added after the SPL binary to cover the BSS (Block
+Started by Symbol) region. This region holds the various variables used by
+SPL. It is set to 0 by SPL when it starts up. If you want to append data to
+the SPL image (such as a device tree file), you must pad out the BSS region
+to avoid the data overlapping with U-Boot variables. This entry is useful in
+that case. It automatically pads out the entry size to cover both the code,
+data and BSS.
+
+The contents of this entry will a certain number of zero bytes, determined
+by __bss_size
 
 The ELF file 'spl/u-boot-spl' must also be available for this to work, since
 binman uses that to look up the BSS address.
@@ -995,18 +1048,50 @@
 
 
 
+Entry: u-boot-spl-expanded: U-Boot SPL flat binary broken out into its component parts
+--------------------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - spl-dtb: Controls whether this entry is selected (set to 'y' or '1' to
+        select)
+
+This is a section containing the U-Boot binary, BSS padding if needed and a
+devicetree. Using this entry type automatically creates this section, with
+the following entries in it:
+
+   u-boot-spl-nodtb
+   u-boot-spl-bss-pad
+   u-boot-dtb
+
+Having the devicetree separate allows binman to update it in the final
+image, so that the entries positions are provided to the running U-Boot.
+
+This entry is selected based on the value of the 'spl-dtb' entryarg. If
+this is non-empty (and not 'n' or '0') then this expanded entry is selected.
+
+
+
 Entry: u-boot-spl-nodtb: SPL binary without device tree appended
 ----------------------------------------------------------------
 
 Properties / Entry arguments:
-    - filename: Filename of spl/u-boot-spl-nodtb.bin (default
-        'spl/u-boot-spl-nodtb.bin')
+    - filename: Filename to include (default 'spl/u-boot-spl-nodtb.bin')
 
 This is the U-Boot SPL binary, It does not include a device tree blob at
 the end of it so may not be able to work without it, assuming SPL needs
-a device tree to operation on your platform. You can add a u_boot_spl_dtb
-entry after this one, or use a u_boot_spl entry instead (which contains
-both SPL and the device tree).
+a device tree to operate on your platform. You can add a u-boot-spl-dtb
+entry after this one, or use a u-boot-spl entry instead' which normally
+expands to a section containing u-boot-spl-dtb, u-boot-spl-bss-pad and
+u-boot-spl-dtb
+
+SPL can access binman symbols at runtime. See:
+
+    'Access to binman entry offsets at run time (symbols)'
+
+in the binman README for more information.
+
+The ELF file 'spl/u-boot-spl' must also be available for this to work, since
+binman uses that to look up symbols to write into the SPL binary.
 
 
 
@@ -1042,6 +1127,31 @@
 The ELF file 'tpl/u-boot-tpl' must also be available for this to work, since
 binman uses that to look up symbols to write into the TPL binary.
 
+Note that this entry is automatically replaced with u-boot-tpl-expanded
+unless --no-expanded is used or the node has a 'no-expanded' property.
+
+
+
+Entry: u-boot-tpl-bss-pad: U-Boot TPL binary padded with a BSS region
+---------------------------------------------------------------------
+
+Properties / Entry arguments:
+    None
+
+This holds the padding added after the TPL binary to cover the BSS (Block
+Started by Symbol) region. This region holds the various variables used by
+TPL. It is set to 0 by TPL when it starts up. If you want to append data to
+the TPL image (such as a device tree file), you must pad out the BSS region
+to avoid the data overlapping with U-Boot variables. This entry is useful in
+that case. It automatically pads out the entry size to cover both the code,
+data and BSS.
+
+The contents of this entry will a certain number of zero bytes, determined
+by __bss_size
+
+The ELF file 'tpl/u-boot-tpl' must also be available for this to work, since
+binman uses that to look up the BSS address.
+
 
 
 Entry: u-boot-tpl-dtb: U-Boot TPL device tree
@@ -1077,6 +1187,53 @@
 
 
 
+Entry: u-boot-tpl-expanded: U-Boot TPL flat binary broken out into its component parts
+--------------------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - tpl-dtb: Controls whether this entry is selected (set to 'y' or '1' to
+        select)
+
+This is a section containing the U-Boot binary, BSS padding if needed and a
+devicetree. Using this entry type automatically creates this section, with
+the following entries in it:
+
+   u-boot-tpl-nodtb
+   u-boot-tpl-bss-pad
+   u-boot-dtb
+
+Having the devicetree separate allows binman to update it in the final
+image, so that the entries positions are provided to the running U-Boot.
+
+This entry is selected based on the value of the 'tpl-dtb' entryarg. If
+this is non-empty (and not 'n' or '0') then this expanded entry is selected.
+
+
+
+Entry: u-boot-tpl-nodtb: TPL binary without device tree appended
+----------------------------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename to include (default 'tpl/u-boot-tpl-nodtb.bin')
+
+This is the U-Boot TPL binary, It does not include a device tree blob at
+the end of it so may not be able to work without it, assuming TPL needs
+a device tree to operate on your platform. You can add a u-boot-tpl-dtb
+entry after this one, or use a u-boot-tpl entry instead, which normally
+expands to a section containing u-boot-tpl-dtb, u-boot-tpl-bss-pad and
+u-boot-tpl-dtb
+
+TPL can access binman symbols at runtime. See:
+
+    'Access to binman entry offsets at run time (symbols)'
+
+in the binman README for more information.
+
+The ELF file 'tpl/u-boot-tpl' must also be available for this to work, since
+binman uses that to look up symbols to write into the TPL binary.
+
+
+
 Entry: u-boot-tpl-with-ucode-ptr: U-Boot TPL with embedded microcode pointer
 ----------------------------------------------------------------------------
 
@@ -1147,7 +1304,7 @@
 See Entry_u_boot_ucode for full details of the three entries involved in
 this process. This entry updates U-Boot with the offset and size of the
 microcode, to allow early x86 boot code to find it without doing anything
-complicated. Otherwise it is the same as the u_boot entry.
+complicated. Otherwise it is the same as the u-boot entry.
 
 
 
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index d58a730..7022271 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -102,22 +102,30 @@
         self.allow_missing = False
 
     @staticmethod
-    def Lookup(node_path, etype):
+    def Lookup(node_path, etype, expanded):
         """Look up the entry class for a node.
 
         Args:
             node_node: Path name of Node object containing information about
                        the entry to create (used for errors)
             etype:   Entry type to use
+            expanded: Use the expanded version of etype
 
         Returns:
-            The entry class object if found, else None
+            The entry class object if found, else None if not found and expanded
+                is True
+
+        Raise:
+            ValueError if expanded is False and the class is not found
         """
         # Convert something like 'u-boot@0' to 'u_boot' since we are only
         # interested in the type.
         module_name = etype.replace('-', '_')
+
         if '@' in module_name:
             module_name = module_name.split('@')[0]
+        if expanded:
+            module_name += '_expanded'
         module = modules.get(module_name)
 
         # Also allow entry-type modules to be brought in from the etype directory.
@@ -127,6 +135,8 @@
             try:
                 module = importlib.import_module('binman.etype.' + module_name)
             except ImportError as e:
+                if expanded:
+                    return None
                 raise ValueError("Unknown entry type '%s' in node '%s' (expected etype/%s.py, error '%s'" %
                                  (etype, node_path, module_name, e))
             modules[module_name] = module
@@ -135,21 +145,32 @@
         return getattr(module, 'Entry_%s' % module_name)
 
     @staticmethod
-    def Create(section, node, etype=None):
+    def Create(section, node, etype=None, expanded=False):
         """Create a new entry for a node.
 
         Args:
-            section: Section object containing this node
-            node:    Node object containing information about the entry to
-                     create
-            etype:   Entry type to use, or None to work it out (used for tests)
+            section:  Section object containing this node
+            node:     Node object containing information about the entry to
+                      create
+            etype:    Entry type to use, or None to work it out (used for tests)
+            expanded: True to use expanded versions of entries, where available
 
         Returns:
             A new Entry object of the correct type (a subclass of Entry)
         """
         if not etype:
             etype = fdt_util.GetString(node, 'type', node.name)
-        obj = Entry.Lookup(node.path, etype)
+        obj = Entry.Lookup(node.path, etype, expanded)
+        if obj and expanded:
+            # Check whether to use the expanded entry
+            new_etype = etype + '-expanded'
+            can_expand = not fdt_util.GetBool(node, 'no-expanded')
+            if can_expand and obj.UseExpanded(node, etype, new_etype):
+                etype = new_etype
+            else:
+                obj = None
+        if not obj:
+            obj = Entry.Lookup(node.path, etype, False)
 
         # Call its constructor to get the object we want.
         return obj(section, etype, node)
@@ -180,6 +201,8 @@
         if tools.NotPowerOfTwo(self.align):
             raise ValueError("Node '%s': Alignment %s must be a power of two" %
                              (self._node.path, self.align))
+        if self.section and self.align is None:
+            self.align = self.section.align_default
         self.pad_before = fdt_util.GetInt(self._node, 'pad-before', 0)
         self.pad_after = fdt_util.GetInt(self._node, 'pad-after', 0)
         self.align_size = fdt_util.GetInt(self._node, 'align-size')
@@ -205,12 +228,23 @@
             Dict:
                 key: Filename from this entry (without the path)
                 value: Tuple:
-                    Fdt object for this dtb, or None if not available
+                    Entry object for this dtb
                     Filename of file containing this dtb
         """
         return {}
 
     def ExpandEntries(self):
+        """Expand out entries which produce other entries
+
+        Some entries generate subnodes automatically, from which sub-entries
+        are then created. This method allows those to be added to the binman
+        definition for the current image. An entry which implements this method
+        should call state.AddSubnode() to add a subnode and can add properties
+        with state.AddString(), etc.
+
+        An example is 'files', which produces a section containing a list of
+        files.
+        """
         pass
 
     def AddMissingProperties(self, have_image_pos):
@@ -406,6 +440,11 @@
         """Convenience function to raise an error referencing a node"""
         raise ValueError("Node '%s': %s" % (self._node.path, msg))
 
+    def Info(self, msg):
+        """Convenience function to log info referencing a node"""
+        tag = "Info '%s'" % self._node.path
+        tout.Detail('%30s: %s' % (tag, msg))
+
     def Detail(self, msg):
         """Convenience function to log detail referencing a node"""
         tag = "Node '%s'" % self._node.path
@@ -445,9 +484,13 @@
         """
         return self._node.path
 
-    def GetData(self):
+    def GetData(self, required=True):
         """Get the contents of an entry
 
+        Args:
+            required: True if the data must be present, False if it is OK to
+                return None
+
         Returns:
             bytes content of the entry, excluding any padding. If the entry is
                 compressed, the compressed data is returned
@@ -637,7 +680,7 @@
             modules.remove('_testing')
         missing = []
         for name in modules:
-            module = Entry.Lookup('WriteDocs', name)
+            module = Entry.Lookup('WriteDocs', name, False)
             docs = getattr(module, '__doc__')
             if test_missing == name:
                 docs = None
@@ -896,3 +939,25 @@
             self.uncomp_size = len(indata)
         data = tools.Compress(indata, self.compress)
         return data
+
+    @classmethod
+    def UseExpanded(cls, node, etype, new_etype):
+        """Check whether to use an expanded entry type
+
+        This is called by Entry.Create() when it finds an expanded version of
+        an entry type (e.g. 'u-boot-expanded'). If this method returns True then
+        it will be used (e.g. in place of 'u-boot'). If it returns False, it is
+        ignored.
+
+        Args:
+            node:     Node object containing information about the entry to
+                      create
+            etype:    Original entry type being used
+            new_etype: New entry type proposed
+
+        Returns:
+            True to use this entry type, False to use the original one
+        """
+        tout.Info("Node '%s': etype '%s': %s selected" %
+                  (node.path, etype, new_etype))
+        return True
diff --git a/tools/binman/entry_test.py b/tools/binman/entry_test.py
index 80802f3..c3d5f3e 100644
--- a/tools/binman/entry_test.py
+++ b/tools/binman/entry_test.py
@@ -87,6 +87,18 @@
         base = entry.Entry.Create(None, self.GetNode(), 'blob-dtb')
         self.assertIsNone(base.ReadChildData(base))
 
+    def testExpandedEntry(self):
+        """Test use of an expanded entry when available"""
+        base = entry.Entry.Create(None, self.GetNode())
+        self.assertEqual('u-boot', base.etype)
+
+        expanded = entry.Entry.Create(None, self.GetNode(), expanded=True)
+        self.assertEqual('u-boot-expanded', expanded.etype)
+
+        with self.assertRaises(ValueError) as e:
+            entry.Entry.Create(None, self.GetNode(), 'missing', expanded=True)
+        self.assertIn("Unknown entry type 'missing' in node '/binman/u-boot'",
+                      str(e.exception))
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/etype/atf_bl31.py b/tools/binman/etype/atf_bl31.py
index 195adc7..163d714 100644
--- a/tools/binman/etype/atf_bl31.py
+++ b/tools/binman/etype/atf_bl31.py
@@ -8,7 +8,7 @@
 from binman.etype.blob_named_by_arg import Entry_blob_named_by_arg
 
 class Entry_atf_bl31(Entry_blob_named_by_arg):
-    """Entry containing an ARM Trusted Firmware (ATF) BL31 blob
+    """ARM Trusted Firmware (ATF) BL31 blob
 
     Properties / Entry arguments:
         - atf-bl31-path: Filename of file to read into entry. This is typically
diff --git a/tools/binman/etype/blob.py b/tools/binman/etype/blob.py
index 81756c3..018f8c9 100644
--- a/tools/binman/etype/blob.py
+++ b/tools/binman/etype/blob.py
@@ -11,7 +11,7 @@
 from patman import tout
 
 class Entry_blob(Entry):
-    """Entry containing an arbitrary binary blob
+    """Arbitrary binary blob
 
     Note: This should not be used by itself. It is normally used as a parent
     class by other entry types.
@@ -24,7 +24,7 @@
 
     This entry reads data from a file and places it in the entry. The
     default filename is often specified specified by the subclass. See for
-    example the 'u_boot' entry which provides the filename 'u-boot.bin'.
+    example the 'u-boot' entry which provides the filename 'u-boot.bin'.
 
     If compression is enabled, an extra 'uncomp-size' property is written to
     the node (if enabled with -u) which provides the uncompressed size of the
diff --git a/tools/binman/etype/blob_dtb.py b/tools/binman/etype/blob_dtb.py
index 724647a..3ce7511 100644
--- a/tools/binman/etype/blob_dtb.py
+++ b/tools/binman/etype/blob_dtb.py
@@ -44,15 +44,6 @@
         return None
 
     def GetFdts(self):
-        """Get the device trees used by this entry
-
-        Returns:
-            Dict:
-                key: Filename from this entry (without the path)
-                value: Tuple:
-                    Fdt object for this dtb, or None if not available
-                    Filename of file containing this dtb
-        """
         fname = self.GetDefaultFilename()
         return {self.GetFdtEtype(): [self, fname]}
 
diff --git a/tools/binman/etype/blob_ext.py b/tools/binman/etype/blob_ext.py
index e372445..d6b0ca1 100644
--- a/tools/binman/etype/blob_ext.py
+++ b/tools/binman/etype/blob_ext.py
@@ -13,7 +13,7 @@
 from patman import tout
 
 class Entry_blob_ext(Entry_blob):
-    """Entry containing an externally built binary blob
+    """Externally built binary blob
 
     Note: This should not be used by itself. It is normally used as a parent
     class by other entry types.
diff --git a/tools/binman/etype/blob_phase.py b/tools/binman/etype/blob_phase.py
new file mode 100644
index 0000000..54ca54c
--- /dev/null
+++ b/tools/binman/etype/blob_phase.py
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type base class for U-Boot or SPL binary with devicetree
+#
+
+from binman.etype.section import Entry_section
+
+class Entry_blob_phase(Entry_section):
+    """Section that holds a phase binary
+
+    This is a base class that should not normally be used directly. It is used
+    when converting a 'u-boot' entry automatically into a 'u-boot-expanded'
+    entry; similarly for SPL.
+    """
+    def __init__(self, section, etype, node, root_fname, dtb_file, bss_pad):
+        """Set up a new blob for a phase
+
+        This holds an executable for a U-Boot phase, optional BSS padding and
+        a devicetree
+
+        Args:
+            section: entry_Section object for this entry's parent
+            etype: Type of object
+            node: Node defining this entry
+            root_fname: Root filename for the binary ('u-boot',
+                'spl/u-boot-spl', etc.)
+            dtb_file: Name of devicetree file ('u-boot.dtb', u-boot-spl.dtb',
+                etc.)
+            bss_pad: True to add BSS padding before the devicetree
+        """
+        # Put this here to allow entry-docs and help to work without libfdt
+        global state
+        from binman import state
+
+        super().__init__(section, etype, node)
+        self.root_fname = root_fname
+        self.dtb_file = dtb_file
+        self.bss_pad = bss_pad
+
+    def ExpandEntries(self):
+        """Create the subnodes"""
+        names = [self.root_fname + '-nodtb', self.root_fname + '-dtb']
+        if self.bss_pad:
+            names.insert(1, self.root_fname + '-bss-pad')
+        for name in names:
+            subnode = state.AddSubnode(self._node, name)
+
+        # Read entries again, now that we have some
+        self._ReadEntries()
diff --git a/tools/binman/etype/cbfs.py b/tools/binman/etype/cbfs.py
index 6cdbaa0..44db7b9 100644
--- a/tools/binman/etype/cbfs.py
+++ b/tools/binman/etype/cbfs.py
@@ -13,7 +13,7 @@
 from dtoc import fdt_util
 
 class Entry_cbfs(Entry):
-    """Entry containing a Coreboot Filesystem (CBFS)
+    """Coreboot Filesystem (CBFS)
 
     A CBFS provides a way to group files into a group. It has a simple directory
     structure and allows the position of individual files to be set, since it is
@@ -22,7 +22,7 @@
 
     CBFS is used by coreboot as its way of orgnanising SPI-flash contents.
 
-    The contents of the CBFS are defined by subnodes of the cbfs entry, e.g.:
+    The contents of the CBFS are defined by subnodes of the cbfs entry, e.g.::
 
         cbfs {
             size = <0x100000>;
@@ -38,7 +38,7 @@
     Note that the size is required since binman does not support calculating it.
     The contents of each entry is just what binman would normally provide if it
     were not a CBFS node. A blob type can be used to import arbitrary files as
-    with the second subnode below:
+    with the second subnode below::
 
         cbfs {
             size = <0x100000>;
@@ -84,7 +84,7 @@
             This is an ELF file that has been loaded (i.e. mapped to memory), so
             appears in the CBFS as a flat binary. The input file must be an ELF
             image, for example this puts "u-boot" (the ELF image) into a 'stage'
-            entry:
+            entry::
 
                 cbfs {
                     size = <0x100000>;
@@ -94,7 +94,7 @@
                     };
                 };
 
-            You can use your own ELF file with something like:
+            You can use your own ELF file with something like::
 
                 cbfs {
                     size = <0x100000>;
@@ -127,7 +127,7 @@
     particular offset in the CBFS and a few other things.
 
     Of course binman can create images containing multiple CBFSs, simply by
-    defining these in the binman config:
+    defining these in the binman config::
 
 
         binman {
@@ -169,6 +169,7 @@
 
         super().__init__(section, etype, node)
         self._cbfs_arg = fdt_util.GetString(node, 'cbfs-arch', 'x86')
+        self.align_default = None
         self._cbfs_entries = OrderedDict()
         self._ReadSubnodes()
         self.reader = None
diff --git a/tools/binman/etype/collection.py b/tools/binman/etype/collection.py
new file mode 100644
index 0000000..1625575
--- /dev/null
+++ b/tools/binman/etype/collection.py
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+
+# Support for a collection of entries from other parts of an image
+
+from collections import OrderedDict
+import os
+
+from binman.entry import Entry
+from dtoc import fdt_util
+
+class Entry_collection(Entry):
+    """An entry which contains a collection of other entries
+
+    Properties / Entry arguments:
+        - content: List of phandles to entries to include
+
+    This allows reusing the contents of other entries. The contents of the
+    listed entries are combined to form this entry. This serves as a useful
+    base class for entry types which need to process data from elsewhere in
+    the image, not necessarily child entries.
+    """
+    def __init__(self, section, etype, node):
+        super().__init__(section, etype, node)
+        self.content = fdt_util.GetPhandleList(self._node, 'content')
+        if not self.content:
+            self.Raise("Collection must have a 'content' property")
+
+    def GetContents(self, required):
+        """Get the contents of this entry
+
+        Args:
+            required: True if the data must be present, False if it is OK to
+                return None
+
+        Returns:
+            bytes content of the entry
+        """
+        # Join up all the data
+        self.Info('Getting contents, required=%s' % required)
+        data = b''
+        for entry_phandle in self.content:
+            entry_data = self.section.GetContentsByPhandle(entry_phandle, self,
+                                                           required)
+            if not required and entry_data is None:
+                self.Info('Contents not available yet')
+                # Data not available yet
+                return None
+            data += entry_data
+
+        self.Info('Returning contents size %x' % len(data))
+
+        return data
+
+    def ObtainContents(self):
+        data = self.GetContents(False)
+        if data is None:
+            return False
+        self.SetContents(data)
+        return True
+
+    def ProcessContents(self):
+        # The blob may have changed due to WriteSymbols()
+        data = self.GetContents(True)
+        return self.ProcessContentsUpdate(data)
diff --git a/tools/binman/etype/fdtmap.py b/tools/binman/etype/fdtmap.py
index 6ca88a1..2339fee 100644
--- a/tools/binman/etype/fdtmap.py
+++ b/tools/binman/etype/fdtmap.py
@@ -53,24 +53,24 @@
     Note that the -u option must be provided to ensure that binman updates the
     FDT with the position of each entry.
 
-    Example output for a simple image with U-Boot and an FDT map:
+    Example output for a simple image with U-Boot and an FDT map::
 
-    / {
-        image-name = "binman";
-        size = <0x00000112>;
-        image-pos = <0x00000000>;
-        offset = <0x00000000>;
-        u-boot {
-            size = <0x00000004>;
+        / {
+            image-name = "binman";
+            size = <0x00000112>;
             image-pos = <0x00000000>;
             offset = <0x00000000>;
+            u-boot {
+                size = <0x00000004>;
+                image-pos = <0x00000000>;
+                offset = <0x00000000>;
+            };
+            fdtmap {
+                size = <0x0000010e>;
+                image-pos = <0x00000004>;
+                offset = <0x00000004>;
+            };
         };
-        fdtmap {
-            size = <0x0000010e>;
-            image-pos = <0x00000004>;
-            offset = <0x00000004>;
-        };
-    };
 
     If allow-repack is used then 'orig-offset' and 'orig-size' properties are
     added as necessary. See the binman README.
diff --git a/tools/binman/etype/files.py b/tools/binman/etype/files.py
index 1feebd0..5db36ab 100644
--- a/tools/binman/etype/files.py
+++ b/tools/binman/etype/files.py
@@ -15,7 +15,7 @@
 
 
 class Entry_files(Entry_section):
-    """Entry containing a set of files
+    """A set of files arranged in a section
 
     Properties / Entry arguments:
         - pattern: Filename pattern to match the files to include
diff --git a/tools/binman/etype/fit.py b/tools/binman/etype/fit.py
index 1a7cbd7..6936f57 100644
--- a/tools/binman/etype/fit.py
+++ b/tools/binman/etype/fit.py
@@ -14,7 +14,7 @@
 from patman import tools
 
 class Entry_fit(Entry):
-    """Entry containing a FIT
+    """Flat Image Tree (FIT)
 
     This calls mkimage to create a FIT (U-Boot Flat Image Tree) based on the
     input provided.
@@ -22,7 +22,7 @@
     Nodes for the FIT should be written out in the binman configuration just as
     they would be in a file passed to mkimage.
 
-    For example, this creates an image containing a FIT with U-Boot SPL:
+    For example, this creates an image containing a FIT with U-Boot SPL::
 
         binman {
             fit {
@@ -52,7 +52,7 @@
     The fit,fdt-list property (see above) indicates that of-list should be used.
     If the property is missing you will get an error.
 
-    Then add a 'generator node', a node with a name starting with '@':
+    Then add a 'generator node', a node with a name starting with '@'::
 
         images {
             @fdt-SEQ {
@@ -67,7 +67,7 @@
     node acts like a template to generate the nodes. The generator node itself
     does not appear in the output - it is replaced with what binman generates.
 
-    You can create config nodes in a similar way:
+    You can create config nodes in a similar way::
 
         configurations {
             default = "@config-DEFAULT-SEQ";
@@ -84,8 +84,10 @@
 
     Available substitutions for '@' nodes are:
 
-        SEQ    Sequence number of the generated fdt (1, 2, ...)
-        NAME   Name of the dtb as provided (i.e. without adding '.dtb')
+    SEQ:
+        Sequence number of the generated fdt (1, 2, ...)
+    NAME
+        Name of the dtb as provided (i.e. without adding '.dtb')
 
     Note that if no devicetree files are provided (with '-a of-list' as above)
     then no nodes will be generated.
@@ -94,10 +96,11 @@
     if of configuration whose devicetree matches the 'default-dt' entry
     argument, e.g. with '-a default-dt=sun50i-a64-pine64-lts'.
 
-    Available substitutions for '@' property values are:
+    Available substitutions for '@' property values are
 
-        DEFAULT-SEQ  Sequence number of the default fdt,as provided by the
-                     'default-dt' entry argument
+    DEFAULT-SEQ:
+        Sequence number of the default fdt,as provided by the 'default-dt' entry
+        argument
 
     Properties (in the 'fit' node itself):
         fit,external-offset: Indicates that the contents of the FIT are external
diff --git a/tools/binman/etype/intel_cmc.py b/tools/binman/etype/intel_cmc.py
index 644fa42..494d43c 100644
--- a/tools/binman/etype/intel_cmc.py
+++ b/tools/binman/etype/intel_cmc.py
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_cmc(Entry_blob_ext):
-    """Entry containing an Intel Chipset Micro Code (CMC) file
+    """Intel Chipset Micro Code (CMC) file
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
diff --git a/tools/binman/etype/intel_fsp.py b/tools/binman/etype/intel_fsp.py
index 2ac012b..326cb7d 100644
--- a/tools/binman/etype/intel_fsp.py
+++ b/tools/binman/etype/intel_fsp.py
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_fsp(Entry_blob_ext):
-    """Entry containing an Intel Firmware Support Package (FSP) file
+    """Intel Firmware Support Package (FSP) file
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
diff --git a/tools/binman/etype/intel_fsp_m.py b/tools/binman/etype/intel_fsp_m.py
index 434b0f1..9bcac790 100644
--- a/tools/binman/etype/intel_fsp_m.py
+++ b/tools/binman/etype/intel_fsp_m.py
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_fsp_m(Entry_blob_ext):
-    """Entry containing Intel Firmware Support Package (FSP) memory init
+    """Intel Firmware Support Package (FSP) memory init
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
diff --git a/tools/binman/etype/intel_fsp_s.py b/tools/binman/etype/intel_fsp_s.py
index 564e122..1d5046d 100644
--- a/tools/binman/etype/intel_fsp_s.py
+++ b/tools/binman/etype/intel_fsp_s.py
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_fsp_s(Entry_blob_ext):
-    """Entry containing Intel Firmware Support Package (FSP) silicon init
+    """Intel Firmware Support Package (FSP) silicon init
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
diff --git a/tools/binman/etype/intel_fsp_t.py b/tools/binman/etype/intel_fsp_t.py
index df0c5fb..80d95cc 100644
--- a/tools/binman/etype/intel_fsp_t.py
+++ b/tools/binman/etype/intel_fsp_t.py
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_fsp_t(Entry_blob_ext):
-    """Entry containing Intel Firmware Support Package (FSP) temp ram init
+    """Intel Firmware Support Package (FSP) temp ram init
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
diff --git a/tools/binman/etype/intel_ifwi.py b/tools/binman/etype/intel_ifwi.py
index 1a0e481..903d39b 100644
--- a/tools/binman/etype/intel_ifwi.py
+++ b/tools/binman/etype/intel_ifwi.py
@@ -13,7 +13,7 @@
 from patman import tools
 
 class Entry_intel_ifwi(Entry_blob_ext):
-    """Entry containing an Intel Integrated Firmware Image (IFWI) file
+    """Intel Integrated Firmware Image (IFWI) file
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry. This is either the
@@ -37,10 +37,10 @@
     sub-partition (and optional entry name).
 
     Properties for subnodes:
-        ifwi-subpart - sub-parition to put this entry into, e.g. "IBBP"
-        ifwi-entry - entry name t use, e.g. "IBBL"
-        ifwi-replace - if present, indicates that the item should be replaced
-            in the IFWI. Otherwise it is added.
+        - ifwi-subpart: sub-parition to put this entry into, e.g. "IBBP"
+        - ifwi-entry: entry name t use, e.g. "IBBL"
+        - ifwi-replace: if present, indicates that the item should be replaced
+          in the IFWI. Otherwise it is added.
 
     See README.x86 for information about x86 binary blobs.
     """
diff --git a/tools/binman/etype/intel_me.py b/tools/binman/etype/intel_me.py
index a6fe542..b93ebab 100644
--- a/tools/binman/etype/intel_me.py
+++ b/tools/binman/etype/intel_me.py
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_me(Entry_blob_ext):
-    """Entry containing an Intel Management Engine (ME) file
+    """Intel Management Engine (ME) file
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
diff --git a/tools/binman/etype/intel_mrc.py b/tools/binman/etype/intel_mrc.py
index ccbb046..bb8b26f 100644
--- a/tools/binman/etype/intel_mrc.py
+++ b/tools/binman/etype/intel_mrc.py
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_mrc(Entry_blob_ext):
-    """Entry containing an Intel Memory Reference Code (MRC) file
+    """Intel Memory Reference Code (MRC) file
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
diff --git a/tools/binman/etype/intel_refcode.py b/tools/binman/etype/intel_refcode.py
index 5ead08b..9112730 100644
--- a/tools/binman/etype/intel_refcode.py
+++ b/tools/binman/etype/intel_refcode.py
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_refcode(Entry_blob_ext):
-    """Entry containing an Intel Reference Code file
+    """Intel Reference Code file
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
diff --git a/tools/binman/etype/intel_vbt.py b/tools/binman/etype/intel_vbt.py
index 2a98c12..8afd576 100644
--- a/tools/binman/etype/intel_vbt.py
+++ b/tools/binman/etype/intel_vbt.py
@@ -7,7 +7,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_vbt(Entry_blob_ext):
-    """Entry containing an Intel Video BIOS Table (VBT) file
+    """Intel Video BIOS Table (VBT) file
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
diff --git a/tools/binman/etype/intel_vga.py b/tools/binman/etype/intel_vga.py
index a103f1c..51e6465 100644
--- a/tools/binman/etype/intel_vga.py
+++ b/tools/binman/etype/intel_vga.py
@@ -8,7 +8,7 @@
 from binman.etype.blob_ext import Entry_blob_ext
 
 class Entry_intel_vga(Entry_blob_ext):
-    """Entry containing an Intel Video Graphics Adaptor (VGA) file
+    """Intel Video Graphics Adaptor (VGA) file
 
     Properties / Entry arguments:
         - filename: Filename of file to read into entry
diff --git a/tools/binman/etype/mkimage.py b/tools/binman/etype/mkimage.py
index 8fddc88..e499775 100644
--- a/tools/binman/etype/mkimage.py
+++ b/tools/binman/etype/mkimage.py
@@ -12,14 +12,14 @@
 from patman import tools
 
 class Entry_mkimage(Entry):
-    """Entry containing a binary produced by mkimage
+    """Binary produced by mkimage
 
     Properties / Entry arguments:
         - datafile: Filename for -d argument
         - args: Other arguments to pass
 
     The data passed to mkimage is collected from subnodes of the mkimage node,
-    e.g.:
+    e.g.::
 
         mkimage {
             args = "-n test -T imximage";
@@ -36,6 +36,7 @@
         super().__init__(section, etype, node)
         self._args = fdt_util.GetString(self._node, 'args').split(' ')
         self._mkimage_entries = OrderedDict()
+        self.align_default = None
         self._ReadSubnodes()
 
     def ObtainContents(self):
diff --git a/tools/binman/etype/scp.py b/tools/binman/etype/scp.py
index 93f8787..a9bee3c 100644
--- a/tools/binman/etype/scp.py
+++ b/tools/binman/etype/scp.py
@@ -7,7 +7,7 @@
 from binman.etype.blob_named_by_arg import Entry_blob_named_by_arg
 
 class Entry_scp(Entry_blob_named_by_arg):
-    """Entry containing a System Control Processor (SCP) firmware blob
+    """System Control Processor (SCP) firmware blob
 
     Properties / Entry arguments:
         - scp-path: Filename of file to read into the entry, typically scp.bin
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index 1ceadef..c3bac02 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -22,11 +22,13 @@
 class Entry_section(Entry):
     """Entry that contains other entries
 
-    Properties / Entry arguments: (see binman README for more information)
+    Properties / Entry arguments: (see binman README for more information):
         pad-byte: Pad byte to use when padding
         sort-by-offset: True if entries should be sorted by offset, False if
-            they must be in-order in the device tree description
+        they must be in-order in the device tree description
+
         end-at-4gb: Used to build an x86 ROM which ends at 4GB (2^32)
+
         skip-at-start: Number of bytes before the first entry starts. These
             effectively adjust the starting offset of entries. For example,
             if this is 16, then the first entry would start at 16. An entry
@@ -34,6 +36,8 @@
             file, since the first 16 bytes are skipped when writing.
         name-prefix: Adds a prefix to the name of every entry in the section
             when writing out the map
+        align_default: Default alignment for this section, if no alignment is
+            given in the entry
 
     Properties:
         allow_missing: True if this section permits external blobs to be
@@ -74,6 +78,7 @@
             if self._skip_at_start is None:
                 self._skip_at_start = 0
         self._name_prefix = fdt_util.GetString(self._node, 'name-prefix')
+        self.align_default = fdt_util.GetInt(self._node, 'align-default', 0)
         filename = fdt_util.GetString(self._node, 'filename')
         if filename:
             self._filename = filename
@@ -84,7 +89,8 @@
         for node in self._node.subnodes:
             if node.name.startswith('hash') or node.name.startswith('signature'):
                 continue
-            entry = Entry.Create(self, node)
+            entry = Entry.Create(self, node,
+                                 expanded=self.GetImage().use_expanded)
             entry.ReadNode()
             entry.SetPrefix(self._name_prefix)
             self._entries[node.name] = entry
@@ -126,12 +132,6 @@
         return True
 
     def ExpandEntries(self):
-        """Expand out any entries which have calculated sub-entries
-
-        Some entries are expanded out at runtime, e.g. 'files', which produces
-        a section containing a list of files. Process these entries so that
-        this information is added to the device tree.
-        """
         super().ExpandEntries()
         for entry in self._entries.values():
             entry.ExpandEntries()
@@ -183,7 +183,7 @@
 
         return data
 
-    def _BuildSectionData(self):
+    def _BuildSectionData(self, required):
         """Build the contents of a section
 
         This places all entries at the right place, dealing with padding before
@@ -191,13 +191,20 @@
         pad-before and pad-after properties in the section items) since that is
         handled by the parent section.
 
+        Args:
+            required: True if the data must be present, False if it is OK to
+                return None
+
         Returns:
             Contents of the section (bytes)
         """
         section_data = b''
 
         for entry in self._entries.values():
-            data = self.GetPaddedDataForEntry(entry, entry.GetData())
+            entry_data = entry.GetData(required)
+            if not required and entry_data is None:
+                return None
+            data = self.GetPaddedDataForEntry(entry, entry_data)
             # Handle empty space before the entry
             pad = (entry.offset or 0) - self._skip_at_start - len(section_data)
             if pad > 0:
@@ -229,18 +236,24 @@
             data = self.GetData()
         return section.GetPaddedDataForEntry(self, data)
 
-    def GetData(self):
+    def GetData(self, required=True):
         """Get the contents of an entry
 
         This builds the contents of the section, stores this as the contents of
         the section and returns it
 
+        Args:
+            required: True if the data must be present, False if it is OK to
+                return None
+
         Returns:
             bytes content of the section, made up for all all of its subentries.
             This excludes any padding. If the section is compressed, the
             compressed data is returned
         """
-        data = self._BuildSectionData()
+        data = self._BuildSectionData(required)
+        if data is None:
+            return None
         self.SetContents(data)
         return data
 
@@ -266,7 +279,7 @@
             self._SortEntries()
         self._ExpandEntries()
 
-        data = self._BuildSectionData()
+        data = self._BuildSectionData(True)
         self.SetContents(data)
 
         self.CheckSize()
@@ -363,16 +376,20 @@
     def GetEntries(self):
         return self._entries
 
-    def GetContentsByPhandle(self, phandle, source_entry):
+    def GetContentsByPhandle(self, phandle, source_entry, required):
         """Get the data contents of an entry specified by a phandle
 
         This uses a phandle to look up a node and and find the entry
-        associated with it. Then it returnst he contents of that entry.
+        associated with it. Then it returns the contents of that entry.
+
+        The node must be a direct subnode of this section.
 
         Args:
             phandle: Phandle to look up (integer)
             source_entry: Entry containing that phandle (used for error
                 reporting)
+            required: True if the data must be present, False if it is OK to
+                return None
 
         Returns:
             data from associated entry (as a string), or None if not found
@@ -382,7 +399,7 @@
             source_entry.Raise("Cannot find node for phandle %d" % phandle)
         for entry in self._entries.values():
             if entry._node == node:
-                return entry.GetData()
+                return entry.GetData(required)
         source_entry.Raise("Cannot find entry for node '%s'" % node.name)
 
     def LookupSymbol(self, sym_name, optional, msg, base_addr, entries=None):
diff --git a/tools/binman/etype/text.py b/tools/binman/etype/text.py
index a69c2a4..45dfcc4 100644
--- a/tools/binman/etype/text.py
+++ b/tools/binman/etype/text.py
@@ -25,7 +25,7 @@
         <text>: The text to place in the entry (overrides the above mechanism).
             This is useful when the text is constant.
 
-    Example node:
+    Example node::
 
         text {
             size = <50>;
@@ -38,7 +38,7 @@
 
     and binman will insert that string into the entry.
 
-    It is also possible to put the string directly in the node:
+    It is also possible to put the string directly in the node::
 
         text {
             size = <8>;
@@ -46,7 +46,7 @@
             message = "a message directly in the node"
         };
 
-    or just:
+    or just::
 
         text {
             size = <8>;
diff --git a/tools/binman/etype/u_boot.py b/tools/binman/etype/u_boot.py
index 4767197..e8d180a 100644
--- a/tools/binman/etype/u_boot.py
+++ b/tools/binman/etype/u_boot.py
@@ -2,7 +2,7 @@
 # Copyright (c) 2016 Google, Inc
 # Written by Simon Glass <sjg@chromium.org>
 #
-# Entry-type module for U-Boot binary
+# Entry-type module for the expanded U-Boot binary
 #
 
 from binman.entry import Entry
@@ -16,14 +16,16 @@
 
     This is the U-Boot binary, containing relocation information to allow it
     to relocate itself at runtime. The binary typically includes a device tree
-    blob at the end of it. Use u_boot_nodtb if you want to package the device
-    tree separately.
+    blob at the end of it.
 
     U-Boot can access binman symbols at runtime. See:
 
         'Access to binman entry offsets at run time (fdt)'
 
     in the binman README for more information.
+
+    Note that this entry is automatically replaced with u-boot-expanded unless
+    --no-expanded is used or the node has a 'no-expanded' property.
     """
     def __init__(self, section, etype, node):
         super().__init__(section, etype, node)
diff --git a/tools/binman/etype/u_boot_dtb_with_ucode.py b/tools/binman/etype/u_boot_dtb_with_ucode.py
index 66a9db5..554b3b2 100644
--- a/tools/binman/etype/u_boot_dtb_with_ucode.py
+++ b/tools/binman/etype/u_boot_dtb_with_ucode.py
@@ -19,9 +19,9 @@
     this process. This entry provides the U-Boot device-tree file, which
     contains the microcode. If the microcode is not being collated into one
     place then the offset and size of the microcode is recorded by this entry,
-    for use by u_boot_with_ucode_ptr. If it is being collated, then this
+    for use by u-boot-with-ucode_ptr. If it is being collated, then this
     entry deletes the microcode from the device tree (to save space) and makes
-    it available to u_boot_ucode.
+    it available to u-boot-ucode.
     """
     def __init__(self, section, etype, node):
         # Put this here to allow entry-docs and help to work without libfdt
diff --git a/tools/binman/etype/u_boot_expanded.py b/tools/binman/etype/u_boot_expanded.py
new file mode 100644
index 0000000..8797824
--- /dev/null
+++ b/tools/binman/etype/u_boot_expanded.py
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for U-Boot binary
+#
+
+from binman.etype.blob_phase import Entry_blob_phase
+
+class Entry_u_boot_expanded(Entry_blob_phase):
+    """U-Boot flat binary broken out into its component parts
+
+    This is a section containing the U-Boot binary and a devicetree. Using this
+    entry type automatically creates this section, with the following entries
+    in it:
+
+       u-boot-nodtb
+       u-boot-dtb
+
+    Having the devicetree separate allows binman to update it in the final
+    image, so that the entries positions are provided to the running U-Boot.
+    """
+    def __init__(self, section, etype, node):
+        super().__init__(section, etype, node, 'u-boot', 'u-boot-dtb', False)
diff --git a/tools/binman/etype/u_boot_nodtb.py b/tools/binman/etype/u_boot_nodtb.py
index e84df49..347ba7d 100644
--- a/tools/binman/etype/u_boot_nodtb.py
+++ b/tools/binman/etype/u_boot_nodtb.py
@@ -12,13 +12,13 @@
     """U-Boot flat binary without device tree appended
 
     Properties / Entry arguments:
-        - filename: Filename of u-boot.bin (default 'u-boot-nodtb.bin')
+        - filename: Filename to include (default 'u-boot-nodtb.bin')
 
     This is the U-Boot binary, containing relocation information to allow it
     to relocate itself at runtime. It does not include a device tree blob at
-    the end of it so normally cannot work without it. You can add a u_boot_dtb
-    entry after this one, or use a u_boot entry instead (which contains both
-    U-Boot and the device tree).
+    the end of it so normally cannot work without it. You can add a u-boot-dtb
+    entry after this one, or use a u-boot entry instead, normally expands to a
+    section containing u-boot and u-boot-dtb
     """
     def __init__(self, section, etype, node):
         super().__init__(section, etype, node)
diff --git a/tools/binman/etype/u_boot_spl.py b/tools/binman/etype/u_boot_spl.py
index d66e461..6f79bf5 100644
--- a/tools/binman/etype/u_boot_spl.py
+++ b/tools/binman/etype/u_boot_spl.py
@@ -30,6 +30,9 @@
 
     The ELF file 'spl/u-boot-spl' must also be available for this to work, since
     binman uses that to look up symbols to write into the SPL binary.
+
+    Note that this entry is automatically replaced with u-boot-spl-expanded
+    unless --no-expanded is used or the node has a 'no-expanded' property.
     """
     def __init__(self, section, etype, node):
         super().__init__(section, etype, node)
diff --git a/tools/binman/etype/u_boot_spl_bss_pad.py b/tools/binman/etype/u_boot_spl_bss_pad.py
index df15cd2..18c5596 100644
--- a/tools/binman/etype/u_boot_spl_bss_pad.py
+++ b/tools/binman/etype/u_boot_spl_bss_pad.py
@@ -18,13 +18,16 @@
     Properties / Entry arguments:
         None
 
-    This is similar to u_boot_spl except that padding is added after the SPL
-    binary to cover the BSS (Block Started by Symbol) region. This region holds
-    the various used by SPL. It is set to 0 by SPL when it starts up. If you
-    want to append data to the SPL image (such as a device tree file), you must
-    pad out the BSS region to avoid the data overlapping with U-Boot variables.
-    This entry is useful in that case. It automatically pads out the entry size
-    to cover both the code, data and BSS.
+    This holds the padding added after the SPL binary to cover the BSS (Block
+    Started by Symbol) region. This region holds the various variables used by
+    SPL. It is set to 0 by SPL when it starts up. If you want to append data to
+    the SPL image (such as a device tree file), you must pad out the BSS region
+    to avoid the data overlapping with U-Boot variables. This entry is useful in
+    that case. It automatically pads out the entry size to cover both the code,
+    data and BSS.
+
+    The contents of this entry will a certain number of zero bytes, determined
+    by __bss_size
 
     The ELF file 'spl/u-boot-spl' must also be available for this to work, since
     binman uses that to look up the BSS address.
diff --git a/tools/binman/etype/u_boot_spl_expanded.py b/tools/binman/etype/u_boot_spl_expanded.py
new file mode 100644
index 0000000..8e138e6
--- /dev/null
+++ b/tools/binman/etype/u_boot_spl_expanded.py
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for expanded U-Boot SPL binary
+#
+
+from patman import tout
+
+from binman import state
+from binman.etype.blob_phase import Entry_blob_phase
+
+class Entry_u_boot_spl_expanded(Entry_blob_phase):
+    """U-Boot SPL flat binary broken out into its component parts
+
+    Properties / Entry arguments:
+        - spl-dtb: Controls whether this entry is selected (set to 'y' or '1' to
+            select)
+
+    This is a section containing the U-Boot binary, BSS padding if needed and a
+    devicetree. Using this entry type automatically creates this section, with
+    the following entries in it:
+
+       u-boot-spl-nodtb
+       u-boot-spl-bss-pad
+       u-boot-dtb
+
+    Having the devicetree separate allows binman to update it in the final
+    image, so that the entries positions are provided to the running U-Boot.
+
+    This entry is selected based on the value of the 'spl-dtb' entryarg. If
+    this is non-empty (and not 'n' or '0') then this expanded entry is selected.
+    """
+    def __init__(self, section, etype, node):
+        bss_pad = state.GetEntryArgBool('spl-bss-pad')
+        super().__init__(section, etype, node, 'u-boot-spl', 'u-boot-spl-dtb',
+                         bss_pad)
+
+    @classmethod
+    def UseExpanded(cls, node, etype, new_etype):
+        val = state.GetEntryArgBool('spl-dtb')
+        tout.DoOutput(tout.INFO if val else tout.DETAIL,
+                      "Node '%s': etype '%s': %s %sselected" %
+                      (node.path, etype, new_etype, '' if val else 'not '))
+        return val
diff --git a/tools/binman/etype/u_boot_spl_nodtb.py b/tools/binman/etype/u_boot_spl_nodtb.py
index c154cfd..316b381 100644
--- a/tools/binman/etype/u_boot_spl_nodtb.py
+++ b/tools/binman/etype/u_boot_spl_nodtb.py
@@ -5,6 +5,7 @@
 # Entry-type module for 'u-boot-spl-nodtb.bin'
 #
 
+from binman import elf
 from binman.entry import Entry
 from binman.etype.blob import Entry_blob
 
@@ -12,17 +13,30 @@
     """SPL binary without device tree appended
 
     Properties / Entry arguments:
-        - filename: Filename of spl/u-boot-spl-nodtb.bin (default
-            'spl/u-boot-spl-nodtb.bin')
+        - filename: Filename to include (default 'spl/u-boot-spl-nodtb.bin')
 
     This is the U-Boot SPL binary, It does not include a device tree blob at
     the end of it so may not be able to work without it, assuming SPL needs
-    a device tree to operation on your platform. You can add a u_boot_spl_dtb
-    entry after this one, or use a u_boot_spl entry instead (which contains
-    both SPL and the device tree).
+    a device tree to operate on your platform. You can add a u-boot-spl-dtb
+    entry after this one, or use a u-boot-spl entry instead' which normally
+    expands to a section containing u-boot-spl-dtb, u-boot-spl-bss-pad and
+    u-boot-spl-dtb
+
+    SPL can access binman symbols at runtime. See:
+
+        'Access to binman entry offsets at run time (symbols)'
+
+    in the binman README for more information.
+
+    The ELF file 'spl/u-boot-spl' must also be available for this to work, since
+    binman uses that to look up symbols to write into the SPL binary.
     """
     def __init__(self, section, etype, node):
         super().__init__(section, etype, node)
+        self.elf_fname = 'spl/u-boot-spl'
 
     def GetDefaultFilename(self):
         return 'spl/u-boot-spl-nodtb.bin'
+
+    def WriteSymbols(self, section):
+        elf.LookupAndWriteSymbols(self.elf_fname, self, section.GetImage())
diff --git a/tools/binman/etype/u_boot_tpl.py b/tools/binman/etype/u_boot_tpl.py
index 02287ab..0c575df 100644
--- a/tools/binman/etype/u_boot_tpl.py
+++ b/tools/binman/etype/u_boot_tpl.py
@@ -30,6 +30,9 @@
 
     The ELF file 'tpl/u-boot-tpl' must also be available for this to work, since
     binman uses that to look up symbols to write into the TPL binary.
+
+    Note that this entry is automatically replaced with u-boot-tpl-expanded
+    unless --no-expanded is used or the node has a 'no-expanded' property.
     """
     def __init__(self, section, etype, node):
         super().__init__(section, etype, node)
diff --git a/tools/binman/etype/u_boot_tpl_bss_pad.py b/tools/binman/etype/u_boot_tpl_bss_pad.py
new file mode 100644
index 0000000..521b24a
--- /dev/null
+++ b/tools/binman/etype/u_boot_tpl_bss_pad.py
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for BSS padding for tpl/u-boot-tpl.bin. This padding
+# can be added after the TPL binary to ensure that anything concatenated
+# to it will appear to TPL to be at the end of BSS rather than the start.
+#
+
+from binman import elf
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
+from patman import tools
+
+class Entry_u_boot_tpl_bss_pad(Entry_blob):
+    """U-Boot TPL binary padded with a BSS region
+
+    Properties / Entry arguments:
+        None
+
+    This holds the padding added after the TPL binary to cover the BSS (Block
+    Started by Symbol) region. This region holds the various variables used by
+    TPL. It is set to 0 by TPL when it starts up. If you want to append data to
+    the TPL image (such as a device tree file), you must pad out the BSS region
+    to avoid the data overlapping with U-Boot variables. This entry is useful in
+    that case. It automatically pads out the entry size to cover both the code,
+    data and BSS.
+
+    The contents of this entry will a certain number of zero bytes, determined
+    by __bss_size
+
+    The ELF file 'tpl/u-boot-tpl' must also be available for this to work, since
+    binman uses that to look up the BSS address.
+    """
+    def __init__(self, section, etype, node):
+        super().__init__(section, etype, node)
+
+    def ObtainContents(self):
+        fname = tools.GetInputFilename('tpl/u-boot-tpl')
+        bss_size = elf.GetSymbolAddress(fname, '__bss_size')
+        if not bss_size:
+            self.Raise('Expected __bss_size symbol in tpl/u-boot-tpl')
+        self.SetContents(tools.GetBytes(0, bss_size))
+        return True
diff --git a/tools/binman/etype/u_boot_tpl_expanded.py b/tools/binman/etype/u_boot_tpl_expanded.py
new file mode 100644
index 0000000..15cdac4
--- /dev/null
+++ b/tools/binman/etype/u_boot_tpl_expanded.py
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for expanded U-Boot TPL binary
+#
+
+from patman import tout
+
+from binman import state
+from binman.etype.blob_phase import Entry_blob_phase
+
+class Entry_u_boot_tpl_expanded(Entry_blob_phase):
+    """U-Boot TPL flat binary broken out into its component parts
+
+    Properties / Entry arguments:
+        - tpl-dtb: Controls whether this entry is selected (set to 'y' or '1' to
+            select)
+
+    This is a section containing the U-Boot binary, BSS padding if needed and a
+    devicetree. Using this entry type automatically creates this section, with
+    the following entries in it:
+
+       u-boot-tpl-nodtb
+       u-boot-tpl-bss-pad
+       u-boot-dtb
+
+    Having the devicetree separate allows binman to update it in the final
+    image, so that the entries positions are provided to the running U-Boot.
+
+    This entry is selected based on the value of the 'tpl-dtb' entryarg. If
+    this is non-empty (and not 'n' or '0') then this expanded entry is selected.
+    """
+    def __init__(self, section, etype, node):
+        bss_pad = state.GetEntryArgBool('tpl-bss-pad')
+        super().__init__(section, etype, node, 'u-boot-tpl', 'u-boot-tpl-dtb',
+                         bss_pad)
+
+    @classmethod
+    def UseExpanded(cls, node, etype, new_etype):
+        val = state.GetEntryArgBool('tpl-dtb')
+        tout.DoOutput(tout.INFO if val else tout.DETAIL,
+                      "Node '%s': etype '%s': %s %sselected" %
+                      (node.path, etype, new_etype, '' if val else 'not '))
+        return val
diff --git a/tools/binman/etype/u_boot_tpl_nodtb.py b/tools/binman/etype/u_boot_tpl_nodtb.py
new file mode 100644
index 0000000..98f3853
--- /dev/null
+++ b/tools/binman/etype/u_boot_tpl_nodtb.py
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for 'u-boot-tpl-nodtb.bin'
+#
+
+from binman import elf
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
+
+class Entry_u_boot_tpl_nodtb(Entry_blob):
+    """TPL binary without device tree appended
+
+    Properties / Entry arguments:
+        - filename: Filename to include (default 'tpl/u-boot-tpl-nodtb.bin')
+
+    This is the U-Boot TPL binary, It does not include a device tree blob at
+    the end of it so may not be able to work without it, assuming TPL needs
+    a device tree to operate on your platform. You can add a u-boot-tpl-dtb
+    entry after this one, or use a u-boot-tpl entry instead, which normally
+    expands to a section containing u-boot-tpl-dtb, u-boot-tpl-bss-pad and
+    u-boot-tpl-dtb
+
+    TPL can access binman symbols at runtime. See:
+
+        'Access to binman entry offsets at run time (symbols)'
+
+    in the binman README for more information.
+
+    The ELF file 'tpl/u-boot-tpl' must also be available for this to work, since
+    binman uses that to look up symbols to write into the TPL binary.
+    """
+    def __init__(self, section, etype, node):
+        super().__init__(section, etype, node)
+        self.elf_fname = 'tpl/u-boot-tpl'
+
+    def GetDefaultFilename(self):
+        return 'tpl/u-boot-tpl-nodtb.bin'
+
+    def WriteSymbols(self, section):
+        elf.LookupAndWriteSymbols(self.elf_fname, self, section.GetImage())
diff --git a/tools/binman/etype/u_boot_with_ucode_ptr.py b/tools/binman/etype/u_boot_with_ucode_ptr.py
index 92d2fc6..20be22a 100644
--- a/tools/binman/etype/u_boot_with_ucode_ptr.py
+++ b/tools/binman/etype/u_boot_with_ucode_ptr.py
@@ -26,7 +26,7 @@
     See Entry_u_boot_ucode for full details of the three entries involved in
     this process. This entry updates U-Boot with the offset and size of the
     microcode, to allow early x86 boot code to find it without doing anything
-    complicated. Otherwise it is the same as the u_boot entry.
+    complicated. Otherwise it is the same as the u-boot entry.
     """
     def __init__(self, section, etype, node):
         super().__init__(section, etype, node)
diff --git a/tools/binman/etype/vblock.py b/tools/binman/etype/vblock.py
index eba5351..c0a6a28 100644
--- a/tools/binman/etype/vblock.py
+++ b/tools/binman/etype/vblock.py
@@ -9,12 +9,13 @@
 from collections import OrderedDict
 import os
 
-from binman.entry import Entry, EntryArg
+from binman.entry import EntryArg
+from binman.etype.collection import Entry_collection
 
 from dtoc import fdt_util
 from patman import tools
 
-class Entry_vblock(Entry):
+class Entry_vblock(Entry_collection):
     """An entry which contains a Chromium OS verified boot block
 
     Properties / Entry arguments:
@@ -37,9 +38,6 @@
     """
     def __init__(self, section, etype, node):
         super().__init__(section, etype, node)
-        self.content = fdt_util.GetPhandleList(self._node, 'content')
-        if not self.content:
-            self.Raise("Vblock must have a 'content' property")
         (self.keydir, self.keyblock, self.signprivate, self.version,
          self.kernelkey, self.preamble_flags) = self.GetEntryArgsOrProps([
             EntryArg('keydir', str),
@@ -49,15 +47,21 @@
             EntryArg('kernelkey', str),
             EntryArg('preamble-flags', int)])
 
-    def GetVblock(self):
+    def GetVblock(self, required):
+        """Get the contents of this entry
+
+        Args:
+            required: True if the data must be present, False if it is OK to
+                return None
+
+        Returns:
+            bytes content of the entry, which is the signed vblock for the
+                provided data
+        """
         # Join up the data files to be signed
-        input_data = b''
-        for entry_phandle in self.content:
-            data = self.section.GetContentsByPhandle(entry_phandle, self)
-            if data is None:
-                # Data not available yet
-                return False
-            input_data += data
+        input_data = self.GetContents(required)
+        if input_data is None:
+            return None
 
         uniq = self.GetUniqueName()
         output_fname = tools.GetOutputFilename('vblock.%s' % uniq)
@@ -79,13 +83,13 @@
         return tools.ReadFile(output_fname)
 
     def ObtainContents(self):
-        data = self.GetVblock()
-        if data is False:
+        data = self.GetVblock(False)
+        if data is None:
             return False
         self.SetContents(data)
         return True
 
     def ProcessContents(self):
         # The blob may have changed due to WriteSymbols()
-        data = self.GetVblock()
+        data = self.GetVblock(True)
         return self.ProcessContentsUpdate(data)
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 814e91d..89fe661 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -305,7 +305,8 @@
 
     def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
                     entry_args=None, images=None, use_real_dtb=False,
-                    verbosity=None, allow_missing=False, extra_indirs=None):
+                    use_expanded=False, verbosity=None, allow_missing=False,
+                    extra_indirs=None):
         """Run binman with a given test file
 
         Args:
@@ -322,6 +323,8 @@
                 the u-boot-dtb entry. Normally this is not needed and the
                 test contents (the U_BOOT_DTB_DATA string) can be used.
                 But in some test we need the real contents.
+            use_expanded: True to use expanded entries where available, e.g.
+                'u-boot-expanded' instead of 'u-boot'
             verbosity: Verbosity level to use (0-3, None=don't set it)
             allow_missing: Set the '--allow-missing' flag so that missing
                 external binaries just produce a warning instead of an error
@@ -344,6 +347,8 @@
             args.append('-u')
         if not use_real_dtb:
             args.append('--fake-dtb')
+        if not use_expanded:
+            args.append('--no-expanded')
         if entry_args:
             for arg, value in entry_args.items():
                 args.append('-a%s=%s' % (arg, value))
@@ -403,9 +408,9 @@
         dtb.Pack()
         return dtb.GetContents()
 
-    def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
-                       update_dtb=False, entry_args=None, reset_dtbs=True,
-                       extra_indirs=None):
+    def _DoReadFileDtb(self, fname, use_real_dtb=False, use_expanded=False,
+                       map=False, update_dtb=False, entry_args=None,
+                       reset_dtbs=True, extra_indirs=None):
         """Run binman and return the resulting image
 
         This runs binman with a given test file and then reads the resulting
@@ -420,6 +425,8 @@
                 the u-boot-dtb entry. Normally this is not needed and the
                 test contents (the U_BOOT_DTB_DATA string) can be used.
                 But in some test we need the real contents.
+            use_expanded: True to use expanded entries where available, e.g.
+                'u-boot-expanded' instead of 'u-boot'
             map: True to output map files for the images
             update_dtb: Update the offset and size of each entry in the device
                 tree before packing it into the image
@@ -454,7 +461,7 @@
         try:
             retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
                     entry_args=entry_args, use_real_dtb=use_real_dtb,
-                    extra_indirs=extra_indirs)
+                    use_expanded=use_expanded, extra_indirs=extra_indirs)
             self.assertEqual(0, retcode)
             out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
 
@@ -624,7 +631,7 @@
     def testFullHelp(self):
         """Test that the full help is displayed with -H"""
         result = self._RunBinman('-H')
-        help_file = os.path.join(self._binman_dir, 'README')
+        help_file = os.path.join(self._binman_dir, 'README.rst')
         # Remove possible extraneous strings
         extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
         gothelp = result.stdout.replace(extra, '')
@@ -637,7 +644,7 @@
         try:
             command.test_result = command.CommandResult()
             result = self._DoBinman('-H')
-            help_file = os.path.join(self._binman_dir, 'README')
+            help_file = os.path.join(self._binman_dir, 'README.rst')
         finally:
             command.test_result = None
 
@@ -652,7 +659,7 @@
         """Test that we can run it with a specific board"""
         self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
         TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
-        result = self._DoBinman('build', '-b', 'sandbox')
+        result = self._DoBinman('build', '-n', '-b', 'sandbox')
         self.assertEqual(0, result)
 
     def testNeedBoard(self):
@@ -1337,21 +1344,50 @@
         data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
         self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
 
-    def testSymbols(self):
-        """Test binman can assign symbols embedded in U-Boot"""
+    def checkSymbols(self, dts, base_data, u_boot_offset, entry_args=None,
+                     use_expanded=False):
+        """Check the image contains the expected symbol values
+
+        Args:
+            dts: Device tree file to use for test
+            base_data: Data before and after 'u-boot' section
+            u_boot_offset: Offset of 'u-boot' section in image
+            entry_args: Dict of entry args to supply to binman
+                key: arg name
+                value: value of that arg
+            use_expanded: True to use expanded entries where available, e.g.
+                'u-boot-expanded' instead of 'u-boot'
+        """
         elf_fname = self.ElfTestFile('u_boot_binman_syms')
         syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
         addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
-        self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
+        self.assertEqual(syms['_binman_u_boot_spl_any_prop_offset'].address,
+                         addr)
 
         self._SetupSplElf('u_boot_binman_syms')
-        data = self._DoReadFile('053_symbols.dts')
-        sym_values = struct.pack('<LQLL', 0x00, 0x1c, 0x28, 0x04)
-        expected = (sym_values + U_BOOT_SPL_DATA[20:] +
+        data = self._DoReadFileDtb(dts, entry_args=entry_args,
+                                   use_expanded=use_expanded)[0]
+        # The image should contain the symbols from u_boot_binman_syms.c
+        # Note that image_pos is adjusted by the base address of the image,
+        # which is 0x10 in our test image
+        sym_values = struct.pack('<LQLL', 0x00,
+                                 u_boot_offset + len(U_BOOT_DATA),
+                                 0x10 + u_boot_offset, 0x04)
+        expected = (sym_values + base_data[20:] +
                     tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
-                    U_BOOT_SPL_DATA[20:])
+                    base_data[20:])
         self.assertEqual(expected, data)
 
+    def testSymbols(self):
+        """Test binman can assign symbols embedded in U-Boot"""
+        self.checkSymbols('053_symbols.dts', U_BOOT_SPL_DATA, 0x18)
+
+    def testSymbolsNoDtb(self):
+        """Test binman can assign symbols embedded in U-Boot SPL"""
+        self.checkSymbols('196_symbols_nodtb.dts',
+                          U_BOOT_SPL_NODTB_DATA + U_BOOT_SPL_DTB_DATA,
+                          0x38)
+
     def testPackUnitAddress(self):
         """Test that we support multiple binaries with the same name"""
         data = self._DoReadFile('054_unit_address.dts')
@@ -1682,7 +1718,7 @@
         """Test we detect a vblock which has no content to sign"""
         with self.assertRaises(ValueError) as e:
             self._DoReadFile('075_vblock_no_content.dts')
-        self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
+        self.assertIn("Node '/binman/vblock': Collection must have a 'content' "
                       'property', str(e.exception))
 
     def testVblockBadPhandle(self):
@@ -4186,18 +4222,7 @@
 
     def testSymbolsSubsection(self):
         """Test binman can assign symbols from a subsection"""
-        elf_fname = self.ElfTestFile('u_boot_binman_syms')
-        syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
-        addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
-        self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
-
-        self._SetupSplElf('u_boot_binman_syms')
-        data = self._DoReadFile('187_symbols_sub.dts')
-        sym_values = struct.pack('<LQLL', 0x00, 0x1c, 0x28, 0x04)
-        expected = (sym_values + U_BOOT_SPL_DATA[20:] +
-                    tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
-                    U_BOOT_SPL_DATA[20:])
-        self.assertEqual(expected, data)
+        self.checkSymbols('187_symbols_sub.dts', U_BOOT_SPL_DATA, 0x18)
 
     def testReadImageEntryArg(self):
         """Test reading an image that would need an entry arg to generate"""
@@ -4245,6 +4270,244 @@
 
         self.assertEquals(U_BOOT_DATA, u_boot.ReadData())
 
+    def testTplNoDtb(self):
+        """Test that an image with tpl/u-boot-tpl-nodtb.bin can be created"""
+        data = self._DoReadFile('192_u_boot_tpl_nodtb.dts')
+        self.assertEqual(U_BOOT_TPL_NODTB_DATA,
+                         data[:len(U_BOOT_TPL_NODTB_DATA)])
+
+    def testTplBssPad(self):
+        """Test that we can pad TPL's BSS with zeros"""
+        # ELF file with a '__bss_size' symbol
+        self._SetupTplElf()
+        data = self._DoReadFile('193_tpl_bss_pad.dts')
+        self.assertEqual(U_BOOT_TPL_DATA + tools.GetBytes(0, 10) + U_BOOT_DATA,
+                         data)
+
+    def testTplBssPadMissing(self):
+        """Test that a missing symbol is detected"""
+        self._SetupTplElf('u_boot_ucode_ptr')
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('193_tpl_bss_pad.dts')
+        self.assertIn('Expected __bss_size symbol in tpl/u-boot-tpl',
+                      str(e.exception))
+
+    def checkDtbSizes(self, data, pad_len, start):
+        """Check the size arguments in a dtb embedded in an image
+
+        Args:
+            data: The image data
+            pad_len: Length of the pad section in the image, in bytes
+            start: Start offset of the devicetree to examine, within the image
+
+        Returns:
+            Size of the devicetree in bytes
+        """
+        dtb_data = data[start:]
+        dtb = fdt.Fdt.FromData(dtb_data)
+        fdt_size = dtb.GetFdtObj().totalsize()
+        dtb.Scan()
+        props = self._GetPropTree(dtb, 'size')
+        self.assertEqual({
+            'size': len(data),
+            'u-boot-spl/u-boot-spl-bss-pad:size': pad_len,
+            'u-boot-spl/u-boot-spl-dtb:size': 801,
+            'u-boot-spl/u-boot-spl-nodtb:size': len(U_BOOT_SPL_NODTB_DATA),
+            'u-boot-spl:size': 860,
+            'u-boot-tpl:size': len(U_BOOT_TPL_DATA),
+            'u-boot/u-boot-dtb:size': 781,
+            'u-boot/u-boot-nodtb:size': len(U_BOOT_NODTB_DATA),
+            'u-boot:size': 827,
+            }, props)
+        return fdt_size
+
+    def testExpanded(self):
+        """Test that an expanded entry type is selected when needed"""
+        self._SetupSplElf()
+        self._SetupTplElf()
+
+        # SPL has a devicetree, TPL does not
+        entry_args = {
+            'spl-dtb': '1',
+            'spl-bss-pad': 'y',
+            'tpl-dtb': '',
+        }
+        self._DoReadFileDtb('194_fdt_incl.dts', use_expanded=True,
+                            entry_args=entry_args)
+        image = control.images['image']
+        entries = image.GetEntries()
+        self.assertEqual(3, len(entries))
+
+        # First, u-boot, which should be expanded into u-boot-nodtb and dtb
+        self.assertIn('u-boot', entries)
+        entry = entries['u-boot']
+        self.assertEqual('u-boot-expanded', entry.etype)
+        subent = entry.GetEntries()
+        self.assertEqual(2, len(subent))
+        self.assertIn('u-boot-nodtb', subent)
+        self.assertIn('u-boot-dtb', subent)
+
+        # Second, u-boot-spl, which should be expanded into three parts
+        self.assertIn('u-boot-spl', entries)
+        entry = entries['u-boot-spl']
+        self.assertEqual('u-boot-spl-expanded', entry.etype)
+        subent = entry.GetEntries()
+        self.assertEqual(3, len(subent))
+        self.assertIn('u-boot-spl-nodtb', subent)
+        self.assertIn('u-boot-spl-bss-pad', subent)
+        self.assertIn('u-boot-spl-dtb', subent)
+
+        # Third, u-boot-tpl, which should be not be expanded, since TPL has no
+        # devicetree
+        self.assertIn('u-boot-tpl', entries)
+        entry = entries['u-boot-tpl']
+        self.assertEqual('u-boot-tpl', entry.etype)
+        self.assertEqual(None, entry.GetEntries())
+
+    def testExpandedTpl(self):
+        """Test that an expanded entry type is selected for TPL when needed"""
+        self._SetupTplElf()
+
+        entry_args = {
+            'tpl-bss-pad': 'y',
+            'tpl-dtb': 'y',
+        }
+        self._DoReadFileDtb('195_fdt_incl_tpl.dts', use_expanded=True,
+                            entry_args=entry_args)
+        image = control.images['image']
+        entries = image.GetEntries()
+        self.assertEqual(1, len(entries))
+
+        # We only have u-boot-tpl, which be expanded
+        self.assertIn('u-boot-tpl', entries)
+        entry = entries['u-boot-tpl']
+        self.assertEqual('u-boot-tpl-expanded', entry.etype)
+        subent = entry.GetEntries()
+        self.assertEqual(3, len(subent))
+        self.assertIn('u-boot-tpl-nodtb', subent)
+        self.assertIn('u-boot-tpl-bss-pad', subent)
+        self.assertIn('u-boot-tpl-dtb', subent)
+
+    def testExpandedNoPad(self):
+        """Test an expanded entry without BSS pad enabled"""
+        self._SetupSplElf()
+        self._SetupTplElf()
+
+        # SPL has a devicetree, TPL does not
+        entry_args = {
+            'spl-dtb': 'something',
+            'spl-bss-pad': 'n',
+            'tpl-dtb': '',
+        }
+        self._DoReadFileDtb('194_fdt_incl.dts', use_expanded=True,
+                            entry_args=entry_args)
+        image = control.images['image']
+        entries = image.GetEntries()
+
+        # Just check u-boot-spl, which should be expanded into two parts
+        self.assertIn('u-boot-spl', entries)
+        entry = entries['u-boot-spl']
+        self.assertEqual('u-boot-spl-expanded', entry.etype)
+        subent = entry.GetEntries()
+        self.assertEqual(2, len(subent))
+        self.assertIn('u-boot-spl-nodtb', subent)
+        self.assertIn('u-boot-spl-dtb', subent)
+
+    def testExpandedTplNoPad(self):
+        """Test that an expanded entry type with padding disabled in TPL"""
+        self._SetupTplElf()
+
+        entry_args = {
+            'tpl-bss-pad': '',
+            'tpl-dtb': 'y',
+        }
+        self._DoReadFileDtb('195_fdt_incl_tpl.dts', use_expanded=True,
+                            entry_args=entry_args)
+        image = control.images['image']
+        entries = image.GetEntries()
+        self.assertEqual(1, len(entries))
+
+        # We only have u-boot-tpl, which be expanded
+        self.assertIn('u-boot-tpl', entries)
+        entry = entries['u-boot-tpl']
+        self.assertEqual('u-boot-tpl-expanded', entry.etype)
+        subent = entry.GetEntries()
+        self.assertEqual(2, len(subent))
+        self.assertIn('u-boot-tpl-nodtb', subent)
+        self.assertIn('u-boot-tpl-dtb', subent)
+
+    def testFdtInclude(self):
+        """Test that an Fdt is update within all binaries"""
+        self._SetupSplElf()
+        self._SetupTplElf()
+
+        # SPL has a devicetree, TPL does not
+        self.maxDiff = None
+        entry_args = {
+            'spl-dtb': '1',
+            'spl-bss-pad': 'y',
+            'tpl-dtb': '',
+        }
+        # Build the image. It includes two separate devicetree binaries, each
+        # with their own contents, but all contain the binman definition.
+        data = self._DoReadFileDtb(
+            '194_fdt_incl.dts', use_real_dtb=True, use_expanded=True,
+            update_dtb=True, entry_args=entry_args)[0]
+        pad_len = 10
+
+        # Check the U-Boot dtb
+        start = len(U_BOOT_NODTB_DATA)
+        fdt_size = self.checkDtbSizes(data, pad_len, start)
+
+        # Now check SPL
+        start += fdt_size + len(U_BOOT_SPL_NODTB_DATA) + pad_len
+        fdt_size = self.checkDtbSizes(data, pad_len, start)
+
+        # TPL has no devicetree
+        start += fdt_size + len(U_BOOT_TPL_DATA)
+        self.assertEqual(len(data), start)
+
+    def testSymbolsExpanded(self):
+        """Test binman can assign symbols in expanded entries"""
+        entry_args = {
+            'spl-dtb': '1',
+        }
+        self.checkSymbols('197_symbols_expand.dts', U_BOOT_SPL_NODTB_DATA +
+                          U_BOOT_SPL_DTB_DATA, 0x38,
+                          entry_args=entry_args, use_expanded=True)
+
+    def testCollection(self):
+        """Test a collection"""
+        data = self._DoReadFile('198_collection.dts')
+        self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA +
+                         tools.GetBytes(0xff, 2) + U_BOOT_NODTB_DATA +
+                         tools.GetBytes(0xfe, 3) + U_BOOT_DTB_DATA,
+                         data)
+
+    def testCollectionSection(self):
+        """Test a collection where a section must be built first"""
+        # Sections never have their contents when GetData() is called, but when
+        # _BuildSectionData() is called with required=True, a section will force
+        # building the contents, producing an error is anything is still
+        # missing.
+        data = self._DoReadFile('199_collection_section.dts')
+        section = U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA
+        self.assertEqual(section + U_BOOT_DATA + tools.GetBytes(0xff, 2) +
+                         section + tools.GetBytes(0xfe, 3) + U_BOOT_DATA,
+                         data)
+
+    def testAlignDefault(self):
+        """Test that default alignment works on sections"""
+        data = self._DoReadFile('200_align_default.dts')
+        expected = (U_BOOT_DATA + tools.GetBytes(0, 8 - len(U_BOOT_DATA)) +
+                    U_BOOT_DATA)
+        # Special alignment for section
+        expected += tools.GetBytes(0, 32 - len(expected))
+        # No alignment within the nested section
+        expected += U_BOOT_DATA + U_BOOT_NODTB_DATA;
+        # Now the final piece, which should be default-aligned
+        expected += tools.GetBytes(0, 88 - len(expected)) + U_BOOT_NODTB_DATA
+        self.assertEqual(expected, data)
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/image.py b/tools/binman/image.py
index e949435..10778f4 100644
--- a/tools/binman/image.py
+++ b/tools/binman/image.py
@@ -47,9 +47,23 @@
             exception). This should be used if the Image is being loaded from
             a file rather than generated. In that case we obviously don't need
             the entry arguments since the contents already exists.
+        use_expanded: True if we are updating the FDT wth entry offsets, etc.
+            and should use the expanded versions of the U-Boot entries.
+            Any entry type that includes a devicetree must put it in a
+            separate entry so that it will be updated. For example. 'u-boot'
+            normally just picks up 'u-boot.bin' which includes the
+            devicetree, but this is not updateable, since it comes into
+            binman as one piece and binman doesn't know that it is actually
+            an executable followed by a devicetree. Of course it could be
+            taught this, but then when reading an image (e.g. 'binman ls')
+            it may need to be able to split the devicetree out of the image
+            in order to determine the location of things. Instead we choose
+            to ignore 'u-boot-bin' in this case, and build it ourselves in
+            binman with 'u-boot-dtb.bin' and 'u-boot.dtb'. See
+            Entry_u_boot_expanded and Entry_blob_phase for details.
     """
     def __init__(self, name, node, copy_to_orig=True, test=False,
-                 ignore_missing=False):
+                 ignore_missing=False, use_expanded=False):
         super().__init__(None, 'section', node, test=test)
         self.copy_to_orig = copy_to_orig
         self.name = 'main-section'
@@ -59,6 +73,7 @@
         self.fdtmap_data = None
         self.allow_repack = False
         self._ignore_missing = ignore_missing
+        self.use_expanded = use_expanded
         if not test:
             self.ReadNode()
 
diff --git a/tools/binman/index.rst b/tools/binman/index.rst
new file mode 100644
index 0000000..6eef7b5
--- /dev/null
+++ b/tools/binman/index.rst
@@ -0,0 +1,9 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Binman
+======
+
+.. toctree::
+   :maxdepth: 2
+
+   README
diff --git a/tools/binman/setup.py b/tools/binman/setup.py
index fe408ed..5ed94ab 100644
--- a/tools/binman/setup.py
+++ b/tools/binman/setup.py
@@ -7,6 +7,6 @@
       scripts=['binman'],
       packages=['binman', 'binman.etype'],
       package_dir={'binman': ''},
-      package_data={'binman': ['README', 'README.entries']},
+      package_data={'binman': ['README.rst', 'entries.rst']},
       classifiers=['Environment :: Console',
                    'Topic :: Software Development :: Embedded Systems'])
diff --git a/tools/binman/state.py b/tools/binman/state.py
index bb3e36e..dfb1760 100644
--- a/tools/binman/state.py
+++ b/tools/binman/state.py
@@ -13,15 +13,20 @@
 from patman import tools
 from patman import tout
 
+# Map an dtb etype to its expected filename
+DTB_TYPE_FNAME = {
+    'u-boot-spl-dtb': 'spl/u-boot-spl.dtb',
+    'u-boot-tpl-dtb': 'tpl/u-boot-tpl.dtb',
+    }
+
 # Records the device-tree files known to binman, keyed by entry type (e.g.
 # 'u-boot-spl-dtb'). These are the output FDT files, which can be updated by
 # binman. They have been copied to <xxx>.out files.
 #
-#   key: entry type
+#   key: entry type (e.g. 'u-boot-dtb)
 #   value: tuple:
 #       Fdt object
 #       Filename
-#       Entry object, or None if not known
 output_fdt_info = {}
 
 # Prefix to add to an fdtmap path to turn it into a path to the /binman node
@@ -118,11 +123,11 @@
         etype: Entry type (e.g. 'u-boot-dtb')
         data: Data to replace the DTB with
     """
-    dtb, fname, entry = output_fdt_info[etype]
+    dtb, fname = output_fdt_info[etype]
     dtb_fname = dtb.GetFilename()
     tools.WriteFile(dtb_fname, data)
     dtb = fdt.FdtScan(dtb_fname)
-    output_fdt_info[etype] = [dtb, fname, entry]
+    output_fdt_info[etype] = [dtb, fname]
 
 def SetEntryArgs(args):
     """Set the value of the entry args
@@ -136,12 +141,16 @@
     global entry_args
 
     entry_args = {}
+    tout.Debug('Processing entry args:')
     if args:
         for arg in args:
             m = re.match('([^=]*)=(.*)', arg)
             if not m:
                 raise ValueError("Invalid entry arguemnt '%s'" % arg)
-            entry_args[m.group(1)] = m.group(2)
+            name, value = m.groups()
+            tout.Debug('   %20s = %s' % (name, value))
+            entry_args[name] = value
+    tout.Debug('Processing entry args done')
 
 def GetEntryArg(name):
     """Get the value of an entry argument
@@ -154,6 +163,19 @@
     """
     return entry_args.get(name)
 
+def GetEntryArgBool(name):
+    """Get the value of an entry argument as a boolean
+
+    Args:
+        name: Name of argument to retrieve
+
+    Returns:
+        False if the entry argument is consider False (empty, '0' or 'n'), else
+            True
+    """
+    val = GetEntryArg(name)
+    return val and val not in ['n', '0']
+
 def Prepare(images, dtb):
     """Get device tree files ready for use
 
@@ -177,22 +199,22 @@
     main_dtb = dtb
     output_fdt_info.clear()
     fdt_path_prefix = ''
-    output_fdt_info['u-boot-dtb'] = [dtb, 'u-boot.dtb', None]
-    output_fdt_info['u-boot-spl-dtb'] = [dtb, 'spl/u-boot-spl.dtb', None]
-    output_fdt_info['u-boot-tpl-dtb'] = [dtb, 'tpl/u-boot-tpl.dtb', None]
-    if not use_fake_dtb:
+    output_fdt_info['u-boot-dtb'] = [dtb, 'u-boot.dtb']
+    if use_fake_dtb:
+        for etype, fname in DTB_TYPE_FNAME.items():
+            output_fdt_info[etype] = [dtb, fname]
+    else:
         fdt_set = {}
-        for image in images.values():
-            fdt_set.update(image.GetFdts())
-        for etype, other in fdt_set.items():
-            entry, other_fname = other
-            infile = tools.GetInputFilename(other_fname)
-            other_fname_dtb = fdt_util.EnsureCompiled(infile)
-            out_fname = tools.GetOutputFilename('%s.out' %
-                    os.path.split(other_fname)[1])
-            tools.WriteFile(out_fname, tools.ReadFile(other_fname_dtb))
-            other_dtb = fdt.FdtScan(out_fname)
-            output_fdt_info[etype] = [other_dtb, out_fname, entry]
+        for etype, fname in DTB_TYPE_FNAME.items():
+            infile = tools.GetInputFilename(fname, allow_missing=True)
+            if infile and os.path.exists(infile):
+                fname_dtb = fdt_util.EnsureCompiled(infile)
+                out_fname = tools.GetOutputFilename('%s.out' %
+                        os.path.split(fname)[1])
+                tools.WriteFile(out_fname, tools.ReadFile(fname_dtb))
+                other_dtb = fdt.FdtScan(out_fname)
+                output_fdt_info[etype] = [other_dtb, out_fname]
+
 
 def PrepareFromLoadedData(image):
     """Get device tree files ready for use with a loaded image
@@ -215,7 +237,7 @@
     tout.Info('Preparing device trees')
     output_fdt_info.clear()
     fdt_path_prefix = ''
-    output_fdt_info['fdtmap'] = [image.fdtmap_dtb, 'u-boot.dtb', None]
+    output_fdt_info['fdtmap'] = [image.fdtmap_dtb, 'u-boot.dtb']
     main_dtb = None
     tout.Info("   Found device tree type 'fdtmap' '%s'" % image.fdtmap_dtb.name)
     for etype, value in image.GetFdts().items():
@@ -233,7 +255,7 @@
         if 'multiple-images' in image_node.props:
             image_node = dtb.GetNode('/binman/%s' % image.image_node)
         fdt_path_prefix = image_node.path
-        output_fdt_info[etype] = [dtb, None, entry]
+        output_fdt_info[etype] = [dtb, None]
     tout.Info("   FDT path prefix '%s'" % fdt_path_prefix)
 
 
@@ -268,12 +290,11 @@
             is node, SPL and TPL)
     """
     yield node
-    for dtb, fname, entry in output_fdt_info.values():
+    for entry_type, (dtb, fname) in output_fdt_info.items():
         if dtb != node.GetFdt():
-            if for_repack and entry.etype != 'u-boot-dtb':
+            if for_repack and entry_type != 'u-boot-dtb':
                 continue
             other_node = dtb.GetNode(fdt_path_prefix + node.path)
-            #print('   try', fdt_path_prefix + node.path, other_node)
             if other_node:
                 yield other_node
 
diff --git a/tools/binman/test/053_symbols.dts b/tools/binman/test/053_symbols.dts
index 8af5751..2965809 100644
--- a/tools/binman/test/053_symbols.dts
+++ b/tools/binman/test/053_symbols.dts
@@ -10,7 +10,7 @@
 		};
 
 		u-boot {
-			offset = <24>;
+			offset = <0x18>;
 		};
 
 		u-boot-spl2 {
diff --git a/tools/binman/test/149_symbols_tpl.dts b/tools/binman/test/149_symbols_tpl.dts
index dfc84af..0a4ab3f 100644
--- a/tools/binman/test/149_symbols_tpl.dts
+++ b/tools/binman/test/149_symbols_tpl.dts
@@ -21,7 +21,6 @@
 
 		section {
 			u-boot-tpl {
-				type = "u-boot-tpl";
 			};
 		};
 	};
diff --git a/tools/binman/test/155_symbols_tpl_x86.dts b/tools/binman/test/155_symbols_tpl_x86.dts
index 72ca447..9d7dc51 100644
--- a/tools/binman/test/155_symbols_tpl_x86.dts
+++ b/tools/binman/test/155_symbols_tpl_x86.dts
@@ -24,7 +24,6 @@
 
 		section {
 			u-boot-tpl {
-				type = "u-boot-tpl";
 			};
 		};
 	};
diff --git a/tools/binman/test/192_u_boot_tpl_nodtb.dts b/tools/binman/test/192_u_boot_tpl_nodtb.dts
new file mode 100644
index 0000000..94cef39
--- /dev/null
+++ b/tools/binman/test/192_u_boot_tpl_nodtb.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		u-boot-tpl-nodtb {
+		};
+	};
+};
diff --git a/tools/binman/test/193_tpl_bss_pad.dts b/tools/binman/test/193_tpl_bss_pad.dts
new file mode 100644
index 0000000..f5c2db0
--- /dev/null
+++ b/tools/binman/test/193_tpl_bss_pad.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		u-boot-tpl {
+		};
+
+		u-boot-tpl-bss-pad {
+		};
+
+		u-boot {
+		};
+	};
+};
diff --git a/tools/binman/test/194_fdt_incl.dts b/tools/binman/test/194_fdt_incl.dts
new file mode 100644
index 0000000..b14c8ff
--- /dev/null
+++ b/tools/binman/test/194_fdt_incl.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		u-boot {
+		};
+		u-boot-spl {
+		};
+		u-boot-tpl {
+		};
+	};
+};
diff --git a/tools/binman/test/195_fdt_incl_tpl.dts b/tools/binman/test/195_fdt_incl_tpl.dts
new file mode 100644
index 0000000..3756ac4
--- /dev/null
+++ b/tools/binman/test/195_fdt_incl_tpl.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		u-boot-tpl {
+		};
+	};
+};
diff --git a/tools/binman/test/196_symbols_nodtb.dts b/tools/binman/test/196_symbols_nodtb.dts
new file mode 100644
index 0000000..5c900d6
--- /dev/null
+++ b/tools/binman/test/196_symbols_nodtb.dts
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		pad-byte = <0xff>;
+		u-boot-spl-nodtb {
+		};
+		u-boot-spl-dtb {
+		};
+
+		u-boot {
+			offset = <0x38>;
+		};
+
+		u-boot-spl2 {
+			type = "u-boot-spl-nodtb";
+		};
+		u-boot-spl-dtb2 {
+			type = "u-boot-spl-dtb";
+		};
+	};
+};
diff --git a/tools/binman/test/197_symbols_expand.dts b/tools/binman/test/197_symbols_expand.dts
new file mode 100644
index 0000000..8aee76d
--- /dev/null
+++ b/tools/binman/test/197_symbols_expand.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		pad-byte = <0xff>;
+		u-boot-spl {
+		};
+
+		u-boot {
+			offset = <0x38>;
+			no-expanded;
+		};
+
+		u-boot-spl2 {
+			type = "u-boot-spl";
+		};
+	};
+};
diff --git a/tools/binman/test/198_collection.dts b/tools/binman/test/198_collection.dts
new file mode 100644
index 0000000..484a1b0
--- /dev/null
+++ b/tools/binman/test/198_collection.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		collection {
+			content = <&u_boot_nodtb &dtb>;
+		};
+		fill {
+			size = <2>;
+			fill-byte = [ff];
+		};
+		u_boot_nodtb: u-boot-nodtb {
+		};
+		fill2 {
+			type = "fill";
+			size = <3>;
+			fill-byte = [fe];
+		};
+		dtb: u-boot-dtb {
+		};
+	};
+};
diff --git a/tools/binman/test/199_collection_section.dts b/tools/binman/test/199_collection_section.dts
new file mode 100644
index 0000000..03a7319
--- /dev/null
+++ b/tools/binman/test/199_collection_section.dts
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		collection {
+			content = <&section &u_boot>;
+		};
+		fill {
+			size = <2>;
+			fill-byte = [ff];
+		};
+		section: section {
+			u-boot-nodtb {
+			};
+			u-boot-dtb {
+			};
+		};
+		fill2 {
+			type = "fill";
+			size = <3>;
+			fill-byte = [fe];
+		};
+		u_boot: u-boot {
+			no-expanded;
+		};
+	};
+};
diff --git a/tools/binman/test/200_align_default.dts b/tools/binman/test/200_align_default.dts
new file mode 100644
index 0000000..1b15577
--- /dev/null
+++ b/tools/binman/test/200_align_default.dts
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		align-default = <8>;
+		u-boot {
+		};
+
+		u-boot-align {
+			type = "u-boot";
+		};
+
+		section {
+			align = <32>;
+			u-boot {
+			};
+
+			u-boot-nodtb {
+			};
+		};
+
+		u-boot-nodtb {
+		};
+	};
+};
diff --git a/tools/binman/test/u_boot_binman_syms.c b/tools/binman/test/u_boot_binman_syms.c
index 4520b31..37fc339 100644
--- a/tools/binman/test/u_boot_binman_syms.c
+++ b/tools/binman/test/u_boot_binman_syms.c
@@ -8,7 +8,7 @@
 #define CONFIG_BINMAN
 #include <binman_sym.h>
 
-binman_sym_declare(unsigned long, u_boot_spl, offset);
+binman_sym_declare(unsigned long, u_boot_spl_any, offset);
 binman_sym_declare(unsigned long long, u_boot_spl2, offset);
 binman_sym_declare(unsigned long, u_boot_any, image_pos);
 binman_sym_declare(unsigned long, u_boot_any, size);
diff --git a/tools/buildman/builderthread.py b/tools/buildman/builderthread.py
index 6c6dbd7..06ed272 100644
--- a/tools/buildman/builderthread.py
+++ b/tools/buildman/builderthread.py
@@ -344,7 +344,8 @@
 
             # Write out the image and function size information and an objdump
             env = result.toolchain.MakeEnvironment(self.builder.full_path)
-            with open(os.path.join(build_dir, 'out-env'), 'w') as fd:
+            with open(os.path.join(build_dir, 'out-env'), 'w',
+                      encoding='utf-8') as fd:
                 for var in sorted(env.keys()):
                     print('%s="%s"' % (var, env[var]), file=fd)
             lines = []
diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile
new file mode 100644
index 0000000..d2f0074
--- /dev/null
+++ b/tools/docker/Dockerfile
@@ -0,0 +1,203 @@
+# SPDX-License-Identifier: GPL-2.0+
+# This Dockerfile is used to build an image containing basic stuff to be used
+# to build U-Boot and run our test suites.
+
+FROM ubuntu:bionic-20200807
+MAINTAINER Tom Rini <trini@konsulko.com>
+LABEL Description=" This image is for building U-Boot inside a container"
+
+# Make sure apt is happy
+ENV DEBIAN_FRONTEND=noninteractive
+
+# Add LLVM repository
+RUN apt-get update && apt-get install -y gnupg2 wget xz-utils && rm -rf /var/lib/apt/lists/*
+RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
+RUN echo deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main | tee /etc/apt/sources.list.d/llvm.list
+
+# Manually install the kernel.org "Crosstool" based toolchains for gcc-7.3
+RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/9.2.0/x86_64-gcc-9.2.0-nolibc-aarch64-linux.tar.xz | tar -C /opt -xJ
+RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/9.2.0/x86_64-gcc-9.2.0-nolibc-arm-linux-gnueabi.tar.xz | tar -C /opt -xJ
+RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/9.2.0/x86_64-gcc-9.2.0-nolibc-i386-linux.tar.xz | tar -C /opt -xJ
+RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/9.2.0/x86_64-gcc-9.2.0-nolibc-m68k-linux.tar.xz | tar -C /opt -xJ
+RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/9.2.0/x86_64-gcc-9.2.0-nolibc-mips-linux.tar.xz | tar -C /opt -xJ
+RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/9.2.0/x86_64-gcc-9.2.0-nolibc-microblaze-linux.tar.xz | tar -C /opt -xJ
+RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/9.2.0/x86_64-gcc-9.2.0-nolibc-nios2-linux.tar.xz | tar -C /opt -xJ
+RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/9.2.0/x86_64-gcc-9.2.0-nolibc-powerpc-linux.tar.xz | tar -C /opt -xJ
+RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/9.2.0/x86_64-gcc-9.2.0-nolibc-riscv32-linux.tar.xz | tar -C /opt -xJ
+RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/9.2.0/x86_64-gcc-9.2.0-nolibc-riscv64-linux.tar.xz | tar -C /opt -xJ
+RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/9.2.0/x86_64-gcc-9.2.0-nolibc-sh2-linux.tar.xz | tar -C /opt -xJ
+
+# Manually install other toolchains
+RUN wget -O - https://github.com/foss-xtensa/toolchain/releases/download/2018.02/x86_64-2018.02-xtensa-dc233c-elf.tar.gz | tar -C /opt -xz
+RUN wget -O - https://github.com/foss-for-synopsys-dwc-arc-processors/toolchain/releases/download/arc-2019.09-release/arc_gnu_2019.09_prebuilt_uclibc_le_archs_linux_install.tar.gz | tar --no-same-owner -C /opt -xz
+RUN wget -O - https://github.com/vincentzwc/prebuilt-nds32-toolchain/releases/download/20180521/nds32le-linux-glibc-v3-upstream.tar.gz | tar -C /opt -xz
+
+# Update and install things from apt now
+RUN apt-get update && apt-get install -y \
+	automake \
+	autopoint \
+	bc \
+	binutils-dev \
+	bison \
+	build-essential \
+	clang-10 \
+	coreutils \
+	cpio \
+	cppcheck \
+	curl \
+	device-tree-compiler \
+	dosfstools \
+	e2fsprogs \
+	efitools \
+	fakeroot \
+	flex \
+	gdisk \
+	git \
+	gnu-efi \
+	graphviz \
+	grub-efi-amd64-bin \
+	grub-efi-ia32-bin \
+	help2man \
+	iasl \
+	imagemagick \
+	iputils-ping \
+	libguestfs-tools \
+	libisl15 \
+	liblz4-tool \
+	libpixman-1-dev \
+	libpython-dev \
+	libsdl1.2-dev \
+	libsdl2-dev \
+	libssl-dev \
+	libudev-dev \
+	libusb-1.0-0-dev \
+	lzma-alone \
+	lzop \
+	mount \
+	mtd-utils \
+	mtools \
+	openssl \
+	picocom \
+	parted \
+	pkg-config \
+	python \
+	python-dev \
+	python-pip \
+	python-virtualenv \
+	python3-pip \
+	python3-sphinx \
+	rpm2cpio \
+	sbsigntool \
+	sloccount \
+	sparse \
+	srecord \
+	sudo \
+	swig \
+	util-linux \
+	uuid-dev \
+	virtualenv \
+	zip \
+	&& rm -rf /var/lib/apt/lists/*
+
+# Manually install libmpfr4 for the toolchains
+RUN wget http://mirrors.kernel.org/ubuntu/pool/main/m/mpfr4/libmpfr4_3.1.4-1_amd64.deb && dpkg -i libmpfr4_3.1.4-1_amd64.deb && rm libmpfr4_3.1.4-1_amd64.deb
+
+# Manually install a new enough version of efitools (must be v1.5.2 or later)
+RUN wget http://mirrors.kernel.org/ubuntu/pool/universe/e/efitools/efitools_1.8.1-0ubuntu2_amd64.deb && sudo dpkg -i efitools_1.8.1-0ubuntu2_amd64.deb && rm efitools_1.8.1-0ubuntu2_amd64.deb
+
+# Manually install a new enough version of sbsigntools (must be v0.9.4 or later)
+RUN git clone https://git.kernel.org/pub/scm/linux/kernel/git/jejb/sbsigntools.git /tmp/sbsigntools && \
+	cd /tmp/sbsigntools && \
+	git checkout -b latest v0.9.4 && \
+	./autogen.sh && \
+	./configure && \
+	make && \
+	make install && \
+	rm -rf /tmp/sbsigntools
+
+# Build GRUB UEFI targets for ARM & RISC-V, 32-bit and 64-bit
+RUN git clone git://git.savannah.gnu.org/grub.git /tmp/grub && \
+	cd /tmp/grub && \
+	git checkout grub-2.04 && \
+	./bootstrap && \
+	mkdir -p /opt/grub && \
+	./configure --target=aarch64 --with-platform=efi \
+	CC=gcc \
+	TARGET_CC=/opt/gcc-9.2.0-nolibc/aarch64-linux/bin/aarch64-linux-gcc \
+	TARGET_OBJCOPY=/opt/gcc-9.2.0-nolibc/aarch64-linux/bin/aarch64-linux-objcopy \
+	TARGET_STRIP=/opt/gcc-9.2.0-nolibc/aarch64-linux/bin/aarch64-linux-strip \
+	TARGET_NM=/opt/gcc-9.2.0-nolibc/aarch64-linux/bin/aarch64-linux-nm \
+	TARGET_RANLIB=/opt/gcc-9.2.0-nolibc/aarch64-linux/bin/aarch64-linux-ranlib && \
+	make && \
+	./grub-mkimage -O arm64-efi -o /opt/grub/grubaa64.efi --prefix= -d \
+	grub-core cat chain configfile echo efinet ext2 fat halt help linux \
+	lsefisystab loadenv lvm minicmd normal part_msdos part_gpt reboot \
+	search search_fs_file search_fs_uuid search_label serial sleep test \
+	true && \
+	make clean && \
+	./configure --target=arm --with-platform=efi \
+	CC=gcc \
+	TARGET_CC=/opt/gcc-9.2.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-gcc \
+	TARGET_OBJCOPY=/opt/gcc-9.2.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-objcopy \
+	TARGET_STRIP=/opt/gcc-9.2.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-strip \
+	TARGET_NM=/opt/gcc-9.2.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-nm \
+	TARGET_RANLIB=/opt/gcc-9.2.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-ranlib && \
+	make && \
+	./grub-mkimage -O arm-efi -o /opt/grub/grubarm.efi --prefix= -d \
+	grub-core cat chain configfile echo efinet ext2 fat halt help linux \
+	lsefisystab loadenv lvm minicmd normal part_msdos part_gpt reboot \
+	search search_fs_file search_fs_uuid search_label serial sleep test \
+	true && \
+	make clean && \
+	./configure --target=riscv64 --with-platform=efi \
+	CC=gcc \
+	TARGET_CC=/opt/gcc-9.2.0-nolibc/riscv64-linux/bin/riscv64-linux-gcc \
+	TARGET_OBJCOPY=/opt/gcc-9.2.0-nolibc/riscv64-linux/bin/riscv64-linux-objcopy \
+	TARGET_STRIP=/opt/gcc-9.2.0-nolibc/riscv64-linux/bin/riscv64-linux-strip \
+	TARGET_NM=/opt/gcc-9.2.0-nolibc/riscv64-linux/bin/riscv64-linux-nm \
+	TARGET_RANLIB=/opt/gcc-9.2.0-nolibc/riscv64-linux/bin/riscv64-linux-ranlib && \
+	make && \
+	./grub-mkimage -O riscv64-efi -o /opt/grub/grubriscv64.efi --prefix= -d \
+	grub-core cat chain configfile echo efinet ext2 fat halt help linux \
+	lsefisystab loadenv lvm minicmd normal part_msdos part_gpt reboot \
+	search search_fs_file search_fs_uuid search_label serial sleep test \
+	true && \
+	make clean && \
+	./configure --target=riscv32 --with-platform=efi \
+	CC=gcc \
+	TARGET_CC=/opt/gcc-9.2.0-nolibc/riscv32-linux/bin/riscv32-linux-gcc \
+	TARGET_OBJCOPY=/opt/gcc-9.2.0-nolibc/riscv32-linux/bin/riscv32-linux-objcopy \
+	TARGET_STRIP=/opt/gcc-9.2.0-nolibc/riscv32-linux/bin/riscv32-linux-strip \
+	TARGET_NM=/opt/gcc-9.2.0-nolibc/riscv32-linux/bin/riscv32-linux-nm \
+	TARGET_RANLIB=/opt/gcc-9.2.0-nolibc/riscv32-linux/bin/riscv32-linux-ranlib && \
+	make && \
+	./grub-mkimage -O riscv32-efi -o /opt/grub/grubriscv32.efi --prefix= -d \
+	grub-core cat chain configfile echo efinet ext2 fat halt help linux \
+	lsefisystab loadenv lvm minicmd normal part_msdos part_gpt reboot \
+	search search_fs_file search_fs_uuid search_label serial sleep test \
+	true && \
+	rm -rf /tmp/grub
+
+RUN git clone git://git.qemu.org/qemu.git /tmp/qemu && \
+	cd /tmp/qemu && \
+	git submodule update --init dtc && \
+	git checkout v4.2.0 && \
+	./configure --prefix=/opt/qemu --target-list="aarch64-softmmu,arm-softmmu,i386-softmmu,mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu,ppc-softmmu,riscv32-softmmu,riscv64-softmmu,sh4-softmmu,x86_64-softmmu,xtensa-softmmu" && \
+	make -j$(nproc) all install && \
+	rm -rf /tmp/qemu
+
+# Create our user/group
+RUN echo uboot ALL=NOPASSWD: ALL > /etc/sudoers.d/uboot
+RUN useradd -m -U uboot
+USER uboot:uboot
+
+# Create the buildman config file
+RUN /bin/echo -e "[toolchain]\nroot = /usr" > ~/.buildman
+RUN /bin/echo -e "kernelorg = /opt/gcc-9.2.0-nolibc/*" >> ~/.buildman
+RUN /bin/echo -e "arc = /opt/arc_gnu_2019.09_prebuilt_uclibc_le_archs_linux_install" >> ~/.buildman
+RUN /bin/echo -e "\n[toolchain-prefix]\nxtensa = /opt/2018.02/xtensa-dc233c-elf/bin/xtensa-dc233c-elf-" >> ~/.buildman;
+RUN /bin/echo -e "\nnds32 = /opt/nds32le-linux-glibc-v3-upstream/bin/nds32le-linux-" >> ~/.buildman;
+RUN /bin/echo -e "\n[toolchain-alias]\nsh = sh2" >> ~/.buildman
+RUN /bin/echo -e "\nriscv = riscv64" >> ~/.buildman
+RUN /bin/echo -e "\nsandbox = x86_64" >> ~/.buildman
+RUN /bin/echo -e "\nx86 = i386" >> ~/.buildman;
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py
index b7abaed..1374f01 100644
--- a/tools/dtoc/dtb_platdata.py
+++ b/tools/dtoc/dtb_platdata.py
@@ -52,6 +52,20 @@
 STRUCT_PREFIX = 'dtd_'
 VAL_PREFIX = 'dtv_'
 
+# Properties which are considered to be phandles
+#    key: property name
+#    value: name of associated #cells property in the target node
+#
+# New phandle properties must be added here; otherwise they will come through as
+# simple integers and finding devices by phandle will not work.
+# Any property that ends with one of these (e.g. 'cd-gpios') will be considered
+# a phandle property.
+PHANDLE_PROPS = {
+    'clocks': '#clock-cells',
+    'gpios': '#gpio-cells',
+    'sandbox,emul': '#emul-cells',
+    }
+
 class Ftype(IntEnum):
     SOURCE, HEADER = range(2)
 
@@ -136,8 +150,10 @@
             from the U-Boot source code
         _fdt: Fdt object, referencing the device tree
         _dtb_fname: Filename of the input device tree binary file
-        _valid_nodes: A list of Node object with compatible strings. The list
-            is ordered by conv_name_to_c(node.name)
+        _valid_nodes_unsorted: A list of Node object with compatible strings,
+            ordered by devicetree node order
+        _valid_nodes: A list of Node object with compatible strings, ordered by
+            conv_name_to_c(node.name)
         _include_disabled: true to include nodes marked status = "disabled"
         _outfile: The current output file (sys.stdout or a real file)
         _lines: Stashed list of output lines for outputting in the future
@@ -149,18 +165,25 @@
                         key (str): Field name
                         value: Prop object with field information
         _basedir (str): Base directory of source tree
+        _valid_uclasses (list of src_scan.Uclass): List of uclasses needed for
+            the selected devices (see _valid_node), in alphabetical order
+        _instantiate: Instantiate devices so they don't need to be bound at
+            run-time
     """
-    def __init__(self, scan, dtb_fname, include_disabled):
+    def __init__(self, scan, dtb_fname, include_disabled, instantiate=False):
         self._scan = scan
         self._fdt = None
         self._dtb_fname = dtb_fname
         self._valid_nodes = None
+        self._valid_nodes_unsorted = None
         self._include_disabled = include_disabled
         self._outfile = None
         self._lines = []
         self._dirnames = [None] * len(Ftype)
         self._struct_data = collections.OrderedDict()
         self._basedir = None
+        self._valid_uclasses = None
+        self._instantiate = instantiate
 
     def setup_output_dirs(self, output_dirs):
         """Set up the output directories
@@ -223,6 +246,7 @@
         """
         if self._outfile != sys.stdout:
             self._outfile.close()
+            self._outfile = None
 
     def out(self, line):
         """Output a string to the output file
@@ -281,7 +305,11 @@
             ValueError: if the phandle cannot be parsed or the required property
                 is not present
         """
-        if prop.name in ['clocks', 'cd-gpios']:
+        cells_prop = None
+        for name, cprop in PHANDLE_PROPS.items():
+            if prop.name.endswith(name):
+                cells_prop = cprop
+        if cells_prop:
             if not isinstance(prop.value, list):
                 prop.value = [prop.value]
             val = prop.value
@@ -301,14 +329,10 @@
                 if not target:
                     raise ValueError("Cannot parse '%s' in node '%s'" %
                                      (prop.name, node_name))
-                cells = None
-                for prop_name in ['#clock-cells', '#gpio-cells']:
-                    cells = target.props.get(prop_name)
-                    if cells:
-                        break
+                cells = target.props.get(cells_prop)
                 if not cells:
                     raise ValueError("Node '%s' has no cells property" %
-                                     (target.name))
+                                     target.name)
                 num_args = fdt_util.fdt32_to_cpu(cells.value)
                 max_args = max(max_args, num_args)
                 args.append(num_args)
@@ -324,38 +348,84 @@
         """
         self._fdt = fdt.FdtScan(self._dtb_fname)
 
-    def scan_node(self, root, valid_nodes):
+    def scan_node(self, node, valid_nodes):
         """Scan a node and subnodes to build a tree of node and phandle info
 
-        This adds each node to self._valid_nodes.
+        This adds each subnode to self._valid_nodes if it is enabled and has a
+        compatible string.
 
         Args:
-            root (Node): Root node for scan
+            node (Node): Node for scan for subnodes
             valid_nodes (list of Node): List of Node objects to add to
         """
-        for node in root.subnodes:
-            if 'compatible' in node.props:
-                status = node.props.get('status')
+        for subnode in node.subnodes:
+            if 'compatible' in subnode.props:
+                status = subnode.props.get('status')
                 if (not self._include_disabled and not status or
                         status.value != 'disabled'):
-                    valid_nodes.append(node)
+                    valid_nodes.append(subnode)
 
             # recurse to handle any subnodes
-            self.scan_node(node, valid_nodes)
+            self.scan_node(subnode, valid_nodes)
 
-    def scan_tree(self):
+    def scan_tree(self, add_root):
         """Scan the device tree for useful information
 
         This fills in the following properties:
-            _valid_nodes: A list of nodes we wish to consider include in the
-                platform data
+            _valid_nodes_unsorted: A list of nodes we wish to consider include
+                in the platform data (in devicetree node order)
+            _valid_nodes: Sorted version of _valid_nodes_unsorted
+
+        Args:
+            add_root: True to add the root node also (which wouldn't normally
+                be added as it may not have a compatible string)
         """
+        root = self._fdt.GetRoot()
         valid_nodes = []
-        self.scan_node(self._fdt.GetRoot(), valid_nodes)
+        if add_root:
+            valid_nodes.append(root)
+        self.scan_node(root, valid_nodes)
+        self._valid_nodes_unsorted = valid_nodes
         self._valid_nodes = sorted(valid_nodes,
                                    key=lambda x: conv_name_to_c(x.name))
+
+    def prepare_nodes(self):
+        """Add extra properties to the nodes we are using
+
+        The following properties are added for use by dtoc:
+            idx: Index number of this node (0=first, etc.)
+            struct_name: Name of the struct dtd used by this node
+            var_name: C name for this node
+            child_devs: List of child devices for this node, each a None
+            child_refs: Dict of references for each child:
+                key: Position in child list (-1=head, 0=first, 1=second, ...
+                                             n-1=last, n=head)
+            seq: Sequence number of the device (unique within its uclass), or
+                -1 not not known yet
+            dev_ref: Reference to this device, e.g. 'DM_DEVICE_REF(serial)'
+            driver: Driver record for this node, or None if not known
+            uclass: Uclass record for this node, or None if not known
+            uclass_seq: Position of this device within the uclass list (0=first,
+                n-1=last)
+            parent_seq: Position of this device within it siblings (0=first,
+                n-1=last)
+            parent_driver: Driver record of the node's parent, or None if none.
+                We don't use node.parent.driver since node.parent may not be in
+                the list of valid nodes
+        """
         for idx, node in enumerate(self._valid_nodes):
             node.idx = idx
+            node.struct_name, _ = self._scan.get_normalized_compat_name(node)
+            node.var_name = conv_name_to_c(node.name)
+            node.child_devs = []
+            node.child_refs = {}
+            node.seq = -1
+            node.dev_ref = None
+            node.driver = None
+            node.uclass = None
+            node.uclass_seq = None
+            node.parent_seq = None
+            node.parent_driver = None
 
     @staticmethod
     def get_num_cells(node):
@@ -370,6 +440,9 @@
                 Number of size cells for this node
         """
         parent = node.parent
+        if parent and not parent.props:
+            raise ValueError("Parent node '%s' has no properties - do you need u-boot,dm-spl or similar?" %
+                             parent.path)
         num_addr, num_size = 2, 2
         if parent:
             addr_prop = parent.props.get('#address-cells')
@@ -397,20 +470,21 @@
             if reg.type != fdt.Type.INT:
                 raise ValueError("Node '%s' reg property is not an int" %
                                  node.name)
+            if not isinstance(reg.value, list):
+                reg.value = [reg.value]
             if len(reg.value) % total:
                 raise ValueError(
-                    "Node '%s' reg property has %d cells "
+                    "Node '%s' (parent '%s') reg property has %d cells "
                     'which is not a multiple of na + ns = %d + %d)' %
-                    (node.name, len(reg.value), num_addr, num_size))
+                    (node.name, node.parent.name, len(reg.value), num_addr,
+                     num_size))
             reg.num_addr = num_addr
             reg.num_size = num_size
-            if num_addr != 1 or num_size != 1:
+            if num_addr > 1 or num_size > 1:
                 reg.type = fdt.Type.INT64
                 i = 0
                 new_value = []
                 val = reg.value
-                if not isinstance(val, list):
-                    val = [val]
                 while i < len(val):
                     addr = fdt_util.fdt_cells_to_cpu(val[i:], reg.num_addr)
                     i += num_addr
@@ -434,7 +508,6 @@
         """
         structs = self._struct_data
         for node in self._valid_nodes:
-            node_name, _ = self._scan.get_normalized_compat_name(node)
             fields = {}
 
             # Get a list of all the valid properties in this node.
@@ -442,9 +515,9 @@
                 if name not in PROP_IGNORE_LIST and name[0] != '#':
                     fields[name] = copy.deepcopy(prop)
 
-            # If we've seen this node_name before, update the existing struct.
-            if node_name in structs:
-                struct = structs[node_name]
+            # If we've seen this struct_name before, update the existing struct
+            if node.struct_name in structs:
+                struct = structs[node.struct_name]
                 for name, prop in fields.items():
                     oldprop = struct.get(name)
                     if oldprop:
@@ -454,11 +527,10 @@
 
             # Otherwise store this as a new struct.
             else:
-                structs[node_name] = fields
+                structs[node.struct_name] = fields
 
         for node in self._valid_nodes:
-            node_name, _ = self._scan.get_normalized_compat_name(node)
-            struct = structs[node_name]
+            struct = structs[node.struct_name]
             for name, prop in node.props.items():
                 if name not in PROP_IGNORE_LIST and name[0] != '#':
                     prop.Widen(struct[name])
@@ -562,28 +634,145 @@
                 self.buf(', '.join(vals[i:i + 8]))
         self.buf('}')
 
-    def _declare_device(self, var_name, struct_name, node_parent):
+    def _declare_device(self, node):
         """Add a device declaration to the output
 
         This declares a U_BOOT_DRVINFO() for the device being processed
 
         Args:
-            var_name (str): C name for the node
-            struct_name (str): Name for the dt struct associated with the node
-            node_parent (Node): Parent of the node (or None if none)
+            node: Node to process
         """
-        self.buf('U_BOOT_DRVINFO(%s) = {\n' % var_name)
-        self.buf('\t.name\t\t= "%s",\n' % struct_name)
-        self.buf('\t.plat\t= &%s%s,\n' % (VAL_PREFIX, var_name))
-        self.buf('\t.plat_size\t= sizeof(%s%s),\n' % (VAL_PREFIX, var_name))
+        self.buf('U_BOOT_DRVINFO(%s) = {\n' % node.var_name)
+        self.buf('\t.name\t\t= "%s",\n' % node.struct_name)
+        self.buf('\t.plat\t\t= &%s%s,\n' % (VAL_PREFIX, node.var_name))
+        self.buf('\t.plat_size\t= sizeof(%s%s),\n' %
+                 (VAL_PREFIX, node.var_name))
         idx = -1
-        if node_parent and node_parent in self._valid_nodes:
-            idx = node_parent.idx
+        if node.parent and node.parent in self._valid_nodes:
+            idx = node.parent.idx
         self.buf('\t.parent_idx\t= %d,\n' % idx)
         self.buf('};\n')
         self.buf('\n')
 
-    def _output_prop(self, node, prop):
+    def prep_priv(self, struc, name, suffix, section='.priv_data'):
+        if not struc:
+            return None
+        var_name = '_%s%s' % (name, suffix)
+        hdr = self._scan._structs.get(struc)
+        if hdr:
+            self.buf('#include <%s>\n' % hdr.fname)
+        else:
+            print('Warning: Cannot find header file for struct %s' % struc)
+        attr = '__attribute__ ((section ("%s")))' % section
+        return var_name, struc, attr
+
+    def alloc_priv(self, info, name, extra, suffix='_priv'):
+        result = self.prep_priv(info, name, suffix)
+        if not result:
+            return None
+        var_name, struc, section = result
+        self.buf('u8 %s_%s[sizeof(struct %s)]\n\t%s;\n' %
+                 (var_name, extra, struc.strip(), section))
+        return '%s_%s' % (var_name, extra)
+
+    def alloc_plat(self, info, name, extra, node):
+        result = self.prep_priv(info, name, '_plat')
+        if not result:
+            return None
+        var_name, struc, section = result
+        self.buf('struct %s %s\n\t%s_%s = {\n' %
+                 (struc.strip(), section, var_name, extra))
+        self.buf('\t.dtplat = {\n')
+        for pname in sorted(node.props):
+            self._output_prop(node, node.props[pname], 2)
+        self.buf('\t},\n')
+        self.buf('};\n')
+        return '&%s_%s' % (var_name, extra)
+
+    def _declare_device_inst(self, node, parent_driver):
+        """Add a device instance declaration to the output
+
+        This declares a DM_DEVICE_INST() for the device being processed
+
+        Args:
+            node: Node to output
+        """
+        driver = node.driver
+        uclass = node.uclass
+        self.buf('\n')
+        num_lines = len(self._lines)
+        plat_name = self.alloc_plat(driver.plat, driver.name, node.var_name,
+                                    node)
+        priv_name = self.alloc_priv(driver.priv, driver.name, node.var_name)
+        parent_plat_name = None
+        parent_priv_name = None
+        if parent_driver:
+            # TODO: deal with uclass providing these values
+            parent_plat_name = self.alloc_priv(
+                parent_driver.child_plat, driver.name, node.var_name,
+                '_parent_plat')
+            parent_priv_name = self.alloc_priv(
+                parent_driver.child_priv, driver.name, node.var_name,
+                '_parent_priv')
+        uclass_plat_name = self.alloc_priv(
+            uclass.per_dev_plat, driver.name + '_uc', node.var_name, 'plat')
+        uclass_priv_name = self.alloc_priv(uclass.per_dev_priv,
+                                           driver.name + '_uc', node.var_name)
+        for hdr in driver.headers:
+            self.buf('#include %s\n' % hdr)
+
+        # Add a blank line if we emitted any stuff above, for readability
+        if num_lines != len(self._lines):
+            self.buf('\n')
+
+        self.buf('DM_DEVICE_INST(%s) = {\n' % node.var_name)
+        self.buf('\t.driver\t\t= DM_DRIVER_REF(%s),\n' % node.struct_name)
+        self.buf('\t.name\t\t= "%s",\n' % node.struct_name)
+        if plat_name:
+            self.buf('\t.plat_\t\t= %s,\n' % plat_name)
+        else:
+            self.buf('\t.plat_\t\t= &%s%s,\n' % (VAL_PREFIX, node.var_name))
+        if parent_plat_name:
+            self.buf('\t.parent_plat_\t= %s,\n' % parent_plat_name)
+        if uclass_plat_name:
+            self.buf('\t.uclass_plat_\t= %s,\n' % uclass_plat_name)
+        driver_date = None
+
+        if node != self._fdt.GetRoot():
+            compat_list = node.props['compatible'].value
+            if not isinstance(compat_list, list):
+                compat_list = [compat_list]
+            for compat in compat_list:
+                driver_data = driver.compat.get(compat)
+                if driver_data:
+                    self.buf('\t.driver_data\t= %s,\n' % driver_data)
+                    break
+
+        if node.parent and node.parent.parent:
+            self.buf('\t.parent\t\t= DM_DEVICE_REF(%s),\n' %
+                     node.parent.var_name)
+        if priv_name:
+            self.buf('\t.priv_\t\t= %s,\n' % priv_name)
+        self.buf('\t.uclass\t\t= DM_UCLASS_REF(%s),\n' % uclass.name)
+
+        if uclass_priv_name:
+            self.buf('\t.uclass_priv_ = %s,\n' % uclass_priv_name)
+        if parent_priv_name:
+            self.buf('\t.parent_priv_\t= %s,\n' % parent_priv_name)
+        self.list_node('uclass_node', uclass.node_refs, node.uclass_seq)
+        self.list_head('child_head', 'sibling_node', node.child_devs, node.var_name)
+        if node.parent in self._valid_nodes:
+            self.list_node('sibling_node', node.parent.child_refs,
+                           node.parent_seq)
+        # flags is left as 0
+
+        self.buf('\t.seq_ = %d,\n' % node.seq)
+
+        self.buf('};\n')
+        self.buf('\n')
+        return parent_plat_name
+
+    def _output_prop(self, node, prop, tabs=1):
         """Output a line containing the value of a struct member
 
         Args:
@@ -593,7 +782,7 @@
         if prop.name in PROP_IGNORE_LIST or prop.name[0] == '#':
             return
         member_name = conv_name_to_c(prop.name)
-        self.buf('\t%s= ' % tab_to(3, '.' + member_name))
+        self.buf('%s%s= ' % ('\t' * tabs, tab_to(3, '.' + member_name)))
 
         # Special handling for lists
         if isinstance(prop.value, list):
@@ -602,35 +791,269 @@
             self.buf(get_value(prop.type, prop.value))
         self.buf(',\n')
 
-    def _output_values(self, var_name, struct_name, node):
+    def _output_values(self, node):
         """Output the definition of a device's struct values
 
         Args:
-            var_name (str): C name for the node
-            struct_name (str): Name for the dt struct associated with the node
-            node (Node): Node being output
+            node (Node): Node to output
         """
         self.buf('static struct %s%s %s%s = {\n' %
-                 (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
+                 (STRUCT_PREFIX, node.struct_name, VAL_PREFIX, node.var_name))
         for pname in sorted(node.props):
             self._output_prop(node, node.props[pname])
         self.buf('};\n')
 
-    def output_node(self, node):
+    def list_head(self, head_member, node_member, node_refs, var_name):
+        self.buf('\t.%s\t= {\n' % head_member)
+        if node_refs:
+            last = node_refs[-1].dev_ref
+            first = node_refs[0].dev_ref
+            member = node_member
+        else:
+            last = 'DM_DEVICE_REF(%s)' % var_name
+            first = last
+            member = head_member
+        self.buf('\t\t.prev = &%s->%s,\n' % (last, member))
+        self.buf('\t\t.next = &%s->%s,\n' % (first, member))
+        self.buf('\t},\n')
+
+    def list_node(self, member, node_refs, seq):
+        self.buf('\t.%s\t= {\n' % member)
+        self.buf('\t\t.prev = %s,\n' % node_refs[seq - 1])
+        self.buf('\t\t.next = %s,\n' % node_refs[seq + 1])
+        self.buf('\t},\n')
+
+    def generate_uclasses(self):
+        if not self.check_instantiate(True):
+            return
+        self.out('\n')
+        self.out('#include <common.h>\n')
+        self.out('#include <dm.h>\n')
+        self.out('#include <dt-structs.h>\n')
+        self.out('\n')
+        self.buf('/*\n')
+        self.buf(
+            " * uclass declarations, ordered by 'struct uclass' linker_list idx:\n")
+        uclass_list = self._valid_uclasses
+        for seq, uclass in enumerate(uclass_list):
+            self.buf(' * %3d: %s\n' % (seq, uclass.name))
+        self.buf(' *\n')
+        self.buf(' * Sequence numbers allocated in each uclass:\n')
+        for uclass in uclass_list:
+            if uclass.alias_num_to_node:
+                self.buf(' * %s: %s\n' % (uclass.name, uclass.uclass_id))
+                for seq, node in uclass.alias_num_to_node.items():
+                    self.buf(' *    %d: %s\n' % (seq, node.path))
+        self.buf(' */\n')
+
+        uclass_node = {}
+        for seq, uclass in enumerate(uclass_list):
+            uclass_node[seq] = ('&DM_UCLASS_REF(%s)->sibling_node' %
+                                uclass.name)
+        uclass_node[-1] = '&uclass_head'
+        uclass_node[len(uclass_list)] = '&uclass_head'
+        self.buf('\n')
+        self.buf('struct list_head %s = {\n' % 'uclass_head')
+        self.buf('\t.prev = %s,\n' % uclass_node[len(uclass_list) -1])
+        self.buf('\t.next = %s,\n' % uclass_node[0])
+        self.buf('};\n')
+        self.buf('\n')
+
+        for seq, uclass in enumerate(uclass_list):
+            uc_drv = self._scan._uclass.get(uclass.uclass_id)
+
+            priv_name = self.alloc_priv(uc_drv.priv, uc_drv.name, '')
+
+            self.buf('DM_UCLASS_INST(%s) = {\n' % uclass.name)
+            if priv_name:
+                self.buf('\t.priv_\t\t= %s,\n' % priv_name)
+            self.buf('\t.uc_drv\t\t= DM_UCLASS_DRIVER_REF(%s),\n' % uclass.name)
+            self.list_node('sibling_node', uclass_node, seq)
+            self.list_head('dev_head', 'uclass_node', uc_drv.devs, None)
+            self.buf('};\n')
+            self.buf('\n')
+        self.out(''.join(self.get_buf()))
+
+    def read_aliases(self):
+        """Read the aliases and attach the information to self._alias
+
+        Raises:
+            ValueError: The alias path is not found
+        """
+        alias_node = self._fdt.GetNode('/aliases')
+        if not alias_node:
+            return
+        re_num = re.compile('(^[a-z0-9-]+[a-z]+)([0-9]+)$')
+        for prop in alias_node.props.values():
+            m_alias = re_num.match(prop.name)
+            if not m_alias:
+                raise ValueError("Cannot decode alias '%s'" % prop.name)
+            name, num = m_alias.groups()
+            node = self._fdt.GetNode(prop.value)
+            result = self._scan.add_uclass_alias(name, num, node)
+            if result is None:
+                raise ValueError("Alias '%s' path '%s' not found" %
+                                 (prop.name, prop.value))
+            elif result is False:
+                print("Could not find uclass for alias '%s'" % prop.name)
+
+    def generate_decl(self):
+        nodes_to_output = list(self._valid_nodes)
+
+        self.buf('#include <dm/device-internal.h>\n')
+        self.buf('#include <dm/uclass-internal.h>\n')
+        self.buf('\n')
+        self.buf(
+            '/* driver declarations - these allow DM_DRIVER_GET() to be used */\n')
+        for node in nodes_to_output:
+            self.buf('extern U_BOOT_DRIVER(%s);\n' % node.struct_name);
+        self.buf('\n')
+
+        if self._instantiate:
+            self.buf(
+                '/* device declarations - these allow DM_DEVICE_REF() to be used */\n')
+            for node in nodes_to_output:
+                self.buf('extern DM_DEVICE_INST(%s);\n' % node.var_name)
+            self.buf('\n')
+
+        uclass_list = self._valid_uclasses
+
+        self.buf(
+            '/* uclass driver declarations - needed for DM_UCLASS_DRIVER_REF() */\n')
+        for uclass in uclass_list:
+            self.buf('extern UCLASS_DRIVER(%s);\n' % uclass.name)
+
+        if self._instantiate:
+            self.buf('\n')
+            self.buf('/* uclass declarations - needed for DM_UCLASS_REF() */\n')
+            for uclass in uclass_list:
+                self.buf('extern DM_UCLASS_INST(%s);\n' % uclass.name)
+        self.out(''.join(self.get_buf()))
+
+    def assign_seqs(self):
+        """Assign a sequence number to each node"""
+        for node in self._valid_nodes_unsorted:
+            seq = self._scan.assign_seq(node)
+            if seq is not None:
+                node.seq = seq
+
+    def process_nodes(self, need_drivers):
+        nodes_to_output = list(self._valid_nodes)
+
+        # Figure out which drivers we actually use
+        self._scan.mark_used(nodes_to_output)
+
+        for node in nodes_to_output:
+            node.dev_ref = 'DM_DEVICE_REF(%s)' % node.var_name
+            driver = self._scan.get_driver(node.struct_name)
+            if not driver:
+                if not need_drivers:
+                    continue
+                raise ValueError("Cannot parse/find driver for '%s'" %
+                                 node.struct_name)
+            node.driver = driver
+            uclass = self._scan._uclass.get(driver.uclass_id)
+            if not uclass:
+                raise ValueError("Cannot parse/find uclass '%s' for driver '%s'" %
+                                (driver.uclass_id, node.struct_name))
+            node.uclass = uclass
+            node.uclass_seq = len(node.uclass.devs)
+            node.uclass.devs.append(node)
+            uclass.node_refs[node.uclass_seq] = \
+                '&%s->uclass_node' % node.dev_ref
+
+            parent_driver = None
+            if node.parent in self._valid_nodes:
+                parent_driver = self._scan.get_driver(node.parent.struct_name)
+                if not parent_driver:
+                    if not need_drivers:
+                        continue
+                    raise ValueError(
+                        "Cannot parse/find parent driver '%s' for '%s'" %
+                        (node.parent.struct_name, node.struct_name))
+                node.parent_seq = len(node.parent.child_devs)
+                node.parent.child_devs.append(node)
+                node.parent.child_refs[node.parent_seq] = \
+                    '&%s->sibling_node' % node.dev_ref
+                node.parent_driver = parent_driver
+
+        for node in nodes_to_output:
+            ref = '&%s->child_head' % node.dev_ref
+            node.child_refs[-1] = ref
+            node.child_refs[len(node.child_devs)] = ref
+
+        uclass_set = set()
+        for driver in self._scan._drivers.values():
+            if driver.used and driver.uclass:
+                uclass_set.add(driver.uclass)
+        self._valid_uclasses = sorted(list(uclass_set),
+                                      key=lambda uc: uc.uclass_id)
+
+        for seq, uclass in enumerate(uclass_set):
+            ref = '&DM_UCLASS_REF(%s)->dev_head' % uclass.name
+            uclass.node_refs[-1] = ref
+            uclass.node_refs[len(uclass.devs)] = ref
+
+    def output_node_plat(self, node):
         """Output the C code for a node
 
         Args:
             node (fdt.Node): node to output
         """
-        struct_name, _ = self._scan.get_normalized_compat_name(node)
-        var_name = conv_name_to_c(node.name)
-        self.buf('/* Node %s index %d */\n' % (node.path, node.idx))
+        driver = node.driver
+        parent_driver = node.parent_driver
 
-        self._output_values(var_name, struct_name, node)
-        self._declare_device(var_name, struct_name, node.parent)
+        line1 = 'Node %s index %d' % (node.path, node.idx)
+        if driver:
+            self.buf('/*\n')
+            self.buf(' * %s\n' % line1)
+            self.buf(' * driver %s parent %s\n' % (driver.name,
+                parent_driver.name if parent_driver else 'None'))
+            self.buf(' */\n')
+        else:
+            self.buf('/* %s */\n' % line1)
+
+        self._output_values(node)
+        self._declare_device(node)
 
         self.out(''.join(self.get_buf()))
 
+    def output_node_instance(self, node):
+        """Output the C code for a node
+
+        Args:
+            node (fdt.Node): node to output
+        """
+        parent_driver = node.parent_driver
+
+        self.buf('/*\n')
+        self.buf(' * Node %s index %d\n' % (node.path, node.idx))
+        self.buf(' * driver %s parent %s\n' % (node.driver.name,
+                 parent_driver.name if parent_driver else 'None'))
+        self.buf('*/\n')
+
+        if not node.driver.plat:
+            self._output_values(node)
+        self._declare_device_inst(node, parent_driver)
+
+        self.out(''.join(self.get_buf()))
+
+    def check_instantiate(self, require):
+        """Check if self._instantiate is set to the required value
+
+        If not, this outputs a message into the current file
+
+        Args:
+            require: True to require --instantiate, False to require that it not
+                be enabled
+        """
+        if require != self._instantiate:
+            self.out(
+                '/* This file is not used: --instantiate was %senabled */\n' %
+                ('not ' if require else ''))
+            return False
+        return True
+
     def generate_plat(self):
         """Generate device defintions for the platform data
 
@@ -641,6 +1064,8 @@
         See the documentation in doc/driver-model/of-plat.rst for more
         information.
         """
+        if not self.check_instantiate(False):
+            return
         self.out('/* Allow use of U_BOOT_DRVINFO() in this file */\n')
         self.out('#define DT_PLAT_C\n')
         self.out('\n')
@@ -649,8 +1074,57 @@
         self.out('#include <dt-structs.h>\n')
         self.out('\n')
 
-        for node in self._valid_nodes:
-            self.output_node(node)
+        if self._valid_nodes:
+            self.out('/*\n')
+            self.out(
+                " * driver_info declarations, ordered by 'struct driver_info' linker_list idx:\n")
+            self.out(' *\n')
+            self.out(' * idx  %-20s %-s\n' % ('driver_info', 'driver'))
+            self.out(' * ---  %-20s %-s\n' % ('-' * 20, '-' * 20))
+            for node in self._valid_nodes:
+                self.out(' * %3d: %-20s %-s\n' %
+                        (node.idx, node.var_name, node.struct_name))
+            self.out(' * ---  %-20s %-s\n' % ('-' * 20, '-' * 20))
+            self.out(' */\n')
+            self.out('\n')
+
+            for node in self._valid_nodes:
+                self.output_node_plat(node)
+
+        self.out(''.join(self.get_buf()))
+
+    def generate_device(self):
+        """Generate device instances
+
+        This writes out DM_DEVICE_INST() records for each device in the
+        build.
+
+        See the documentation in doc/driver-model/of-plat.rst for more
+        information.
+        """
+        if not self.check_instantiate(True):
+            return
+        self.out('#include <common.h>\n')
+        self.out('#include <dm.h>\n')
+        self.out('#include <dt-structs.h>\n')
+        self.out('\n')
+
+        if self._valid_nodes:
+            self.out('/*\n')
+            self.out(
+                " * udevice declarations, ordered by 'struct udevice' linker_list position:\n")
+            self.out(' *\n')
+            self.out(' * idx  %-20s %-s\n' % ('udevice', 'driver'))
+            self.out(' * ---  %-20s %-s\n' % ('-' * 20, '-' * 20))
+            for node in self._valid_nodes:
+                self.out(' * %3d: %-20s %-s\n' %
+                        (node.idx, node.var_name, node.struct_name))
+            self.out(' * ---  %-20s %-s\n' % ('-' * 20, '-' * 20))
+            self.out(' */\n')
+            self.out('\n')
+
+            for node in self._valid_nodes:
+                self.output_node_instance(node)
 
         self.out(''.join(self.get_buf()))
 
@@ -658,19 +1132,37 @@
 # Types of output file we understand
 # key: Command used to generate this file
 # value: OutputFile for this command
-OUTPUT_FILES = {
+OUTPUT_FILES_COMMON = {
+    'decl':
+        OutputFile(Ftype.HEADER, 'dt-decl.h', DtbPlatdata.generate_decl,
+                   'Declares externs for all device/uclass instances'),
     'struct':
         OutputFile(Ftype.HEADER, 'dt-structs-gen.h',
                    DtbPlatdata.generate_structs,
                    'Defines the structs used to hold devicetree data'),
+    }
+
+# File generated without instantiate
+OUTPUT_FILES_NOINST = {
     'platdata':
         OutputFile(Ftype.SOURCE, 'dt-plat.c', DtbPlatdata.generate_plat,
                    'Declares the U_BOOT_DRIVER() records and platform data'),
     }
 
+# File generated with instantiate
+OUTPUT_FILES_INST = {
+    'device':
+        OutputFile(Ftype.SOURCE, 'dt-device.c', DtbPlatdata.generate_device,
+                   'Declares the DM_DEVICE_INST() records'),
+    'uclass':
+        OutputFile(Ftype.SOURCE, 'dt-uclass.c', DtbPlatdata.generate_uclasses,
+                   'Declares the uclass instances (struct uclass)'),
+    }
 
-def run_steps(args, dtb_file, include_disabled, output, output_dirs,
-              warning_disabled=False, drivers_additional=None, basedir=None):
+
+def run_steps(args, dtb_file, include_disabled, output, output_dirs, phase,
+              instantiate, warning_disabled=False, drivers_additional=None,
+              basedir=None, scan=None):
     """Run all the steps of the dtoc tool
 
     Args:
@@ -681,12 +1173,22 @@
         output_dirs (tuple of str):
             Directory to put C output files
             Directory to put H output files
+        phase: The phase of U-Boot that we are generating data for, e.g. 'spl'
+             or 'tpl'. None if not known
+        instantiate: Instantiate devices so they don't need to be bound at
+            run-time
         warning_disabled (bool): True to avoid showing warnings about missing
             drivers
         drivers_additional (list): List of additional drivers to use during
             scanning
         basedir (str): Base directory of U-Boot source code. Defaults to the
             grandparent of this file's directory
+        scan (src_src.Scanner): Scanner from a previous run. This can help speed
+            up tests. Use None for normal operation
+
+    Returns:
+        DtbPlatdata object
+
     Raises:
         ValueError: if args has no command, or an unknown command
     """
@@ -695,26 +1197,45 @@
     if output and output_dirs and any(output_dirs):
         raise ValueError('Must specify either output or output_dirs, not both')
 
-    scan = src_scan.Scanner(basedir, warning_disabled, drivers_additional)
-    plat = DtbPlatdata(scan, dtb_file, include_disabled)
-    scan.scan_drivers()
+    if not scan:
+        scan = src_scan.Scanner(basedir, drivers_additional, phase)
+        scan.scan_drivers()
+        do_process = True
+    else:
+        do_process = False
+    plat = DtbPlatdata(scan, dtb_file, include_disabled, instantiate)
     plat.scan_dtb()
-    plat.scan_tree()
+    plat.scan_tree(add_root=instantiate)
+    plat.prepare_nodes()
     plat.scan_reg_sizes()
     plat.setup_output_dirs(output_dirs)
     plat.scan_structs()
     plat.scan_phandles()
+    plat.process_nodes(instantiate)
+    plat.read_aliases()
+    plat.assign_seqs()
+
+    # Figure out what output files we plan to generate
+    output_files = OUTPUT_FILES_COMMON
+    if instantiate:
+        output_files.update(OUTPUT_FILES_INST)
+    else:
+        output_files.update(OUTPUT_FILES_NOINST)
 
     cmds = args[0].split(',')
     if 'all' in cmds:
-        cmds = sorted(OUTPUT_FILES.keys())
+        cmds = sorted(output_files.keys())
     for cmd in cmds:
-        outfile = OUTPUT_FILES.get(cmd)
+        outfile = output_files.get(cmd)
         if not outfile:
             raise ValueError("Unknown command '%s': (use: %s)" %
-                             (cmd, ', '.join(sorted(OUTPUT_FILES.keys()))))
+                             (cmd, ', '.join(sorted(output_files.keys()))))
         plat.setup_output(outfile.ftype,
                           outfile.fname if output_dirs else output)
         plat.out_header(outfile)
         outfile.method(plat)
     plat.finish_output()
+
+    if not warning_disabled:
+        scan.show_warnings()
+    return plat
diff --git a/tools/dtoc/dtoc_test_scan_drivers.cxx b/tools/dtoc/dtoc_test_scan_drivers.cxx
deleted file mode 100644
index f448767..0000000
--- a/tools/dtoc/dtoc_test_scan_drivers.cxx
+++ /dev/null
@@ -1 +0,0 @@
-DM_DRIVER_ALIAS(sandbox_gpio, sandbox_gpio_alias2)
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
index 25ce513..3996971 100644
--- a/tools/dtoc/fdt.py
+++ b/tools/dtoc/fdt.py
@@ -103,6 +103,8 @@
     """A device tree property
 
     Properties:
+        node: Node containing this property
+        offset: Offset of the property (None if still to be synced)
         name: Property name (as per the device tree)
         value: Property value as a string of bytes, or a list of strings of
             bytes
@@ -114,7 +116,7 @@
         self.name = name
         self.value = None
         self.bytes = bytes(data)
-        self.dirty = False
+        self.dirty = offset is None
         if not data:
             self.type = Type.BOOL
             self.value = True
@@ -228,9 +230,14 @@
         Raises:
             FdtException if auto_resize is False and there is not enough space
         """
-        if self._offset is None or self.dirty:
+        if self.dirty:
             node = self._node
             fdt_obj = node._fdt._fdt_obj
+            node_name = fdt_obj.get_name(node._offset)
+            if node_name and node_name != node.name:
+                raise ValueError("Internal error, node '%s' name mismatch '%s'" %
+                                 (node.path, node_name))
+
             if auto_resize:
                 while fdt_obj.setprop(node.Offset(), self.name, self.bytes,
                                     (libfdt.NOSPACE,)) == -libfdt.NOSPACE:
@@ -239,13 +246,15 @@
                     fdt_obj.setprop(node.Offset(), self.name, self.bytes)
             else:
                 fdt_obj.setprop(node.Offset(), self.name, self.bytes)
+            self.dirty = False
 
 
 class Node:
     """A device tree node
 
     Properties:
-        offset: Integer offset in the device tree
+        parent: Parent Node
+        offset: Integer offset in the device tree (None if to be synced)
         name: Device tree node tname
         path: Full path to node, along with the node name itself
         _fdt: Device tree object
@@ -324,6 +333,11 @@
         fdt_obj = self._fdt._fdt_obj
         if self._offset != my_offset:
             self._offset = my_offset
+        name = fdt_obj.get_name(self._offset)
+        if name and self.name != name:
+            raise ValueError("Internal error, node '%s' name mismatch '%s'" %
+                             (self.path, name))
+
         offset = fdt_obj.first_subnode(self._offset, QUIET_NOTFOUND)
         for subnode in self.subnodes:
             if subnode.name != fdt_obj.get_name(offset):
@@ -339,8 +353,8 @@
             p = fdt_obj.get_property_by_offset(poffset)
             prop = self.props.get(p.name)
             if not prop:
-                raise ValueError("Internal error, property '%s' missing, "
-                                 'offset %d' % (p.name, poffset))
+                raise ValueError("Internal error, node '%s' property '%s' missing, "
+                                 'offset %d' % (self.path, p.name, poffset))
             prop.RefreshOffset(poffset)
             poffset = fdt_obj.next_property_offset(poffset, QUIET_NOTFOUND)
 
@@ -447,8 +461,13 @@
         Args:
             prop_name: Name of property to add
             val: Bytes value of property
+
+        Returns:
+            Prop added
         """
-        self.props[prop_name] = Prop(self, None, prop_name, val)
+        prop = Prop(self, None, prop_name, val)
+        self.props[prop_name] = prop
+        return prop
 
     def AddString(self, prop_name, val):
         """Add a new string property to a node
@@ -459,9 +478,12 @@
         Args:
             prop_name: Name of property to add
             val: String value of property
+
+        Returns:
+            Prop added
         """
         val = bytes(val, 'utf-8')
-        self.AddData(prop_name, val + b'\0')
+        return self.AddData(prop_name, val + b'\0')
 
     def AddInt(self, prop_name, val):
         """Add a new integer property to a node
@@ -472,8 +494,11 @@
         Args:
             prop_name: Name of property to add
             val: Integer value of property
+
+        Returns:
+            Prop added
         """
-        self.AddData(prop_name, struct.pack('>I', val))
+        return self.AddData(prop_name, struct.pack('>I', val))
 
     def AddSubnode(self, name):
         """Add a new subnode to the node
@@ -499,9 +524,13 @@
             auto_resize: Resize the device tree automatically if it does not
                 have enough space for the update
 
+        Returns:
+            True if the node had to be added, False if it already existed
+
         Raises:
             FdtException if auto_resize is False and there is not enough space
         """
+        added = False
         if self._offset is None:
             # The subnode doesn't exist yet, so add it
             fdt_obj = self._fdt._fdt_obj
@@ -515,23 +544,45 @@
             else:
                 offset = fdt_obj.add_subnode(self.parent._offset, self.name)
             self._offset = offset
+            added = True
 
-        # Sync subnodes in reverse so that we don't disturb node offsets for
-        # nodes that are earlier in the DT. This avoids an O(n^2) rescan of
-        # node offsets.
+        # Sync the existing subnodes first, so that we can rely on the offsets
+        # being correct. As soon as we add new subnodes, it pushes all the
+        # existing subnodes up.
         for node in reversed(self.subnodes):
-            node.Sync(auto_resize)
+            if node._offset is not None:
+                node.Sync(auto_resize)
 
-        # Sync properties now, whose offsets should not have been disturbed.
-        # We do this after subnodes, since this disturbs the offsets of these
-        # properties. Note that new properties will have an offset of None here,
-        # which Python 3 cannot sort against int. So use a large value instead
-        # to ensure that the new properties are added first.
+        # Sync subnodes in reverse so that we get the expected order. Each
+        # new node goes at the start of the subnode list. This avoids an O(n^2)
+        # rescan of node offsets.
+        num_added = 0
+        for node in reversed(self.subnodes):
+            if node.Sync(auto_resize):
+                num_added += 1
+        if num_added:
+            # Reorder our list of nodes to put the new ones first, since that's
+            # what libfdt does
+            old_count = len(self.subnodes) - num_added
+            subnodes = self.subnodes[old_count:] + self.subnodes[:old_count]
+            self.subnodes = subnodes
+
+        # Sync properties now, whose offsets should not have been disturbed,
+        # since properties come before subnodes. This is done after all the
+        # subnode processing above, since updating properties can disturb the
+        # offsets of those subnodes.
+        # Properties are synced in reverse order, with new properties added
+        # before existing properties are synced. This ensures that the offsets
+        # of earlier properties are not disturbed.
+        # Note that new properties will have an offset of None here, which
+        # Python cannot sort against int. So use a large value instead so that
+        # new properties are added first.
         prop_list = sorted(self.props.values(),
                            key=lambda prop: prop._offset or 1 << 31,
                            reverse=True)
         for prop in prop_list:
             prop.Sync(auto_resize)
+        return added
 
 
 class Fdt:
@@ -642,8 +693,9 @@
         Raises:
             FdtException if auto_resize is False and there is not enough space
         """
+        self.CheckCache()
         self._root.Sync(auto_resize)
-        self.Invalidate()
+        self.Refresh()
 
     def Pack(self):
         """Pack the device tree down to its minimum size
@@ -652,7 +704,7 @@
         build up in the device tree binary.
         """
         CheckErr(self._fdt_obj.pack(), 'pack')
-        self.Invalidate()
+        self.Refresh()
 
     def GetContents(self):
         """Get the contents of the FDT
@@ -704,11 +756,11 @@
         if self._cached_offsets:
             return
         self.Refresh()
-        self._cached_offsets = True
 
     def Refresh(self):
         """Refresh the offset cache"""
         self._root.Refresh(0)
+        self._cached_offsets = True
 
     def GetStructOffset(self, offset):
         """Get the file offset of a given struct offset
diff --git a/tools/dtoc/main.py b/tools/dtoc/main.py
index b0ad0f3..93706de 100755
--- a/tools/dtoc/main.py
+++ b/tools/dtoc/main.py
@@ -53,6 +53,8 @@
     sys.argv = [sys.argv[0]]
     test_name = args and args[0] or None
 
+    test_dtoc.setup()
+
     test_util.RunTestSuites(
         result, debug=True, verbosity=1, test_preserve_dirs=False,
         processes=processes, test_name=test_name, toolpath=[],
@@ -79,10 +81,14 @@
                   help='Select output directory for H files (defaults to --c-output-di)')
 parser.add_option('-d', '--dtb-file', action='store',
                   help='Specify the .dtb input file')
+parser.add_option('-i', '--instantiate', action='store_true', default=False,
+                  help='Instantiate devices to avoid needing device_bind()')
 parser.add_option('--include-disabled', action='store_true',
                   help='Include disabled nodes')
 parser.add_option('-o', '--output', action='store',
                   help='Select output filename')
+parser.add_option('-p', '--phase', type=str,
+                  help='set phase of U-Boot this invocation is for (spl/tpl)')
 parser.add_option('-P', '--processes', type=int,
                   help='set number of processes to use for running tests')
 parser.add_option('-t', '--test', action='store_true', dest='test',
@@ -102,4 +108,5 @@
 else:
     dtb_platdata.run_steps(args, options.dtb_file, options.include_disabled,
                            options.output,
-                           [options.c_output_dir, options.h_output_dir])
+                           [options.c_output_dir, options.h_output_dir],
+                           options.phase, instantiate=options.instantiate)
diff --git a/tools/dtoc/src_scan.py b/tools/dtoc/src_scan.py
index f63c9fc..2db9688 100644
--- a/tools/dtoc/src_scan.py
+++ b/tools/dtoc/src_scan.py
@@ -33,6 +33,8 @@
     new = new.replace('-', '_')
     new = new.replace(',', '_')
     new = new.replace('.', '_')
+    if new == '/':
+        return 'root'
     return new
 
 def get_compat_name(node):
@@ -54,15 +56,123 @@
 
     Attributes:
         name: Name of driver. For U_BOOT_DRIVER(x) this is 'x'
+        fname: Filename where the driver was found
+        uclass_id: Name of uclass, e.g. 'UCLASS_I2C'
+        compat: Driver data for each compatible string:
+            key: Compatible string, e.g. 'rockchip,rk3288-grf'
+            value: Driver data, e,g, 'ROCKCHIP_SYSCON_GRF', or None
+        fname: Filename where the driver was found
+        priv (str): struct name of the priv_auto member, e.g. 'serial_priv'
+        plat (str): struct name of the plat_auto member, e.g. 'serial_plat'
+        child_priv (str): struct name of the per_child_auto member,
+            e.g. 'pci_child_priv'
+        child_plat (str): struct name of the per_child_plat_auto member,
+            e.g. 'pci_child_plat'
+        used (bool): True if the driver is used by the structs being output
+        phase (str): Which phase of U-Boot to use this driver
+        headers (list): List of header files needed for this driver (each a str)
+            e.g. ['<asm/cpu.h>']
+        dups (list): Driver objects with the same name as this one, that were
+            found after this one
+        warn_dups (bool): True if the duplicates are not distinguisble using
+            the phase
+        uclass (Uclass): uclass for this driver
+    """
+    def __init__(self, name, fname):
+        self.name = name
+        self.fname = fname
+        self.uclass_id = None
+        self.compat = None
+        self.priv = ''
+        self.plat = ''
+        self.child_priv = ''
+        self.child_plat = ''
+        self.used = False
+        self.phase = ''
+        self.headers = []
+        self.dups = []
+        self.warn_dups = False
+        self.uclass = None
+
+    def __eq__(self, other):
+        return (self.name == other.name and
+                self.uclass_id == other.uclass_id and
+                self.compat == other.compat and
+                self.priv == other.priv and
+                self.plat == other.plat and
+                self.used == other.used)
+
+    def __repr__(self):
+        return ("Driver(name='%s', used=%s, uclass_id='%s', compat=%s, priv=%s)" %
+                (self.name, self.used, self.uclass_id, self.compat, self.priv))
+
+
+class UclassDriver:
+    """Holds information about a uclass driver
+
+    Attributes:
+        name: Uclass name, e.g. 'i2c' if the driver is for UCLASS_I2C
+        uclass_id: Uclass ID, e.g. 'UCLASS_I2C'
+        priv: struct name of the private data, e.g. 'i2c_priv'
+        per_dev_priv (str): struct name of the priv_auto member, e.g. 'spi_info'
+        per_dev_plat (str): struct name of the plat_auto member, e.g. 'i2c_chip'
+        per_child_priv (str): struct name of the per_child_auto member,
+            e.g. 'pci_child_priv'
+        per_child_plat (str): struct name of the per_child_plat_auto member,
+            e.g. 'pci_child_plat'
+        alias_num_to_node (dict): Aliases for this uclasses (for sequence
+                numbers)
+            key (int): Alias number, e.g. 2 for "pci2"
+            value (str): Node the alias points to
+        alias_path_to_num (dict): Convert a path to an alias number
+            key (str): Full path to node (e.g. '/soc/pci')
+            seq (int): Alias number, e.g. 2 for "pci2"
+        devs (list): List of devices in this uclass, each a Node
+        node_refs (dict): References in the linked list of devices:
+            key (int): Sequence number (0=first, n-1=last, -1=head, n=tail)
+            value (str): Reference to the device at that position
     """
     def __init__(self, name):
         self.name = name
+        self.uclass_id = None
+        self.priv = ''
+        self.per_dev_priv = ''
+        self.per_dev_plat = ''
+        self.per_child_priv = ''
+        self.per_child_plat = ''
+        self.alias_num_to_node = {}
+        self.alias_path_to_num = {}
+        self.devs = []
+        self.node_refs = {}
 
     def __eq__(self, other):
-        return self.name == other.name
+        return (self.name == other.name and
+                self.uclass_id == other.uclass_id and
+                self.priv == other.priv)
 
     def __repr__(self):
-        return "Driver(name='%s')" % self.name
+        return ("UclassDriver(name='%s', uclass_id='%s')" %
+                (self.name, self.uclass_id))
+
+    def __hash__(self):
+        # We can use the uclass ID since it is unique among uclasses
+        return hash(self.uclass_id)
+
+
+class Struct:
+    """Holds information about a struct definition
+
+    Attributes:
+        name: Struct name, e.g. 'fred' if the struct is 'struct fred'
+        fname: Filename containing the struct, in a format that C files can
+            include, e.g. 'asm/clk.h'
+    """
+    def __init__(self, name, fname):
+        self.name = name
+        self.fname =fname
+
+    def __repr__(self):
+        return ("Struct(name='%s', fname='%s')" % (self.name, self.fname))
 
 
 class Scanner:
@@ -78,11 +188,24 @@
             key: Driver alias declared with
                 DM_DRIVER_ALIAS(driver_alias, driver_name)
             value: Driver name declared with U_BOOT_DRIVER(driver_name)
-        _warning_disabled: true to disable warnings about driver names not found
         _drivers_additional (list or str): List of additional drivers to use
             during scanning
+        _of_match: Dict holding information about compatible strings
+            key: Name of struct udevice_id variable
+            value: Dict of compatible info in that variable:
+               key: Compatible string, e.g. 'rockchip,rk3288-grf'
+               value: Driver data, e,g, 'ROCKCHIP_SYSCON_GRF', or None
+        _compat_to_driver: Maps compatible strings to Driver
+        _uclass: Dict of uclass information
+            key: uclass name, e.g. 'UCLASS_I2C'
+            value: UClassDriver
+        _structs: Dict of all structs found in U-Boot:
+            key: Name of struct
+            value: Struct object
+        _phase: The phase of U-Boot that we are generating data for, e.g. 'spl'
+             or 'tpl'. None if not known
     """
-    def __init__(self, basedir, warning_disabled, drivers_additional):
+    def __init__(self, basedir, drivers_additional, phase=''):
         """Set up a new Scanner
         """
         if not basedir:
@@ -93,7 +216,23 @@
         self._drivers = {}
         self._driver_aliases = {}
         self._drivers_additional = drivers_additional or []
-        self._warning_disabled = warning_disabled
+        self._missing_drivers = set()
+        self._of_match = {}
+        self._compat_to_driver = {}
+        self._uclass = {}
+        self._structs = {}
+        self._phase = phase
+
+    def get_driver(self, name):
+        """Get a driver given its name
+
+        Args:
+            name (str): Driver name
+
+        Returns:
+            Driver: Driver or None if not found
+        """
+        return self._drivers.get(name)
 
     def get_normalized_compat_name(self, node):
         """Get a node's normalized compat name
@@ -112,7 +251,10 @@
                 In case of no match found, the return will be the same as
                 get_compat_name()
         """
-        compat_list_c = get_compat_name(node)
+        if not node.parent:
+            compat_list_c = ['root_driver']
+        else:
+            compat_list_c = get_compat_name(node)
 
         for compat_c in compat_list_c:
             if not compat_c in self._drivers.keys():
@@ -125,16 +267,329 @@
                 aliases_c.remove(compat_c)
             return compat_c, aliases_c
 
-        if not self._warning_disabled:
-            print('WARNING: the driver %s was not found in the driver list'
-                  % (compat_list_c[0]))
+        self._missing_drivers.add(compat_list_c[0])
 
         return compat_list_c[0], compat_list_c[1:]
 
+    def _parse_structs(self, fname, buff):
+        """Parse a H file to extract struct definitions contained within
+
+        This parses 'struct xx {' definitions to figure out what structs this
+        header defines.
+
+        Args:
+            buff (str): Contents of file
+            fname (str): Filename (to use when printing errors)
+        """
+        structs = {}
+
+        re_struct = re.compile('^struct ([a-z0-9_]+) {$')
+        re_asm = re.compile('../arch/[a-z0-9]+/include/asm/(.*)')
+        prefix = ''
+        for line in buff.splitlines():
+            # Handle line continuation
+            if prefix:
+                line = prefix + line
+                prefix = ''
+            if line.endswith('\\'):
+                prefix = line[:-1]
+                continue
+
+            m_struct = re_struct.match(line)
+            if m_struct:
+                name = m_struct.group(1)
+                include_dir = os.path.join(self._basedir, 'include')
+                rel_fname = os.path.relpath(fname, include_dir)
+                m_asm = re_asm.match(rel_fname)
+                if m_asm:
+                    rel_fname = 'asm/' + m_asm.group(1)
+                structs[name] = Struct(name, rel_fname)
+        self._structs.update(structs)
+
+    @classmethod
+    def _get_re_for_member(cls, member):
+        """_get_re_for_member: Get a compiled regular expression
+
+        Args:
+            member (str): Struct member name, e.g. 'priv_auto'
+
+        Returns:
+            re.Pattern: Compiled regular expression that parses:
+
+               .member = sizeof(struct fred),
+
+            and returns "fred" as group 1
+        """
+        return re.compile(r'^\s*.%s\s*=\s*sizeof\(struct\s+(.*)\),$' % member)
+
+    def _parse_uclass_driver(self, fname, buff):
+        """Parse a C file to extract uclass driver information contained within
+
+        This parses UCLASS_DRIVER() structs to obtain various pieces of useful
+        information.
+
+        It updates the following member:
+            _uclass: Dict of uclass information
+                key: uclass name, e.g. 'UCLASS_I2C'
+                value: UClassDriver
+
+        Args:
+            fname (str): Filename being parsed (used for warnings)
+            buff (str): Contents of file
+        """
+        uc_drivers = {}
+
+        # Collect the driver name and associated Driver
+        driver = None
+        re_driver = re.compile(r'^UCLASS_DRIVER\((.*)\)')
+
+        # Collect the uclass ID, e.g. 'UCLASS_SPI'
+        re_id = re.compile(r'\s*\.id\s*=\s*(UCLASS_[A-Z0-9_]+)')
+
+        # Matches the header/size information for uclass-private data
+        re_priv = self._get_re_for_member('priv_auto')
+
+        # Set up parsing for the auto members
+        re_per_device_priv = self._get_re_for_member('per_device_auto')
+        re_per_device_plat = self._get_re_for_member('per_device_plat_auto')
+        re_per_child_priv = self._get_re_for_member('per_child_auto')
+        re_per_child_plat = self._get_re_for_member('per_child_plat_auto')
+
+        prefix = ''
+        for line in buff.splitlines():
+            # Handle line continuation
+            if prefix:
+                line = prefix + line
+                prefix = ''
+            if line.endswith('\\'):
+                prefix = line[:-1]
+                continue
+
+            driver_match = re_driver.search(line)
+
+            # If we have seen UCLASS_DRIVER()...
+            if driver:
+                m_id = re_id.search(line)
+                m_priv = re_priv.match(line)
+                m_per_dev_priv = re_per_device_priv.match(line)
+                m_per_dev_plat = re_per_device_plat.match(line)
+                m_per_child_priv = re_per_child_priv.match(line)
+                m_per_child_plat = re_per_child_plat.match(line)
+                if m_id:
+                    driver.uclass_id = m_id.group(1)
+                elif m_priv:
+                    driver.priv = m_priv.group(1)
+                elif m_per_dev_priv:
+                    driver.per_dev_priv = m_per_dev_priv.group(1)
+                elif m_per_dev_plat:
+                    driver.per_dev_plat = m_per_dev_plat.group(1)
+                elif m_per_child_priv:
+                    driver.per_child_priv = m_per_child_priv.group(1)
+                elif m_per_child_plat:
+                    driver.per_child_plat = m_per_child_plat.group(1)
+                elif '};' in line:
+                    if not driver.uclass_id:
+                        raise ValueError(
+                            "%s: Cannot parse uclass ID in driver '%s'" %
+                            (fname, driver.name))
+                    uc_drivers[driver.uclass_id] = driver
+                    driver = None
+
+            elif driver_match:
+                driver_name = driver_match.group(1)
+                driver = UclassDriver(driver_name)
+
+        self._uclass.update(uc_drivers)
+
+    def _parse_driver(self, fname, buff):
+        """Parse a C file to extract driver information contained within
+
+        This parses U_BOOT_DRIVER() structs to obtain various pieces of useful
+        information.
+
+        It updates the following members:
+            _drivers - updated with new Driver records for each driver found
+                in the file
+            _of_match - updated with each compatible string found in the file
+            _compat_to_driver - Maps compatible string to Driver
+            _driver_aliases - Maps alias names to driver name
+
+        Args:
+            fname (str): Filename being parsed (used for warnings)
+            buff (str): Contents of file
+
+        Raises:
+            ValueError: Compatible variable is mentioned in .of_match in
+                U_BOOT_DRIVER() but not found in the file
+        """
+        # Dict holding information about compatible strings collected in this
+        # function so far
+        #    key: Name of struct udevice_id variable
+        #    value: Dict of compatible info in that variable:
+        #       key: Compatible string, e.g. 'rockchip,rk3288-grf'
+        #       value: Driver data, e,g, 'ROCKCHIP_SYSCON_GRF', or None
+        of_match = {}
+
+        # Dict holding driver information collected in this function so far
+        #    key: Driver name (C name as in U_BOOT_DRIVER(xxx))
+        #    value: Driver
+        drivers = {}
+
+        # Collect the driver info
+        driver = None
+        re_driver = re.compile(r'^U_BOOT_DRIVER\((.*)\)')
+
+        # Collect the uclass ID, e.g. 'UCLASS_SPI'
+        re_id = re.compile(r'\s*\.id\s*=\s*(UCLASS_[A-Z0-9_]+)')
+
+        # Collect the compatible string, e.g. 'rockchip,rk3288-grf'
+        compat = None
+        re_compat = re.compile(r'{\s*.compatible\s*=\s*"(.*)"\s*'
+                               r'(,\s*.data\s*=\s*(\S*))?\s*},')
+
+        # This is a dict of compatible strings that were found:
+        #    key: Compatible string, e.g. 'rockchip,rk3288-grf'
+        #    value: Driver data, e,g, 'ROCKCHIP_SYSCON_GRF', or None
+        compat_dict = {}
+
+        # Holds the var nane of the udevice_id list, e.g.
+        # 'rk3288_syscon_ids_noc' in
+        # static const struct udevice_id rk3288_syscon_ids_noc[] = {
+        ids_name = None
+        re_ids = re.compile(r'struct udevice_id (.*)\[\]\s*=')
+
+        # Matches the references to the udevice_id list
+        re_of_match = re.compile(
+            r'\.of_match\s*=\s*(of_match_ptr\()?([a-z0-9_]+)(\))?,')
+
+        re_phase = re.compile('^\s*DM_PHASE\((.*)\).*$')
+        re_hdr = re.compile('^\s*DM_HEADER\((.*)\).*$')
+        re_alias = re.compile(r'DM_DRIVER_ALIAS\(\s*(\w+)\s*,\s*(\w+)\s*\)')
+
+        # Matches the struct name for priv, plat
+        re_priv = self._get_re_for_member('priv_auto')
+        re_plat = self._get_re_for_member('plat_auto')
+        re_child_priv = self._get_re_for_member('per_child_auto')
+        re_child_plat = self._get_re_for_member('per_child_plat_auto')
+
+        prefix = ''
+        for line in buff.splitlines():
+            # Handle line continuation
+            if prefix:
+                line = prefix + line
+                prefix = ''
+            if line.endswith('\\'):
+                prefix = line[:-1]
+                continue
+
+            driver_match = re_driver.search(line)
+
+            # If this line contains U_BOOT_DRIVER()...
+            if driver:
+                m_id = re_id.search(line)
+                m_of_match = re_of_match.search(line)
+                m_priv = re_priv.match(line)
+                m_plat = re_plat.match(line)
+                m_cplat = re_child_plat.match(line)
+                m_cpriv = re_child_priv.match(line)
+                m_phase = re_phase.match(line)
+                m_hdr = re_hdr.match(line)
+                if m_priv:
+                    driver.priv = m_priv.group(1)
+                elif m_plat:
+                    driver.plat = m_plat.group(1)
+                elif m_cplat:
+                    driver.child_plat = m_cplat.group(1)
+                elif m_cpriv:
+                    driver.child_priv = m_cpriv.group(1)
+                elif m_id:
+                    driver.uclass_id = m_id.group(1)
+                elif m_of_match:
+                    compat = m_of_match.group(2)
+                elif m_phase:
+                    driver.phase = m_phase.group(1)
+                elif m_hdr:
+                    driver.headers.append(m_hdr.group(1))
+                elif '};' in line:
+                    is_root = driver.name == 'root_driver'
+                    if driver.uclass_id and (compat or is_root):
+                        if not is_root:
+                            if compat not in of_match:
+                                raise ValueError(
+                                    "%s: Unknown compatible var '%s' (found: %s)" %
+                                    (fname, compat, ','.join(of_match.keys())))
+                            driver.compat = of_match[compat]
+
+                            # This needs to be deterministic, since a driver may
+                            # have multiple compatible strings pointing to it.
+                            # We record the one earliest in the alphabet so it
+                            # will produce the same result on all machines.
+                            for compat_id in of_match[compat]:
+                                old = self._compat_to_driver.get(compat_id)
+                                if not old or driver.name < old.name:
+                                    self._compat_to_driver[compat_id] = driver
+                        drivers[driver.name] = driver
+                    else:
+                        # The driver does not have a uclass or compat string.
+                        # The first is required but the second is not, so just
+                        # ignore this.
+                        pass
+                    driver = None
+                    ids_name = None
+                    compat = None
+                    compat_dict = {}
+
+            elif ids_name:
+                compat_m = re_compat.search(line)
+                if compat_m:
+                    compat_dict[compat_m.group(1)] = compat_m.group(3)
+                elif '};' in line:
+                    of_match[ids_name] = compat_dict
+                    ids_name = None
+            elif driver_match:
+                driver_name = driver_match.group(1)
+                driver = Driver(driver_name, fname)
+            else:
+                ids_m = re_ids.search(line)
+                m_alias = re_alias.match(line)
+                if ids_m:
+                    ids_name = ids_m.group(1)
+                elif m_alias:
+                    self._driver_aliases[m_alias[2]] = m_alias[1]
+
+        # Make the updates based on what we found
+        for driver in drivers.values():
+            if driver.name in self._drivers:
+                orig = self._drivers[driver.name]
+                if self._phase:
+                    # If the original driver matches our phase, use it
+                    if orig.phase == self._phase:
+                        orig.dups.append(driver)
+                        continue
+
+                    # Otherwise use the new driver, which is assumed to match
+                else:
+                    # We have no way of distinguishing them
+                    driver.warn_dups = True
+                driver.dups.append(orig)
+            self._drivers[driver.name] = driver
+        self._of_match.update(of_match)
+
+    def show_warnings(self):
+        """Show any warnings that have been collected"""
+        for name in sorted(list(self._missing_drivers)):
+            print('WARNING: the driver %s was not found in the driver list'
+                  % name)
+
     def scan_driver(self, fname):
         """Scan a driver file to build a list of driver names and aliases
 
-        This procedure will populate self._drivers and self._driver_aliases
+        It updates the following members:
+            _drivers - updated with new Driver records for each driver found
+                in the file
+            _of_match - updated with each compatible string found in the file
+            _compat_to_driver - Maps compatible string to Driver
+            _driver_aliases - Maps alias names to driver name
 
         Args
             fname: Driver filename to scan
@@ -147,23 +602,35 @@
                 print("Skipping file '%s' due to unicode error" % fname)
                 return
 
-            # The following re will search for driver names declared as
-            # U_BOOT_DRIVER(driver_name)
-            drivers = re.findall(r'U_BOOT_DRIVER\((.*)\)', buff)
+            # If this file has any U_BOOT_DRIVER() declarations, process it to
+            # obtain driver information
+            if 'U_BOOT_DRIVER' in buff:
+                self._parse_driver(fname, buff)
+            if 'UCLASS_DRIVER' in buff:
+                self._parse_uclass_driver(fname, buff)
 
-            for driver in drivers:
-                self._drivers[driver] = Driver(driver)
+    def scan_header(self, fname):
+        """Scan a header file to build a list of struct definitions
 
-            # The following re will search for driver aliases declared as
-            # DM_DRIVER_ALIAS(alias, driver_name)
-            driver_aliases = re.findall(
-                r'DM_DRIVER_ALIAS\(\s*(\w+)\s*,\s*(\w+)\s*\)',
-                buff)
+        It updates the following members:
+            _structs - updated with new Struct records for each struct found
+                in the file
 
-            for alias in driver_aliases: # pragma: no cover
-                if len(alias) != 2:
-                    continue
-                self._driver_aliases[alias[1]] = alias[0]
+        Args
+            fname: header filename to scan
+        """
+        with open(fname, encoding='utf-8') as inf:
+            try:
+                buff = inf.read()
+            except UnicodeDecodeError:
+                # This seems to happen on older Python versions
+                print("Skipping file '%s' due to unicode error" % fname)
+                return
+
+            # If this file has any U_BOOT_DRIVER() declarations, process it to
+            # obtain driver information
+            if 'struct' in buff:
+                self._parse_structs(fname, buff)
 
     def scan_drivers(self):
         """Scan the driver folders to build a list of driver names and aliases
@@ -171,11 +638,17 @@
         This procedure will populate self._drivers and self._driver_aliases
         """
         for (dirpath, _, filenames) in os.walk(self._basedir):
+            rel_path = dirpath[len(self._basedir):]
+            if rel_path.startswith('/'):
+                rel_path = rel_path[1:]
+            if rel_path.startswith('build') or rel_path.startswith('.git'):
+                continue
             for fname in filenames:
-                if not fname.endswith('.c'):
-                    continue
-                self.scan_driver(dirpath + '/' + fname)
-
+                pathname = dirpath + '/' + fname
+                if fname.endswith('.c'):
+                    self.scan_driver(pathname)
+                elif fname.endswith('.h'):
+                    self.scan_header(pathname)
         for fname in self._drivers_additional:
             if not isinstance(fname, str) or len(fname) == 0:
                 continue
@@ -183,3 +656,84 @@
                 self.scan_driver(fname)
             else:
                 self.scan_driver(self._basedir + '/' + fname)
+
+        # Get the uclass for each driver
+        # TODO: Can we just get the uclass for the ones we use, e.g. in
+        # mark_used()?
+        for driver in self._drivers.values():
+            driver.uclass = self._uclass.get(driver.uclass_id)
+
+    def mark_used(self, nodes):
+        """Mark the drivers associated with a list of nodes as 'used'
+
+        This takes a list of nodes, finds the driver for each one and marks it
+        as used.
+
+        If two used drivers have the same name, issue a warning.
+
+        Args:
+            nodes (list of None): Nodes that are in use
+        """
+        # Figure out which drivers we actually use
+        for node in nodes:
+            struct_name, _ = self.get_normalized_compat_name(node)
+            driver = self._drivers.get(struct_name)
+            if driver:
+                driver.used = True
+                if driver.dups and driver.warn_dups:
+                    print("Warning: Duplicate driver name '%s' (orig=%s, dups=%s)" %
+                          (driver.name, driver.fname,
+                           ', '.join([drv.fname for drv in driver.dups])))
+
+    def add_uclass_alias(self, name, num, node):
+        """Add an alias to a uclass
+
+        Args:
+            name: Name of uclass, e.g. 'i2c'
+            num: Alias number, e.g. 2 for alias 'i2c2'
+            node: Node the alias points to, or None if None
+
+        Returns:
+            True if the node was added
+            False if the node was not added (uclass of that name not found)
+            None if the node could not be added because it was None
+        """
+        for uclass in self._uclass.values():
+            if uclass.name == name:
+                if node is None:
+                    return None
+                uclass.alias_num_to_node[int(num)] = node
+                uclass.alias_path_to_num[node.path] = int(num)
+                return True
+        return False
+
+    def assign_seq(self, node):
+        """Figure out the sequence number for a node
+
+        This looks in the node's uclass and assigns a sequence number if needed,
+        based on the aliases and other nodes in that uclass.
+
+        It updates the uclass alias_path_to_num and alias_num_to_node
+
+        Args:
+            node (Node): Node object to look up
+        """
+        if node.driver and node.seq == -1 and node.uclass:
+            uclass = node.uclass
+            num = uclass.alias_path_to_num.get(node.path)
+            if num is not None:
+                return num
+            else:
+                # Dynamically allocate the next available value after all
+                # existing ones
+                if uclass.alias_num_to_node:
+                    start = max(uclass.alias_num_to_node.keys())
+                else:
+                    start = -1
+                for seq in range(start + 1, 1000):
+                    if seq not in uclass.alias_num_to_node:
+                        break
+                uclass.alias_path_to_num[node.path] = seq
+                uclass.alias_num_to_node[seq] = node
+                return seq
+        return None
diff --git a/tools/dtoc/dtoc_test.dts b/tools/dtoc/test/dtoc_test.dts
similarity index 100%
rename from tools/dtoc/dtoc_test.dts
rename to tools/dtoc/test/dtoc_test.dts
diff --git a/tools/dtoc/dtoc_test_add_prop.dts b/tools/dtoc/test/dtoc_test_add_prop.dts
similarity index 100%
rename from tools/dtoc/dtoc_test_add_prop.dts
rename to tools/dtoc/test/dtoc_test_add_prop.dts
diff --git a/tools/dtoc/dtoc_test_addr32.dts b/tools/dtoc/test/dtoc_test_addr32.dts
similarity index 100%
rename from tools/dtoc/dtoc_test_addr32.dts
rename to tools/dtoc/test/dtoc_test_addr32.dts
diff --git a/tools/dtoc/dtoc_test_addr32_64.dts b/tools/dtoc/test/dtoc_test_addr32_64.dts
similarity index 100%
rename from tools/dtoc/dtoc_test_addr32_64.dts
rename to tools/dtoc/test/dtoc_test_addr32_64.dts
diff --git a/tools/dtoc/dtoc_test_addr64.dts b/tools/dtoc/test/dtoc_test_addr64.dts
similarity index 100%
rename from tools/dtoc/dtoc_test_addr64.dts
rename to tools/dtoc/test/dtoc_test_addr64.dts
diff --git a/tools/dtoc/dtoc_test_addr64_32.dts b/tools/dtoc/test/dtoc_test_addr64_32.dts
similarity index 100%
rename from tools/dtoc/dtoc_test_addr64_32.dts
rename to tools/dtoc/test/dtoc_test_addr64_32.dts
diff --git a/tools/dtoc/test/dtoc_test_alias_bad.dts b/tools/dtoc/test/dtoc_test_alias_bad.dts
new file mode 100644
index 0000000..d4f502a
--- /dev/null
+++ b/tools/dtoc/test/dtoc_test_alias_bad.dts
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test device tree file for dtoc
+ *
+ * Copyright 2017 Google, Inc
+ */
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		testbus2 = &bus2;
+		testfdt1 = &testfdt_1;
+		i2c4- = &i2c;
+	};
+
+	spl-test {
+		u-boot,dm-pre-reloc;
+		compatible = "sandbox,spl-test";
+		boolval;
+		intval = <1>;
+	};
+
+	i2c: i2c {
+		u-boot,dm-pre-reloc;
+		compatible = "sandbox,i2c";
+		intval = <3>;
+	};
+
+	spl-test3 {
+		u-boot,dm-pre-reloc;
+		compatible = "sandbox,spl-test";
+		stringarray = "one";
+		longbytearray = [09 0a 0b 0c 0d 0e 0f 10];
+	};
+
+	bus2: some-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "denx,u-boot-test-bus";
+		reg = <3 1>;
+		ping-expect = <4>;
+		ping-add = <4>;
+		testfdt_1: test {
+			compatible = "denx,u-boot-fdt-test", "google,another-fdt-test";
+			reg = <5>;
+			ping-expect = <5>;
+			ping-add = <5>;
+		};
+
+		test0 {
+			compatible = "google,another-fdt-test";
+		};
+	};
+};
diff --git a/tools/dtoc/test/dtoc_test_alias_bad_path.dts b/tools/dtoc/test/dtoc_test_alias_bad_path.dts
new file mode 100644
index 0000000..0beca4f
--- /dev/null
+++ b/tools/dtoc/test/dtoc_test_alias_bad_path.dts
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test device tree file for dtoc
+ *
+ * Copyright 2017 Google, Inc
+ */
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		testbus2 = &bus2;
+		testfdt1 = &testfdt_1;
+		i2c4 = "/does/not/exist";
+	};
+
+	spl-test {
+		u-boot,dm-pre-reloc;
+		compatible = "sandbox,spl-test";
+		boolval;
+		intval = <1>;
+	};
+
+	i2c: i2c {
+		u-boot,dm-pre-reloc;
+		compatible = "sandbox,i2c";
+		intval = <3>;
+	};
+
+	spl-test3 {
+		u-boot,dm-pre-reloc;
+		compatible = "sandbox,spl-test";
+		stringarray = "one";
+		longbytearray = [09 0a 0b 0c 0d 0e 0f 10];
+	};
+
+	bus2: some-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "denx,u-boot-test-bus";
+		reg = <3 1>;
+		ping-expect = <4>;
+		ping-add = <4>;
+		testfdt_1: test {
+			compatible = "denx,u-boot-fdt-test", "google,another-fdt-test";
+			reg = <5>;
+			ping-expect = <5>;
+			ping-add = <5>;
+		};
+
+		test0 {
+			compatible = "google,another-fdt-test";
+		};
+	};
+};
diff --git a/tools/dtoc/test/dtoc_test_alias_bad_uc.dts b/tools/dtoc/test/dtoc_test_alias_bad_uc.dts
new file mode 100644
index 0000000..ae64f5b
--- /dev/null
+++ b/tools/dtoc/test/dtoc_test_alias_bad_uc.dts
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test device tree file for dtoc
+ *
+ * Copyright 2017 Google, Inc
+ */
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		testbus2 = &bus2;
+		testfdt1 = &testfdt_1;
+		other1 = &testfdt_1;
+	};
+
+	spl-test {
+		u-boot,dm-pre-reloc;
+		compatible = "sandbox,spl-test";
+		boolval;
+		intval = <1>;
+	};
+
+	i2c: i2c {
+		u-boot,dm-pre-reloc;
+		compatible = "sandbox,i2c";
+		intval = <3>;
+	};
+
+	spl-test3 {
+		u-boot,dm-pre-reloc;
+		compatible = "sandbox,spl-test";
+		stringarray = "one";
+		longbytearray = [09 0a 0b 0c 0d 0e 0f 10];
+	};
+
+	bus2: some-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "denx,u-boot-test-bus";
+		reg = <3 1>;
+		ping-expect = <4>;
+		ping-add = <4>;
+		testfdt_1: test {
+			compatible = "denx,u-boot-fdt-test", "google,another-fdt-test";
+			reg = <5>;
+			ping-expect = <5>;
+			ping-add = <5>;
+		};
+
+		test0 {
+			compatible = "google,another-fdt-test";
+		};
+	};
+};
diff --git a/tools/dtoc/dtoc_test_aliases.dts b/tools/dtoc/test/dtoc_test_aliases.dts
similarity index 100%
rename from tools/dtoc/dtoc_test_aliases.dts
rename to tools/dtoc/test/dtoc_test_aliases.dts
diff --git a/tools/dtoc/dtoc_test_bad_reg.dts b/tools/dtoc/test/dtoc_test_bad_reg.dts
similarity index 100%
rename from tools/dtoc/dtoc_test_bad_reg.dts
rename to tools/dtoc/test/dtoc_test_bad_reg.dts
diff --git a/tools/dtoc/dtoc_test_bad_reg2.dts b/tools/dtoc/test/dtoc_test_bad_reg2.dts
similarity index 100%
rename from tools/dtoc/dtoc_test_bad_reg2.dts
rename to tools/dtoc/test/dtoc_test_bad_reg2.dts
diff --git a/tools/dtoc/dtoc_test_driver_alias.dts b/tools/dtoc/test/dtoc_test_driver_alias.dts
similarity index 100%
rename from tools/dtoc/dtoc_test_driver_alias.dts
rename to tools/dtoc/test/dtoc_test_driver_alias.dts
diff --git a/tools/dtoc/dtoc_test_empty.dts b/tools/dtoc/test/dtoc_test_empty.dts
similarity index 100%
rename from tools/dtoc/dtoc_test_empty.dts
rename to tools/dtoc/test/dtoc_test_empty.dts
diff --git a/tools/dtoc/test/dtoc_test_inst.dts b/tools/dtoc/test/dtoc_test_inst.dts
new file mode 100644
index 0000000..b8177fc
--- /dev/null
+++ b/tools/dtoc/test/dtoc_test_inst.dts
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test device tree file for dtoc
+ *
+ * Copyright 2017 Google, Inc
+ */
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		testbus2 = &bus2;
+		testfdt1 = &testfdt_1;
+		i2c4 = &i2c;
+	};
+
+	spl-test {
+		u-boot,dm-pre-reloc;
+		compatible = "sandbox,spl-test";
+		boolval;
+		intval = <1>;
+	};
+
+	i2c: i2c {
+		u-boot,dm-pre-reloc;
+		compatible = "sandbox,i2c";
+		intval = <3>;
+	};
+
+	spl-test3 {
+		u-boot,dm-pre-reloc;
+		compatible = "sandbox,spl-test";
+		stringarray = "one";
+		longbytearray = [09 0a 0b 0c 0d 0e 0f 10];
+	};
+
+	bus2: some-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "denx,u-boot-test-bus";
+		reg = <3 1>;
+		ping-expect = <4>;
+		ping-add = <4>;
+		testfdt_1: test {
+			compatible = "denx,u-boot-fdt-test", "google,another-fdt-test";
+			reg = <5>;
+			ping-expect = <5>;
+			ping-add = <5>;
+		};
+
+		test0 {
+			compatible = "google,another-fdt-test";
+		};
+	};
+};
diff --git a/tools/dtoc/dtoc_test_invalid_driver.dts b/tools/dtoc/test/dtoc_test_invalid_driver.dts
similarity index 100%
rename from tools/dtoc/dtoc_test_invalid_driver.dts
rename to tools/dtoc/test/dtoc_test_invalid_driver.dts
diff --git a/tools/dtoc/test/dtoc_test_noprops.dts b/tools/dtoc/test/dtoc_test_noprops.dts
new file mode 100644
index 0000000..e6fdd11
--- /dev/null
+++ b/tools/dtoc/test/dtoc_test_noprops.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test device tree file for dtoc
+ *
+ * Copyright 2017 Google, Inc
+ */
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	i2c@0 {
+		pmic@9 {
+			compatible = "sandbox,pmic";
+			u-boot,dm-pre-reloc;
+			reg = <9>;
+			low-power;
+		};
+	};
+};
diff --git a/tools/dtoc/dtoc_test_phandle.dts b/tools/dtoc/test/dtoc_test_phandle.dts
similarity index 100%
rename from tools/dtoc/dtoc_test_phandle.dts
rename to tools/dtoc/test/dtoc_test_phandle.dts
diff --git a/tools/dtoc/dtoc_test_phandle_bad.dts b/tools/dtoc/test/dtoc_test_phandle_bad.dts
similarity index 100%
rename from tools/dtoc/dtoc_test_phandle_bad.dts
rename to tools/dtoc/test/dtoc_test_phandle_bad.dts
diff --git a/tools/dtoc/dtoc_test_phandle_bad2.dts b/tools/dtoc/test/dtoc_test_phandle_bad2.dts
similarity index 100%
rename from tools/dtoc/dtoc_test_phandle_bad2.dts
rename to tools/dtoc/test/dtoc_test_phandle_bad2.dts
diff --git a/tools/dtoc/dtoc_test_phandle_cd_gpios.dts b/tools/dtoc/test/dtoc_test_phandle_cd_gpios.dts
similarity index 100%
rename from tools/dtoc/dtoc_test_phandle_cd_gpios.dts
rename to tools/dtoc/test/dtoc_test_phandle_cd_gpios.dts
diff --git a/tools/dtoc/dtoc_test_phandle_reorder.dts b/tools/dtoc/test/dtoc_test_phandle_reorder.dts
similarity index 100%
rename from tools/dtoc/dtoc_test_phandle_reorder.dts
rename to tools/dtoc/test/dtoc_test_phandle_reorder.dts
diff --git a/tools/dtoc/dtoc_test_phandle_single.dts b/tools/dtoc/test/dtoc_test_phandle_single.dts
similarity index 100%
rename from tools/dtoc/dtoc_test_phandle_single.dts
rename to tools/dtoc/test/dtoc_test_phandle_single.dts
diff --git a/tools/dtoc/test/dtoc_test_scan_drivers.cxx b/tools/dtoc/test/dtoc_test_scan_drivers.cxx
new file mode 100644
index 0000000..f370b89
--- /dev/null
+++ b/tools/dtoc/test/dtoc_test_scan_drivers.cxx
@@ -0,0 +1,5 @@
+/* Aliases must be in driver files */
+U_BOOT_DRIVER(sandbox_gpio) {
+};
+
+DM_DRIVER_ALIAS(sandbox_gpio, sandbox_gpio_alias2)
diff --git a/tools/dtoc/dtoc_test_simple.dts b/tools/dtoc/test/dtoc_test_simple.dts
similarity index 91%
rename from tools/dtoc/dtoc_test_simple.dts
rename to tools/dtoc/test/dtoc_test_simple.dts
index 1c87b89..b5c1274 100644
--- a/tools/dtoc/dtoc_test_simple.dts
+++ b/tools/dtoc/test/dtoc_test_simple.dts
@@ -45,15 +45,19 @@
 	};
 
 	i2c@0 {
-		compatible = "sandbox,i2c-test";
+		compatible = "sandbox,i2c";
 		u-boot,dm-pre-reloc;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		pmic@9 {
-			compatible = "sandbox,pmic-test";
+			compatible = "sandbox,pmic";
 			u-boot,dm-pre-reloc;
 			reg = <9>;
 			low-power;
 		};
 	};
+
+	orig-node {
+		orig = <1 23 4>;
+	};
 };
diff --git a/tools/dtoc/test/dtoc_test_single_reg.dts b/tools/dtoc/test/dtoc_test_single_reg.dts
new file mode 100644
index 0000000..804b678
--- /dev/null
+++ b/tools/dtoc/test/dtoc_test_single_reg.dts
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test device tree file for dtoc
+ *
+ * Copyright 2017 Google, Inc
+ */
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	i2c@0 {
+		compatible = "sandbox,i2c";
+		u-boot,dm-pre-reloc;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pmic@9 {
+			compatible = "sandbox,pmic";
+			u-boot,dm-pre-reloc;
+			reg = <9>;
+			low-power;
+
+			gpio {
+				compatible = "sandbox,gpio";
+			};
+		};
+	};
+};
diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py
index d961d67..a05e3d9 100755
--- a/tools/dtoc/test_dtoc.py
+++ b/tools/dtoc/test_dtoc.py
@@ -10,16 +10,19 @@
 """
 
 import collections
+import copy
 import glob
 import os
 import struct
 import unittest
 
+from dtb_platdata import Ftype
 from dtb_platdata import get_value
 from dtb_platdata import tab_to
 from dtoc import dtb_platdata
 from dtoc import fdt
 from dtoc import fdt_util
+from dtoc import src_scan
 from dtoc.src_scan import conv_name_to_c
 from dtoc.src_scan import get_compat_name
 from patman import test_util
@@ -38,13 +41,23 @@
 #include <stdbool.h>
 #include <linux/libfdt.h>'''
 
-C_HEADER = '''/*
+DECL_HEADER = '''/*
+ * DO NOT MODIFY
+ *
+ * Declares externs for all device/uclass instances.
+ * This was generated by dtoc from a .dtb (device tree binary) file.
+ */
+'''
+
+C_HEADER_PRE = '''/*
  * DO NOT MODIFY
  *
  * Declares the U_BOOT_DRIVER() records and platform data.
  * This was generated by dtoc from a .dtb (device tree binary) file.
  */
+'''
 
+C_HEADER = C_HEADER_PRE + '''
 /* Allow use of U_BOOT_DRVINFO() in this file */
 #define DT_PLAT_C
 
@@ -53,6 +66,21 @@
 #include <dt-structs.h>
 '''
 
+UCLASS_HEADER_COMMON = '''/*
+ * DO NOT MODIFY
+ *
+ * Declares the uclass instances (struct uclass).
+ * This was generated by dtoc from a .dtb (device tree binary) file.
+ */
+'''
+
+UCLASS_HEADER = UCLASS_HEADER_COMMON + '''
+/* This file is not used: --instantiate was not enabled */
+'''
+
+# Scanner saved from a previous run of the tests (to speed things up)
+saved_scan = None
+
 # This is a test so is allowed to access private things in the module it is
 # testing
 # pylint: disable=W0212
@@ -67,10 +95,23 @@
     Returns:
         str: Filename of compiled file in output directory
     """
-    return fdt_util.EnsureCompiled(os.path.join(OUR_PATH, dts_fname),
+    return fdt_util.EnsureCompiled(os.path.join(OUR_PATH, 'test', dts_fname),
                                    capture_stderr=capture_stderr)
 
 
+def setup():
+    global saved_scan
+
+    # Disable warnings so that calls to get_normalized_compat_name() will not
+    # output things.
+    saved_scan = src_scan.Scanner(None, False)
+    saved_scan.scan_drivers()
+
+def copy_scan():
+    """Get a copy of saved_scan so that each test can start clean"""
+    return copy.deepcopy(saved_scan)
+
+
 class TestDtoc(unittest.TestCase):
     """Tests for dtoc"""
     @classmethod
@@ -112,15 +153,22 @@
         self.assertEqual(expected, actual)
 
     @staticmethod
-    def run_test(args, dtb_file, output):
+    def run_test(args, dtb_file, output, instantiate=False):
         """Run a test using dtoc
 
         Args:
             args (list of str): List of arguments for dtoc
             dtb_file (str): Filename of .dtb file
             output (str): Filename of output file
+
+        Returns:
+            DtbPlatdata object
         """
-        dtb_platdata.run_steps(args, dtb_file, False, output, [], True)
+        # Make a copy of the 'scan' object, since it includes uclasses and
+        # drivers, which get updated during execution.
+        return dtb_platdata.run_steps(
+            args, dtb_file, False, output, [], None, instantiate,
+            warning_disabled=True, scan=copy_scan())
 
     def test_name(self):
         """Test conversion of device tree names to C identifiers"""
@@ -175,7 +223,10 @@
         """Test output from a device tree file with no nodes"""
         dtb_file = get_dtb_file('dtoc_test_empty.dts')
         output = tools.GetOutputFilename('output')
-        self.run_test(['struct'], dtb_file, output)
+
+        # Run this one without saved_scan to complete test coverage
+        dtb_platdata.run_steps(['struct'], dtb_file, False, output, [], None,
+                               False)
         with open(output) as infile:
             lines = infile.read().splitlines()
         self.assertEqual(HEADER.splitlines(), lines)
@@ -185,12 +236,64 @@
             lines = infile.read().splitlines()
         self.assertEqual(C_HEADER.splitlines() + [''], lines)
 
+    decl_text = DECL_HEADER + '''
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+
+/* driver declarations - these allow DM_DRIVER_GET() to be used */
+extern U_BOOT_DRIVER(sandbox_i2c);
+extern U_BOOT_DRIVER(sandbox_pmic);
+extern U_BOOT_DRIVER(sandbox_spl_test);
+extern U_BOOT_DRIVER(sandbox_spl_test);
+extern U_BOOT_DRIVER(sandbox_spl_test);
+
+/* uclass driver declarations - needed for DM_UCLASS_DRIVER_REF() */
+extern UCLASS_DRIVER(i2c);
+extern UCLASS_DRIVER(misc);
+extern UCLASS_DRIVER(pmic);
+'''
+    decl_text_inst = DECL_HEADER + '''
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+
+/* driver declarations - these allow DM_DRIVER_GET() to be used */
+extern U_BOOT_DRIVER(sandbox_i2c);
+extern U_BOOT_DRIVER(root_driver);
+extern U_BOOT_DRIVER(denx_u_boot_test_bus);
+extern U_BOOT_DRIVER(sandbox_spl_test);
+extern U_BOOT_DRIVER(sandbox_spl_test);
+extern U_BOOT_DRIVER(denx_u_boot_fdt_test);
+extern U_BOOT_DRIVER(denx_u_boot_fdt_test);
+
+/* device declarations - these allow DM_DEVICE_REF() to be used */
+extern DM_DEVICE_INST(i2c);
+extern DM_DEVICE_INST(root);
+extern DM_DEVICE_INST(some_bus);
+extern DM_DEVICE_INST(spl_test);
+extern DM_DEVICE_INST(spl_test3);
+extern DM_DEVICE_INST(test);
+extern DM_DEVICE_INST(test0);
+
+/* uclass driver declarations - needed for DM_UCLASS_DRIVER_REF() */
+extern UCLASS_DRIVER(i2c);
+extern UCLASS_DRIVER(misc);
+extern UCLASS_DRIVER(root);
+extern UCLASS_DRIVER(testbus);
+extern UCLASS_DRIVER(testfdt);
+
+/* uclass declarations - needed for DM_UCLASS_REF() */
+extern DM_UCLASS_INST(i2c);
+extern DM_UCLASS_INST(misc);
+extern DM_UCLASS_INST(root);
+extern DM_UCLASS_INST(testbus);
+extern DM_UCLASS_INST(testfdt);
+'''
     struct_text = HEADER + '''
-struct dtd_sandbox_i2c_test {
+struct dtd_sandbox_i2c {
 };
-struct dtd_sandbox_pmic_test {
+struct dtd_sandbox_pmic {
 \tbool\t\tlow_power;
-\tfdt64_t\t\treg[2];
+\tfdt32_t\t\treg[1];
 };
 struct dtd_sandbox_spl_test {
 \tconst char *	acpi_name;
@@ -205,31 +308,52 @@
 \tconst char *\tstringval;
 };
 '''
-
     platdata_text = C_HEADER + '''
-/* Node /i2c@0 index 0 */
-static struct dtd_sandbox_i2c_test dtv_i2c_at_0 = {
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: i2c_at_0             sandbox_i2c
+ *   1: pmic_at_9            sandbox_pmic
+ *   2: spl_test             sandbox_spl_test
+ *   3: spl_test2            sandbox_spl_test
+ *   4: spl_test3            sandbox_spl_test
+ * ---  -------------------- --------------------
+ */
+
+/*
+ * Node /i2c@0 index 0
+ * driver sandbox_i2c parent None
+ */
+static struct dtd_sandbox_i2c dtv_i2c_at_0 = {
 };
 U_BOOT_DRVINFO(i2c_at_0) = {
-\t.name\t\t= "sandbox_i2c_test",
-\t.plat\t= &dtv_i2c_at_0,
+\t.name\t\t= "sandbox_i2c",
+\t.plat\t\t= &dtv_i2c_at_0,
 \t.plat_size\t= sizeof(dtv_i2c_at_0),
 \t.parent_idx\t= -1,
 };
 
-/* Node /i2c@0/pmic@9 index 1 */
-static struct dtd_sandbox_pmic_test dtv_pmic_at_9 = {
+/*
+ * Node /i2c@0/pmic@9 index 1
+ * driver sandbox_pmic parent sandbox_i2c
+ */
+static struct dtd_sandbox_pmic dtv_pmic_at_9 = {
 \t.low_power\t\t= true,
-\t.reg\t\t\t= {0x9, 0x0},
+\t.reg\t\t\t= {0x9},
 };
 U_BOOT_DRVINFO(pmic_at_9) = {
-\t.name\t\t= "sandbox_pmic_test",
-\t.plat\t= &dtv_pmic_at_9,
+\t.name\t\t= "sandbox_pmic",
+\t.plat\t\t= &dtv_pmic_at_9,
 \t.plat_size\t= sizeof(dtv_pmic_at_9),
 \t.parent_idx\t= 0,
 };
 
-/* Node /spl-test index 2 */
+/*
+ * Node /spl-test index 2
+ * driver sandbox_spl_test parent None
+ */
 static struct dtd_sandbox_spl_test dtv_spl_test = {
 \t.boolval\t\t= true,
 \t.bytearray\t\t= {0x6, 0x0, 0x0},
@@ -244,12 +368,15 @@
 };
 U_BOOT_DRVINFO(spl_test) = {
 \t.name\t\t= "sandbox_spl_test",
-\t.plat\t= &dtv_spl_test,
+\t.plat\t\t= &dtv_spl_test,
 \t.plat_size\t= sizeof(dtv_spl_test),
 \t.parent_idx\t= -1,
 };
 
-/* Node /spl-test2 index 3 */
+/*
+ * Node /spl-test2 index 3
+ * driver sandbox_spl_test parent None
+ */
 static struct dtd_sandbox_spl_test dtv_spl_test2 = {
 \t.acpi_name\t\t= "\\\\_SB.GPO0",
 \t.bytearray\t\t= {0x1, 0x23, 0x34},
@@ -263,12 +390,15 @@
 };
 U_BOOT_DRVINFO(spl_test2) = {
 \t.name\t\t= "sandbox_spl_test",
-\t.plat\t= &dtv_spl_test2,
+\t.plat\t\t= &dtv_spl_test2,
 \t.plat_size\t= sizeof(dtv_spl_test2),
 \t.parent_idx\t= -1,
 };
 
-/* Node /spl-test3 index 4 */
+/*
+ * Node /spl-test3 index 4
+ * driver sandbox_spl_test parent None
+ */
 static struct dtd_sandbox_spl_test dtv_spl_test3 = {
 \t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,
 \t\t0x0},
@@ -276,12 +406,406 @@
 };
 U_BOOT_DRVINFO(spl_test3) = {
 \t.name\t\t= "sandbox_spl_test",
-\t.plat\t= &dtv_spl_test3,
+\t.plat\t\t= &dtv_spl_test3,
 \t.plat_size\t= sizeof(dtv_spl_test3),
 \t.parent_idx\t= -1,
 };
 
 '''
+    uclass_text = UCLASS_HEADER
+    uclass_text_inst = '''
+
+#include <common.h>
+#include <dm.h>
+#include <dt-structs.h>
+
+/*
+ * uclass declarations, ordered by 'struct uclass' linker_list idx:
+ *   0: i2c
+ *   1: misc
+ *   2: root
+ *   3: testbus
+ *   4: testfdt
+ *
+ * Sequence numbers allocated in each uclass:
+ * i2c: UCLASS_I2C
+ *    4: /i2c
+ * misc: UCLASS_MISC
+ *    0: /spl-test
+ *    1: /spl-test3
+ * root: UCLASS_ROOT
+ *    0: /
+ * testbus: UCLASS_TEST_BUS
+ *    2: /some-bus
+ * testfdt: UCLASS_TEST_FDT
+ *    1: /some-bus/test
+ *    2: /some-bus/test0
+ */
+
+struct list_head uclass_head = {
+	.prev = &DM_UCLASS_REF(testfdt)->sibling_node,
+	.next = &DM_UCLASS_REF(i2c)->sibling_node,
+};
+
+DM_UCLASS_INST(i2c) = {
+	.uc_drv		= DM_UCLASS_DRIVER_REF(i2c),
+	.sibling_node	= {
+		.prev = &uclass_head,
+		.next = &DM_UCLASS_REF(misc)->sibling_node,
+	},
+	.dev_head	= {
+		.prev = &DM_DEVICE_REF(i2c)->uclass_node,
+		.next = &DM_DEVICE_REF(i2c)->uclass_node,
+	},
+};
+
+DM_UCLASS_INST(misc) = {
+	.uc_drv		= DM_UCLASS_DRIVER_REF(misc),
+	.sibling_node	= {
+		.prev = &DM_UCLASS_REF(i2c)->sibling_node,
+		.next = &DM_UCLASS_REF(root)->sibling_node,
+	},
+	.dev_head	= {
+		.prev = &DM_DEVICE_REF(spl_test3)->uclass_node,
+		.next = &DM_DEVICE_REF(spl_test)->uclass_node,
+	},
+};
+
+DM_UCLASS_INST(root) = {
+	.uc_drv		= DM_UCLASS_DRIVER_REF(root),
+	.sibling_node	= {
+		.prev = &DM_UCLASS_REF(misc)->sibling_node,
+		.next = &DM_UCLASS_REF(testbus)->sibling_node,
+	},
+	.dev_head	= {
+		.prev = &DM_DEVICE_REF(root)->uclass_node,
+		.next = &DM_DEVICE_REF(root)->uclass_node,
+	},
+};
+
+DM_UCLASS_INST(testbus) = {
+	.uc_drv		= DM_UCLASS_DRIVER_REF(testbus),
+	.sibling_node	= {
+		.prev = &DM_UCLASS_REF(root)->sibling_node,
+		.next = &DM_UCLASS_REF(testfdt)->sibling_node,
+	},
+	.dev_head	= {
+		.prev = &DM_DEVICE_REF(some_bus)->uclass_node,
+		.next = &DM_DEVICE_REF(some_bus)->uclass_node,
+	},
+};
+
+#include <dm/test.h>
+u8 _testfdt_priv_[sizeof(struct dm_test_uc_priv)]
+	__attribute__ ((section (".priv_data")));
+DM_UCLASS_INST(testfdt) = {
+	.priv_		= _testfdt_priv_,
+	.uc_drv		= DM_UCLASS_DRIVER_REF(testfdt),
+	.sibling_node	= {
+		.prev = &DM_UCLASS_REF(testbus)->sibling_node,
+		.next = &uclass_head,
+	},
+	.dev_head	= {
+		.prev = &DM_DEVICE_REF(test0)->uclass_node,
+		.next = &DM_DEVICE_REF(test)->uclass_node,
+	},
+};
+
+'''
+    device_text = '''/*
+ * DO NOT MODIFY
+ *
+ * Declares the DM_DEVICE_INST() records.
+ * This was generated by dtoc from a .dtb (device tree binary) file.
+ */
+
+/* This file is not used: --instantiate was not enabled */
+'''
+    device_text_inst = '''/*
+ * DO NOT MODIFY
+ *
+ * Declares the DM_DEVICE_INST() records.
+ * This was generated by dtoc from a .dtb (device tree binary) file.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dt-structs.h>
+
+/*
+ * udevice declarations, ordered by 'struct udevice' linker_list position:
+ *
+ * idx  udevice              driver
+ * ---  -------------------- --------------------
+ *   0: i2c                  sandbox_i2c
+ *   1: root                 root_driver
+ *   2: some_bus             denx_u_boot_test_bus
+ *   3: spl_test             sandbox_spl_test
+ *   4: spl_test3            sandbox_spl_test
+ *   5: test                 denx_u_boot_fdt_test
+ *   6: test0                denx_u_boot_fdt_test
+ * ---  -------------------- --------------------
+ */
+
+/*
+ * Node /i2c index 0
+ * driver sandbox_i2c parent root_driver
+*/
+static struct dtd_sandbox_i2c dtv_i2c = {
+\t.intval\t\t\t= 0x3,
+};
+
+#include <asm/i2c.h>
+u8 _sandbox_i2c_priv_i2c[sizeof(struct sandbox_i2c_priv)]
+\t__attribute__ ((section (".priv_data")));
+#include <i2c.h>
+u8 _sandbox_i2c_uc_priv_i2c[sizeof(struct dm_i2c_bus)]
+\t__attribute__ ((section (".priv_data")));
+
+DM_DEVICE_INST(i2c) = {
+\t.driver\t\t= DM_DRIVER_REF(sandbox_i2c),
+\t.name\t\t= "sandbox_i2c",
+\t.plat_\t\t= &dtv_i2c,
+\t.priv_\t\t= _sandbox_i2c_priv_i2c,
+\t.uclass\t\t= DM_UCLASS_REF(i2c),
+\t.uclass_priv_ = _sandbox_i2c_uc_priv_i2c,
+\t.uclass_node\t= {
+\t\t.prev = &DM_UCLASS_REF(i2c)->dev_head,
+\t\t.next = &DM_UCLASS_REF(i2c)->dev_head,
+\t},
+\t.child_head\t= {
+\t\t.prev = &DM_DEVICE_REF(i2c)->child_head,
+\t\t.next = &DM_DEVICE_REF(i2c)->child_head,
+\t},
+\t.sibling_node\t= {
+\t\t.prev = &DM_DEVICE_REF(root)->child_head,
+\t\t.next = &DM_DEVICE_REF(some_bus)->sibling_node,
+\t},
+\t.seq_ = 4,
+};
+
+/*
+ * Node / index 1
+ * driver root_driver parent None
+*/
+static struct dtd_root_driver dtv_root = {
+};
+
+DM_DEVICE_INST(root) = {
+\t.driver\t\t= DM_DRIVER_REF(root_driver),
+\t.name\t\t= "root_driver",
+\t.plat_\t\t= &dtv_root,
+\t.uclass\t\t= DM_UCLASS_REF(root),
+\t.uclass_node\t= {
+\t\t.prev = &DM_UCLASS_REF(root)->dev_head,
+\t\t.next = &DM_UCLASS_REF(root)->dev_head,
+\t},
+\t.child_head\t= {
+\t\t.prev = &DM_DEVICE_REF(spl_test3)->sibling_node,
+\t\t.next = &DM_DEVICE_REF(i2c)->sibling_node,
+\t},
+\t.seq_ = 0,
+};
+
+/*
+ * Node /some-bus index 2
+ * driver denx_u_boot_test_bus parent root_driver
+*/
+
+#include <dm/test.h>
+struct dm_test_pdata __attribute__ ((section (".priv_data")))
+\t_denx_u_boot_test_bus_plat_some_bus = {
+\t.dtplat = {
+\t\t.ping_add\t\t= 0x4,
+\t\t.ping_expect\t\t= 0x4,
+\t\t.reg\t\t\t= {0x3, 0x1},
+\t},
+};
+#include <dm/test.h>
+u8 _denx_u_boot_test_bus_priv_some_bus[sizeof(struct dm_test_priv)]
+\t__attribute__ ((section (".priv_data")));
+#include <dm/test.h>
+u8 _denx_u_boot_test_bus_ucplat_some_bus[sizeof(struct dm_test_uclass_priv)]
+\t__attribute__ ((section (".priv_data")));
+#include <test.h>
+
+DM_DEVICE_INST(some_bus) = {
+\t.driver\t\t= DM_DRIVER_REF(denx_u_boot_test_bus),
+\t.name\t\t= "denx_u_boot_test_bus",
+\t.plat_\t\t= &_denx_u_boot_test_bus_plat_some_bus,
+\t.uclass_plat_\t= _denx_u_boot_test_bus_ucplat_some_bus,
+\t.driver_data\t= DM_TEST_TYPE_FIRST,
+\t.priv_\t\t= _denx_u_boot_test_bus_priv_some_bus,
+\t.uclass\t\t= DM_UCLASS_REF(testbus),
+\t.uclass_node\t= {
+\t\t.prev = &DM_UCLASS_REF(testbus)->dev_head,
+\t\t.next = &DM_UCLASS_REF(testbus)->dev_head,
+\t},
+\t.child_head\t= {
+\t\t.prev = &DM_DEVICE_REF(test0)->sibling_node,
+\t\t.next = &DM_DEVICE_REF(test)->sibling_node,
+\t},
+\t.sibling_node\t= {
+\t\t.prev = &DM_DEVICE_REF(i2c)->sibling_node,
+\t\t.next = &DM_DEVICE_REF(spl_test)->sibling_node,
+\t},
+\t.seq_ = 2,
+};
+
+/*
+ * Node /spl-test index 3
+ * driver sandbox_spl_test parent root_driver
+*/
+static struct dtd_sandbox_spl_test dtv_spl_test = {
+\t.boolval\t\t= true,
+\t.intval\t\t\t= 0x1,
+};
+
+DM_DEVICE_INST(spl_test) = {
+\t.driver\t\t= DM_DRIVER_REF(sandbox_spl_test),
+\t.name\t\t= "sandbox_spl_test",
+\t.plat_\t\t= &dtv_spl_test,
+\t.uclass\t\t= DM_UCLASS_REF(misc),
+\t.uclass_node\t= {
+\t\t.prev = &DM_UCLASS_REF(misc)->dev_head,
+\t\t.next = &DM_DEVICE_REF(spl_test3)->uclass_node,
+\t},
+\t.child_head\t= {
+\t\t.prev = &DM_DEVICE_REF(spl_test)->child_head,
+\t\t.next = &DM_DEVICE_REF(spl_test)->child_head,
+\t},
+\t.sibling_node\t= {
+\t\t.prev = &DM_DEVICE_REF(some_bus)->sibling_node,
+\t\t.next = &DM_DEVICE_REF(spl_test3)->sibling_node,
+\t},
+\t.seq_ = 0,
+};
+
+/*
+ * Node /spl-test3 index 4
+ * driver sandbox_spl_test parent root_driver
+*/
+static struct dtd_sandbox_spl_test dtv_spl_test3 = {
+\t.longbytearray\t\t= {0x90a0b0c, 0xd0e0f10},
+\t.stringarray\t\t= "one",
+};
+
+DM_DEVICE_INST(spl_test3) = {
+\t.driver\t\t= DM_DRIVER_REF(sandbox_spl_test),
+\t.name\t\t= "sandbox_spl_test",
+\t.plat_\t\t= &dtv_spl_test3,
+\t.uclass\t\t= DM_UCLASS_REF(misc),
+\t.uclass_node\t= {
+\t\t.prev = &DM_DEVICE_REF(spl_test)->uclass_node,
+\t\t.next = &DM_UCLASS_REF(misc)->dev_head,
+\t},
+\t.child_head\t= {
+\t\t.prev = &DM_DEVICE_REF(spl_test3)->child_head,
+\t\t.next = &DM_DEVICE_REF(spl_test3)->child_head,
+\t},
+\t.sibling_node\t= {
+\t\t.prev = &DM_DEVICE_REF(spl_test)->sibling_node,
+\t\t.next = &DM_DEVICE_REF(root)->child_head,
+\t},
+\t.seq_ = 1,
+};
+
+/*
+ * Node /some-bus/test index 5
+ * driver denx_u_boot_fdt_test parent denx_u_boot_test_bus
+*/
+
+#include <dm/test.h>
+struct dm_test_pdata __attribute__ ((section (".priv_data")))
+\t_denx_u_boot_fdt_test_plat_test = {
+\t.dtplat = {
+\t\t.ping_add\t\t= 0x5,
+\t\t.ping_expect\t\t= 0x5,
+\t\t.reg\t\t\t= {0x5},
+\t},
+};
+#include <dm/test.h>
+u8 _denx_u_boot_fdt_test_priv_test[sizeof(struct dm_test_priv)]
+\t__attribute__ ((section (".priv_data")));
+#include <dm/test.h>
+u8 _denx_u_boot_fdt_test_parent_plat_test[sizeof(struct dm_test_parent_plat)]
+\t__attribute__ ((section (".priv_data")));
+#include <dm/test.h>
+u8 _denx_u_boot_fdt_test_parent_priv_test[sizeof(struct dm_test_parent_data)]
+\t__attribute__ ((section (".priv_data")));
+
+DM_DEVICE_INST(test) = {
+\t.driver\t\t= DM_DRIVER_REF(denx_u_boot_fdt_test),
+\t.name\t\t= "denx_u_boot_fdt_test",
+\t.plat_\t\t= &_denx_u_boot_fdt_test_plat_test,
+\t.parent_plat_\t= _denx_u_boot_fdt_test_parent_plat_test,
+\t.driver_data\t= DM_TEST_TYPE_FIRST,
+\t.parent\t\t= DM_DEVICE_REF(some_bus),
+\t.priv_\t\t= _denx_u_boot_fdt_test_priv_test,
+\t.uclass\t\t= DM_UCLASS_REF(testfdt),
+\t.parent_priv_\t= _denx_u_boot_fdt_test_parent_priv_test,
+\t.uclass_node\t= {
+\t\t.prev = &DM_UCLASS_REF(testfdt)->dev_head,
+\t\t.next = &DM_DEVICE_REF(test0)->uclass_node,
+\t},
+\t.child_head\t= {
+\t\t.prev = &DM_DEVICE_REF(test)->child_head,
+\t\t.next = &DM_DEVICE_REF(test)->child_head,
+\t},
+\t.sibling_node\t= {
+\t\t.prev = &DM_DEVICE_REF(some_bus)->child_head,
+\t\t.next = &DM_DEVICE_REF(test0)->sibling_node,
+\t},
+\t.seq_ = 1,
+};
+
+/*
+ * Node /some-bus/test0 index 6
+ * driver denx_u_boot_fdt_test parent denx_u_boot_test_bus
+*/
+
+#include <dm/test.h>
+struct dm_test_pdata __attribute__ ((section (".priv_data")))
+\t_denx_u_boot_fdt_test_plat_test0 = {
+\t.dtplat = {
+\t},
+};
+#include <dm/test.h>
+u8 _denx_u_boot_fdt_test_priv_test0[sizeof(struct dm_test_priv)]
+\t__attribute__ ((section (".priv_data")));
+#include <dm/test.h>
+u8 _denx_u_boot_fdt_test_parent_plat_test0[sizeof(struct dm_test_parent_plat)]
+\t__attribute__ ((section (".priv_data")));
+#include <dm/test.h>
+u8 _denx_u_boot_fdt_test_parent_priv_test0[sizeof(struct dm_test_parent_data)]
+\t__attribute__ ((section (".priv_data")));
+
+DM_DEVICE_INST(test0) = {
+\t.driver\t\t= DM_DRIVER_REF(denx_u_boot_fdt_test),
+\t.name\t\t= "denx_u_boot_fdt_test",
+\t.plat_\t\t= &_denx_u_boot_fdt_test_plat_test0,
+\t.parent_plat_\t= _denx_u_boot_fdt_test_parent_plat_test0,
+\t.driver_data\t= DM_TEST_TYPE_SECOND,
+\t.parent\t\t= DM_DEVICE_REF(some_bus),
+\t.priv_\t\t= _denx_u_boot_fdt_test_priv_test0,
+\t.uclass\t\t= DM_UCLASS_REF(testfdt),
+\t.parent_priv_\t= _denx_u_boot_fdt_test_parent_priv_test0,
+\t.uclass_node\t= {
+\t\t.prev = &DM_DEVICE_REF(test)->uclass_node,
+\t\t.next = &DM_UCLASS_REF(testfdt)->dev_head,
+\t},
+\t.child_head\t= {
+\t\t.prev = &DM_DEVICE_REF(test0)->child_head,
+\t\t.next = &DM_DEVICE_REF(test0)->child_head,
+\t},
+\t.sibling_node\t= {
+\t\t.prev = &DM_DEVICE_REF(test)->sibling_node,
+\t\t.next = &DM_DEVICE_REF(some_bus)->child_head,
+\t},
+\t.seq_ = 2,
+};
+
+'''
 
     def test_simple(self):
         """Test output from some simple nodes with various types of data"""
@@ -299,10 +823,18 @@
 
         self._check_strings(self.platdata_text, data)
 
+        self.run_test(['decl'], dtb_file, output)
+        with open(output) as infile:
+            data = infile.read()
+
+        self._check_strings(self.decl_text, data)
+
         # Try the 'all' command
         self.run_test(['all'], dtb_file, output)
         data = tools.ReadFile(output, binary=False)
-        self._check_strings(self.platdata_text + self.struct_text, data)
+        self._check_strings(
+            self.decl_text + self.device_text + self.platdata_text +
+            self.struct_text + self.uclass_text, data)
 
     def test_driver_alias(self):
         """Test output from a device tree file with a driver alias"""
@@ -323,7 +855,19 @@
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
-/* Node /gpios@0 index 0 */
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: gpios_at_0           sandbox_gpio
+ * ---  -------------------- --------------------
+ */
+
+/*
+ * Node /gpios@0 index 0
+ * driver sandbox_gpio parent None
+ */
 static struct dtd_sandbox_gpio dtv_gpios_at_0 = {
 \t.gpio_bank_name\t\t= "a",
 \t.gpio_controller\t= true,
@@ -331,7 +875,7 @@
 };
 U_BOOT_DRVINFO(gpios_at_0) = {
 \t.name\t\t= "sandbox_gpio",
-\t.plat\t= &dtv_gpios_at_0,
+\t.plat\t\t= &dtv_gpios_at_0,
 \t.plat_size\t= sizeof(dtv_gpios_at_0),
 \t.parent_idx\t= -1,
 };
@@ -343,7 +887,9 @@
         dtb_file = get_dtb_file('dtoc_test_invalid_driver.dts')
         output = tools.GetOutputFilename('output')
         with test_util.capture_sys_output() as _:
-            dtb_platdata.run_steps(['struct'], dtb_file, False, output, [])
+            dtb_platdata.run_steps(
+                ['struct'], dtb_file, False, output, [], None, False,
+                scan=copy_scan())
         with open(output) as infile:
             data = infile.read()
         self._check_strings(HEADER + '''
@@ -352,16 +898,27 @@
 ''', data)
 
         with test_util.capture_sys_output() as _:
-            dtb_platdata.run_steps(['platdata'], dtb_file, False, output, [])
+            dtb_platdata.run_steps(
+                ['platdata'], dtb_file, False, output, [], None, False,
+                scan=copy_scan())
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: spl_test             invalid
+ * ---  -------------------- --------------------
+ */
+
 /* Node /spl-test index 0 */
 static struct dtd_invalid dtv_spl_test = {
 };
 U_BOOT_DRVINFO(spl_test) = {
 \t.name\t\t= "invalid",
-\t.plat\t= &dtv_spl_test,
+\t.plat\t\t= &dtv_spl_test,
 \t.plat_size\t= sizeof(dtv_spl_test),
 \t.parent_idx\t= -1,
 };
@@ -388,13 +945,26 @@
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: phandle2_target      target
+ *   1: phandle3_target      target
+ *   2: phandle_source       source
+ *   3: phandle_source2      source
+ *   4: phandle_target       target
+ * ---  -------------------- --------------------
+ */
+
 /* Node /phandle2-target index 0 */
 static struct dtd_target dtv_phandle2_target = {
 \t.intval\t\t\t= 0x1,
 };
 U_BOOT_DRVINFO(phandle2_target) = {
 \t.name\t\t= "target",
-\t.plat\t= &dtv_phandle2_target,
+\t.plat\t\t= &dtv_phandle2_target,
 \t.plat_size\t= sizeof(dtv_phandle2_target),
 \t.parent_idx\t= -1,
 };
@@ -405,7 +975,7 @@
 };
 U_BOOT_DRVINFO(phandle3_target) = {
 \t.name\t\t= "target",
-\t.plat\t= &dtv_phandle3_target,
+\t.plat\t\t= &dtv_phandle3_target,
 \t.plat_size\t= sizeof(dtv_phandle3_target),
 \t.parent_idx\t= -1,
 };
@@ -420,7 +990,7 @@
 };
 U_BOOT_DRVINFO(phandle_source) = {
 \t.name\t\t= "source",
-\t.plat\t= &dtv_phandle_source,
+\t.plat\t\t= &dtv_phandle_source,
 \t.plat_size\t= sizeof(dtv_phandle_source),
 \t.parent_idx\t= -1,
 };
@@ -432,7 +1002,7 @@
 };
 U_BOOT_DRVINFO(phandle_source2) = {
 \t.name\t\t= "source",
-\t.plat\t= &dtv_phandle_source2,
+\t.plat\t\t= &dtv_phandle_source2,
 \t.plat_size\t= sizeof(dtv_phandle_source2),
 \t.parent_idx\t= -1,
 };
@@ -443,7 +1013,7 @@
 };
 U_BOOT_DRVINFO(phandle_target) = {
 \t.name\t\t= "target",
-\t.plat\t= &dtv_phandle_target,
+\t.plat\t\t= &dtv_phandle_target,
 \t.plat_size\t= sizeof(dtv_phandle_target),
 \t.parent_idx\t= -1,
 };
@@ -474,6 +1044,16 @@
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: phandle_source2      source
+ *   1: phandle_target       target
+ * ---  -------------------- --------------------
+ */
+
 /* Node /phandle-source2 index 0 */
 static struct dtd_source dtv_phandle_source2 = {
 \t.clocks\t\t\t= {
@@ -481,7 +1061,7 @@
 };
 U_BOOT_DRVINFO(phandle_source2) = {
 \t.name\t\t= "source",
-\t.plat\t= &dtv_phandle_source2,
+\t.plat\t\t= &dtv_phandle_source2,
 \t.plat_size\t= sizeof(dtv_phandle_source2),
 \t.parent_idx\t= -1,
 };
@@ -491,7 +1071,7 @@
 };
 U_BOOT_DRVINFO(phandle_target) = {
 \t.name\t\t= "target",
-\t.plat\t= &dtv_phandle_target,
+\t.plat\t\t= &dtv_phandle_target,
 \t.plat_size\t= sizeof(dtv_phandle_target),
 \t.parent_idx\t= -1,
 };
@@ -502,17 +1082,32 @@
         """Test that phandle targets are generated when unsing cd-gpios"""
         dtb_file = get_dtb_file('dtoc_test_phandle_cd_gpios.dts')
         output = tools.GetOutputFilename('output')
-        dtb_platdata.run_steps(['platdata'], dtb_file, False, output, [], True)
+        dtb_platdata.run_steps(
+            ['platdata'], dtb_file, False, output, [], None, False,
+            warning_disabled=True, scan=copy_scan())
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: phandle2_target      target
+ *   1: phandle3_target      target
+ *   2: phandle_source       source
+ *   3: phandle_source2      source
+ *   4: phandle_target       target
+ * ---  -------------------- --------------------
+ */
+
 /* Node /phandle2-target index 0 */
 static struct dtd_target dtv_phandle2_target = {
 \t.intval\t\t\t= 0x1,
 };
 U_BOOT_DRVINFO(phandle2_target) = {
 \t.name\t\t= "target",
-\t.plat\t= &dtv_phandle2_target,
+\t.plat\t\t= &dtv_phandle2_target,
 \t.plat_size\t= sizeof(dtv_phandle2_target),
 \t.parent_idx\t= -1,
 };
@@ -523,7 +1118,7 @@
 };
 U_BOOT_DRVINFO(phandle3_target) = {
 \t.name\t\t= "target",
-\t.plat\t= &dtv_phandle3_target,
+\t.plat\t\t= &dtv_phandle3_target,
 \t.plat_size\t= sizeof(dtv_phandle3_target),
 \t.parent_idx\t= -1,
 };
@@ -538,7 +1133,7 @@
 };
 U_BOOT_DRVINFO(phandle_source) = {
 \t.name\t\t= "source",
-\t.plat\t= &dtv_phandle_source,
+\t.plat\t\t= &dtv_phandle_source,
 \t.plat_size\t= sizeof(dtv_phandle_source),
 \t.parent_idx\t= -1,
 };
@@ -550,7 +1145,7 @@
 };
 U_BOOT_DRVINFO(phandle_source2) = {
 \t.name\t\t= "source",
-\t.plat\t= &dtv_phandle_source2,
+\t.plat\t\t= &dtv_phandle_source2,
 \t.plat_size\t= sizeof(dtv_phandle_source2),
 \t.parent_idx\t= -1,
 };
@@ -561,7 +1156,7 @@
 };
 U_BOOT_DRVINFO(phandle_target) = {
 \t.name\t\t= "target",
-\t.plat\t= &dtv_phandle_target,
+\t.plat\t\t= &dtv_phandle_target,
 \t.plat_size\t= sizeof(dtv_phandle_target),
 \t.parent_idx\t= -1,
 };
@@ -611,13 +1206,24 @@
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: test1                test1
+ *   1: test2                test2
+ *   2: test3                test3
+ * ---  -------------------- --------------------
+ */
+
 /* Node /test1 index 0 */
 static struct dtd_test1 dtv_test1 = {
 \t.reg\t\t\t= {0x1234, 0x5678},
 };
 U_BOOT_DRVINFO(test1) = {
 \t.name\t\t= "test1",
-\t.plat\t= &dtv_test1,
+\t.plat\t\t= &dtv_test1,
 \t.plat_size\t= sizeof(dtv_test1),
 \t.parent_idx\t= -1,
 };
@@ -628,7 +1234,7 @@
 };
 U_BOOT_DRVINFO(test2) = {
 \t.name\t\t= "test2",
-\t.plat\t= &dtv_test2,
+\t.plat\t\t= &dtv_test2,
 \t.plat_size\t= sizeof(dtv_test2),
 \t.parent_idx\t= -1,
 };
@@ -639,7 +1245,7 @@
 };
 U_BOOT_DRVINFO(test3) = {
 \t.name\t\t= "test3",
-\t.plat\t= &dtv_test3,
+\t.plat\t\t= &dtv_test3,
 \t.plat_size\t= sizeof(dtv_test3),
 \t.parent_idx\t= -1,
 };
@@ -666,13 +1272,23 @@
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: test1                test1
+ *   1: test2                test2
+ * ---  -------------------- --------------------
+ */
+
 /* Node /test1 index 0 */
 static struct dtd_test1 dtv_test1 = {
 \t.reg\t\t\t= {0x1234, 0x5678},
 };
 U_BOOT_DRVINFO(test1) = {
 \t.name\t\t= "test1",
-\t.plat\t= &dtv_test1,
+\t.plat\t\t= &dtv_test1,
 \t.plat_size\t= sizeof(dtv_test1),
 \t.parent_idx\t= -1,
 };
@@ -683,7 +1299,7 @@
 };
 U_BOOT_DRVINFO(test2) = {
 \t.name\t\t= "test2",
-\t.plat\t= &dtv_test2,
+\t.plat\t\t= &dtv_test2,
 \t.plat_size\t= sizeof(dtv_test2),
 \t.parent_idx\t= -1,
 };
@@ -713,13 +1329,24 @@
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: test1                test1
+ *   1: test2                test2
+ *   2: test3                test3
+ * ---  -------------------- --------------------
+ */
+
 /* Node /test1 index 0 */
 static struct dtd_test1 dtv_test1 = {
 \t.reg\t\t\t= {0x123400000000, 0x5678},
 };
 U_BOOT_DRVINFO(test1) = {
 \t.name\t\t= "test1",
-\t.plat\t= &dtv_test1,
+\t.plat\t\t= &dtv_test1,
 \t.plat_size\t= sizeof(dtv_test1),
 \t.parent_idx\t= -1,
 };
@@ -730,7 +1357,7 @@
 };
 U_BOOT_DRVINFO(test2) = {
 \t.name\t\t= "test2",
-\t.plat\t= &dtv_test2,
+\t.plat\t\t= &dtv_test2,
 \t.plat_size\t= sizeof(dtv_test2),
 \t.parent_idx\t= -1,
 };
@@ -741,7 +1368,7 @@
 };
 U_BOOT_DRVINFO(test3) = {
 \t.name\t\t= "test3",
-\t.plat\t= &dtv_test3,
+\t.plat\t\t= &dtv_test3,
 \t.plat_size\t= sizeof(dtv_test3),
 \t.parent_idx\t= -1,
 };
@@ -771,13 +1398,24 @@
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: test1                test1
+ *   1: test2                test2
+ *   2: test3                test3
+ * ---  -------------------- --------------------
+ */
+
 /* Node /test1 index 0 */
 static struct dtd_test1 dtv_test1 = {
 \t.reg\t\t\t= {0x1234, 0x567800000000},
 };
 U_BOOT_DRVINFO(test1) = {
 \t.name\t\t= "test1",
-\t.plat\t= &dtv_test1,
+\t.plat\t\t= &dtv_test1,
 \t.plat_size\t= sizeof(dtv_test1),
 \t.parent_idx\t= -1,
 };
@@ -788,7 +1426,7 @@
 };
 U_BOOT_DRVINFO(test2) = {
 \t.name\t\t= "test2",
-\t.plat\t= &dtv_test2,
+\t.plat\t\t= &dtv_test2,
 \t.plat_size\t= sizeof(dtv_test2),
 \t.parent_idx\t= -1,
 };
@@ -799,7 +1437,7 @@
 };
 U_BOOT_DRVINFO(test3) = {
 \t.name\t\t= "test3",
-\t.plat\t= &dtv_test3,
+\t.plat\t\t= &dtv_test3,
 \t.plat_size\t= sizeof(dtv_test3),
 \t.parent_idx\t= -1,
 };
@@ -824,7 +1462,7 @@
         with self.assertRaises(ValueError) as exc:
             self.run_test(['struct'], dtb_file, output)
         self.assertIn(
-            "Node 'spl-test' reg property has 3 cells which is not a multiple of na + ns = 1 + 1)",
+            "Node 'spl-test' (parent '/') reg property has 3 cells which is not a multiple of na + ns = 1 + 1)",
             str(exc.exception))
 
     def test_add_prop(self):
@@ -845,24 +1483,40 @@
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
-/* Node /spl-test index 0 */
+/*
+ * driver_info declarations, ordered by 'struct driver_info' linker_list idx:
+ *
+ * idx  driver_info          driver
+ * ---  -------------------- --------------------
+ *   0: spl_test             sandbox_spl_test
+ *   1: spl_test2            sandbox_spl_test
+ * ---  -------------------- --------------------
+ */
+
+/*
+ * Node /spl-test index 0
+ * driver sandbox_spl_test parent None
+ */
 static struct dtd_sandbox_spl_test dtv_spl_test = {
 \t.intval\t\t\t= 0x1,
 };
 U_BOOT_DRVINFO(spl_test) = {
 \t.name\t\t= "sandbox_spl_test",
-\t.plat\t= &dtv_spl_test,
+\t.plat\t\t= &dtv_spl_test,
 \t.plat_size\t= sizeof(dtv_spl_test),
 \t.parent_idx\t= -1,
 };
 
-/* Node /spl-test2 index 1 */
+/*
+ * Node /spl-test2 index 1
+ * driver sandbox_spl_test parent None
+ */
 static struct dtd_sandbox_spl_test dtv_spl_test2 = {
 \t.intarray\t\t= 0x5,
 };
 U_BOOT_DRVINFO(spl_test2) = {
 \t.name\t\t= "sandbox_spl_test",
-\t.plat\t= &dtv_spl_test2,
+\t.plat\t\t= &dtv_spl_test2,
 \t.plat_size\t= sizeof(dtv_spl_test2),
 \t.parent_idx\t= -1,
 };
@@ -882,7 +1536,9 @@
         output = tools.GetOutputFilename('output')
         self.run_test(['all'], dtb_file, output)
         data = tools.ReadFile(output, binary=False)
-        self._check_strings(self.platdata_text + self.struct_text, data)
+        self._check_strings(
+            self.decl_text + self.device_text + self.platdata_text +
+            self.struct_text + self.uclass_text, data)
 
     def test_no_command(self):
         """Test running dtoc without a command"""
@@ -897,13 +1553,16 @@
         output = tools.GetOutputFilename('output')
         with self.assertRaises(ValueError) as exc:
             self.run_test(['invalid-cmd'], dtb_file, output)
-        self.assertIn("Unknown command 'invalid-cmd': (use: platdata, struct)",
-                      str(exc.exception))
+        self.assertIn(
+            "Unknown command 'invalid-cmd': (use: decl, platdata, struct)",
+            str(exc.exception))
 
     def test_output_conflict(self):
         """Test a conflict between and output dirs and output file"""
         with self.assertRaises(ValueError) as exc:
-            dtb_platdata.run_steps(['all'], None, False, 'out', ['cdir'], True)
+            dtb_platdata.run_steps(
+                ['all'], None, False, 'out', ['cdir'], None, False,
+                warning_disabled=True, scan=copy_scan())
         self.assertIn("Must specify either output or output_dirs, not both",
                       str(exc.exception))
 
@@ -919,11 +1578,264 @@
         fnames = glob.glob(outdir + '/*')
         self.assertEqual(2, len(fnames))
 
-        dtb_platdata.run_steps(['all'], dtb_file, False, None, [outdir], True)
+        dtb_platdata.run_steps(
+            ['all'], dtb_file, False, None, [outdir], None, False,
+            warning_disabled=True, scan=copy_scan())
         fnames = glob.glob(outdir + '/*')
-        self.assertEqual(4, len(fnames))
+        self.assertEqual(7, len(fnames))
 
         leafs = set(os.path.basename(fname) for fname in fnames)
         self.assertEqual(
-            {'dt-structs-gen.h', 'source.dts', 'dt-plat.c', 'source.dtb'},
+            {'dt-structs-gen.h', 'source.dts', 'dt-plat.c', 'source.dtb',
+             'dt-uclass.c', 'dt-decl.h', 'dt-device.c'},
             leafs)
+
+    def setup_process_test(self):
+        """Set up a test of process_nodes()
+
+        This uses saved_scan but returns a deep copy of it, so it is safe to
+        modify it in these tests
+
+        Returns:
+            tuple:
+                DtbPlatdata: object to test
+                Scanner: scanner to use
+        """
+        dtb_file = get_dtb_file('dtoc_test_simple.dts')
+        output = tools.GetOutputFilename('output')
+
+        # Take a copy before messing with it
+        scan = copy_scan()
+        plat = dtb_platdata.DtbPlatdata(scan, dtb_file, False)
+        plat.scan_dtb()
+        plat.scan_tree(False)
+        plat.prepare_nodes()
+        return plat, scan
+
+    def test_process_nodes(self):
+        """Test processing nodes to add various info"""
+        plat, scan = self.setup_process_test()
+        plat.process_nodes(True)
+
+        i2c_node = plat._fdt.GetNode('/i2c@0')
+        pmic_node = plat._fdt.GetNode('/i2c@0/pmic@9')
+        pmic = scan._drivers['sandbox_pmic']
+        i2c = scan._drivers['sandbox_i2c']
+        self.assertEqual('DM_DEVICE_REF(pmic_at_9)', pmic_node.dev_ref)
+        self.assertEqual(pmic, pmic_node.driver)
+        self.assertEqual(i2c_node, pmic_node.parent)
+        self.assertEqual(i2c, pmic_node.parent_driver)
+
+        # The pmic is the only child
+        self.assertEqual(pmic_node.parent_seq, 0)
+        self.assertEqual([pmic_node], i2c_node.child_devs)
+
+        # Start and end of the list should be the child_head
+        ref = '&DM_DEVICE_REF(i2c_at_0)->child_head'
+        self.assertEqual(
+            {-1: ref, 0: '&DM_DEVICE_REF(pmic_at_9)->sibling_node', 1: ref},
+            i2c_node.child_refs)
+
+    def test_process_nodes_bad_parent(self):
+        # Pretend that i2c has a parent (the pmic) and delete that driver
+        plat, scan = self.setup_process_test()
+
+        i2c_node = plat._fdt.GetNode('/i2c@0')
+        pmic_node = plat._fdt.GetNode('/i2c@0/pmic@9')
+        del scan._drivers['sandbox_pmic']
+        i2c_node.parent = pmic_node
+
+        # Process twice, the second time to generate an exception
+        plat.process_nodes(False)
+        with self.assertRaises(ValueError) as exc:
+            plat.process_nodes(True)
+        self.assertIn(
+            "Cannot parse/find parent driver 'sandbox_pmic' for 'sandbox_i2c",
+            str(exc.exception))
+
+    def test_process_nodes_bad_node(self):
+        plat, scan = self.setup_process_test()
+
+        # Now remove the pmic driver
+        del scan._drivers['sandbox_pmic']
+
+        # Process twice, the second time to generate an exception
+        plat.process_nodes(False)
+        with self.assertRaises(ValueError) as exc:
+            plat.process_nodes(True)
+        self.assertIn("Cannot parse/find driver for 'sandbox_pmic",
+                      str(exc.exception))
+
+    def test_process_nodes_bad_uclass(self):
+        plat, scan = self.setup_process_test()
+
+        self.assertIn('UCLASS_I2C', scan._uclass)
+        del scan._uclass['UCLASS_I2C']
+        with self.assertRaises(ValueError) as exc:
+            plat.process_nodes(True)
+        self.assertIn("Cannot parse/find uclass 'UCLASS_I2C' for driver 'sandbox_i2c'",
+                      str(exc.exception))
+
+    def test_process_nodes_used(self):
+        """Test processing nodes to add various info"""
+        plat, scan = self.setup_process_test()
+        plat.process_nodes(True)
+
+        pmic = scan._drivers['sandbox_pmic']
+        self.assertTrue(pmic.used)
+
+        gpio = scan._drivers['sandbox_gpio']
+        self.assertFalse(gpio.used)
+
+    def test_alias_read(self):
+        """Test obtaining aliases"""
+        dtb_file = get_dtb_file('dtoc_test_inst.dts')
+        output = tools.GetOutputFilename('output')
+        plat = self.run_test(['struct'], dtb_file, output)
+
+        scan = plat._scan
+        testfdt_node = plat._fdt.GetNode('/some-bus/test')
+        test0_node = plat._fdt.GetNode('/some-bus/test0')
+        self.assertIn('UCLASS_TEST_FDT', scan._uclass)
+        uc = scan._uclass['UCLASS_TEST_FDT']
+        self.assertEqual({1: testfdt_node, 2: test0_node},
+                         uc.alias_num_to_node)
+        self.assertEqual({'/some-bus/test': 1, '/some-bus/test0': 2},
+                         uc.alias_path_to_num)
+
+        # Try adding an alias that doesn't exist
+        self.assertFalse(scan.add_uclass_alias('fred', 3, None))
+
+        # Try adding an alias for a missing node
+        self.assertIsNone(scan.add_uclass_alias('testfdt', 3, None))
+
+    def test_alias_read_bad(self):
+        """Test invalid alias property name"""
+        dtb_file = get_dtb_file('dtoc_test_alias_bad.dts')
+        output = tools.GetOutputFilename('output')
+        with self.assertRaises(ValueError) as exc:
+            plat = self.run_test(['struct'], dtb_file, output)
+        self.assertIn("Cannot decode alias 'i2c4-'", str(exc.exception))
+
+    def test_alias_read_bad_path(self):
+        """Test alias pointing to a non-existent node"""
+        # This line may produce a warning, so capture it:
+        # Warning (alias_paths): /aliases:i2c4: aliases property is not a valid
+        #    node (/does/not/exist)
+        dtb_file = get_dtb_file('dtoc_test_alias_bad_path.dts', True)
+
+        output = tools.GetOutputFilename('output')
+        with self.assertRaises(ValueError) as exc:
+            plat = self.run_test(['struct'], dtb_file, output)
+        self.assertIn("Alias 'i2c4' path '/does/not/exist' not found",
+                      str(exc.exception))
+
+    def test_alias_read_bad_uclass(self):
+        """Test alias for a uclass that doesn't exist"""
+        dtb_file = get_dtb_file('dtoc_test_alias_bad_uc.dts')
+        output = tools.GetOutputFilename('output')
+        with test_util.capture_sys_output() as (stdout, _):
+            plat = self.run_test(['struct'], dtb_file, output)
+        self.assertEqual("Could not find uclass for alias 'other1'",
+                         stdout.getvalue().strip())
+
+    def test_sequence(self):
+        """Test assignment of sequence numnbers"""
+        dtb_file = get_dtb_file('dtoc_test_inst.dts')
+        output = tools.GetOutputFilename('output')
+        plat = self.run_test(['struct'], dtb_file, output)
+
+        scan = plat._scan
+        testfdt = plat._fdt.GetNode('/some-bus/test')
+        self.assertEqual(1, testfdt.seq)
+        i2c = plat._fdt.GetNode('/i2c')
+
+        # For now this uclass is not compiled in, so no sequence is assigned
+        self.assertEqual(4, i2c.seq)
+        spl = plat._fdt.GetNode('/spl-test')
+        self.assertEqual(0, spl.seq)
+
+    def test_process_root(self):
+        """Test assignment of sequence numnbers"""
+        dtb_file = get_dtb_file('dtoc_test_simple.dts')
+        output = tools.GetOutputFilename('output')
+
+        # Take a copy before messing with it
+        scan = copy_scan()
+        plat = dtb_platdata.DtbPlatdata(scan, dtb_file, False)
+        plat.scan_dtb()
+        root = plat._fdt.GetRoot()
+
+        plat.scan_tree(False)
+        self.assertNotIn(root, plat._valid_nodes)
+
+        plat.scan_tree(True)
+        self.assertIn(root, plat._valid_nodes)
+        self.assertEqual('root_driver',
+                         scan.get_normalized_compat_name(root)[0])
+
+    def test_simple_inst(self):
+        """Test output from some simple nodes with instantiate enabled"""
+        dtb_file = get_dtb_file('dtoc_test_inst.dts')
+        output = tools.GetOutputFilename('output')
+
+        self.run_test(['decl'], dtb_file, output, True)
+        with open(output) as infile:
+            data = infile.read()
+
+        self._check_strings(self.decl_text_inst, data)
+
+        self.run_test(['platdata'], dtb_file, output, True)
+        with open(output) as infile:
+            data = infile.read()
+
+        self._check_strings(C_HEADER_PRE + '''
+/* This file is not used: --instantiate was enabled */
+''', data)
+
+        self.run_test(['uclass'], dtb_file, output, True)
+        with open(output) as infile:
+            data = infile.read()
+
+        self._check_strings(UCLASS_HEADER_COMMON + self.uclass_text_inst, data)
+
+        self.run_test(['device'], dtb_file, output, True)
+        with open(output) as infile:
+            data = infile.read()
+
+        self._check_strings(self.device_text_inst, data)
+
+    def test_inst_no_hdr(self):
+        """Test dealing with a struct tsssshat has no header"""
+        dtb_file = get_dtb_file('dtoc_test_inst.dts')
+        output = tools.GetOutputFilename('output')
+
+        # Run it once to set everything up
+        plat = self.run_test(['decl'], dtb_file, output, True)
+        scan = plat._scan
+
+        # Restart the output file and delete any record of the uclass' struct
+        plat.setup_output(Ftype.SOURCE, output)
+        del scan._structs['dm_test_uc_priv']
+
+        # Now generate the uclasses, which should provide a warning
+        with test_util.capture_sys_output() as (stdout, _):
+            plat.generate_uclasses()
+        self.assertEqual(
+            'Warning: Cannot find header file for struct dm_test_uc_priv',
+            stdout.getvalue().strip())
+
+    def test_missing_props(self):
+        """Test detection of a parent node with no properties"""
+        dtb_file = get_dtb_file('dtoc_test_noprops.dts', capture_stderr=True)
+        output = tools.GetOutputFilename('output')
+        with self.assertRaises(ValueError) as exc:
+            self.run_test(['struct'], dtb_file, output)
+        self.assertIn("Parent node '/i2c@0' has no properties - do you need",
+                      str(exc.exception))
+
+    def test_single_reg(self):
+        """Test detection of a parent node with no properties"""
+        dtb_file = get_dtb_file('dtoc_test_single_reg.dts')
+        output = tools.GetOutputFilename('output')
+        self.run_test(['struct'], dtb_file, output)
diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py
index e8fbbd5..856392b 100755
--- a/tools/dtoc/test_fdt.py
+++ b/tools/dtoc/test_fdt.py
@@ -48,6 +48,17 @@
     data = dtb.GetContents()[offset:offset + len(prop.value)]
     return prop, [chr(x) for x in data]
 
+def find_dtb_file(dts_fname):
+    """Locate a test file in the test/ directory
+
+    Args:
+        dts_fname (str): Filename to find, e.g. 'dtoc_test_simple.dts]
+
+    Returns:
+        str: Path to the test filename
+    """
+    return os.path.join('tools/dtoc/test', dts_fname)
+
 
 class TestFdt(unittest.TestCase):
     """Tests for the Fdt module
@@ -64,7 +75,7 @@
         tools.FinaliseOutputDir()
 
     def setUp(self):
-        self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
+        self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts'))
 
     def testFdt(self):
         """Test that we can open an Fdt"""
@@ -141,8 +152,9 @@
         tools.FinaliseOutputDir()
 
     def setUp(self):
-        self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
+        self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts'))
         self.node = self.dtb.GetNode('/spl-test')
+        self.fdt = self.dtb.GetFdtObj()
 
     def testOffset(self):
         """Tests that we can obtain the offset of a node"""
@@ -186,7 +198,7 @@
     def testRefreshExtraNode(self):
         """Test refreshing offsets when an expected node is missing"""
         # Delete it from the device tre, not our tables
-        self.dtb.GetFdtObj().del_node(self.node.Offset())
+        self.fdt.del_node(self.node.Offset())
         with self.assertRaises(ValueError) as e:
             self.dtb.Refresh()
         self.assertIn('Internal error, node name mismatch '
@@ -198,17 +210,77 @@
         del self.node.props['notstring']
         with self.assertRaises(ValueError) as e:
             self.dtb.Refresh()
-        self.assertIn("Internal error, property 'notstring' missing, offset ",
+        self.assertIn("Internal error, node '/spl-test' property 'notstring' missing, offset ",
                       str(e.exception))
 
     def testLookupPhandle(self):
         """Test looking up a single phandle"""
-        dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
+        dtb = fdt.FdtScan(find_dtb_file('dtoc_test_phandle.dts'))
         node = dtb.GetNode('/phandle-source2')
         prop = node.props['clocks']
         target = dtb.GetNode('/phandle-target')
         self.assertEqual(target, dtb.LookupPhandle(fdt32_to_cpu(prop.value)))
 
+    def testAddNodeSpace(self):
+        """Test adding a single node when out of space"""
+        self.fdt.pack()
+        self.node.AddSubnode('subnode')
+        with self.assertRaises(libfdt.FdtException) as e:
+            self.dtb.Sync(auto_resize=False)
+        self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
+
+        self.dtb.Sync(auto_resize=True)
+        offset = self.fdt.path_offset('/spl-test/subnode')
+        self.assertTrue(offset > 0)
+
+    def testAddNodes(self):
+        """Test adding various subnode and properies"""
+        node = self.dtb.GetNode('/i2c@0')
+
+        # Add one more node next to the pmic one
+        sn1 = node.AddSubnode('node-one')
+        sn1.AddInt('integer-a', 12)
+        sn1.AddInt('integer-b', 23)
+
+        # Sync so that everything is clean
+        self.dtb.Sync(auto_resize=True)
+
+        # Add two subnodes next to pmic and node-one
+        sn2 = node.AddSubnode('node-two')
+        sn2.AddInt('integer-2a', 34)
+        sn2.AddInt('integer-2b', 45)
+
+        sn3 = node.AddSubnode('node-three')
+        sn3.AddInt('integer-3', 123)
+
+        # Add a property to the node after i2c@0 to check that this is not
+        # disturbed by adding a subnode to i2c@0
+        orig_node = self.dtb.GetNode('/orig-node')
+        orig_node.AddInt('integer-4', 456)
+
+        # Add a property to the pmic node to check that pmic properties are not
+        # disturbed
+        pmic = self.dtb.GetNode('/i2c@0/pmic@9')
+        pmic.AddInt('integer-5', 567)
+
+        self.dtb.Sync(auto_resize=True)
+
+    def testRefreshNameMismatch(self):
+        """Test name mismatch when syncing nodes and properties"""
+        prop = self.node.AddInt('integer-a', 12)
+
+        wrong_offset = self.dtb.GetNode('/i2c@0')._offset
+        self.node._offset = wrong_offset
+        with self.assertRaises(ValueError) as e:
+            self.dtb.Sync()
+        self.assertIn("Internal error, node '/spl-test' name mismatch 'i2c@0'",
+                      str(e.exception))
+
+        with self.assertRaises(ValueError) as e:
+            self.node.Refresh(wrong_offset)
+        self.assertIn("Internal error, node '/spl-test' name mismatch 'i2c@0'",
+                      str(e.exception))
+
 
 class TestProp(unittest.TestCase):
     """Test operation of the Prop class"""
@@ -222,7 +294,7 @@
         tools.FinaliseOutputDir()
 
     def setUp(self):
-        self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
+        self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts'))
         self.node = self.dtb.GetNode('/spl-test')
         self.fdt = self.dtb.GetFdtObj()
 
@@ -230,7 +302,7 @@
         self.assertEqual(None, self.dtb.GetNode('missing'))
 
     def testPhandle(self):
-        dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
+        dtb = fdt.FdtScan(find_dtb_file('dtoc_test_phandle.dts'))
         node = dtb.GetNode('/phandle-source2')
         prop = node.props['clocks']
         self.assertTrue(fdt32_to_cpu(prop.value) > 0)
@@ -374,17 +446,6 @@
         self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
         self.dtb.Sync(auto_resize=True)
 
-    def testAddNode(self):
-        self.fdt.pack()
-        self.node.AddSubnode('subnode')
-        with self.assertRaises(libfdt.FdtException) as e:
-            self.dtb.Sync(auto_resize=False)
-        self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
-
-        self.dtb.Sync(auto_resize=True)
-        offset = self.fdt.path_offset('/spl-test/subnode')
-        self.assertTrue(offset > 0)
-
     def testAddMore(self):
         """Test various other methods for adding and setting properties"""
         self.node.AddZeroProp('one')
@@ -488,7 +549,7 @@
         tools.FinaliseOutputDir()
 
     def setUp(self):
-        self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
+        self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts'))
         self.node = self.dtb.GetNode('/spl-test')
 
     def testGetInt(self):
@@ -531,7 +592,7 @@
                       str(e.exception))
 
     def testGetPhandleList(self):
-        dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
+        dtb = fdt.FdtScan(find_dtb_file('dtoc_test_phandle.dts'))
         node = dtb.GetNode('/phandle-source2')
         self.assertEqual([1], fdt_util.GetPhandleList(node, 'clocks'))
         node = dtb.GetNode('/phandle-source')
@@ -551,7 +612,7 @@
         self.assertEqual(0, fdt_util.fdt_cells_to_cpu(val, 0))
         self.assertEqual(2, fdt_util.fdt_cells_to_cpu(val, 1))
 
-        dtb2 = fdt.FdtScan('tools/dtoc/dtoc_test_addr64.dts')
+        dtb2 = fdt.FdtScan(find_dtb_file('dtoc_test_addr64.dts'))
         node1 = dtb2.GetNode('/test1')
         val = node1.props['reg'].value
         self.assertEqual(0x1234, fdt_util.fdt_cells_to_cpu(val, 2))
@@ -565,7 +626,7 @@
 
     def testEnsureCompiled(self):
         """Test a degenerate case of this function (file already compiled)"""
-        dtb = fdt_util.EnsureCompiled('tools/dtoc/dtoc_test_simple.dts')
+        dtb = fdt_util.EnsureCompiled(find_dtb_file('dtoc_test_simple.dts'))
         self.assertEqual(dtb, fdt_util.EnsureCompiled(dtb))
 
     def testEnsureCompiledTmpdir(self):
@@ -574,7 +635,7 @@
             old_outdir = tools.outdir
             tools.outdir= None
             tmpdir = tempfile.mkdtemp(prefix='test_fdt.')
-            dtb = fdt_util.EnsureCompiled('tools/dtoc/dtoc_test_simple.dts',
+            dtb = fdt_util.EnsureCompiled(find_dtb_file('dtoc_test_simple.dts'),
                                           tmpdir)
             self.assertEqual(tmpdir, os.path.dirname(dtb))
             shutil.rmtree(tmpdir)
diff --git a/tools/dtoc/test_src_scan.py b/tools/dtoc/test_src_scan.py
index 7d68653..d6da038 100644
--- a/tools/dtoc/test_src_scan.py
+++ b/tools/dtoc/test_src_scan.py
@@ -7,6 +7,7 @@
 This includes unit tests for scanning of the source code
 """
 
+import copy
 import os
 import shutil
 import tempfile
@@ -17,6 +18,20 @@
 from patman import test_util
 from patman import tools
 
+OUR_PATH = os.path.dirname(os.path.realpath(__file__))
+
+class FakeNode:
+    """Fake Node object for testing"""
+    def __init__(self):
+        self.name = None
+        self.props = {}
+
+class FakeProp:
+    """Fake Prop object for testing"""
+    def __init__(self):
+        self.name = None
+        self.value = None
+
 # This is a test so is allowed to access private things in the module it is
 # testing
 # pylint: disable=W0212
@@ -33,7 +48,7 @@
 
     def test_simple(self):
         """Simple test of scanning drivers"""
-        scan = src_scan.Scanner(None, True, None)
+        scan = src_scan.Scanner(None, None)
         scan.scan_drivers()
         self.assertIn('sandbox_gpio', scan._drivers)
         self.assertIn('sandbox_gpio_alias', scan._driver_aliases)
@@ -44,7 +59,7 @@
     def test_additional(self):
         """Test with additional drivers to scan"""
         scan = src_scan.Scanner(
-            None, True, [None, '', 'tools/dtoc/dtoc_test_scan_drivers.cxx'])
+            None, [None, '', 'tools/dtoc/test/dtoc_test_scan_drivers.cxx'])
         scan.scan_drivers()
         self.assertIn('sandbox_gpio_alias2', scan._driver_aliases)
         self.assertEqual('sandbox_gpio',
@@ -61,7 +76,7 @@
         with open(driver_fn, 'wb+') as fout:
             fout.write(b'\x81')
 
-        scan = src_scan.Scanner(None, True, [driver_fn])
+        scan = src_scan.Scanner(None, [driver_fn])
         with test_util.capture_sys_output() as (stdout, _):
             scan.scan_drivers()
         self.assertRegex(stdout.getvalue(),
@@ -69,10 +84,22 @@
 
     def test_driver(self):
         """Test the Driver class"""
-        drv1 = src_scan.Driver('fred')
-        drv2 = src_scan.Driver('mary')
-        drv3 = src_scan.Driver('fred')
-        self.assertEqual("Driver(name='fred')", str(drv1))
+        i2c = 'I2C_UCLASS'
+        compat = {'rockchip,rk3288-grf': 'ROCKCHIP_SYSCON_GRF',
+                  'rockchip,rk3288-srf': None}
+        drv1 = src_scan.Driver('fred', 'fred.c')
+        drv2 = src_scan.Driver('mary', 'mary.c')
+        drv3 = src_scan.Driver('fred', 'fred.c')
+        drv1.uclass_id = i2c
+        drv1.compat = compat
+        drv2.uclass_id = i2c
+        drv2.compat = compat
+        drv3.uclass_id = i2c
+        drv3.compat = compat
+        self.assertEqual(
+            "Driver(name='fred', used=False, uclass_id='I2C_UCLASS', "
+            "compat={'rockchip,rk3288-grf': 'ROCKCHIP_SYSCON_GRF', "
+            "'rockchip,rk3288-srf': None}, priv=)", str(drv1))
         self.assertEqual(drv1, drv3)
         self.assertNotEqual(drv1, drv2)
         self.assertNotEqual(drv2, drv3)
@@ -91,17 +118,375 @@
 
             fname_list = []
             add_file('fname.c')
+            add_file('.git/ignoreme.c')
             add_file('dir/fname2.c')
+            add_file('build-sandbox/ignoreme2.c')
 
             # Mock out scan_driver and check that it is called with the
             # expected files
             with mock.patch.object(src_scan.Scanner, "scan_driver")  as mocked:
-                scan = src_scan.Scanner(indir, True, None)
+                scan = src_scan.Scanner(indir, None)
                 scan.scan_drivers()
             self.assertEqual(2, len(mocked.mock_calls))
             self.assertEqual(mock.call(fname_list[0]),
                              mocked.mock_calls[0])
-            self.assertEqual(mock.call(fname_list[1]),
+            # .git file should be ignored
+            self.assertEqual(mock.call(fname_list[2]),
                              mocked.mock_calls[1])
         finally:
             shutil.rmtree(indir)
+
+    def test_scan(self):
+        """Test scanning of a driver"""
+        fname = os.path.join(OUR_PATH, '..', '..', 'drivers/i2c/tegra_i2c.c')
+        buff = tools.ReadFile(fname, False)
+        scan = src_scan.Scanner(None, None)
+        scan._parse_driver(fname, buff)
+        self.assertIn('i2c_tegra', scan._drivers)
+        drv = scan._drivers['i2c_tegra']
+        self.assertEqual('i2c_tegra', drv.name)
+        self.assertEqual('UCLASS_I2C', drv.uclass_id)
+        self.assertEqual(
+            {'nvidia,tegra114-i2c': 'TYPE_114',
+             'nvidia,tegra20-i2c': 'TYPE_STD',
+             'nvidia,tegra20-i2c-dvc': 'TYPE_DVC'}, drv.compat)
+        self.assertEqual('i2c_bus', drv.priv)
+        self.assertEqual(1, len(scan._drivers))
+
+    def test_normalized_name(self):
+        """Test operation of get_normalized_compat_name()"""
+        prop = FakeProp()
+        prop.name = 'compatible'
+        prop.value = 'rockchip,rk3288-grf'
+        node = FakeNode()
+        node.props = {'compatible': prop}
+
+        # get_normalized_compat_name() uses this to check for root node
+        node.parent = FakeNode()
+
+        scan = src_scan.Scanner(None, None)
+        with test_util.capture_sys_output() as (stdout, _):
+            name, aliases = scan.get_normalized_compat_name(node)
+        self.assertEqual('rockchip_rk3288_grf', name)
+        self.assertEqual([], aliases)
+        self.assertEqual(1, len(scan._missing_drivers))
+        self.assertEqual({'rockchip_rk3288_grf'}, scan._missing_drivers)
+            #'WARNING: the driver rockchip_rk3288_grf was not found in the driver list',
+            #stdout.getvalue().strip())
+
+        i2c = 'I2C_UCLASS'
+        compat = {'rockchip,rk3288-grf': 'ROCKCHIP_SYSCON_GRF',
+                  'rockchip,rk3288-srf': None}
+        drv = src_scan.Driver('fred', 'fred.c')
+        drv.uclass_id = i2c
+        drv.compat = compat
+        scan._drivers['rockchip_rk3288_grf'] = drv
+
+        scan._driver_aliases['rockchip_rk3288_srf'] = 'rockchip_rk3288_grf'
+
+        with test_util.capture_sys_output() as (stdout, _):
+            name, aliases = scan.get_normalized_compat_name(node)
+        self.assertEqual('', stdout.getvalue().strip())
+        self.assertEqual('rockchip_rk3288_grf', name)
+        self.assertEqual([], aliases)
+
+        prop.value = 'rockchip,rk3288-srf'
+        with test_util.capture_sys_output() as (stdout, _):
+            name, aliases = scan.get_normalized_compat_name(node)
+        self.assertEqual('', stdout.getvalue().strip())
+        self.assertEqual('rockchip_rk3288_grf', name)
+        self.assertEqual(['rockchip_rk3288_srf'], aliases)
+
+    def test_scan_errors(self):
+        """Test detection of scanning errors"""
+        buff = '''
+static const struct udevice_id tegra_i2c_ids2[] = {
+	{ .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
+	{ }
+};
+
+U_BOOT_DRIVER(i2c_tegra) = {
+	.name	= "i2c_tegra",
+	.id	= UCLASS_I2C,
+	.of_match = tegra_i2c_ids,
+};
+'''
+        scan = src_scan.Scanner(None, None)
+        with self.assertRaises(ValueError) as exc:
+            scan._parse_driver('file.c', buff)
+        self.assertIn(
+            "file.c: Unknown compatible var 'tegra_i2c_ids' (found: tegra_i2c_ids2)",
+            str(exc.exception))
+
+    def test_of_match(self):
+        """Test detection of of_match_ptr() member"""
+        buff = '''
+static const struct udevice_id tegra_i2c_ids[] = {
+	{ .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
+	{ }
+};
+
+U_BOOT_DRIVER(i2c_tegra) = {
+	.name	= "i2c_tegra",
+	.id	= UCLASS_I2C,
+	.of_match = of_match_ptr(tegra_i2c_ids),
+};
+'''
+        scan = src_scan.Scanner(None, None)
+        scan._parse_driver('file.c', buff)
+        self.assertIn('i2c_tegra', scan._drivers)
+        drv = scan._drivers['i2c_tegra']
+        self.assertEqual('i2c_tegra', drv.name)
+        self.assertEqual('', drv.phase)
+        self.assertEqual([], drv.headers)
+
+    def test_priv(self):
+        """Test collection of struct info from drivers"""
+        buff = '''
+static const struct udevice_id test_ids[] = {
+	{ .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
+	{ }
+};
+
+U_BOOT_DRIVER(testing) = {
+	.name	= "testing",
+	.id	= UCLASS_I2C,
+	.of_match = test_ids,
+	.priv_auto	= sizeof(struct some_priv),
+	.plat_auto = sizeof(struct some_plat),
+	.per_child_auto	= sizeof(struct some_cpriv),
+	.per_child_plat_auto = sizeof(struct some_cplat),
+	DM_PHASE(tpl)
+	DM_HEADER(<i2c.h>)
+	DM_HEADER(<asm/clk.h>)
+};
+'''
+        scan = src_scan.Scanner(None, None)
+        scan._parse_driver('file.c', buff)
+        self.assertIn('testing', scan._drivers)
+        drv = scan._drivers['testing']
+        self.assertEqual('testing', drv.name)
+        self.assertEqual('UCLASS_I2C', drv.uclass_id)
+        self.assertEqual(
+            {'nvidia,tegra114-i2c': 'TYPE_114'}, drv.compat)
+        self.assertEqual('some_priv', drv.priv)
+        self.assertEqual('some_plat', drv.plat)
+        self.assertEqual('some_cpriv', drv.child_priv)
+        self.assertEqual('some_cplat', drv.child_plat)
+        self.assertEqual('tpl', drv.phase)
+        self.assertEqual(['<i2c.h>', '<asm/clk.h>'], drv.headers)
+        self.assertEqual(1, len(scan._drivers))
+
+    def test_uclass_scan(self):
+        """Test collection of uclass-driver info"""
+        buff = '''
+UCLASS_DRIVER(i2c) = {
+	.id		= UCLASS_I2C,
+	.name		= "i2c",
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
+	.priv_auto	= sizeof(struct some_priv),
+	.per_device_auto	= sizeof(struct per_dev_priv),
+	.per_device_plat_auto	= sizeof(struct per_dev_plat),
+	.per_child_auto	= sizeof(struct per_child_priv),
+	.per_child_plat_auto	= sizeof(struct per_child_plat),
+	.child_post_bind = i2c_child_post_bind,
+};
+
+'''
+        scan = src_scan.Scanner(None, None)
+        scan._parse_uclass_driver('file.c', buff)
+        self.assertIn('UCLASS_I2C', scan._uclass)
+        drv = scan._uclass['UCLASS_I2C']
+        self.assertEqual('i2c', drv.name)
+        self.assertEqual('UCLASS_I2C', drv.uclass_id)
+        self.assertEqual('some_priv', drv.priv)
+        self.assertEqual('per_dev_priv', drv.per_dev_priv)
+        self.assertEqual('per_dev_plat', drv.per_dev_plat)
+        self.assertEqual('per_child_priv', drv.per_child_priv)
+        self.assertEqual('per_child_plat', drv.per_child_plat)
+        self.assertEqual(1, len(scan._uclass))
+
+        drv2 = copy.deepcopy(drv)
+        self.assertEqual(drv, drv2)
+        drv2.priv = 'other_priv'
+        self.assertNotEqual(drv, drv2)
+
+        # The hashes only depend on the uclass ID, so should be equal
+        self.assertEqual(drv.__hash__(), drv2.__hash__())
+
+        self.assertEqual("UclassDriver(name='i2c', uclass_id='UCLASS_I2C')",
+                         str(drv))
+
+    def test_uclass_scan_errors(self):
+        """Test detection of uclass scanning errors"""
+        buff = '''
+UCLASS_DRIVER(i2c) = {
+	.name		= "i2c",
+};
+
+'''
+        scan = src_scan.Scanner(None, None)
+        with self.assertRaises(ValueError) as exc:
+            scan._parse_uclass_driver('file.c', buff)
+        self.assertIn("file.c: Cannot parse uclass ID in driver 'i2c'",
+                      str(exc.exception))
+
+    def test_struct_scan(self):
+        """Test collection of struct info"""
+        buff = '''
+/* some comment */
+struct some_struct1 {
+	struct i2c_msg *msgs;
+	uint nmsgs;
+};
+'''
+        scan = src_scan.Scanner(None, None)
+        scan._basedir = os.path.join(OUR_PATH, '..', '..')
+        scan._parse_structs('arch/arm/include/asm/file.h', buff)
+        self.assertIn('some_struct1', scan._structs)
+        struc = scan._structs['some_struct1']
+        self.assertEqual('some_struct1', struc.name)
+        self.assertEqual('asm/file.h', struc.fname)
+
+        buff = '''
+/* another comment */
+struct another_struct {
+	int speed_hz;
+	int max_transaction_bytes;
+};
+'''
+        scan._parse_structs('include/file2.h', buff)
+        self.assertIn('another_struct', scan._structs)
+        struc = scan._structs['another_struct']
+        self.assertEqual('another_struct', struc.name)
+        self.assertEqual('file2.h', struc.fname)
+
+        self.assertEqual(2, len(scan._structs))
+
+        self.assertEqual("Struct(name='another_struct', fname='file2.h')",
+                         str(struc))
+
+    def test_struct_scan_errors(self):
+        """Test scanning a header file with an invalid unicode file"""
+        output = tools.GetOutputFilename('output.h')
+        tools.WriteFile(output, b'struct this is a test \x81 of bad unicode')
+
+        scan = src_scan.Scanner(None, None)
+        with test_util.capture_sys_output() as (stdout, _):
+            scan.scan_header(output)
+        self.assertIn('due to unicode error', stdout.getvalue())
+
+    def setup_dup_drivers(self, name, phase=''):
+        """Set up for a duplcate test
+
+        Returns:
+            tuple:
+                Scanner to use
+                Driver record for first driver
+                Text of second driver declaration
+                Node for driver 1
+        """
+        driver1 = '''
+static const struct udevice_id test_ids[] = {
+	{ .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
+	{ }
+};
+
+U_BOOT_DRIVER(%s) = {
+	.name	= "testing",
+	.id	= UCLASS_I2C,
+	.of_match = test_ids,
+	%s
+};
+''' % (name, 'DM_PHASE(%s)' % phase if phase else '')
+        driver2 = '''
+static const struct udevice_id test_ids[] = {
+	{ .compatible = "nvidia,tegra114-dvc" },
+	{ }
+};
+
+U_BOOT_DRIVER(%s) = {
+	.name	= "testing",
+	.id	= UCLASS_RAM,
+	.of_match = test_ids,
+};
+''' % name
+        scan = src_scan.Scanner(None, None, phase)
+        scan._parse_driver('file1.c', driver1)
+        self.assertIn(name, scan._drivers)
+        drv1 = scan._drivers[name]
+
+        prop = FakeProp()
+        prop.name = 'compatible'
+        prop.value = 'nvidia,tegra114-i2c'
+        node = FakeNode()
+        node.name = 'testing'
+        node.props = {'compatible': prop}
+
+        # get_normalized_compat_name() uses this to check for root node
+        node.parent = FakeNode()
+
+        return scan, drv1, driver2, node
+
+    def test_dup_drivers(self):
+        """Test handling of duplicate drivers"""
+        name = 'nvidia_tegra114_i2c'
+        scan, drv1, driver2, node = self.setup_dup_drivers(name)
+        self.assertEqual('', drv1.phase)
+
+        # The driver should not have a duplicate yet
+        self.assertEqual([], drv1.dups)
+
+        scan._parse_driver('file2.c', driver2)
+
+        # The first driver should now be a duplicate of the second
+        drv2 = scan._drivers[name]
+        self.assertEqual('', drv2.phase)
+        self.assertEqual(1, len(drv2.dups))
+        self.assertEqual([drv1], drv2.dups)
+
+        # There is no way to distinguish them, so we should expect a warning
+        self.assertTrue(drv2.warn_dups)
+
+        # We should see a warning
+        with test_util.capture_sys_output() as (stdout, _):
+            scan.mark_used([node])
+        self.assertEqual(
+            "Warning: Duplicate driver name 'nvidia_tegra114_i2c' (orig=file2.c, dups=file1.c)",
+            stdout.getvalue().strip())
+
+    def test_dup_drivers_phase(self):
+        """Test handling of duplicate drivers but with different phases"""
+        name = 'nvidia_tegra114_i2c'
+        scan, drv1, driver2, node = self.setup_dup_drivers(name, 'spl')
+        scan._parse_driver('file2.c', driver2)
+        self.assertEqual('spl', drv1.phase)
+
+        # The second driver should now be a duplicate of the second
+        self.assertEqual(1, len(drv1.dups))
+        drv2 = drv1.dups[0]
+
+        # The phase is different, so we should not warn of dups
+        self.assertFalse(drv1.warn_dups)
+
+        # We should not see a warning
+        with test_util.capture_sys_output() as (stdout, _):
+            scan.mark_used([node])
+        self.assertEqual('', stdout.getvalue().strip())
+
+    def test_sequence(self):
+        """Test assignment of sequence numnbers"""
+        scan = src_scan.Scanner(None, None, '')
+        node = FakeNode()
+        uc = src_scan.UclassDriver('UCLASS_I2C')
+        node.uclass = uc
+        node.driver = True
+        node.seq = -1
+        node.path = 'mypath'
+        uc.alias_num_to_node[2] = node
+
+        # This should assign 3 (after the 2 that exists)
+        seq = scan.assign_seq(node)
+        self.assertEqual(3, seq)
+        self.assertEqual({'mypath': 3}, uc.alias_path_to_num)
+        self.assertEqual({2: node, 3: node}, uc.alias_num_to_node)
diff --git a/tools/fdtgrep.c b/tools/fdtgrep.c
index e4112b8..db51246 100644
--- a/tools/fdtgrep.c
+++ b/tools/fdtgrep.c
@@ -213,7 +213,7 @@
 	} else {
 		printf(" = [");
 		for (i = 0; i < len; i++)
-			printf("%02x%s", *p++, i < len - 1 ? " " : "");
+			printf("%02x%s", (unsigned char)*p++, i < len - 1 ? " " : "");
 		printf("]");
 	}
 }
diff --git a/tools/imx8image.c b/tools/imx8image.c
index 133780f..fa8f227 100644
--- a/tools/imx8image.c
+++ b/tools/imx8image.c
@@ -365,7 +365,7 @@
 	struct stat sbuf;
 	unsigned char *ptr;
 	int tail;
-	int zero = 0;
+	uint64_t zero = 0;
 	uint8_t zeros[4096];
 	int size, ret;
 
diff --git a/tools/imx8mimage.c b/tools/imx8mimage.c
index 9985b95..11e40cc 100644
--- a/tools/imx8mimage.c
+++ b/tools/imx8mimage.c
@@ -248,7 +248,7 @@
 	struct stat sbuf;
 	unsigned char *ptr;
 	int tail;
-	int zero = 0;
+	uint64_t zero = 0;
 	uint8_t zeros[4096];
 	int size, ret;
 
diff --git a/tools/logos/engicam.bmp b/tools/logos/engicam.bmp
old mode 100755
new mode 100644
Binary files differ
diff --git a/tools/moveconfig.py b/tools/moveconfig.py
index 9514d9a..1ac30c0 100755
--- a/tools/moveconfig.py
+++ b/tools/moveconfig.py
@@ -12,6 +12,10 @@
 
 This tool intends to help this tremendous work.
 
+Installing
+----------
+
+You may need to install 'python3-asteval' for the 'asteval' module.
 
 Usage
 -----
@@ -573,7 +577,11 @@
     """
     pattern = re.compile(r'^\s*#\s*if.*$\n^\s*#\s*endif.*$\n*', flags=re.M)
     with open(header_path) as f:
-        data = f.read()
+        try:
+            data = f.read()
+        except UnicodeDecodeError as e:
+            print("Failed on file %s': %s" % (header_path, e))
+            return
 
     new_data = pattern.sub('\n', data)
 
@@ -596,7 +604,11 @@
       options: option flags.
     """
     with open(header_path) as f:
-        lines = f.readlines()
+        try:
+            lines = f.readlines()
+        except UnicodeDecodeError as e:
+            print("Failed on file %s': %s" % (header_path, e))
+            return
 
     matched = []
     for i, line in enumerate(lines):
diff --git a/tools/mtk_image.c b/tools/mtk_image.c
index bde1e5d..418c5fd 100644
--- a/tools/mtk_image.c
+++ b/tools/mtk_image.c
@@ -243,8 +243,13 @@
 	}
 };
 
+/* Indicates whether we're generating or verifying */
+static bool img_gen;
+static uint32_t img_size;
+
 /* Image type selected by user */
 static enum brlyt_img_type hdr_media;
+static uint32_t hdr_offset;
 static int use_lk_hdr;
 static bool is_arm64_image;
 
@@ -275,6 +280,7 @@
 
 	/* User passed arguments from image name */
 	static const char *media = "";
+	static const char *hdr_offs = "";
 	static const char *nandinfo = "";
 	static const char *lk = "";
 	static const char *arm64_param = "";
@@ -317,6 +323,9 @@
 			if (!strcmp(key, "media"))
 				media = val;
 
+			if (!strcmp(key, "hdroffset"))
+				hdr_offs = val;
+
 			if (!strcmp(key, "nandinfo"))
 				nandinfo = val;
 
@@ -359,6 +368,10 @@
 		}
 	}
 
+	/* parse device header offset */
+	if (hdr_offs && hdr_offs[0])
+		hdr_offset = strtoul(hdr_offs, NULL, 0);
+
 	if (arm64_param && arm64_param[0] == '1')
 		is_arm64_image = true;
 
@@ -422,6 +435,7 @@
 static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
 {
 	union gen_boot_header *gbh = (union gen_boot_header *)ptr;
+	uint32_t gfh_offset, total_size, devh_size;
 	struct brom_layout_header *bh;
 	struct gfh_header *gfh;
 	const char *bootmedia;
@@ -453,7 +467,32 @@
 	    le32_to_cpu(bh->type) != BRLYT_TYPE_SDMMC))
 		return -1;
 
-	gfh = (struct gfh_header *)(ptr + le32_to_cpu(bh->header_size));
+	devh_size = sizeof(struct gen_device_header);
+
+	if (img_gen) {
+		gfh_offset = devh_size;
+	} else {
+		gfh_offset = le32_to_cpu(bh->header_size);
+
+		if (gfh_offset + sizeof(struct gfh_header) > img_size) {
+			/*
+			 * This may happen if the hdr_offset used to generate
+			 * this image is not zero.
+			 * Since device header size is not fixed, we can't
+			 * cover all possible cases.
+			 * Assuming the image is valid only if the real
+			 * device header size equals to devh_size.
+			 */
+			total_size = le32_to_cpu(bh->total_size);
+
+			if (total_size - gfh_offset > img_size - devh_size)
+				return -1;
+
+			gfh_offset = devh_size;
+		}
+	}
+
+	gfh = (struct gfh_header *)(ptr + gfh_offset);
 
 	if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
 		return -1;
@@ -549,6 +588,8 @@
 	if (le32_to_cpu(lk->magic) == LK_PART_MAGIC)
 		return 0;
 
+	img_size = image_size;
+
 	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
 		return mtk_image_verify_nand_header(ptr, 0);
 	else
@@ -682,8 +723,8 @@
 
 	/* BRLYT header */
 	put_brom_layout_header(&hdr->brlyt, hdr_media);
-	hdr->brlyt.header_size = cpu_to_le32(sizeof(struct gen_device_header));
-	hdr->brlyt.total_size = cpu_to_le32(filesize);
+	hdr->brlyt.header_size = cpu_to_le32(hdr_offset + sizeof(*hdr));
+	hdr->brlyt.total_size = cpu_to_le32(hdr_offset + filesize);
 	hdr->brlyt.header_size_2 = hdr->brlyt.header_size;
 	hdr->brlyt.total_size_2 = hdr->brlyt.total_size;
 
@@ -747,6 +788,9 @@
 		return;
 	}
 
+	img_gen = true;
+	img_size = sbuf->st_size;
+
 	if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
 		mtk_image_set_nand_header(ptr, sbuf->st_size, params->addr);
 	else
diff --git a/tools/patman/README b/tools/patman/README
index 6b80663..53f55ce 100644
--- a/tools/patman/README
+++ b/tools/patman/README
@@ -136,17 +136,17 @@
 
 First do a dry run:
 
-$ ./tools/patman/patman -n
+$ ./tools/patman/patman send -n
 
 If it can't detect the upstream branch, try telling it how many patches
 there are in your series:
 
-$ ./tools/patman/patman -n -c5
+$ ./tools/patman/patman -c5 send -n
 
 This will create patch files in your current directory and tell you who
 it is thinking of sending them to. Take a look at the patch files.
 
-$ ./tools/patman/patman -n -c5 -s1
+$ ./tools/patman/patman -c5 -s1 send -n
 
 Similar to the above, but skip the first commit and take the next 5. This
 is useful if your top commit is for setting up testing.
@@ -433,12 +433,12 @@
 on the list. So you can tell patman to create and check some patches
 (skipping the first patch) with:
 
-    patman -s1 -n
+    patman -s1 send -n
 
 If you want to do all of them including the work-in-progress one, then
 (if you are tracking an upstream branch):
 
-    patman -n
+    patman send -n
 
 Let's say that patman reports an error in the second patch. Then:
 
@@ -450,7 +450,7 @@
 
 Now you have an updated patch series. To check it:
 
-    patman -s1 -n
+    patman -s1 send -n
 
 Let's say it is now clean and you want to send it. Now you need to set up
 the destination. So amend the top commit with:
@@ -485,7 +485,7 @@
 
 Now to send the patches, take off the -n flag:
 
-   patman -s1
+   patman -s1 send
 
 The patches will be created, shown in your editor, and then sent along with
 the cover letter. Note that patman's tags are automatically removed so that
diff --git a/tools/patman/func_test.py b/tools/patman/func_test.py
index 89072b1..450fe66 100644
--- a/tools/patman/func_test.py
+++ b/tools/patman/func_test.py
@@ -186,7 +186,7 @@
             - Commit-notes
         """
         process_tags = True
-        ignore_bad_tags = True
+        ignore_bad_tags = False
         stefan = b'Stefan Br\xc3\xbcns <stefan.bruens@rwth-aachen.de>'.decode('utf-8')
         rick = 'Richard III <richard@palace.gov>'
         mel = b'Lord M\xc3\xablchett <clergy@palace.gov>'.decode('utf-8')
diff --git a/tools/patman/gitutil.py b/tools/patman/gitutil.py
index bf1271d..5e4c112 100644
--- a/tools/patman/gitutil.py
+++ b/tools/patman/gitutil.py
@@ -345,7 +345,7 @@
     else:
        return None, files
 
-def BuildEmailList(in_list, tag=None, alias=None, raise_on_error=True):
+def BuildEmailList(in_list, tag=None, alias=None, warn_on_error=True):
     """Build a list of email addresses based on an input list.
 
     Takes a list of email addresses and aliases, and turns this into a list
@@ -359,7 +359,7 @@
         in_list:        List of aliases/email addresses
         tag:            Text to put before each address
         alias:          Alias dictionary
-        raise_on_error: True to raise an error when an alias fails to match,
+        warn_on_error: True to raise an error when an alias fails to match,
                 False to just print a message.
 
     Returns:
@@ -382,7 +382,7 @@
     quote = '"' if tag and tag[0] == '-' else ''
     raw = []
     for item in in_list:
-        raw += LookupEmail(item, alias, raise_on_error=raise_on_error)
+        raw += LookupEmail(item, alias, warn_on_error=warn_on_error)
     result = []
     for item in raw:
         if not item in result:
@@ -416,7 +416,7 @@
 
     return True
 
-def EmailPatches(series, cover_fname, args, dry_run, raise_on_error, cc_fname,
+def EmailPatches(series, cover_fname, args, dry_run, warn_on_error, cc_fname,
         self_only=False, alias=None, in_reply_to=None, thread=False,
         smtp_server=None):
     """Email a patch series.
@@ -426,8 +426,8 @@
         cover_fname: filename of cover letter
         args: list of filenames of patch files
         dry_run: Just return the command that would be run
-        raise_on_error: True to raise an error when an alias fails to match,
-                False to just print a message.
+        warn_on_error: True to print a warning when an alias fails to match,
+                False to ignore it.
         cc_fname: Filename of Cc file for per-commit Cc
         self_only: True to just email to yourself as a test
         in_reply_to: If set we'll pass this to git as --in-reply-to.
@@ -475,7 +475,7 @@
     # Restore argv[0] since we clobbered it.
     >>> sys.argv[0] = _old_argv0
     """
-    to = BuildEmailList(series.get('to'), '--to', alias, raise_on_error)
+    to = BuildEmailList(series.get('to'), '--to', alias, warn_on_error)
     if not to:
         git_config_to = command.Output('git', 'config', 'sendemail.to',
                                        raise_on_error=False)
@@ -487,9 +487,9 @@
                   "git config sendemail.to u-boot@lists.denx.de")
             return
     cc = BuildEmailList(list(set(series.get('cc')) - set(series.get('to'))),
-                        '--cc', alias, raise_on_error)
+                        '--cc', alias, warn_on_error)
     if self_only:
-        to = BuildEmailList([os.getenv('USER')], '--to', alias, raise_on_error)
+        to = BuildEmailList([os.getenv('USER')], '--to', alias, warn_on_error)
         cc = []
     cmd = ['git', 'send-email', '--annotate']
     if smtp_server:
@@ -511,7 +511,7 @@
     return cmdstr
 
 
-def LookupEmail(lookup_name, alias=None, raise_on_error=True, level=0):
+def LookupEmail(lookup_name, alias=None, warn_on_error=True, level=0):
     """If an email address is an alias, look it up and return the full name
 
     TODO: Why not just use git's own alias feature?
@@ -519,8 +519,8 @@
     Args:
         lookup_name: Alias or email address to look up
         alias: Dictionary containing aliases (None to use settings default)
-        raise_on_error: True to raise an error when an alias fails to match,
-                False to just print a message.
+        warn_on_error: True to print a warning when an alias fails to match,
+                False to ignore it.
 
     Returns:
         tuple:
@@ -547,18 +547,16 @@
     >>> LookupEmail('all', alias)
     ['f.bloggs@napier.co.nz', 'j.bloggs@napier.co.nz', 'm.poppins@cloud.net']
     >>> LookupEmail('odd', alias)
-    Traceback (most recent call last):
-    ...
-    ValueError: Alias 'odd' not found
+    Alias 'odd' not found
+    []
     >>> LookupEmail('loop', alias)
     Traceback (most recent call last):
     ...
     OSError: Recursive email alias at 'other'
-    >>> LookupEmail('odd', alias, raise_on_error=False)
-    Alias 'odd' not found
+    >>> LookupEmail('odd', alias, warn_on_error=False)
     []
     >>> # In this case the loop part will effectively be ignored.
-    >>> LookupEmail('loop', alias, raise_on_error=False)
+    >>> LookupEmail('loop', alias, warn_on_error=False)
     Recursive email alias at 'other'
     Recursive email alias at 'john'
     Recursive email alias at 'mary'
@@ -576,7 +574,7 @@
     out_list = []
     if level > 10:
         msg = "Recursive email alias at '%s'" % lookup_name
-        if raise_on_error:
+        if warn_on_error:
             raise OSError(msg)
         else:
             print(col.Color(col.RED, msg))
@@ -585,18 +583,15 @@
     if lookup_name:
         if not lookup_name in alias:
             msg = "Alias '%s' not found" % lookup_name
-            if raise_on_error:
-                raise ValueError(msg)
-            else:
+            if warn_on_error:
                 print(col.Color(col.RED, msg))
-                return out_list
+            return out_list
         for item in alias[lookup_name]:
-            todo = LookupEmail(item, alias, raise_on_error, level + 1)
+            todo = LookupEmail(item, alias, warn_on_error, level + 1)
             for new_item in todo:
                 if not new_item in out_list:
                     out_list.append(new_item)
 
-    #print("No match for alias '%s'" % lookup_name)
     return out_list
 
 def GetTopLevel():
diff --git a/tools/patman/main.py b/tools/patman/main.py
index c4e4d80..04e37a5 100755
--- a/tools/patman/main.py
+++ b/tools/patman/main.py
@@ -9,6 +9,7 @@
 from argparse import ArgumentParser
 import os
 import re
+import shutil
 import sys
 import traceback
 import unittest
@@ -68,7 +69,8 @@
 send.add_argument('-r', '--in-reply-to', type=str, action='store',
                   help="Message ID that this series is in reply to")
 send.add_argument('-t', '--ignore-bad-tags', action='store_true',
-                  default=False, help='Ignore bad tags / aliases')
+                  default=False,
+                  help='Ignore bad tags / aliases (default=warn)')
 send.add_argument('-T', '--thread', action='store_true', dest='thread',
                   default=False, help='Create patches as a single thread')
 send.add_argument('--cc-cmd', dest='cc_cmd', type=str, action='store',
@@ -170,12 +172,17 @@
     elif args.full_help:
         pager = os.getenv('PAGER')
         if not pager:
+            pager = shutil.which('less')
+        if not pager:
             pager = 'more'
         fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
                              'README')
         command.Run(pager, fname)
 
     else:
+        # If we are not processing tags, no need to warning about bad ones
+        if not args.process_tags:
+            args.ignore_bad_tags = True
         control.send(args)
 
 # Check status of patches in patchwork
diff --git a/tools/patman/patchstream.py b/tools/patman/patchstream.py
index cdcd50a..a44cd86 100644
--- a/tools/patman/patchstream.py
+++ b/tools/patman/patchstream.py
@@ -133,8 +133,8 @@
             ValueError: Warning is generated with no commit associated
         """
         if not self.commit:
-            raise ValueError('Warning outside commit: %s' % warn)
-        if warn not in self.commit.warn:
+            print('Warning outside commit: %s' % warn)
+        elif warn not in self.commit.warn:
             self.commit.warn.append(warn)
 
     def _add_to_series(self, line, name, value):
diff --git a/tools/patman/series.py b/tools/patman/series.py
index 41a1173..8ae218d 100644
--- a/tools/patman/series.py
+++ b/tools/patman/series.py
@@ -234,7 +234,7 @@
             str = 'Change log exists, but no version is set'
             print(col.Color(col.RED, str))
 
-    def MakeCcFile(self, process_tags, cover_fname, raise_on_error,
+    def MakeCcFile(self, process_tags, cover_fname, warn_on_error,
                    add_maintainers, limit):
         """Make a cc file for us to use for per-commit Cc automation
 
@@ -243,8 +243,8 @@
         Args:
             process_tags: Process tags as if they were aliases
             cover_fname: If non-None the name of the cover letter.
-            raise_on_error: True to raise an error when an alias fails to match,
-                False to just print a message.
+            warn_on_error: True to print a warning when an alias fails to match,
+                False to ignore it.
             add_maintainers: Either:
                 True/False to call the get_maintainers to CC maintainers
                 List of maintainers to include (for testing)
@@ -261,9 +261,9 @@
             cc = []
             if process_tags:
                 cc += gitutil.BuildEmailList(commit.tags,
-                                               raise_on_error=raise_on_error)
+                                               warn_on_error=warn_on_error)
             cc += gitutil.BuildEmailList(commit.cc_list,
-                                           raise_on_error=raise_on_error)
+                                           warn_on_error=warn_on_error)
             if type(add_maintainers) == type(cc):
                 cc += add_maintainers
             elif add_maintainers:
diff --git a/tools/patman/tools.py b/tools/patman/tools.py
index 10997e4..e5f391b 100644
--- a/tools/patman/tools.py
+++ b/tools/patman/tools.py
@@ -130,8 +130,12 @@
         allow_missing: True if the filename can be missing
 
     Returns:
-        The full path of the filename, within the input directory, or
-        None on error
+        fname, if indir is None;
+        full path of the filename, within the input directory;
+        None, if file is missing and allow_missing is True
+
+    Raises:
+        ValueError if file is missing and allow_missing is False
     """
     if not indir or fname[:1] == '/':
         return fname