Merge tag 'efi-2019-10-rc1-2' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi

Pull request for UEFI sub-system for v2019.10-rc1 (2)

* Implement the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
* Address errors of type -Werror=address-of-packed-member when building
  with GCC9.1
* Fix an error when adding memory add addres 0x00000000.
* Rework some code comments for Sphinx compliance.
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..e27d86f
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,361 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+# Grab our configured image.  The source for this is found at:
+# https://gitlab.denx.de/u-boot/gitlab-ci-runner
+image: trini/u-boot-gitlab-ci-runner:xenial-20190222-24April2019
+
+# We run some tests in different order, to catch some failures quicker.
+stages:
+  - test.py
+  - testsuites
+  - world build
+
+.buildman_and_testpy_template: &buildman_and_testpy_dfn
+  tags: [ 'all' ]
+  stage: test.py
+  before_script:
+    # Clone uboot-test-hooks
+    - git clone --depth=1 git://github.com/swarren/uboot-test-hooks.git /tmp/uboot-test-hooks
+    - ln -s travis-ci /tmp/uboot-test-hooks/bin/`hostname`
+    - ln -s travis-ci /tmp/uboot-test-hooks/py/`hostname`
+    - virtualenv /tmp/venv
+    - . /tmp/venv/bin/activate
+    - pip install pytest==2.8.7
+    - pip install python-subunit
+    - grub-mkimage -o ~/grub_x86.efi -O i386-efi normal  echo lsefimmap lsefi lsefisystab efinet tftp minicmd
+    - grub-mkimage -o ~/grub_x64.efi -O x86_64-efi normal  echo lsefimmap lsefi lsefisystab efinet tftp minicmd
+    - mkdir ~/grub2-arm
+    - ( cd ~/grub2-arm; wget -O - http://download.opensuse.org/ports/armv7hl/distribution/leap/42.2/repo/oss/suse/armv7hl/grub2-arm-efi-2.02~beta2-87.1.armv7hl.rpm | rpm2cpio | cpio -di )
+    - mkdir ~/grub2-arm64
+    - ( cd ~/grub2-arm64; wget -O - http://download.opensuse.org/ports/aarch64/distribution/leap/42.2/repo/oss/suse/aarch64/grub2-arm64-efi-2.02~beta2-87.1.aarch64.rpm | rpm2cpio | cpio -di )
+    - if [[ "${QEMU_TARGET}" != "" ]]; then
+        git clone git://git.qemu.org/qemu.git /tmp/qemu;
+        pushd /tmp/qemu;
+        git submodule update --init dtc &&
+        git checkout ${QEMU_VERSION} &&
+        ./configure --prefix=/tmp/qemu-install --target-list=${QEMU_TARGET} &&
+        make -j$(nproc) all install;
+        popd;
+      fi
+  after_script:
+    - rm -rf ~/grub2* /tmp/uboot-test-hooks /tmp/qemu /tmp/venv
+  script:
+    # From buildman, exit code 129 means warnings only.  If we've been asked to
+    # use clang only do one configuration.
+    - if [[ "${BUILDMAN}" != "" ]]; then
+        ret=0;
+        tools/buildman/buildman -P -E ${BUILDMAN} ${OVERRIDE}|| ret=$?;
+        if [[ $ret -ne 0 && $ret -ne 129 ]]; then
+          tools/buildman/buildman -sdeP ${BUILDMAN};
+          exit $ret;
+        fi;
+      fi
+    # "not a_test_which_does_not_exist" is a dummy -k parameter which will
+    # never prevent any test from running. That way, we can always pass
+    # "-k something" even when $TEST_PY_TEST_SPEC doesnt need a custom
+    # value.
+    - export UBOOT_TRAVIS_BUILD_DIR=`cd .. && pwd`/.bm-work/${TEST_PY_BD};
+      export PATH=/tmp/qemu-install/bin:/tmp/uboot-test-hooks/bin:/usr/bin:/bin;
+      export PYTHONPATH=/tmp/uboot-test-hooks/py/travis-ci;
+      if [[ "${TEST_PY_BD}" != "" ]]; then
+        ./test/py/test.py --bd ${TEST_PY_BD} ${TEST_PY_ID}
+          -k "${TEST_PY_TEST_SPEC:-not a_test_which_does_not_exist}"
+          --build-dir "$UBOOT_TRAVIS_BUILD_DIR";
+        ret=$?;
+        if [[ $ret -ne 0 ]]; then
+          exit $ret;
+        fi;
+      fi;
+
+build all 32bit ARM plaforms:
+  tags: [ 'all' ]
+  stage: world build
+  script:
+    - ret=0;
+     ./tools/buildman/buildman -P -E arm -x aarch64 || ret=$?;
+     if [[ $ret -ne 0 && $ret -ne 129 ]]; then
+       ./tools/buildman/buildman -sdeP;
+       exit $ret;
+     fi;
+
+build all 64bit ARM plaforms:
+  tags: [ 'all' ]
+  stage: world build
+  script:
+    - virtualenv /tmp/venv
+    - . /tmp/venv/bin/activate
+    - pip install pyelftools
+    - ret=0;
+     ./tools/buildman/buildman -P -E aarch64 || ret=$?;
+     if [[ $ret -ne 0 && $ret -ne 129 ]]; then
+       ./tools/buildman/buildman -sdeP;
+       exit $ret;
+     fi;
+
+build all PowerPC plaforms:
+  tags: [ 'all' ]
+  stage: world build
+  script:
+    - ret=0;
+     ./tools/buildman/buildman -P -E powerpc || ret=$?;
+     if [[ $ret -ne 0 && $ret -ne 129 ]]; then
+       ./tools/buildman/buildman -sdeP;
+       exit $ret;
+     fi;
+
+build all other plaforms:
+  tags: [ 'all' ]
+  stage: world build
+  script:
+    - ret=0;
+     ./tools/buildman/buildman -P -E -x arm,powerpc || ret=$?;
+     if [[ $ret -ne 0 && $ret -ne 129 ]]; then
+       ./tools/buildman/buildman -sdeP;
+       exit $ret;
+     fi;
+
+# QA jobs for code analytics
+# static code analysis with cppcheck (we can add --enable=all later)
+cppcheck:
+  tags: [ 'all' ]
+  stage: testsuites
+  script:
+    - cppcheck --force --quiet --inline-suppr .
+
+# search for TODO within source tree
+grep TODO/FIXME/HACK:
+  tags: [ 'all' ]
+  stage: testsuites
+  script:
+    - grep -r TODO .
+    - grep -r FIXME .
+    # search for HACK within source tree and ignore HACKKIT board
+    - grep -r HACK . | grep -v HACKKIT
+
+# 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)
+
+# Run various tool tests
+Run patman testsuite:
+  tags: [ 'all' ]
+  stage: testsuites
+  script:
+    - git config --global user.name "GitLab CI Runner"
+    - git config --global user.email trini@konsulko.com
+    - ./tools/patman/patman --test
+
+Run buildman testsuite:
+  tags: [ 'all' ]
+  stage: testsuites
+  script:
+    - ./tools/buildman/buildman -t
+
+Run binman and dtoc testsuite:
+  tags: [ 'all' ]
+  stage: testsuites
+  script:
+    - export UBOOT_TRAVIS_BUILD_DIR=`cd .. && pwd`/.bm-work/sandbox_spl;
+      ./tools/buildman/buildman -P sandbox_spl && 
+     export PYTHONPATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc/pylibfdt";
+     export PATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc:${PATH}";
+     ./tools/binman/binman -t &&
+     ./tools/dtoc/dtoc -t
+
+# Test sandbox with test.py
+sandbox test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "sandbox"
+    BUILDMAN: "^sandbox$"
+  <<: *buildman_and_testpy_dfn
+
+sandbox_spl test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "sandbox_spl"
+    BUILDMAN: "^sandbox_spl$"
+    TEST_PY_TEST_SPEC: "test_ofplatdata"
+  <<: *buildman_and_testpy_dfn
+
+evb-ast2500 test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "evb-ast2500"
+    TEST_PY_ID: "--id qemu"
+    QEMU_TARGET: "arm-softmmu"
+    QEMU_VERSION: "506179e42112be77bfd071f050b15762d3b2cd43"
+    BUILDMAN: "^evb-ast2500$"
+  <<: *buildman_and_testpy_dfn
+
+sandbox_flattree test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "sandbox_flattree"
+    BUILDMAN: "^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"
+    QEMU_TARGET: "arm-softmmu"
+    QEMU_VERSION: "v3.0.0"
+    BUILDMAN: "^vexpress_ca15_tc2$"
+  <<: *buildman_and_testpy_dfn
+
+vexpress_ca9x4 test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "vexpress_ca9x4"
+    TEST_PY_ID: "--id qemu"
+    QEMU_TARGET: "arm-softmmu"
+    BUILDMAN: "^vexpress_ca9x4$"
+  <<: *buildman_and_testpy_dfn
+
+integratorcp_cm926ejs test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "integratorcp_cm926ejs"
+    TEST_PY_TEST_SPEC: "not sleep"
+    TEST_PY_ID: "--id qemu"
+    QEMU_TARGET: "arm-softmmu"
+    BUILDMAN: "^integratorcp_cm926ejs$"
+  <<: *buildman_and_testpy_dfn
+
+qemu_arm test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "qemu_arm"
+    TEST_PY_TEST_SPEC: "not sleep"
+    QEMU_TARGET: "arm-softmmu"
+    BUILDMAN: "^qemu_arm$"
+  <<: *buildman_and_testpy_dfn
+
+qemu_arm64 test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "qemu_arm64"
+    TEST_PY_TEST_SPEC: "not sleep"
+    QEMU_TARGET: "aarch64-softmmu"
+    BUILDMAN: "^qemu_arm64$"
+  <<: *buildman_and_testpy_dfn
+
+qemu_mips test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "qemu_mips"
+    TEST_PY_TEST_SPEC: "not sleep"
+    QEMU_TARGET: "mips-softmmu"
+    BUILDMAN: "^qemu_mips$"
+    TOOLCHAIN: "mips"
+  <<: *buildman_and_testpy_dfn
+
+qemu_mipsel test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "qemu_mipsel"
+    TEST_PY_TEST_SPEC: "not sleep"
+    QEMU_TARGET: "mipsel-softmmu"
+    BUILDMAN: "^qemu_mipsel$"
+    TOOLCHAIN: "mips"
+  <<: *buildman_and_testpy_dfn
+
+qemu_mips64 test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "qemu_mips64"
+    TEST_PY_TEST_SPEC: "not sleep"
+    QEMU_TARGET: "mips64-softmmu"
+    BUILDMAN: "^qemu_mips64$"
+    TOOLCHAIN: "mips"
+  <<: *buildman_and_testpy_dfn
+
+qemu_mips64el test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "qemu_mips64el"
+    TEST_PY_TEST_SPEC: "not sleep"
+    QEMU_TARGET: "mips64el-softmmu"
+    BUILDMAN: "^qemu_mips64el$"
+    TOOLCHAIN: "mips"
+  <<: *buildman_and_testpy_dfn
+
+qemu-ppce500 test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "qemu-ppce500"
+    TEST_PY_TEST_SPEC: "not sleep"
+    QEMU_TARGET: "ppc-softmmu"
+    BUILDMAN: "^qemu-ppce500$"
+    TOOLCHAIN: "powerpc"
+  <<: *buildman_and_testpy_dfn
+
+qemu-x86 test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "qemu-x86"
+    TEST_PY_TEST_SPEC: "not sleep"
+    QEMU_TARGET: "i386-softmmu"
+    BUILDMAN: "^qemu-x86$"
+    TOOLCHAIN: "i386"
+  <<: *buildman_and_testpy_dfn
+
+qemu-x86_64 test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "qemu-x86_64"
+    TEST_PY_TEST_SPEC: "not sleep"
+    QEMU_TARGET: "x86_64-softmmu"
+    BUILDMAN: "^qemu-x86_64$"
+    TOOLCHAIN: "i386"
+  <<: *buildman_and_testpy_dfn
+
+zynq_zc702 test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "zynq_zc702"
+    TEST_PY_TEST_SPEC: "not sleep"
+    QEMU_TARGET: "arm-softmmu"
+    TEST_PY_ID: "--id qemu"
+    BUILDMAN: "^zynq_zc702$"
+  <<: *buildman_and_testpy_dfn
+
+xilinx_versal_virt test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "xilinx_versal_virt"
+    TEST_PY_TEST_SPEC: "not sleep"
+    QEMU_TARGET: "aarch64-softmmu"
+    TEST_PY_ID: "--id qemu"
+    BUILDMAN: "^xilinx_versal_virt$"
+  <<: *buildman_and_testpy_dfn
+
+xtfpga test.py:
+  tags: [ 'all' ]
+  variables:
+    TEST_PY_BD: "xtfpga"
+    TEST_PY_TEST_SPEC: "not sleep"
+    QEMU_TARGET: "xtensa-softmmu"
+    TEST_PY_ID: "--id qemu"
+    BUILDMAN: "^xtfpga$"
+    TOOLCHAIN: "xtensa-dc233c-elf"
+  <<: *buildman_and_testpy_dfn
diff --git a/.travis.yml b/.travis.yml
index c21bbbb..f20268b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -365,13 +365,11 @@
     - name: "test/py sandbox"
       env:
         - TEST_PY_BD="sandbox"
-          TEST_PY_TEST_SPEC="not pci"
           BUILDMAN="^sandbox$"
           TOOLCHAIN="i386"
     - name: "test/py sandbox with clang"
       env:
         - TEST_PY_BD="sandbox"
-          TEST_PY_TEST_SPEC="not pci"
           BUILDMAN="^sandbox$"
           OVERRIDE="clang-7"
     - name: "test/py sandbox_spl"
@@ -384,9 +382,15 @@
     - name: "test/py sandbox_flattree"
       env:
         - TEST_PY_BD="sandbox_flattree"
-          TEST_PY_TEST_SPEC="not pci"
           BUILDMAN="^sandbox_flattree$"
           TOOLCHAIN="i386"
+    - name: "test/py evb-ast2500"
+      env:
+        - TEST_PY_BD="evb-ast2500"
+          TEST_PY_ID="--id qemu"
+          QEMU_TARGET="arm-softmmu"
+          QEMU_VERSION="506179e42112be77bfd071f050b15762d3b2cd43"
+          BUILDMAN="^evb-ast2500$"
     - name: "test/py vexpress_ca15_tc2"
       env:
         - TEST_PY_BD="vexpress_ca15_tc2"
diff --git a/MAINTAINERS b/MAINTAINERS
index bc67c49..a72ccd0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -311,6 +311,7 @@
 F:	drivers/power/regulator/stm32-vrefbuf.c
 F:	drivers/power/regulator/stpmic1.c
 F:	drivers/ram/stm32mp1/
+F:	drivers/remoteproc/stm32_copro.c
 F:	drivers/misc/stm32_rcc.c
 F:	drivers/reset/stm32-reset.c
 F:	drivers/spi/stm32_qspi.c
@@ -606,7 +607,7 @@
 F:	drivers/mtd/nand/raw/
 
 NDS32
-M:	Macpaul Lin <macpaul@andestech.com>
+M:	Rick Chen <rick@andestech.com>
 S:	Maintained
 T:	git https://gitlab.denx.de/u-boot/custodians/u-boot-nds32.git
 F:	arch/nds32/
@@ -616,6 +617,7 @@
 S:	Maintained
 T:	git https://gitlab.denx.de/u-boot/custodians/u-boot-net.git
 F:	drivers/net/
+F:	include/net.h
 F:	net/
 
 NIOS
diff --git a/arch/Kconfig b/arch/Kconfig
index a946af8..949eb28 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -125,6 +125,7 @@
 	imply PCH
 	imply PHYLIB
 	imply DM_MDIO
+	imply DM_MDIO_MUX
 
 config SH
 	bool "SuperH architecture"
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 5ab9cbe..51d4ace 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -840,6 +840,7 @@
 
 config ARCH_QEMU
 	bool "QEMU Virtual Platform"
+	select ARCH_SUPPORT_TFABOOT
 	select DM
 	select DM_SERIAL
 	select OF_CONTROL
@@ -936,6 +937,7 @@
 	select SPL_STACK_R if SPL
 	select SPL_SYS_MALLOC_SIMPLE if SPL
 	select SPL_SYS_THUMB_BUILD if !ARM64
+	select SUNXI_GPIO
 	select SYS_NS16550
 	select SYS_THUMB_BUILD if !ARM64
 	select USB if DISTRO_DEFAULTS
@@ -1099,6 +1101,7 @@
 	select ARCH_MISC_INIT
 	select ARM64
 	select ARMV8_MULTIENTRY
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_LATE_INIT
 	select SUPPORT_SPL
 	select FSL_DDR_INTERACTIVE if !SD_BOOT
@@ -1114,6 +1117,7 @@
 	select ARCH_MISC_INIT
 	select ARM64
 	select ARMV8_MULTIENTRY
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_LATE_INIT
 	select SUPPORT_SPL
 	imply SCSI
@@ -1132,6 +1136,7 @@
 	select ARCH_MISC_INIT
 	select ARM64
 	select ARMV8_MULTIENTRY
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_LATE_INIT
 	select SUPPORT_SPL
 	select FSL_DDR_BIST
@@ -1164,6 +1169,7 @@
 	select ARCH_MISC_INIT
 	select ARM64
 	select ARMV8_MULTIENTRY
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_LATE_INIT
 	help
 	  Support for NXP LX2160ARDB platform.
@@ -1177,6 +1183,7 @@
 	select ARCH_MISC_INIT
 	select ARM64
 	select ARMV8_MULTIENTRY
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_LATE_INIT
 	help
 	  Support for NXP LX2160AQDS platform.
@@ -1217,6 +1224,7 @@
 	bool "Support ls1012aqds"
 	select ARCH_LS1012A
 	select ARM64
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_LATE_INIT
 	help
 	  Support for Freescale LS1012AQDS platform.
@@ -1228,6 +1236,7 @@
 	bool "Support ls1012ardb"
 	select ARCH_LS1012A
 	select ARM64
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_LATE_INIT
 	imply SCSI
 	imply SCSI_AHCI
@@ -1241,6 +1250,7 @@
 	bool "Support ls1012a2g5rdb"
 	select ARCH_LS1012A
 	select ARM64
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_LATE_INIT
 	imply SCSI
 	help
@@ -1253,6 +1263,7 @@
 	bool "Support ls1012afrwy"
 	select ARCH_LS1012A
 	select ARM64
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_LATE_INIT
 	imply SCSI
 	imply SCSI_AHCI
@@ -1266,6 +1277,7 @@
 	bool "Support ls1012afrdm"
 	select ARCH_LS1012A
 	select ARM64
+	select ARCH_SUPPORT_TFABOOT
 	help
 	  Support for Freescale LS1012AFRDM platform.
 	  The LS1012A Freedom  board (FRDM) is a high-performance
@@ -1277,6 +1289,7 @@
 	select ARCH_LS1028A
 	select ARM64
 	select ARMV8_MULTIENTRY
+	select ARCH_SUPPORT_TFABOOT
 	help
 	  Support for Freescale LS1028AQDS platform
 	  The LS1028A Development System (QDS) is a high-performance
@@ -1288,6 +1301,7 @@
 	select ARCH_LS1028A
 	select ARM64
 	select ARMV8_MULTIENTRY
+	select ARCH_SUPPORT_TFABOOT
 	help
 	  Support for Freescale LS1028ARDB platform
 	  The LS1028A Development System (RDB) is a high-performance
@@ -1300,6 +1314,7 @@
 	select ARCH_MISC_INIT
 	select ARM64
 	select ARMV8_MULTIENTRY
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_LATE_INIT
 	select SUPPORT_SPL
 	select FSL_DDR_INTERACTIVE if !SD_BOOT
@@ -1358,6 +1373,7 @@
 	select ARCH_LS1043A
 	select ARM64
 	select ARMV8_MULTIENTRY
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_EARLY_INIT_F
 	select BOARD_LATE_INIT
 	select SUPPORT_SPL
@@ -1372,6 +1388,7 @@
 	select ARCH_LS1043A
 	select ARM64
 	select ARMV8_MULTIENTRY
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_EARLY_INIT_F
 	select BOARD_LATE_INIT
 	select SUPPORT_SPL
@@ -1383,6 +1400,7 @@
 	select ARCH_LS1046A
 	select ARM64
 	select ARMV8_MULTIENTRY
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_EARLY_INIT_F
 	select BOARD_LATE_INIT
 	select DM_SPI_FLASH if DM_SPI
@@ -1402,6 +1420,7 @@
 	select ARCH_LS1046A
 	select ARM64
 	select ARMV8_MULTIENTRY
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_EARLY_INIT_F
 	select BOARD_LATE_INIT
 	select DM_SPI_FLASH if DM_SPI
@@ -1421,6 +1440,7 @@
 	select ARCH_LS1046A
 	select ARM64
 	select ARMV8_MULTIENTRY
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_EARLY_INIT_F
 	select BOARD_LATE_INIT
 	select DM_SPI_FLASH if DM_SPI
@@ -1564,6 +1584,17 @@
 
 endchoice
 
+config ARCH_SUPPORT_TFABOOT
+	bool
+
+config TFABOOT
+	bool "Support for booting from TF-A"
+	depends on ARCH_SUPPORT_TFABOOT
+	default n
+	help
+	  Enabling this will make a U-Boot binary that is capable of being
+	  booted via TF-A.
+
 config TI_SECURE_DEVICE
 	bool "HS Device Type Support"
 	depends on ARCH_KEYSTONE || ARCH_OMAP2PLUS || ARCH_K3
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
index 3f6c983..5c32738 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
@@ -623,10 +623,3 @@
 	help
 	  For some SoC(such as LS1043A and LS1046A), USB and QE-HDLC multiplex use
 	  pins, select it when the pins are assigned to USB.
-
-config TFABOOT
-       bool "Support for booting from TFA"
-       default n
-       help
-         Enabling this will make a U-Boot binary that is capable of being
-         booted via TFA.
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 39cf4c3..f553507 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -482,6 +482,7 @@
 	sun8i-h2-plus-orangepi-r1.dtb \
 	sun8i-h2-plus-orangepi-zero.dtb \
 	sun8i-h3-bananapi-m2-plus.dtb \
+	sun8i-h3-beelink-x2.dtb \
 	sun8i-h3-libretech-all-h3-cc.dtb \
 	sun8i-h3-nanopi-m1.dtb \
 	sun8i-h3-nanopi-m1-plus.dtb \
diff --git a/arch/arm/dts/k3-am65-main.dtsi b/arch/arm/dts/k3-am65-main.dtsi
index adcd634..39fec03 100644
--- a/arch/arm/dts/k3-am65-main.dtsi
+++ b/arch/arm/dts/k3-am65-main.dtsi
@@ -69,4 +69,78 @@
 		clock-frequency = <48000000>;
 		current-speed = <115200>;
 	};
+
+	main_pmx0: pinmux@11c000 {
+		compatible = "pinctrl-single";
+		reg = <0x0 0x11c000 0x0 0x2e4>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0xffffffff>;
+	};
+
+	main_pmx1: pinmux@11c2e8 {
+		compatible = "pinctrl-single";
+		reg = <0x0 0x11c2e8 0x0 0x24>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0xffffffff>;
+	};
+
+	sdhci0: sdhci@4f80000 {
+		compatible = "ti,am654-sdhci-5.1";
+		reg = <0x0 0x4f80000 0x0 0x260>, <0x0 0x4f90000 0x0 0x134>;
+		power-domains = <&k3_pds 47>;
+		clocks = <&k3_clks 47 0>, <&k3_clks 47 1>;
+		clock-names = "clk_ahb", "clk_xin";
+		interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+		mmc-ddr-1_8v;
+		mmc-hs200-1_8v;
+		ti,otap-del-sel = <0x2>;
+		ti,trm-icp = <0x8>;
+		dma-coherent;
+	};
+
+	main_i2c0: i2c@2000000 {
+		compatible = "ti,am654-i2c", "ti,omap4-i2c";
+		reg = <0x0 0x2000000 0x0 0x100>;
+		interrupts = <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "fck";
+		clocks = <&k3_clks 110 1>;
+		power-domains = <&k3_pds 110>;
+	};
+
+	main_i2c1: i2c@2010000 {
+		compatible = "ti,am654-i2c", "ti,omap4-i2c";
+		reg = <0x0 0x2010000 0x0 0x100>;
+		interrupts = <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "fck";
+		clocks = <&k3_clks 111 1>;
+		power-domains = <&k3_pds 111>;
+	};
+
+	main_i2c2: i2c@2020000 {
+		compatible = "ti,am654-i2c", "ti,omap4-i2c";
+		reg = <0x0 0x2020000 0x0 0x100>;
+		interrupts = <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "fck";
+		clocks = <&k3_clks 112 1>;
+		power-domains = <&k3_pds 112>;
+	};
+
+	main_i2c3: i2c@2030000 {
+		compatible = "ti,am654-i2c", "ti,omap4-i2c";
+		reg = <0x0 0x2030000 0x0 0x100>;
+		interrupts = <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "fck";
+		clocks = <&k3_clks 113 1>;
+		power-domains = <&k3_pds 113>;
+	};
 };
diff --git a/arch/arm/dts/k3-am65-mcu.dtsi b/arch/arm/dts/k3-am65-mcu.dtsi
index 8c611d1..1fd0277 100644
--- a/arch/arm/dts/k3-am65-mcu.dtsi
+++ b/arch/arm/dts/k3-am65-mcu.dtsi
@@ -15,4 +15,15 @@
 			clock-frequency = <96000000>;
 			current-speed = <115200>;
 	};
+
+	mcu_i2c0: i2c@40b00000 {
+		compatible = "ti,am654-i2c", "ti,omap4-i2c";
+		reg = <0x0 0x40b00000 0x0 0x100>;
+		interrupts = <GIC_SPI 564 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "fck";
+		clocks = <&k3_clks 114 1>;
+		power-domains = <&k3_pds 114>;
+	};
 };
diff --git a/arch/arm/dts/k3-am65-wakeup.dtsi b/arch/arm/dts/k3-am65-wakeup.dtsi
index 1f591ef..1f85006 100644
--- a/arch/arm/dts/k3-am65-wakeup.dtsi
+++ b/arch/arm/dts/k3-am65-wakeup.dtsi
@@ -34,6 +34,14 @@
 		};
 	};
 
+	wkup_pmx0: pinmux@4301c000 {
+		compatible = "pinctrl-single";
+		reg = <0x4301c000 0x118>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0xffffffff>;
+	};
+
 	wkup_uart0: serial@42300000 {
 		compatible = "ti,am654-uart";
 		reg = <0x42300000 0x100>;
@@ -43,4 +51,15 @@
 		clock-frequency = <48000000>;
 		current-speed = <115200>;
 	};
+
+	wkup_i2c0: i2c@42120000 {
+		compatible = "ti,am654-i2c", "ti,omap4-i2c";
+		reg = <0x42120000 0x100>;
+		interrupts = <GIC_SPI 696 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "fck";
+		clocks = <&k3_clks 115 1>;
+		power-domains = <&k3_pds 115>;
+	};
 };
diff --git a/arch/arm/dts/k3-am65.dtsi b/arch/arm/dts/k3-am65.dtsi
index 9d1ed49..4727193 100644
--- a/arch/arm/dts/k3-am65.dtsi
+++ b/arch/arm/dts/k3-am65.dtsi
@@ -8,6 +8,7 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/pinctrl/k3.h>
 
 / {
 	model = "Texas Instruments K3 AM654 SoC";
@@ -22,6 +23,12 @@
 		serial2 = &main_uart0;
 		serial3 = &main_uart1;
 		serial4 = &main_uart2;
+		i2c0 = &wkup_i2c0;
+		i2c1 = &mcu_i2c0;
+		i2c2 = &main_i2c0;
+		i2c3 = &main_i2c1;
+		i2c4 = &main_i2c2;
+		i2c5 = &main_i2c3;
 	};
 
 	chosen { };
diff --git a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi
index 844a5cd..449b1dd 100644
--- a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi
+++ b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi
@@ -21,51 +21,21 @@
 &cbass_main{
 	u-boot,dm-spl;
 
-	main_pmx0: pinmux@11c000 {
-		compatible = "pinctrl-single";
-		reg = <0x0 0x11c000 0x0 0x2e4>;
-		#pinctrl-cells = <1>;
-		pinctrl-single,register-width = <32>;
-		pinctrl-single,function-mask = <0xffffffff>;
-	};
-
-	main_pmx1: pinmux@11c2e8 {
-		compatible = "pinctrl-single";
-		reg = <0x0 0x11c2e8 0x0 0x24>;
-		#pinctrl-cells = <1>;
-		pinctrl-single,register-width = <32>;
-		pinctrl-single,function-mask = <0xffffffff>;
-	};
-
-	sdhci0: sdhci@04F80000 {
-		compatible = "arasan,sdhci-5.1";
-		reg = <0x0 0x4F80000 0x0 0x1000>,
-		      <0x0 0x4F90000 0x0 0x400>;
-		clocks = <&k3_clks 47 1>;
-		power-domains = <&k3_pds 47>;
-		max-frequency = <25000000>;
-	};
-
 	sdhci1: sdhci@04FA0000 {
-		compatible = "arasan,sdhci-5.1";
+		compatible = "ti,am654-sdhci-5.1";
 		reg = <0x0 0x4FA0000 0x0 0x1000>,
 		      <0x0 0x4FB0000 0x0 0x400>;
 		clocks = <&k3_clks 48 1>;
 		power-domains = <&k3_pds 48>;
 		max-frequency = <25000000>;
+		ti,otap-del-sel = <0x2>;
+		ti,trm-icp = <0x8>;
 	};
 
 };
 
 &cbass_mcu {
 	u-boot,dm-spl;
-	wkup_pmx0: pinmux@4301c000 {
-		compatible = "pinctrl-single";
-		reg = <0x0 0x4301c000 0x0 0x118>;
-		#pinctrl-cells = <1>;
-		pinctrl-single,register-width = <32>;
-		pinctrl-single,function-mask = <0xffffffff>;
-	};
 
 	navss_mcu: navss-mcu {
 		compatible = "simple-bus";
@@ -250,6 +220,14 @@
 
 &k3_reset {
 	u-boot,dm-spl;
+};
+
+&wkup_pmx0 {
+	u-boot,dm-spl;
+
+	wkup_i2c0_pins_default {
+		u-boot,dm-spl;
+	};
 };
 
 &main_pmx0 {
@@ -276,7 +254,8 @@
 			AM65X_IOPAD(0x0190, PIN_INPUT_PULLUP, 0)	/* (A24) MMC0_DAT5 */
 			AM65X_IOPAD(0x018c, PIN_INPUT_PULLUP, 0)	/* (B26) MMC0_DAT6 */
 			AM65X_IOPAD(0x0188, PIN_INPUT_PULLUP, 0)	/* (D25) MMC0_DAT7 */
-			AM65X_IOPAD(0x01b0, PIN_INPUT, 0)			/* (C25) MMC0_DS */
+			AM65X_IOPAD(0x01b4, PIN_INPUT_PULLUP, 0)	/* (A23) MMC0_SDCD */
+			AM65X_IOPAD(0x01b0, PIN_INPUT, 0)		/* (C25) MMC0_DS */
 		>;
 		u-boot,dm-spl;
 	};
@@ -336,11 +315,6 @@
 
 &sdhci0 {
 	u-boot,dm-spl;
-	status = "okay";
-	non-removable;
-	bus-width = <8>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&main_mmc0_pins_default>;
 };
 
 &sdhci1 {
@@ -349,6 +323,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_mmc1_pins_default>;
 	sdhci-caps-mask = <0x7 0x0>;
+	ti,driver-strength-ohm = <50>;
 };
 
 &mcu_cpsw {
@@ -382,3 +357,7 @@
 		reg-names = "gmii-sel";
 	};
 };
+
+&wkup_i2c0 {
+	u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/k3-am654-base-board.dts b/arch/arm/dts/k3-am654-base-board.dts
index af6956f..e73b9aa 100644
--- a/arch/arm/dts/k3-am654-base-board.dts
+++ b/arch/arm/dts/k3-am654-base-board.dts
@@ -6,6 +6,7 @@
 /dts-v1/;
 
 #include "k3-am654.dtsi"
+#include <dt-bindings/pinctrl/k3.h>
 
 / {
 	compatible =  "ti,am654-evm", "ti,am654";
@@ -34,3 +35,52 @@
 		};
 	};
 };
+
+&main_pmx0 {
+	main_mmc0_pins_default: main_mmc0_pins_default {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x01a8, PIN_INPUT_PULLDOWN, 0)	/* (B25) MMC0_CLK */
+			AM65X_IOPAD(0x01aC, PIN_INPUT_PULLUP, 0)	/* (B27) MMC0_CMD */
+			AM65X_IOPAD(0x01a4, PIN_INPUT_PULLUP, 0)	/* (A26) MMC0_DAT0 */
+			AM65X_IOPAD(0x01a0, PIN_INPUT_PULLUP, 0)	/* (E25) MMC0_DAT1 */
+			AM65X_IOPAD(0x019c, PIN_INPUT_PULLUP, 0)	/* (C26) MMC0_DAT2 */
+			AM65X_IOPAD(0x0198, PIN_INPUT_PULLUP, 0)	/* (A25) MMC0_DAT3 */
+			AM65X_IOPAD(0x0194, PIN_INPUT_PULLUP, 0)	/* (E24) MMC0_DAT4 */
+			AM65X_IOPAD(0x0190, PIN_INPUT_PULLUP, 0)	/* (A24) MMC0_DAT5 */
+			AM65X_IOPAD(0x018c, PIN_INPUT_PULLUP, 0)	/* (B26) MMC0_DAT6 */
+			AM65X_IOPAD(0x0188, PIN_INPUT_PULLUP, 0)	/* (D25) MMC0_DAT7 */
+			AM65X_IOPAD(0x01b4, PIN_INPUT_PULLUP, 0)	/* (A23) MMC0_SDCD */
+			AM65X_IOPAD(0x01b0, PIN_INPUT, 0)		/* (C25) MMC0_DS */
+		>;
+	};
+};
+
+&wkup_pmx0 {
+	wkup_i2c0_pins_default: wkup-i2c0-pins-default {
+		pinctrl-single,pins = <
+			AM65X_WKUP_IOPAD(0x00e0, PIN_INPUT, 0) /* (AC7) WKUP_I2C0_SCL */
+			AM65X_WKUP_IOPAD(0x00e4, PIN_INPUT, 0) /* (AD6) WKUP_I2C0_SDA */
+		>;
+	};
+};
+
+&sdhci0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mmc0_pins_default>;
+	bus-width = <8>;
+	non-removable;
+	ti,driver-strength-ohm = <50>;
+};
+
+&wkup_i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_i2c0_pins_default>;
+	clock-frequency = <400000>;
+
+	tca9554: gpio@38 {
+		compatible = "nxp,pca9554";
+		reg = <0x38>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+};
diff --git a/arch/arm/dts/k3-am654-r5-base-board.dts b/arch/arm/dts/k3-am654-r5-base-board.dts
index a07038b..9d9b3d5 100644
--- a/arch/arm/dts/k3-am654-r5-base-board.dts
+++ b/arch/arm/dts/k3-am654-r5-base-board.dts
@@ -96,6 +96,12 @@
 		u-boot,dm-spl;
 	};
 
+	clk_200mhz: dummy_clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <200000000>;
+		u-boot,dm-spl;
+	};
 };
 
 &dmsc {
@@ -130,10 +136,56 @@
 		>;
 		u-boot,dm-spl;
 	};
+
+	wkup_i2c0_pins_default: wkup-i2c0-pins-default {
+		pinctrl-single,pins = <
+			AM65X_WKUP_IOPAD(0x00e0, PIN_INPUT, 0) /* (AC7) WKUP_I2C0_SCL */
+			AM65X_WKUP_IOPAD(0x00e4, PIN_INPUT, 0) /* (AD6) WKUP_I2C0_SDA */
+		>;
+	};
 };
 
+&main_pmx0 {
+	u-boot,dm-spl;
+	main_mmc0_pins_default: main_mmc0_pins_default {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x01a8, PIN_INPUT_PULLDOWN, 0)	/* (B25) MMC0_CLK */
+			AM65X_IOPAD(0x01aC, PIN_INPUT_PULLUP, 0)	/* (B27) MMC0_CMD */
+			AM65X_IOPAD(0x01a4, PIN_INPUT_PULLUP, 0)	/* (A26) MMC0_DAT0 */
+			AM65X_IOPAD(0x01a0, PIN_INPUT_PULLUP, 0)	/* (E25) MMC0_DAT1 */
+			AM65X_IOPAD(0x019c, PIN_INPUT_PULLUP, 0)	/* (C26) MMC0_DAT2 */
+			AM65X_IOPAD(0x0198, PIN_INPUT_PULLUP, 0)	/* (A25) MMC0_DAT3 */
+			AM65X_IOPAD(0x0194, PIN_INPUT_PULLUP, 0)	/* (E24) MMC0_DAT4 */
+			AM65X_IOPAD(0x0190, PIN_INPUT_PULLUP, 0)	/* (A24) MMC0_DAT5 */
+			AM65X_IOPAD(0x018c, PIN_INPUT_PULLUP, 0)	/* (B26) MMC0_DAT6 */
+			AM65X_IOPAD(0x0188, PIN_INPUT_PULLUP, 0)	/* (D25) MMC0_DAT7 */
+			AM65X_IOPAD(0x01b0, PIN_INPUT, 0)		/* (C25) MMC0_DS */
+		>;
+	};
+};
+
 &memorycontroller {
 	vtt-supply = <&vtt_supply>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&wkup_vtt_pins_default>;
 };
+
+&sdhci0 {
+	clock-names = "clk_xin";
+	clocks = <&clk_200mhz>;
+	/delete-property/ power-domains;
+	ti,driver-strength-ohm = <50>;
+};
+
+&sdhci1 {
+	clock-names = "clk_xin";
+	clocks = <&clk_200mhz>;
+	/delete-property/ power-domains;
+	ti,driver-strength-ohm = <50>;
+};
+
+&wkup_i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_i2c0_pins_default>;
+	clock-frequency = <400000>;
+};
diff --git a/arch/arm/dts/mt7629-rfb.dts b/arch/arm/dts/mt7629-rfb.dts
index 4612218..08c3b59 100644
--- a/arch/arm/dts/mt7629-rfb.dts
+++ b/arch/arm/dts/mt7629-rfb.dts
@@ -18,7 +18,6 @@
 
 	chosen {
 		stdout-path = &uart0;
-		tick-timer = &timer0;
 	};
 };
 
diff --git a/arch/arm/dts/mt7629.dtsi b/arch/arm/dts/mt7629.dtsi
index c87115e..ecbd29d 100644
--- a/arch/arm/dts/mt7629.dtsi
+++ b/arch/arm/dts/mt7629.dtsi
@@ -82,8 +82,8 @@
 		compatible = "mediatek,timer";
 		reg = <0x10004000 0x80>;
 		interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_LOW>;
-		clocks = <&topckgen CLK_TOP_10M_SEL>,
-			 <&topckgen CLK_TOP_CLKXTAL_D4>;
+		clocks = <&topckgen CLK_TOP_CLKXTAL_D4>,
+			 <&topckgen CLK_TOP_10M_SEL>;
 		clock-names = "mux", "src";
 		u-boot,dm-pre-reloc;
 	};
diff --git a/arch/arm/dts/rk3288-evb-u-boot.dtsi b/arch/arm/dts/rk3288-evb-u-boot.dtsi
new file mode 100644
index 0000000..8ac7840
--- /dev/null
+++ b/arch/arm/dts/rk3288-evb-u-boot.dtsi
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Rockchip Electronics Co., Ltd
+ */
+
+#include "rk3288-u-boot.dtsi"
+
+&pinctrl {
+	u-boot,dm-pre-reloc;
+};
+
+&uart2 {
+	u-boot,dm-pre-reloc;
+};
+
+&sdmmc {
+	u-boot,dm-pre-reloc;
+};
+
+&emmc {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio3 {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio8 {
+	u-boot,dm-pre-reloc;
+};
+
+&sdmmc_bus4 {
+	u-boot,dm-spl;
+};
+
+&sdmmc_clk {
+	u-boot,dm-spl;
+};
+
+&sdmmc_cmd {
+	u-boot,dm-spl;
+};
+
+&sdmmc_pwr {
+	u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/rk3288-evb.dts b/arch/arm/dts/rk3288-evb.dts
index 575de44..eac91a8 100644
--- a/arch/arm/dts/rk3288-evb.dts
+++ b/arch/arm/dts/rk3288-evb.dts
@@ -26,31 +26,6 @@
 	rockchip,sdram-params = <0x20d266a4 0x5b6 2 533000000 6 9 0>;
 };
 
-&pinctrl {
-	u-boot,dm-pre-reloc;
-};
-
 &pwm1 {
 	status = "okay";
 };
-
-&uart2 {
-	u-boot,dm-pre-reloc;
-	reg-shift = <2>;
-};
-
-&sdmmc {
-	u-boot,dm-pre-reloc;
-};
-
-&emmc {
-	u-boot,dm-pre-reloc;
-};
-
-&gpio3 {
-	u-boot,dm-pre-reloc;
-};
-
-&gpio8 {
-	u-boot,dm-pre-reloc;
-};
diff --git a/arch/arm/dts/rk3288-fennec-u-boot.dtsi b/arch/arm/dts/rk3288-fennec-u-boot.dtsi
new file mode 100644
index 0000000..2efb309
--- /dev/null
+++ b/arch/arm/dts/rk3288-fennec-u-boot.dtsi
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Rockchip Electronics Co., Ltd
+ */
+
+#include "rk3288-u-boot.dtsi"
+
+&pinctrl {
+	u-boot,dm-pre-reloc;
+};
+
+&uart2 {
+	u-boot,dm-pre-reloc;
+};
+
+&sdmmc {
+	u-boot,dm-pre-reloc;
+};
+
+&emmc {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio3 {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio8 {
+	u-boot,dm-pre-reloc;
+};
+
+&pcfg_pull_none_drv_8ma {
+	u-boot,dm-spl;
+};
+
+&pcfg_pull_up_drv_8ma {
+	u-boot,dm-spl;
+};
+
+&sdmmc_bus4 {
+	u-boot,dm-spl;
+};
+
+&sdmmc_clk {
+	u-boot,dm-spl;
+};
+
+&sdmmc_cmd {
+	u-boot,dm-spl;
+};
+
+&sdmmc_pwr {
+	u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/rk3288-fennec.dts b/arch/arm/dts/rk3288-fennec.dts
index b569307..e1d55e3 100644
--- a/arch/arm/dts/rk3288-fennec.dts
+++ b/arch/arm/dts/rk3288-fennec.dts
@@ -26,31 +26,6 @@
 	rockchip,sdram-params = <0x20d266a4 0x5b6 2 533000000 6 9 0>;
 };
 
-&pinctrl {
-	u-boot,dm-pre-reloc;
-};
-
 &pwm1 {
 	status = "okay";
 };
-
-&uart2 {
-	u-boot,dm-pre-reloc;
-	reg-shift = <2>;
-};
-
-&sdmmc {
-	u-boot,dm-pre-reloc;
-};
-
-&emmc {
-	u-boot,dm-pre-reloc;
-};
-
-&gpio3 {
-	u-boot,dm-pre-reloc;
-};
-
-&gpio8 {
-	u-boot,dm-pre-reloc;
-};
diff --git a/arch/arm/dts/rk3288-firefly-u-boot.dtsi b/arch/arm/dts/rk3288-firefly-u-boot.dtsi
new file mode 100644
index 0000000..8b9c383
--- /dev/null
+++ b/arch/arm/dts/rk3288-firefly-u-boot.dtsi
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Rockchip Electronics Co., Ltd
+ */
+
+#include "rk3288-u-boot.dtsi"
+
+&pinctrl {
+	u-boot,dm-pre-reloc;
+};
+
+&uart2 {
+	u-boot,dm-pre-reloc;
+};
+
+&sdmmc {
+	u-boot,dm-pre-reloc;
+};
+
+&emmc {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio3 {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio8 {
+	u-boot,dm-pre-reloc;
+};
+
+&pcfg_pull_up_drv_12ma {
+	u-boot,dm-spl;
+};
+
+&sdmmc_bus4 {
+	u-boot,dm-spl;
+};
+
+&sdmmc_clk {
+	u-boot,dm-spl;
+};
+
+&sdmmc_cmd {
+	u-boot,dm-spl;
+};
+
+&sdmmc_pwr {
+	u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/rk3288-firefly.dts b/arch/arm/dts/rk3288-firefly.dts
index 2e075406..1cff04e 100644
--- a/arch/arm/dts/rk3288-firefly.dts
+++ b/arch/arm/dts/rk3288-firefly.dts
@@ -37,7 +37,6 @@
 };
 
 &pinctrl {
-	u-boot,dm-pre-reloc;
 	act8846 {
 		pmic_vsel: pmic-vsel {
 			rockchip,pins = <7 14 RK_FUNC_GPIO &pcfg_output_low>;
@@ -59,25 +58,3 @@
 &pwm1 {
 	status = "okay";
 };
-
-&uart2 {
-	u-boot,dm-pre-reloc;
-	reg-shift = <2>;
-};
-
-&usb_host1 {
-	vbus-supply = <&vcc_host_5v>;
-	status = "okay";
-};
-
-&sdmmc {
-	u-boot,dm-pre-reloc;
-};
-
-&gpio3 {
-	u-boot,dm-pre-reloc;
-};
-
-&gpio8 {
-	u-boot,dm-pre-reloc;
-};
diff --git a/arch/arm/dts/rk3288-firefly.dtsi b/arch/arm/dts/rk3288-firefly.dtsi
index 2239ab9..b7f279f 100644
--- a/arch/arm/dts/rk3288-firefly.dtsi
+++ b/arch/arm/dts/rk3288-firefly.dtsi
@@ -320,6 +320,11 @@
 		output-low;
 	};
 
+	pcfg_pull_up_drv_12ma: pcfg-pull-up-drv-12ma {
+		bias-pull-up;
+		drive-strength = <12>;
+	};
+
 	act8846 {
 		pwr_hold: pwr-hold {
 			rockchip,pins = <0 1 RK_FUNC_GPIO &pcfg_output_high>;
@@ -363,8 +368,27 @@
 	};
 
 	sdmmc {
+		/*
+		 * Default drive strength isn't enough to achieve even
+		 * high-speed mode on firefly board so bump up to 12ma.
+		 */
+		sdmmc_bus4: sdmmc-bus4 {
+			rockchip,pins = <6 RK_PC0 1 &pcfg_pull_up_drv_12ma>,
+					<6 RK_PC1 1 &pcfg_pull_up_drv_12ma>,
+					<6 RK_PC2 1 &pcfg_pull_up_drv_12ma>,
+					<6 RK_PC3 1 &pcfg_pull_up_drv_12ma>;
+		};
+
+		sdmmc_clk: sdmmc-clk {
+			rockchip,pins = <6 RK_PC4 1 &pcfg_pull_none_12ma>;
+		};
+
+		sdmmc_cmd: sdmmc-cmd {
+			rockchip,pins = <6 RK_PC5 1 &pcfg_pull_up_drv_12ma>;
+		};
+
 		sdmmc_pwr: sdmmc-pwr {
-			rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+			rockchip,pins = <7 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
 		};
 	};
 
diff --git a/arch/arm/dts/rk3288-miqi-u-boot.dtsi b/arch/arm/dts/rk3288-miqi-u-boot.dtsi
new file mode 100644
index 0000000..4f63fc9
--- /dev/null
+++ b/arch/arm/dts/rk3288-miqi-u-boot.dtsi
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Rockchip Electronics Co., Ltd
+ */
+
+#include "rk3288-u-boot.dtsi"
+
+&pinctrl {
+	u-boot,dm-pre-reloc;
+};
+
+&uart2 {
+	u-boot,dm-pre-reloc;
+};
+
+&sdmmc {
+	u-boot,dm-pre-reloc;
+};
+
+&emmc {
+	u-boot,dm-pre-reloc;
+};
+
+&sdmmc_bus4 {
+	u-boot,dm-spl;
+};
+
+&sdmmc_clk {
+	u-boot,dm-spl;
+};
+
+&sdmmc_cmd {
+	u-boot,dm-spl;
+};
+
+&sdmmc_pwr {
+	u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/rk3288-miqi.dts b/arch/arm/dts/rk3288-miqi.dts
index 29e60dd..e47170c 100644
--- a/arch/arm/dts/rk3288-miqi.dts
+++ b/arch/arm/dts/rk3288-miqi.dts
@@ -25,21 +25,3 @@
 		0xa60 0x40 0x10 0x0>;
 	rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
 };
-
-
-&pinctrl {
-	u-boot,dm-pre-reloc;
-};
-
-&uart2 {
-	u-boot,dm-pre-reloc;
-	reg-shift = <2>;
-};
-
-&sdmmc {
-	u-boot,dm-pre-reloc;
-};
-
-&emmc {
-	u-boot,dm-pre-reloc;
-};
diff --git a/arch/arm/dts/rk3288-popmetal-u-boot.dtsi b/arch/arm/dts/rk3288-popmetal-u-boot.dtsi
new file mode 100644
index 0000000..8ac7840
--- /dev/null
+++ b/arch/arm/dts/rk3288-popmetal-u-boot.dtsi
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Rockchip Electronics Co., Ltd
+ */
+
+#include "rk3288-u-boot.dtsi"
+
+&pinctrl {
+	u-boot,dm-pre-reloc;
+};
+
+&uart2 {
+	u-boot,dm-pre-reloc;
+};
+
+&sdmmc {
+	u-boot,dm-pre-reloc;
+};
+
+&emmc {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio3 {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio8 {
+	u-boot,dm-pre-reloc;
+};
+
+&sdmmc_bus4 {
+	u-boot,dm-spl;
+};
+
+&sdmmc_clk {
+	u-boot,dm-spl;
+};
+
+&sdmmc_cmd {
+	u-boot,dm-spl;
+};
+
+&sdmmc_pwr {
+	u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/rk3288-popmetal.dts b/arch/arm/dts/rk3288-popmetal.dts
index d1e1cd5..5c6d06f 100644
--- a/arch/arm/dts/rk3288-popmetal.dts
+++ b/arch/arm/dts/rk3288-popmetal.dts
@@ -26,32 +26,6 @@
 	rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
 };
 
-
-&pinctrl {
-	u-boot,dm-pre-reloc;
-};
-
 &pwm1 {
 	status = "okay";
 };
-
-&uart2 {
-	u-boot,dm-pre-reloc;
-	reg-shift = <2>;
-};
-
-&sdmmc {
-	u-boot,dm-pre-reloc;
-};
-
-&emmc {
-	u-boot,dm-pre-reloc;
-};
-
-&gpio3 {
-	u-boot,dm-pre-reloc;
-};
-
-&gpio8 {
-	u-boot,dm-pre-reloc;
-};
diff --git a/arch/arm/dts/rk3288-u-boot.dtsi b/arch/arm/dts/rk3288-u-boot.dtsi
index 4cf75c7..3f00a3b 100644
--- a/arch/arm/dts/rk3288-u-boot.dtsi
+++ b/arch/arm/dts/rk3288-u-boot.dtsi
@@ -3,6 +3,13 @@
  * Copyright (C) 2019 Rockchip Electronics Co., Ltd
  */
 
+/ {
+	chosen {
+		u-boot,spl-boot-order = \
+			"same-as-spl", &emmc, &sdmmc;
+	};
+};
+
 &dmc {
 	u-boot,dm-pre-reloc;
 };
diff --git a/arch/arm/dts/rk3368-lion-u-boot.dtsi b/arch/arm/dts/rk3368-lion-u-boot.dtsi
index fb4a4fb..edc93e4 100644
--- a/arch/arm/dts/rk3368-lion-u-boot.dtsi
+++ b/arch/arm/dts/rk3368-lion-u-boot.dtsi
@@ -12,7 +12,6 @@
 	chosen {
 		stdout-path = "serial0:115200n8";
 		u-boot,spl-boot-order = &emmc, &sdmmc;
-		tick-timer = "/timer@ff810000";
 	};
 
 };
diff --git a/arch/arm/dts/rk3368-px5-evb-u-boot.dtsi b/arch/arm/dts/rk3368-px5-evb-u-boot.dtsi
index f5406d4..002767a 100644
--- a/arch/arm/dts/rk3368-px5-evb-u-boot.dtsi
+++ b/arch/arm/dts/rk3368-px5-evb-u-boot.dtsi
@@ -5,7 +5,6 @@
 / {
 	chosen {
 		u-boot,spl-boot-order = &emmc;
-		tick-timer = "/timer@ff810000";
 	};
 };
 
diff --git a/arch/arm/dts/rk3399-ficus.dts b/arch/arm/dts/rk3399-ficus.dts
index 4b2dd82..6b059bd 100644
--- a/arch/arm/dts/rk3399-ficus.dts
+++ b/arch/arm/dts/rk3399-ficus.dts
@@ -23,6 +23,52 @@
 		clock-output-names = "clkin_gmac";
 		#clock-cells = <0>;
 	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&user_led1>, <&user_led2>, <&user_led3>,
+			    <&user_led4>, <&wlan_led>, <&bt_led>;
+
+		user_led1 {
+			label = "red:user1";
+			gpios = <&gpio4 25 0>;
+			linux,default-trigger = "heartbeat";
+		};
+
+		user_led2 {
+			label = "red:user2";
+			gpios = <&gpio4 26 0>;
+			linux,default-trigger = "mmc0";
+		};
+
+		user_led3 {
+			label = "red:user3";
+			gpios = <&gpio4 30 0>;
+			linux,default-trigger = "mmc1";
+		};
+
+		user_led4 {
+			label = "red:user4";
+			gpios = <&gpio1 0 0>;
+			panic-indicator;
+			linux,default-trigger = "none";
+		};
+
+		wlan_active_led {
+			label = "red:wlan";
+			gpios = <&gpio1 1 0>;
+			linux,default-trigger = "phy0tx";
+			default-state = "off";
+		};
+
+		bt_active_led {
+			label = "red:bt";
+			gpios = <&gpio1 4 0>;
+			linux,default-trigger = "hci0-power";
+			default-state = "off";
+		};
+	};
 };
 
 &gmac {
@@ -49,23 +95,63 @@
 	gmac {
 		rgmii_sleep_pins: rgmii-sleep-pins {
 			rockchip,pins =
-				<3 15 RK_FUNC_GPIO &pcfg_output_low>;
+				<3 RK_PB7 RK_FUNC_GPIO &pcfg_output_low>;
 		};
 	};
 
 	pcie {
 		pcie_drv: pcie-drv {
 			rockchip,pins =
-				<1 24 RK_FUNC_GPIO &pcfg_pull_none>;
+				<1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
 			};
 	};
 
 	usb2 {
 		host_vbus_drv: host-vbus-drv {
 			rockchip,pins =
-				<4 27 RK_FUNC_GPIO &pcfg_pull_none>;
+				<4 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>;
 		};
 	};
+
+	leds {
+		user_led1: user_led1 {
+			rockchip,pins =
+				<4 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		user_led2: user_led2 {
+			rockchip,pins =
+				<4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		user_led3: user_led3 {
+			rockchip,pins =
+				<4 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		user_led4: user_led4 {
+			rockchip,pins =
+				<1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		wlan_led: wlan_led {
+			rockchip,pins =
+				<1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		bt_led: bt_led {
+			rockchip,pins =
+				<1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&usbdrd_dwc3_0 {
+	dr_mode = "host";
+};
+
+&usbdrd_dwc3_1 {
+	dr_mode = "host";
 };
 
 &vcc3v3_pcie {
diff --git a/arch/arm/dts/rk3399-nanopi-neo4-u-boot.dtsi b/arch/arm/dts/rk3399-nanopi-neo4-u-boot.dtsi
index 7d22528..eb0aca4 100644
--- a/arch/arm/dts/rk3399-nanopi-neo4-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-nanopi-neo4-u-boot.dtsi
@@ -4,3 +4,4 @@
  */
 
 #include "rk3399-nanopi4-u-boot.dtsi"
+#include "rk3399-sdram-ddr3-1866.dtsi"
diff --git a/arch/arm/dts/rk3399-rock-pi-4-u-boot.dtsi b/arch/arm/dts/rk3399-rock-pi-4-u-boot.dtsi
index 7bddc3a..5bd8696 100644
--- a/arch/arm/dts/rk3399-rock-pi-4-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-rock-pi-4-u-boot.dtsi
@@ -4,3 +4,10 @@
  */
 
 #include "rk3399-u-boot.dtsi"
+#include "rk3399-sdram-lpddr4-100.dtsi"
+
+/ {
+	chosen {
+		u-boot,spl-boot-order = "same-as-spl", &sdhci, &sdmmc;
+	};
+};
diff --git a/arch/arm/dts/rk3399-rock960.dts b/arch/arm/dts/rk3399-rock960.dts
index 7e06bc9..12285c5 100644
--- a/arch/arm/dts/rk3399-rock960.dts
+++ b/arch/arm/dts/rk3399-rock960.dts
@@ -1,6 +1,6 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
- * Copyright (C) 2018 Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ * Copyright (c) 2018 Linaro Ltd.
  */
 
 /dts-v1/;
@@ -13,6 +13,53 @@
 	chosen {
 		stdout-path = "serial2:1500000n8";
 	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&user_led1>, <&user_led2>, <&user_led3>,
+			    <&user_led4>, <&wlan_led>, <&bt_led>;
+
+		user_led1 {
+			label = "green:user1";
+			gpios = <&gpio4 RK_PC2 0>;
+			linux,default-trigger = "heartbeat";
+		};
+
+		user_led2 {
+			label = "green:user2";
+			gpios = <&gpio4 RK_PC6 0>;
+			linux,default-trigger = "mmc0";
+		};
+
+		user_led3 {
+			label = "green:user3";
+			gpios = <&gpio4 RK_PD0 0>;
+			linux,default-trigger = "mmc1";
+		};
+
+		user_led4 {
+			label = "green:user4";
+			gpios = <&gpio4 RK_PD4 0>;
+			panic-indicator;
+			linux,default-trigger = "none";
+		};
+
+		wlan_active_led {
+			label = "yellow:wlan";
+			gpios = <&gpio4 RK_PD5 0>;
+			linux,default-trigger = "phy0tx";
+			default-state = "off";
+		};
+
+		bt_active_led {
+			label = "blue:bt";
+			gpios = <&gpio4 RK_PD6 0>;
+			linux,default-trigger = "hci0-power";
+			default-state = "off";
+		};
+	};
+
 };
 
 &pcie0 {
@@ -20,6 +67,38 @@
 };
 
 &pinctrl {
+	leds {
+		user_led1: user_led1 {
+			rockchip,pins =
+				<4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		user_led2: user_led2 {
+			rockchip,pins =
+				<4 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		user_led3: user_led3 {
+			rockchip,pins =
+				<4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		user_led4: user_led4 {
+			rockchip,pins =
+				<4 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		wlan_led: wlan_led {
+			rockchip,pins =
+				<4 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		bt_led: bt_led {
+			rockchip,pins =
+				<4 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
 	pcie {
 		pcie_drv: pcie-drv {
 			rockchip,pins =
@@ -35,6 +114,14 @@
 	};
 };
 
+&usbdrd_dwc3_0 {
+	dr_mode = "otg";
+};
+
+&usbdrd_dwc3_1 {
+	dr_mode = "host";
+};
+
 &vcc3v3_pcie {
 	gpio = <&gpio2 5 GPIO_ACTIVE_HIGH>;
 };
diff --git a/arch/arm/dts/rk3399-rock960.dtsi b/arch/arm/dts/rk3399-rock960.dtsi
index 51644d6..c7d48d4 100644
--- a/arch/arm/dts/rk3399-rock960.dtsi
+++ b/arch/arm/dts/rk3399-rock960.dtsi
@@ -1,13 +1,32 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
+ * Copyright (c) 2018 Collabora Ltd.
+ * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd.
  * Copyright (c) 2018 Linaro Ltd.
  */
 
-#include <dt-bindings/pwm/pwm.h>
-#include <dt-bindings/pinctrl/rockchip.h>
 #include "rk3399.dtsi"
+#include "rk3399-opp.dtsi"
 
 / {
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		clocks = <&rk808 1>;
+		clock-names = "ext_clock";
+		pinctrl-names = "default";
+		pinctrl-0 = <&wifi_enable_h>;
+		reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
+	};
+
+	vcc12v_dcin: vcc12v-dcin {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc12v_dcin";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
 	vcc1v8_s0: vcc1v8-s0 {
 		compatible = "regulator-fixed";
 		regulator-name = "vcc1v8_s0";
@@ -16,12 +35,13 @@
 		regulator-always-on;
 	};
 
-	vcc_sys: vcc-sys {
+	vcc5v0_sys: vcc5v0-sys {
 		compatible = "regulator-fixed";
-		regulator-name = "vcc_sys";
+		regulator-name = "vcc5v0_sys";
 		regulator-min-microvolt = <5000000>;
 		regulator-max-microvolt = <5000000>;
 		regulator-always-on;
+		vin-supply = <&vcc12v_dcin>;
 	};
 
 	vcc3v3_sys: vcc3v3-sys {
@@ -30,7 +50,7 @@
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
 		regulator-always-on;
-		vin-supply = <&vcc_sys>;
+		vin-supply = <&vcc5v0_sys>;
 	};
 
 	vcc3v3_pcie: vcc3v3-pcie-regulator {
@@ -54,20 +74,8 @@
 		regulator-min-microvolt = <5000000>;
 		regulator-max-microvolt = <5000000>;
 		regulator-always-on;
-		vin-supply = <&vcc_sys>;
-	};
-
-	vdd_log: vdd-log {
-		compatible = "pwm-regulator";
-		pwms = <&pwm2 0 25000 0>;
-		regulator-name = "vdd_log";
-		regulator-min-microvolt = <800000>;
-		regulator-max-microvolt = <1400000>;
-		regulator-always-on;
-		regulator-boot-on;
-		vin-supply = <&vcc_sys>;
+		vin-supply = <&vcc5v0_sys>;
 	};
-
 };
 
 &cpu_l0 {
@@ -98,10 +106,22 @@
 	status = "okay";
 };
 
+&gpu {
+	mali-supply = <&vdd_gpu>;
+	status = "okay";
+};
+
 &hdmi {
+	ddc-i2c-bus = <&i2c3>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&hdmi_cec>;
 	status = "okay";
 };
 
+&hdmi_sound {
+	status = "okay";
+};
+
 &i2c0 {
 	clock-frequency = <400000>;
 	i2c-scl-rising-time-ns = <168>;
@@ -118,7 +138,7 @@
 		regulator-ramp-delay = <1000>;
 		regulator-always-on;
 		regulator-boot-on;
-		vin-supply = <&vcc_sys>;
+		vin-supply = <&vcc5v0_sys>;
 		status = "okay";
 
 		regulator-state-mem {
@@ -136,7 +156,7 @@
 		regulator-ramp-delay = <1000>;
 		regulator-always-on;
 		regulator-boot-on;
-		vin-supply = <&vcc_sys>;
+		vin-supply = <&vcc5v0_sys>;
 		regulator-state-mem {
 			regulator-off-in-suspend;
 		};
@@ -154,16 +174,16 @@
 		#clock-cells = <1>;
 		clock-output-names = "xin32k", "rk808-clkout2";
 
-		vcc1-supply = <&vcc_sys>;
-		vcc2-supply = <&vcc_sys>;
-		vcc3-supply = <&vcc_sys>;
-		vcc4-supply = <&vcc_sys>;
-		vcc6-supply = <&vcc_sys>;
-		vcc7-supply = <&vcc_sys>;
+		vcc1-supply = <&vcc5v0_sys>;
+		vcc2-supply = <&vcc5v0_sys>;
+		vcc3-supply = <&vcc5v0_sys>;
+		vcc4-supply = <&vcc5v0_sys>;
+		vcc6-supply = <&vcc5v0_sys>;
+		vcc7-supply = <&vcc5v0_sys>;
 		vcc8-supply = <&vcc3v3_sys>;
-		vcc9-supply = <&vcc_sys>;
-		vcc10-supply = <&vcc_sys>;
-		vcc11-supply = <&vcc_sys>;
+		vcc9-supply = <&vcc5v0_sys>;
+		vcc10-supply = <&vcc5v0_sys>;
+		vcc11-supply = <&vcc5v0_sys>;
 		vcc12-supply = <&vcc3v3_sys>;
 		vddio-supply = <&vcc_1v8>;
 
@@ -344,6 +364,10 @@
 	status = "okay";
 };
 
+&i2s2 {
+        status = "okay";
+};
+
 &io_domains {
 	bt656-supply = <&vcc1v8_s0>; /* bt656_gpio2ab_ms */
 	audio-supply = <&vcc1v8_s0>; /* audio_gpio3d4a_ms */
@@ -370,47 +394,94 @@
 };
 
 &pinctrl {
+	bt {
+		bt_enable_h: bt-enable-h {
+			rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		bt_host_wake_l: bt-host-wake-l {
+			rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		bt_wake_l: bt-wake-l {
+			rockchip,pins = <2 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
 	sdmmc {
 		sdmmc_bus1: sdmmc-bus1 {
 			rockchip,pins =
-				<4 8 RK_FUNC_1 &pcfg_pull_up_8ma>;
+				<4 RK_PB0 1 &pcfg_pull_up_8ma>;
 		};
 
 		sdmmc_bus4: sdmmc-bus4 {
 			rockchip,pins =
-				<4 8 RK_FUNC_1 &pcfg_pull_up_8ma>,
-				<4 9 RK_FUNC_1 &pcfg_pull_up_8ma>,
-				<4 10 RK_FUNC_1 &pcfg_pull_up_8ma>,
-				<4 11 RK_FUNC_1 &pcfg_pull_up_8ma>;
+				<4 RK_PB0 1 &pcfg_pull_up_8ma>,
+				<4 RK_PB1 1 &pcfg_pull_up_8ma>,
+				<4 RK_PB2 1 &pcfg_pull_up_8ma>,
+				<4 RK_PB3 1 &pcfg_pull_up_8ma>;
 		};
 
 		sdmmc_clk: sdmmc-clk {
 			rockchip,pins =
-				<4 12 RK_FUNC_1 &pcfg_pull_none_18ma>;
+				<4 RK_PB4 1 &pcfg_pull_none_18ma>;
 		};
 
 		sdmmc_cmd: sdmmc-cmd {
 			rockchip,pins =
+				<4 RK_PB5 1 &pcfg_pull_up_8ma>;
+		};
+	};
+
+	sdio0 {
+		sdio0_bus4: sdio0-bus4 {
+			rockchip,pins =
-				<4 13 RK_FUNC_1 &pcfg_pull_up_8ma>;
+				<2 RK_PC4 1 &pcfg_pull_up_20ma>,
+				<2 RK_PC5 1 &pcfg_pull_up_20ma>,
+				<2 RK_PC6 1 &pcfg_pull_up_20ma>,
+				<2 RK_PC7 1 &pcfg_pull_up_20ma>;
+		};
+
+		sdio0_cmd: sdio0-cmd {
+			rockchip,pins =
+				<2 RK_PD0 1 &pcfg_pull_up_20ma>;
+		};
+
+		sdio0_clk: sdio0-clk {
+			rockchip,pins =
+				<2 RK_PD1 1 &pcfg_pull_none_20ma>;
 		};
 	};
 
 	pmic {
 		pmic_int_l: pmic-int-l {
 			rockchip,pins =
-				<1 21 RK_FUNC_GPIO &pcfg_pull_up>;
+				<1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>;
 		};
 
 		vsel1_gpio: vsel1-gpio {
 			rockchip,pins =
-				<1 17 RK_FUNC_GPIO &pcfg_pull_down>;
+				<1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>;
 		};
 
 		vsel2_gpio: vsel2-gpio {
 			rockchip,pins =
-				<1 14 RK_FUNC_GPIO &pcfg_pull_down>;
+				<1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>;
 		};
 	};
+
+	sdio-pwrseq {
+		wifi_enable_h: wifi-enable-h {
+			rockchip,pins =
+				<0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	wifi {
+		wifi_host_wake_l: wifi-host-wake-l {
+			rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
 };
 
 &pwm2 {
@@ -421,6 +492,32 @@
 	status = "okay";
 };
 
+&sdio0 {
+	bus-width = <4>;
+	clock-frequency = <50000000>;
+	cap-sdio-irq;
+	cap-sd-highspeed;
+	keep-power-in-suspend;
+	mmc-pwrseq = <&sdio_pwrseq>;
+	non-removable;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>;
+	sd-uhs-sdr104;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	brcmf: wifi@1 {
+		compatible = "brcm,bcm4329-fmac";
+		reg = <1>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <RK_PA3 GPIO_ACTIVE_HIGH>;
+		interrupt-names = "host-wake";
+		pinctrl-names = "default";
+		pinctrl-0 = <&wifi_host_wake_l>;
+	};
+};
+
 &sdhci {
 	bus-width = <8>;
 	mmc-hs400-1_8v;
@@ -445,16 +542,42 @@
 	status = "okay";
 };
 
+&tsadc {
+	rockchip,hw-tshut-mode = <1>;
+	rockchip,hw-tshut-polarity = <1>;
+	rockchip,hw-tshut-temp = <110000>;
+	status = "okay";
+};
+
 &uart0 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&uart0_xfer &uart0_cts>;
+	pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
 	status = "okay";
+
+	bluetooth {
+		compatible = "brcm,bcm43438-bt";
+		clocks = <&rk808 1>;
+		clock-names = "ext_clock";
+		device-wakeup-gpios = <&gpio2 RK_PD3 GPIO_ACTIVE_HIGH>;
+		host-wakeup-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>;
+		shutdown-gpios = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&bt_host_wake_l &bt_wake_l &bt_enable_h>;
+	};
 };
 
 &uart2 {
 	status = "okay";
 };
 
+&tcphy0 {
+	status = "okay";
+};
+
+&tcphy1 {
+	status = "okay";
+};
+
 &u2phy0 {
 	status = "okay";
 };
@@ -497,10 +620,34 @@
 	status = "okay";
 };
 
+&usbdrd3_0 {
+	status = "okay";
+};
+
+&usbdrd_dwc3_0 {
+	status = "okay";
+};
+
+&usbdrd3_1 {
+	status = "okay";
+};
+
+&usbdrd_dwc3_1 {
+	status = "okay";
+};
+
 &vopb {
 	status = "okay";
 };
 
+&vopb_mmu {
+	status = "okay";
+};
+
 &vopl {
 	status = "okay";
 };
+
+&vopl_mmu {
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3399-rockpro64-u-boot.dtsi b/arch/arm/dts/rk3399-rockpro64-u-boot.dtsi
index 50b0ca0..f7f26d5 100644
--- a/arch/arm/dts/rk3399-rockpro64-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-rockpro64-u-boot.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include "rk3399-u-boot.dtsi"
+#include "rk3399-sdram-lpddr4-100.dtsi"
 
 &vdd_log {
 	regulator-init-microvolt = <950000>;
diff --git a/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi b/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi
new file mode 100644
index 0000000..4a4414a
--- /dev/null
+++ b/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi
@@ -0,0 +1,1537 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ * (C) Copyright 2019 Amarula Solutions.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+&dmc {
+	rockchip,sdram-params = <
+		0x2
+		0xa
+		0x3
+		0x2
+		0x1
+		0x0
+		0xf
+		0xf
+		1
+		0x80241d22
+		0x15050f08
+		0x00000602
+		0x00002122
+		0x0000004c
+		0x00000000
+		0x2
+		0xa
+		0x3
+		0x2
+		0x1
+		0x0
+		0xf
+		0xf
+		1
+		0x80241d22
+		0x15050f08
+		0x00000602
+		0x00002122
+		0x0000004c
+		0x00000000
+		50
+		7
+		2
+		13
+		1
+		0x00000b00
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00013880
+		0x000c3500
+		0x00000005
+		0x00000320
+		0x00027100
+		0x00186a00
+		0x00000005
+		0x00000640
+		0x00002710
+		0x000186a0
+		0x00000005
+		0x01000064
+		0x00000000
+		0x02020101
+		0x00000102
+		0x00000050
+		0x000000c8
+		0x00000000
+		0x06140000
+		0x00081c00
+		0x0400040c
+		0x19042008
+		0x10080a11
+		0x22310800
+		0x00200f0a
+		0x0a030704
+		0x08000204
+		0x00000a0a
+		0x04006db0
+		0x0a0a0804
+		0x0600db60
+		0x0a0a0806
+		0x04000db6
+		0x02030404
+		0x0f0a0800
+		0x08040411
+		0x1400640a
+		0x02010a0a
+		0x00010001
+		0x04082012
+		0x00041109
+		0x00000000
+		0x03010000
+		0x06100048
+		0x0c280090
+		0x00bb0009
+		0x00000000
+		0x00060005
+		0x000a0005
+		0x000a0014
+		0x01000000
+		0x030a0000
+		0x0c000002
+		0x00000103
+		0x0005030a
+		0x00060037
+		0x0005006e
+		0x05050007
+		0x03030605
+		0x06050301
+		0x06030c05
+		0x05050302
+		0x03030305
+		0x00000301
+		0x00000301
+		0x00000001
+		0x00000000
+		0x00000000
+		0x01000000
+		0x80104002
+		0x00040003
+		0x00040005
+		0x00030000
+		0x00050004
+		0x00000004
+		0x00040003
+		0x00040005
+		0x18400000
+		0x00000c20
+		0x185030a0
+		0x02ec0000
+		0x00000176
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x06030300
+		0x00030303
+		0x02030200
+		0x00040703
+		0x03020302
+		0x02000407
+		0x07030203
+		0x00030f04
+		0x00070004
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00010000
+		0x20040020
+		0x00200400
+		0x01000400
+		0x00000b80
+		0x00000000
+		0x00000001
+		0x00000002
+		0x0000000e
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00500000
+		0x00640028
+		0x00640404
+		0x005000a0
+		0x060600c8
+		0x000a00c8
+		0x000d0005
+		0x000d0404
+		0x00000000
+		0x00000000
+		0x00000000
+		0x001400a3
+		0x00e30009
+		0x00120024
+		0x00040063
+		0x00000000
+		0x00310031
+		0x00000031
+		0x004d0000
+		0x004d004d
+		0x004d0000
+		0x004d004d
+		0x00010101
+		0x00000000
+		0x00000000
+		0x001400a3
+		0x00e30009
+		0x00120024
+		0x00040063
+		0x00000000
+		0x00310031
+		0x00000031
+		0x004d0000
+		0x004d004d
+		0x004d0000
+		0x004d004d
+		0x00010101
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000001
+		0x00000000
+		0x18151100
+		0x0000000c
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00020003
+		0x00400100
+		0x000c0190
+		0x01000200
+		0x03200040
+		0x00020018
+		0x00400100
+		0x00080032
+		0x00140000
+		0x00030028
+		0x01010100
+		0x02000202
+		0x0b000002
+		0x01000f0f
+		0x00000000
+		0x00000000
+		0x00010003
+		0x00000c03
+		0x00040101
+		0x04010100
+		0x01000000
+		0x02010000
+		0x00000001
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00010000
+		0x00000001
+		0x01010001
+		0x05040001
+		0x040a0703
+		0x02080808
+		0x020e000a
+		0x020f010b
+		0x000d0008
+		0x00080b0a
+		0x03000200
+		0x00000100
+		0x00000000
+		0x00000000
+		0x0d000001
+		0x00000028
+		0x00010000
+		0x00000003
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00010100
+		0x01000000
+		0x00000001
+		0x00000303
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x000556aa
+		0x000aaaaa
+		0x000aa955
+		0x00055555
+		0x000b3133
+		0x0004cd33
+		0x0004cecc
+		0x000b32cc
+		0x00010300
+		0x03000100
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00ffff00
+		0x1a160000
+		0x08000012
+		0x00000c20
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000c20
+		0x00007940
+		0x18500409
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00001850
+		0x0000f320
+		0x0176060c
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000176
+		0x00000e9c
+		0x02020205
+		0x03030202
+		0x00000018
+		0x00000000
+		0x00000000
+		0x00001403
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00030000
+		0x000a001c
+		0x000e0020
+		0x00060018
+		0x00000000
+		0x00000000
+		0x02000000
+		0x00090305
+		0x00050101
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x01000001
+		0x01010101
+		0x01000101
+		0x01000100
+		0x00010001
+		0x00010002
+		0x00020100
+		0x00000002
+		0x00000b00
+		0x00000000
+		0x000002ec
+		0x00000176
+		0x000030a0
+		0x00001850
+		0x00001840
+		0x01760c20
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00001850
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000c20
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00010000
+		0x00000007
+		0x01000001
+		0x00000000
+		0x3fffffff
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x0f000101
+		0x082b3223
+		0x080c0004
+		0x00061c00
+		0x00000214
+		0x00bb0009
+		0x0c280090
+		0x06100048
+		0x00000500
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x04040100
+		0x0a000004
+		0x00000128
+		0x00000000
+		0x0003000f
+		0x00000018
+		0x00000000
+		0x00000000
+		0x00060002
+		0x00010001
+		0x00000101
+		0x00020001
+		0x00080004
+		0x00000000
+		0x05030000
+		0x070a0404
+		0x00000000
+		0x00000000
+		0x00000000
+		0x000f0f00
+		0x0000001e
+		0x00000000
+		0x01010300
+		0x00000000
+		0x00000000
+		0x01000000
+		0x00000101
+		0x55555a5a
+		0x55555a5a
+		0x55555a5a
+		0x55555a5a
+		0x0c050001
+		0x06020009
+		0x00010004
+		0x00000203
+		0x00030000
+		0x170f0000
+		0x00060018
+		0x000e0020
+		0x000a001c
+		0x00000000
+		0x00000000
+		0x00000100
+		0x140a0000
+		0x000d010a
+		0x0100c802
+		0x010a0064
+		0x000e0100
+		0x0100000e
+		0x00c900c9
+		0x00650100
+		0x1e1a0065
+		0x10010204
+		0x06070605
+		0x20000202
+		0x00201000
+		0x00201000
+		0x04041000
+		0x10020100
+		0x0003010c
+		0x004b004a
+		0x1a0f0000
+		0x0102041e
+		0x34000000
+		0x00000000
+		0x00000000
+		0x00010000
+		0x00000400
+		0x00310000
+		0x004d4d00
+		0x00120024
+		0x4d000031
+		0x0000144d
+		0x00310009
+		0x004d4d00
+		0x00000004
+		0x4d000031
+		0x0000244d
+		0x00310012
+		0x004d4d00
+		0x00090014
+		0x4d000031
+		0x0004004d
+		0x00310000
+		0x004d4d00
+		0x00120024
+		0x4d000031
+		0x0000144d
+		0x00310009
+		0x004d4d00
+		0x00000004
+		0x4d000031
+		0x0000244d
+		0x00310012
+		0x004d4d00
+		0x00090014
+		0x4d000031
+		0x0200004d
+		0x00c8000d
+		0x08080064
+		0x040a0404
+		0x03000d92
+		0x010a2001
+		0x0f11080a
+		0x0000110a
+		0x2200d92e
+		0x080c2003
+		0x0809080a
+		0x00000a0a
+		0x11006c97
+		0x040a2002
+		0x0200020a
+		0x02000200
+		0x02000200
+		0x02000200
+		0x02000200
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x01000400
+		0x00017600
+		0x00000e9c
+		0x00001850
+		0x0000f320
+		0x00000c20
+		0x00007940
+		0x08000000
+		0x00000100
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000002
+		0x76543210
+		0x0004f008
+		0x00020159
+		0x00000000
+		0x00000000
+		0x00010000
+		0x01665555
+		0x03665555
+		0x00010f00
+		0x04000100
+		0x00000000
+		0x00170180
+		0x00cc0201
+		0x00030066
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x04080000
+		0x04080400
+		0x30000000
+		0x0c00c007
+		0x00000100
+		0x00000000
+		0xfd02fe01
+		0xf708fb04
+		0xdf20ef10
+		0x7f80bf40
+		0x0001aaaa
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00200000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x02800280
+		0x02800280
+		0x02800280
+		0x02800280
+		0x00000280
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00800000
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x01590080
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000200
+		0x00000000
+		0x51315152
+		0xc0003150
+		0x010000c0
+		0x00100c00
+		0x07044204
+		0x000f0c18
+		0x01000140
+		0x00000c10
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x76543210
+		0x0004f008
+		0x00020159
+		0x00000000
+		0x00000000
+		0x00010000
+		0x01665555
+		0x03665555
+		0x00010f00
+		0x04000100
+		0x00000000
+		0x00170180
+		0x00cc0201
+		0x00030066
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x04080000
+		0x04080400
+		0x30000000
+		0x0c00c007
+		0x00000100
+		0x00000000
+		0xfd02fe01
+		0xf708fb04
+		0xdf20ef10
+		0x7f80bf40
+		0x0000aaaa
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00200000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x02800280
+		0x02800280
+		0x02800280
+		0x02800280
+		0x00000280
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00800000
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x01590080
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000200
+		0x00000000
+		0x51315152
+		0xc0003150
+		0x010000c0
+		0x00100c00
+		0x07044204
+		0x000f0c18
+		0x01000140
+		0x00000c10
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x76543210
+		0x0004f008
+		0x00020159
+		0x00000000
+		0x00000000
+		0x00010000
+		0x01665555
+		0x03665555
+		0x00010f00
+		0x04000100
+		0x00000000
+		0x00170180
+		0x00cc0201
+		0x00030066
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x04080000
+		0x04080400
+		0x30000000
+		0x0c00c007
+		0x00000100
+		0x00000000
+		0xfd02fe01
+		0xf708fb04
+		0xdf20ef10
+		0x7f80bf40
+		0x0001aaaa
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00200000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x02800280
+		0x02800280
+		0x02800280
+		0x02800280
+		0x00000280
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00800000
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x01590080
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000200
+		0x00000000
+		0x51315152
+		0xc0003150
+		0x010000c0
+		0x00100c00
+		0x07044204
+		0x000f0c18
+		0x01000140
+		0x00000c10
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x76543210
+		0x0004f008
+		0x00020159
+		0x00000000
+		0x00000000
+		0x00010000
+		0x01665555
+		0x03665555
+		0x00010f00
+		0x04000100
+		0x00000000
+		0x00170180
+		0x00cc0201
+		0x00030066
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x04080000
+		0x04080400
+		0x30000000
+		0x0c00c007
+		0x00000100
+		0x00000000
+		0xfd02fe01
+		0xf708fb04
+		0xdf20ef10
+		0x7f80bf40
+		0x0000aaaa
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00200000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x02800280
+		0x02800280
+		0x02800280
+		0x02800280
+		0x00000280
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00800000
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x01590080
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000200
+		0x00000000
+		0x51315152
+		0xc0003150
+		0x010000c0
+		0x00100c00
+		0x07044204
+		0x000f0c18
+		0x01000140
+		0x00000c10
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000002
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00400320
+		0x00000040
+		0x00dcba98
+		0x00000000
+		0x00dcba98
+		0x01000000
+		0x00020003
+		0x00000000
+		0x00000000
+		0x00000000
+		0x0000002a
+		0x00000015
+		0x00000015
+		0x0000002a
+		0x00000033
+		0x0000000c
+		0x0000000c
+		0x00000033
+		0x0a418820
+		0x003f0000
+		0x0000003f
+		0x00030055
+		0x03000300
+		0x03000300
+		0x000c0300
+		0x42080010
+		0x00000003
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000002
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00400320
+		0x00000040
+		0x00000000
+		0x00000000
+		0x00000000
+		0x01000000
+		0x00020003
+		0x00000000
+		0x00000000
+		0x00000000
+		0x0000002a
+		0x00000015
+		0x00000015
+		0x0000002a
+		0x00000033
+		0x0000000c
+		0x0000000c
+		0x00000033
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00030055
+		0x03000300
+		0x03000300
+		0x000c0300
+		0x42080010
+		0x00000003
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000002
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00400320
+		0x00000040
+		0x00000000
+		0x00000000
+		0x00000000
+		0x01000000
+		0x00020003
+		0x00000000
+		0x00000000
+		0x00000000
+		0x0000002a
+		0x00000015
+		0x00000015
+		0x0000002a
+		0x00000033
+		0x0000000c
+		0x0000000c
+		0x00000033
+		0x1ee6b16a
+		0x10000000
+		0x00000000
+		0x00030055
+		0x03000300
+		0x03000300
+		0x000c0300
+		0x42080010
+		0x00000003
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000005
+		0x04000f01
+		0x00020040
+		0x00020055
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000050
+		0x00000000
+		0x01010100
+		0x00000600
+		0x00000000
+		0x00006400
+		0x09221902
+		0x00000000
+		0x000d1f01
+		0x0d1f0d1f
+		0x0d1f0d1f
+		0x00030003
+		0x03000300
+		0x00000300
+		0x09221902
+		0x00000000
+		0x00000000
+		0x01020000
+		0x00000001
+		0x00000411
+		0x00000411
+		0x00000040
+		0x00000040
+		0x00000411
+		0x00000411
+		0x00004410
+		0x00004410
+		0x00004410
+		0x00004410
+		0x00004410
+		0x00000411
+		0x00004410
+		0x00000411
+		0x00004410
+		0x00000411
+		0x00004410
+		0x00000000
+		0x00000000
+		0x00000000
+		0x64000000
+		0x00000000
+		0x00000000
+		0x00000108
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0xe4000000
+		0x00000000
+		0x00000000
+		0x01010000
+		0x00000000
+	>;
+};
diff --git a/arch/arm/dts/rk3399-u-boot.dtsi b/arch/arm/dts/rk3399-u-boot.dtsi
index fcfce9a..2738a38 100644
--- a/arch/arm/dts/rk3399-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-u-boot.dtsi
@@ -3,6 +3,10 @@
  * Copyright (C) 2019 Jagan Teki <jagan@amarulasolutions.com>
  */
 
+&pmu {
+	u-boot,dm-pre-reloc;
+};
+
 &sdmmc {
 	u-boot,dm-pre-reloc;
 };
diff --git a/arch/arm/dts/stm32f469-disco-u-boot.dtsi b/arch/arm/dts/stm32f469-disco-u-boot.dtsi
index 2409cf7..5a89f13 100644
--- a/arch/arm/dts/stm32f469-disco-u-boot.dtsi
+++ b/arch/arm/dts/stm32f469-disco-u-boot.dtsi
@@ -67,7 +67,7 @@
 		};
 
 		qspi: quadspi@A0001000 {
-			compatible = "st,stm32-qspi";
+			compatible = "st,stm32f469-qspi";
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0xA0001000 0x1000>, <0x90000000 0x10000000>;
diff --git a/arch/arm/dts/stm32f7-u-boot.dtsi b/arch/arm/dts/stm32f7-u-boot.dtsi
index 3ba7f84..32613c9 100644
--- a/arch/arm/dts/stm32f7-u-boot.dtsi
+++ b/arch/arm/dts/stm32f7-u-boot.dtsi
@@ -44,7 +44,7 @@
 		};
 
 		qspi: quadspi@A0001000 {
-			compatible = "st,stm32-qspi";
+			compatible = "st,stm32f469-qspi";
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0xA0001000 0x1000>, <0x90000000 0x10000000>;
diff --git a/arch/arm/dts/sun8i-h3-beelink-x2.dts b/arch/arm/dts/sun8i-h3-beelink-x2.dts
new file mode 100644
index 0000000..25540b7
--- /dev/null
+++ b/arch/arm/dts/sun8i-h3-beelink-x2.dts
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2017 Marcus Cooper <codekipper@gmail.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 "sun8i-h3.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "Beelink X2";
+	compatible = "roofull,beelink-x2", "allwinner,sun8i-h3";
+
+	aliases {
+		serial0 = &uart0;
+		ethernet0 = &emac;
+		ethernet1 = &sdiowifi;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	connector {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_con_in: endpoint {
+				remote-endpoint = <&hdmi_out_con>;
+			};
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		blue {
+			label = "beelink-x2:blue:pwr";
+			gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */
+			default-state = "on";
+		};
+
+		red {
+			label = "beelink-x2:red:standby";
+			gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>; /* PA15 */
+		};
+	};
+
+	wifi_pwrseq: wifi_pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 */
+	};
+
+	sound_spdif {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "On-board SPDIF";
+
+		simple-audio-card,cpu {
+			sound-dai = <&spdif>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&spdif_out>;
+		};
+	};
+
+	spdif_out: spdif-out {
+		#sound-dai-cells = <0>;
+		compatible = "linux,spdif-dit";
+	};
+};
+
+&de {
+	status = "okay";
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&emac {
+	phy-handle = <&int_mii_phy>;
+	phy-mode = "mii";
+	allwinner,leds-active-low;
+	status = "okay";
+};
+
+&hdmi {
+	status = "okay";
+};
+
+&hdmi_out {
+	hdmi_out_con: endpoint {
+		remote-endpoint = <&hdmi_con_in>;
+	};
+};
+
+&ir {
+	pinctrl-names = "default";
+	pinctrl-0 = <&ir_pins_a>;
+	status = "okay";
+};
+
+&mmc0 {
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+	status = "okay";
+};
+
+&mmc1 {
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	non-removable;
+	status = "okay";
+
+	/*
+	 * Explicitly define the sdio device, so that we can add an ethernet
+	 * alias for it (which e.g. makes u-boot set a mac-address).
+	 */
+	sdiowifi: sdio_wifi@1 {
+		reg = <1>;
+	};
+};
+
+&mmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_8bit_pins>;
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <8>;
+	non-removable;
+	cap-mmc-hw-reset;
+	status = "okay";
+};
+
+&ohci0 {
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&reg_usb0_vbus {
+	gpio = <&r_pio 0 2 GPIO_ACTIVE_HIGH>; /* PL2 */
+	status = "okay";
+};
+
+&spdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spdif_tx_pins_a>;
+	status = "okay";
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins_a>;
+	status = "okay";
+};
+
+&usb_otg {
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usbphy {
+	/* USB VBUS is always on except for the OTG port */
+	status = "okay";
+	usb0_id_det-gpios = <&pio 0 7 GPIO_ACTIVE_HIGH>; /* PA07 */
+	usb0_vbus-supply = <&reg_usb0_vbus>;
+};
diff --git a/arch/arm/include/asm/arch-rockchip/pmu_rk3399.h b/arch/arm/include/asm/arch-rockchip/pmu_rk3399.h
new file mode 100644
index 0000000..f1096dc
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/pmu_rk3399.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier:     GPL-2.0+ */
+/*
+ * (C) Copyright 2018 Rockchip Electronics Co., Ltd.
+ *
+ */
+
+#ifndef __SOC_ROCKCHIP_RK3399_PMU_H__
+#define __SOC_ROCKCHIP_RK3399_PMU_H__
+
+struct rk3399_pmu_regs {
+	u32 pmu_wakeup_cfg[5];
+	u32 pmu_pwrdn_con;
+	u32 pmu_pwrdn_st;
+	u32 pmu_pll_con;
+	u32 pmu_pwrmode_con;
+	u32 pmu_sft_con;
+	u32 pmu_int_con;
+	u32 pmu_int_st;
+	u32 pmu_gpio0_pos_int_con;
+	u32 pmu_gpio0_net_int_con;
+	u32 pmu_gpio1_pos_int_con;
+	u32 pmu_gpio1_net_int_con;
+	u32 pmu_gpio0_pos_int_st;
+	u32 pmu_gpio0_net_int_st;
+	u32 pmu_gpio1_pos_int_st;
+	u32 pmu_gpio1_net_int_st;
+	u32 pmu_pwrdn_inten;
+	u32 pmu_pwrdn_status;
+	u32 pmu_wakeup_status;
+	u32 pmu_bus_clr;
+	u32 pmu_bus_idle_req;
+	u32 pmu_bus_idle_st;
+	u32 pmu_bus_idle_ack;
+	u32 pmu_cci500_con;
+	u32 pmu_adb400_con;
+	u32 pmu_adb400_st;
+	u32 pmu_power_st;
+	u32 pmu_core_pwr_st;
+	u32 pmu_osc_cnt;
+	u32 pmu_plllock_cnt;
+	u32 pmu_pllrst_cnt;
+	u32 pmu_stable_cnt;
+	u32 pmu_ddrio_pwron_cnt;
+	u32 pmu_wakeup_rst_clr_cnt;
+	u32 pmu_ddr_sref_st;
+	u32 pmu_scu_l_pwrdn_cnt;
+	u32 pmu_scu_l_pwrup_cnt;
+	u32 pmu_scu_b_pwrdn_cnt;
+	u32 pmu_scu_b_pwrup_cnt;
+	u32 pmu_gpu_pwrdn_cnt;
+	u32 pmu_gpu_pwrup_cnt;
+	u32 pmu_center_pwrdn_cnt;
+	u32 pmu_center_pwrup_cnt;
+	u32 pmu_timeout_cnt;
+	u32 pmu_cpu0apm_con;
+	u32 pmu_cpu1apm_con;
+	u32 pmu_cpu2apm_con;
+	u32 pmu_cpu3apm_con;
+	u32 pmu_cpu0bpm_con;
+	u32 pmu_cpu1bpm_con;
+	u32 pmu_noc_auto_ena;
+	u32 pmu_pwrdn_con1;
+	u32 reserved0[0x4];
+	u32 pmu_sys_reg_reg0;
+	u32 pmu_sys_reg_reg1;
+	u32 pmu_sys_reg_reg2;
+	u32 pmu_sys_reg_reg3;
+};
+
+check_member(rk3399_pmu_regs, pmu_sys_reg_reg3, 0xfc);
+
+#endif	/* __SOC_ROCKCHIP_RK3399_PMU_H__ */
diff --git a/arch/arm/include/asm/arch-rockchip/sdram.h b/arch/arm/include/asm/arch-rockchip/sdram.h
index bbe425d..9220763 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram.h
@@ -8,12 +8,6 @@
 #ifndef _ASM_ARCH_RK3288_SDRAM_H__
 #define _ASM_ARCH_RK3288_SDRAM_H__
 
-enum {
-	DDR3 = 3,
-	LPDDR3 = 6,
-	UNUSED = 0xFF,
-};
-
 struct rk3288_sdram_channel {
 	/*
 	 * bit width in address, eg:
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_common.h b/arch/arm/include/asm/arch-rockchip/sdram_common.h
index 671c318..8027b53 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram_common.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram_common.h
@@ -5,6 +5,44 @@
 
 #ifndef _ASM_ARCH_SDRAM_COMMON_H
 #define _ASM_ARCH_SDRAM_COMMON_H
+
+enum {
+	DDR4 = 0,
+	DDR3 = 0x3,
+	LPDDR2 = 0x5,
+	LPDDR3 = 0x6,
+	LPDDR4 = 0x7,
+	UNUSED = 0xFF
+};
+
+struct sdram_cap_info {
+	unsigned int rank;
+	/* dram column number, 0 means this channel is invalid */
+	unsigned int col;
+	/* dram bank number, 3:8bank, 2:4bank */
+	unsigned int bk;
+	/* channel buswidth, 2:32bit, 1:16bit, 0:8bit */
+	unsigned int bw;
+	/* die buswidth, 2:32bit, 1:16bit, 0:8bit */
+	unsigned int dbw;
+	/*
+	 * row_3_4 = 1: 6Gb or 12Gb die
+	 * row_3_4 = 0: normal die, power of 2
+	 */
+	unsigned int row_3_4;
+	unsigned int cs0_row;
+	unsigned int cs1_row;
+	unsigned int ddrconfig;
+};
+
+struct sdram_base_params {
+	unsigned int ddr_freq;
+	unsigned int dramtype;
+	unsigned int num_channels;
+	unsigned int stride;
+	unsigned int odt;
+};
+
 /*
  * sys_reg bitfield struct
  * [31]		row_3_4_ch1
@@ -28,30 +66,82 @@
  * [1:0]	dbw_ch0
 */
 #define SYS_REG_DDRTYPE_SHIFT		13
+#define DDR_SYS_REG_VERSION		2
 #define SYS_REG_DDRTYPE_MASK		7
 #define SYS_REG_NUM_CH_SHIFT		12
 #define SYS_REG_NUM_CH_MASK		1
 #define SYS_REG_ROW_3_4_SHIFT(ch)	(30 + (ch))
 #define SYS_REG_ROW_3_4_MASK		1
+#define SYS_REG_ENC_ROW_3_4(n, ch)	((n) << (30 + (ch)))
 #define SYS_REG_CHINFO_SHIFT(ch)	(28 + (ch))
+#define SYS_REG_ENC_CHINFO(ch)		(1 << SYS_REG_CHINFO_SHIFT(ch))
+#define SYS_REG_ENC_DDRTYPE(n)		((n) << SYS_REG_DDRTYPE_SHIFT)
+#define SYS_REG_ENC_NUM_CH(n)		(((n) - SYS_REG_NUM_CH_MASK) << \
+					SYS_REG_NUM_CH_SHIFT)
 #define SYS_REG_RANK_SHIFT(ch)		(11 + (ch) * 16)
 #define SYS_REG_RANK_MASK		1
+#define SYS_REG_ENC_RANK(n, ch)		(((n) - SYS_REG_RANK_MASK) << \
+					 SYS_REG_RANK_SHIFT(ch))
 #define SYS_REG_COL_SHIFT(ch)		(9 + (ch) * 16)
 #define SYS_REG_COL_MASK		3
+#define SYS_REG_ENC_COL(n, ch)		(((n) - 9) << SYS_REG_COL_SHIFT(ch))
 #define SYS_REG_BK_SHIFT(ch)		(8 + (ch) * 16)
 #define SYS_REG_BK_MASK			1
+#define SYS_REG_ENC_BK(n, ch)		(((n) == 3 ? 0 : 1) << \
+					SYS_REG_BK_SHIFT(ch))
 #define SYS_REG_CS0_ROW_SHIFT(ch)	(6 + (ch) * 16)
 #define SYS_REG_CS0_ROW_MASK		3
 #define SYS_REG_CS1_ROW_SHIFT(ch)	(4 + (ch) * 16)
 #define SYS_REG_CS1_ROW_MASK		3
 #define SYS_REG_BW_SHIFT(ch)		(2 + (ch) * 16)
 #define SYS_REG_BW_MASK			3
+#define SYS_REG_ENC_BW(n, ch)		((2 >> (n)) << SYS_REG_BW_SHIFT(ch))
 #define SYS_REG_DBW_SHIFT(ch)		((ch) * 16)
 #define SYS_REG_DBW_MASK		3
+#define SYS_REG_ENC_DBW(n, ch)		((2 >> (n)) << SYS_REG_DBW_SHIFT(ch))
+
+#define SYS_REG_ENC_VERSION(n)		((n) << 28)
+#define SYS_REG_ENC_CS0_ROW(n, os_reg2, os_reg3, ch) do { \
+			(os_reg2) |= (((n) - 13) & 0x3) << (6 + 16 * (ch)); \
+			(os_reg3) |= ((((n) - 13) & 0x4) >> 2) << \
+				     (5 + 2 * (ch)); \
+		} while (0)
+
+#define SYS_REG_ENC_CS1_ROW(n, os_reg2, os_reg3, ch) do { \
+			(os_reg2) &= (~(0x3 << (4 + 16 * (ch)))); \
+			(os_reg3) &= (~(0x1 << (4 + 2 * (ch)))); \
+			(os_reg2) |= (((n) - 13) & 0x3) << (4 + 16 * (ch)); \
+			(os_reg3) |= ((((n) - 13) & 0x4) >> 2) << \
+				     (4 + 2 * (ch)); \
+		} while (0)
+
+#define SYS_REG_CS1_COL_SHIFT(ch)	(0 + 2 * (ch))
+#define SYS_REG_ENC_CS1_COL(n, ch)      (((n) - 9) << SYS_REG_CS1_COL_SHIFT(ch))
 
 /* Get sdram size decode from reg */
 size_t rockchip_sdram_size(phys_addr_t reg);
 
 /* Called by U-Boot board_init_r for Rockchip SoCs */
 int dram_init(void);
+
+#if !defined(CONFIG_RAM_ROCKCHIP_DEBUG)
+inline void sdram_print_dram_type(unsigned char dramtype)
+{
+}
+
+inline void sdram_print_ddr_info(struct sdram_cap_info *cap_info,
+				 struct sdram_base_params *base)
+{
+}
+
+inline void sdram_print_stride(unsigned int stride)
+{
+}
+#else
+void sdram_print_dram_type(unsigned char dramtype);
+void sdram_print_ddr_info(struct sdram_cap_info *cap_info,
+			  struct sdram_base_params *base);
+void sdram_print_stride(unsigned int stride);
+#endif /* CONFIG_RAM_ROCKCHIP_DEBUG */
+
 #endif
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rk322x.h b/arch/arm/include/asm/arch-rockchip/sdram_rk322x.h
index d0091a7..336c5d7 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram_rk322x.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram_rk322x.h
@@ -7,13 +7,6 @@
 
 #include <common.h>
 
-enum {
-	DDR3		= 3,
-	LPDDR2		= 5,
-	LPDDR3		= 6,
-	UNUSED		= 0xFF,
-};
-
 struct rk322x_sdram_channel {
 	/*
 	 * bit width in address, eg:
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h b/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
index c6a260b..dc65ae7 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
@@ -6,14 +6,6 @@
 #ifndef _ASM_ARCH_SDRAM_RK3399_H
 #define _ASM_ARCH_SDRAM_RK3399_H
 
-enum {
-	DDR3 = 0x3,
-	LPDDR2 = 0x5,
-	LPDDR3 = 0x6,
-	LPDDR4 = 0x7,
-	UNUSED = 0xFF
-};
-
 struct rk3399_ddr_pctl_regs {
 	u32 denali_ctl[332];
 };
@@ -26,6 +18,31 @@
 	u32 denali_pi[200];
 };
 
+union noc_ddrtimingc0 {
+	u32 d32;
+	struct {
+		unsigned burstpenalty : 4;
+		unsigned reserved0 : 4;
+		unsigned wrtomwr : 6;
+		unsigned reserved1 : 18;
+	} b;
+};
+
+union noc_ddrmode {
+	u32 d32;
+	struct {
+		unsigned autoprecharge : 1;
+		unsigned bypassfiltering : 1;
+		unsigned fawbank : 1;
+		unsigned burstsize : 2;
+		unsigned mwrsize : 2;
+		unsigned reserved2 : 1;
+		unsigned forceorder : 8;
+		unsigned forceorderstate : 8;
+		unsigned reserved3 : 8;
+	} b;
+};
+
 struct rk3399_msch_regs {
 	u32 coreid;
 	u32 revisionid;
@@ -44,9 +61,9 @@
 struct rk3399_msch_timings {
 	u32 ddrtiminga0;
 	u32 ddrtimingb0;
-	u32 ddrtimingc0;
+	union noc_ddrtimingc0 ddrtimingc0;
 	u32 devtodev0;
-	u32 ddrmode;
+	union noc_ddrmode ddrmode;
 	u32 agingx0;
 };
 
@@ -72,37 +89,13 @@
 #define MEM_RST_VALID	1
 
 struct rk3399_sdram_channel {
-	unsigned int rank;
-	/* dram column number, 0 means this channel is invalid */
-	unsigned int col;
-	/* dram bank number, 3:8bank, 2:4bank */
-	unsigned int bk;
-	/* channel buswidth, 2:32bit, 1:16bit, 0:8bit */
-	unsigned int bw;
-	/* die buswidth, 2:32bit, 1:16bit, 0:8bit */
-	unsigned int dbw;
-	/*
-	 * row_3_4 = 1: 6Gb or 12Gb die
-	 * row_3_4 = 0: normal die, power of 2
-	 */
-	unsigned int row_3_4;
-	unsigned int cs0_row;
-	unsigned int cs1_row;
-	unsigned int ddrconfig;
+	struct sdram_cap_info cap_info;
 	struct rk3399_msch_timings noc_timings;
 };
 
-struct rk3399_base_params {
-	unsigned int ddr_freq;
-	unsigned int dramtype;
-	unsigned int num_channels;
-	unsigned int stride;
-	unsigned int odt;
-};
-
 struct rk3399_sdram_params {
 	struct rk3399_sdram_channel ch[2];
-	struct rk3399_base_params base;
+	struct sdram_base_params base;
 	struct rk3399_ddr_pctl_regs pctl_regs;
 	struct rk3399_ddr_pi_regs pi_regs;
 	struct rk3399_ddr_publ_regs phy_regs;
diff --git a/arch/arm/include/asm/arch-rockchip/sys_proto.h b/arch/arm/include/asm/arch-rockchip/sys_proto.h
index 928e4f2..905c774 100644
--- a/arch/arm/include/asm/arch-rockchip/sys_proto.h
+++ b/arch/arm/include/asm/arch-rockchip/sys_proto.h
@@ -6,28 +6,6 @@
 #ifndef _ASM_ARCH_SYS_PROTO_H
 #define _ASM_ARCH_SYS_PROTO_H
 
-#ifdef CONFIG_ROCKCHIP_RK3288
-#include <asm/armv7.h>
-
-static void configure_l2ctlr(void)
-{
-	uint32_t l2ctlr;
-
-	l2ctlr = read_l2ctlr();
-	l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */
-
-	/*
-	* Data RAM write latency: 2 cycles
-	* Data RAM read latency: 2 cycles
-	* Data RAM setup latency: 1 cycle
-	* Tag RAM write latency: 1 cycle
-	* Tag RAM read latency: 1 cycle
-	* Tag RAM setup latency: 1 cycle
-	*/
-	l2ctlr |= (1 << 3 | 1 << 0);
-	write_l2ctlr(l2ctlr);
-}
-#endif /* CONFIG_ROCKCHIP_RK3288 */
 
 /* provided to defeat compiler optimisation in board_init_f() */
 void gru_dummy_function(int i);
diff --git a/arch/arm/include/asm/arch-rockchip/timer.h b/arch/arm/include/asm/arch-rockchip/timer.h
index a8379be..77b5422 100644
--- a/arch/arm/include/asm/arch-rockchip/timer.h
+++ b/arch/arm/include/asm/arch-rockchip/timer.h
@@ -15,7 +15,4 @@
 	u32 timer_int_status;
 };
 
-void rockchip_timer_init(void);
-void rockchip_udelay(unsigned int usec);
-
 #endif
diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h
index eeb4da5..0a1da02 100644
--- a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h
@@ -9,6 +9,8 @@
 #ifndef _SUNXI_DRAM_SUN50I_H6_H
 #define _SUNXI_DRAM_SUN50I_H6_H
 
+#include <stdbool.h>
+
 enum sunxi_dram_type {
 	SUNXI_DRAM_TYPE_DDR3 = 3,
 	SUNXI_DRAM_TYPE_DDR4,
@@ -16,6 +18,11 @@
 	SUNXI_DRAM_TYPE_LPDDR3,
 };
 
+static inline bool sunxi_dram_is_lpddr(int type)
+{
+	return type >= SUNXI_DRAM_TYPE_LPDDR2;
+}
+
 /*
  * The following information is mainly retrieved by disassembly and some FPGA
  * test code of sun50iw3 platform.
@@ -286,6 +293,32 @@
 #define DCR_DDR3	(3 << 0)
 #define DCR_DDR4	(4 << 0)
 #define DCR_DDR8BANK	BIT(3)
+#define DCR_DDR2T	BIT(28)
+
+/*
+ * The delay parameters allow to allegedly specify delay times of some
+ * unknown unit for each individual bit trace in each of the four data bytes
+ * the 32-bit wide access consists of. Also three control signals can be
+ * adjusted individually.
+ */
+#define NR_OF_BYTE_LANES	(32 / BITS_PER_BYTE)
+/* The eight data lines (DQn) plus DM, DQS, DQS/DM/DQ Output Enable and DQSN */
+#define WR_LINES_PER_BYTE_LANE	(BITS_PER_BYTE + 4)
+/*
+ * The eight data lines (DQn) plus DM, DQS, DQS/DM/DQ Output Enable, DQSN,
+ * Termination and Power down
+ */
+#define RD_LINES_PER_BYTE_LANE	(BITS_PER_BYTE + 6)
+struct dram_para {
+	u32 clk;
+	enum sunxi_dram_type type;
+	u8 cols;
+	u8 rows;
+	u8 ranks;
+	const u8 dx_read_delays[NR_OF_BYTE_LANES][RD_LINES_PER_BYTE_LANE];
+	const u8 dx_write_delays[NR_OF_BYTE_LANES][WR_LINES_PER_BYTE_LANE];
+};
+
 
 static inline int ns_to_t(int nanoseconds)
 {
@@ -294,4 +327,6 @@
 	return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
 }
 
+void mctl_set_timing_params(struct dram_para *para);
+
 #endif /* _SUNXI_DRAM_SUN50I_H6_H */
diff --git a/arch/arm/include/asm/omap_i2c.h b/arch/arm/include/asm/omap_i2c.h
index c1695cb..a697540 100644
--- a/arch/arm/include/asm/omap_i2c.h
+++ b/arch/arm/include/asm/omap_i2c.h
@@ -3,8 +3,6 @@
 #ifndef _OMAP_I2C_H
 #define _OMAP_I2C_H
 
-#include <asm/arch/cpu.h>
-
 #ifdef CONFIG_DM_I2C
 
 /* Information about a GPIO bank */
diff --git a/arch/arm/include/asm/proc-armv/ptrace.h b/arch/arm/include/asm/proc-armv/ptrace.h
index 183b00a..e37ad8f 100644
--- a/arch/arm/include/asm/proc-armv/ptrace.h
+++ b/arch/arm/include/asm/proc-armv/ptrace.h
@@ -86,7 +86,7 @@
 #define user_mode(regs)	\
 	(((regs)->ARM_cpsr & 0xf) == 0)
 
-#ifdef CONFIG_ARM_THUMB
+#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD)
 #define thumb_mode(regs) \
 	(((regs)->ARM_cpsr & T_BIT))
 #else
diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S
index 30fba20..c74641d 100644
--- a/arch/arm/lib/crt0.S
+++ b/arch/arm/lib/crt0.S
@@ -58,6 +58,33 @@
  */
 
 /*
+ * Macro for clearing BSS during SPL execution. Usually called during the
+ * relocation process for most boards before entering board_init_r(), but
+ * can also be done early before entering board_init_f() on plaforms that
+ * can afford it due to sufficient memory being available early.
+ */
+
+.macro SPL_CLEAR_BSS
+	ldr	r0, =__bss_start	/* this is auto-relocated! */
+
+#ifdef CONFIG_USE_ARCH_MEMSET
+	ldr	r3, =__bss_end		/* this is auto-relocated! */
+	mov	r1, #0x00000000		/* prepare zero to clear BSS */
+
+	subs	r2, r3, r0		/* r2 = memset len */
+	bl	memset
+#else
+	ldr	r1, =__bss_end		/* this is auto-relocated! */
+	mov	r2, #0x00000000		/* prepare zero to clear BSS */
+
+clbss_l:cmp	r0, r1			/* while not at end of BSS */
+	strlo	r2, [r0]		/* clear 32-bit BSS word */
+	addlo	r0, r0, #4		/* move to next */
+	blo	clbss_l
+#endif
+.endm
+
+/*
  * entry point of crt0 sequence
  */
 
@@ -82,6 +109,10 @@
 	mov	r9, r0
 	bl	board_init_f_init_reserve
 
+#if defined(CONFIG_SPL_EARLY_BSS)
+	SPL_CLEAR_BSS
+#endif
+
 	mov	r0, #0
 	bl	board_init_f
 
@@ -119,6 +150,11 @@
 	bl	c_runtime_cpu_setup	/* we still call old routine here */
 #endif
 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)
+
+#if !defined(CONFIG_SPL_EARLY_BSS)
+	SPL_CLEAR_BSS
+#endif
+
 # ifdef CONFIG_SPL_BUILD
 	/* Use a DRAM stack for the rest of SPL, if requested */
 	bl	spl_relocate_stack_gd
@@ -126,23 +162,6 @@
 	movne	sp, r0
 	movne	r9, r0
 # endif
-	ldr	r0, =__bss_start	/* this is auto-relocated! */
-
-#ifdef CONFIG_USE_ARCH_MEMSET
-	ldr	r3, =__bss_end		/* this is auto-relocated! */
-	mov	r1, #0x00000000		/* prepare zero to clear BSS */
-
-	subs	r2, r3, r0		/* r2 = memset len */
-	bl	memset
-#else
-	ldr	r1, =__bss_end		/* this is auto-relocated! */
-	mov	r2, #0x00000000		/* prepare zero to clear BSS */
-
-clbss_l:cmp	r0, r1			/* while not at end of BSS */
-	strlo	r2, [r0]		/* clear 32-bit BSS word */
-	addlo	r0, r0, #4		/* move to next */
-	blo	clbss_l
-#endif
 
 #if ! defined(CONFIG_SPL_BUILD)
 	bl coloured_LED_init
diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig
index e677a2e..f25f822 100644
--- a/arch/arm/mach-k3/Kconfig
+++ b/arch/arm/mach-k3/Kconfig
@@ -58,6 +58,45 @@
 	int
 	default 16
 
+config K3_LOAD_SYSFW
+	bool
+	depends on SPL
+
+config K3_SYSFW_IMAGE_NAME
+	string "File name of SYSFW firmware and configuration blob"
+	depends on K3_LOAD_SYSFW
+	default	"sysfw.itb"
+	help
+	  Filename of the combined System Firmware and configuration image tree
+	  blob to be loaded when booting from a filesystem.
+
+config K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT
+	hex "MMC sector to load SYSFW firmware and configuration blob from"
+	depends on K3_LOAD_SYSFW && SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
+	default 0x3600
+	help
+	  Address on the MMC to load the combined System Firmware and
+	  configuration image tree blob from, when the MMC is being used
+	  in raw mode. Units: MMC sectors (1 sector = 512 bytes).
+
+config K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART
+	hex "MMC partition to load SYSFW firmware and configuration blob from"
+	depends on K3_LOAD_SYSFW && SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
+	default 2
+	help
+	  Partition on the MMC to the combined System Firmware and configuration
+	  image tree blob from, when the MMC is being used in raw mode.
+
+config K3_SYSFW_IMAGE_SIZE_MAX
+	int "Amount of memory dynamically allocated for loading SYSFW blob"
+	depends on K3_LOAD_SYSFW
+	default	269000
+	help
+	  Amount of memory (in bytes) reserved through dynamic allocation at
+	  runtime for loading the combined System Firmware and configuration image
+	  tree blob. Keep it as tight as possible, as this directly affects the
+	  overall SPL memory footprint.
+
 config SYS_K3_SPL_ATF
 	bool "Start Cortex-A from SPL"
 	depends on SPL && CPU_V7R
diff --git a/arch/arm/mach-k3/Makefile b/arch/arm/mach-k3/Makefile
index 0c3a4f7..3af7f2e 100644
--- a/arch/arm/mach-k3/Makefile
+++ b/arch/arm/mach-k3/Makefile
@@ -7,4 +7,7 @@
 obj-$(CONFIG_ARM64) += arm64-mmu.o
 obj-$(CONFIG_CPU_V7R) += r5_mpu.o lowlevel_init.o
 obj-$(CONFIG_TI_SECURE_DEVICE) += security.o
+ifeq ($(CONFIG_SPL_BUILD),y)
+obj-$(CONFIG_K3_LOAD_SYSFW) += sysfw-loader.o
+endif
 obj-y += common.o
diff --git a/arch/arm/mach-k3/am6_init.c b/arch/arm/mach-k3/am6_init.c
index 60a5803..cb96581 100644
--- a/arch/arm/mach-k3/am6_init.c
+++ b/arch/arm/mach-k3/am6_init.c
@@ -10,8 +10,12 @@
 #include <asm/io.h>
 #include <spl.h>
 #include <asm/arch/hardware.h>
+#include <asm/arch/sysfw-loader.h>
+#include <asm/arch/sys_proto.h>
 #include "common.h"
 #include <dm.h>
+#include <dm/uclass-internal.h>
+#include <dm/pinctrl.h>
 
 #ifdef CONFIG_SPL_BUILD
 static void mmr_unlock(u32 base, u32 partition)
@@ -63,7 +67,7 @@
 
 void board_init_f(ulong dummy)
 {
-#if defined(CONFIG_K3_AM654_DDRSS)
+#if defined(CONFIG_K3_LOAD_SYSFW) || defined(CONFIG_K3_AM654_DDRSS)
 	struct udevice *dev;
 	int ret;
 #endif
@@ -83,8 +87,33 @@
 	/* Init DM early in-order to invoke system controller */
 	spl_early_init();
 
+#ifdef CONFIG_K3_LOAD_SYSFW
+	/*
+	 * Process pinctrl for the serial0 a.k.a. WKUP_UART0 module and continue
+	 * regardless of the result of pinctrl. Do this without probing the
+	 * device, but instead by searching the device that would request the
+	 * given sequence number if probed. The UART will be used by the system
+	 * firmware (SYSFW) image for various purposes and SYSFW depends on us
+	 * to initialize its pin settings.
+	 */
+	ret = uclass_find_device_by_seq(UCLASS_SERIAL, 0, true, &dev);
+	if (!ret)
+		pinctrl_select_state(dev, "default");
+
+	/*
+	 * Load, start up, and configure system controller firmware. Provide
+	 * the U-Boot console init function to the SYSFW post-PM configuration
+	 * callback hook, effectively switching on (or over) the console
+	 * output.
+	 */
+	k3_sysfw_loader(preloader_console_init);
+#else
 	/* Prepare console output */
 	preloader_console_init();
+#endif
+
+	/* Perform EEPROM-based board detection */
+	do_board_detect();
 
 #ifdef CONFIG_K3_AM654_DDRSS
 	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
diff --git a/arch/arm/mach-k3/include/mach/am6_hardware.h b/arch/arm/mach-k3/include/mach/am6_hardware.h
index 3343233..6df7631 100644
--- a/arch/arm/mach-k3/include/mach/am6_hardware.h
+++ b/arch/arm/mach-k3/include/mach/am6_hardware.h
@@ -44,4 +44,7 @@
 #define CTRLMMR_LOCK_KICK1				0x0100c
 #define CTRLMMR_LOCK_KICK1_UNLOCK_VAL			0xd172bc5a
 
+/* MCU SCRATCHPAD usage */
+#define TI_SRAM_SCRATCH_BOARD_EEPROM_START CONFIG_SYS_K3_MCU_SCRATCHPAD_BASE
+
 #endif /* __ASM_ARCH_AM6_HARDWARE_H */
diff --git a/arch/arm/mach-k3/include/mach/sys_proto.h b/arch/arm/mach-k3/include/mach/sys_proto.h
index 018725b..787a274 100644
--- a/arch/arm/mach-k3/include/mach/sys_proto.h
+++ b/arch/arm/mach-k3/include/mach/sys_proto.h
@@ -12,4 +12,6 @@
 		  u32 bound);
 struct ti_sci_handle *get_ti_sci_handle(void);
 int fdt_fixup_msmc_ram(void *blob, char *parent_path, char *node_name);
+int do_board_detect(void);
+
 #endif
diff --git a/arch/arm/mach-k3/include/mach/sysfw-loader.h b/arch/arm/mach-k3/include/mach/sysfw-loader.h
new file mode 100644
index 0000000..36eb265
--- /dev/null
+++ b/arch/arm/mach-k3/include/mach/sysfw-loader.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ *	Andreas Dannenberg <dannenberg@ti.com>
+ */
+
+#ifndef _SYSFW_LOADER_H_
+#define _SYSFW_LOADER_H_
+
+void k3_sysfw_loader(void (*config_pm_done_callback)(void));
+
+#endif
diff --git a/arch/arm/mach-k3/sysfw-loader.c b/arch/arm/mach-k3/sysfw-loader.c
new file mode 100644
index 0000000..2ede820
--- /dev/null
+++ b/arch/arm/mach-k3/sysfw-loader.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * K3: System Firmware Loader
+ *
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ *	Andreas Dannenberg <dannenberg@ti.com>
+ */
+
+#include <common.h>
+#include <spl.h>
+#include <malloc.h>
+#include <remoteproc.h>
+#include <linux/soc/ti/ti_sci_protocol.h>
+#include <asm/arch/sys_proto.h>
+
+/* Name of the FIT image nodes for SYSFW and its config data */
+#define SYSFW_FIRMWARE			"sysfw.bin"
+#define SYSFW_CFG_BOARD			"board-cfg.bin"
+#define SYSFW_CFG_PM			"pm-cfg.bin"
+#define SYSFW_CFG_RM			"rm-cfg.bin"
+#define SYSFW_CFG_SEC			"sec-cfg.bin"
+
+static bool sysfw_loaded;
+static void *sysfw_load_address;
+
+/*
+ * Populate SPL hook to override the default load address used by the SPL
+ * loader function with a custom address for SYSFW loading.
+ */
+struct image_header *spl_get_load_buffer(ssize_t offset, size_t size)
+{
+	if (sysfw_loaded)
+		return (struct image_header *)(CONFIG_SYS_TEXT_BASE + offset);
+	else if (sysfw_load_address)
+		return sysfw_load_address;
+	else
+		panic("SYSFW load address not defined!");
+}
+
+/*
+ * Populate SPL hook to skip the default SPL loader FIT post-processing steps
+ * during SYSFW loading and return to the calling function so we can perform
+ * our own custom processing.
+ */
+bool spl_load_simple_fit_skip_processing(void)
+{
+	return !sysfw_loaded;
+}
+
+static int fit_get_data_by_name(const void *fit, int images, const char *name,
+				const void **addr, size_t *size)
+{
+	int node_offset;
+
+	node_offset = fdt_subnode_offset(fit, images, name);
+	if (node_offset < 0)
+		return -ENOENT;
+
+	return fit_image_get_data(fit, node_offset, addr, size);
+}
+
+static void k3_sysfw_load_using_fit(void *fit)
+{
+	int images;
+	const void *sysfw_addr;
+	size_t sysfw_size;
+	int ret;
+
+	/* Find the node holding the images information */
+	images = fdt_path_offset(fit, FIT_IMAGES_PATH);
+	if (images < 0)
+		panic("Cannot find /images node (%d)\n", images);
+
+	/* Extract System Firmware (SYSFW) image from FIT */
+	ret = fit_get_data_by_name(fit, images, SYSFW_FIRMWARE,
+				   &sysfw_addr, &sysfw_size);
+	if (ret < 0)
+		panic("Error accessing %s node in FIT (%d)\n", SYSFW_FIRMWARE,
+		      ret);
+
+	/*
+	 * Start up system controller firmware
+	 *
+	 * It is assumed that remoteproc device 0 is the corresponding
+	 * system-controller that runs SYSFW. Make sure DT reflects the same.
+	 */
+	ret = rproc_dev_init(0);
+	if (ret)
+		panic("rproc failed to be initialized (%d)\n", ret);
+
+	ret = rproc_load(0, (ulong)sysfw_addr, (ulong)sysfw_size);
+	if (ret)
+		panic("Firmware failed to start on rproc (%d)\n", ret);
+
+	ret = rproc_start(0);
+	if (ret)
+		panic("Firmware init failed on rproc (%d)\n", ret);
+}
+
+static void k3_sysfw_configure_using_fit(void *fit,
+					 struct ti_sci_handle *ti_sci)
+{
+	struct ti_sci_board_ops *board_ops = &ti_sci->ops.board_ops;
+	int images;
+	const void *cfg_fragment_addr;
+	size_t cfg_fragment_size;
+	int ret;
+
+	/* Find the node holding the images information */
+	images = fdt_path_offset(fit, FIT_IMAGES_PATH);
+	if (images < 0)
+		panic("Cannot find /images node (%d)\n", images);
+
+	/* Extract board configuration from FIT */
+	ret = fit_get_data_by_name(fit, images, SYSFW_CFG_BOARD,
+				   &cfg_fragment_addr, &cfg_fragment_size);
+	if (ret < 0)
+		panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_BOARD,
+		      ret);
+
+	/* Apply board configuration to SYSFW */
+	ret = board_ops->board_config(ti_sci,
+				      (u64)(u32)cfg_fragment_addr,
+				      (u32)cfg_fragment_size);
+	if (ret)
+		panic("Failed to set board configuration (%d)\n", ret);
+
+	/* Extract power/clock (PM) specific configuration from FIT */
+	ret = fit_get_data_by_name(fit, images, SYSFW_CFG_PM,
+				   &cfg_fragment_addr, &cfg_fragment_size);
+	if (ret < 0)
+		panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_PM,
+		      ret);
+
+	/* Apply power/clock (PM) specific configuration to SYSFW */
+	ret = board_ops->board_config_pm(ti_sci,
+					 (u64)(u32)cfg_fragment_addr,
+					 (u32)cfg_fragment_size);
+	if (ret)
+		panic("Failed to set board PM configuration (%d)\n", ret);
+
+	/* Extract resource management (RM) specific configuration from FIT */
+	ret = fit_get_data_by_name(fit, images, SYSFW_CFG_RM,
+				   &cfg_fragment_addr, &cfg_fragment_size);
+	if (ret < 0)
+		panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_RM,
+		      ret);
+
+	/* Apply resource management (RM) configuration to SYSFW */
+	ret = board_ops->board_config_rm(ti_sci,
+					 (u64)(u32)cfg_fragment_addr,
+					 (u32)cfg_fragment_size);
+	if (ret)
+		panic("Failed to set board RM configuration (%d)\n", ret);
+
+	/* Extract security specific configuration from FIT */
+	ret = fit_get_data_by_name(fit, images, SYSFW_CFG_SEC,
+				   &cfg_fragment_addr, &cfg_fragment_size);
+	if (ret < 0)
+		panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_SEC,
+		      ret);
+
+	/* Apply security configuration to SYSFW */
+	ret = board_ops->board_config_security(ti_sci,
+					       (u64)(u32)cfg_fragment_addr,
+					       (u32)cfg_fragment_size);
+	if (ret)
+		panic("Failed to set board security configuration (%d)\n",
+		      ret);
+}
+
+void k3_sysfw_loader(void (*config_pm_done_callback)(void))
+{
+	struct spl_image_info spl_image = { 0 };
+	struct spl_boot_device bootdev = { 0 };
+	struct ti_sci_handle *ti_sci;
+	int ret;
+
+	/* Reserve a block of aligned memory for loading the SYSFW image */
+	sysfw_load_address = memalign(ARCH_DMA_MINALIGN,
+				      CONFIG_K3_SYSFW_IMAGE_SIZE_MAX);
+	if (!sysfw_load_address)
+		panic("Error allocating %u bytes of memory for SYSFW image\n",
+		      CONFIG_K3_SYSFW_IMAGE_SIZE_MAX);
+
+	debug("%s: allocated %u bytes at 0x%p\n", __func__,
+	      CONFIG_K3_SYSFW_IMAGE_SIZE_MAX, sysfw_load_address);
+
+	/* Set load address for legacy modes that bypass spl_get_load_buffer */
+	spl_image.load_addr = (uintptr_t)sysfw_load_address;
+
+	bootdev.boot_device = spl_boot_device();
+
+	/* Load combined System Controller firmware and config data image */
+	switch (bootdev.boot_device) {
+#if CONFIG_IS_ENABLED(MMC_SUPPORT)
+	case BOOT_DEVICE_MMC1:
+	case BOOT_DEVICE_MMC2:
+	case BOOT_DEVICE_MMC2_2:
+		ret = spl_mmc_load(&spl_image, &bootdev,
+#ifdef CONFIG_K3_SYSFW_IMAGE_NAME
+				   CONFIG_K3_SYSFW_IMAGE_NAME,
+#else
+				   NULL,
+#endif
+#ifdef CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART
+				   CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART,
+#else
+				   0,
+#endif
+#ifdef CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT
+				   CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT);
+#else
+				   0);
+#endif
+		break;
+#endif
+	default:
+		panic("Loading SYSFW image from device %u not supported!\n",
+		      bootdev.boot_device);
+	}
+
+	if (ret)
+		panic("Error %d occurred during loading SYSFW image!\n", ret);
+
+	/*
+	 * Now that SYSFW got loaded set helper flag to restore regular SPL
+	 * loader behavior so we can later boot into the next stage as expected.
+	 */
+	sysfw_loaded = true;
+
+	/* Ensure the SYSFW image is in FIT format */
+	if (image_get_magic((const image_header_t *)sysfw_load_address) !=
+	    FDT_MAGIC)
+		panic("SYSFW image not in FIT format!\n");
+
+	/* Extract and start SYSFW */
+	k3_sysfw_load_using_fit(sysfw_load_address);
+
+	/* Get handle for accessing SYSFW services */
+	ti_sci = get_ti_sci_handle();
+
+	/* Parse and apply the different SYSFW configuration fragments */
+	k3_sysfw_configure_using_fit(sysfw_load_address, ti_sci);
+
+	/*
+	 * Now that all clocks and PM aspects are setup, invoke a user-
+	 * provided callback function. Usually this callback would be used
+	 * to setup or re-configure the U-Boot console UART.
+	 */
+	if (config_pm_done_callback)
+		config_pm_done_callback();
+
+	/* Output System Firmware version info */
+	printf("SYSFW ABI: %d.%d (firmware rev 0x%04x '%.*s')\n",
+	       ti_sci->version.abi_major, ti_sci->version.abi_minor,
+	       ti_sci->version.firmware_revision,
+	       sizeof(ti_sci->version.firmware_description),
+	       ti_sci->version.firmware_description);
+}
diff --git a/arch/arm/mach-mediatek/mt7629/lowlevel_init.S b/arch/arm/mach-mediatek/mt7629/lowlevel_init.S
index 3375796..0a0672c 100644
--- a/arch/arm/mach-mediatek/mt7629/lowlevel_init.S
+++ b/arch/arm/mach-mediatek/mt7629/lowlevel_init.S
@@ -4,6 +4,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/proc-armv/ptrace.h>
 
 #define WAIT_CODE_SRAM_BASE	0x0010ff00
 
@@ -27,6 +28,18 @@
 	movt	r0, #0x131
 	mcr	p15, 0, r0, c14, c0, 0
 
+	cps	#MON_MODE
+	mrc	p15, 0, r1, c1, c1, 0	@ Get Secure Config
+	orr	r0, r1, #1
+	mcr	p15, 0, r0, c1, c1, 0	@ Set Non Secure bit
+	isb
+	mov	r0, #0
+	mcrr	p15, 4, r0, r0, c14	@ CNTVOFF = 0
+	isb
+	mcr	p15, 0, r1, c1, c1, 0	@ Set Secure bit
+	isb
+	cps	#SVC_MODE
+
 	/* enable SMP bit */
 	mrc	p15, 0, r0, c1, c0, 1
 	orr	r0, r0, #0x40
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 1090d21..17f31e8 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -59,6 +59,8 @@
 	select SPL_DRIVERS_MISC_SUPPORT
 	imply SPL_SERIAL_SUPPORT
 	imply TPL_SERIAL_SUPPORT
+	imply TPL_BOOTROM_SUPPORT
+	imply TPL_ROCKCHIP_COMMON_BOARD
 	select ROCKCHIP_BROM_HELPER
 	select TPL_LIBCOMMON_SUPPORT
 	select TPL_LIBGENERIC_SUPPORT
@@ -68,19 +70,6 @@
 	  and video codec support. Peripherals include Gigabit Ethernet,
 	  USB2 host and OTG, SDIO, I2S, UART, SPI, I2C and PWMs.
 
-if ROCKCHIP_RK322X
-
-config TPL_TEXT_BASE
-        default 0x10081000
-
-config TPL_MAX_SIZE
-        default 28672
-
-config TPL_STACK
-        default 0x10088000
-
-endif
-
 config ROCKCHIP_RK3288
 	bool "Support Rockchip RK3288"
 	select CPU_V7A
@@ -100,6 +89,7 @@
 	imply TPL_OF_PLATDATA
 	imply TPL_RAM
 	imply TPL_REGMAP
+	imply TPL_ROCKCHIP_COMMON_BOARD
 	imply TPL_SERIAL_SUPPORT
 	imply TPL_SYSCON
 	imply USB_FUNCTION_ROCKUSB
@@ -111,19 +101,6 @@
 	  and video codec support. Peripherals include Gigabit Ethernet,
 	  USB2 host and OTG, SDIO, I2S, UARTs, SPI, I2C and PWMs.
 
-if ROCKCHIP_RK3288
-
-config TPL_TEXT_BASE
-	default 0xff704000
-
-config TPL_MAX_SIZE
-	default 32768
-
-config TPL_STACK
-        default 0xff718000
-
-endif
-
 config ROCKCHIP_RK3328
 	bool "Support Rockchip RK3328"
 	select ARM64
@@ -151,6 +128,7 @@
 	imply SPL_SEPARATE_BSS
 	imply SPL_SERIAL_SUPPORT
 	imply TPL_SERIAL_SUPPORT
+	imply TPL_ROCKCHIP_COMMON_BOARD
 	help
 	  The Rockchip RK3368 is a ARM-based SoC with a octa-core (organised
 	  into a big and little cluster with 4 cores each) Cortex-A53 including
@@ -162,19 +140,6 @@
 	  On-chip peripherals include Gigabit Ethernet, USB2 host and OTG, SDIO,
 	  I2S, UARTs, SPI, I2C and PWMs.
 
-if ROCKCHIP_RK3368
-
-config TPL_TEXT_BASE
-        default 0xff8c1000
-
-config TPL_MAX_SIZE
-        default 28672
-
-config TPL_STACK
-        default 0xff8cffff
-
-endif
-
 config ROCKCHIP_RK3399
 	bool "Support Rockchip RK3399"
 	select ARM64
@@ -209,7 +174,6 @@
 	imply TPL_LIBCOMMON_SUPPORT
 	imply TPL_LIBGENERIC_SUPPORT
 	imply TPL_SYS_MALLOC_SIMPLE
-	imply TPL_BOARD_INIT
 	imply TPL_BOOTROM_SUPPORT
 	imply TPL_DRIVERS_MISC_SUPPORT
 	imply TPL_OF_CONTROL
@@ -219,6 +183,7 @@
 	imply TPL_RAM
 	imply TPL_CLK
 	imply TPL_TINY_MEMSET
+	imply TPL_ROCKCHIP_COMMON_BOARD
 	help
 	  The Rockchip RK3399 is a ARM-based SoC with a dual-core Cortex-A72
 	  and quad-core Cortex-A53.
@@ -227,22 +192,6 @@
 	  and video codec support. Peripherals include Gigabit Ethernet,
 	  USB2 host and OTG, SDIO, I2S, UARTs, SPI, I2C and PWMs.
 
-if ROCKCHIP_RK3399
-
-config TPL_LDSCRIPT
-	default "arch/arm/mach-rockchip/u-boot-tpl-v8.lds"
-
-config TPL_TEXT_BASE
-        default 0xff8c2000
-
-config TPL_MAX_SIZE
-        default 188416
-
-config TPL_STACK
-        default 0xff8effff
-
-endif
-
 config ROCKCHIP_RV1108
 	bool "Support Rockchip RV1108"
 	select CPU_V7A
@@ -278,16 +227,17 @@
           SPL will return to the boot rom, which will then load the U-Boot
           binary to keep going on.
 
+config TPL_ROCKCHIP_COMMON_BOARD
+	bool ""
+	depends on TPL
+	help
+	  Rockchip SoCs have similar boot process, prefer to use TPL for DRAM
+	  init and back to bootrom, and SPL as Trust ATF/U-Boot loader. TPL
+	  common board is a basic TPL board init which can be shared for most
+	  of SoCs to avoid copy-pase for different SoCs.
+
 config ROCKCHIP_BOOT_MODE_REG
 	hex "Rockchip boot mode flag register address"
-	default 0x200081c8 if ROCKCHIP_RK3036
-	default 0x20004040 if ROCKCHIP_RK3188
-	default 0x110005c8 if ROCKCHIP_RK322X
-	default 0xff730094 if ROCKCHIP_RK3288
-	default 0xff738200 if ROCKCHIP_RK3368
-	default 0xff320300 if ROCKCHIP_RK3399
-	default 0x10300580 if ROCKCHIP_RV1108
-	default 0
 	help
 	  The Soc will enter to different boot mode(defined in asm/arch-rockchip/boot_mode.h)
 	  according to the value from this register.
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 23760a9..a12b8d4 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -8,16 +8,12 @@
 # the stack-pointer is valid before switching to the U-Boot stack).
 obj-spl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o
 obj-tpl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o
-
-obj-tpl-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-tpl.o
-obj-tpl-$(CONFIG_ROCKCHIP_RK3368) += rk3368-board-tpl.o
-obj-tpl-$(CONFIG_ROCKCHIP_RK322X) += rk322x-board-tpl.o
-obj-tpl-$(CONFIG_ROCKCHIP_RK3399) += rk3399-board-tpl.o
+obj-tpl-$(CONFIG_TPL_ROCKCHIP_COMMON_BOARD) += tpl.o
 
 obj-spl-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board-spl.o
 obj-spl-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-spl.o
 obj-spl-$(CONFIG_ROCKCHIP_RK322X) += rk322x-board-spl.o spl-boot-order.o
-obj-spl-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-spl.o
+obj-spl-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-spl.o spl-boot-order.o
 obj-spl-$(CONFIG_ROCKCHIP_RK3328) += rk3328-board-spl.o
 obj-spl-$(CONFIG_ROCKCHIP_RK3368) += rk3368-board-spl.o spl-boot-order.o
 obj-spl-$(CONFIG_ROCKCHIP_RK3399) += rk3399-board-spl.o spl-boot-order.o
@@ -41,12 +37,6 @@
 
 obj-$(CONFIG_$(SPL_TPL_)RAM) += sdram_common.o
 
-ifndef CONFIG_ARM64
-ifndef CONFIG_ROCKCHIP_RK3188
-obj-y += rk_timer.o
-endif
-endif
-
 obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036/
 obj-$(CONFIG_ROCKCHIP_RK3128) += rk3128/
 ifndef CONFIG_TPL_BUILD
diff --git a/arch/arm/mach-rockchip/make_fit_atf.py b/arch/arm/mach-rockchip/make_fit_atf.py
index db0ae96..b9a1988 100755
--- a/arch/arm/mach-rockchip/make_fit_atf.py
+++ b/arch/arm/mach-rockchip/make_fit_atf.py
@@ -13,16 +13,7 @@
 import sys
 import getopt
 import logging
-
-# pip install pyelftools
-from elftools.elf.elffile import ELFFile
-
-ELF_SEG_P_TYPE = 'p_type'
-ELF_SEG_P_PADDR = 'p_paddr'
-ELF_SEG_P_VADDR = 'p_vaddr'
-ELF_SEG_P_OFFSET = 'p_offset'
-ELF_SEG_P_FILESZ = 'p_filesz'
-ELF_SEG_P_MEMSZ = 'p_memsz'
+import struct
 
 DT_HEADER = """
 /*
@@ -118,33 +109,19 @@
     file.write('\n')
 
 def generate_atf_fit_dts_uboot(fit_file, uboot_file_name):
-    num_load_seg = 0
-    p_paddr = 0xFFFFFFFF
-    with open(uboot_file_name, 'rb') as uboot_file:
-        uboot = ELFFile(uboot_file)
-        for i in range(uboot.num_segments()):
-            seg = uboot.get_segment(i)
-            if seg.__getitem__(ELF_SEG_P_TYPE) == 'PT_LOAD':
-                p_paddr = seg.__getitem__(ELF_SEG_P_PADDR)
-                num_load_seg = num_load_seg + 1
-
-    assert (p_paddr != 0xFFFFFFFF and num_load_seg == 1)
-
+    segments = unpack_elf(uboot_file_name)
+    if len(segments) != 1:
+        raise ValueError("Invalid u-boot ELF image '%s'" % uboot_file_name)
+    index, entry, p_paddr, data = segments[0]
     fit_file.write(DT_UBOOT % p_paddr)
 
 def generate_atf_fit_dts_bl31(fit_file, bl31_file_name, dtbs_file_name):
-    with open(bl31_file_name, 'rb') as bl31_file:
-        bl31 = ELFFile(bl31_file)
-        elf_entry = bl31.header['e_entry']
-        segments = bl31.num_segments()
-        for i in range(segments):
-            seg = bl31.get_segment(i)
-            if seg.__getitem__(ELF_SEG_P_TYPE) == 'PT_LOAD':
-                paddr = seg.__getitem__(ELF_SEG_P_PADDR)
-                append_bl31_node(fit_file, i + 1, paddr, elf_entry)
+    segments = unpack_elf(bl31_file_name)
+    for index, entry, paddr, data in segments:
+        append_bl31_node(fit_file, index + 1, paddr, entry)
     append_fdt_node(fit_file, dtbs_file_name)
     fit_file.write(DT_IMAGES_NODE_END)
-    append_conf_node(fit_file, dtbs_file_name, segments)
+    append_conf_node(fit_file, dtbs_file_name, len(segments))
 
 def generate_atf_fit_dts(fit_file_name, bl31_file_name, uboot_file_name, dtbs_file_name):
     # Generate FIT script for ATF image.
@@ -162,17 +139,29 @@
         fit_file.close()
 
 def generate_atf_binary(bl31_file_name):
-    with open(bl31_file_name, 'rb') as bl31_file:
-        bl31 = ELFFile(bl31_file)
+    for index, entry, paddr, data in unpack_elf(bl31_file_name):
+        file_name = 'bl31_0x%08x.bin' % paddr
+        with open(file_name, "wb") as atf:
+            atf.write(data)
+
+def unpack_elf(filename):
+    with open(filename, 'rb') as file:
+        elf = file.read()
+    if elf[0:7] != b'\x7fELF\x02\x01\x01' or elf[18:20] != b'\xb7\x00':
+        raise ValueError("Invalid arm64 ELF file '%s'" % filename)
+
+    e_entry, e_phoff = struct.unpack_from('<2Q', elf, 0x18)
+    e_phentsize, e_phnum = struct.unpack_from('<2H', elf, 0x36)
+    segments = []
 
-        num = bl31.num_segments()
-        for i in range(num):
-            seg = bl31.get_segment(i)
-            if seg.__getitem__(ELF_SEG_P_TYPE) == 'PT_LOAD':
-                paddr = seg.__getitem__(ELF_SEG_P_PADDR)
-                file_name = 'bl31_0x%08x.bin' % paddr
-                with open(file_name, "wb") as atf:
-                    atf.write(seg.data())
+    for index in range(e_phnum):
+        offset = e_phoff + e_phentsize * index
+        p_type, p_flags, p_offset = struct.unpack_from('<LLQ', elf, offset)
+        if p_type == 1: # PT_LOAD
+            p_paddr, p_filesz = struct.unpack_from('<2Q', elf, offset + 0x18)
+            p_data = elf[p_offset:p_offset + p_filesz]
+            segments.append((index, e_entry, p_paddr, p_data))
+    return segments
 
 def main():
     uboot_elf = "./u-boot"
diff --git a/arch/arm/mach-rockchip/rk3036-board-spl.c b/arch/arm/mach-rockchip/rk3036-board-spl.c
index 110d06d..fbc89b6 100644
--- a/arch/arm/mach-rockchip/rk3036-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3036-board-spl.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * (C) Copyright 2015 Rockchip Electronics Co., Ltd
+ * (C) Copyright 2015-2019 Rockchip Electronics Co., Ltd
  */
 
 #include <common.h>
@@ -8,14 +8,37 @@
 #include <asm/io.h>
 #include <asm/arch-rockchip/bootrom.h>
 #include <asm/arch-rockchip/sdram_rk3036.h>
-#include <asm/arch-rockchip/timer.h>
+
+#define TIMER_LOAD_COUNT_L	0x00
+#define TIMER_LOAD_COUNT_H	0x04
+#define TIMER_CONTROL_REG	0x10
+#define TIMER_EN	0x1
+#define	TIMER_FMODE	(0 << 1)
+#define	TIMER_RMODE	(1 << 1)
+
+void rockchip_stimer_init(void)
+{
+	asm volatile("mcr p15, 0, %0, c14, c0, 0"
+		     : : "r"(COUNTER_FREQUENCY));
+
+	writel(0, CONFIG_ROCKCHIP_STIMER_BASE + TIMER_CONTROL_REG);
+	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE);
+	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE + 4);
+	writel(TIMER_EN | TIMER_FMODE, CONFIG_ROCKCHIP_STIMER_BASE +
+	       TIMER_CONTROL_REG);
+}
 
 void board_init_f(ulong dummy)
 {
 #ifdef CONFIG_DEBUG_UART
 	debug_uart_init();
 #endif
-	rockchip_timer_init();
+
+	/* Init secure timer */
+	rockchip_stimer_init();
+	/* Init ARM arch timer in arch/arm/cpu/armv7/arch_timer.c */
+	timer_init();
+
 	sdram_init();
 
 	/* return to maskrom */
diff --git a/arch/arm/mach-rockchip/rk3036-board.c b/arch/arm/mach-rockchip/rk3036-board.c
index e6ea0e9..c594c4d 100644
--- a/arch/arm/mach-rockchip/rk3036-board.c
+++ b/arch/arm/mach-rockchip/rk3036-board.c
@@ -14,7 +14,6 @@
 #include <asm/arch-rockchip/grf_rk3036.h>
 #include <asm/arch-rockchip/boot_mode.h>
 #include <asm/arch-rockchip/sdram_rk3036.h>
-#include <dm/pinctrl.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
diff --git a/arch/arm/mach-rockchip/rk3036/Kconfig b/arch/arm/mach-rockchip/rk3036/Kconfig
index 5e04d20..51cd43b 100644
--- a/arch/arm/mach-rockchip/rk3036/Kconfig
+++ b/arch/arm/mach-rockchip/rk3036/Kconfig
@@ -1,5 +1,8 @@
 if ROCKCHIP_RK3036
 
+choice
+	prompt "RK3036 board select"
+
 config TARGET_EVB_RK3036
 	bool "EVB_RK3036"
 	select BOARD_LATE_INIT
@@ -8,6 +11,11 @@
 	bool "KYLIN_RK3036"
 	select BOARD_LATE_INIT
 
+endchoice
+
+config ROCKCHIP_BOOT_MODE_REG
+	default 0x200081c8
+
 config SYS_SOC
 	default "rk3036"
 
diff --git a/arch/arm/mach-rockchip/rk3036/sdram_rk3036.c b/arch/arm/mach-rockchip/rk3036/sdram_rk3036.c
index 1d940a0..c39cbb8 100644
--- a/arch/arm/mach-rockchip/rk3036/sdram_rk3036.c
+++ b/arch/arm/mach-rockchip/rk3036/sdram_rk3036.c
@@ -9,7 +9,6 @@
 #include <asm/arch-rockchip/grf_rk3036.h>
 #include <asm/arch-rockchip/hardware.h>
 #include <asm/arch-rockchip/sdram_rk3036.h>
-#include <asm/arch-rockchip/timer.h>
 #include <asm/arch-rockchip/uart.h>
 
 /*
@@ -345,7 +344,7 @@
 
 	/* waiting for pll lock */
 	while (readl(&pll->con1) & (1 << PLL_LOCK_STATUS_SHIFT))
-		rockchip_udelay(1);
+		udelay(1);
 
 	/* PLL enter normal-mode */
 	rk_clrsetreg(&priv->cru->cru_mode_con, DPLL_MODE_MASK,
@@ -373,25 +372,25 @@
 			1 << DDRCTRL_PSRST_SHIFT | 1 << DDRCTRL_SRST_SHIFT |
 			1 << DDRPHY_PSRST_SHIFT | 1 << DDRPHY_SRST_SHIFT);
 
-	rockchip_udelay(10);
+	udelay(10);
 
 	rk_clrreg(&priv->cru->cru_softrst_con[5], 1 << DDRPHY_PSRST_SHIFT |
 						  1 << DDRPHY_SRST_SHIFT);
-	rockchip_udelay(10);
+	udelay(10);
 
 	rk_clrreg(&priv->cru->cru_softrst_con[5], 1 << DDRCTRL_PSRST_SHIFT |
 						  1 << DDRCTRL_SRST_SHIFT);
-	rockchip_udelay(10);
+	udelay(10);
 
 	clrsetbits_le32(&ddr_phy->ddrphy_reg1,
 			SOFT_RESET_MASK << SOFT_RESET_SHIFT,
 			0 << SOFT_RESET_SHIFT);
-	rockchip_udelay(10);
+	udelay(10);
 	clrsetbits_le32(&ddr_phy->ddrphy_reg1,
 			SOFT_RESET_MASK << SOFT_RESET_SHIFT,
 			3 << SOFT_RESET_SHIFT);
 
-	rockchip_udelay(1);
+	udelay(1);
 }
 
 void phy_dll_bypass_set(struct rk3036_sdram_priv *priv, unsigned int freq)
@@ -444,7 +443,7 @@
 			 u32 rank, u32 cmd, u32 arg)
 {
 	writel((START_CMD | (rank << 20) | arg | cmd), &pctl->mcmd);
-	rockchip_udelay(1);
+	udelay(1);
 	while (readl(&pctl->mcmd) & START_CMD)
 		;
 }
@@ -454,7 +453,7 @@
 	struct rk3036_ddr_pctl *pctl = priv->pctl;
 
 	send_command(pctl, 3, DESELECT_CMD, 0);
-	rockchip_udelay(1);
+	udelay(1);
 	send_command(pctl, 3, PREA_CMD, 0);
 	send_command(pctl, 3, MRS_CMD,
 		     (0x02 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT |
@@ -492,7 +491,7 @@
 	clrsetbits_le32(&ddr_phy->ddrphy_reg2, 0x03,
 			DQS_SQU_CAL_NORMAL_MODE | DQS_SQU_CAL_START);
 
-	rockchip_udelay(1);
+	udelay(1);
 	while ((readl(&ddr_phy->ddrphy_reg62) & CAL_DONE_MASK) !=
 		(HIGH_8BIT_CAL_DONE | LOW_8BIT_CAL_DONE)) {
 		;
diff --git a/arch/arm/mach-rockchip/rk3128-board.c b/arch/arm/mach-rockchip/rk3128-board.c
index fa71685..0945829 100644
--- a/arch/arm/mach-rockchip/rk3128-board.c
+++ b/arch/arm/mach-rockchip/rk3128-board.c
@@ -12,7 +12,6 @@
 #include <asm/arch-rockchip/periph.h>
 #include <asm/arch-rockchip/grf_rk3128.h>
 #include <asm/arch-rockchip/boot_mode.h>
-#include <asm/arch-rockchip/timer.h>
 #include <power/regulator.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -33,8 +32,6 @@
 {
 	int ret = 0;
 
-	rockchip_timer_init();
-
 	ret = regulators_enable_boot_on(false);
 	if (ret) {
 		debug("%s: Cannot enable boot on regulator\n", __func__);
diff --git a/arch/arm/mach-rockchip/rk3128/Kconfig b/arch/arm/mach-rockchip/rk3128/Kconfig
index a82b7dc..b867401 100644
--- a/arch/arm/mach-rockchip/rk3128/Kconfig
+++ b/arch/arm/mach-rockchip/rk3128/Kconfig
@@ -13,6 +13,9 @@
 
 endchoice
 
+config ROCKCHIP_BOOT_MODE_REG
+	default 0x100a0038
+
 config SYS_SOC
 	default "rk3128"
 
diff --git a/arch/arm/mach-rockchip/rk3188-board-spl.c b/arch/arm/mach-rockchip/rk3188-board-spl.c
index 77b9b36..c3efe0d 100644
--- a/arch/arm/mach-rockchip/rk3188-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3188-board-spl.c
@@ -22,8 +22,6 @@
 #include <asm/arch-rockchip/periph.h>
 #include <asm/arch-rockchip/pmu_rk3188.h>
 #include <asm/arch-rockchip/sdram.h>
-#include <asm/arch-rockchip/timer.h>
-#include <dm/pinctrl.h>
 #include <dm/root.h>
 #include <dm/test.h>
 #include <dm/util.h>
diff --git a/arch/arm/mach-rockchip/rk3188-board.c b/arch/arm/mach-rockchip/rk3188-board.c
index 80d8c42..94fd6c0 100644
--- a/arch/arm/mach-rockchip/rk3188-board.c
+++ b/arch/arm/mach-rockchip/rk3188-board.c
@@ -15,7 +15,6 @@
 #include <asm/arch-rockchip/periph.h>
 #include <asm/arch-rockchip/pmu_rk3288.h>
 #include <asm/arch-rockchip/boot_mode.h>
-#include <dm/pinctrl.h>
 
 __weak int rk_board_late_init(void)
 {
@@ -42,37 +41,7 @@
 
 int board_init(void)
 {
-#if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM)
-	struct udevice *pinctrl;
-	int ret;
-
-	/*
-	 * We need to implement sdcard iomux here for the further
-	 * initialization, otherwise, it'll hit sdcard command sending
-	 * timeout exception.
-	 */
-	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
-	if (ret) {
-		debug("%s: Cannot find pinctrl device\n", __func__);
-		goto err;
-	}
-	ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD);
-	if (ret) {
-		debug("%s: Failed to set up SD card\n", __func__);
-		goto err;
-	}
-
-	return 0;
-err:
-	printf("board_init: Error %d\n", ret);
-
-	/* No way to report error here */
-	hang();
-
-	return -1;
-#else
 	return 0;
-#endif
 }
 
 #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
diff --git a/arch/arm/mach-rockchip/rk3188/Kconfig b/arch/arm/mach-rockchip/rk3188/Kconfig
index a6fc691..e24e68e 100644
--- a/arch/arm/mach-rockchip/rk3188/Kconfig
+++ b/arch/arm/mach-rockchip/rk3188/Kconfig
@@ -9,6 +9,9 @@
 	  Expansion connectors provide access to display pins, I2C, SPI,
 	  UART and GPIOs.
 
+config ROCKCHIP_BOOT_MODE_REG
+	default 0x20004040
+
 config SYS_SOC
 	default "rk3188"
 
diff --git a/arch/arm/mach-rockchip/rk322x-board-spl.c b/arch/arm/mach-rockchip/rk322x-board-spl.c
index c9b41c6..c825e31 100644
--- a/arch/arm/mach-rockchip/rk322x-board-spl.c
+++ b/arch/arm/mach-rockchip/rk322x-board-spl.c
@@ -19,6 +19,31 @@
 	return MMCSD_MODE_RAW;
 }
 
+#define TIMER_LOAD_COUNT_L	0x00
+#define TIMER_LOAD_COUNT_H	0x04
+#define TIMER_CONTROL_REG	0x10
+#define TIMER_EN	0x1
+#define	TIMER_FMODE	BIT(0)
+#define	TIMER_RMODE	BIT(1)
+
+void rockchip_stimer_init(void)
+{
+	/* If Timer already enabled, don't re-init it */
+	u32 reg = readl(CONFIG_ROCKCHIP_STIMER_BASE + TIMER_CONTROL_REG);
+
+	if (reg & TIMER_EN)
+		return;
+
+	asm volatile("mcr p15, 0, %0, c14, c0, 0"
+		     : : "r"(COUNTER_FREQUENCY));
+
+	writel(0, CONFIG_ROCKCHIP_STIMER_BASE + TIMER_CONTROL_REG);
+	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE);
+	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE + 4);
+	writel(TIMER_EN | TIMER_FMODE, CONFIG_ROCKCHIP_STIMER_BASE +
+	       TIMER_CONTROL_REG);
+}
+
 #define SGRF_DDR_CON0 0x10150000
 void board_init_f(ulong dummy)
 {
@@ -31,6 +56,11 @@
 	}
 	preloader_console_init();
 
+	/* Init secure timer */
+	rockchip_stimer_init();
+	/* Init ARM arch timer in arch/arm/cpu/armv7/arch_timer.c */
+	timer_init();
+
 	/* Disable the ddr secure region setting to make it non-secure */
 	rk_clrreg(SGRF_DDR_CON0, 0x4000);
 }
diff --git a/arch/arm/mach-rockchip/rk322x-board-tpl.c b/arch/arm/mach-rockchip/rk322x-board-tpl.c
deleted file mode 100644
index 92d40ee..0000000
--- a/arch/arm/mach-rockchip/rk322x-board-tpl.c
+++ /dev/null
@@ -1,53 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2019 Rockchip Electronics Co., Ltd
- */
-
-#include <common.h>
-#include <debug_uart.h>
-#include <dm.h>
-#include <ram.h>
-#include <spl.h>
-#include <asm/io.h>
-#include <asm/arch-rockchip/bootrom.h>
-#include <asm/arch-rockchip/timer.h>
-
-u32 spl_boot_device(void)
-{
-	return BOOT_DEVICE_MMC1;
-}
-
-void board_init_f(ulong dummy)
-{
-	struct udevice *dev;
-	int ret;
-
-	/*
-	 * Debug UART can be used from here if required:
-	 *
-	 * debug_uart_init();
-	 * printch('a');
-	 * printhex8(0x1234);
-	 * printascii("string");
-	 */
-	debug_uart_init();
-	printascii("TPL Init");
-
-	ret = spl_early_init();
-	if (ret) {
-		debug("spl_early_init() failed: %d\n", ret);
-		hang();
-	}
-
-	rockchip_timer_init();
-	printf("timer init done\n");
-	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
-	if (ret) {
-		printf("DRAM init failed: %d\n", ret);
-		return;
-	}
-
-#if defined(CONFIG_TPL_ROCKCHIP_BACK_TO_BROM) && !defined(CONFIG_TPL_BOARD_INIT)
-	back_to_bootrom(BROM_BOOT_NEXTSTAGE);
-#endif
-}
diff --git a/arch/arm/mach-rockchip/rk322x/Kconfig b/arch/arm/mach-rockchip/rk322x/Kconfig
index 8a1f95f..2fc6f6e 100644
--- a/arch/arm/mach-rockchip/rk322x/Kconfig
+++ b/arch/arm/mach-rockchip/rk322x/Kconfig
@@ -1,18 +1,37 @@
 if ROCKCHIP_RK322X
 
+
 config TARGET_EVB_RK3229
 	bool "EVB_RK3229"
 	select BOARD_LATE_INIT
 
+config ROCKCHIP_BOOT_MODE_REG
+	default 0x110005c8
+
 config SYS_SOC
 	default "rk322x"
 
 config SYS_MALLOC_F_LEN
-	default 0x400
+	default 0x800
+
+config SPL_LIBCOMMON_SUPPORT
+	default y
+
+config SPL_LIBGENERIC_SUPPORT
+	default y
 
 config SPL_SERIAL_SUPPORT
 	default y
 
+config TPL_MAX_SIZE
+        default 28672
+
+config TPL_STACK
+        default 0x10088000
+
+config TPL_TEXT_BASE
+        default 0x10081000
+
 source "board/rockchip/evb_rk3229/Kconfig"
 
 endif
diff --git a/arch/arm/mach-rockchip/rk3288-board-spl.c b/arch/arm/mach-rockchip/rk3288-board-spl.c
index d8d215d..c2e1681 100644
--- a/arch/arm/mach-rockchip/rk3288-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3288-board-spl.c
@@ -22,8 +22,6 @@
 #include <asm/arch-rockchip/sdram.h>
 #include <asm/arch-rockchip/sdram_common.h>
 #include <asm/arch-rockchip/sys_proto.h>
-#include <asm/arch-rockchip/timer.h>
-#include <dm/pinctrl.h>
 #include <dm/root.h>
 #include <dm/test.h>
 #include <dm/util.h>
@@ -104,6 +102,36 @@
 }
 #endif
 
+__weak int arch_cpu_init(void)
+{
+	return 0;
+}
+
+#define TIMER_LOAD_COUNT_L	0x00
+#define TIMER_LOAD_COUNT_H	0x04
+#define TIMER_CONTROL_REG	0x10
+#define TIMER_EN	0x1
+#define	TIMER_FMODE	BIT(0)
+#define	TIMER_RMODE	BIT(1)
+
+void rockchip_stimer_init(void)
+{
+	/* If Timer already enabled, don't re-init it */
+	u32 reg = readl(CONFIG_ROCKCHIP_STIMER_BASE + TIMER_CONTROL_REG);
+
+	if (reg & TIMER_EN)
+		return;
+
+	asm volatile("mcr p15, 0, %0, c14, c0, 0"
+		     : : "r"(COUNTER_FREQUENCY));
+
+	writel(0, CONFIG_ROCKCHIP_STIMER_BASE + TIMER_CONTROL_REG);
+	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE);
+	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE + 4);
+	writel(TIMER_EN | TIMER_FMODE, CONFIG_ROCKCHIP_STIMER_BASE +
+	       TIMER_CONTROL_REG);
+}
+
 void board_init_f(ulong dummy)
 {
 	struct udevice *dev;
@@ -127,8 +155,12 @@
 		hang();
 	}
 
-	rockchip_timer_init();
-	configure_l2ctlr();
+	/* Init secure timer */
+	rockchip_stimer_init();
+	/* Init ARM arch timer in arch/arm/cpu/armv7/arch_timer.c */
+	timer_init();
+
+	arch_cpu_init();
 
 	ret = rockchip_get_clk(&dev);
 	if (ret) {
diff --git a/arch/arm/mach-rockchip/rk3288-board-tpl.c b/arch/arm/mach-rockchip/rk3288-board-tpl.c
deleted file mode 100644
index 787129b..0000000
--- a/arch/arm/mach-rockchip/rk3288-board-tpl.c
+++ /dev/null
@@ -1,70 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2017 Amarula Solutions
- */
-
-#include <common.h>
-#include <debug_uart.h>
-#include <dm.h>
-#include <ram.h>
-#include <spl.h>
-#include <version.h>
-#include <asm/io.h>
-#include <asm/arch-rockchip/bootrom.h>
-#include <asm/arch-rockchip/clock.h>
-#include <asm/arch-rockchip/sys_proto.h>
-#include <asm/arch-rockchip/timer.h>
-
-void board_init_f(ulong dummy)
-{
-	struct udevice *dev;
-	int ret;
-
-#ifdef CONFIG_DEBUG_UART
-	/*
-	 * Debug UART can be used from here if required:
-	 *
-	 * debug_uart_init();
-	 * printch('a');
-	 * printhex8(0x1234);
-	 * printascii("string");
-	 */
-	debug_uart_init();
-#endif
-	ret = spl_early_init();
-	if (ret) {
-		debug("spl_early_init() failed: %d\n", ret);
-		hang();
-	}
-
-	rockchip_timer_init();
-	configure_l2ctlr();
-
-	ret = rockchip_get_clk(&dev);
-	if (ret) {
-		debug("CLK init failed: %d\n", ret);
-		return;
-	}
-
-	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
-	if (ret) {
-		debug("DRAM init failed: %d\n", ret);
-		return;
-	}
-}
-
-void board_return_to_bootrom(void)
-{
-	back_to_bootrom(BROM_BOOT_NEXTSTAGE);
-}
-
-u32 spl_boot_device(void)
-{
-	return BOOT_DEVICE_BOOTROM;
-}
-
-void spl_board_init(void)
-{
-	puts("\nU-Boot TPL " PLAIN_VERSION " (" U_BOOT_DATE " - " \
-				U_BOOT_TIME ")\n");
-}
diff --git a/arch/arm/mach-rockchip/rk3288-board.c b/arch/arm/mach-rockchip/rk3288-board.c
index e2de5b2..a250d50 100644
--- a/arch/arm/mach-rockchip/rk3288-board.c
+++ b/arch/arm/mach-rockchip/rk3288-board.c
@@ -16,7 +16,6 @@
 #include <asm/arch-rockchip/qos_rk3288.h>
 #include <asm/arch-rockchip/boot_mode.h>
 #include <asm/gpio.h>
-#include <dm/pinctrl.h>
 #include <dt-bindings/clock/rk3288-cru.h>
 #include <power/regulator.h>
 
@@ -145,33 +144,7 @@
 int board_init(void)
 {
 #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM)
-	struct udevice *pinctrl;
-	int ret;
-
-	/*
-	 * We need to implement sdcard iomux here for the further
-	 * initlization, otherwise, it'll hit sdcard command sending
-	 * timeout exception.
-	 */
-	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
-	if (ret) {
-		debug("%s: Cannot find pinctrl device\n", __func__);
-		goto err;
-	}
-	ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD);
-	if (ret) {
-		debug("%s: Failed to set up SD card\n", __func__);
-		goto err;
-	}
-
 	return 0;
-err:
-	printf("board_init: Error %d\n", ret);
-
-	/* No way to report error here */
-	hang();
-
-	return -1;
 #else
 	int ret;
 
diff --git a/arch/arm/mach-rockchip/rk3288/Kconfig b/arch/arm/mach-rockchip/rk3288/Kconfig
index c5dcd06..de8d9c2 100644
--- a/arch/arm/mach-rockchip/rk3288/Kconfig
+++ b/arch/arm/mach-rockchip/rk3288/Kconfig
@@ -1,5 +1,8 @@
 if ROCKCHIP_RK3288
 
+choice
+	prompt "RK3288 board select"
+
 config TARGET_CHROMEBOOK_JERRY
 	bool "Google/Rockchip Veyron-Jerry Chromebook"
 	select BOARD_LATE_INIT
@@ -44,6 +47,7 @@
 config TARGET_EVB_RK3288
 	bool "Evb-RK3288"
 	select BOARD_LATE_INIT
+	select TPL
 	help
 	  EVB-RK3288 is a RK3288-based development board with 2 USB ports,
 	  HDMI, VGA, micro-SD card, audio, WiFi  and Gigabit Ethernet, It
@@ -125,6 +129,8 @@
 	  8GB eMMC and 2GB of SDRAM. Expansion connectors provide access to
 	  I2C, SPI, UART, GPIOs.
 
+endchoice
+
 config ROCKCHIP_FAST_SPL
 	bool "Change the CPU to full speed in SPL"
 	depends on TARGET_CHROMEBOOK_JERRY
@@ -134,11 +140,14 @@
 	  voltage. This option is only available on boards which support it
 	  and have the required PMIC code.
 
+config ROCKCHIP_BOOT_MODE_REG
+	default 0xff730094
+
 config SYS_SOC
 	default "rk3288"
 
 config SYS_MALLOC_F_LEN
-	default 0x0800
+	default 0x2000
 
 config SPL_DRIVERS_MISC_SUPPORT
 	default y
@@ -152,6 +161,18 @@
 config SPL_SERIAL_SUPPORT
 	default y
 
+config TPL_LDSCRIPT
+	default "arch/arm/mach-rockchip/u-boot-tpl.lds"
+
+config TPL_MAX_SIZE
+	default 32768
+
+config TPL_STACK
+        default 0xff718000
+
+config TPL_TEXT_BASE
+	default 0xff704000
+
 source "board/amarula/vyasa-rk3288/Kconfig"
 
 source "board/chipspark/popmetal_rk3288/Kconfig"
diff --git a/arch/arm/mach-rockchip/rk3288/rk3288.c b/arch/arm/mach-rockchip/rk3288/rk3288.c
index 7941ca6..7552472 100644
--- a/arch/arm/mach-rockchip/rk3288/rk3288.c
+++ b/arch/arm/mach-rockchip/rk3288/rk3288.c
@@ -2,19 +2,45 @@
 /*
  * Copyright (c) 2016 Rockchip Electronics Co., Ltd
  */
+#include <asm/armv7.h>
 #include <asm/io.h>
 #include <asm/arch-rockchip/hardware.h>
 #include <asm/arch-rockchip/grf_rk3288.h>
 
 #define GRF_BASE	0xff770000
 
+#ifdef CONFIG_SPL_BUILD
+static void configure_l2ctlr(void)
+{
+	u32 l2ctlr;
+
+	l2ctlr = read_l2ctlr();
+	l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */
+
+	/*
+	 * Data RAM write latency: 2 cycles
+	 * Data RAM read latency: 2 cycles
+	 * Data RAM setup latency: 1 cycle
+	 * Tag RAM write latency: 1 cycle
+	 * Tag RAM read latency: 1 cycle
+	 * Tag RAM setup latency: 1 cycle
+	 */
+	l2ctlr |= (1 << 3 | 1 << 0);
+	write_l2ctlr(l2ctlr);
+}
+#endif
+
 int arch_cpu_init(void)
 {
+#ifdef CONFIG_SPL_BUILD
+	configure_l2ctlr();
+#else
 	/* We do some SoC one time setting here. */
 	struct rk3288_grf * const grf = (void *)GRF_BASE;
 
 	/* Use rkpwm by default */
 	rk_setreg(&grf->soc_con2, 1 << 0);
+#endif
 
 	return 0;
 }
diff --git a/arch/arm/mach-rockchip/rk3328-board-spl.c b/arch/arm/mach-rockchip/rk3328-board-spl.c
index 7f49d05..f24fd89 100644
--- a/arch/arm/mach-rockchip/rk3328-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3328-board-spl.c
@@ -7,7 +7,6 @@
 #include <common.h>
 #include <debug_uart.h>
 #include <dm.h>
-#include <dm/pinctrl.h>
 #include <ram.h>
 #include <spl.h>
 #include <asm/io.h>
diff --git a/arch/arm/mach-rockchip/rk3328/Kconfig b/arch/arm/mach-rockchip/rk3328/Kconfig
index 6c5c430..f8e1528 100644
--- a/arch/arm/mach-rockchip/rk3328/Kconfig
+++ b/arch/arm/mach-rockchip/rk3328/Kconfig
@@ -12,11 +12,20 @@
 
 endchoice
 
+config ROCKCHIP_BOOT_MODE_REG
+	default 0xff1005c8
+
 config SYS_SOC
 	default "rk3328"
 
 config SYS_MALLOC_F_LEN
-	default 0x0800
+	default 0x2000
+
+config SPL_LIBCOMMON_SUPPORT
+	default y
+
+config SPL_LIBGENERIC_SUPPORT
+	default y
 
 source "board/rockchip/evb_rk3328/Kconfig"
 
diff --git a/arch/arm/mach-rockchip/rk3368-board-spl.c b/arch/arm/mach-rockchip/rk3368-board-spl.c
index c651193..6ba106c6 100644
--- a/arch/arm/mach-rockchip/rk3368-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3368-board-spl.c
@@ -11,6 +11,33 @@
 #include <asm/io.h>
 #include <asm/arch-rockchip/periph.h>
 
+__weak int arch_cpu_init(void)
+{
+	return 0;
+}
+
+#define TIMER_LOAD_COUNT_L	0x00
+#define TIMER_LOAD_COUNT_H	0x04
+#define TIMER_CONTROL_REG	0x10
+#define TIMER_EN	0x1
+#define	TIMER_FMODE	BIT(0)
+#define	TIMER_RMODE	BIT(1)
+
+void rockchip_stimer_init(void)
+{
+	/* If Timer already enabled, don't re-init it */
+	u32 reg = readl(CONFIG_ROCKCHIP_STIMER_BASE + TIMER_CONTROL_REG);
+
+	if (reg & TIMER_EN)
+		return;
+
+	writel(0, CONFIG_ROCKCHIP_STIMER_BASE + TIMER_CONTROL_REG);
+	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE);
+	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE + 4);
+	writel(TIMER_EN | TIMER_FMODE, CONFIG_ROCKCHIP_STIMER_BASE +
+	       TIMER_CONTROL_REG);
+}
+
 void board_init_f(ulong dummy)
 {
 	struct udevice *dev;
@@ -22,6 +49,12 @@
 		hang();
 	}
 
+	/* Init secure timer */
+	rockchip_stimer_init();
+	/* Init ARM arch timer in arch/arm/cpu/armv7/arch_timer.c */
+	timer_init();
+
+	arch_cpu_init();
 	preloader_console_init();
 
 	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
diff --git a/arch/arm/mach-rockchip/rk3368-board-tpl.c b/arch/arm/mach-rockchip/rk3368-board-tpl.c
deleted file mode 100644
index dc65a02..0000000
--- a/arch/arm/mach-rockchip/rk3368-board-tpl.c
+++ /dev/null
@@ -1,123 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
- */
-
-#include <common.h>
-#include <debug_uart.h>
-#include <dm.h>
-#include <ram.h>
-#include <spl.h>
-#include <syscon.h>
-#include <asm/io.h>
-#include <asm/arch-rockchip/bootrom.h>
-#include <asm/arch-rockchip/clock.h>
-#include <asm/arch-rockchip/cru_rk3368.h>
-#include <asm/arch-rockchip/hardware.h>
-#include <asm/arch-rockchip/timer.h>
-
-/*
- * The SPL (and also the full U-Boot stage on the RK3368) will run in
- * secure mode (i.e. EL3) and an ATF will eventually be booted before
- * starting up the operating system... so we can initialize the SGRF
- * here and rely on the ATF installing the final (secure) policy
- * later.
- */
-static inline uintptr_t sgrf_soc_con_addr(unsigned no)
-{
-	const uintptr_t SGRF_BASE =
-		(uintptr_t)syscon_get_first_range(ROCKCHIP_SYSCON_SGRF);
-
-	return SGRF_BASE + sizeof(u32) * no;
-}
-
-static inline uintptr_t sgrf_busdmac_addr(unsigned no)
-{
-	const uintptr_t SGRF_BASE =
-		(uintptr_t)syscon_get_first_range(ROCKCHIP_SYSCON_SGRF);
-	const uintptr_t SGRF_BUSDMAC_OFFSET = 0x100;
-	const uintptr_t SGRF_BUSDMAC_BASE = SGRF_BASE + SGRF_BUSDMAC_OFFSET;
-
-	return SGRF_BUSDMAC_BASE + sizeof(u32) * no;
-}
-
-static void sgrf_init(void)
-{
-	struct rk3368_cru * const cru =
-		(struct rk3368_cru * const)rockchip_get_cru();
-	const u16 SGRF_SOC_CON_SEC = GENMASK(15, 0);
-	const u16 SGRF_BUSDMAC_CON0_SEC = BIT(2);
-	const u16 SGRF_BUSDMAC_CON1_SEC = GENMASK(15, 12);
-
-	/* Set all configurable IP to 'non secure'-mode */
-	rk_setreg(sgrf_soc_con_addr(5), SGRF_SOC_CON_SEC);
-	rk_setreg(sgrf_soc_con_addr(6), SGRF_SOC_CON_SEC);
-	rk_setreg(sgrf_soc_con_addr(7), SGRF_SOC_CON_SEC);
-
-	/*
-	 * From rockchip-uboot/arch/arm/cpu/armv8/rk33xx/cpu.c
-	 * Original comment: "ddr space set no secure mode"
-	 */
-	rk_clrreg(sgrf_soc_con_addr(8), SGRF_SOC_CON_SEC);
-	rk_clrreg(sgrf_soc_con_addr(9), SGRF_SOC_CON_SEC);
-	rk_clrreg(sgrf_soc_con_addr(10), SGRF_SOC_CON_SEC);
-
-	/* Set 'secure dma' to 'non secure'-mode */
-	rk_setreg(sgrf_busdmac_addr(0), SGRF_BUSDMAC_CON0_SEC);
-	rk_setreg(sgrf_busdmac_addr(1), SGRF_BUSDMAC_CON1_SEC);
-
-	dsb();  /* barrier */
-
-	rk_setreg(&cru->softrst_con[1], DMA1_SRST_REQ);
-	rk_setreg(&cru->softrst_con[4], DMA2_SRST_REQ);
-
-	dsb();  /* barrier */
-	udelay(10);
-
-	rk_clrreg(&cru->softrst_con[1], DMA1_SRST_REQ);
-	rk_clrreg(&cru->softrst_con[4], DMA2_SRST_REQ);
-}
-
-void board_init_f(ulong dummy)
-{
-	struct udevice *dev;
-	int ret;
-
-#ifdef CONFIG_DEBUG_UART
-	/*
-	 * Debug UART can be used from here if required:
-	 *
-	 * debug_uart_init();
-	 * printch('a');
-	 * printhex8(0x1234);
-	 * printascii("string");
-	 */
-	debug_uart_init();
-	printascii("U-Boot TPL board init\n");
-#endif
-
-	ret = spl_early_init();
-	if (ret) {
-		debug("spl_early_init() failed: %d\n", ret);
-		hang();
-	}
-
-	/* Reset security, so we can use DMA in the MMC drivers */
-	sgrf_init();
-
-	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
-	if (ret) {
-		debug("DRAM init failed: %d\n", ret);
-		return;
-	}
-}
-
-void board_return_to_bootrom(void)
-{
-	back_to_bootrom(BROM_BOOT_NEXTSTAGE);
-}
-
-u32 spl_boot_device(void)
-{
-	return BOOT_DEVICE_BOOTROM;
-}
diff --git a/arch/arm/mach-rockchip/rk3368/Kconfig b/arch/arm/mach-rockchip/rk3368/Kconfig
index 325572a..d6ca5f1 100644
--- a/arch/arm/mach-rockchip/rk3368/Kconfig
+++ b/arch/arm/mach-rockchip/rk3368/Kconfig
@@ -42,9 +42,21 @@
          sensor STK3410.
 endchoice
 
+config ROCKCHIP_BOOT_MODE_REG
+	default 0xff738200
+
 config SYS_SOC
 	default "rk3368"
 
+config SYS_MALLOC_F_LEN
+	default 0x2000
+
+config SPL_LIBCOMMON_SUPPORT
+	default y
+
+config SPL_LIBGENERIC_SUPPORT
+	default y
+
 source "board/theobroma-systems/lion_rk3368/Kconfig"
 source "board/rockchip/sheep_rk3368/Kconfig"
 source "board/geekbuying/geekbox/Kconfig"
@@ -53,4 +65,13 @@
 config SPL_LDSCRIPT
 	default "arch/arm/cpu/armv8/u-boot-spl.lds"
 
+config TPL_MAX_SIZE
+        default 28672
+
+config TPL_STACK
+        default 0xff8cffff
+
+config TPL_TEXT_BASE
+        default 0xff8c1000
+
 endif
diff --git a/arch/arm/mach-rockchip/rk3368/rk3368.c b/arch/arm/mach-rockchip/rk3368/rk3368.c
index f06d277..47786f5 100644
--- a/arch/arm/mach-rockchip/rk3368/rk3368.c
+++ b/arch/arm/mach-rockchip/rk3368/rk3368.c
@@ -5,12 +5,13 @@
  */
 
 #include <common.h>
+#include <syscon.h>
 #include <asm/armv8/mmu.h>
 #include <asm/io.h>
 #include <asm/arch-rockchip/clock.h>
 #include <asm/arch-rockchip/cru_rk3368.h>
 #include <asm/arch-rockchip/grf_rk3368.h>
-#include <syscon.h>
+#include <asm/arch-rockchip/hardware.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -97,6 +98,78 @@
 }
 #endif
 
+#ifdef CONFIG_SPL_BUILD
+/*
+ * The SPL (and also the full U-Boot stage on the RK3368) will run in
+ * secure mode (i.e. EL3) and an ATF will eventually be booted before
+ * starting up the operating system... so we can initialize the SGRF
+ * here and rely on the ATF installing the final (secure) policy
+ * later.
+ */
+static inline uintptr_t sgrf_soc_con_addr(unsigned int no)
+{
+	const uintptr_t SGRF_BASE =
+		(uintptr_t)syscon_get_first_range(ROCKCHIP_SYSCON_SGRF);
+
+	return SGRF_BASE + sizeof(u32) * no;
+}
+
+static inline uintptr_t sgrf_busdmac_addr(unsigned int no)
+{
+	const uintptr_t SGRF_BASE =
+		(uintptr_t)syscon_get_first_range(ROCKCHIP_SYSCON_SGRF);
+	const uintptr_t SGRF_BUSDMAC_OFFSET = 0x100;
+	const uintptr_t SGRF_BUSDMAC_BASE = SGRF_BASE + SGRF_BUSDMAC_OFFSET;
+
+	return SGRF_BUSDMAC_BASE + sizeof(u32) * no;
+}
+
+static void sgrf_init(void)
+{
+	struct rk3368_cru * const cru =
+		(struct rk3368_cru * const)rockchip_get_cru();
+	const u16 SGRF_SOC_CON_SEC = GENMASK(15, 0);
+	const u16 SGRF_BUSDMAC_CON0_SEC = BIT(2);
+	const u16 SGRF_BUSDMAC_CON1_SEC = GENMASK(15, 12);
+
+	/* Set all configurable IP to 'non secure'-mode */
+	rk_setreg(sgrf_soc_con_addr(5), SGRF_SOC_CON_SEC);
+	rk_setreg(sgrf_soc_con_addr(6), SGRF_SOC_CON_SEC);
+	rk_setreg(sgrf_soc_con_addr(7), SGRF_SOC_CON_SEC);
+
+	/*
+	 * From rockchip-uboot/arch/arm/cpu/armv8/rk33xx/cpu.c
+	 * Original comment: "ddr space set no secure mode"
+	 */
+	rk_clrreg(sgrf_soc_con_addr(8), SGRF_SOC_CON_SEC);
+	rk_clrreg(sgrf_soc_con_addr(9), SGRF_SOC_CON_SEC);
+	rk_clrreg(sgrf_soc_con_addr(10), SGRF_SOC_CON_SEC);
+
+	/* Set 'secure dma' to 'non secure'-mode */
+	rk_setreg(sgrf_busdmac_addr(0), SGRF_BUSDMAC_CON0_SEC);
+	rk_setreg(sgrf_busdmac_addr(1), SGRF_BUSDMAC_CON1_SEC);
+
+	dsb();  /* barrier */
+
+	rk_setreg(&cru->softrst_con[1], DMA1_SRST_REQ);
+	rk_setreg(&cru->softrst_con[4], DMA2_SRST_REQ);
+
+	dsb();  /* barrier */
+	udelay(10);
+
+	rk_clrreg(&cru->softrst_con[1], DMA1_SRST_REQ);
+	rk_clrreg(&cru->softrst_con[4], DMA2_SRST_REQ);
+}
+
+int arch_cpu_init(void)
+{
+	/* Reset security, so we can use DMA in the MMC drivers */
+	sgrf_init();
+
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_DEBUG_UART_BOARD_INIT
 void board_debug_uart_init(void)
 {
diff --git a/arch/arm/mach-rockchip/rk3399-board-spl.c b/arch/arm/mach-rockchip/rk3399-board-spl.c
index 890d800..7154d8e 100644
--- a/arch/arm/mach-rockchip/rk3399-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3399-board-spl.c
@@ -21,7 +21,6 @@
 #include <asm/arch-rockchip/periph.h>
 #include <asm/arch-rockchip/sys_proto.h>
 #include <power/regulator.h>
-#include <dm/pinctrl.h>
 
 void board_return_to_bootrom(void)
 {
@@ -110,30 +109,12 @@
 			   "u-boot,spl-boot-device", boot_ofpath);
 }
 
-#define TIMER_CHN10_BASE	0xff8680a0
-#define TIMER_END_COUNT_L	0x00
-#define TIMER_END_COUNT_H	0x04
-#define TIMER_INIT_COUNT_L	0x10
-#define TIMER_INIT_COUNT_H	0x14
-#define TIMER_CONTROL_REG	0x1c
-
-#define TIMER_EN	0x1
-#define	TIMER_FMODE	(0 << 1)
-#define	TIMER_RMODE	(1 << 1)
-
-void secure_timer_init(void)
+__weak void rockchip_stimer_init(void)
 {
-	writel(0xffffffff, TIMER_CHN10_BASE + TIMER_END_COUNT_L);
-	writel(0xffffffff, TIMER_CHN10_BASE + TIMER_END_COUNT_H);
-	writel(0, TIMER_CHN10_BASE + TIMER_INIT_COUNT_L);
-	writel(0, TIMER_CHN10_BASE + TIMER_INIT_COUNT_H);
-	writel(TIMER_EN | TIMER_FMODE, TIMER_CHN10_BASE + TIMER_CONTROL_REG);
 }
 
-
 void board_init_f(ulong dummy)
 {
-	struct udevice *pinctrl;
 	struct udevice *dev;
 	struct rk3399_pmusgrf_regs *sgrf;
 	struct rk3399_grf_regs *grf;
@@ -190,13 +171,7 @@
 	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
 	rk_clrreg(&grf->emmccore_con[11], 0x0ff);
 
-	secure_timer_init();
-
-	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
-	if (ret) {
-		pr_err("Pinctrl init failed: %d\n", ret);
-		return;
-	}
+	rockchip_stimer_init();
 
 	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
 	if (ret) {
diff --git a/arch/arm/mach-rockchip/rk3399-board-tpl.c b/arch/arm/mach-rockchip/rk3399-board-tpl.c
deleted file mode 100644
index 4a30124..0000000
--- a/arch/arm/mach-rockchip/rk3399-board-tpl.c
+++ /dev/null
@@ -1,91 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2019 Rockchip Electronics Co., Ltd
- */
-
-#include <common.h>
-#include <debug_uart.h>
-#include <dm.h>
-#include <ram.h>
-#include <spl.h>
-#include <version.h>
-#include <asm/io.h>
-#include <asm/arch-rockchip/bootrom.h>
-
-#define TIMER_CHN10_BASE	0xff8680a0
-#define TIMER_END_COUNT_L	0x00
-#define TIMER_END_COUNT_H	0x04
-#define TIMER_INIT_COUNT_L	0x10
-#define TIMER_INIT_COUNT_H	0x14
-#define TIMER_CONTROL_REG	0x1c
-
-#define TIMER_EN	0x1
-#define	TIMER_FMODE	(0 << 1)
-#define	TIMER_RMODE	(1 << 1)
-
-void secure_timer_init(void)
-{
-	writel(0xffffffff, TIMER_CHN10_BASE + TIMER_END_COUNT_L);
-	writel(0xffffffff, TIMER_CHN10_BASE + TIMER_END_COUNT_H);
-	writel(0, TIMER_CHN10_BASE + TIMER_INIT_COUNT_L);
-	writel(0, TIMER_CHN10_BASE + TIMER_INIT_COUNT_H);
-	writel(TIMER_EN | TIMER_FMODE, TIMER_CHN10_BASE + TIMER_CONTROL_REG);
-}
-
-void board_init_f(ulong dummy)
-{
-	struct udevice *dev;
-	int ret;
-
-#ifdef CONFIG_DEBUG_UART
-	debug_uart_init();
-	/*
-	 * Debug UART can be used from here if required:
-	 *
-	 * debug_uart_init();
-	 * printch('a');
-	 * printhex8(0x1234);
-	 * printascii("string");
-	 */
-	debug("U-Boot TPL board init\n");
-#endif
-	ret = spl_early_init();
-	if (ret) {
-		debug("spl_early_init() failed: %d\n", ret);
-		hang();
-	}
-
-	secure_timer_init();
-
-	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
-	if (ret) {
-		pr_err("DRAM init failed: %d\n", ret);
-		return;
-	}
-}
-
-void board_return_to_bootrom(void)
-{
-	back_to_bootrom(BROM_BOOT_NEXTSTAGE);
-}
-
-u32 spl_boot_device(void)
-{
-	return BOOT_DEVICE_BOOTROM;
-}
-
-void spl_board_init(void)
-{
-	puts("\nU-Boot TPL "  PLAIN_VERSION " (" U_BOOT_DATE " - "
-	     U_BOOT_TIME " " U_BOOT_TZ ")\n");
-}
-
-#ifdef CONFIG_SPL_LOAD_FIT
-int board_fit_config_name_match(const char *name)
-{
-	/* Just empty function now - can't decide what to choose */
-	debug("%s: %s\n", __func__, name);
-
-	return 0;
-}
-#endif
diff --git a/arch/arm/mach-rockchip/rk3399/Kconfig b/arch/arm/mach-rockchip/rk3399/Kconfig
index 2c5c93c..6660d05 100644
--- a/arch/arm/mach-rockchip/rk3399/Kconfig
+++ b/arch/arm/mach-rockchip/rk3399/Kconfig
@@ -64,11 +64,32 @@
 
 endchoice
 
+config ROCKCHIP_BOOT_MODE_REG
+	default 0xff320300
+
 config SYS_SOC
 	default "rk3399"
 
 config SYS_MALLOC_F_LEN
-	default 0x0800
+	default 0x4000
+
+config SPL_LIBCOMMON_SUPPORT
+	default y
+
+config SPL_LIBGENERIC_SUPPORT
+	default y
+
+config TPL_LDSCRIPT
+	default "arch/arm/mach-rockchip/u-boot-tpl-v8.lds"
+
+config TPL_MAX_SIZE
+        default 188416
+
+config TPL_STACK
+        default 0xff8effff
+
+config TPL_TEXT_BASE
+        default 0xff8c2000
 
 source "board/rockchip/evb_rk3399/Kconfig"
 source "board/theobroma-systems/puma_rk3399/Kconfig"
diff --git a/arch/arm/mach-rockchip/rk3399/rk3399.c b/arch/arm/mach-rockchip/rk3399/rk3399.c
index e1f9f8b..0f09ea5 100644
--- a/arch/arm/mach-rockchip/rk3399/rk3399.c
+++ b/arch/arm/mach-rockchip/rk3399/rk3399.c
@@ -38,6 +38,35 @@
 
 struct mm_region *mem_map = rk3399_mem_map;
 
+#ifdef CONFIG_SPL_BUILD
+
+#define TIMER_END_COUNT_L	0x00
+#define TIMER_END_COUNT_H	0x04
+#define TIMER_INIT_COUNT_L	0x10
+#define TIMER_INIT_COUNT_H	0x14
+#define TIMER_CONTROL_REG	0x1c
+
+#define TIMER_EN	0x1
+#define TIMER_FMODE	BIT(0)
+#define TIMER_RMODE	BIT(1)
+
+void rockchip_stimer_init(void)
+{
+	/* If Timer already enabled, don't re-init it */
+	u32 reg = readl(CONFIG_ROCKCHIP_STIMER_BASE + TIMER_CONTROL_REG);
+
+	if (reg & TIMER_EN)
+		return;
+
+	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE + TIMER_END_COUNT_L);
+	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE + TIMER_END_COUNT_H);
+	writel(0, CONFIG_ROCKCHIP_STIMER_BASE + TIMER_INIT_COUNT_L);
+	writel(0, CONFIG_ROCKCHIP_STIMER_BASE + TIMER_INIT_COUNT_H);
+	writel(TIMER_EN | TIMER_FMODE, CONFIG_ROCKCHIP_STIMER_BASE + \
+	       TIMER_CONTROL_REG);
+}
+#endif
+
 int dram_init_banksize(void)
 {
 	size_t max_size = min((unsigned long)gd->ram_size, gd->ram_top);
diff --git a/arch/arm/mach-rockchip/rk3399/syscon_rk3399.c b/arch/arm/mach-rockchip/rk3399/syscon_rk3399.c
index a8bb5b1..259ca44 100644
--- a/arch/arm/mach-rockchip/rk3399/syscon_rk3399.c
+++ b/arch/arm/mach-rockchip/rk3399/syscon_rk3399.c
@@ -13,6 +13,7 @@
 	{ .compatible = "rockchip,rk3399-pmugrf", .data = ROCKCHIP_SYSCON_PMUGRF },
 	{ .compatible = "rockchip,rk3399-pmusgrf", .data = ROCKCHIP_SYSCON_PMUSGRF },
 	{ .compatible = "rockchip,rk3399-cic", .data = ROCKCHIP_SYSCON_CIC },
+	{ .compatible = "rockchip,rk3399-pmu", .data = ROCKCHIP_SYSCON_PMU },
 	{ }
 };
 
@@ -58,4 +59,11 @@
 	.of_match = rk3399_syscon_ids + 3,
 	.bind = rk3399_syscon_bind_of_platdata,
 };
+
+U_BOOT_DRIVER(rockchip_rk3399_pmu) = {
+	.name = "rockchip_rk3399_pmu",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3399_syscon_ids + 4,
+	.bind = rk3399_syscon_bind_of_platdata,
+};
 #endif
diff --git a/arch/arm/mach-rockchip/rk_timer.c b/arch/arm/mach-rockchip/rk_timer.c
deleted file mode 100644
index 29d379f..0000000
--- a/arch/arm/mach-rockchip/rk_timer.c
+++ /dev/null
@@ -1,40 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2015 Rockchip Electronics Co., Ltd
- */
-
-#include <common.h>
-#include <asm/arch-rockchip/timer.h>
-#include <asm/io.h>
-#include <linux/types.h>
-
-struct rk_timer * const timer_ptr = (void *)CONFIG_SYS_TIMER_BASE;
-
-static uint64_t rockchip_get_ticks(void)
-{
-	uint64_t timebase_h, timebase_l;
-
-	timebase_l = readl(&timer_ptr->timer_curr_value0);
-	timebase_h = readl(&timer_ptr->timer_curr_value1);
-
-	return timebase_h << 32 | timebase_l;
-}
-
-void rockchip_udelay(unsigned int usec)
-{
-	uint64_t tmp;
-
-	/* get timestamp */
-	tmp = rockchip_get_ticks() + usec_to_tick(usec);
-
-	/* loop till event */
-	while (rockchip_get_ticks() < tmp+1)
-		;
-}
-
-void rockchip_timer_init(void)
-{
-	writel(0xffffffff, &timer_ptr->timer_load_count0);
-	writel(0xffffffff, &timer_ptr->timer_load_count1);
-	writel(1, &timer_ptr->timer_ctrl_reg);
-}
diff --git a/arch/arm/mach-rockchip/rv1108/Kconfig b/arch/arm/mach-rockchip/rv1108/Kconfig
index e3a63b8..a12216d 100644
--- a/arch/arm/mach-rockchip/rv1108/Kconfig
+++ b/arch/arm/mach-rockchip/rv1108/Kconfig
@@ -1,5 +1,8 @@
 if ROCKCHIP_RV1108
 
+choice
+	prompt "RV1108 board select"
+
 config TARGET_EVB_RV1108
 	bool "EVB_RV1108"
 	help
@@ -22,6 +25,11 @@
 	help
 	  RV1108 ELGIN is a board based on the Rockchip RV1108.
 
+endchoice
+
+config ROCKCHIP_BOOT_MODE_REG
+	default 0x10300580
+
 config SYS_SOC
 	default "rv1108"
 
diff --git a/arch/arm/mach-rockchip/spl-boot-order.c b/arch/arm/mach-rockchip/spl-boot-order.c
index 0e485de..c19c285 100644
--- a/arch/arm/mach-rockchip/spl-boot-order.c
+++ b/arch/arm/mach-rockchip/spl-boot-order.c
@@ -8,7 +8,7 @@
 #include <mmc.h>
 #include <spl.h>
 
-#if CONFIG_IS_ENABLED(OF_CONTROL)
+#if CONFIG_IS_ENABLED(OF_LIBFDT)
 /**
  * spl_node_to_boot_device() - maps from a DT-node to a SPL boot device
  * @node:	of_offset of the node
diff --git a/arch/arm/mach-rockchip/tpl.c b/arch/arm/mach-rockchip/tpl.c
new file mode 100644
index 0000000..55f6e92
--- /dev/null
+++ b/arch/arm/mach-rockchip/tpl.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <ram.h>
+#include <spl.h>
+#include <version.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/bootrom.h>
+
+#define TIMER_LOAD_COUNT_L	0x00
+#define TIMER_LOAD_COUNT_H	0x04
+#define TIMER_CONTROL_REG	0x10
+#define TIMER_EN	0x1
+#define	TIMER_FMODE	BIT(0)
+#define	TIMER_RMODE	BIT(1)
+
+__weak void rockchip_stimer_init(void)
+{
+	/* If Timer already enabled, don't re-init it */
+	u32 reg = readl(CONFIG_ROCKCHIP_STIMER_BASE + TIMER_CONTROL_REG);
+
+	if (reg & TIMER_EN)
+		return;
+
+#ifndef CONFIG_ARM64
+	asm volatile("mcr p15, 0, %0, c14, c0, 0"
+		     : : "r"(COUNTER_FREQUENCY));
+#endif
+
+	writel(0, CONFIG_ROCKCHIP_STIMER_BASE + TIMER_CONTROL_REG);
+	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE);
+	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE + 4);
+	writel(TIMER_EN | TIMER_FMODE, CONFIG_ROCKCHIP_STIMER_BASE +
+	       TIMER_CONTROL_REG);
+}
+
+void board_init_f(ulong dummy)
+{
+	struct udevice *dev;
+	int ret;
+
+#if defined(CONFIG_DEBUG_UART) && defined(CONFIG_TPL_SERIAL_SUPPORT)
+	/*
+	 * Debug UART can be used from here if required:
+	 *
+	 * debug_uart_init();
+	 * printch('a');
+	 * printhex8(0x1234);
+	 * printascii("string");
+	 */
+	debug_uart_init();
+#ifdef CONFIG_TPL_BANNER_PRINT
+	printascii("\nU-Boot TPL " PLAIN_VERSION " (" U_BOOT_DATE " - " \
+				U_BOOT_TIME ")\n");
+#endif
+#endif
+	ret = spl_early_init();
+	if (ret) {
+		debug("spl_early_init() failed: %d\n", ret);
+		hang();
+	}
+
+	/* Init secure timer */
+	rockchip_stimer_init();
+	/* Init ARM arch timer in arch/arm/cpu/ */
+	timer_init();
+
+	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+	if (ret) {
+		printf("DRAM init failed: %d\n", ret);
+		return;
+	}
+}
+
+void board_return_to_bootrom(void)
+{
+	back_to_bootrom(BROM_BOOT_NEXTSTAGE);
+}
+
+u32 spl_boot_device(void)
+{
+	return BOOT_DEVICE_BOOTROM;
+}
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 1669e62..ffdf09f 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -300,6 +300,7 @@
 	select ARM64
 	select SUPPORT_SPL
 	select FIT
+	select PHY_SUN4I_USB
 	select SPL_LOAD_FIT
 	select DRAM_SUN50I_H6
 
@@ -340,7 +341,7 @@
 	This allows both the SPL and the U-Boot proper to be entered in
 	either mode and switch to AArch64 if needed.
 
-if SUNXI_DRAM_DW
+if SUNXI_DRAM_DW || DRAM_SUN50I_H6
 config SUNXI_DRAM_DDR3
 	bool
 
@@ -370,6 +371,22 @@
 	This option is the LPDDR3 timing used by the stock boot0 by
 	Allwinner.
 
+config SUNXI_DRAM_H6_LPDDR3
+	bool "LPDDR3 DRAM chips on the H6 DRAM controller"
+	select SUNXI_DRAM_LPDDR3
+	depends on DRAM_SUN50I_H6
+	---help---
+	This option is the LPDDR3 timing used by the stock boot0 by
+	Allwinner.
+
+config SUNXI_DRAM_H6_DDR3_1333
+	bool "DDR3-1333 boot0 timings on the H6 DRAM controller"
+	select SUNXI_DRAM_DDR3
+	depends on DRAM_SUN50I_H6
+	---help---
+	This option is the DDR3 timing used by the boot0 on H6 TV boxes
+	which use a DDR3-1333 timing.
+
 config SUNXI_DRAM_DDR2_V3S
 	bool "DDR2 found in V3s chip"
 	select SUNXI_DRAM_DDR2
diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
index 43a93e3..d129f33 100644
--- a/arch/arm/mach-sunxi/Makefile
+++ b/arch/arm/mach-sunxi/Makefile
@@ -39,4 +39,5 @@
 obj-$(CONFIG_SUNXI_DRAM_DW)	+= dram_sunxi_dw.o
 obj-$(CONFIG_SUNXI_DRAM_DW)	+= dram_timings/
 obj-$(CONFIG_DRAM_SUN50I_H6)	+= dram_sun50i_h6.o
+obj-$(CONFIG_DRAM_SUN50I_H6)	+= dram_timings/
 endif
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h6.c b/arch/arm/mach-sunxi/dram_sun50i_h6.c
index 5da90a2..2a8275d 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h6.c
@@ -32,33 +32,8 @@
  * similar PHY is ZynqMP.
  */
 
-/*
- * The delay parameters below allow to allegedly specify delay times of some
- * unknown unit for each individual bit trace in each of the four data bytes
- * the 32-bit wide access consists of. Also three control signals can be
- * adjusted individually.
- */
-#define NR_OF_BYTE_LANES	(32 / BITS_PER_BYTE)
-/* The eight data lines (DQn) plus DM, DQS, DQS/DM/DQ Output Enable and DQSN */
-#define WR_LINES_PER_BYTE_LANE	(BITS_PER_BYTE + 4)
-/*
- * The eight data lines (DQn) plus DM, DQS, DQS/DM/DQ Output Enable, DQSN,
- * Termination and Power down
- */
-#define RD_LINES_PER_BYTE_LANE	(BITS_PER_BYTE + 6)
-struct dram_para {
-	u32 clk;
-	enum sunxi_dram_type type;
-	u8 cols;
-	u8 rows;
-	u8 ranks;
-	const u8 dx_read_delays[NR_OF_BYTE_LANES][RD_LINES_PER_BYTE_LANE];
-	const u8 dx_write_delays[NR_OF_BYTE_LANES][WR_LINES_PER_BYTE_LANE];
-};
-
 static void mctl_sys_init(struct dram_para *para);
 static void mctl_com_init(struct dram_para *para);
-static void mctl_set_timing_lpddr3(struct dram_para *para);
 static void mctl_channel_init(struct dram_para *para);
 
 static void mctl_core_init(struct dram_para *para)
@@ -67,7 +42,8 @@
 	mctl_com_init(para);
 	switch (para->type) {
 	case SUNXI_DRAM_TYPE_LPDDR3:
-		mctl_set_timing_lpddr3(para);
+	case SUNXI_DRAM_TYPE_DDR3:
+		mctl_set_timing_params(para);
 		break;
 	default:
 		panic("Unsupported DRAM type!");
@@ -75,12 +51,14 @@
 	mctl_channel_init(para);
 }
 
+/* PHY initialisation */
 static void mctl_phy_pir_init(u32 val)
 {
 	struct sunxi_mctl_phy_reg * const mctl_phy =
 			(struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
 
-	writel(val | BIT(0), &mctl_phy->pir);
+	writel(val, &mctl_phy->pir);
+	writel(val | BIT(0), &mctl_phy->pir);	/* Start initialisation. */
 	mctl_await_completion(&mctl_phy->pgsr[0], BIT(0), BIT(0));
 }
 
@@ -169,125 +147,6 @@
 	MBUS_CONF(HDCP2,  true,    HIGH, 2,  100,   64,   32);
 }
 
-static u32 mr_lpddr3[12] = {
-	0x00000000, 0x00000043, 0x0000001a, 0x00000001,
-	0x00000000, 0x00000000, 0x00000048, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000003,
-};
-
-/* TODO: flexible timing */
-static void mctl_set_timing_lpddr3(struct dram_para *para)
-{
-	struct sunxi_mctl_ctl_reg * const mctl_ctl =
-			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
-	struct sunxi_mctl_phy_reg * const mctl_phy =
-			(struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
-
-	u8 tccd		= 2;
-	u8 tfaw		= max(ns_to_t(50), 4);
-	u8 trrd		= max(ns_to_t(10), 2);
-	u8 trcd		= max(ns_to_t(24), 2);
-	u8 trc		= ns_to_t(70);
-	u8 txp		= max(ns_to_t(8), 2);
-	u8 twtr		= max(ns_to_t(8), 2);
-	u8 trtp		= max(ns_to_t(8), 2);
-	u8 twr		= max(ns_to_t(15), 2);
-	u8 trp		= ns_to_t(18);
-	u8 tras		= ns_to_t(42);
-	u8 twtr_sa	= ns_to_t(5);
-	u8 tcksrea	= ns_to_t(11);
-	u16 trefi	= ns_to_t(3900) / 32;
-	u16 trfc	= ns_to_t(210);
-	u16 txsr	= ns_to_t(220);
-
-	if (CONFIG_DRAM_CLK % 400 == 0) {
-		/* Round up these parameters */
-		twtr_sa++;
-		tcksrea++;
-	}
-
-	u8 tmrw		= 5;
-	u8 tmrd		= 5;
-	u8 tmod		= 12;
-	u8 tcke		= 3;
-	u8 tcksrx	= 5;
-	u8 tcksre	= 5;
-	u8 tckesr	= 5;
-	u8 trasmax	= CONFIG_DRAM_CLK / 60;
-	u8 txs		= 4;
-	u8 txsdll	= 4;
-	u8 txsabort	= 4;
-	u8 txsfast	= 4;
-
-	u8 tcl		= 5; /* CL 10 */
-	u8 tcwl		= 3; /* CWL 6 */
-	u8 t_rdata_en	= twtr_sa + 8;
-
-	u32 tdinit0	= (200 * CONFIG_DRAM_CLK) + 1;		/* 200us */
-	u32 tdinit1	= (100 * CONFIG_DRAM_CLK) / 1000 + 1;	/* 100ns */
-	u32 tdinit2	= (11 * CONFIG_DRAM_CLK) + 1;		/* 11us */
-	u32 tdinit3	= (1 * CONFIG_DRAM_CLK) + 1;		/* 1us */
-
-	u8 twtp		= tcwl + 4 + twr + 1;
-	/*
-	 * The code below for twr2rd and trd2wr follows the IP core's
-	 * document from ZynqMP and i.MX7. The BSP has both number
-	 * substracted by 2.
-	 */
-	u8 twr2rd	= tcwl + 4 + 1 + twtr;
-	u8 trd2wr	= tcl + 4 + (tcksrea >> 1) - tcwl + 1;
-
-	/* set mode register */
-	memcpy(mctl_phy->mr, mr_lpddr3, sizeof(mr_lpddr3));
-
-	/* set DRAM timing */
-	writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | tras,
-	       &mctl_ctl->dramtmg[0]);
-	writel((txp << 16) | (trtp << 8) | trc, &mctl_ctl->dramtmg[1]);
-	writel((tcwl << 24) | (tcl << 16) | (trd2wr << 8) | twr2rd,
-	       &mctl_ctl->dramtmg[2]);
-	writel((tmrw << 20) | (tmrd << 12) | tmod, &mctl_ctl->dramtmg[3]);
-	writel((trcd << 24) | (tccd << 16) | (trrd << 8) | trp,
-	       &mctl_ctl->dramtmg[4]);
-	writel((tcksrx << 24) | (tcksre << 16) | (tckesr << 8) | tcke,
-	       &mctl_ctl->dramtmg[5]);
-	/* Value suggested by ZynqMP manual and used by libdram */
-	writel((txp + 2) | 0x02020000, &mctl_ctl->dramtmg[6]);
-	writel((txsfast << 24) | (txsabort << 16) | (txsdll << 8) | txs,
-	       &mctl_ctl->dramtmg[8]);
-	writel(txsr, &mctl_ctl->dramtmg[14]);
-
-	clrsetbits_le32(&mctl_ctl->init[0], (3 << 30), (1 << 30));
-	writel(0, &mctl_ctl->dfimisc);
-	clrsetbits_le32(&mctl_ctl->rankctl, 0xff0, 0x660);
-
-	/*
-	 * Set timing registers of the PHY.
-	 * Note: the PHY is clocked 2x from the DRAM frequency.
-	 */
-	writel((trrd << 25) | (tras << 17) | (trp << 9) | (trtp << 1),
-	       &mctl_phy->dtpr[0]);
-	writel((tfaw << 17) | 0x28000400 | (tmrd << 1), &mctl_phy->dtpr[1]);
-	writel(((txs << 6) - 1) | (tcke << 17), &mctl_phy->dtpr[2]);
-	writel(((txsdll << 22) - (0x1 << 16)) | twtr_sa | (tcksrea << 8),
-	       &mctl_phy->dtpr[3]);
-	writel((txp << 1) | (trfc << 17) | 0x800, &mctl_phy->dtpr[4]);
-	writel((trc << 17) | (trcd << 9) | (twtr << 1), &mctl_phy->dtpr[5]);
-	writel(0x0505, &mctl_phy->dtpr[6]);
-
-	/* Configure DFI timing */
-	writel(tcl | 0x2000200 | (t_rdata_en << 16) | 0x808000,
-	       &mctl_ctl->dfitmg0);
-	writel(0x040201, &mctl_ctl->dfitmg1);
-
-	/* Configure PHY timing */
-	writel(tdinit0 | (tdinit1 << 20), &mctl_phy->ptr[3]);
-	writel(tdinit2 | (tdinit3 << 18), &mctl_phy->ptr[4]);
-
-	/* set refresh timing */
-	writel((trefi << 16) | trfc, &mctl_ctl->rfshtmg);
-}
-
 static void mctl_sys_init(struct dram_para *para)
 {
 	struct sunxi_ccm_reg * const ccm =
@@ -426,14 +285,11 @@
 	mctl_set_addrmap(para);
 
 	setbits_le32(&mctl_com->cr, BIT(31));
-	/*
-	 * This address is magic; it's in SID memory area, but there's no
-	 * known definition of it.
-	 * On my Pine H64 board it has content 7.
-	 */
-	if (readl(0x03006100) == 7)
+
+	/* The bonding ID seems to be always 7. */
+	if (readl(SUNXI_SIDC_BASE + 0x100) == 7)	/* bonding ID */
 		clrbits_le32(&mctl_com->cr, BIT(27));
-	else if (readl(0x03006100) == 3)
+	else if (readl(SUNXI_SIDC_BASE + 0x100) == 3)
 		setbits_le32(&mctl_com->cr, BIT(27));
 
 	if (para->clk > 408)
@@ -444,22 +300,37 @@
 		reg_val = 0x3f00;
 	clrsetbits_le32(&mctl_com->unk_0x008, 0x3f00, reg_val);
 
-	/* TODO: half DQ, non-LPDDR3 types */
-	writel(MSTR_DEVICETYPE_LPDDR3 | MSTR_BUSWIDTH_FULL |
-	       MSTR_BURST_LENGTH(8) | MSTR_ACTIVE_RANKS(para->ranks) |
-	       0x80000000, &mctl_ctl->mstr);
-	writel(DCR_LPDDR3 | DCR_DDR8BANK | 0x400, &mctl_phy->dcr);
+	/* TODO: half DQ, DDR4 */
+	reg_val = MSTR_BUSWIDTH_FULL | MSTR_BURST_LENGTH(8) |
+		  MSTR_ACTIVE_RANKS(para->ranks);
+	if (para->type == SUNXI_DRAM_TYPE_LPDDR3)
+		reg_val |= MSTR_DEVICETYPE_LPDDR3;
+	if (para->type == SUNXI_DRAM_TYPE_DDR3)
+		reg_val |= MSTR_DEVICETYPE_DDR3 | MSTR_2TMODE;
+	writel(reg_val | BIT(31), &mctl_ctl->mstr);
+
+	if (para->type == SUNXI_DRAM_TYPE_LPDDR3)
+		reg_val = DCR_LPDDR3 | DCR_DDR8BANK;
+	if (para->type == SUNXI_DRAM_TYPE_DDR3)
+		reg_val = DCR_DDR3 | DCR_DDR8BANK | DCR_DDR2T;
+	writel(reg_val | 0x400, &mctl_phy->dcr);
 
 	if (para->ranks == 2)
 		writel(0x0303, &mctl_ctl->odtmap);
 	else
 		writel(0x0201, &mctl_ctl->odtmap);
 
-	/* TODO: non-LPDDR3 types */
-	tmp = para->clk * 7 / 2000;
-	reg_val = 0x0400;
-	reg_val |= (tmp + 7) << 24;
-	reg_val |= (((para->clk < 400) ? 3 : 4) - tmp) << 16;
+	/* TODO: DDR4 */
+	if (para->type == SUNXI_DRAM_TYPE_LPDDR3) {
+		tmp = para->clk * 7 / 2000;
+		reg_val = 0x0400;
+		reg_val |= (tmp + 7) << 24;
+		reg_val |= (((para->clk < 400) ? 3 : 4) - tmp) << 16;
+	} else if (para->type == SUNXI_DRAM_TYPE_DDR3) {
+		reg_val = 0x06000400;	/* TODO?: Use CL - CWL value in [7:0] */
+	} else {
+		panic("Only (LP)DDR3 supported (type = %d)\n", para->type);
+	}
 	writel(reg_val, &mctl_ctl->odtcfg);
 
 	/* TODO: half DQ */
@@ -514,6 +385,9 @@
 	setbits_le32(&mctl_phy->pgcr[0], BIT(26));
 	udelay(1);
 
+	if (para->type != SUNXI_DRAM_TYPE_LPDDR3)
+		return;
+
 	for (i = 1; i < 14; i++) {
 		val = readl(&mctl_phy->acbdlr[i]);
 		val += 0x0a0a0a0a;
@@ -561,7 +435,8 @@
 	else
 		clrsetbits_le32(&mctl_phy->dtcr[1], 0x30000, 0x10000);
 
-	clrbits_le32(&mctl_phy->dtcr[1], BIT(1));
+	if (sunxi_dram_is_lpddr(para->type))
+		clrbits_le32(&mctl_phy->dtcr[1], BIT(1));
 	if (para->ranks == 2) {
 		writel(0x00010001, &mctl_phy->rankidr);
 		writel(0x20000, &mctl_phy->odtcr);
@@ -570,8 +445,11 @@
 		writel(0x10000, &mctl_phy->odtcr);
 	}
 
-	/* TODO: non-LPDDR3 types */
-	clrsetbits_le32(&mctl_phy->dtcr[0], 0xF0000000, 0x10000040);
+	/* set bits [3:0] to 1? 0 not valid in ZynqMP d/s */
+	if (para->type == SUNXI_DRAM_TYPE_LPDDR3)
+		clrsetbits_le32(&mctl_phy->dtcr[0], 0xF0000000, 0x10000040);
+	else
+		clrsetbits_le32(&mctl_phy->dtcr[0], 0xF0000000, 0x10000000);
 	if (para->clk <= 792) {
 		if (para->clk <= 672) {
 			if (para->clk <= 600)
@@ -601,12 +479,13 @@
 			writel(0x06060606, &mctl_phy->acbdlr[i]);
 	}
 
-	/* TODO: non-LPDDR3 types */
-	mctl_phy_pir_init(PIR_ZCAL | PIR_DCAL | PIR_PHYRST | PIR_DRAMINIT |
-			  PIR_QSGATE | PIR_RDDSKW | PIR_WRDSKW | PIR_RDEYE |
-			  PIR_WREYE);
+	val = PIR_ZCAL | PIR_DCAL | PIR_PHYRST | PIR_DRAMINIT | PIR_QSGATE |
+	      PIR_RDDSKW | PIR_WRDSKW | PIR_RDEYE | PIR_WREYE;
+	if (para->type == SUNXI_DRAM_TYPE_DDR3)
+		val |= PIR_DRAMRST | PIR_WL;
+	mctl_phy_pir_init(val);
 
-	/* TODO: non-LPDDR3 types */
+	/* TODO: DDR4 types ? */
 	for (i = 0; i < 4; i++)
 		writel(0x00000909, &mctl_phy->dx[i].gcr[5]);
 
@@ -662,7 +541,8 @@
 		panic("Error while initializing DRAM PHY!\n");
 	}
 
-	clrsetbits_le32(&mctl_phy->dsgcr, 0xc0, 0x40);
+	if (sunxi_dram_is_lpddr(para->type))
+		clrsetbits_le32(&mctl_phy->dsgcr, 0xc0, 0x40);
 	clrbits_le32(&mctl_phy->pgcr[1], 0x40);
 	clrbits_le32(&mctl_ctl->dfimisc, BIT(0));
 	writel(1, &mctl_ctl->swctl);
@@ -714,29 +594,46 @@
 	return (1ULL << (para->cols + para->rows + 3)) * 4 * para->ranks;
 }
 
-#define SUN50I_H6_DX_WRITE_DELAYS				\
+#define SUN50I_H6_LPDDR3_DX_WRITE_DELAYS			\
 	{{  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },	\
 	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },	\
 	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  4,  4,  0 },	\
 	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }}
-#define SUN50I_H6_DX_READ_DELAYS					\
+#define SUN50I_H6_LPDDR3_DX_READ_DELAYS					\
 	{{  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,  0 },	\
 	 {  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,  0 },	\
 	 {  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,  0 },	\
 	 {  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,  0 }}
 
+#define SUN50I_H6_DDR3_DX_WRITE_DELAYS				\
+	{{  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },	\
+	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },	\
+	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },	\
+	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }}
+#define SUN50I_H6_DDR3_DX_READ_DELAYS					\
+	{{  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },	\
+	 {  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,  0 },	\
+	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },	\
+	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }}
+
 unsigned long sunxi_dram_init(void)
 {
 	struct sunxi_mctl_com_reg * const mctl_com =
 			(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
 	struct dram_para para = {
 		.clk = CONFIG_DRAM_CLK,
-		.type = SUNXI_DRAM_TYPE_LPDDR3,
 		.ranks = 2,
 		.cols = 11,
 		.rows = 14,
-		.dx_read_delays  = SUN50I_H6_DX_READ_DELAYS,
-		.dx_write_delays = SUN50I_H6_DX_WRITE_DELAYS,
+#ifdef CONFIG_SUNXI_DRAM_H6_LPDDR3
+		.type = SUNXI_DRAM_TYPE_LPDDR3,
+		.dx_read_delays  = SUN50I_H6_LPDDR3_DX_READ_DELAYS,
+		.dx_write_delays = SUN50I_H6_LPDDR3_DX_WRITE_DELAYS,
+#elif defined(CONFIG_SUNXI_DRAM_H6_DDR3_1333)
+		.type = SUNXI_DRAM_TYPE_DDR3,
+		.dx_read_delays  = SUN50I_H6_DDR3_DX_READ_DELAYS,
+		.dx_write_delays = SUN50I_H6_DDR3_DX_WRITE_DELAYS,
+#endif
 	};
 
 	unsigned long size;
diff --git a/arch/arm/mach-sunxi/dram_timings/Makefile b/arch/arm/mach-sunxi/dram_timings/Makefile
index 278a8a1..0deb991 100644
--- a/arch/arm/mach-sunxi/dram_timings/Makefile
+++ b/arch/arm/mach-sunxi/dram_timings/Makefile
@@ -1,3 +1,5 @@
 obj-$(CONFIG_SUNXI_DRAM_DDR3_1333)	+= ddr3_1333.o
 obj-$(CONFIG_SUNXI_DRAM_LPDDR3_STOCK)	+= lpddr3_stock.o
 obj-$(CONFIG_SUNXI_DRAM_DDR2_V3S)	+= ddr2_v3s.o
+obj-$(CONFIG_SUNXI_DRAM_H6_LPDDR3)	+= h6_lpddr3.o
+obj-$(CONFIG_SUNXI_DRAM_H6_DDR3_1333)	+= h6_ddr3_1333.o
diff --git a/arch/arm/mach-sunxi/dram_timings/h6_ddr3_1333.c b/arch/arm/mach-sunxi/dram_timings/h6_ddr3_1333.c
new file mode 100644
index 0000000..611eaa3
--- /dev/null
+++ b/arch/arm/mach-sunxi/dram_timings/h6_ddr3_1333.c
@@ -0,0 +1,144 @@
+/*
+ * sun50i H6 DDR3-1333 timings, as programmed by Allwinner's boot0
+ * for some TV boxes with the H6 and DDR3 memory.
+ *
+ * The chips are probably able to be driven by a faster clock, but boot0
+ * uses a more conservative timing (as usual).
+ *
+ * (C) Copyright 2018,2019 Arm Ltd.
+ *   based on previous work by:
+ *   (C) Copyright 2017      Icenowy Zheng <icenowy@aosc.io>
+ *
+ * References used:
+ * - JEDEC DDR3 SDRAM standard:	JESD79-3F.pdf
+ * - Samsung K4B2G0446D datasheet
+ * - ZynqMP UG1087 register DDRC/PHY documentation
+ *
+ * Many thanks to Jernej Skrabec for contributing some fixes!
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/dram.h>
+#include <asm/arch/cpu.h>
+
+/*
+ * Only the first four are used for DDR3(?)
+ * MR0: BL8, seq. read burst, no test, fast exit (DLL on), no DLL reset,
+ *	CAS latency (CL): 11, write recovery (WR): 12
+ * MR1: DLL enabled, output strength RZQ/6, Rtt_norm RZQ/2,
+ *	write levelling disabled, TDQS disabled, output buffer enabled
+ * MR2: manual full array self refresh, dynamic ODT off,
+ * 	CAS write latency (CWL): 8
+ */
+static u32 mr_ddr3[7] = {
+	0x00001c70, 0x00000040, 0x00000018, 0x00000000,
+	0x00000000, 0x00000400, 0x00000848,
+};
+
+/* TODO: flexible timing */
+void mctl_set_timing_params(struct dram_para *para)
+{
+	struct sunxi_mctl_ctl_reg * const mctl_ctl =
+			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+	struct sunxi_mctl_phy_reg * const mctl_phy =
+			(struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
+	int i;
+
+	u8 tccd		= 2;			/* JEDEC: 4nCK */
+	u8 tfaw		= ns_to_t(50);		/* JEDEC: 30 ns w/ 1K pages */
+	u8 trrd		= max(ns_to_t(6), 4);	/* JEDEC: max(6 ns, 4nCK) */
+	u8 trcd		= ns_to_t(15);		/* JEDEC: 13.5 ns */
+	u8 trc		= ns_to_t(53);		/* JEDEC: 49.5 ns */
+	u8 txp		= max(ns_to_t(6), 3);	/* JEDEC: max(6 ns, 3nCK) */
+	u8 twtr		= max(ns_to_t(8), 2);	/* JEDEC: max(7.5 ns, 4nCK) */
+	u8 trtp		= max(ns_to_t(8), 2);	/* JEDEC: max(7.5 ns, 4nCK) */
+	u8 twr		= ns_to_t(15);		/* JEDEC: 15 ns */
+	u8 trp		= ns_to_t(15);		/* JEDEC: >= 13.75 ns */
+	u8 tras		= ns_to_t(38);		/* JEDEC >= 36 ns, <= 9*trefi */
+	u8 twtr_sa	= 2;			/* ? */
+	u8 tcksrea	= 4;			/* ? */
+	u16 trefi	= ns_to_t(7800) / 32;	/* JEDEC: 7.8us@Tcase <= 85C */
+	u16 trfc	= ns_to_t(350);		/* JEDEC: 160 ns for 2Gb */
+	u16 txsr	= 4;			/* ? */
+
+	u8 tmrw		= 0;			/* ? */
+	u8 tmrd		= 4;			/* JEDEC: 4nCK */
+	u8 tmod		= max(ns_to_t(15), 12);	/* JEDEC: max(15 ns, 12nCK) */
+	u8 tcke		= max(ns_to_t(6), 3);	/* JEDEC: max(5.625 ns, 3nCK) */
+	u8 tcksrx	= max(ns_to_t(10), 5);	/* JEDEC: max(10 ns, 5nCK) */
+	u8 tcksre	= max(ns_to_t(10), 5);	/* JEDEC: max(10 ns, 5nCK) */
+	u8 tckesr	= tcke + 1;		/* JEDEC: tCKE(min) + 1nCK */
+	u8 trasmax	= 24;			/* JEDEC: tREFI * 9 */
+	u8 txs		= ns_to_t(360) / 32;	/* JEDEC: max(5nCK,tRFC+10ns) */
+	u8 txsdll	= 4;			/* JEDEC: 512 nCK */
+	u8 txsabort	= 4;			/* ? */
+	u8 txsfast	= 4;			/* ? */
+	u8 tcl		= 6;			/* JEDEC: CL / 2 => 6 */
+	u8 tcwl		= 4;			/* JEDEC: 8 */
+	u8 t_rdata_en	= 7;			/* ? */
+
+	u32 tdinit0	= (500 * CONFIG_DRAM_CLK) + 1;	/* 500us */
+	u32 tdinit1	= (360 * CONFIG_DRAM_CLK) / 1000 + 1;
+	u32 tdinit2	= (200 * CONFIG_DRAM_CLK) + 1;
+	u32 tdinit3	= (1 * CONFIG_DRAM_CLK) + 1;	/* 1us */
+
+	u8 twtp		= tcwl + 2 + twr;	/* (WL + BL / 2 + tWR) / 2 */
+	u8 twr2rd	= tcwl + 2 + twtr;	/* (WL + BL / 2 + tWTR) / 2 */
+	u8 trd2wr	= 5;			/* (RL + BL / 2 + 2 - WL) / 2 */
+
+	if (tcl + 1 >= trtp + trp)
+		trtp = tcl + 2 - trp;
+
+	/* set mode registers */
+	for (i = 0; i < ARRAY_SIZE(mr_ddr3); i++)
+		writel(mr_ddr3[i], &mctl_phy->mr[i]);
+
+	/* set DRAM timing */
+	writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | tras,
+	       &mctl_ctl->dramtmg[0]);
+	writel((txp << 16) | (trtp << 8) | trc, &mctl_ctl->dramtmg[1]);
+	writel((tcwl << 24) | (tcl << 16) | (trd2wr << 8) | twr2rd,
+	       &mctl_ctl->dramtmg[2]);
+	writel((tmrw << 20) | (tmrd << 12) | tmod, &mctl_ctl->dramtmg[3]);
+	writel((trcd << 24) | (tccd << 16) | (trrd << 8) | trp,
+	       &mctl_ctl->dramtmg[4]);
+	writel((tcksrx << 24) | (tcksre << 16) | (tckesr << 8) | tcke,
+	       &mctl_ctl->dramtmg[5]);
+	/* Value suggested by ZynqMP manual and used by libdram */
+	writel((txp + 2) | 0x02020000, &mctl_ctl->dramtmg[6]);
+	writel((txsfast << 24) | (txsabort << 16) | (txsdll << 8) | txs,
+	       &mctl_ctl->dramtmg[8]);
+	writel(txsr, &mctl_ctl->dramtmg[14]);
+
+	clrsetbits_le32(&mctl_ctl->init[0], (3 << 30), (1 << 30));
+	writel(0, &mctl_ctl->dfimisc);
+	clrsetbits_le32(&mctl_ctl->rankctl, 0xff0, 0x660);
+
+	/*
+	 * Set timing registers of the PHY.
+	 * Note: the PHY is clocked 2x from the DRAM frequency.
+	 */
+	writel((trrd << 25) | (tras << 17) | (trp << 9) | (trtp << 1),
+	       &mctl_phy->dtpr[0]);
+	writel((tfaw << 17) | 0x28000400 | (tmrd << 1), &mctl_phy->dtpr[1]);
+	writel(((txs << 6) - 1) | (tcke << 17), &mctl_phy->dtpr[2]);
+	writel(((txsdll << 22) - (0x1 << 16)) | twtr_sa | (tcksrea << 8),
+	       &mctl_phy->dtpr[3]);
+	writel((txp << 1) | (trfc << 17) | 0x800, &mctl_phy->dtpr[4]);
+	writel((trc << 17) | (trcd << 9) | (twtr << 1), &mctl_phy->dtpr[5]);
+	writel(0x0505, &mctl_phy->dtpr[6]);
+
+	/* Configure DFI timing */
+	writel(tcl | 0x2000200 | (t_rdata_en << 16) | 0x808000,
+	       &mctl_ctl->dfitmg0);
+	writel(0x040201, &mctl_ctl->dfitmg1);
+
+	/* Configure PHY timing. Zynq uses different registers. */
+	writel(tdinit0 | (tdinit1 << 20), &mctl_phy->ptr[3]);
+	writel(tdinit2 | (tdinit3 << 18), &mctl_phy->ptr[4]);
+
+	/* set refresh timing */
+	writel((trefi << 16) | trfc, &mctl_ctl->rfshtmg);
+}
diff --git a/arch/arm/mach-sunxi/dram_timings/h6_lpddr3.c b/arch/arm/mach-sunxi/dram_timings/h6_lpddr3.c
new file mode 100644
index 0000000..1000860
--- /dev/null
+++ b/arch/arm/mach-sunxi/dram_timings/h6_lpddr3.c
@@ -0,0 +1,132 @@
+/*
+ * sun50i H6 LPDDR3 timings
+ *
+ * (C) Copyright 2017      Icenowy Zheng <icenowy@aosc.io>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/dram.h>
+#include <asm/arch/cpu.h>
+
+static u32 mr_lpddr3[12] = {
+	0x00000000, 0x00000043, 0x0000001a, 0x00000001,
+	0x00000000, 0x00000000, 0x00000048, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000003,
+};
+
+/* TODO: flexible timing */
+void mctl_set_timing_params(struct dram_para *para)
+{
+	struct sunxi_mctl_ctl_reg * const mctl_ctl =
+			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+	struct sunxi_mctl_phy_reg * const mctl_phy =
+			(struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
+	int i;
+
+	u8 tccd		= 2;
+	u8 tfaw		= max(ns_to_t(50), 4);
+	u8 trrd		= max(ns_to_t(10), 2);
+	u8 trcd		= max(ns_to_t(24), 2);
+	u8 trc		= ns_to_t(70);
+	u8 txp		= max(ns_to_t(8), 2);
+	u8 twtr		= max(ns_to_t(8), 2);
+	u8 trtp		= max(ns_to_t(8), 2);
+	u8 twr		= max(ns_to_t(15), 2);
+	u8 trp		= ns_to_t(18);
+	u8 tras		= ns_to_t(42);
+	u8 twtr_sa	= ns_to_t(5);
+	u8 tcksrea	= ns_to_t(11);
+	u16 trefi	= ns_to_t(3900) / 32;
+	u16 trfc	= ns_to_t(210);
+	u16 txsr	= ns_to_t(220);
+
+	if (CONFIG_DRAM_CLK % 400 == 0) {
+		/* Round up these parameters */
+		twtr_sa++;
+		tcksrea++;
+	}
+
+	u8 tmrw		= 5;
+	u8 tmrd		= 5;
+	u8 tmod		= 12;
+	u8 tcke		= 3;
+	u8 tcksrx	= 5;
+	u8 tcksre	= 5;
+	u8 tckesr	= 5;
+	u8 trasmax	= CONFIG_DRAM_CLK / 60;
+	u8 txs		= 4;
+	u8 txsdll	= 4;
+	u8 txsabort	= 4;
+	u8 txsfast	= 4;
+
+	u8 tcl		= 5; /* CL 10 */
+	u8 tcwl		= 3; /* CWL 6 */
+	u8 t_rdata_en	= twtr_sa + 8;
+
+	u32 tdinit0	= (200 * CONFIG_DRAM_CLK) + 1;		/* 200us */
+	u32 tdinit1	= (100 * CONFIG_DRAM_CLK) / 1000 + 1;	/* 100ns */
+	u32 tdinit2	= (11 * CONFIG_DRAM_CLK) + 1;		/* 11us */
+	u32 tdinit3	= (1 * CONFIG_DRAM_CLK) + 1;		/* 1us */
+
+	u8 twtp		= tcwl + 4 + twr + 1;
+	/*
+	 * The code below for twr2rd and trd2wr follows the IP core's
+	 * document from ZynqMP and i.MX7. The BSP has both number
+	 * substracted by 2.
+	 */
+	u8 twr2rd	= tcwl + 4 + 1 + twtr;
+	u8 trd2wr	= tcl + 4 + (tcksrea >> 1) - tcwl + 1;
+
+	/* set mode registers */
+	for (i = 0; i < ARRAY_SIZE(mr_lpddr3); i++)
+		writel(mr_lpddr3[i], &mctl_phy->mr[i]);
+
+	/* set DRAM timing */
+	writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | tras,
+	       &mctl_ctl->dramtmg[0]);
+	writel((txp << 16) | (trtp << 8) | trc, &mctl_ctl->dramtmg[1]);
+	writel((tcwl << 24) | (tcl << 16) | (trd2wr << 8) | twr2rd,
+	       &mctl_ctl->dramtmg[2]);
+	writel((tmrw << 20) | (tmrd << 12) | tmod, &mctl_ctl->dramtmg[3]);
+	writel((trcd << 24) | (tccd << 16) | (trrd << 8) | trp,
+	       &mctl_ctl->dramtmg[4]);
+	writel((tcksrx << 24) | (tcksre << 16) | (tckesr << 8) | tcke,
+	       &mctl_ctl->dramtmg[5]);
+	/* Value suggested by ZynqMP manual and used by libdram */
+	writel((txp + 2) | 0x02020000, &mctl_ctl->dramtmg[6]);
+	writel((txsfast << 24) | (txsabort << 16) | (txsdll << 8) | txs,
+	       &mctl_ctl->dramtmg[8]);
+	writel(txsr, &mctl_ctl->dramtmg[14]);
+
+	clrsetbits_le32(&mctl_ctl->init[0], (3 << 30), (1 << 30));
+	writel(0, &mctl_ctl->dfimisc);
+	clrsetbits_le32(&mctl_ctl->rankctl, 0xff0, 0x660);
+
+	/*
+	 * Set timing registers of the PHY.
+	 * Note: the PHY is clocked 2x from the DRAM frequency.
+	 */
+	writel((trrd << 25) | (tras << 17) | (trp << 9) | (trtp << 1),
+	       &mctl_phy->dtpr[0]);
+	writel((tfaw << 17) | 0x28000400 | (tmrd << 1), &mctl_phy->dtpr[1]);
+	writel(((txs << 6) - 1) | (tcke << 17), &mctl_phy->dtpr[2]);
+	writel(((txsdll << 22) - (0x1 << 16)) | twtr_sa | (tcksrea << 8),
+	       &mctl_phy->dtpr[3]);
+	writel((txp << 1) | (trfc << 17) | 0x800, &mctl_phy->dtpr[4]);
+	writel((trc << 17) | (trcd << 9) | (twtr << 1), &mctl_phy->dtpr[5]);
+	writel(0x0505, &mctl_phy->dtpr[6]);
+
+	/* Configure DFI timing */
+	writel(tcl | 0x2000200 | (t_rdata_en << 16) | 0x808000,
+	       &mctl_ctl->dfitmg0);
+	writel(0x040201, &mctl_ctl->dfitmg1);
+
+	/* Configure PHY timing */
+	writel(tdinit0 | (tdinit1 << 20), &mctl_phy->ptr[3]);
+	writel(tdinit2 | (tdinit3 << 18), &mctl_phy->ptr[4]);
+
+	/* set refresh timing */
+	writel((trefi << 16) | trfc, &mctl_ctl->rfshtmg);
+}
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 531c1af..a05414e 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -756,6 +756,10 @@
 			  3 0x300 0xB000 0x1000
 			 >;
 
+		dma-ranges = <0 0x000 0x10000000 0x1000
+			      1 0x100 0x20000000 0x1000
+			     >;
+
 		dev@0,0 {
 			compatible = "denx,u-boot-fdt-dummy";
 			reg = <0 0x0 0x1000>;
@@ -824,7 +828,28 @@
 		dma-names = "m2m", "tx0", "rx0";
 	};
 
+	/*
+	 * keep mdio-mux ahead of mdio so that the mux is removed first at the
+	 * end of the test.  If parent mdio is removed first, clean-up of the
+	 * mux will trigger a 2nd probe of parent-mdio, leaving parent-mdio
+	 * active at the end of the test.  That it turn doesn't allow the mdio
+	 * class to be destroyed, triggering an error.
+	 */
+	mdio-mux-test {
+		compatible = "sandbox,mdio-mux";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		mdio-parent-bus = <&mdio>;
+
+		mdio-ch-test@0 {
+			reg = <0>;
+		};
+		mdio-ch-test@1 {
+			reg = <1>;
+		};
+	};
+
-	mdio-test {
+	mdio: mdio-test {
 		compatible = "sandbox,mdio";
 	};
 };
diff --git a/board/amarula/vyasa-rk3288/vyasa-rk3288.c b/board/amarula/vyasa-rk3288/vyasa-rk3288.c
index 2b509f5..baf197c 100644
--- a/board/amarula/vyasa-rk3288/vyasa-rk3288.c
+++ b/board/amarula/vyasa-rk3288/vyasa-rk3288.c
@@ -6,14 +6,6 @@
 #include <common.h>
 
 #ifndef CONFIG_TPL_BUILD
-#include <spl.h>
-
-void board_boot_order(u32 *spl_boot_list)
-{
-	/* eMMC prior to sdcard. */
-	spl_boot_list[0] = BOOT_DEVICE_MMC2;
-	spl_boot_list[1] = BOOT_DEVICE_MMC1;
-}
 
 int spl_start_uboot(void)
 {
diff --git a/board/chipspark/popmetal_rk3288/popmetal-rk3288.c b/board/chipspark/popmetal_rk3288/popmetal-rk3288.c
index 355c78b..9ba1fbd 100644
--- a/board/chipspark/popmetal_rk3288/popmetal-rk3288.c
+++ b/board/chipspark/popmetal_rk3288/popmetal-rk3288.c
@@ -4,16 +4,8 @@
  */
 
 #include <common.h>
-#include <spl.h>
 #include <asm/gpio.h>
 
-void board_boot_order(u32 *spl_boot_list)
-{
-	/* eMMC prior to sdcard */
-	spl_boot_list[0] = BOOT_DEVICE_MMC2;
-	spl_boot_list[1] = BOOT_DEVICE_MMC1;
-}
-
 #define GPIO7A3_HUB_RST	227
 
 int rk_board_late_init(void)
diff --git a/board/emulation/qemu-riscv/Kconfig b/board/emulation/qemu-riscv/Kconfig
index 7f9a74d..6cc7c31 100644
--- a/board/emulation/qemu-riscv/Kconfig
+++ b/board/emulation/qemu-riscv/Kconfig
@@ -24,6 +24,7 @@
 	imply VIRTIO_MMIO
 	imply VIRTIO_NET
 	imply VIRTIO_BLK
+	imply VIRTIO_PCI
 	imply CMD_PING
 	imply CMD_FS_GENERIC
 	imply DOS_PARTITION
diff --git a/board/mqmaker/miqi_rk3288/miqi-rk3288.c b/board/mqmaker/miqi_rk3288/miqi-rk3288.c
index d6992a2..779bc64 100644
--- a/board/mqmaker/miqi_rk3288/miqi-rk3288.c
+++ b/board/mqmaker/miqi_rk3288/miqi-rk3288.c
@@ -3,12 +3,3 @@
  * (C) Copyright 2016 Rockchip Electronics Co., Ltd
  */
 
-#include <common.h>
-#include <spl.h>
-
-void board_boot_order(u32 *spl_boot_list)
-{
-	/* eMMC prior to sdcard. */
-	spl_boot_list[0] = BOOT_DEVICE_MMC2;
-	spl_boot_list[1] = BOOT_DEVICE_MMC1;
-}
diff --git a/board/rockchip/evb_rk3288/evb-rk3288.c b/board/rockchip/evb_rk3288/evb-rk3288.c
index d6992a2..779bc64 100644
--- a/board/rockchip/evb_rk3288/evb-rk3288.c
+++ b/board/rockchip/evb_rk3288/evb-rk3288.c
@@ -3,12 +3,3 @@
  * (C) Copyright 2016 Rockchip Electronics Co., Ltd
  */
 
-#include <common.h>
-#include <spl.h>
-
-void board_boot_order(u32 *spl_boot_list)
-{
-	/* eMMC prior to sdcard. */
-	spl_boot_list[0] = BOOT_DEVICE_MMC2;
-	spl_boot_list[1] = BOOT_DEVICE_MMC1;
-}
diff --git a/board/rockchip/evb_rk3399/README b/board/rockchip/evb_rk3399/README
index 6469821..ea3258c 100644
--- a/board/rockchip/evb_rk3399/README
+++ b/board/rockchip/evb_rk3399/README
@@ -35,12 +35,6 @@
   > git clone https://github.com/rockchip-linux/rkbin.git
   > git clone https://github.com/rockchip-linux/rkdeveloptool.git
 
-Get some prerequisites
-======================
-
-You need the Python elftools.elf.elffile library for make_fit_atf.py to work:
-
-  > sudo apt-get install python-pyelftools
 
 Compile ATF
 ===========
diff --git a/board/rockchip/fennec_rk3288/fennec-rk3288.c b/board/rockchip/fennec_rk3288/fennec-rk3288.c
index ce45544..779bc64 100644
--- a/board/rockchip/fennec_rk3288/fennec-rk3288.c
+++ b/board/rockchip/fennec_rk3288/fennec-rk3288.c
@@ -3,12 +3,3 @@
  * (C) Copyright 2016 Rockchip Electronics Co., Ltd
  */
 
-#include <common.h>
-#include <spl.h>
-
-void board_boot_order(u32 *spl_boot_list)
-{
-	/* eMMC prior to sdcard */
-	spl_boot_list[0] = BOOT_DEVICE_MMC2;
-	spl_boot_list[1] = BOOT_DEVICE_MMC1;
-}
diff --git a/board/sifive/fu540/Kconfig b/board/sifive/fu540/Kconfig
index 8eb5e30..5d65080 100644
--- a/board/sifive/fu540/Kconfig
+++ b/board/sifive/fu540/Kconfig
@@ -28,7 +28,6 @@
 	imply CMD_PING
 	imply CLK_SIFIVE
 	imply CLK_SIFIVE_FU540_PRCI
-	imply CLK_SIFIVE_GEMGXL_MGMT
 	imply DOS_PARTITION
 	imply EFI_PARTITION
 	imply IP_DYN
@@ -39,6 +38,12 @@
 	imply PHY_LIB
 	imply PHY_MSCC
 	imply SIFIVE_SERIAL
+	imply SPI
+	imply SPI_SIFIVE
+	imply MMC
+	imply MMC_SPI
+	imply MMC_BROKEN_CD
+	imply CMD_MMC
 	imply SMP
 
 endif
diff --git a/board/sifive/fu540/fu540.c b/board/sifive/fu540/fu540.c
index 5adc4a3..11daf1a 100644
--- a/board/sifive/fu540/fu540.c
+++ b/board/sifive/fu540/fu540.c
@@ -8,6 +8,128 @@
 
 #include <common.h>
 #include <dm.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#ifdef CONFIG_MISC_INIT_R
+
+#define FU540_OTP_BASE_ADDR			0x10070000
+
+struct fu540_otp_regs {
+	u32 pa;     /* Address input */
+	u32 paio;   /* Program address input */
+	u32 pas;    /* Program redundancy cell selection input */
+	u32 pce;    /* OTP Macro enable input */
+	u32 pclk;   /* Clock input */
+	u32 pdin;   /* Write data input */
+	u32 pdout;  /* Read data output */
+	u32 pdstb;  /* Deep standby mode enable input (active low) */
+	u32 pprog;  /* Program mode enable input */
+	u32 ptc;    /* Test column enable input */
+	u32 ptm;    /* Test mode enable input */
+	u32 ptm_rep;/* Repair function test mode enable input */
+	u32 ptr;    /* Test row enable input */
+	u32 ptrim;  /* Repair function enable input */
+	u32 pwe;    /* Write enable input (defines program cycle) */
+} __packed;
+
+#define BYTES_PER_FUSE				4
+#define NUM_FUSES				0x1000
+
+static int fu540_otp_read(int offset, void *buf, int size)
+{
+	struct fu540_otp_regs *regs = (void __iomem *)FU540_OTP_BASE_ADDR;
+	unsigned int i;
+	int fuseidx = offset / BYTES_PER_FUSE;
+	int fusecount = size / BYTES_PER_FUSE;
+	u32 fusebuf[fusecount];
+
+	/* check bounds */
+	if (offset < 0 || size < 0)
+		return -EINVAL;
+	if (fuseidx >= NUM_FUSES)
+		return -EINVAL;
+	if ((fuseidx + fusecount) > NUM_FUSES)
+		return -EINVAL;
+
+	/* init OTP */
+	writel(0x01, &regs->pdstb); /* wake up from stand-by */
+	writel(0x01, &regs->ptrim); /* enable repair function */
+	writel(0x01, &regs->pce);   /* enable input */
+
+	/* read all requested fuses */
+	for (i = 0; i < fusecount; i++, fuseidx++) {
+		writel(fuseidx, &regs->pa);
+
+		/* cycle clock to read */
+		writel(0x01, &regs->pclk);
+		mdelay(1);
+		writel(0x00, &regs->pclk);
+		mdelay(1);
+
+		/* read the value */
+		fusebuf[i] = readl(&regs->pdout);
+	}
+
+	/* shut down */
+	writel(0, &regs->pce);
+	writel(0, &regs->ptrim);
+	writel(0, &regs->pdstb);
+
+	/* copy out */
+	memcpy(buf, fusebuf, size);
+
+	return 0;
+}
+
+static u32 fu540_read_serialnum(void)
+{
+	int ret;
+	u32 serial[2] = {0};
+
+	for (int i = 0xfe * 4; i > 0; i -= 8) {
+		ret = fu540_otp_read(i, serial, sizeof(serial));
+		if (ret) {
+			printf("%s: error reading from OTP\n", __func__);
+			break;
+		}
+		if (serial[0] == ~serial[1])
+			return serial[0];
+	}
+
+	return 0;
+}
+
+static void fu540_setup_macaddr(u32 serialnum)
+{
+	/* Default MAC address */
+	unsigned char mac[6] = { 0x70, 0xb3, 0xd5, 0x92, 0xf0, 0x00 };
+
+	/*
+	 * We derive our board MAC address by ORing last three bytes
+	 * of board serial number to above default MAC address.
+	 *
+	 * This logic of deriving board MAC address is taken from
+	 * SiFive FSBL and is kept unchanged.
+	 */
+	mac[5] |= (serialnum >>  0) & 0xff;
+	mac[4] |= (serialnum >>  8) & 0xff;
+	mac[3] |= (serialnum >> 16) & 0xff;
+
+	/* Update environment variable */
+	eth_env_set_enetaddr("ethaddr", mac);
+}
+
+int misc_init_r(void)
+{
+	/* Set ethaddr environment variable if not set */
+	if (!env_get("ethaddr"))
+		fu540_setup_macaddr(fu540_read_serialnum());
+
+	return 0;
+}
+
+#endif
 
 int board_init(void)
 {
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index bdd1854..c7e9d3e 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -172,6 +172,12 @@
 F:	configs/beelink_gs1_defconfig
 F:	arch/arm/dts/sun50i-h6-beelink-gs1.dts
 
+BEELINK X2 BOARD
+M:	Marcus Cooper <codekipper@gmail.com>
+S:	Maintained
+F:	configs/beelink_x2_defconfig
+F:	arch/arm/dts/sun8i-h3-beelink-x2.dts
+
 COLOMBUS BOARD
 M:	Maxime Ripard <maxime.ripard@bootlin.com>
 S:	Maintained
diff --git a/board/ti/am65x/Kconfig b/board/ti/am65x/Kconfig
index 98172c2..47b41cd 100644
--- a/board/ti/am65x/Kconfig
+++ b/board/ti/am65x/Kconfig
@@ -12,14 +12,18 @@
 	select ARM64
 	select SOC_K3_AM6
 	select SYS_DISABLE_DCACHE_OPS
+	select BOARD_LATE_INIT
+	imply TI_I2C_BOARD_DETECT
 
 config TARGET_AM654_R5_EVM
 	bool "TI K3 based AM654 EVM running on R5"
 	select CPU_V7R
 	select SYS_THUMB_BUILD
 	select SOC_K3_AM6
+	select K3_LOAD_SYSFW
 	select K3_AM654_DDRSS
 	imply SYS_K3_SPL_ATF
+	imply TI_I2C_BOARD_DETECT
 
 endchoice
 
@@ -34,6 +38,8 @@
 config SYS_CONFIG_NAME
        default "am65x_evm"
 
+source "board/ti/common/Kconfig"
+
 endif
 
 if TARGET_AM654_R5_EVM
@@ -50,4 +56,6 @@
 config SPL_LDSCRIPT
 	default "arch/arm/mach-omap2/u-boot-spl.lds"
 
+source "board/ti/common/Kconfig"
+
 endif
diff --git a/board/ti/am65x/README b/board/ti/am65x/README
index 0b82bd5..16384e0 100644
--- a/board/ti/am65x/README
+++ b/board/ti/am65x/README
@@ -209,3 +209,55 @@
                 | |    Secure config  | |
                 | +-------------------+ |
                 +-----------------------+
+
+eMMC:
+-----
+ROM supports booting from eMMC from boot0 partition offset 0x0
+
+Flashing images to eMMC:
+
+The following commands can be used to download tiboot3.bin, tispl.bin,
+u-boot.img, and sysfw.itb from an SD card and write them to the eMMC boot0
+partition at respective addresses.
+
+=> mmc dev 0 1
+=> fatload mmc 1 ${loadaddr} tiboot3.bin
+=> mmc write ${loadaddr} 0x0 0x400
+=> fatload mmc 1 ${loadaddr} tispl.bin
+=> mmc write ${loadaddr} 0x400 0x1000
+=> fatload mmc 1 ${loadaddr} u-boot.img
+=> mmc write ${loadaddr} 0x1400 0x2000
+=> fatload mmc 1 ${loadaddr} sysfw.itb
+=> mmc write ${loadaddr} 0x3600 0x800
+
+To give the ROM access to the boot partition, the following commands must be
+used for the first time:
+=> mmc partconf 0 1 1 1
+=> mmc bootbus 0 1 0 0
+
+To create a software partition for the rootfs, the following command can be
+used:
+=> gpt write mmc 0 ${partitions}
+
+eMMC layout:
+
+           boot0 partition (8 MB)                        user partition
+   0x0+----------------------------------+      0x0+-------------------------+
+      |     tiboot3.bin (512 KB)         |         |                         |
+ 0x400+----------------------------------+         |                         |
+      |       tispl.bin (2 MB)           |         |                         |
+0x1400+----------------------------------+         |        rootfs           |
+      |       u-boot.img (4 MB)          |         |                         |
+0x3400+----------------------------------+         |                         |
+      |      environment (128 KB)        |         |                         |
+0x3500+----------------------------------+         |                         |
+      |   backup environment (128 KB)    |         |                         |
+0x3600+----------------------------------+         |                         |
+      |          sysfw (1 MB)            |         |                         |
+0x3E00+----------------------------------+         +-------------------------+
+
+Kernel image and DT are expected to be present in the /boot folder of rootfs.
+To boot kernel from eMMC, use the following commands:
+=> setenv mmcdev 0
+=> setenv bootpart 0
+=> boot
diff --git a/board/ti/am65x/evm.c b/board/ti/am65x/evm.c
index 52f5d6b..7bd8c4f 100644
--- a/board/ti/am65x/evm.c
+++ b/board/ti/am65x/evm.c
@@ -8,10 +8,31 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/hardware.h>
+#include <asm/gpio.h>
 #include <asm/io.h>
+#include <asm/omap_common.h>
 #include <spl.h>
 #include <asm/arch/sys_proto.h>
 
+#include "../common/board_detect.h"
+
+#define board_is_am65x_base_board()	board_ti_is("AM6-COMPROCEVM")
+
+/* Daughter card presence detection signals */
+enum {
+	AM65X_EVM_APP_BRD_DET,
+	AM65X_EVM_LCD_BRD_DET,
+	AM65X_EVM_SERDES_BRD_DET,
+	AM65X_EVM_HDMI_GPMC_BRD_DET,
+	AM65X_EVM_BRD_DET_COUNT,
+};
+
+/* Max number of MAC addresses that are parsed/processed per daughter card */
+#define DAUGHTER_CARD_NO_OF_MAC_ADDR	8
+
 DECLARE_GLOBAL_DATA_PTR;
 
 int board_init(void)
@@ -80,3 +101,223 @@
 	return ret;
 }
 #endif
+
+int do_board_detect(void)
+{
+	int ret;
+
+	ret = ti_i2c_eeprom_am6_get_base(CONFIG_EEPROM_BUS_ADDRESS,
+					 CONFIG_EEPROM_CHIP_ADDRESS);
+	if (ret)
+		pr_err("Reading on-board EEPROM at 0x%02x failed %d\n",
+		       CONFIG_EEPROM_CHIP_ADDRESS, ret);
+
+	return ret;
+}
+
+static void setup_board_eeprom_env(void)
+{
+	char *name = "am65x";
+
+	if (do_board_detect())
+		goto invalid_eeprom;
+
+	if (board_is_am65x_base_board())
+		name = "am65x";
+	else
+		printf("Unidentified board claims %s in eeprom header\n",
+		       board_ti_get_name());
+
+invalid_eeprom:
+	set_board_info_env_am6(name);
+}
+
+static int init_daughtercard_det_gpio(char *gpio_name, struct gpio_desc *desc)
+{
+	int ret;
+
+	memset(desc, 0, sizeof(*desc));
+
+	ret = dm_gpio_lookup_name(gpio_name, desc);
+	if (ret < 0)
+		return ret;
+
+	/* Request GPIO, simply re-using the name as label */
+	ret = dm_gpio_request(desc, gpio_name);
+	if (ret < 0)
+		return ret;
+
+	return dm_gpio_set_dir_flags(desc, GPIOD_IS_IN);
+}
+
+static int probe_daughtercards(void)
+{
+	struct ti_am6_eeprom ep;
+	struct gpio_desc board_det_gpios[AM65X_EVM_BRD_DET_COUNT];
+	char mac_addr[DAUGHTER_CARD_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN];
+	u8 mac_addr_cnt;
+	char name_overlays[1024] = { 0 };
+	int i, j;
+	int ret;
+
+	/*
+	 * Daughter card presence detection signal name to GPIO (via I2C I/O
+	 * expander @ address 0x38) name and EEPROM I2C address mapping.
+	 */
+	const struct {
+		char *gpio_name;
+		u8 i2c_addr;
+	} slot_map[AM65X_EVM_BRD_DET_COUNT] = {
+		{ "gpio@38_0", 0x52, },	/* AM65X_EVM_APP_BRD_DET */
+		{ "gpio@38_1", 0x55, },	/* AM65X_EVM_LCD_BRD_DET */
+		{ "gpio@38_2", 0x54, },	/* AM65X_EVM_SERDES_BRD_DET */
+		{ "gpio@38_3", 0x53, },	/* AM65X_EVM_HDMI_GPMC_BRD_DET */
+	};
+
+	/* Declaration of daughtercards to probe */
+	const struct {
+		u8 slot_index;		/* Slot the card is installed */
+		char *card_name;	/* EEPROM-programmed card name */
+		char *dtbo_name;	/* Device tree overlay to apply */
+		u8 eth_offset;		/* ethXaddr MAC address index offset */
+	} cards[] = {
+		{
+			AM65X_EVM_APP_BRD_DET,
+			"AM6-GPAPPEVM",
+			"k3-am654-gp.dtbo",
+			0,
+		},
+		{
+			AM65X_EVM_APP_BRD_DET,
+			"AM6-IDKAPPEVM",
+			"k3-am654-idk.dtbo",
+			3,
+		},
+		{
+			AM65X_EVM_SERDES_BRD_DET,
+			"SER-PCIE2LEVM",
+			"k3-am654-pcie-usb2.dtbo",
+			0,
+		},
+		{
+			AM65X_EVM_SERDES_BRD_DET,
+			"SER-PCIEUSBEVM",
+			"k3-am654-pcie-usb3.dtbo",
+			0,
+		},
+		{
+			AM65X_EVM_LCD_BRD_DET,
+			"OLDI-LCD1EVM",
+			"k3-am654-evm-oldi-lcd1evm.dtbo",
+			0,
+		},
+	};
+
+	/*
+	 * Initialize GPIO used for daughtercard slot presence detection and
+	 * keep the resulting handles in local array for easier access.
+	 */
+	for (i = 0; i < AM65X_EVM_BRD_DET_COUNT; i++) {
+		ret = init_daughtercard_det_gpio(slot_map[i].gpio_name,
+						 &board_det_gpios[i]);
+		if (ret < 0)
+			return ret;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(cards); i++) {
+		/* Obtain card-specific slot index and associated I2C address */
+		u8 slot_index = cards[i].slot_index;
+		u8 i2c_addr = slot_map[slot_index].i2c_addr;
+
+		/*
+		 * The presence detection signal is active-low, hence skip
+		 * over this card slot if anything other than 0 is returned.
+		 */
+		ret = dm_gpio_get_value(&board_det_gpios[slot_index]);
+		if (ret < 0)
+			return ret;
+		else if (ret)
+			continue;
+
+		/* Get and parse the daughter card EEPROM record */
+		ret = ti_i2c_eeprom_am6_get(CONFIG_EEPROM_BUS_ADDRESS, i2c_addr,
+					    &ep,
+					    (char **)mac_addr,
+					    DAUGHTER_CARD_NO_OF_MAC_ADDR,
+					    &mac_addr_cnt);
+		if (ret) {
+			pr_err("Reading daughtercard EEPROM at 0x%02x failed %d\n",
+			       i2c_addr, ret);
+			/*
+			 * Even this is pretty serious let's just skip over
+			 * this particular daughtercard, rather than ending
+			 * the probing process altogether.
+			 */
+			continue;
+		}
+
+		/* Only process the parsed data if we found a match */
+		if (strncmp(ep.name, cards[i].card_name, sizeof(ep.name)))
+			continue;
+
+		printf("detected %s\n", cards[i].card_name);
+
+		/*
+		 * Populate any MAC addresses from daughtercard into the U-Boot
+		 * environment, starting with a card-specific offset so we can
+		 * have multiple cards contribute to the MAC pool in a well-
+		 * defined manner.
+		 */
+		for (j = 0; j < mac_addr_cnt; j++) {
+			if (!is_valid_ethaddr((u8 *)mac_addr[j]))
+				continue;
+
+			eth_env_set_enetaddr_by_index("eth",
+						      cards[i].eth_offset + j,
+						      (uchar *)mac_addr[j]);
+		}
+
+		/* Skip if no overlays are to be added */
+		if (!strlen(cards[i].dtbo_name))
+			continue;
+
+		/*
+		 * Make sure we are not running out of buffer space by checking
+		 * if we can fit the new overlay, a trailing space to be used
+		 * as a separator, plus the terminating zero.
+		 */
+		if (strlen(name_overlays) + strlen(cards[i].dtbo_name) + 2 >
+		    sizeof(name_overlays))
+			return -ENOMEM;
+
+		/* Append to our list of overlays */
+		strcat(name_overlays, cards[i].dtbo_name);
+		strcat(name_overlays, " ");
+	}
+
+	/* Apply device tree overlay(s) to the U-Boot environment, if any */
+	if (strlen(name_overlays))
+		return env_set("name_overlays", name_overlays);
+
+	return 0;
+}
+
+int board_late_init(void)
+{
+	struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
+
+	setup_board_eeprom_env();
+
+	/*
+	 * The first MAC address for ethernet a.k.a. ethernet0 comes from
+	 * efuse populated via the am654 gigabit eth switch subsystem driver.
+	 * All the other ones are populated via EEPROM, hence continue with
+	 * an index of 1.
+	 */
+	board_ti_am6_set_ethaddr(1, ep->mac_addr_cnt);
+
+	/* Check for and probe any plugged-in daughtercards */
+	probe_daughtercards();
+
+	return 0;
+}
diff --git a/board/ti/common/board_detect.c b/board/ti/common/board_detect.c
index e258e22..32fa105 100644
--- a/board/ti/common/board_detect.c
+++ b/board/ti/common/board_detect.c
@@ -8,6 +8,7 @@
  */
 
 #include <common.h>
+#include <asm/arch/hardware.h>
 #include <asm/omap_common.h>
 #include <dm/uclass.h>
 #include <i2c.h>
@@ -284,6 +285,191 @@
 	return 0;
 }
 
+static int ti_i2c_eeprom_am6_parse_record(struct ti_am6_eeprom_record *record,
+					  struct ti_am6_eeprom *ep,
+					  char **mac_addr,
+					  u8 mac_addr_max_cnt,
+					  u8 *mac_addr_cnt)
+{
+	switch (record->header.id) {
+	case TI_AM6_EEPROM_RECORD_BOARD_INFO:
+		if (record->header.len != sizeof(record->data.board_info))
+			return -EINVAL;
+
+		if (!ep)
+			break;
+
+		/* Populate (and clean, if needed) the board name */
+		strlcpy(ep->name, record->data.board_info.name,
+			sizeof(ep->name));
+		ti_eeprom_string_cleanup(ep->name);
+
+		/* Populate selected other fields from the board info record */
+		strlcpy(ep->version, record->data.board_info.version,
+			sizeof(ep->version));
+		strlcpy(ep->software_revision,
+			record->data.board_info.software_revision,
+			sizeof(ep->software_revision));
+		strlcpy(ep->serial, record->data.board_info.serial,
+			sizeof(ep->serial));
+		break;
+	case TI_AM6_EEPROM_RECORD_MAC_INFO:
+		if (record->header.len != sizeof(record->data.mac_info))
+			return -EINVAL;
+
+		if (!mac_addr || !mac_addr_max_cnt)
+			break;
+
+		*mac_addr_cnt = ((record->data.mac_info.mac_control &
+				 TI_AM6_EEPROM_MAC_ADDR_COUNT_MASK) >>
+				 TI_AM6_EEPROM_MAC_ADDR_COUNT_SHIFT) + 1;
+
+		/*
+		 * The EEPROM can (but may not) hold a very large amount
+		 * of MAC addresses, by far exceeding what we want/can store
+		 * in the common memory array, so only grab what we can fit.
+		 * Note that a value of 0 means 1 MAC address, and so on.
+		 */
+		*mac_addr_cnt = min(*mac_addr_cnt, mac_addr_max_cnt);
+
+		memcpy(mac_addr, record->data.mac_info.mac_addr,
+		       *mac_addr_cnt * TI_EEPROM_HDR_ETH_ALEN);
+		break;
+	case 0x00:
+		/* Illegal value... Fall through... */
+	case 0xFF:
+		/* Illegal value... Something went horribly wrong... */
+		return -EINVAL;
+	default:
+		pr_warn("%s: Ignoring record id %u\n", __func__,
+			record->header.id);
+	}
+
+	return 0;
+}
+
+int __maybe_unused ti_i2c_eeprom_am6_get(int bus_addr, int dev_addr,
+					 struct ti_am6_eeprom *ep,
+					 char **mac_addr,
+					 u8 mac_addr_max_cnt,
+					 u8 *mac_addr_cnt)
+{
+	struct udevice *dev;
+	struct udevice *bus;
+	unsigned int eeprom_addr;
+	struct ti_am6_eeprom_record_board_id board_id;
+	struct ti_am6_eeprom_record record;
+	int rc;
+
+	/* Initialize with a known bad marker for i2c fails.. */
+	memset(ep, 0, sizeof(*ep));
+	ep->header = TI_DEAD_EEPROM_MAGIC;
+
+	/* Read the board ID record which is always the first EEPROM record */
+	rc = ti_i2c_eeprom_get(bus_addr, dev_addr, TI_EEPROM_HEADER_MAGIC,
+			       sizeof(board_id), (uint8_t *)&board_id);
+	if (rc)
+		return rc;
+
+	if (board_id.header.id != TI_AM6_EEPROM_RECORD_BOARD_ID) {
+		pr_err("%s: Invalid board ID record!\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Establish DM handle to board config EEPROM */
+	rc = uclass_get_device_by_seq(UCLASS_I2C, bus_addr, &bus);
+	if (rc)
+		return rc;
+	rc = i2c_get_chip(bus, dev_addr, 1, &dev);
+	if (rc)
+		return rc;
+
+	ep->header = TI_EEPROM_HEADER_MAGIC;
+
+	/* Ready to parse TLV structure. Initialize variables... */
+	*mac_addr_cnt = 0;
+
+	/*
+	 * After the all-encompassing board ID record all other records follow
+	 * a TLV-type scheme. Point to the first such record and then start
+	 * parsing those one by one.
+	 */
+	eeprom_addr = sizeof(board_id);
+
+	while (true) {
+		rc = dm_i2c_read(dev, eeprom_addr, (uint8_t *)&record.header,
+				 sizeof(record.header));
+		if (rc)
+			return rc;
+
+		/*
+		 * Check for end of list marker. If we reached it don't go
+		 * any further and stop parsing right here.
+		 */
+		if (record.header.id == TI_AM6_EEPROM_RECORD_END_LIST)
+			break;
+
+		eeprom_addr += sizeof(record.header);
+
+		debug("%s: dev_addr=0x%02x header.id=%u header.len=%u\n",
+		      __func__, dev_addr, record.header.id,
+		      record.header.len);
+
+		/* Read record into memory if it fits */
+		if (record.header.len <= sizeof(record.data)) {
+			rc = dm_i2c_read(dev, eeprom_addr,
+					 (uint8_t *)&record.data,
+					 record.header.len);
+			if (rc)
+				return rc;
+
+			/* Process record */
+			rc = ti_i2c_eeprom_am6_parse_record(&record, ep,
+							    mac_addr,
+							    mac_addr_max_cnt,
+							    mac_addr_cnt);
+			if (rc) {
+				pr_err("%s: EEPROM parsing error!\n", __func__);
+				return rc;
+			}
+		} else {
+			/*
+			 * We may get here in case of larger records which
+			 * are not yet understood.
+			 */
+			pr_err("%s: Ignoring record id %u\n", __func__,
+			       record.header.id);
+		}
+
+		eeprom_addr += record.header.len;
+	}
+
+	return 0;
+}
+
+int __maybe_unused ti_i2c_eeprom_am6_get_base(int bus_addr, int dev_addr)
+{
+	struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
+	int ret;
+
+	/*
+	 * Always execute EEPROM read by not allowing to bypass it during the
+	 * first invocation of SPL which happens on the R5 core.
+	 */
+#if !(defined(CONFIG_SPL_BUILD) && defined(CONFIG_CPU_V7R))
+	if (ep->header == TI_EEPROM_HEADER_MAGIC) {
+		debug("%s: EEPROM has already been read\n", __func__);
+		return 0;
+	}
+#endif
+
+	ret = ti_i2c_eeprom_am6_get(bus_addr, dev_addr, ep,
+				    (char **)ep->mac_addr,
+				    AM6_EEPROM_HDR_NO_OF_MAC_ADDR,
+				    &ep->mac_addr_cnt);
+	return ret;
+}
+
 bool __maybe_unused board_ti_is(char *name_tag)
 {
 	struct ti_common_eeprom *ep = TI_EEPROM_DATA;
@@ -348,6 +534,25 @@
 	memset(mac_addr, 0, TI_EEPROM_HDR_ETH_ALEN);
 }
 
+void __maybe_unused
+board_ti_am6_get_eth_mac_addr(int index,
+			      u8 mac_addr[TI_EEPROM_HDR_ETH_ALEN])
+{
+	struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
+
+	if (ep->header == TI_DEAD_EEPROM_MAGIC)
+		goto fail;
+
+	if (index < 0 || index >= ep->mac_addr_cnt)
+		goto fail;
+
+	memcpy(mac_addr, ep->mac_addr[index], TI_EEPROM_HDR_ETH_ALEN);
+	return;
+
+fail:
+	memset(mac_addr, 0, TI_EEPROM_HDR_ETH_ALEN);
+}
+
 u64 __maybe_unused board_ti_get_emif1_size(void)
 {
 	struct ti_common_eeprom *ep = TI_EEPROM_DATA;
@@ -385,6 +590,34 @@
 	else
 		env_set("board_rev", unknown);
 
+	if (ep->serial)
+		env_set("board_serial", ep->serial);
+	else
+		env_set("board_serial", unknown);
+}
+
+void __maybe_unused set_board_info_env_am6(char *name)
+{
+	char *unknown = "unknown";
+	struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
+
+	if (name)
+		env_set("board_name", name);
+	else if (ep->name)
+		env_set("board_name", ep->name);
+	else
+		env_set("board_name", unknown);
+
+	if (ep->version)
+		env_set("board_rev", ep->version);
+	else
+		env_set("board_rev", unknown);
+
+	if (ep->software_revision)
+		env_set("board_software_revision", ep->software_revision);
+	else
+		env_set("board_software_revision", unknown);
+
 	if (ep->serial)
 		env_set("board_serial", ep->serial);
 	else
@@ -453,6 +686,19 @@
 	}
 }
 
+void board_ti_am6_set_ethaddr(int index, int count)
+{
+	u8 mac_addr[6];
+	int i;
+
+	for (i = 0; i < count; i++) {
+		board_ti_am6_get_eth_mac_addr(i, mac_addr);
+		if (is_valid_ethaddr(mac_addr))
+			eth_env_set_enetaddr_by_index("eth", i + index,
+						      mac_addr);
+	}
+}
+
 bool __maybe_unused board_ti_was_eeprom_read(void)
 {
 	struct ti_common_eeprom *ep = TI_EEPROM_DATA;
diff --git a/board/ti/common/board_detect.h b/board/ti/common/board_detect.h
index f8495a7..a45d896 100644
--- a/board/ti/common/board_detect.h
+++ b/board/ti/common/board_detect.h
@@ -43,6 +43,133 @@
 	char mac_addr[TI_EEPROM_HDR_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN];
 } __attribute__ ((__packed__));
 
+/* AM6x TI EVM EEPROM Definitions */
+#define TI_AM6_EEPROM_RECORD_BOARD_ID		0x01
+#define TI_AM6_EEPROM_RECORD_BOARD_INFO		0x10
+#define TI_AM6_EEPROM_RECORD_DDR_INFO		0x11
+#define TI_AM6_EEPROM_RECORD_DDR_SPD		0x12
+#define TI_AM6_EEPROM_RECORD_MAC_INFO		0x13
+#define TI_AM6_EEPROM_RECORD_END_LIST		0xFE
+
+/*
+ * Common header for AM6x TI EVM EEPROM records. Used to encapsulate the config
+ * EEPROM in its entirety as well as for individual records contained within.
+ */
+struct ti_am6_eeprom_record_header {
+	u8 id;
+	u16 len;
+} __attribute__ ((__packed__));
+
+/* AM6x TI EVM EEPROM board ID structure */
+struct ti_am6_eeprom_record_board_id {
+	u32 magic_number;
+	struct ti_am6_eeprom_record_header header;
+} __attribute__ ((__packed__));
+
+/* AM6x TI EVM EEPROM board info structure */
+#define AM6_EEPROM_HDR_NAME_LEN			16
+#define AM6_EEPROM_HDR_VERSION_LEN		2
+#define AM6_EEPROM_HDR_PROC_NR_LEN		4
+#define AM6_EEPROM_HDR_VARIANT_LEN		2
+#define AM6_EEPROM_HDR_PCB_REV_LEN		2
+#define AM6_EEPROM_HDR_SCH_BOM_REV_LEN		2
+#define AM6_EEPROM_HDR_SW_REV_LEN		2
+#define AM6_EEPROM_HDR_VID_LEN			2
+#define AM6_EEPROM_HDR_BLD_WK_LEN		2
+#define AM6_EEPROM_HDR_BLD_YR_LEN		2
+#define AM6_EEPROM_HDR_4P_NR_LEN		6
+#define AM6_EEPROM_HDR_SERIAL_LEN		4
+
+struct ti_am6_eeprom_record_board_info {
+	char name[AM6_EEPROM_HDR_NAME_LEN];
+	char version[AM6_EEPROM_HDR_VERSION_LEN];
+	char proc_number[AM6_EEPROM_HDR_PROC_NR_LEN];
+	char variant[AM6_EEPROM_HDR_VARIANT_LEN];
+	char pcb_revision[AM6_EEPROM_HDR_PCB_REV_LEN];
+	char schematic_bom_revision[AM6_EEPROM_HDR_SCH_BOM_REV_LEN];
+	char software_revision[AM6_EEPROM_HDR_SW_REV_LEN];
+	char vendor_id[AM6_EEPROM_HDR_VID_LEN];
+	char build_week[AM6_EEPROM_HDR_BLD_WK_LEN];
+	char build_year[AM6_EEPROM_HDR_BLD_YR_LEN];
+	char board_4p_number[AM6_EEPROM_HDR_4P_NR_LEN];
+	char serial[AM6_EEPROM_HDR_SERIAL_LEN];
+} __attribute__ ((__packed__));
+
+/* Memory location to keep a copy of the AM6 board info record */
+#define TI_AM6_EEPROM_BD_INFO_DATA ((struct ti_am6_eeprom_record_board_info *) \
+					     TI_SRAM_SCRATCH_BOARD_EEPROM_START)
+
+/* AM6x TI EVM EEPROM DDR info structure */
+#define TI_AM6_EEPROM_DDR_CTRL_INSTANCE_MASK		GENMASK(1, 0)
+#define TI_AM6_EEPROM_DDR_CTRL_INSTANCE_SHIFT		0
+#define TI_AM6_EEPROM_DDR_CTRL_SPD_DATA_LOC_MASK	GENMASK(3, 2)
+#define TI_AM6_EEPROM_DDR_CTRL_SPD_DATA_LOC_NA		(0 << 2)
+#define TI_AM6_EEPROM_DDR_CTRL_SPD_DATA_LOC_BOARDID	(2 << 2)
+#define TI_AM6_EEPROM_DDR_CTRL_SPD_DATA_LOC_I2C51	(3 << 2)
+#define TI_AM6_EEPROM_DDR_CTRL_MEM_TYPE_MASK		GENMASK(5, 4)
+#define TI_AM6_EEPROM_DDR_CTRL_MEM_TYPE_DDR3		(0 << 4)
+#define TI_AM6_EEPROM_DDR_CTRL_MEM_TYPE_DDR4		(1 << 4)
+#define TI_AM6_EEPROM_DDR_CTRL_MEM_TYPE_LPDDR4		(2 << 4)
+#define TI_AM6_EEPROM_DDR_CTRL_IF_DATA_WIDTH_MASK	GENMASK(7, 6)
+#define TI_AM6_EEPROM_DDR_CTRL_IF_DATA_WIDTH_16		(0 << 6)
+#define TI_AM6_EEPROM_DDR_CTRL_IF_DATA_WIDTH_32		(1 << 6)
+#define TI_AM6_EEPROM_DDR_CTRL_IF_DATA_WIDTH_64		(2 << 6)
+#define TI_AM6_EEPROM_DDR_CTRL_DEV_DATA_WIDTH_MASK	GENMASK(9, 8)
+#define TI_AM6_EEPROM_DDR_CTRL_DEV_DATA_WIDTH_8		(0 << 8)
+#define TI_AM6_EEPROM_DDR_CTRL_DEV_DATA_WIDTH_16	(1 << 8)
+#define TI_AM6_EEPROM_DDR_CTRL_DEV_DATA_WIDTH_32	(2 << 8)
+#define TI_AM6_EEPROM_DDR_CTRL_RANKS_2			BIT(10)
+#define TI_AM6_EEPROM_DDR_CTRL_DENS_MASK		GENMASK(13, 11)
+#define TI_AM6_EEPROM_DDR_CTRL_DENS_1GB			(0 << 11)
+#define TI_AM6_EEPROM_DDR_CTRL_DENS_2GB			(1 << 11)
+#define TI_AM6_EEPROM_DDR_CTRL_DENS_4GB			(2 << 11)
+#define TI_AM6_EEPROM_DDR_CTRL_DENS_8GB			(3 << 11)
+#define TI_AM6_EEPROM_DDR_CTRL_DENS_12GB		(4 << 11)
+#define TI_AM6_EEPROM_DDR_CTRL_DENS_16GB		(5 << 11)
+#define TI_AM6_EEPROM_DDR_CTRL_DENS_24GB		(6 << 11)
+#define TI_AM6_EEPROM_DDR_CTRL_DENS_32GB		(7 << 11)
+#define TI_AM6_EEPROM_DDR_CTRL_ECC			BIT(14)
+
+struct ti_am6_eeprom_record_ddr_info {
+	u16 ddr_control;
+} __attribute__ ((__packed__));
+
+/* AM6x TI EVM EEPROM DDR SPD structure */
+#define TI_AM6_EEPROM_DDR_SPD_INSTANCE_MASK		GENMASK(1, 0)
+#define TI_AM6_EEPROM_DDR_SPD_INSTANCE_SHIFT		0
+#define TI_AM6_EEPROM_DDR_SPD_MEM_TYPE_MASK		GENMASK(4, 3)
+#define TI_AM6_EEPROM_DDR_SPD_MEM_TYPE_DDR3		(0 << 3)
+#define TI_AM6_EEPROM_DDR_SPD_MEM_TYPE_DDR4		(1 << 3)
+#define TI_AM6_EEPROM_DDR_SPD_MEM_TYPE_LPDDR4		(2 << 3)
+#define TI_AM6_EEPROM_DDR_SPD_DATA_LEN			512
+
+struct ti_am6_eeprom_record_ddr_spd {
+	u16 spd_control;
+	u8 data[TI_AM6_EEPROM_DDR_SPD_DATA_LEN];
+} __attribute__ ((__packed__));
+
+/* AM6x TI EVM EEPROM MAC info structure */
+#define TI_AM6_EEPROM_MAC_INFO_INSTANCE_MASK		GENMASK(2, 0)
+#define TI_AM6_EEPROM_MAC_INFO_INSTANCE_SHIFT		0
+#define TI_AM6_EEPROM_MAC_ADDR_COUNT_MASK		GENMASK(7, 3)
+#define TI_AM6_EEPROM_MAC_ADDR_COUNT_SHIFT		3
+#define TI_AM6_EEPROM_MAC_ADDR_MAX_COUNT		32
+
+struct ti_am6_eeprom_record_mac_info {
+	u16 mac_control;
+	u8 mac_addr[TI_AM6_EEPROM_MAC_ADDR_MAX_COUNT][TI_EEPROM_HDR_ETH_ALEN];
+} __attribute__ ((__packed__));
+
+struct ti_am6_eeprom_record {
+	struct ti_am6_eeprom_record_header header;
+	union {
+		struct ti_am6_eeprom_record_board_info board_info;
+		struct ti_am6_eeprom_record_ddr_info ddr_info;
+		struct ti_am6_eeprom_record_ddr_spd ddr_spd;
+		struct ti_am6_eeprom_record_mac_info mac_info;
+	} data;
+} __attribute__ ((__packed__));
+
 /* DRA7 EEPROM MAGIC Header identifier */
 #define DRA7_EEPROM_HEADER_MAGIC	0xAA5533EE
 #define DRA7_EEPROM_HDR_NAME_LEN	16
@@ -99,7 +226,38 @@
 #define TI_EEPROM_DATA ((struct ti_common_eeprom *)\
 				TI_SRAM_SCRATCH_BOARD_EEPROM_START)
 
+/*
+ * Maximum number of Ethernet MAC addresses extracted from the AM6x on-board
+ * EEPROM during the initial probe and carried forward in SRAM.
+ */
+#define AM6_EEPROM_HDR_NO_OF_MAC_ADDR	8
+
 /**
+ * struct ti_am6_eeprom - Null terminated, usable EEPROM contents, as extracted
+ *	from the AM6 on-board EEPROM. Note that we only carry a subset of data
+ *	at this time to be considerate about memory consumption.
+ * @header:		Magic number for data validity indication
+ * @name:		NULL terminated name
+ * @version:		NULL terminated version
+ * @software_revision:	NULL terminated software revision
+ * @serial:		Board serial number
+ * @mac_addr_cnt:	Number of MAC addresses stored in this object
+ * @mac_addr:		MAC addresses
+ */
+struct ti_am6_eeprom {
+	u32 header;
+	char name[AM6_EEPROM_HDR_NAME_LEN + 1];
+	char version[AM6_EEPROM_HDR_VERSION_LEN + 1];
+	char software_revision[AM6_EEPROM_HDR_SW_REV_LEN + 1];
+	char serial[AM6_EEPROM_HDR_SERIAL_LEN + 1];
+	u8 mac_addr_cnt;
+	char mac_addr[AM6_EEPROM_HDR_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN];
+};
+
+#define TI_AM6_EEPROM_DATA ((struct ti_am6_eeprom *) \
+				TI_SRAM_SCRATCH_BOARD_EEPROM_START)
+
+/**
  * ti_i2c_eeprom_am_get() - Consolidated eeprom data collection for AM* TI EVMs
  * @bus_addr:	I2C bus address
  * @dev_addr:	I2C slave address
@@ -117,6 +275,33 @@
 int ti_i2c_eeprom_dra7_get(int bus_addr, int dev_addr);
 
 /**
+ * ti_i2c_eeprom_am6_get() - Consolidated eeprom data for AM6x TI EVMs and
+ *			     associated daughter cards, parsed into user-
+ *			     provided data structures
+ * @bus_addr:	I2C bus address
+ * @dev_addr:	I2C slave address
+ * @ep:		Pointer to structure receiving AM6-specific header data
+ * @mac_addr:	Pointer to memory receiving parsed MAC addresses. May be
+ *		NULL to skip MAC parsing.
+ * @mac_addr_max_cnt: Maximum number of MAC addresses that can be stored into
+ *		      mac_addr. May be NULL to skip MAC parsing.
+ * @mac_addr_cnt: Pointer to a location returning how many MAC addressed got
+ *		  actually parsed.
+ */
+int __maybe_unused ti_i2c_eeprom_am6_get(int bus_addr, int dev_addr,
+					 struct ti_am6_eeprom *ep,
+					 char **mac_addr,
+					 u8 mac_addr_max_cnt,
+					 u8 *mac_addr_cnt);
+
+/**
+ * ti_i2c_eeprom_am6_get_base() - Consolidated eeprom data for AM6x TI EVMs
+ * @bus_addr:	I2C bus address
+ * @dev_addr:	I2C slave address
+ */
+int __maybe_unused ti_i2c_eeprom_am6_get_base(int bus_addr, int dev_addr);
+
+/**
  * board_ti_is() - Board detection logic for TI EVMs
  * @name_tag:	Tag used in eeprom for the board
  *
@@ -193,6 +378,15 @@
 void set_board_info_env(char *name);
 
 /**
+ * set_board_info_env_am6() - Setup commonly used board information environment
+ *			      vars for AM6-type boards
+ * @name:	Name of the board
+ *
+ * If name is NULL, default_name is used.
+ */
+void set_board_info_env_am6(char *name);
+
+/**
  * board_ti_set_ethaddr- Sets the ethaddr environment from EEPROM
  * @index: The first eth<index>addr environment variable to set
  *
@@ -205,6 +399,18 @@
 void board_ti_set_ethaddr(int index);
 
 /**
+ * board_ti_am6_set_ethaddr- Sets the ethaddr environment from EEPROM
+ * @index: The first eth<index>addr environment variable to set
+ * @count: The number of MAC addresses to process
+ *
+ * EEPROM should be already read before calling this function. The EEPROM
+ * contains n dedicated MAC addresses. This function sets the ethaddr
+ * environment variable for all the available MAC addresses starting
+ * from eth<index>addr.
+ */
+void board_ti_am6_set_ethaddr(int index, int count);
+
+/**
  * board_ti_was_eeprom_read() - Check to see if the eeprom contents have been read
  *
  * This function is useful to determine if the eeprom has already been read and
diff --git a/board/vamrs/rock960_rk3399/MAINTAINERS b/board/vamrs/rock960_rk3399/MAINTAINERS
index 22b2db9..5ee5256 100644
--- a/board/vamrs/rock960_rk3399/MAINTAINERS
+++ b/board/vamrs/rock960_rk3399/MAINTAINERS
@@ -1,11 +1,11 @@
 ROCK960-RK3399
-M:      Manivannan Sadhasivam manivannan.sadhasivam@linaro.org
+M:      Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
 S:      Maintained
 F:      board/rockchip/rock960_rk3399
 F:      include/configs/rock960_rk3399.h
 F:      configs/rock960-rk3399_defconfig
 
 FICUS EE
-M:      Manivannan Sadhasivam manivannan.sadhasivam@linaro.org
+M:      Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
 S:      Maintained
 F:	configs/ficus-rk3399_defconfig
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 67284d8..175c6ad 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -408,6 +408,14 @@
 	  Save all environment variables into the compiled-in persistent
 	  storage.
 
+config CMD_ERASEENV
+	bool "eraseenv"
+	default n
+	depends on CMD_SAVEENV
+	help
+	  Erase environment variables from the compiled-in persistent
+	  storage.
+
 config CMD_ENV_EXISTS
 	bool "env exists"
 	default y
@@ -563,6 +571,13 @@
 	    base - print or set address offset
 	    loop - initialize loop on address range
 
+config CMD_RANDOM
+	bool "random"
+	default y
+	depends on CMD_MEMORY && (LIB_RAND || LIB_HW_RAND)
+	help
+	  random - fill memory with random data
+
 config CMD_MEMTEST
 	bool "memtest"
 	help
diff --git a/cmd/mdio.c b/cmd/mdio.c
index a6fa926..add6440 100644
--- a/cmd/mdio.c
+++ b/cmd/mdio.c
@@ -268,6 +268,11 @@
 		break;
 	}
 
+	if (!bus) {
+		puts("No MDIO bus found\n");
+		return CMD_RET_FAILURE;
+	}
+
 	if (op[0] == 'l') {
 		mdio_list_devices();
 
diff --git a/cmd/mem.c b/cmd/mem.c
index 392ed17..c6b8038 100644
--- a/cmd/mem.c
+++ b/cmd/mem.c
@@ -1082,6 +1082,49 @@
 
 #endif
 
+#ifdef CONFIG_CMD_RANDOM
+static int do_random(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	unsigned long addr, len;
+	unsigned long seed; // NOT INITIALIZED ON PURPOSE
+	unsigned int *buf, *start;
+	unsigned char *buf8;
+	unsigned int i;
+
+	if (argc < 3 || argc > 4) {
+		printf("usage: %s <addr> <len> [<seed>]\n", argv[0]);
+		return 0;
+	}
+
+	len = simple_strtoul(argv[2], NULL, 16);
+	addr = simple_strtoul(argv[1], NULL, 16);
+
+	if (argc == 4) {
+		seed = simple_strtoul(argv[3], NULL, 16);
+		if (seed == 0) {
+			printf("The seed cannot be 0. Using 0xDEADBEEF.\n");
+			seed = 0xDEADBEEF;
+		}
+	} else {
+		seed = get_timer(0) ^ rand();
+	}
+
+	srand(seed);
+	start = map_sysmem(addr, len);
+	buf = start;
+	for (i = 0; i < (len / 4); i++)
+		*buf++ = rand();
+
+	buf8 = (unsigned char *)buf;
+	for (i = 0; i < (len % 4); i++)
+		*buf8++ = rand() & 0xFF;
+
+	unmap_sysmem(start);
+	printf("%lu bytes filled with random data\n", len);
+	return 1;
+}
+#endif
+
 /**************************************************/
 U_BOOT_CMD(
 	md,	3,	1,	do_mem_md,
@@ -1250,3 +1293,12 @@
 	""
 );
 #endif
+
+#ifdef CONFIG_CMD_RANDOM
+U_BOOT_CMD(
+	random,	4,	0,	do_random,
+	"fill memory with random pattern",
+	"<addr> <len> [<seed>]\n"
+	"   - Fill 'len' bytes of memory starting at 'addr' with random data\n"
+);
+#endif
diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index 7e468ab..46b1e60 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -767,6 +767,20 @@
 	"save environment variables to persistent storage",
 	""
 );
+
+#if defined(CONFIG_CMD_ERASEENV)
+static int do_env_erase(cmd_tbl_t *cmdtp, int flag, int argc,
+			char * const argv[])
+{
+	return env_erase() ? 1 : 0;
+}
+
+U_BOOT_CMD(
+	eraseenv, 1, 0,	do_env_erase,
+	"erase environment variables from persistent storage",
+	""
+);
+#endif
 #endif
 #endif /* CONFIG_SPL_BUILD */
 
@@ -1316,6 +1330,9 @@
 #endif
 #if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
 	U_BOOT_CMD_MKENT(save, 1, 0, do_env_save, "", ""),
+#if defined(CONFIG_CMD_ERASEENV)
+	U_BOOT_CMD_MKENT(erase, 1, 0, do_env_erase, "", ""),
+#endif
 #endif
 	U_BOOT_CMD_MKENT(set, CONFIG_SYS_MAXARGS, 0, do_env_set, "", ""),
 #if defined(CONFIG_CMD_ENV_EXISTS)
@@ -1396,6 +1413,9 @@
 #endif
 #if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
 	"env save - save environment\n"
+#if defined(CONFIG_CMD_ERASEENV)
+	"env erase - erase environment\n"
+#endif
 #endif
 #if defined(CONFIG_CMD_NVEDIT_EFI)
 	"env set -e name [arg ...] - set UEFI variable; unset if 'arg' not specified\n"
diff --git a/common/command.c b/common/command.c
index e192bb2..db25bf5 100644
--- a/common/command.c
+++ b/common/command.c
@@ -356,8 +356,13 @@
 	int i, j, k, len, seplen, argc;
 	int cnt;
 	char last_char;
+#ifdef CONFIG_CMDLINE_PS_SUPPORT
+	const char *ps_prompt = env_get("PS1");
+#else
+	const char *ps_prompt = CONFIG_SYS_PROMPT;
+#endif
 
-	if (strcmp(prompt, CONFIG_SYS_PROMPT) != 0)
+	if (strcmp(prompt, ps_prompt) != 0)
 		return 0;	/* not in normal console */
 
 	cnt = strlen(buf);
diff --git a/common/fdt_support.c b/common/fdt_support.c
index f31e9b0..a23367b 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -1292,6 +1292,12 @@
 	return __of_translate_address(blob, node_offset, in_addr, "ranges");
 }
 
+u64 fdt_translate_dma_address(const void *blob, int node_offset,
+			      const fdt32_t *in_addr)
+{
+	return __of_translate_address(blob, node_offset, in_addr, "dma-ranges");
+}
+
 /**
  * fdt_node_offset_by_compat_reg: Find a node that matches compatiable and
  * who's reg property matches a physical cpu address
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 126931b..5978fb2 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -116,6 +116,9 @@
 config SPL_TEXT_BASE
 	hex "SPL Text Base"
 	default ISW_ENTRY_ADDR if AM43XX || AM33XX || OMAP54XX || ARCH_KEYSTONE
+	default 0x10060 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN9I
+	default 0x20060 if MACH_SUN50I_H6
+	default 0x00060 if ARCH_SUNXI
 	default 0x0
 	help
 	  The address in memory that SPL will be running from.
@@ -245,6 +248,16 @@
 	  info. Disabling this option could be useful to reduce SPL boot time
 	  (e.g. approx. 6 ms faster, when output on i.MX6 with 115200 baud).
 
+config SPL_EARLY_BSS
+	depends on ARM && !ARM64
+	bool "Allows initializing BSS early before entering board_init_f"
+	help
+	  On some platform we have sufficient memory available early on to
+	  allow setting up and using a basic BSS prior to entering
+	  board_init_f. Activating this option will also de-activate the
+	  clearing of BSS during the SPL relocation process, thus allowing
+	  to carry state from board_init_f to board_init_r by way of BSS.
+
 config SPL_DISPLAY_PRINT
 	bool "Display a board-specific message in SPL"
 	help
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 87ecf0b..969f777 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -340,6 +340,16 @@
 #endif
 }
 
+/*
+ * Weak default function to allow customizing SPL fit loading for load-only
+ * use cases by allowing to skip the parsing/processing of the FIT contents
+ * (so that this can be done separately in a more customized fashion)
+ */
+__weak bool spl_load_simple_fit_skip_processing(void)
+{
+	return false;
+}
+
 int spl_load_simple_fit(struct spl_image_info *spl_image,
 			struct spl_load_info *info, ulong sector, void *fit)
 {
@@ -389,6 +399,10 @@
 	if (count == 0)
 		return -EIO;
 
+	/* skip further processing if requested to enable load-only use cases */
+	if (spl_load_simple_fit_skip_processing())
+		return 0;
+
 	/* find the node holding the images information */
 	images = fdt_path_offset(fit, FIT_IMAGES_PATH);
 	if (images < 0) {
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index 324d91c..b361988 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -151,7 +151,8 @@
 
 #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
 static int mmc_load_image_raw_partition(struct spl_image_info *spl_image,
-					struct mmc *mmc, int partition)
+					struct mmc *mmc, int partition,
+					unsigned long sector)
 {
 	disk_partition_t info;
 	int err;
@@ -180,8 +181,7 @@
 	}
 
 #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
-	return mmc_load_image_raw_sector(spl_image, mmc,
-			info.start + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
+	return mmc_load_image_raw_sector(spl_image, mmc, info.start + sector);
 #else
 	return mmc_load_image_raw_sector(spl_image, mmc, info.start);
 #endif
@@ -234,7 +234,8 @@
 #endif
 
 #ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION
-static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc)
+static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc,
+			      const char *filename)
 {
 	int err = -ENOSYS;
 
@@ -248,7 +249,7 @@
 #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
 	err = spl_load_image_fat(spl_image, mmc_get_blk_desc(mmc),
 				 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
-				 CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
+				 filename);
 	if (!err)
 		return err;
 #endif
@@ -263,7 +264,7 @@
 #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
 	err = spl_load_image_ext(spl_image, mmc_get_blk_desc(mmc),
 				 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
-				 CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
+				 filename);
 	if (!err)
 		return err;
 #endif
@@ -276,7 +277,8 @@
 	return err;
 }
 #else
-static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc)
+static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc,
+			      const char *filename)
 {
 	return -ENOSYS;
 }
@@ -301,24 +303,31 @@
 }
 #endif
 
-int spl_mmc_load_image(struct spl_image_info *spl_image,
-		       struct spl_boot_device *bootdev)
+int spl_mmc_load(struct spl_image_info *spl_image,
+		 struct spl_boot_device *bootdev,
+		 const char *filename,
+		 int raw_part,
+		 unsigned long raw_sect)
 {
-	struct mmc *mmc = NULL;
+	static struct mmc *mmc;
 	u32 boot_mode;
 	int err = 0;
 	__maybe_unused int part;
 
-	err = spl_mmc_find_device(&mmc, bootdev->boot_device);
-	if (err)
-		return err;
+	/* Perform peripheral init only once */
+	if (!mmc) {
+		err = spl_mmc_find_device(&mmc, bootdev->boot_device);
+		if (err)
+			return err;
 
-	err = mmc_init(mmc);
-	if (err) {
+		err = mmc_init(mmc);
+		if (err) {
+			mmc = NULL;
 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
-		printf("spl: mmc init failed with error: %d\n", err);
+			printf("spl: mmc init failed with error: %d\n", err);
 #endif
-		return err;
+			return err;
+		}
 	}
 
 	boot_mode = spl_boot_mode(bootdev->boot_device);
@@ -356,17 +365,13 @@
 				return err;
 		}
 #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
-		err = spl_boot_partition(bootdev->boot_device);
-		if (!err)
-			return err;
-
-		err = mmc_load_image_raw_partition(spl_image, mmc, err);
+		err = mmc_load_image_raw_partition(spl_image, mmc, raw_part,
+						   raw_sect);
 		if (!err)
 			return err;
 #endif
 #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
-		err = mmc_load_image_raw_sector(spl_image, mmc,
-			CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
+		err = mmc_load_image_raw_sector(spl_image, mmc, raw_sect);
 		if (!err)
 			return err;
 #endif
@@ -374,7 +379,7 @@
 	case MMCSD_MODE_FS:
 		debug("spl: mmc boot mode: fs\n");
 
-		err = spl_mmc_do_fs_boot(spl_image, mmc);
+		err = spl_mmc_do_fs_boot(spl_image, mmc, filename);
 		if (!err)
 			return err;
 
@@ -388,6 +393,27 @@
 	return err;
 }
 
+int spl_mmc_load_image(struct spl_image_info *spl_image,
+		       struct spl_boot_device *bootdev)
+{
+	return spl_mmc_load(spl_image, bootdev,
+#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
+			    CONFIG_SPL_FS_LOAD_PAYLOAD_NAME,
+#else
+			    NULL,
+#endif
+#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION
+			    spl_boot_partition(bootdev->boot_device),
+#else
+			    0,
+#endif
+#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
+			    CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
+#else
+			    0);
+#endif
+}
+
 SPL_LOAD_IMAGE_METHOD("MMC1", 0, BOOT_DEVICE_MMC1, spl_mmc_load_image);
 SPL_LOAD_IMAGE_METHOD("MMC2", 0, BOOT_DEVICE_MMC2, spl_mmc_load_image);
 SPL_LOAD_IMAGE_METHOD("MMC2_2", 0, BOOT_DEVICE_MMC2_2, spl_mmc_load_image);
diff --git a/configs/A10-OLinuXino-Lime_defconfig b/configs/A10-OLinuXino-Lime_defconfig
index 61b38b6..a986bf8 100644
--- a/configs/A10-OLinuXino-Lime_defconfig
+++ b/configs/A10-OLinuXino-Lime_defconfig
@@ -11,7 +11,6 @@
 CONFIG_SATAPWR="PC3"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/A10s-OLinuXino-M_defconfig b/configs/A10s-OLinuXino-M_defconfig
index 7cc8b83..26c927f 100644
--- a/configs/A10s-OLinuXino-M_defconfig
+++ b/configs/A10s-OLinuXino-M_defconfig
@@ -9,7 +9,6 @@
 CONFIG_MMC_SUNXI_SLOT_EXTRA=1
 CONFIG_USB1_VBUS_PIN="PB10"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/A13-OLinuXinoM_defconfig b/configs/A13-OLinuXinoM_defconfig
index 1f8023e..1d48214 100644
--- a/configs/A13-OLinuXinoM_defconfig
+++ b/configs/A13-OLinuXinoM_defconfig
@@ -13,7 +13,6 @@
 CONFIG_VIDEO_LCD_POWER="PB10"
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/A13-OLinuXino_defconfig b/configs/A13-OLinuXino_defconfig
index 0010d09..63c8a2a 100644
--- a/configs/A13-OLinuXino_defconfig
+++ b/configs/A13-OLinuXino_defconfig
@@ -15,7 +15,6 @@
 CONFIG_VIDEO_LCD_POWER="AXP0-0"
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_CMD_DFU=y
 # CONFIG_CMD_FLASH is not set
diff --git a/configs/A20-OLinuXino-Lime2-eMMC_defconfig b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
index ed270f0..b00fcf3 100644
--- a/configs/A20-OLinuXino-Lime2-eMMC_defconfig
+++ b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
@@ -13,7 +13,6 @@
 CONFIG_SPL_SPI_SUNXI=y
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_CMD_DFU=y
 # CONFIG_CMD_FLASH is not set
diff --git a/configs/A20-OLinuXino-Lime2_defconfig b/configs/A20-OLinuXino-Lime2_defconfig
index ec702ce..db1c25c 100644
--- a/configs/A20-OLinuXino-Lime2_defconfig
+++ b/configs/A20-OLinuXino-Lime2_defconfig
@@ -11,7 +11,6 @@
 CONFIG_SATAPWR="PC3"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_CMD_DFU=y
 # CONFIG_CMD_FLASH is not set
diff --git a/configs/A20-OLinuXino-Lime_defconfig b/configs/A20-OLinuXino-Lime_defconfig
index 87badd6..e1e72ed 100644
--- a/configs/A20-OLinuXino-Lime_defconfig
+++ b/configs/A20-OLinuXino-Lime_defconfig
@@ -9,7 +9,6 @@
 CONFIG_SATAPWR="PC3"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/A20-OLinuXino_MICRO-eMMC_defconfig b/configs/A20-OLinuXino_MICRO-eMMC_defconfig
index 39d3d7f..62d878f 100644
--- a/configs/A20-OLinuXino_MICRO-eMMC_defconfig
+++ b/configs/A20-OLinuXino_MICRO-eMMC_defconfig
@@ -11,7 +11,6 @@
 CONFIG_SATAPWR="PB8"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/A20-OLinuXino_MICRO_defconfig b/configs/A20-OLinuXino_MICRO_defconfig
index 3967303..29efaf6 100644
--- a/configs/A20-OLinuXino_MICRO_defconfig
+++ b/configs/A20-OLinuXino_MICRO_defconfig
@@ -12,7 +12,6 @@
 CONFIG_SATAPWR="PB8"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/A20-Olimex-SOM-EVB_defconfig b/configs/A20-Olimex-SOM-EVB_defconfig
index bad6911..59dfdcc 100644
--- a/configs/A20-Olimex-SOM-EVB_defconfig
+++ b/configs/A20-Olimex-SOM-EVB_defconfig
@@ -13,7 +13,6 @@
 CONFIG_SATAPWR="PC3"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig b/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
index f343bb6..c41e435 100644
--- a/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
+++ b/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
@@ -13,7 +13,6 @@
 CONFIG_GMAC_TX_DELAY=4
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/A20-Olimex-SOM204-EVB_defconfig b/configs/A20-Olimex-SOM204-EVB_defconfig
index 8f9d350..38cc65b 100644
--- a/configs/A20-Olimex-SOM204-EVB_defconfig
+++ b/configs/A20-Olimex-SOM204-EVB_defconfig
@@ -12,7 +12,6 @@
 CONFIG_GMAC_TX_DELAY=4
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/A33-OLinuXino_defconfig b/configs/A33-OLinuXino_defconfig
index 893a5f2..4389856 100644
--- a/configs/A33-OLinuXino_defconfig
+++ b/configs/A33-OLinuXino_defconfig
@@ -16,7 +16,6 @@
 CONFIG_VIDEO_LCD_BL_EN="PB2"
 CONFIG_VIDEO_LCD_BL_PWM="PH0"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/Ainol_AW1_defconfig b/configs/Ainol_AW1_defconfig
index f2db707..c44050f 100644
--- a/configs/Ainol_AW1_defconfig
+++ b/configs/Ainol_AW1_defconfig
@@ -14,7 +14,6 @@
 CONFIG_VIDEO_LCD_BL_EN="PH7"
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Ampe_A76_defconfig b/configs/Ampe_A76_defconfig
index f1c3b2e..0a27747 100644
--- a/configs/Ampe_A76_defconfig
+++ b/configs/Ampe_A76_defconfig
@@ -15,7 +15,6 @@
 CONFIG_VIDEO_LCD_BL_EN="AXP0-1"
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Auxtek-T003_defconfig b/configs/Auxtek-T003_defconfig
index 5d55ccf..c0fb547 100644
--- a/configs/Auxtek-T003_defconfig
+++ b/configs/Auxtek-T003_defconfig
@@ -8,7 +8,6 @@
 CONFIG_USB1_VBUS_PIN="PB10"
 CONFIG_VIDEO_COMPOSITE=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Auxtek-T004_defconfig b/configs/Auxtek-T004_defconfig
index be2a94a..ae320b7 100644
--- a/configs/Auxtek-T004_defconfig
+++ b/configs/Auxtek-T004_defconfig
@@ -6,7 +6,6 @@
 CONFIG_DRAM_CLK=432
 CONFIG_USB1_VBUS_PIN="PG13"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Bananapi_M2_Ultra_defconfig b/configs/Bananapi_M2_Ultra_defconfig
index 278e54f..384820d 100644
--- a/configs/Bananapi_M2_Ultra_defconfig
+++ b/configs/Bananapi_M2_Ultra_defconfig
@@ -9,7 +9,6 @@
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-r40-bananapi-m2-ultra"
diff --git a/configs/Bananapi_defconfig b/configs/Bananapi_defconfig
index 5be660a..86cc3a2 100644
--- a/configs/Bananapi_defconfig
+++ b/configs/Bananapi_defconfig
@@ -9,7 +9,6 @@
 CONFIG_GMAC_TX_DELAY=3
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Bananapi_m2m_defconfig b/configs/Bananapi_m2m_defconfig
index 7daaaa0..87e2d34 100644
--- a/configs/Bananapi_m2m_defconfig
+++ b/configs/Bananapi_m2m_defconfig
@@ -10,7 +10,6 @@
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_USB0_ID_DET="PH8"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_PARTITION_UUIDS is not set
diff --git a/configs/Bananapro_defconfig b/configs/Bananapro_defconfig
index 5de48ae..8636eab 100644
--- a/configs/Bananapro_defconfig
+++ b/configs/Bananapro_defconfig
@@ -11,7 +11,6 @@
 CONFIG_GMAC_TX_DELAY=3
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/CHIP_defconfig b/configs/CHIP_defconfig
index f94de1f..95c564c 100644
--- a/configs/CHIP_defconfig
+++ b/configs/CHIP_defconfig
@@ -6,7 +6,6 @@
 CONFIG_DRAM_TIMINGS_DDR3_800E_1066G_1333J=y
 CONFIG_USB0_VBUS_PIN="PB10"
 CONFIG_VIDEO_COMPOSITE=y
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_CMD_DFU=y
 CONFIG_CMD_USB_MASS_STORAGE=y
diff --git a/configs/CHIP_pro_defconfig b/configs/CHIP_pro_defconfig
index 5fd7998..6cd500f 100644
--- a/configs/CHIP_pro_defconfig
+++ b/configs/CHIP_pro_defconfig
@@ -5,7 +5,6 @@
 CONFIG_MACH_SUN5I=y
 CONFIG_DRAM_TIMINGS_DDR3_800E_1066G_1333J=y
 CONFIG_USB0_VBUS_PIN="PB10"
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_MTDPARTS=y
diff --git a/configs/CSQ_CS908_defconfig b/configs/CSQ_CS908_defconfig
index d5e9ae5..d1ba5c8 100644
--- a/configs/CSQ_CS908_defconfig
+++ b/configs/CSQ_CS908_defconfig
@@ -7,7 +7,6 @@
 CONFIG_USB1_VBUS_PIN=""
 CONFIG_USB2_VBUS_PIN=""
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/Chuwi_V7_CW0825_defconfig b/configs/Chuwi_V7_CW0825_defconfig
index efe45c1..acd931c 100644
--- a/configs/Chuwi_V7_CW0825_defconfig
+++ b/configs/Chuwi_V7_CW0825_defconfig
@@ -14,7 +14,6 @@
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 CONFIG_VIDEO_LCD_PANEL_HITACHI_TX18D42VM=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Colombus_defconfig b/configs/Colombus_defconfig
index 64c7f81..5e52388 100644
--- a/configs/Colombus_defconfig
+++ b/configs/Colombus_defconfig
@@ -17,7 +17,6 @@
 CONFIG_VIDEO_LCD_PANEL_I2C_SCL="PA24"
 CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/Cubieboard2_defconfig b/configs/Cubieboard2_defconfig
index c9bc1a8..d1ff8fd 100644
--- a/configs/Cubieboard2_defconfig
+++ b/configs/Cubieboard2_defconfig
@@ -8,7 +8,6 @@
 CONFIG_SATAPWR="PB8"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Cubieboard4_defconfig b/configs/Cubieboard4_defconfig
index 2abbd33..0134820 100644
--- a/configs/Cubieboard4_defconfig
+++ b/configs/Cubieboard4_defconfig
@@ -12,7 +12,6 @@
 CONFIG_USB1_VBUS_PIN="PH14"
 CONFIG_USB3_VBUS_PIN="PH15"
 CONFIG_AXP_GPIO=y
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/Cubieboard_defconfig b/configs/Cubieboard_defconfig
index 36b1a89..1ff7270 100644
--- a/configs/Cubieboard_defconfig
+++ b/configs/Cubieboard_defconfig
@@ -8,7 +8,6 @@
 CONFIG_SATAPWR="PB8"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Cubietruck_defconfig b/configs/Cubietruck_defconfig
index 6088549..ed8fbe9 100644
--- a/configs/Cubietruck_defconfig
+++ b/configs/Cubietruck_defconfig
@@ -13,7 +13,6 @@
 CONFIG_GMAC_TX_DELAY=1
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_CMD_DFU=y
 # CONFIG_CMD_FLASH is not set
diff --git a/configs/Cubietruck_plus_defconfig b/configs/Cubietruck_plus_defconfig
index ef6a9d5..0573c1f 100644
--- a/configs/Cubietruck_plus_defconfig
+++ b/configs/Cubietruck_plus_defconfig
@@ -16,7 +16,6 @@
 CONFIG_AXP_GPIO=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_CONSOLE_MUX=y
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/Empire_electronix_d709_defconfig b/configs/Empire_electronix_d709_defconfig
index 07f32e2..f5dd96d 100644
--- a/configs/Empire_electronix_d709_defconfig
+++ b/configs/Empire_electronix_d709_defconfig
@@ -16,7 +16,6 @@
 CONFIG_VIDEO_LCD_BL_EN="AXP0-1"
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Empire_electronix_m712_defconfig b/configs/Empire_electronix_m712_defconfig
index 82a4a06..b8c3c56 100644
--- a/configs/Empire_electronix_m712_defconfig
+++ b/configs/Empire_electronix_m712_defconfig
@@ -15,7 +15,6 @@
 CONFIG_VIDEO_LCD_BL_EN="AXP0-1"
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Hummingbird_A31_defconfig b/configs/Hummingbird_A31_defconfig
index 6d8a9a3..f7a7b73 100644
--- a/configs/Hummingbird_A31_defconfig
+++ b/configs/Hummingbird_A31_defconfig
@@ -9,7 +9,6 @@
 CONFIG_VIDEO_VGA_VIA_LCD=y
 CONFIG_VIDEO_VGA_EXTERNAL_DAC_EN="PH25"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/Hyundai_A7HD_defconfig b/configs/Hyundai_A7HD_defconfig
index 89ae241..2b1b1cc 100644
--- a/configs/Hyundai_A7HD_defconfig
+++ b/configs/Hyundai_A7HD_defconfig
@@ -15,7 +15,6 @@
 # CONFIG_VIDEO_LCD_BL_PWM_ACTIVE_LOW is not set
 CONFIG_VIDEO_LCD_PANEL_LVDS=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Itead_Ibox_A20_defconfig b/configs/Itead_Ibox_A20_defconfig
index a5c7d62..f44fc9e 100644
--- a/configs/Itead_Ibox_A20_defconfig
+++ b/configs/Itead_Ibox_A20_defconfig
@@ -8,7 +8,6 @@
 CONFIG_SATAPWR="PB8"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Lamobo_R1_defconfig b/configs/Lamobo_R1_defconfig
index da8a835..0ce8c11 100644
--- a/configs/Lamobo_R1_defconfig
+++ b/configs/Lamobo_R1_defconfig
@@ -10,7 +10,6 @@
 CONFIG_GMAC_TX_DELAY=4
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/LicheePi_Zero_defconfig b/configs/LicheePi_Zero_defconfig
index e71f06b..760cb1b 100644
--- a/configs/LicheePi_Zero_defconfig
+++ b/configs/LicheePi_Zero_defconfig
@@ -4,7 +4,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_V3S=y
 CONFIG_DRAM_CLK=360
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/Linksprite_pcDuino3_Nano_defconfig b/configs/Linksprite_pcDuino3_Nano_defconfig
index 5fce2b1..3277461 100644
--- a/configs/Linksprite_pcDuino3_Nano_defconfig
+++ b/configs/Linksprite_pcDuino3_Nano_defconfig
@@ -10,7 +10,6 @@
 CONFIG_GMAC_TX_DELAY=3
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Linksprite_pcDuino3_defconfig b/configs/Linksprite_pcDuino3_defconfig
index 1208237..ce07a8c 100644
--- a/configs/Linksprite_pcDuino3_defconfig
+++ b/configs/Linksprite_pcDuino3_defconfig
@@ -8,7 +8,6 @@
 CONFIG_SATAPWR="PH2"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Linksprite_pcDuino_defconfig b/configs/Linksprite_pcDuino_defconfig
index 7b73413..9685757 100644
--- a/configs/Linksprite_pcDuino_defconfig
+++ b/configs/Linksprite_pcDuino_defconfig
@@ -6,7 +6,6 @@
 CONFIG_USB1_VBUS_PIN=""
 CONFIG_USB2_VBUS_PIN=""
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/MK808C_defconfig b/configs/MK808C_defconfig
index 23da4da..2da7a85 100644
--- a/configs/MK808C_defconfig
+++ b/configs/MK808C_defconfig
@@ -5,7 +5,6 @@
 CONFIG_MACH_SUN7I=y
 CONFIG_DRAM_CLK=384
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/MSI_Primo73_defconfig b/configs/MSI_Primo73_defconfig
index e48e1a1..746e568 100644
--- a/configs/MSI_Primo73_defconfig
+++ b/configs/MSI_Primo73_defconfig
@@ -10,7 +10,6 @@
 CONFIG_VIDEO_LCD_BL_EN="PH7"
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/MSI_Primo81_defconfig b/configs/MSI_Primo81_defconfig
index 1396784..5eaf24a 100644
--- a/configs/MSI_Primo81_defconfig
+++ b/configs/MSI_Primo81_defconfig
@@ -13,7 +13,6 @@
 CONFIG_VIDEO_LCD_BL_PWM="PH13"
 CONFIG_VIDEO_LCD_PANEL_MIPI_4_LANE_513_MBPS_VIA_SSD2828=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/Marsboard_A10_defconfig b/configs/Marsboard_A10_defconfig
index b0d0c35..2666f1b 100644
--- a/configs/Marsboard_A10_defconfig
+++ b/configs/Marsboard_A10_defconfig
@@ -5,7 +5,6 @@
 CONFIG_MACH_SUN4I=y
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/Mele_A1000G_quad_defconfig b/configs/Mele_A1000G_quad_defconfig
index d321e94..4d900c1 100644
--- a/configs/Mele_A1000G_quad_defconfig
+++ b/configs/Mele_A1000G_quad_defconfig
@@ -8,7 +8,6 @@
 CONFIG_USB1_VBUS_PIN="PC27"
 CONFIG_USB2_VBUS_PIN=""
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/Mele_A1000_defconfig b/configs/Mele_A1000_defconfig
index 672f4fe..fe6c0fa 100644
--- a/configs/Mele_A1000_defconfig
+++ b/configs/Mele_A1000_defconfig
@@ -8,7 +8,6 @@
 CONFIG_VIDEO_COMPOSITE=y
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Mele_I7_defconfig b/configs/Mele_I7_defconfig
index e1e628d..10c151f 100644
--- a/configs/Mele_I7_defconfig
+++ b/configs/Mele_I7_defconfig
@@ -7,7 +7,6 @@
 CONFIG_USB1_VBUS_PIN="PC27"
 CONFIG_USB2_VBUS_PIN=""
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/Mele_M3_defconfig b/configs/Mele_M3_defconfig
index c400f13..b3b38a5 100644
--- a/configs/Mele_M3_defconfig
+++ b/configs/Mele_M3_defconfig
@@ -9,7 +9,6 @@
 CONFIG_VIDEO_VGA=y
 CONFIG_VIDEO_COMPOSITE=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Mele_M5_defconfig b/configs/Mele_M5_defconfig
index f565dbc..57b25ba 100644
--- a/configs/Mele_M5_defconfig
+++ b/configs/Mele_M5_defconfig
@@ -9,7 +9,6 @@
 CONFIG_VIDEO_COMPOSITE=y
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Mele_M9_defconfig b/configs/Mele_M9_defconfig
index 7202bfd..70facee 100644
--- a/configs/Mele_M9_defconfig
+++ b/configs/Mele_M9_defconfig
@@ -7,7 +7,6 @@
 CONFIG_USB1_VBUS_PIN="PC27"
 CONFIG_USB2_VBUS_PIN=""
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/Merrii_A80_Optimus_defconfig b/configs/Merrii_A80_Optimus_defconfig
index cc09533..288b5e6 100644
--- a/configs/Merrii_A80_Optimus_defconfig
+++ b/configs/Merrii_A80_Optimus_defconfig
@@ -12,7 +12,6 @@
 CONFIG_USB1_VBUS_PIN="PH4"
 CONFIG_USB3_VBUS_PIN="PH5"
 CONFIG_AXP_GPIO=y
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/Mini-X_defconfig b/configs/Mini-X_defconfig
index 03fa81e..6000e39 100644
--- a/configs/Mini-X_defconfig
+++ b/configs/Mini-X_defconfig
@@ -6,7 +6,6 @@
 CONFIG_USB0_VBUS_PIN="PB9"
 CONFIG_VIDEO_COMPOSITE=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Nintendo_NES_Classic_Edition_defconfig b/configs/Nintendo_NES_Classic_Edition_defconfig
index 099a2bd..d0a7889 100644
--- a/configs/Nintendo_NES_Classic_Edition_defconfig
+++ b/configs/Nintendo_NES_Classic_Edition_defconfig
@@ -9,7 +9,6 @@
 CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
 CONFIG_AXP_GPIO=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_MTDPARTS=y
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Orangepi_defconfig b/configs/Orangepi_defconfig
index b1a7cbd..2a7bfff 100644
--- a/configs/Orangepi_defconfig
+++ b/configs/Orangepi_defconfig
@@ -12,7 +12,6 @@
 CONFIG_GMAC_TX_DELAY=3
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Orangepi_mini_defconfig b/configs/Orangepi_mini_defconfig
index 35f1b34..9f41fab 100644
--- a/configs/Orangepi_mini_defconfig
+++ b/configs/Orangepi_mini_defconfig
@@ -14,7 +14,6 @@
 CONFIG_GMAC_TX_DELAY=3
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Sinlinx_SinA31s_defconfig b/configs/Sinlinx_SinA31s_defconfig
index 31aa768..0714430 100644
--- a/configs/Sinlinx_SinA31s_defconfig
+++ b/configs/Sinlinx_SinA31s_defconfig
@@ -11,7 +11,6 @@
 CONFIG_USB1_VBUS_PIN=""
 CONFIG_USB2_VBUS_PIN=""
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/Sinlinx_SinA33_defconfig b/configs/Sinlinx_SinA33_defconfig
index 586be35..978e856 100644
--- a/configs/Sinlinx_SinA33_defconfig
+++ b/configs/Sinlinx_SinA33_defconfig
@@ -13,7 +13,6 @@
 CONFIG_VIDEO_LCD_BL_EN="PH6"
 CONFIG_VIDEO_LCD_BL_PWM="PH0"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_CMD_DFU=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Sinovoip_BPI_M2_defconfig b/configs/Sinovoip_BPI_M2_defconfig
index d1ee98b..46ef97d 100644
--- a/configs/Sinovoip_BPI_M2_defconfig
+++ b/configs/Sinovoip_BPI_M2_defconfig
@@ -7,7 +7,6 @@
 CONFIG_USB1_VBUS_PIN=""
 CONFIG_USB2_VBUS_PIN=""
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/Sinovoip_BPI_M3_defconfig b/configs/Sinovoip_BPI_M3_defconfig
index 5174e28..914fc9d 100644
--- a/configs/Sinovoip_BPI_M3_defconfig
+++ b/configs/Sinovoip_BPI_M3_defconfig
@@ -17,7 +17,6 @@
 CONFIG_SATAPWR="PD25"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_CONSOLE_MUX=y
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/Sunchip_CX-A99_defconfig b/configs/Sunchip_CX-A99_defconfig
index 8a9a072..c884d8f 100644
--- a/configs/Sunchip_CX-A99_defconfig
+++ b/configs/Sunchip_CX-A99_defconfig
@@ -12,7 +12,6 @@
 CONFIG_USB1_VBUS_PIN="PL7"
 CONFIG_USB3_VBUS_PIN="PL8"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/UCP1020_SPIFLASH_defconfig b/configs/UCP1020_SPIFLASH_defconfig
deleted file mode 100644
index a2d7e66..0000000
--- a/configs/UCP1020_SPIFLASH_defconfig
+++ /dev/null
@@ -1,60 +0,0 @@
-CONFIG_PPC=y
-CONFIG_SYS_TEXT_BASE=0x11000000
-CONFIG_MPC85xx=y
-CONFIG_TARGET_UCP1020=y
-CONFIG_TARGET_UCP1020_SPIFLASH=y
-CONFIG_FIT=y
-CONFIG_FIT_VERBOSE=y
-CONFIG_OF_BOARD_SETUP=y
-CONFIG_OF_STDOUT_VIA_ALIAS=y
-# CONFIG_MISC_INIT_R is not set
-CONFIG_BOARD_EARLY_INIT_F=y
-CONFIG_BOARD_EARLY_INIT_R=y
-CONFIG_LAST_STAGE_INIT=y
-CONFIG_HUSH_PARSER=y
-# CONFIG_AUTO_COMPLETE is not set
-CONFIG_AUTOBOOT_KEYED=y
-CONFIG_AUTOBOOT_PROMPT="Autobooting in %d seconds, press \"<Esc>\" to stop\n"
-CONFIG_AUTOBOOT_STOP_STR="\x1b"
-CONFIG_CMD_IMLS=y
-CONFIG_CMD_GPIO=y
-CONFIG_CMD_I2C=y
-CONFIG_CMD_MMC=y
-# CONFIG_CMD_NAND is not set
-CONFIG_CMD_MMC_SPI=y
-CONFIG_CMD_SF=y
-CONFIG_CMD_SPI=y
-CONFIG_CMD_USB=y
-CONFIG_CMD_DHCP=y
-CONFIG_CMD_MII=y
-CONFIG_CMD_PING=y
-CONFIG_CMD_DATE=y
-CONFIG_MP=y
-# CONFIG_CMD_HASH is not set
-CONFIG_CMD_CRAMFS=y
-CONFIG_CMD_EXT2=y
-CONFIG_CMD_FAT=y
-CONFIG_ENV_IS_IN_SPI_FLASH=y
-CONFIG_FSL_ESDHC=y
-CONFIG_MTD_NOR_FLASH=y
-CONFIG_FLASH_CFI_DRIVER=y
-CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
-CONFIG_SYS_FLASH_CFI=y
-CONFIG_SPI_FLASH=y
-CONFIG_SF_DEFAULT_MODE=0
-CONFIG_SF_DEFAULT_SPEED=10000000
-CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_SPI_FLASH_SST=y
-CONFIG_SPI_FLASH_WINBOND=y
-CONFIG_PHY_MARVELL=y
-CONFIG_PHY_GIGE=y
-CONFIG_E1000=y
-CONFIG_MII=y
-CONFIG_TSEC_ENET=y
-CONFIG_SYS_NS16550=y
-CONFIG_SPI=y
-CONFIG_FSL_ESPI=y
-CONFIG_USB=y
-CONFIG_USB_STORAGE=y
-CONFIG_FS_CRAMFS=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/UTOO_P66_defconfig b/configs/UTOO_P66_defconfig
index 78cd62c..5be41f1 100644
--- a/configs/UTOO_P66_defconfig
+++ b/configs/UTOO_P66_defconfig
@@ -20,7 +20,6 @@
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 CONFIG_VIDEO_LCD_TL059WV5C0=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Wexler_TAB7200_defconfig b/configs/Wexler_TAB7200_defconfig
index f75606e..b721118 100644
--- a/configs/Wexler_TAB7200_defconfig
+++ b/configs/Wexler_TAB7200_defconfig
@@ -13,7 +13,6 @@
 CONFIG_VIDEO_LCD_BL_EN="PH7"
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Wits_Pro_A20_DKT_defconfig b/configs/Wits_Pro_A20_DKT_defconfig
index 4e37650..954a6b7 100644
--- a/configs/Wits_Pro_A20_DKT_defconfig
+++ b/configs/Wits_Pro_A20_DKT_defconfig
@@ -12,7 +12,6 @@
 CONFIG_VIDEO_LCD_PANEL_LVDS=y
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Wobo_i5_defconfig b/configs/Wobo_i5_defconfig
index 92d851f..3a2c287 100644
--- a/configs/Wobo_i5_defconfig
+++ b/configs/Wobo_i5_defconfig
@@ -7,7 +7,6 @@
 CONFIG_MMC0_CD_PIN="PB3"
 CONFIG_USB1_VBUS_PIN="PG12"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Yones_Toptech_BD1078_defconfig b/configs/Yones_Toptech_BD1078_defconfig
index 376fc2f..9a4743f 100644
--- a/configs/Yones_Toptech_BD1078_defconfig
+++ b/configs/Yones_Toptech_BD1078_defconfig
@@ -19,7 +19,6 @@
 # CONFIG_VIDEO_LCD_BL_PWM_ACTIVE_LOW is not set
 CONFIG_VIDEO_LCD_PANEL_LVDS=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/Yones_Toptech_BS1078_V2_defconfig b/configs/Yones_Toptech_BS1078_V2_defconfig
index b8c923e..cd2b674 100644
--- a/configs/Yones_Toptech_BS1078_V2_defconfig
+++ b/configs/Yones_Toptech_BS1078_V2_defconfig
@@ -16,7 +16,6 @@
 CONFIG_VIDEO_LCD_BL_PWM="PH13"
 CONFIG_VIDEO_LCD_PANEL_LVDS=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/a64-olinuxino_defconfig b/configs/a64-olinuxino_defconfig
index afc8cff..65430c3 100644
--- a/configs/a64-olinuxino_defconfig
+++ b/configs/a64-olinuxino_defconfig
@@ -6,7 +6,6 @@
 CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/am335x_boneblack_vboot_defconfig b/configs/am335x_boneblack_vboot_defconfig
index ffe013f..9ccbd68 100644
--- a/configs/am335x_boneblack_vboot_defconfig
+++ b/configs/am335x_boneblack_vboot_defconfig
@@ -1,4 +1,8 @@
 CONFIG_ARM=y
+# CONFIG_SPL_USE_ARCH_MEMCPY is not set
+# CONFIG_TPL_USE_ARCH_MEMCPY is not set
+# CONFIG_SPL_USE_ARCH_MEMSET is not set
+# CONFIG_TPL_USE_ARCH_MEMSET is not set
 CONFIG_ARCH_OMAP2PLUS=y
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_AM33XX=y
diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig
index b940af3..9d4c6a2 100644
--- a/configs/am65x_evm_a53_defconfig
+++ b/configs/am65x_evm_a53_defconfig
@@ -2,7 +2,7 @@
 CONFIG_ARCH_K3=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_SOC_K3_AM6=y
 CONFIG_TARGET_AM654_A53_EVM=y
 CONFIG_SPL_MMC_SUPPORT=y
@@ -16,12 +16,14 @@
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_OF_BOARD_SETUP=y
-CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run run_kern"
+CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern"
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_TEXT_BASE=0x80080000
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SEPARATE_BSS=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1400
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_DM_MAILBOX=y
 CONFIG_SPL_DM_RESET=y
@@ -30,35 +32,41 @@
 CONFIG_SPL_YMODEM_SUPPORT=y
 CONFIG_CMD_ASKENV=y
 # CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPT=y
+CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_REMOTEPROC=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_TIME=y
 # CONFIG_ISO_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
 CONFIG_OF_CONTROL=y
 CONFIG_SPL_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="k3-am654-base-board"
 CONFIG_SPL_MULTI_DTB_FIT=y
 CONFIG_SPL_MULTI_DTB_FIT_NO_COMPRESSION=y
-CONFIG_ENV_IS_IN_FAT=y
-CONFIG_ENV_FAT_INTERFACE="mmc"
-CONFIG_ENV_FAT_DEVICE_AND_PART="1:1"
+CONFIG_ENV_IS_IN_MMC=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_DM=y
 CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
 CONFIG_CLK=y
 CONFIG_SPL_CLK=y
 CONFIG_CLK_TI_SCI=y
 CONFIG_DMA_CHANNELS=y
 CONFIG_TI_K3_NAVSS_UDMA=y
 CONFIG_TI_SCI_PROTOCOL=y
+CONFIG_DM_GPIO=y
+CONFIG_DM_PCA953X=y
+CONFIG_DM_I2C=y
+CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
+CONFIG_SYS_I2C_OMAP24XX=y
 CONFIG_DM_MAILBOX=y
 CONFIG_K3_SEC_PROXY=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_K3_ARASAN=y
+CONFIG_MMC_SDHCI_AM654=y
 CONFIG_PHY_TI=y
 CONFIG_PHY_FIXED=y
 CONFIG_DM_ETH=y
@@ -80,3 +88,5 @@
 CONFIG_SYSRESET=y
 CONFIG_SPL_SYSRESET=y
 CONFIG_SYSRESET_TI_SCI=y
+CONFIG_FAT_WRITE=y
+CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/am65x_evm_r5_defconfig b/configs/am65x_evm_r5_defconfig
index 3814872..7e81a98 100644
--- a/configs/am65x_evm_r5_defconfig
+++ b/configs/am65x_evm_r5_defconfig
@@ -3,7 +3,7 @@
 CONFIG_SPL_GPIO_SUPPORT=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SYS_MALLOC_F_LEN=0x55000
 CONFIG_SOC_K3_AM6=y
 CONFIG_TARGET_AM654_R5_EVM=y
 CONFIG_SPL_MMC_SUPPORT=y
@@ -18,9 +18,11 @@
 CONFIG_USE_BOOTCOMMAND=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_TEXT_BASE=0x41c00000
-CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SEPARATE_BSS=y
+CONFIG_SPL_EARLY_BSS=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x400
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_DM_MAILBOX=y
 CONFIG_SPL_DM_RESET=y
@@ -35,6 +37,7 @@
 CONFIG_CMD_ASKENV=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_GPT=y
+CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_REMOTEPROC=y
 # CONFIG_CMD_SETEXPR is not set
@@ -51,6 +54,8 @@
 CONFIG_DM=y
 CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
 CONFIG_SPL_OF_TRANSLATE=y
 CONFIG_CLK=y
 CONFIG_SPL_CLK=y
@@ -58,12 +63,15 @@
 CONFIG_TI_SCI_PROTOCOL=y
 CONFIG_DM_GPIO=y
 CONFIG_DA8XX_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
+CONFIG_SYS_I2C_OMAP24XX=y
 CONFIG_DM_MAILBOX=y
 CONFIG_K3_SEC_PROXY=y
 CONFIG_MISC=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_K3_ARASAN=y
+CONFIG_MMC_SDHCI_AM654=y
 CONFIG_PINCTRL=y
 # CONFIG_PINCTRL_GENERIC is not set
 CONFIG_SPL_PINCTRL=y
@@ -88,3 +96,4 @@
 CONFIG_TIMER=y
 CONFIG_SPL_TIMER=y
 CONFIG_OMAP_TIMER=y
+CONFIG_FS_FAT_MAX_CLUSTSIZE=16384
diff --git a/configs/am65x_hs_evm_a53_defconfig b/configs/am65x_hs_evm_a53_defconfig
index 9c55cd3..56052f7 100644
--- a/configs/am65x_hs_evm_a53_defconfig
+++ b/configs/am65x_hs_evm_a53_defconfig
@@ -3,7 +3,7 @@
 CONFIG_TI_SECURE_DEVICE=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_SOC_K3_AM6=y
 CONFIG_TARGET_AM654_A53_EVM=y
 CONFIG_SPL_MMC_SUPPORT=y
@@ -19,12 +19,14 @@
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y
 CONFIG_OF_BOARD_SETUP=y
-CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run run_kern"
+CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern"
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_TEXT_BASE=0x80080000
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SEPARATE_BSS=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1400
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_DM_MAILBOX=y
 CONFIG_SPL_DM_RESET=y
@@ -33,6 +35,7 @@
 CONFIG_SPL_YMODEM_SUPPORT=y
 CONFIG_CMD_ASKENV=y
 # CONFIG_CMD_FLASH is not set
+CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_REMOTEPROC=y
 # CONFIG_CMD_SETEXPR is not set
@@ -56,6 +59,11 @@
 CONFIG_DMA_CHANNELS=y
 CONFIG_TI_K3_NAVSS_UDMA=y
 CONFIG_TI_SCI_PROTOCOL=y
+CONFIG_DM_GPIO=y
+CONFIG_DM_PCA953X=y
+CONFIG_DM_I2C=y
+CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
+CONFIG_SYS_I2C_OMAP24XX=y
 CONFIG_DM_MAILBOX=y
 CONFIG_K3_SEC_PROXY=y
 CONFIG_DM_MMC=y
@@ -77,3 +85,4 @@
 CONFIG_SYSRESET=y
 CONFIG_SPL_SYSRESET=y
 CONFIG_SYSRESET_TI_SCI=y
+CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/am65x_hs_evm_r5_defconfig b/configs/am65x_hs_evm_r5_defconfig
index 0b12f15..d378d1e 100644
--- a/configs/am65x_hs_evm_r5_defconfig
+++ b/configs/am65x_hs_evm_r5_defconfig
@@ -4,7 +4,7 @@
 CONFIG_SPL_GPIO_SUPPORT=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SYS_MALLOC_F_LEN=0x55000
 CONFIG_SOC_K3_AM6=y
 CONFIG_TARGET_AM654_R5_EVM=y
 CONFIG_SPL_MMC_SUPPORT=y
@@ -20,9 +20,11 @@
 CONFIG_USE_BOOTCOMMAND=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_TEXT_BASE=0x41c00000
-CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SEPARATE_BSS=y
+CONFIG_SPL_EARLY_BSS=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x400
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_DM_MAILBOX=y
 CONFIG_SPL_DM_RESET=y
@@ -37,6 +39,7 @@
 CONFIG_CMD_ASKENV=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_GPT=y
+CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_REMOTEPROC=y
 # CONFIG_CMD_SETEXPR is not set
@@ -60,6 +63,9 @@
 CONFIG_TI_SCI_PROTOCOL=y
 CONFIG_DM_GPIO=y
 CONFIG_DA8XX_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
+CONFIG_SYS_I2C_OMAP24XX=y
 CONFIG_DM_MAILBOX=y
 CONFIG_K3_SEC_PROXY=y
 CONFIG_MISC=y
@@ -90,3 +96,4 @@
 CONFIG_TIMER=y
 CONFIG_SPL_TIMER=y
 CONFIG_OMAP_TIMER=y
+CONFIG_FS_FAT_MAX_CLUSTSIZE=16384
diff --git a/configs/amarula_a64_relic_defconfig b/configs/amarula_a64_relic_defconfig
index 4d546af..d41eb34 100644
--- a/configs/amarula_a64_relic_defconfig
+++ b/configs/amarula_a64_relic_defconfig
@@ -7,7 +7,6 @@
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_VIDEO_DE2 is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/ba10_tv_box_defconfig b/configs/ba10_tv_box_defconfig
index 49aa22c..dc47292 100644
--- a/configs/ba10_tv_box_defconfig
+++ b/configs/ba10_tv_box_defconfig
@@ -9,7 +9,6 @@
 CONFIG_USB2_VBUS_PIN="PH12"
 CONFIG_VIDEO_COMPOSITE=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/bananapi_m1_plus_defconfig b/configs/bananapi_m1_plus_defconfig
index 96c3023..c534a54 100644
--- a/configs/bananapi_m1_plus_defconfig
+++ b/configs/bananapi_m1_plus_defconfig
@@ -9,7 +9,6 @@
 CONFIG_GMAC_TX_DELAY=3
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/bananapi_m2_berry_defconfig b/configs/bananapi_m2_berry_defconfig
index 36a2fce..2799955 100644
--- a/configs/bananapi_m2_berry_defconfig
+++ b/configs/bananapi_m2_berry_defconfig
@@ -7,7 +7,6 @@
 CONFIG_MMC0_CD_PIN="PH13"
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-v40-bananapi-m2-berry"
diff --git a/configs/bananapi_m2_plus_h3_defconfig b/configs/bananapi_m2_plus_h3_defconfig
index f45fd5e..87fa0a9 100644
--- a/configs/bananapi_m2_plus_h3_defconfig
+++ b/configs/bananapi_m2_plus_h3_defconfig
@@ -7,7 +7,6 @@
 CONFIG_MACPWR="PD6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/bananapi_m2_plus_h5_defconfig b/configs/bananapi_m2_plus_h5_defconfig
index f7e23d4..bff6f37 100644
--- a/configs/bananapi_m2_plus_h5_defconfig
+++ b/configs/bananapi_m2_plus_h5_defconfig
@@ -7,7 +7,6 @@
 CONFIG_MACPWR="PD6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/bananapi_m2_zero_defconfig b/configs/bananapi_m2_zero_defconfig
index 93d4880..8546674 100644
--- a/configs/bananapi_m2_zero_defconfig
+++ b/configs/bananapi_m2_zero_defconfig
@@ -5,7 +5,6 @@
 CONFIG_DRAM_CLK=408
 CONFIG_MMC0_CD_PIN=""
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/bananapi_m64_defconfig b/configs/bananapi_m64_defconfig
index 06d90dd..0f5d531 100644
--- a/configs/bananapi_m64_defconfig
+++ b/configs/bananapi_m64_defconfig
@@ -7,7 +7,6 @@
 CONFIG_MMC0_CD_PIN="PH13"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/beelink_gs1_defconfig b/configs/beelink_gs1_defconfig
index f16d0fe..f142cde 100644
--- a/configs/beelink_gs1_defconfig
+++ b/configs/beelink_gs1_defconfig
@@ -3,14 +3,16 @@
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I_H6=y
+CONFIG_SUNXI_DRAM_H6_LPDDR3=y
 CONFIG_MMC0_CD_PIN="PF6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_PSCI_RESET is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x20060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-h6-beelink-gs1"
 CONFIG_LED=y
 CONFIG_LED_GPIO=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
diff --git a/configs/beelink_x2_defconfig b/configs/beelink_x2_defconfig
new file mode 100644
index 0000000..be94695
--- /dev/null
+++ b/configs/beelink_x2_defconfig
@@ -0,0 +1,16 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_SPL=y
+CONFIG_MACH_SUN8I_H3=y
+CONFIG_DRAM_CLK=567
+CONFIG_DRAM_ZQ=3881979
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-beelink-x2"
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_CONSOLE_MUX=y
+# CONFIG_CMD_FLASH is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_SUN8I_EMAC=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/chromebit_mickey_defconfig b/configs/chromebit_mickey_defconfig
index 1a34309..cf815dc 100644
--- a/configs/chromebit_mickey_defconfig
+++ b/configs/chromebit_mickey_defconfig
@@ -1,7 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00100000
-CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
 # CONFIG_SPL_MMC_SUPPORT is not set
 CONFIG_TARGET_CHROMEBIT_MICKEY=y
diff --git a/configs/chromebook_bob_defconfig b/configs/chromebook_bob_defconfig
index e61e27c..1c04f0a 100644
--- a/configs/chromebook_bob_defconfig
+++ b/configs/chromebook_bob_defconfig
@@ -2,9 +2,6 @@
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00200000
 CONFIG_SPL_GPIO_SUPPORT=y
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_ROCKCHIP_RK3399=y
 CONFIG_ROCKCHIP_BOOT_MODE_REG=0
 CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x4000
diff --git a/configs/chromebook_jerry_defconfig b/configs/chromebook_jerry_defconfig
index 7c7986e..f6056f8 100644
--- a/configs/chromebook_jerry_defconfig
+++ b/configs/chromebook_jerry_defconfig
@@ -1,7 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00100000
-CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
 # CONFIG_SPL_MMC_SUPPORT is not set
 CONFIG_TARGET_CHROMEBOOK_JERRY=y
diff --git a/configs/chromebook_minnie_defconfig b/configs/chromebook_minnie_defconfig
index 17c1ea6..b4bae3b 100644
--- a/configs/chromebook_minnie_defconfig
+++ b/configs/chromebook_minnie_defconfig
@@ -1,7 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00100000
-CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
 # CONFIG_SPL_MMC_SUPPORT is not set
 CONFIG_TARGET_CHROMEBOOK_MINNIE=y
diff --git a/configs/chromebook_speedy_defconfig b/configs/chromebook_speedy_defconfig
index 0cc1eb6..999dc69 100644
--- a/configs/chromebook_speedy_defconfig
+++ b/configs/chromebook_speedy_defconfig
@@ -1,7 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00100000
-CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
 # CONFIG_SPL_MMC_SUPPORT is not set
 CONFIG_TARGET_CHROMEBOOK_SPEEDY=y
diff --git a/configs/colorfly_e708_q1_defconfig b/configs/colorfly_e708_q1_defconfig
index 7d6cd30..c9d5d4d 100644
--- a/configs/colorfly_e708_q1_defconfig
+++ b/configs/colorfly_e708_q1_defconfig
@@ -16,7 +16,6 @@
 CONFIG_VIDEO_LCD_BL_PWM="PH13"
 CONFIG_VIDEO_LCD_PANEL_LVDS=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/difrnce_dit4350_defconfig b/configs/difrnce_dit4350_defconfig
index 02d233e..3600863 100644
--- a/configs/difrnce_dit4350_defconfig
+++ b/configs/difrnce_dit4350_defconfig
@@ -15,7 +15,6 @@
 CONFIG_VIDEO_LCD_BL_EN="AXP0-1"
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/dserve_dsrv9703c_defconfig b/configs/dserve_dsrv9703c_defconfig
index e4f9d41..0a192a0 100644
--- a/configs/dserve_dsrv9703c_defconfig
+++ b/configs/dserve_dsrv9703c_defconfig
@@ -14,7 +14,6 @@
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 CONFIG_VIDEO_LCD_PANEL_LVDS=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/emlid_neutis_n5_devboard_defconfig b/configs/emlid_neutis_n5_devboard_defconfig
index 3eb1ded..c1307aa 100644
--- a/configs/emlid_neutis_n5_devboard_defconfig
+++ b/configs/emlid_neutis_n5_devboard_defconfig
@@ -8,7 +8,6 @@
 # CONFIG_DRAM_ODT_EN is not set
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig
index b73da72..59d41cb 100644
--- a/configs/evb-ast2500_defconfig
+++ b/configs/evb-ast2500_defconfig
@@ -11,16 +11,19 @@
 CONFIG_PRE_CONSOLE_BUFFER=y
 CONFIG_PRE_CON_BUF_ADDR=0x1e720000
 # CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_HUSH_PARSER=y
 # CONFIG_AUTO_COMPLETE is not set
 CONFIG_CMD_I2C=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
 CONFIG_DEFAULT_DEVICE_TREE="ast2500-evb"
+CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_REGMAP=y
 CONFIG_CLK=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_ASPEED=y
+# CONFIG_MMC is not set
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_ETH=y
 CONFIG_FTGMAC100=y
diff --git a/configs/evb-px5_defconfig b/configs/evb-px5_defconfig
index 9601b12..a2b72c7 100644
--- a/configs/evb-px5_defconfig
+++ b/configs/evb-px5_defconfig
@@ -1,9 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00200000
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3368=y
 CONFIG_TPL_LDSCRIPT="arch/arm/mach-rockchip/u-boot-tpl-v8.lds"
 CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x40000
@@ -70,10 +67,6 @@
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_DEBUG_UART_SKIP_INIT=y
 CONFIG_SYSRESET=y
-CONFIG_TIMER=y
-CONFIG_SPL_TIMER=y
-CONFIG_TPL_TIMER=y
-CONFIG_ROCKCHIP_TIMER=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_PANIC_HANG=y
 CONFIG_SPL_TINY_MEMSET=y
diff --git a/configs/evb-rk3229_defconfig b/configs/evb-rk3229_defconfig
index 31c1b17..2032978 100644
--- a/configs/evb-rk3229_defconfig
+++ b/configs/evb-rk3229_defconfig
@@ -1,9 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x61000000
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x800
 CONFIG_ROCKCHIP_RK322X=y
 CONFIG_TPL_LDSCRIPT="arch/arm/mach-rockchip/u-boot-tpl.lds"
 CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x0
diff --git a/configs/evb-rk3288_defconfig b/configs/evb-rk3288_defconfig
index 843c59d..a6df143 100644
--- a/configs/evb-rk3288_defconfig
+++ b/configs/evb-rk3288_defconfig
@@ -1,12 +1,10 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
-CONFIG_SYS_TEXT_BASE=0x00000000
-CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SYS_TEXT_BASE=0x01000000
 CONFIG_ROCKCHIP_RK3288=y
-CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y
 CONFIG_TARGET_EVB_RK3288=y
 CONFIG_NR_DRAM_BANKS=1
-CONFIG_SPL_STACK_R_ADDR=0x80000
+CONFIG_SPL_SIZE_LIMIT=307200
 CONFIG_DEBUG_UART_BASE=0xff690000
 CONFIG_DEBUG_UART_CLOCK=24000000
 CONFIG_DEBUG_UART=y
@@ -15,9 +13,7 @@
 CONFIG_DEFAULT_FDT_FILE="rk3288-evb-rk808.dtb"
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_DISPLAY_BOARDINFO_LATE=y
-CONFIG_SPL_TEXT_BASE=0xff704000
-CONFIG_SPL_STACK_R=y
-CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000
+CONFIG_SPL_TEXT_BASE=0
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_GPT=y
 CONFIG_CMD_I2C=y
diff --git a/configs/evb-rk3328_defconfig b/configs/evb-rk3328_defconfig
index 92d6817..fcc04f2 100644
--- a/configs/evb-rk3328_defconfig
+++ b/configs/evb-rk3328_defconfig
@@ -1,7 +1,5 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_SYS_TEXT_BASE=0x00200000
 CONFIG_ROCKCHIP_RK3328=y
 CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
diff --git a/configs/evb-rk3399_defconfig b/configs/evb-rk3399_defconfig
index f10502c..764d32f 100644
--- a/configs/evb-rk3399_defconfig
+++ b/configs/evb-rk3399_defconfig
@@ -1,9 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00200000
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_ROCKCHIP_RK3399=y
 CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x50000
 CONFIG_NR_DRAM_BANKS=1
diff --git a/configs/fennec-rk3288_defconfig b/configs/fennec-rk3288_defconfig
index 6dfaff5..16d8fb1 100644
--- a/configs/fennec-rk3288_defconfig
+++ b/configs/fennec-rk3288_defconfig
@@ -1,7 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00000000
-CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
 CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y
 CONFIG_TARGET_FENNEC_RK3288=y
diff --git a/configs/ficus-rk3399_defconfig b/configs/ficus-rk3399_defconfig
index 6a1b279..d1425dc 100644
--- a/configs/ficus-rk3399_defconfig
+++ b/configs/ficus-rk3399_defconfig
@@ -1,9 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00200000
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_ROCKCHIP_RK3399=y
 CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x4000
 CONFIG_TARGET_ROCK960_RK3399=y
diff --git a/configs/firefly-rk3288_defconfig b/configs/firefly-rk3288_defconfig
index 4cedb28..8abe8a6 100644
--- a/configs/firefly-rk3288_defconfig
+++ b/configs/firefly-rk3288_defconfig
@@ -1,7 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00000000
-CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
 CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y
 CONFIG_TARGET_FIREFLY_RK3288=y
diff --git a/configs/firefly-rk3399_defconfig b/configs/firefly-rk3399_defconfig
index 61f05b7..9f05f33 100644
--- a/configs/firefly-rk3399_defconfig
+++ b/configs/firefly-rk3399_defconfig
@@ -1,9 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00200000
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_ROCKCHIP_RK3399=y
 CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x50000
 CONFIG_NR_DRAM_BANKS=1
diff --git a/configs/ga10h_v1_1_defconfig b/configs/ga10h_v1_1_defconfig
index ba86f48..d8eceac 100644
--- a/configs/ga10h_v1_1_defconfig
+++ b/configs/ga10h_v1_1_defconfig
@@ -17,7 +17,6 @@
 CONFIG_VIDEO_LCD_BL_PWM="PH0"
 CONFIG_VIDEO_LCD_PANEL_LVDS=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/gt90h_v4_defconfig b/configs/gt90h_v4_defconfig
index c440504..1cbee12 100644
--- a/configs/gt90h_v4_defconfig
+++ b/configs/gt90h_v4_defconfig
@@ -16,7 +16,6 @@
 CONFIG_VIDEO_LCD_BL_EN="PH6"
 CONFIG_VIDEO_LCD_BL_PWM="PH0"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/h8_homlet_v2_defconfig b/configs/h8_homlet_v2_defconfig
index d60576d..c1144c4 100644
--- a/configs/h8_homlet_v2_defconfig
+++ b/configs/h8_homlet_v2_defconfig
@@ -11,7 +11,6 @@
 CONFIG_AXP_GPIO=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_CONSOLE_MUX=y
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/i12-tvbox_defconfig b/configs/i12-tvbox_defconfig
index 259bf4e..629aea9 100644
--- a/configs/i12-tvbox_defconfig
+++ b/configs/i12-tvbox_defconfig
@@ -7,7 +7,6 @@
 CONFIG_MACPWR="PH21"
 CONFIG_VIDEO_COMPOSITE=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/iNet_3F_defconfig b/configs/iNet_3F_defconfig
index 935a11e..f7b2e4f 100644
--- a/configs/iNet_3F_defconfig
+++ b/configs/iNet_3F_defconfig
@@ -14,7 +14,6 @@
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 CONFIG_VIDEO_LCD_PANEL_LVDS=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/iNet_3W_defconfig b/configs/iNet_3W_defconfig
index a829401..38d8048 100644
--- a/configs/iNet_3W_defconfig
+++ b/configs/iNet_3W_defconfig
@@ -14,7 +14,6 @@
 CONFIG_VIDEO_LCD_BL_EN="PH7"
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/iNet_86VS_defconfig b/configs/iNet_86VS_defconfig
index 93bdddc..7144222 100644
--- a/configs/iNet_86VS_defconfig
+++ b/configs/iNet_86VS_defconfig
@@ -13,7 +13,6 @@
 CONFIG_VIDEO_LCD_BL_EN="AXP0-1"
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/iNet_D978_rev2_defconfig b/configs/iNet_D978_rev2_defconfig
index 1a8ee6b..c3fc0b2 100644
--- a/configs/iNet_D978_rev2_defconfig
+++ b/configs/iNet_D978_rev2_defconfig
@@ -17,7 +17,6 @@
 CONFIG_VIDEO_LCD_BL_PWM="PH0"
 CONFIG_VIDEO_LCD_PANEL_LVDS=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/icnova-a20-swac_defconfig b/configs/icnova-a20-swac_defconfig
index ed54700..b745dac 100644
--- a/configs/icnova-a20-swac_defconfig
+++ b/configs/icnova-a20-swac_defconfig
@@ -13,7 +13,6 @@
 CONFIG_VIDEO_LCD_POWER="PH22"
 CONFIG_VIDEO_LCD_PANEL_LVDS=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_CMD_UNZIP=y
 # CONFIG_CMD_FLASH is not set
diff --git a/configs/inet1_defconfig b/configs/inet1_defconfig
index 25a907b..831b5d0 100644
--- a/configs/inet1_defconfig
+++ b/configs/inet1_defconfig
@@ -14,7 +14,6 @@
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 CONFIG_VIDEO_LCD_PANEL_LVDS=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/inet86dz_defconfig b/configs/inet86dz_defconfig
index c007af9..77da929 100644
--- a/configs/inet86dz_defconfig
+++ b/configs/inet86dz_defconfig
@@ -16,7 +16,6 @@
 CONFIG_VIDEO_LCD_BL_EN="PH6"
 CONFIG_VIDEO_LCD_BL_PWM="PH0"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/inet97fv2_defconfig b/configs/inet97fv2_defconfig
index bc89a76..a5e4c6a 100644
--- a/configs/inet97fv2_defconfig
+++ b/configs/inet97fv2_defconfig
@@ -13,7 +13,6 @@
 CONFIG_VIDEO_LCD_BL_EN="PH7"
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/inet98v_rev2_defconfig b/configs/inet98v_rev2_defconfig
index b39c5f3..d96250d 100644
--- a/configs/inet98v_rev2_defconfig
+++ b/configs/inet98v_rev2_defconfig
@@ -15,7 +15,6 @@
 CONFIG_VIDEO_LCD_BL_EN="AXP0-1"
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/inet9f_rev03_defconfig b/configs/inet9f_rev03_defconfig
index d46c99f..c19c10f 100644
--- a/configs/inet9f_rev03_defconfig
+++ b/configs/inet9f_rev03_defconfig
@@ -13,7 +13,6 @@
 CONFIG_VIDEO_LCD_BL_EN="PH7"
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/inet_q972_defconfig b/configs/inet_q972_defconfig
index 19a3c4c..66c7628 100644
--- a/configs/inet_q972_defconfig
+++ b/configs/inet_q972_defconfig
@@ -15,7 +15,6 @@
 CONFIG_VIDEO_LCD_BL_EN="PA25"
 CONFIG_VIDEO_LCD_BL_PWM="PH13"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/jesurun_q5_defconfig b/configs/jesurun_q5_defconfig
index 3bd4a18..974e63c 100644
--- a/configs/jesurun_q5_defconfig
+++ b/configs/jesurun_q5_defconfig
@@ -8,7 +8,6 @@
 CONFIG_USB0_VBUS_PIN="PB9"
 CONFIG_VIDEO_COMPOSITE=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/libretech_all_h3_cc_h2_plus_defconfig b/configs/libretech_all_h3_cc_h2_plus_defconfig
index 7d7f542..7d42356 100644
--- a/configs/libretech_all_h3_cc_h2_plus_defconfig
+++ b/configs/libretech_all_h3_cc_h2_plus_defconfig
@@ -6,7 +6,6 @@
 CONFIG_DRAM_CLK=672
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/libretech_all_h3_cc_h3_defconfig b/configs/libretech_all_h3_cc_h3_defconfig
index be82721..7ef0000 100644
--- a/configs/libretech_all_h3_cc_h3_defconfig
+++ b/configs/libretech_all_h3_cc_h3_defconfig
@@ -6,7 +6,6 @@
 CONFIG_DRAM_CLK=672
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/libretech_all_h3_cc_h5_defconfig b/configs/libretech_all_h3_cc_h5_defconfig
index ed2c6d5..1e22469 100644
--- a/configs/libretech_all_h3_cc_h5_defconfig
+++ b/configs/libretech_all_h3_cc_h5_defconfig
@@ -6,7 +6,6 @@
 CONFIG_DRAM_CLK=672
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/lion-rk3368_defconfig b/configs/lion-rk3368_defconfig
index 75e8583..2c4e11c 100644
--- a/configs/lion-rk3368_defconfig
+++ b/configs/lion-rk3368_defconfig
@@ -1,9 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00200000
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3368=y
 CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x0
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
@@ -91,10 +88,6 @@
 CONFIG_DEBUG_UART_SKIP_INIT=y
 CONFIG_ROCKCHIP_SPI=y
 CONFIG_SYSRESET=y
-CONFIG_TIMER=y
-CONFIG_SPL_TIMER=y
-CONFIG_TPL_TIMER=y
-CONFIG_ROCKCHIP_TIMER=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_SPL_TINY_MEMSET=y
 CONFIG_LZO=y
diff --git a/configs/miqi-rk3288_defconfig b/configs/miqi-rk3288_defconfig
index 936192f..c9a3511 100644
--- a/configs/miqi-rk3288_defconfig
+++ b/configs/miqi-rk3288_defconfig
@@ -1,7 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00000000
-CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
 CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y
 CONFIG_TARGET_MIQI_RK3288=y
diff --git a/configs/mixtile_loftq_defconfig b/configs/mixtile_loftq_defconfig
index 8d286a2..4dce096 100644
--- a/configs/mixtile_loftq_defconfig
+++ b/configs/mixtile_loftq_defconfig
@@ -9,7 +9,6 @@
 CONFIG_USB1_VBUS_PIN="PH24"
 CONFIG_USB2_VBUS_PIN=""
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/mk802_a10s_defconfig b/configs/mk802_a10s_defconfig
index c9dfa04..48659db 100644
--- a/configs/mk802_a10s_defconfig
+++ b/configs/mk802_a10s_defconfig
@@ -7,7 +7,6 @@
 CONFIG_DRAM_EMR1=0
 CONFIG_USB1_VBUS_PIN="PB10"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/mk802_defconfig b/configs/mk802_defconfig
index 6ecabce..58986e3 100644
--- a/configs/mk802_defconfig
+++ b/configs/mk802_defconfig
@@ -5,7 +5,6 @@
 CONFIG_MACH_SUN4I=y
 CONFIG_USB2_VBUS_PIN="PH12"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/mk802ii_defconfig b/configs/mk802ii_defconfig
index 4474d03..243a195 100644
--- a/configs/mk802ii_defconfig
+++ b/configs/mk802ii_defconfig
@@ -4,7 +4,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN4I=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/mt7629_rfb_defconfig b/configs/mt7629_rfb_defconfig
index 0dceafd..d6a7c84 100644
--- a/configs/mt7629_rfb_defconfig
+++ b/configs/mt7629_rfb_defconfig
@@ -1,4 +1,5 @@
 CONFIG_ARM=y
+CONFIG_SYS_ARCH_TIMER=y
 CONFIG_SYS_THUMB_BUILD=y
 CONFIG_ARCH_MEDIATEK=y
 CONFIG_SYS_TEXT_BASE=0x41e00000
@@ -67,9 +68,6 @@
 CONFIG_SYSRESET=y
 CONFIG_SPL_SYSRESET=y
 CONFIG_SYSRESET_WATCHDOG=y
-CONFIG_TIMER=y
-CONFIG_SPL_TIMER=y
-CONFIG_MTK_TIMER=y
 CONFIG_WDT_MTK=y
 CONFIG_LZMA=y
 # CONFIG_EFI_LOADER is not set
diff --git a/configs/nanopc-t4-rk3399_defconfig b/configs/nanopc-t4-rk3399_defconfig
index 7863e45..bca4f08 100644
--- a/configs/nanopc-t4-rk3399_defconfig
+++ b/configs/nanopc-t4-rk3399_defconfig
@@ -1,9 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00200000
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_ROCKCHIP_RK3399=y
 CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x50000
 CONFIG_NR_DRAM_BANKS=1
diff --git a/configs/nanopi-m4-rk3399_defconfig b/configs/nanopi-m4-rk3399_defconfig
index 8b9237c..dd2065d 100644
--- a/configs/nanopi-m4-rk3399_defconfig
+++ b/configs/nanopi-m4-rk3399_defconfig
@@ -1,9 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00200000
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_ROCKCHIP_RK3399=y
 CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x50000
 CONFIG_NR_DRAM_BANKS=1
diff --git a/configs/nanopi-neo4-rk3399_defconfig b/configs/nanopi-neo4-rk3399_defconfig
index 5799ab3..46039d1 100644
--- a/configs/nanopi-neo4-rk3399_defconfig
+++ b/configs/nanopi-neo4-rk3399_defconfig
@@ -1,9 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00200000
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_ROCKCHIP_RK3399=y
 CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x50000
 CONFIG_NR_DRAM_BANKS=1
diff --git a/configs/nanopi_a64_defconfig b/configs/nanopi_a64_defconfig
index 0845a5c..eb031e6 100644
--- a/configs/nanopi_a64_defconfig
+++ b/configs/nanopi_a64_defconfig
@@ -5,7 +5,6 @@
 CONFIG_MACH_SUN50I=y
 CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/nanopi_m1_defconfig b/configs/nanopi_m1_defconfig
index 1dc2538..f021d87 100644
--- a/configs/nanopi_m1_defconfig
+++ b/configs/nanopi_m1_defconfig
@@ -5,7 +5,6 @@
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=408
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/nanopi_m1_plus_defconfig b/configs/nanopi_m1_plus_defconfig
index 90edbd9..c676579 100644
--- a/configs/nanopi_m1_plus_defconfig
+++ b/configs/nanopi_m1_plus_defconfig
@@ -8,7 +8,6 @@
 CONFIG_MMC0_CD_PIN="PH13"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/nanopi_neo2_defconfig b/configs/nanopi_neo2_defconfig
index 953fe23..984d9dd 100644
--- a/configs/nanopi_neo2_defconfig
+++ b/configs/nanopi_neo2_defconfig
@@ -7,7 +7,6 @@
 CONFIG_DRAM_ZQ=3881977
 # CONFIG_DRAM_ODT_EN is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/nanopi_neo_air_defconfig b/configs/nanopi_neo_air_defconfig
index 5ad90dd..bba31fc 100644
--- a/configs/nanopi_neo_air_defconfig
+++ b/configs/nanopi_neo_air_defconfig
@@ -7,7 +7,6 @@
 # CONFIG_VIDEO_DE2 is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_CONSOLE_MUX=y
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/nanopi_neo_defconfig b/configs/nanopi_neo_defconfig
index e7d6ce4..af36ad4 100644
--- a/configs/nanopi_neo_defconfig
+++ b/configs/nanopi_neo_defconfig
@@ -7,7 +7,6 @@
 # CONFIG_VIDEO_DE2 is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_CONSOLE_MUX=y
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/nanopi_neo_plus2_defconfig b/configs/nanopi_neo_plus2_defconfig
index 4096a61..3aa9cea 100644
--- a/configs/nanopi_neo_plus2_defconfig
+++ b/configs/nanopi_neo_plus2_defconfig
@@ -9,7 +9,6 @@
 CONFIG_MACPWR="PD6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/oceanic_5205_5inmfd_defconfig b/configs/oceanic_5205_5inmfd_defconfig
index 645e02a..219de7a 100644
--- a/configs/oceanic_5205_5inmfd_defconfig
+++ b/configs/oceanic_5205_5inmfd_defconfig
@@ -10,7 +10,6 @@
 CONFIG_MMC0_CD_PIN=""
 CONFIG_SPL_SPI_SUNXI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/orangepi-rk3399_defconfig b/configs/orangepi-rk3399_defconfig
index 82ec242..16a0a17 100644
--- a/configs/orangepi-rk3399_defconfig
+++ b/configs/orangepi-rk3399_defconfig
@@ -1,9 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00200000
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_ROCKCHIP_RK3399=y
 CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x50000
 CONFIG_NR_DRAM_BANKS=1
diff --git a/configs/orangepi_2_defconfig b/configs/orangepi_2_defconfig
index 803c061..a561a11 100644
--- a/configs/orangepi_2_defconfig
+++ b/configs/orangepi_2_defconfig
@@ -7,7 +7,6 @@
 CONFIG_DRAM_CLK=672
 CONFIG_USB1_VBUS_PIN="PG13"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/orangepi_lite2_defconfig b/configs/orangepi_lite2_defconfig
index e5c2846..74c11d8 100644
--- a/configs/orangepi_lite2_defconfig
+++ b/configs/orangepi_lite2_defconfig
@@ -3,11 +3,13 @@
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I_H6=y
+CONFIG_SUNXI_DRAM_H6_LPDDR3=y
 CONFIG_MMC0_CD_PIN="PF6"
 # CONFIG_PSCI_RESET is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x20060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-h6-orangepi-lite2"
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
diff --git a/configs/orangepi_lite_defconfig b/configs/orangepi_lite_defconfig
index 8621ca3..8b274e6 100644
--- a/configs/orangepi_lite_defconfig
+++ b/configs/orangepi_lite_defconfig
@@ -5,7 +5,6 @@
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=672
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/orangepi_one_defconfig b/configs/orangepi_one_defconfig
index d51491d..b56588a 100644
--- a/configs/orangepi_one_defconfig
+++ b/configs/orangepi_one_defconfig
@@ -5,7 +5,6 @@
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=672
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/orangepi_one_plus_defconfig b/configs/orangepi_one_plus_defconfig
index 65537c4..f86bb29 100644
--- a/configs/orangepi_one_plus_defconfig
+++ b/configs/orangepi_one_plus_defconfig
@@ -3,11 +3,13 @@
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I_H6=y
+CONFIG_SUNXI_DRAM_H6_LPDDR3=y
 CONFIG_MMC0_CD_PIN="PF6"
 # CONFIG_PSCI_RESET is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x20060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-h6-orangepi-one-plus"
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
diff --git a/configs/orangepi_pc2_defconfig b/configs/orangepi_pc2_defconfig
index 1069cc7..15ad3af 100644
--- a/configs/orangepi_pc2_defconfig
+++ b/configs/orangepi_pc2_defconfig
@@ -9,7 +9,6 @@
 CONFIG_MACPWR="PD6"
 CONFIG_SPL_SPI_SUNXI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/orangepi_pc_defconfig b/configs/orangepi_pc_defconfig
index e4626f0..7fe516e 100644
--- a/configs/orangepi_pc_defconfig
+++ b/configs/orangepi_pc_defconfig
@@ -5,7 +5,6 @@
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=624
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/orangepi_pc_plus_defconfig b/configs/orangepi_pc_plus_defconfig
index a9e00fc..8586bfc 100644
--- a/configs/orangepi_pc_plus_defconfig
+++ b/configs/orangepi_pc_plus_defconfig
@@ -6,7 +6,6 @@
 CONFIG_DRAM_CLK=624
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/orangepi_plus2e_defconfig b/configs/orangepi_plus2e_defconfig
index 592fb9d..59294bc 100644
--- a/configs/orangepi_plus2e_defconfig
+++ b/configs/orangepi_plus2e_defconfig
@@ -7,7 +7,6 @@
 CONFIG_MACPWR="PD6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/orangepi_plus_defconfig b/configs/orangepi_plus_defconfig
index 6433d0b..e632954 100644
--- a/configs/orangepi_plus_defconfig
+++ b/configs/orangepi_plus_defconfig
@@ -9,7 +9,6 @@
 CONFIG_USB1_VBUS_PIN="PG13"
 CONFIG_SATAPWR="PG11"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/orangepi_prime_defconfig b/configs/orangepi_prime_defconfig
index d862674..8a82669 100644
--- a/configs/orangepi_prime_defconfig
+++ b/configs/orangepi_prime_defconfig
@@ -7,7 +7,6 @@
 CONFIG_DRAM_ZQ=3881977
 # CONFIG_DRAM_ODT_EN is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/orangepi_r1_defconfig b/configs/orangepi_r1_defconfig
index 2b2d6f2..d80d83a 100644
--- a/configs/orangepi_r1_defconfig
+++ b/configs/orangepi_r1_defconfig
@@ -8,7 +8,6 @@
 CONFIG_SPL_SPI_SUNXI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_CONSOLE_MUX=y
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h2-plus-orangepi-r1"
 CONFIG_SUN8I_EMAC=y
diff --git a/configs/orangepi_win_defconfig b/configs/orangepi_win_defconfig
index 59e9639..5b800b5 100644
--- a/configs/orangepi_win_defconfig
+++ b/configs/orangepi_win_defconfig
@@ -6,7 +6,6 @@
 CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
 CONFIG_SPL_SPI_SUNXI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/orangepi_zero_defconfig b/configs/orangepi_zero_defconfig
index c354c8b..69471de 100644
--- a/configs/orangepi_zero_defconfig
+++ b/configs/orangepi_zero_defconfig
@@ -8,7 +8,6 @@
 CONFIG_SPL_SPI_SUNXI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_CONSOLE_MUX=y
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h2-plus-orangepi-zero"
 CONFIG_SUN8I_EMAC=y
diff --git a/configs/orangepi_zero_plus2_defconfig b/configs/orangepi_zero_plus2_defconfig
index 7610179..ed417dc 100644
--- a/configs/orangepi_zero_plus2_defconfig
+++ b/configs/orangepi_zero_plus2_defconfig
@@ -9,7 +9,6 @@
 CONFIG_MMC0_CD_PIN="PH13"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/orangepi_zero_plus_defconfig b/configs/orangepi_zero_plus_defconfig
index 671d871..ad3a6b7 100644
--- a/configs/orangepi_zero_plus_defconfig
+++ b/configs/orangepi_zero_plus_defconfig
@@ -7,7 +7,6 @@
 CONFIG_DRAM_ZQ=3881977
 # CONFIG_DRAM_ODT_EN is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/parrot_r16_defconfig b/configs/parrot_r16_defconfig
index 56b476b..5014745 100644
--- a/configs/parrot_r16_defconfig
+++ b/configs/parrot_r16_defconfig
@@ -12,7 +12,6 @@
 CONFIG_USB1_VBUS_PIN="PD12"
 CONFIG_AXP_GPIO=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_PARTITION_UUIDS is not set
diff --git a/configs/phycore-rk3288_defconfig b/configs/phycore-rk3288_defconfig
index 2e6a4a7..dfddc4a 100644
--- a/configs/phycore-rk3288_defconfig
+++ b/configs/phycore-rk3288_defconfig
@@ -1,7 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00000000
-CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
 CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y
 CONFIG_TARGET_PHYCORE_RK3288=y
diff --git a/configs/pine64-lts_defconfig b/configs/pine64-lts_defconfig
index 0ee1e05..0da6b70 100644
--- a/configs/pine64-lts_defconfig
+++ b/configs/pine64-lts_defconfig
@@ -10,7 +10,6 @@
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_SPL_SPI_SUNXI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/pine64_plus_defconfig b/configs/pine64_plus_defconfig
index c112ea0..65ea32d 100644
--- a/configs/pine64_plus_defconfig
+++ b/configs/pine64_plus_defconfig
@@ -6,7 +6,6 @@
 CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
 CONFIG_PINE64_DT_SELECTION=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/pine_h64_defconfig b/configs/pine_h64_defconfig
index 5ac89b4..dd1368a 100644
--- a/configs/pine_h64_defconfig
+++ b/configs/pine_h64_defconfig
@@ -3,12 +3,15 @@
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I_H6=y
+CONFIG_SUNXI_DRAM_H6_LPDDR3=y
 CONFIG_MMC0_CD_PIN="PF6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_PSCI_RESET is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x20060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-h6-pine-h64"
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB3_VBUS_PIN="PL5"
diff --git a/configs/pinebook_defconfig b/configs/pinebook_defconfig
index 75cb056..2760f8c 100644
--- a/configs/pinebook_defconfig
+++ b/configs/pinebook_defconfig
@@ -7,7 +7,6 @@
 CONFIG_DRAM_ZQ=3881949
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_R_I2C_ENABLE=y
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/polaroid_mid2407pxe03_defconfig b/configs/polaroid_mid2407pxe03_defconfig
index a2be518..0186a69 100644
--- a/configs/polaroid_mid2407pxe03_defconfig
+++ b/configs/polaroid_mid2407pxe03_defconfig
@@ -16,7 +16,6 @@
 CONFIG_VIDEO_LCD_BL_EN="PH6"
 CONFIG_VIDEO_LCD_BL_PWM="PH0"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/polaroid_mid2809pxe04_defconfig b/configs/polaroid_mid2809pxe04_defconfig
index 6ab4e4e..265e6b8 100644
--- a/configs/polaroid_mid2809pxe04_defconfig
+++ b/configs/polaroid_mid2809pxe04_defconfig
@@ -16,7 +16,6 @@
 CONFIG_VIDEO_LCD_BL_EN="PH6"
 CONFIG_VIDEO_LCD_BL_PWM="PH0"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/popmetal-rk3288_defconfig b/configs/popmetal-rk3288_defconfig
index 902294b..4c9a7f0 100644
--- a/configs/popmetal-rk3288_defconfig
+++ b/configs/popmetal-rk3288_defconfig
@@ -1,7 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00000000
-CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
 CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y
 CONFIG_TARGET_POPMETAL_RK3288=y
diff --git a/configs/pov_protab2_ips9_defconfig b/configs/pov_protab2_ips9_defconfig
index d94b316..80cdacf 100644
--- a/configs/pov_protab2_ips9_defconfig
+++ b/configs/pov_protab2_ips9_defconfig
@@ -14,7 +14,6 @@
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 CONFIG_VIDEO_LCD_PANEL_LVDS=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/puma-rk3399_defconfig b/configs/puma-rk3399_defconfig
index 5cb2273..37f845c 100644
--- a/configs/puma-rk3399_defconfig
+++ b/configs/puma-rk3399_defconfig
@@ -2,9 +2,6 @@
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00200000
 CONFIG_SPL_GPIO_SUPPORT=y
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_ROCKCHIP_RK3399=y
 CONFIG_ROCKCHIP_BOOT_MODE_REG=0x0
 CONFIG_TARGET_PUMA_RK3399=y
diff --git a/configs/q8_a13_tablet_defconfig b/configs/q8_a13_tablet_defconfig
index 6607a48..8f81b9a 100644
--- a/configs/q8_a13_tablet_defconfig
+++ b/configs/q8_a13_tablet_defconfig
@@ -15,7 +15,6 @@
 CONFIG_VIDEO_LCD_BL_EN="AXP0-1"
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/q8_a23_tablet_800x480_defconfig b/configs/q8_a23_tablet_800x480_defconfig
index c2eb17f..0413268 100644
--- a/configs/q8_a23_tablet_800x480_defconfig
+++ b/configs/q8_a23_tablet_800x480_defconfig
@@ -16,7 +16,6 @@
 CONFIG_VIDEO_LCD_BL_EN="PH6"
 CONFIG_VIDEO_LCD_BL_PWM="PH0"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/q8_a33_tablet_1024x600_defconfig b/configs/q8_a33_tablet_1024x600_defconfig
index 2ceda4e..7367306 100644
--- a/configs/q8_a33_tablet_1024x600_defconfig
+++ b/configs/q8_a33_tablet_1024x600_defconfig
@@ -16,7 +16,6 @@
 CONFIG_VIDEO_LCD_BL_EN="PH6"
 CONFIG_VIDEO_LCD_BL_PWM="PH0"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/q8_a33_tablet_800x480_defconfig b/configs/q8_a33_tablet_800x480_defconfig
index 3cd7f8f..03006e3 100644
--- a/configs/q8_a33_tablet_800x480_defconfig
+++ b/configs/q8_a33_tablet_800x480_defconfig
@@ -16,7 +16,6 @@
 CONFIG_VIDEO_LCD_BL_EN="PH6"
 CONFIG_VIDEO_LCD_BL_PWM="PH0"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/r7-tv-dongle_defconfig b/configs/r7-tv-dongle_defconfig
index 7fbe541..500d5e9 100644
--- a/configs/r7-tv-dongle_defconfig
+++ b/configs/r7-tv-dongle_defconfig
@@ -6,7 +6,6 @@
 CONFIG_DRAM_CLK=384
 CONFIG_USB1_VBUS_PIN="PG13"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/rock-pi-4-rk3399_defconfig b/configs/rock-pi-4-rk3399_defconfig
index be670df..14ae39a 100644
--- a/configs/rock-pi-4-rk3399_defconfig
+++ b/configs/rock-pi-4-rk3399_defconfig
@@ -1,9 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00200000
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_ROCKCHIP_RK3399=y
 CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x50000
 CONFIG_NR_DRAM_BANKS=1
@@ -28,6 +25,7 @@
 CONFIG_DEFAULT_DEVICE_TREE="rk3399-rock-pi-4"
 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_RAM_RK3399_LPDDR4=y
 CONFIG_ROCKCHIP_GPIO=y
 CONFIG_SYS_I2C_ROCKCHIP=y
 CONFIG_MMC_DW=y
diff --git a/configs/rock64-rk3328_defconfig b/configs/rock64-rk3328_defconfig
index 6529ded..ef453e7 100644
--- a/configs/rock64-rk3328_defconfig
+++ b/configs/rock64-rk3328_defconfig
@@ -2,9 +2,6 @@
 CONFIG_SMBIOS_PRODUCT_NAME="rock64_rk3328"
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_SYS_TEXT_BASE=0x00200000
 CONFIG_ROCKCHIP_RK3328=y
 CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x40000
diff --git a/configs/rock960-rk3399_defconfig b/configs/rock960-rk3399_defconfig
index 1958b7e..ed11fef 100644
--- a/configs/rock960-rk3399_defconfig
+++ b/configs/rock960-rk3399_defconfig
@@ -1,9 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00200000
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_ROCKCHIP_RK3399=y
 CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x4000
 CONFIG_TARGET_ROCK960_RK3399=y
@@ -21,7 +18,8 @@
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_GPT=y
 CONFIG_CMD_MMC=y
-CONFIG_CMD_SF=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_TIME=y
@@ -34,8 +32,8 @@
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
-CONFIG_SF_DEFAULT_SPEED=20000000
 CONFIG_PMIC_RK8XX=y
 CONFIG_REGULATOR_PWM=y
 CONFIG_REGULATOR_RK8XX=y
@@ -47,5 +45,15 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_GENERIC=y
 CONFIG_ROCKCHIP_USB2_PHY=y
+CONFIG_DM_ETH=y
+CONFIG_USB_HOST_ETHER=y
+CONFIG_USB_ETHER_ASIX88179=y
+CONFIG_USB_ETHER_ASIX=y
+CONFIG_USB_ETHER_MCS7830=y
+CONFIG_USB_ETHER_RTL8152=y
+CONFIG_USB_ETHER_SMSC95XX=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
+# CONFIG_USB_XHCI_ROCKCHIP is not set
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_ERRNO_STR=y
diff --git a/configs/rockpro64-rk3399_defconfig b/configs/rockpro64-rk3399_defconfig
index e8fc7ae..72bfff2 100644
--- a/configs/rockpro64-rk3399_defconfig
+++ b/configs/rockpro64-rk3399_defconfig
@@ -1,9 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00200000
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_ROCKCHIP_RK3399=y
 CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x50000
 CONFIG_NR_DRAM_BANKS=1
@@ -28,6 +25,7 @@
 CONFIG_DEFAULT_DEVICE_TREE="rk3399-rockpro64"
 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_RAM_RK3399_LPDDR4=y
 CONFIG_ROCKCHIP_GPIO=y
 CONFIG_SYS_I2C_ROCKCHIP=y
 CONFIG_MMC_DW=y
diff --git a/configs/sheep-rk3368_defconfig b/configs/sheep-rk3368_defconfig
index cff1905..4883f59 100644
--- a/configs/sheep-rk3368_defconfig
+++ b/configs/sheep-rk3368_defconfig
@@ -1,7 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00200000
-CONFIG_SYS_MALLOC_F_LEN=0x1000
 CONFIG_ROCKCHIP_RK3368=y
 CONFIG_TARGET_SHEEP=y
 CONFIG_NR_DRAM_BANKS=1
diff --git a/configs/sifive_fu540_defconfig b/configs/sifive_fu540_defconfig
index f784123..f192037 100644
--- a/configs/sifive_fu540_defconfig
+++ b/configs/sifive_fu540_defconfig
@@ -7,4 +7,5 @@
 CONFIG_FIT=y
 CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DISPLAY_BOARDINFO=y
+CONFIG_MISC_INIT_R=y
 CONFIG_OF_PRIOR_STAGE=y
diff --git a/configs/sopine_baseboard_defconfig b/configs/sopine_baseboard_defconfig
index acd6dd6..e47218c 100644
--- a/configs/sopine_baseboard_defconfig
+++ b/configs/sopine_baseboard_defconfig
@@ -11,7 +11,6 @@
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_SPL_SPI_SUNXI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig
index adf7b61..27b8525 100644
--- a/configs/stm32mp15_basic_defconfig
+++ b/configs/stm32mp15_basic_defconfig
@@ -101,6 +101,9 @@
 CONFIG_DM_REGULATOR_GPIO=y
 CONFIG_DM_REGULATOR_STM32_VREFBUF=y
 CONFIG_DM_REGULATOR_STPMIC1=y
+CONFIG_REMOTEPROC_STM32_COPRO=y
+CONFIG_DM_RTC=y
+CONFIG_RTC_STM32=y
 CONFIG_SERIAL_RX_BUFFER=y
 CONFIG_STM32_SERIAL=y
 CONFIG_SPI=y
diff --git a/configs/stm32mp15_optee_defconfig b/configs/stm32mp15_optee_defconfig
index a205f47..0565e5e 100644
--- a/configs/stm32mp15_optee_defconfig
+++ b/configs/stm32mp15_optee_defconfig
@@ -88,6 +88,9 @@
 CONFIG_DM_REGULATOR_GPIO=y
 CONFIG_DM_REGULATOR_STM32_VREFBUF=y
 CONFIG_DM_REGULATOR_STPMIC1=y
+CONFIG_REMOTEPROC_STM32_COPRO=y
+CONFIG_DM_RTC=y
+CONFIG_RTC_STM32=y
 CONFIG_SERIAL_RX_BUFFER=y
 CONFIG_STM32_SERIAL=y
 CONFIG_SPI=y
diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig
index cdb4d95..844cbcd 100644
--- a/configs/stm32mp15_trusted_defconfig
+++ b/configs/stm32mp15_trusted_defconfig
@@ -87,6 +87,9 @@
 CONFIG_DM_REGULATOR_GPIO=y
 CONFIG_DM_REGULATOR_STM32_VREFBUF=y
 CONFIG_DM_REGULATOR_STPMIC1=y
+CONFIG_REMOTEPROC_STM32_COPRO=y
+CONFIG_DM_RTC=y
+CONFIG_RTC_STM32=y
 CONFIG_SERIAL_RX_BUFFER=y
 CONFIG_STM32_SERIAL=y
 CONFIG_SPI=y
diff --git a/configs/sun8i_a23_evb_defconfig b/configs/sun8i_a23_evb_defconfig
index ef1bd21..3543e95 100644
--- a/configs/sun8i_a23_evb_defconfig
+++ b/configs/sun8i_a23_evb_defconfig
@@ -9,7 +9,6 @@
 CONFIG_USB0_VBUS_DET="axp_vbus_detect"
 CONFIG_USB1_VBUS_PIN="PH7"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/sunxi_Gemei_G9_defconfig b/configs/sunxi_Gemei_G9_defconfig
index 4bd6099..62b6838 100644
--- a/configs/sunxi_Gemei_G9_defconfig
+++ b/configs/sunxi_Gemei_G9_defconfig
@@ -11,7 +11,6 @@
 CONFIG_VIDEO_LCD_BL_PWM="PB2"
 CONFIG_VIDEO_LCD_PANEL_LVDS=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
diff --git a/configs/tbs_a711_defconfig b/configs/tbs_a711_defconfig
index 5d6ffab..d56bf68 100644
--- a/configs/tbs_a711_defconfig
+++ b/configs/tbs_a711_defconfig
@@ -13,7 +13,6 @@
 CONFIG_USB0_ID_DET="PH11"
 CONFIG_AXP_GPIO=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/teres_i_defconfig b/configs/teres_i_defconfig
index 1b57a48..421a8d3 100644
--- a/configs/teres_i_defconfig
+++ b/configs/teres_i_defconfig
@@ -7,7 +7,6 @@
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_USB1_VBUS_PIN="PL7"
 CONFIG_I2C0_ENABLE=y
-CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/tinker-rk3288_defconfig b/configs/tinker-rk3288_defconfig
index 482ee7d..b234539 100644
--- a/configs/tinker-rk3288_defconfig
+++ b/configs/tinker-rk3288_defconfig
@@ -1,9 +1,7 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x01000000
-CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
-CONFIG_TPL_LDSCRIPT="arch/arm/mach-rockchip/u-boot-tpl.lds"
 CONFIG_TARGET_TINKER_RK3288=y
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_SPL_SIZE_LIMIT=307200
diff --git a/configs/vyasa-rk3288_defconfig b/configs/vyasa-rk3288_defconfig
index 1108c6a..eaea625 100644
--- a/configs/vyasa-rk3288_defconfig
+++ b/configs/vyasa-rk3288_defconfig
@@ -3,7 +3,6 @@
 # CONFIG_SPL_USE_ARCH_MEMSET is not set
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00100000
-CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
 CONFIG_TARGET_VYASA_RK3288=y
 CONFIG_NR_DRAM_BANKS=1
diff --git a/disk/part_dos.c b/disk/part_dos.c
index 936cee0..aae9d95 100644
--- a/disk/part_dos.c
+++ b/disk/part_dos.c
@@ -23,6 +23,10 @@
 
 #define DOS_PART_DEFAULT_SECTOR 512
 
+/* should this be configurable? It looks like it's not very common at all
+ * to use large numbers of partitions */
+#define MAX_EXT_PARTS 256
+
 /* Convert char[4] in little endian format to the host format integer
  */
 static inline unsigned int le32_to_int(unsigned char *le32)
@@ -126,6 +130,13 @@
 	dos_partition_t *pt;
 	int i;
 
+	/* set a maximum recursion level */
+	if (part_num > MAX_EXT_PARTS)
+	{
+		printf("** Nested DOS partitions detected, stopping **\n");
+		return;
+    }
+
 	if (blk_dread(dev_desc, ext_part_sector, 1, (ulong *)buffer) != 1) {
 		printf ("** Can't read partition table on %d:" LBAFU " **\n",
 			dev_desc->devnum, ext_part_sector);
@@ -191,6 +202,13 @@
 	int i;
 	int dos_type;
 
+	/* set a maximum recursion level */
+	if (part_num > MAX_EXT_PARTS)
+	{
+		printf("** Nested DOS partitions detected, stopping **\n");
+		return -1;
+    }
+
 	if (blk_dread(dev_desc, ext_part_sector, 1, (ulong *)buffer) != 1) {
 		printf ("** Can't read partition table on %d:" LBAFU " **\n",
 			dev_desc->devnum, ext_part_sector);
diff --git a/doc/README.chromium b/doc/README.chromium
index 096bc4f..8f67da6 100644
--- a/doc/README.chromium
+++ b/doc/README.chromium
@@ -33,12 +33,18 @@
    cd u-boot
    git checkout cros-master
 
+   cd ..
+   git clone https://chromium.googlesource.com/chromiumos/platform/vboot_reference
+   cd vboot_reference
+   git checkout 45964294
+   #  futility: updater: Correct output version for Snow
+
 To build for sandbox:
 
    UB=/tmp/b/chromeos_sandbox    # U-Boot build directory
-   CROS=/home/sglass/cosarm      # Chromium OS directory
-   make O=$UB/chromeos_sandbox_defconfig
-   make O=$UB -j20 -s VBOOT_SOURCE=$CROS/src/platform/vboot_reference \
+   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
 
 Replace sandbox with another supported target.
diff --git a/doc/README.rockchip b/doc/README.rockchip
index 02e2497..8ccbb87 100644
--- a/doc/README.rockchip
+++ b/doc/README.rockchip
@@ -123,10 +123,6 @@
 
    Option 2: Package the image with SPL:
 
-   - We need the Python elftools.elf.elffile library for make_fit_atf.py to work
-
-     => sudo apt-get install python-pyelftools
-
    - Export cross compiler path for aarch64
 
    - Compile ATF
diff --git a/doc/README.sifive-fu540 b/doc/README.sifive-fu540
index fd9f2a8..944ba1c 100644
--- a/doc/README.sifive-fu540
+++ b/doc/README.sifive-fu540
@@ -13,8 +13,7 @@
 3. Cadence MACB ethernet driver for networking support.
 
 TODO:
-1. SPI driver is still missing. So MMC card can't be used in U-Boot as of now.
-2. U-Boot expects the serial console device entry to be present under /chosen
+1. U-Boot expects the serial console device entry to be present under /chosen
    DT node. Example:
    chosen {
         stdout-path = "/soc/serial@10010000:115200";
@@ -33,16 +32,21 @@
 
 Flashing
 ========
-The current U-Boot port is supported in S-mode only and loaded from DRAM.
+The current U-Boot port is supported in S-mode only and loaded directly
+into DRAM.
 
-A prior stage (M-mode) firmware/bootloader (e.g OpenSBI or BBL) is required to
-load the u-boot.bin into memory and provide runtime services. The u-boot.bin
-can be given as a payload to the prior stage (M-mode) firmware/bootloader.
+A prior stage (M-mode) firmware/bootloader (e.g OpenSBI) is required to
+boot the u-boot.bin in S-mode and provide M-mode runtime services.
 
-The description of steps required to build the firmware is beyond the scope of
-this document. Please refer OpenSBI or BBL documenation.
+Currently, the u-boot.bin is used as a payload of the OpenSBI FW_PAYLOAD
+firmware. We need to compile OpenSBI with below command:
+make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<path to u-boot.bin> FW_PAYLOAD_FDT_PATH=<path to hifive-unleashed-a00.dtb from Linux>
+(Note: Prefer hifive-unleashed-a00.dtb from Linux-5.3 or higher)
+(Note: Linux-5.2 is also fine but it does not have ethernet DT node)
+
+More detailed description of steps required to build FW_PAYLOAD firmware
+is beyond the scope of this document. Please refer OpenSBI documenation.
 (Note: OpenSBI git repo is at https://github.com/riscv/opensbi.git)
-(Note: BBL git repo is at https://github.com/riscv/riscv-pk.git)
 
 Once the prior stage firmware/bootloader binary is generated, it should be
 copied to the first partition of the sdcard.
@@ -55,20 +59,18 @@
 
 Sample boot log from HiFive Unleashed board
 ===========================================
-U-Boot 2019.01-00019-gc7953536-dirty (Jan 22 2019 - 11:05:40 -0800)
+U-Boot 2019.07-rc4-00013-g1837f893b0 (Jun 20 2019 - 11:08:48 +0530)
 
 CPU:   rv64imafdc
-Model: sifive,hifive-unleashed-a00
+Model: SiFive HiFive Unleashed A00
 DRAM:  8 GiB
 In:    serial@10010000
 Out:   serial@10010000
 Err:   serial@10010000
-Net:
-Warning: ethernet@10090000 (eth0) using random MAC address - b6:75:4d:48:50:94
-eth0: ethernet@10090000
+Net:   eth0: ethernet@10090000
 Hit any key to stop autoboot:  0
 => version
-U-Boot 2019.01-00019-gc7953536-dirty (Jan 22 2019 - 11:05:40 -0800)
+U-Boot 2019.07-rc4-00013-g1837f893b0 (Jun 20 2019 - 11:08:48 +0530)
 
 riscv64-linux-gcc.br_real (Buildroot 2018.11-rc2-00003-ga0787e9) 8.2.0
 GNU ld (GNU Binutils) 2.31.1
@@ -79,30 +81,19 @@
 load uImage.
 
 ==========================================================================
-=> setenv ethaddr 70:B3:D5:92:F0:C2
-=> setenv ipaddr 10.196.157.189
-=> setenv serverip 10.11.143.218
-=> setenv gatewayip 10.196.156.1
+=> setenv ipaddr 10.206.5.241
 => setenv netmask 255.255.252.0
-=> bdinfo
-boot_params = 0x0000000000000000
-DRAM bank   = 0x0000000000000000
--> start    = 0x0000000080000000
--> size     = 0x0000000200000000
-relocaddr   = 0x00000000fff90000
-reloc off   = 0x000000007fd90000
-ethaddr     = 70:B3:D5:92:F0:C2
-IP addr     = 10.196.157.189
-baudrate    = 115200 bps
-=> tftpboot uImage
+=> setenv serverip 10.206.4.143
+=> setenv gateway 10.206.4.1
+=> tftpboot ${kernel_addr_r} /sifive/fu540/uImage
 ethernet@10090000: PHY present at 0
 ethernet@10090000: Starting autonegotiation...
 ethernet@10090000: Autonegotiation complete
-ethernet@10090000: link up, 1000Mbps full-duplex (lpa: 0x3800)
+ethernet@10090000: link up, 1000Mbps full-duplex (lpa: 0x7c00)
 Using ethernet@10090000 device
-TFTP from server 10.11.143.218; our IP address is 10.196.157.189; sending through gateway 10.196.156.1
-Filename 'uImage'.
-Load address: 0x80200000
+TFTP from server 10.206.4.143; our IP address is 10.206.5.241
+Filename '/sifive/fu540/uImage'.
+Load address: 0x80600000
 Loading: #################################################################
          #################################################################
          #################################################################
@@ -112,192 +103,171 @@
          #################################################################
          #################################################################
          #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
-         #################################################################
+         ########################################
+         1.5 MiB/s
+done
+Bytes transferred = 9162364 (8bce7c hex)
+=> tftpboot ${ramdisk_addr_r} /sifive/fu540/uRamdisk
+ethernet@10090000: PHY present at 0
+ethernet@10090000: Starting autonegotiation...
+ethernet@10090000: Autonegotiation complete
+ethernet@10090000: link up, 1000Mbps full-duplex (lpa: 0x7c00)
+Using ethernet@10090000 device
+TFTP from server 10.206.4.143; our IP address is 10.206.5.241
+Filename '/sifive/fu540/uRamdisk'.
+Load address: 0x82500000
+Loading: #################################################################
          #################################################################
-         ##########################################################
-         2.5 MiB/s
+         ##################################
+         448.2 KiB/s
 done
-Bytes transferred = 14939132 (e3f3fc hex)
-=> bootm 0x80200000 - 0x82200000
-## Booting kernel from Legacy Image at 80200000 ...
+Bytes transferred = 2398272 (249840 hex)
+=> setenv bootargs "root=/dev/ram rw console=ttySIF0 earlycon=sbi"
+=> bootm ${kernel_addr_r} ${ramdisk_addr_r} ${fdtcontroladdr}
+## Booting kernel from Legacy Image at 80600000 ...
    Image Name:   Linux
    Image Type:   RISC-V Linux Kernel Image (uncompressed)
-   Data Size:    14939068 Bytes = 14.2 MiB
+   Data Size:    9162300 Bytes = 8.7 MiB
    Load Address: 80200000
    Entry Point:  80200000
    Verifying Checksum ... OK
-## Flattened Device Tree blob at 82200000
-   Booting using the fdt blob at 0x82200000
+## Loading init Ramdisk from Legacy Image at 82500000 ...
+   Image Name:   Linux RootFS
+   Image Type:   RISC-V Linux RAMDisk Image (uncompressed)
+   Data Size:    2398208 Bytes = 2.3 MiB
+   Load Address: 00000000
+   Entry Point:  00000000
+   Verifying Checksum ... OK
+## Flattened Device Tree blob at ff795730
+   Booting using the fdt blob at 0xff795730
    Loading Kernel Image ... OK
-   Using Device Tree in place at 0000000082200000, end 0000000082205c69
+   Using Device Tree in place at 00000000ff795730, end 00000000ff799dac
 
 Starting kernel ...
 
 [    0.000000] OF: fdt: Ignoring memory range 0x80000000 - 0x80200000
-[    0.000000] Linux version 5.0.0-rc1-00020-g4b51f736 (atish@jedi-01) (gcc version 7.2.0 (GCC)) #262 SMP Mon Jan 21 17:39:27 PST 2019
-[    0.000000] initrd not found or empty - disabling initrd
+[    0.000000] Linux version 5.2.0-rc1-00003-gb9543e66e700 (anup@anup-lab-machine) (gcc version 8.2.0 (Buildroot 2018.11-rc2-00003-ga0787e9)) #1 SMP Thu Jun 20 11:41:26 IST 2019
+[    0.000000] earlycon: sbi0 at I/O port 0x0 (options '')
+[    0.000000] printk: bootconsole [sbi0] enabled
+[    0.000000] Initial ramdisk at: 0x(____ptrval____) (2398208 bytes)
 [    0.000000] Zone ranges:
 [    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000ffffffff]
-[    0.000000]   Normal   [mem 0x0000000100000000-0x000027ffffffffff]
+[    0.000000]   Normal   [mem 0x0000000100000000-0x000000027fffffff]
 [    0.000000] Movable zone start for each node
 [    0.000000] Early memory node ranges
 [    0.000000]   node   0: [mem 0x0000000080200000-0x000000027fffffff]
 [    0.000000] Initmem setup node 0 [mem 0x0000000080200000-0x000000027fffffff]
-[    0.000000] software IO TLB: mapped [mem 0xfbfff000-0xfffff000] (64MB)
-[    0.000000] CPU with hartid=0 has a non-okay status of "masked"
-[    0.000000] CPU with hartid=0 has a non-okay status of "masked"
+[    0.000000] software IO TLB: mapped [mem 0xfb795000-0xff795000] (64MB)
+[    0.000000] CPU with hartid=0 is not available
+[    0.000000] CPU with hartid=0 is not available
 [    0.000000] elf_hwcap is 0x112d
-[    0.000000] percpu: Embedded 15 pages/cpu @(____ptrval____) s29720 r0 d31720 u61440
+[    0.000000] percpu: Embedded 17 pages/cpu s29592 r8192 d31848 u69632
 [    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 2067975
-[    0.000000] Kernel command line: earlyprintk
+[    0.000000] Kernel command line: root=/dev/ram rw console=ttySIF0 earlycon=sbi
 [    0.000000] Dentry cache hash table entries: 1048576 (order: 11, 8388608 bytes)
 [    0.000000] Inode-cache hash table entries: 524288 (order: 10, 4194304 bytes)
 [    0.000000] Sorting __ex_table...
-[    0.000000] Memory: 8178760K/8386560K available (3309K kernel code, 248K rwdata, 872K rodata, 9381K init, 763K bss, 207800K reserved, 0K cma-reserved)
+[    0.000000] Memory: 8182056K/8386560K available (5753K kernel code, 357K rwdata, 1804K rodata, 204K init, 808K bss, 204504K reserved, 0K cma-reserved)
 [    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
 [    0.000000] rcu: Hierarchical RCU implementation.
-[    0.000000] rcu:     RCU event tracing is enabled.
 [    0.000000] rcu:     RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=4.
-[    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 10 jiffies.
+[    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
 [    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4
 [    0.000000] NR_IRQS: 0, nr_irqs: 0, preallocated irqs: 0
-[    0.000000] plic: mapped 53 interrupts to 4 (out of 9) handlers.
-[    0.000000] riscv_timer_init_dt: Registering clocksource cpuid [0] hartid [1]
+[    0.000000] plic: mapped 53 interrupts with 4 handlers for 9 contexts.
+[    0.000000] riscv_timer_init_dt: Registering clocksource cpuid [0] hartid [2]
 [    0.000000] clocksource: riscv_clocksource: mask: 0xffffffffffffffff max_cycles: 0x1d854df40, max_idle_ns: 3526361616960 ns
-[    0.000008] sched_clock: 64 bits at 1000kHz, resolution 1000ns, wraps every 2199023255500ns
-[    0.000221] Console: colour dummy device 80x25
-[    0.000902] printk: console [tty0] enabled
-[    0.000963] Calibrating delay loop (skipped), value calculated using timer frequency.. 2.00 BogoMIPS (lpj=10000)
-[    0.001034] pid_max: default: 32768 minimum: 301
-[    0.001541] Mount-cache hash table entries: 16384 (order: 5, 131072 bytes)
-[    0.001912] Mountpoint-cache hash table entries: 16384 (order: 5, 131072 bytes)
-[    0.003542] rcu: Hierarchical SRCU implementation.
-[    0.004347] smp: Bringing up secondary CPUs ...
-[    1.040259] CPU1: failed to come online
-[    2.080483] CPU2: failed to come online
-[    3.120699] CPU3: failed to come online
-[    3.120765] smp: Brought up 1 node, 1 CPU
-[    3.121923] devtmpfs: initialized
-[    3.124649] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
-[    3.124727] futex hash table entries: 1024 (order: 4, 65536 bytes)
-[    3.125346] random: get_random_u32 called from bucket_table_alloc+0x72/0x172 with crng_init=0
-[    3.125578] NET: Registered protocol family 16
-[    3.126400] sifive-u54-prci 10000000.prci: Registered U54 core clocks
-[    3.126649] sifive-gemgxl-mgmt 100a0000.cadence-gemgxl-mgmt: Registered clock switch 'cadence-gemgxl-mgmt'
-[    3.135572] vgaarb: loaded
-[    3.135858] SCSI subsystem initialized
-[    3.136193] usbcore: registered new interface driver usbfs
-[    3.136266] usbcore: registered new interface driver hub
-[    3.136348] usbcore: registered new device driver usb
-[    3.136446] pps_core: LinuxPPS API ver. 1 registered
-[    3.136484] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
-[    3.136575] PTP clock support registered
-[    3.137256] clocksource: Switched to clocksource riscv_clocksource
-[    3.142711] NET: Registered protocol family 2
-[    3.143322] tcp_listen_portaddr_hash hash table entries: 4096 (order: 4, 65536 bytes)
-[    3.143634] TCP established hash table entries: 65536 (order: 7, 524288 bytes)
-[    3.145799] TCP bind hash table entries: 65536 (order: 8, 1048576 bytes)
-[    3.149121] TCP: Hash tables configured (established 65536 bind 65536)
-[    3.149591] UDP hash table entries: 4096 (order: 5, 131072 bytes)
-[    3.150094] UDP-Lite hash table entries: 4096 (order: 5, 131072 bytes)
-[    3.150781] NET: Registered protocol family 1
-[    3.230693] workingset: timestamp_bits=62 max_order=21 bucket_order=0
-[    3.241224] io scheduler mq-deadline registered
-[    3.241269] io scheduler kyber registered
-[    3.242143] sifive_gpio 10060000.gpio: SiFive GPIO chip registered 16 GPIOs
-[    3.242357] pwm-sifivem 10020000.pwm: Unable to find controller clock
-[    3.242439] pwm-sifivem 10021000.pwm: Unable to find controller clock
-[    3.243228] xilinx-pcie 2000000000.pci: PCIe Link is DOWN
-[    3.243289] xilinx-pcie 2000000000.pci: host bridge /soc/pci@2000000000 ranges:
-[    3.243360] xilinx-pcie 2000000000.pci:   No bus range found for /soc/pci@2000000000, using [bus 00-ff]
-[    3.243447] xilinx-pcie 2000000000.pci:   MEM 0x40000000..0x5fffffff -> 0x40000000
-[    3.243591] xilinx-pcie 2000000000.pci: PCI host bridge to bus 0000:00
-[    3.243636] pci_bus 0000:00: root bus resource [bus 00-ff]
-[    3.243676] pci_bus 0000:00: root bus resource [mem 0x40000000-0x5fffffff]
-[    3.276547] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
-[    3.277689] 10010000.serial: ttySIF0 at MMIO 0x10010000 (irq = 39, base_baud = 0) is a SiFive UART v0
-[    3.786963] printk: console [ttySIF0] enabled
-[    3.791504] 10011000.serial: ttySIF1 at MMIO 0x10011000 (irq = 40, base_baud = 0) is a SiFive UART v0
-[    3.801251] sifive_spi 10040000.spi: mapped; irq=41, cs=1
-[    3.806362] m25p80 spi0.0: unrecognized JEDEC id bytes: 9d, 70, 19
-[    3.812084] m25p80: probe of spi0.0 failed with error -2
-[    3.817453] sifive_spi 10041000.spi: mapped; irq=42, cs=4
-[    3.823027] sifive_spi 10050000.spi: mapped; irq=43, cs=1
-[    3.828604] libphy: Fixed MDIO Bus: probed
-[    3.832623] macb: GEM doesn't support hardware ptp.
-[    3.837196] libphy: MACB_mii_bus: probed
-[    4.041156] Microsemi VSC8541 SyncE 10090000.ethernet-ffffffff:00: attached PHY driver [Microsemi VSC8541 SyncE] (mii_bus:phy_addr=10090000.ethernet-ffffffff:00, irq=POLL)
-[    4.055779] macb 10090000.ethernet eth0: Cadence GEM rev 0x10070109 at 0x10090000 irq 12 (70:b3:d5:92:f0:c2)
-[    4.065780] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
-[    4.072033] ehci-pci: EHCI PCI platform driver
-[    4.076521] usbcore: registered new interface driver usb-storage
-[    4.082843] softdog: initialized. soft_noboot=0 soft_margin=60 sec soft_panic=0 (nowayout=0)
-[    4.127465] mmc_spi spi2.0: SD/MMC host mmc0, no DMA, no WP, no poweroff
-[    4.133645] usbcore: registered new interface driver usbhid
-[    4.138980] usbhid: USB HID core driver
-[    4.143017] NET: Registered protocol family 17
-[    4.147885] pwm-sifivem 10020000.pwm: SiFive PWM chip registered 4 PWMs
-[    4.153945] pwm-sifivem 10021000.pwm: SiFive PWM chip registered 4 PWMs
-[    4.186407] Freeing unused kernel memory: 9380K
-[    4.190224] This architecture does not have kernel memory protection.
-[    4.196609] Run /init as init process
-Starting logging: OK
-Starting mdev...
-[    4.303785] mmc0: host does not support reading read-only switch, assuming write-enable
-[    4.311109] mmc0: new SDHC card on SPI
-[    4.317103] mmcblk0: mmc0:0000 SS08G 7.40 GiB
-[    4.386471]  mmcblk0: p1 p2
-sort: /sys/devices/platform/Fixed: No such file or directory
-modprobe: can't change directory to '/lib/modules': No such file or directory
-Initializing random[    4.759075] random: dd: uninitialized urandom read (512 bytes read)
- number generator... done.
-Starting network...
-udhcpc (v1.24.2) started
-Sending discover...
-Sending discover...
-[    7.927510] macb 10090000.ethernet eth0: link up (1000/Full)
-Sending discover...
-Sending select for 10.196.157.190...
-Lease of 10.196.157.190 obtained, lease time 499743
-deleting routers
-adding dns 10.86.1.1
-adding dns 10.86.2.1
-/etc/init.d/S50dropbear
-Starting dropbear sshd: [   12.772393] random: dropbear: uninitialized urandom read (32 bytes read)
-OK
+[    0.000007] sched_clock: 64 bits at 1000kHz, resolution 1000ns, wraps every 2199023255500ns
+[    0.008553] Console: colour dummy device 80x25
+[    0.012990] Calibrating delay loop (skipped), value calculated using timer frequency.. 2.00 BogoMIPS (lpj=4000)
+[    0.023103] pid_max: default: 32768 minimum: 301
+[    0.028269] Mount-cache hash table entries: 16384 (order: 5, 131072 bytes)
+[    0.035068] Mountpoint-cache hash table entries: 16384 (order: 5, 131072 bytes)
+[    0.042770] *** VALIDATE proc ***
+[    0.045610] *** VALIDATE cgroup1 ***
+[    0.049157] *** VALIDATE cgroup2 ***
+[    0.053743] rcu: Hierarchical SRCU implementation.
+[    0.058297] smp: Bringing up secondary CPUs ...
+[    0.064134] smp: Brought up 1 node, 4 CPUs
+[    0.069114] devtmpfs: initialized
+[    0.073281] random: get_random_u32 called from bucket_table_alloc.isra.10+0x4e/0x160 with crng_init=0
+[    0.082157] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
+[    0.091634] futex hash table entries: 1024 (order: 4, 65536 bytes)
+[    0.098480] NET: Registered protocol family 16
+[    0.114101] vgaarb: loaded
+[    0.116397] SCSI subsystem initialized
+[    0.120358] usbcore: registered new interface driver usbfs
+[    0.125541] usbcore: registered new interface driver hub
+[    0.130936] usbcore: registered new device driver usb
+[    0.136618] clocksource: Switched to clocksource riscv_clocksource
+[    0.148108] NET: Registered protocol family 2
+[    0.152358] tcp_listen_portaddr_hash hash table entries: 4096 (order: 4, 65536 bytes)
+[    0.159928] TCP established hash table entries: 65536 (order: 7, 524288 bytes)
+[    0.169027] TCP bind hash table entries: 65536 (order: 8, 1048576 bytes)
+[    0.178360] TCP: Hash tables configured (established 65536 bind 65536)
+[    0.184653] UDP hash table entries: 4096 (order: 5, 131072 bytes)
+[    0.190819] UDP-Lite hash table entries: 4096 (order: 5, 131072 bytes)
+[    0.197618] NET: Registered protocol family 1
+[    0.201892] RPC: Registered named UNIX socket transport module.
+[    0.207395] RPC: Registered udp transport module.
+[    0.212159] RPC: Registered tcp transport module.
+[    0.216940] RPC: Registered tcp NFSv4.1 backchannel transport module.
+[    0.223445] PCI: CLS 0 bytes, default 64
+[    0.227726] Unpacking initramfs...
+[    0.260556] Freeing initrd memory: 2336K
+[    0.264652] workingset: timestamp_bits=62 max_order=21 bucket_order=0
+[    0.278452] NFS: Registering the id_resolver key type
+[    0.282841] Key type id_resolver registered
+[    0.287067] Key type id_legacy registered
+[    0.291155] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
+[    0.298299] NET: Registered protocol family 38
+[    0.302470] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 254)
+[    0.309906] io scheduler mq-deadline registered
+[    0.314501] io scheduler kyber registered
+[    0.354134] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
+[    0.360725] 10010000.serial: ttySIF0 at MMIO 0x10010000 (irq = 4, base_baud = 0) is a SiFive UART v0
+[    0.369191] printk: console [ttySIF0] enabled
+[    0.369191] printk: console [ttySIF0] enabled
+[    0.377938] printk: bootconsole [sbi0] disabled
+[    0.377938] printk: bootconsole [sbi0] disabled
+[    0.387298] 10011000.serial: ttySIF1 at MMIO 0x10011000 (irq = 1, base_baud = 0) is a SiFive UART v0
+[    0.396411] [drm] radeon kernel modesetting enabled.
+[    0.409818] loop: module loaded
+[    0.412606] libphy: Fixed MDIO Bus: probed
+[    0.416870] macb 10090000.ethernet: Registered clk switch 'sifive-gemgxl-mgmt'
+[    0.423570] macb: GEM doesn't support hardware ptp.
+[    0.428469] libphy: MACB_mii_bus: probed
+[    1.053009] Microsemi VSC8541 SyncE 10090000.ethernet-ffffffff:00: attached PHY driver [Microsemi VSC8541 SyncE] (mii_bus:phy_addr=10090000.ethernet-ffffffff:00, irq=POLL)
+[    1.067548] macb 10090000.ethernet eth0: Cadence GEM rev 0x10070109 at 0x10090000 irq 7 (70:b3:d5:92:f2:f3)
+[    1.077330] e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
+[    1.083069] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
+[    1.089061] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
+[    1.095485] ehci-pci: EHCI PCI platform driver
+[    1.099947] ehci-platform: EHCI generic platform driver
+[    1.105196] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
+[    1.111286] ohci-pci: OHCI PCI platform driver
+[    1.115742] ohci-platform: OHCI generic platform driver
+[    1.121142] usbcore: registered new interface driver uas
+[    1.126269] usbcore: registered new interface driver usb-storage
+[    1.132331] mousedev: PS/2 mouse device common for all mice
+[    1.137978] usbcore: registered new interface driver usbhid
+[    1.143325] usbhid: USB HID core driver
+[    1.148022] NET: Registered protocol family 10
+[    1.152609] Segment Routing with IPv6
+[    1.155571] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
+[    1.161927] NET: Registered protocol family 17
+[    1.165907] Key type dns_resolver registered
+[    1.171694] Freeing unused kernel memory: 204K
+[    1.175375] This architecture does not have kernel memory protection.
+[    1.181792] Run /init as init process
+           _  _
+          | ||_|
+          | | _ ____  _   _  _  _
+          | || |  _ \| | | |\ \/ /
+          | || | | | | |_| |/    \
+          |_||_|_| |_|\____|\_/\_/
+
+               Busybox Rootfs
 
-Welcome to Buildroot
-buildroot login:
+Please press Enter to activate this console.
+/ #
diff --git a/doc/README.android-fastboot-protocol b/doc/android/fastboot-protocol.txt
similarity index 100%
rename from doc/README.android-fastboot-protocol
rename to doc/android/fastboot-protocol.txt
diff --git a/doc/android/fastboot.txt b/doc/android/fastboot.txt
index 431191c..ea0d1da 100644
--- a/doc/android/fastboot.txt
+++ b/doc/android/fastboot.txt
@@ -5,8 +5,8 @@
 Overview
 ========
 
-The protocol that is used over USB and UDP is described in the
-``README.android-fastboot-protocol`` file in the same directory.
+The protocol that is used over USB and UDP is described in
+``doc/android/fastboot-protocol.txt``.
 
 The current implementation supports the following standard commands:
 
diff --git a/doc/device-tree-bindings/net/mdio-mux.txt b/doc/device-tree-bindings/net/mdio-mux.txt
new file mode 100644
index 0000000..eaa31ef
--- /dev/null
+++ b/doc/device-tree-bindings/net/mdio-mux.txt
@@ -0,0 +1,138 @@
+The expected structure of an MDIO MUX device tree node is described here.  This
+is heavily based on current Linux specification.
+One notable difference to Linux is that mdio-parent-bus is currently required
+by U-Boot, not optional as is in Linux.  Current U-Boot MDIO MUX udevice class
+implementation does not have specific support for MDIOs with an integrated MUX,
+the property should be made optional if such support is added.
+
+The MDIO buses downstream of the MUX should be described in the device tree as
+child nodes as indicated below.
+
+Required properties:
+mdio-parent-bus = a phandle to the MDIO bus used to perform actual I/O.  This is
+                  typically a real MDIO device, unless there are cascaded MUXes.
+#address-cells = <1>, each MDIO group is identified by one 32b value.
+#size-cells = <0>
+
+Other properties:
+The properties described here are sufficient for MDIO MUX DM class code, but
+MUX drivers may define additional properties, either required or optional.
+
+Required properties in child nodes:
+reg = value to be configured on the MUX to select the respective downstream
+      MDIO.
+
+Child nodes should normally contain PHY nodes, referenced by phandle from
+ethernet nodes of the eth interfaces using these PHYs.
+
+Example structure, extracted from Linux bindings document:
+
+	/* The parent MDIO bus. */
+	smi1: mdio@1180000001900 {
+		compatible = "cavium,octeon-3860-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x11800 0x00001900 0x0 0x40>;
+	};
+	/*
+	 * An NXP sn74cbtlv3253 dual 1-of-4 switch controlled by a
+	 * pair of GPIO lines.  Child busses 2 and 3 populated with 4
+	 * PHYs each.
+	 */
+	mdio-mux {
+		compatible = "mdio-mux-gpio";
+		gpios = <&gpio1 3 0>, <&gpio1 4 0>;
+		mdio-parent-bus = <&smi1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		mdio@2 {
+			reg = <2>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			phy11: ethernet-phy@1 {
+				reg = <1>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+			phy12: ethernet-phy@2 {
+				reg = <2>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+			phy13: ethernet-phy@3 {
+				reg = <3>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+			phy14: ethernet-phy@4 {
+				reg = <4>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <10 8>; /* Pin 10, active low */
+			};
+		};
+		mdio@3 {
+			reg = <3>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			phy21: ethernet-phy@1 {
+				reg = <1>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy22: ethernet-phy@2 {
+				reg = <2>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy23: ethernet-phy@3 {
+				reg = <3>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy24: ethernet-phy@4 {
+				reg = <4>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+		};
+	};
diff --git a/doc/device-tree-bindings/spi/spi-stm32-qspi.txt b/doc/device-tree-bindings/spi/spi-stm32-qspi.txt
index cec3e12..adeeb63 100644
--- a/doc/device-tree-bindings/spi/spi-stm32-qspi.txt
+++ b/doc/device-tree-bindings/spi/spi-stm32-qspi.txt
@@ -1,39 +1,44 @@
-STM32 QSPI controller device tree bindings
---------------------------------------------
+* STMicroelectronics Quad Serial Peripheral Interface(QSPI)
 
 Required properties:
-- compatible		: should be "st,stm32-qspi".
-- reg			: 1. Physical base address and size of SPI registers map.
-			  2. Physical base address & size of mapped NOR Flash.
-- spi-max-frequency	: Max supported spi frequency.
-- status		: enable in requried dts.
+- compatible: should be "st,stm32f469-qspi"
+- reg: the first contains the register location and length.
+       the second contains the memory mapping address and length
+- reg-names: should contain the reg names "qspi" "qspi_mm"
+- interrupts: should contain the interrupt for the device
+- clocks: the phandle of the clock needed by the QSPI controller
+- A pinctrl must be defined to set pins in mode of operation for QSPI transfer
 
-Connected flash properties
---------------------------
-- spi-max-frequency	: Max supported spi frequency.
-- spi-tx-bus-width	: Bus width (number of lines) for writing (1-4)
-- spi-rx-bus-width	: Bus width (number of lines) for reading (1-4)
-- memory-map		: Address and size for memory-mapping the flash
+Optional properties:
+- resets: must contain the phandle to the reset controller.
+
+A spi flash (NOR/NAND) must be a child of spi node and could have some
+properties. Also see jedec,spi-nor.txt.
+
+Required properties:
+- reg: chip-Select number (QSPI controller may connect 2 flashes)
+- spi-max-frequency: max frequency of spi bus
+
+Optional property:
+- spi-rx-bus-width: see ./spi-bus.txt for the description
 
 Example:
-	qspi: quadspi@A0001000 {
-		compatible = "st,stm32-qspi";
-		#address-cells = <1>;
-		#size-cells = <0>;
-		reg = <0xA0001000 0x1000>, <0x90000000 0x10000000>;
-		reg-names = "QuadSPI", "QuadSPI-memory";
-		interrupts = <92>;
-		spi-max-frequency = <108000000>;
-		status = "okay";
 
-		qflash0: n25q128a {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "micron,n25q128a13", "jedec,spi-nor";
-			spi-max-frequency = <108000000>;
-			spi-tx-bus-width = <4>;
-			spi-rx-bus-width = <4>;
-			memory-map = <0x90000000 0x1000000>;
-			reg = <0>;
-		};
+qspi: spi@a0001000 {
+	compatible = "st,stm32f469-qspi";
+	reg = <0xa0001000 0x1000>, <0x90000000 0x10000000>;
+	reg-names = "qspi", "qspi_mm";
+	interrupts = <91>;
+	resets = <&rcc STM32F4_AHB3_RESET(QSPI)>;
+	clocks = <&rcc 0 STM32F4_AHB3_CLOCK(QSPI)>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_qspi0>;
+
+	flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <108000000>;
+		...
 	};
+};
diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt
index 78b59e7..c9b1802 100644
--- a/doc/uImage.FIT/signature.txt
+++ b/doc/uImage.FIT/signature.txt
@@ -388,8 +388,8 @@
 Test passed
 
 
-Hardware Signing with PKCS#11
------------------------------
+Hardware Signing with PKCS#11 or with HSM
+-----------------------------------------
 
 Securely managing private signing keys can challenging, especially when the
 keys are stored on the file system of a computer that is connected to the
@@ -402,14 +402,43 @@
 device.
 
 Requirements:
-Smartcard/USB token/HSM which can work with the pkcs11 engine
+Smartcard/USB token/HSM which can work with some openssl engine
 openssl
+
+For pkcs11 engine usage:
 libp11 (provides pkcs11 engine)
 p11-kit (recommended to simplify setup)
 opensc (for smartcards and smartcard like USB devices)
 gnutls (recommended for key generation, p11tool)
 
+For generic HSMs respective openssl engine must be installed and locateable by
+openssl. This may require setting up LD_LIBRARY_PATH if engine is not installed
+to openssl's default search paths.
+
+PKCS11 engine support forms "key id" based on "keydir" and with
+"key-name-hint". "key-name-hint" is used as "object" name and "keydir" if
+defined is used to define (prefix for) which PKCS11 source is being used for
+lookup up for the key.
+
+PKCS11 engine key ids:
+   "pkcs11:<keydir>;object=<key-name-hint>;type=<public|private>"
+or
+   "pkcs11:object=<key-name-hint>;type=<public|private>",
+
+Generic HSM engine support forms "key id" based on "keydir" and with
+"key-name-hint". If "keydir" is specified for mkimage it is used as a prefix in
+"key id" and is appended with "key-name-hint".
+
+Generic engine key ids:
+  "<keydir><key-name-hint>"
+or
+  "<key-name-hint>"
+
+As mkimage does not at this time support prompting for passwords HSM may need
+key preloading wrapper to be used when invoking mkimage.
+
-The following examples use the Nitrokey Pro. Instructions for other devices may vary.
+The following examples use the Nitrokey Pro using pkcs11 engine. Instructions
+for other devices may vary.
 
 Notes on pkcs11 engine setup:
 
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index baaf431..c23b668 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -208,7 +208,11 @@
 	if (ret)
 		return ret;
 
-	return blk_select_hwpart(dev, hwpart);
+	ret = blk_select_hwpart(dev, hwpart);
+	if (!ret)
+		blkcache_invalidate(if_type, devnum);
+
+	return ret;
 }
 
 int blk_list_part(enum if_type if_type)
@@ -348,7 +352,13 @@
 
 int blk_dselect_hwpart(struct blk_desc *desc, int hwpart)
 {
-	return blk_select_hwpart(desc->bdev, hwpart);
+	int ret;
+
+	ret = blk_select_hwpart(desc->bdev, hwpart);
+	if (!ret)
+		blkcache_invalidate(desc->if_type, desc->devnum);
+
+	return ret;
 }
 
 int blk_first_device(int if_type, struct udevice **devp)
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 96969b9..7b81eac 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -98,6 +98,7 @@
 	  Enable the STM32 clock (RCC) driver. Enable support for
 	  manipulating STM32MP1's on-SoC clocks.
 
+source "drivers/clk/analogbits/Kconfig"
 source "drivers/clk/at91/Kconfig"
 source "drivers/clk/exynos/Kconfig"
 source "drivers/clk/imx/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 719b9b8..f0ced49 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -8,6 +8,7 @@
 obj-$(CONFIG_$(SPL_TPL_)CLK) += clk_fixed_rate.o
 obj-$(CONFIG_$(SPL_TPL_)CLK) += clk_fixed_factor.o
 
+obj-y += analogbits/
 obj-y += imx/
 obj-y += tegra/
 obj-$(CONFIG_ARCH_ASPEED) += aspeed/
diff --git a/drivers/clk/analogbits/Kconfig b/drivers/clk/analogbits/Kconfig
new file mode 100644
index 0000000..1d25e6f
--- /dev/null
+++ b/drivers/clk/analogbits/Kconfig
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config CLK_ANALOGBITS_WRPLL_CLN28HPC
+	bool
diff --git a/drivers/clk/analogbits/Makefile b/drivers/clk/analogbits/Makefile
new file mode 100644
index 0000000..ec1bb40
--- /dev/null
+++ b/drivers/clk/analogbits/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-$(CONFIG_CLK_ANALOGBITS_WRPLL_CLN28HPC)	+= wrpll-cln28hpc.o
diff --git a/drivers/clk/sifive/wrpll-cln28hpc.c b/drivers/clk/analogbits/wrpll-cln28hpc.c
similarity index 69%
rename from drivers/clk/sifive/wrpll-cln28hpc.c
rename to drivers/clk/analogbits/wrpll-cln28hpc.c
index d377849..776ead3 100644
--- a/drivers/clk/sifive/wrpll-cln28hpc.c
+++ b/drivers/clk/analogbits/wrpll-cln28hpc.c
@@ -1,20 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2019 Western Digital Corporation or its affiliates.
- *
- * Copyright (C) 2018 SiFive, Inc.
+ * Copyright (C) 2018-2019 SiFive, Inc.
  * Wesley Terpstra
  * Paul Walmsley
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 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.
- *
  * This library supports configuration parsing and reprogramming of
  * the CLN28HPC variant of the Analog Bits Wide Range PLL.  The
  * intention is for this library to be reusable for any device that
@@ -29,14 +18,14 @@
  * References:
  * - Analog Bits "Wide Range PLL Datasheet", version 2015.10.01
  * - SiFive FU540-C000 Manual v1p0, Chapter 7 "Clocking and Reset"
+ *   https://static.dev.sifive.com/FU540-C000-v1.0.pdf
  */
 
 #include <linux/bug.h>
 #include <linux/err.h>
 #include <linux/log2.h>
 #include <linux/math64.h>
-
-#include "analogbits-wrpll-cln28hpc.h"
+#include <linux/clk/analogbits-wrpll-cln28hpc.h>
 
 /* MIN_INPUT_FREQ: minimum input clock frequency, in Hz (Fref_min) */
 #define MIN_INPUT_FREQ			7000000
@@ -85,40 +74,38 @@
  * range selection.
  *
  * Return: The RANGE value to be presented to the PLL configuration inputs,
- *         or -1 upon error.
+ *         or a negative return code upon error.
  */
 static int __wrpll_calc_filter_range(unsigned long post_divr_freq)
 {
-	u8 range;
-
 	if (post_divr_freq < MIN_POST_DIVR_FREQ ||
 	    post_divr_freq > MAX_POST_DIVR_FREQ) {
 		WARN(1, "%s: post-divider reference freq out of range: %lu",
 		     __func__, post_divr_freq);
-		return -1;
+		return -ERANGE;
 	}
 
-	if (post_divr_freq < 11000000)
-		range = 1;
-	else if (post_divr_freq < 18000000)
-		range = 2;
-	else if (post_divr_freq < 30000000)
-		range = 3;
-	else if (post_divr_freq < 50000000)
-		range = 4;
-	else if (post_divr_freq < 80000000)
-		range = 5;
-	else if (post_divr_freq < 130000000)
-		range = 6;
-	else
-		range = 7;
+	switch (post_divr_freq) {
+	case 0 ... 10999999:
+		return 1;
+	case 11000000 ... 17999999:
+		return 2;
+	case 18000000 ... 29999999:
+		return 3;
+	case 30000000 ... 49999999:
+		return 4;
+	case 50000000 ... 79999999:
+		return 5;
+	case 80000000 ... 129999999:
+		return 6;
+	}
 
-	return range;
+	return 7;
 }
 
 /**
  * __wrpll_calc_fbdiv() - return feedback fixed divide value
- * @c: ptr to a struct analogbits_wrpll_cfg record to read from
+ * @c: ptr to a struct wrpll_cfg record to read from
  *
  * The internal feedback path includes a fixed by-two divider; the
  * external feedback path does not.  Return the appropriate divider
@@ -133,7 +120,7 @@
  * Return: 2 if internal feedback is enabled or 1 if external feedback
  *         is enabled.
  */
-static u8 __wrpll_calc_fbdiv(struct analogbits_wrpll_cfg *c)
+static u8 __wrpll_calc_fbdiv(const struct wrpll_cfg *c)
 {
 	return (c->flags & WRPLL_FLAGS_INT_FEEDBACK_MASK) ? 2 : 1;
 }
@@ -173,7 +160,7 @@
 		*vco_rate = MIN_VCO_FREQ;
 	} else {
 		divq = ilog2(s);
-		*vco_rate = target_rate << divq;
+		*vco_rate = (u64)target_rate << divq;
 	}
 
 wcd_out:
@@ -182,7 +169,7 @@
 
 /**
  * __wrpll_update_parent_rate() - update PLL data when parent rate changes
- * @c: ptr to a struct analogbits_wrpll_cfg record to write PLL data to
+ * @c: ptr to a struct wrpll_cfg record to write PLL data to
  * @parent_rate: PLL input refclk rate (pre-R-divider)
  *
  * Pre-compute some data used by the PLL configuration algorithm when
@@ -190,46 +177,40 @@
  * computation when the parent rate remains constant - expected to be
  * the common case.
  *
- * Returns: 0 upon success or -1 if the reference clock rate is out of range.
+ * Returns: 0 upon success or -ERANGE if the reference clock rate is
+ * out of range.
  */
-static int __wrpll_update_parent_rate(struct analogbits_wrpll_cfg *c,
+static int __wrpll_update_parent_rate(struct wrpll_cfg *c,
 				      unsigned long parent_rate)
 {
 	u8 max_r_for_parent;
 
 	if (parent_rate > MAX_INPUT_FREQ || parent_rate < MIN_POST_DIVR_FREQ)
-		return -1;
+		return -ERANGE;
 
-	c->_parent_rate = parent_rate;
+	c->parent_rate = parent_rate;
 	max_r_for_parent = div_u64(parent_rate, MIN_POST_DIVR_FREQ);
-	c->_max_r = min_t(u8, MAX_DIVR_DIVISOR, max_r_for_parent);
+	c->max_r = min_t(u8, MAX_DIVR_DIVISOR, max_r_for_parent);
 
-	/* Round up */
-	c->_init_r = div_u64(parent_rate + MAX_POST_DIVR_FREQ - 1,
-			     MAX_POST_DIVR_FREQ);
+	c->init_r = DIV_ROUND_UP_ULL(parent_rate, MAX_POST_DIVR_FREQ);
 
 	return 0;
 }
 
-/*
- * Public functions
- */
-
 /**
- * analogbits_wrpll_configure() - compute PLL configuration for a target rate
- * @c: ptr to a struct analogbits_wrpll_cfg record to write into
+ * wrpll_configure() - compute PLL configuration for a target rate
+ * @c: ptr to a struct wrpll_cfg record to write into
  * @target_rate: target PLL output clock rate (post-Q-divider)
  * @parent_rate: PLL input refclk rate (pre-R-divider)
  *
- * Given a pointer to a PLL context @c, a desired PLL target output
- * rate @target_rate, and a reference clock input rate @parent_rate,
- * compute the appropriate PLL signal configuration values.  PLL
- * reprogramming is not glitchless, so the caller should switch any
- * downstream logic to a different clock source or clock-gate it
- * before presenting these values to the PLL configuration signals.
+ * Compute the appropriate PLL signal configuration values and store
+ * in PLL context @c.  PLL reprogramming is not glitchless, so the
+ * caller should switch any downstream logic to a different clock
+ * source or clock-gate it before presenting these values to the PLL
+ * configuration signals.
  *
  * The caller must pass this function a pre-initialized struct
- * analogbits_wrpll_cfg record: either initialized to zero (with the
+ * wrpll_cfg record: either initialized to zero (with the
  * exception of the .name and .flags fields) or read from the PLL.
  *
  * Context: Any context.  Caller must protect the memory pointed to by @c
@@ -237,41 +218,26 @@
  *
  * Return: 0 upon success; anything else upon failure.
  */
-int analogbits_wrpll_configure_for_rate(struct analogbits_wrpll_cfg *c,
-					u32 target_rate,
-					unsigned long parent_rate)
+int wrpll_configure_for_rate(struct wrpll_cfg *c, u32 target_rate,
+			     unsigned long parent_rate)
 {
 	unsigned long ratio;
 	u64 target_vco_rate, delta, best_delta, f_pre_div, vco, vco_pre;
-	u32 best_f, f, post_divr_freq, fbcfg;
+	u32 best_f, f, post_divr_freq;
 	u8 fbdiv, divq, best_r, r;
-
-	if (!c)
-		return -1;
+	int range;
 
 	if (c->flags == 0) {
 		WARN(1, "%s called with uninitialized PLL config", __func__);
-		return -1;
+		return -EINVAL;
 	}
 
-	fbcfg = WRPLL_FLAGS_INT_FEEDBACK_MASK | WRPLL_FLAGS_EXT_FEEDBACK_MASK;
-	if ((c->flags & fbcfg) == fbcfg) {
-		WARN(1, "%s called with invalid PLL config", __func__);
-		return -1;
-	}
-
-	if (c->flags == WRPLL_FLAGS_EXT_FEEDBACK_MASK) {
-		WARN(1, "%s: external feedback mode not currently supported",
-		     __func__);
-		return -1;
-	}
-
 	/* Initialize rounding data if it hasn't been initialized already */
-	if (parent_rate != c->_parent_rate) {
+	if (parent_rate != c->parent_rate) {
 		if (__wrpll_update_parent_rate(c, parent_rate)) {
 			pr_err("%s: PLL input rate is out of range\n",
 			       __func__);
-			return -1;
+			return -ERANGE;
 		}
 	}
 
@@ -282,11 +248,12 @@
 		c->flags |= WRPLL_FLAGS_BYPASS_MASK;
 		return 0;
 	}
+
 	c->flags &= ~WRPLL_FLAGS_BYPASS_MASK;
 
 	/* Calculate the Q shift and target VCO rate */
 	divq = __wrpll_calc_divq(target_rate, &target_vco_rate);
-	if (divq == 0)
+	if (!divq)
 		return -1;
 	c->divq = divq;
 
@@ -302,8 +269,7 @@
 	 * Consider all values for R which land within
 	 * [MIN_POST_DIVR_FREQ, MAX_POST_DIVR_FREQ]; prefer smaller R
 	 */
-	for (r = c->_init_r; r <= c->_max_r; ++r) {
-		/* What is the best F we can pick in this case? */
+	for (r = c->init_r; r <= c->max_r; ++r) {
 		f_pre_div = ratio * r;
 		f = (f_pre_div + (1 << ROUND_SHIFT)) >> ROUND_SHIFT;
 		f >>= (fbdiv - 1);
@@ -335,46 +301,54 @@
 	post_divr_freq = div_u64(parent_rate, best_r);
 
 	/* Pick the best PLL jitter filter */
-	c->range = __wrpll_calc_filter_range(post_divr_freq);
+	range = __wrpll_calc_filter_range(post_divr_freq);
+	if (range < 0)
+		return range;
+	c->range = range;
 
 	return 0;
 }
 
 /**
- * analogbits_wrpll_calc_output_rate() - calculate the PLL's target output rate
- * @c: ptr to a struct analogbits_wrpll_cfg record to read from
+ * wrpll_calc_output_rate() - calculate the PLL's target output rate
+ * @c: ptr to a struct wrpll_cfg record to read from
  * @parent_rate: PLL refclk rate
  *
  * Given a pointer to the PLL's current input configuration @c and the
  * PLL's input reference clock rate @parent_rate (before the R
  * pre-divider), calculate the PLL's output clock rate (after the Q
- * post-divider)
+ * post-divider).
  *
  * Context: Any context.  Caller must protect the memory pointed to by @c
  *          from simultaneous modification.
  *
- * Return: the PLL's output clock rate, in Hz.
+ * Return: the PLL's output clock rate, in Hz.  The return value from
+ *         this function is intended to be convenient to pass directly
+ *         to the Linux clock framework; thus there is no explicit
+ *         error return value.
  */
-unsigned long analogbits_wrpll_calc_output_rate(struct analogbits_wrpll_cfg *c,
-						unsigned long parent_rate)
+unsigned long wrpll_calc_output_rate(const struct wrpll_cfg *c,
+				     unsigned long parent_rate)
 {
 	u8 fbdiv;
 	u64 n;
 
-	WARN(c->flags & WRPLL_FLAGS_EXT_FEEDBACK_MASK,
-	     "external feedback mode not yet supported");
+	if (c->flags & WRPLL_FLAGS_EXT_FEEDBACK_MASK) {
+		WARN(1, "external feedback mode not yet supported");
+		return ULONG_MAX;
+	}
 
 	fbdiv = __wrpll_calc_fbdiv(c);
 	n = parent_rate * fbdiv * (c->divf + 1);
-	n = div_u64(n, (c->divr + 1));
+	n = div_u64(n, c->divr + 1);
 	n >>= c->divq;
 
 	return n;
 }
 
 /**
- * analogbits_wrpll_calc_max_lock_us() - return the time for the PLL to lock
- * @c: ptr to a struct analogbits_wrpll_cfg record to read from
+ * wrpll_calc_max_lock_us() - return the time for the PLL to lock
+ * @c: ptr to a struct wrpll_cfg record to read from
  *
  * Return the minimum amount of time (in microseconds) that the caller
  * must wait after reprogramming the PLL to ensure that it is locked
@@ -384,7 +358,7 @@
  * Return: the minimum amount of time the caller must wait for the PLL
  *         to lock (in microseconds)
  */
-unsigned int analogbits_wrpll_calc_max_lock_us(struct analogbits_wrpll_cfg *c)
+unsigned int wrpll_calc_max_lock_us(const struct wrpll_cfg *c)
 {
 	return MAX_LOCK_US;
 }
diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c
index 6ffa05b..5806d48 100644
--- a/drivers/clk/clk_stm32mp1.c
+++ b/drivers/clk/clk_stm32mp1.c
@@ -300,6 +300,7 @@
 	_DSI_SEL,
 	_ADC12_SEL,
 	_SPI1_SEL,
+	_RTC_SEL,
 	_PARENT_SEL_NB,
 	_UNKNOWN_SEL = 0xff,
 };
@@ -534,6 +535,7 @@
 	STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL),
 
 	STM32MP1_CLK_SET_CLR(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5),
 	STM32MP1_CLK_SET_CLR(RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL),
 
 	STM32MP1_CLK_SET_CLR_F(RCC_MP_AHB2ENSETR, 5, ADC12, _HCLK2),
@@ -569,6 +571,8 @@
 	STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL),
 
 	STM32MP1_CLK(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL),
+
+	STM32MP1_CLK(RCC_BDCR, 20, RTC, _RTC_SEL),
 };
 
 static const u8 i2c12_parents[] = {_PCLK1, _PLL4_R, _HSI_KER, _CSI_KER};
@@ -594,6 +598,7 @@
 static const u8 adc_parents[] = {_PLL4_R, _CK_PER, _PLL3_Q};
 static const u8 spi_parents[] = {_PLL4_P, _PLL3_Q, _I2S_CKIN, _CK_PER,
 				 _PLL3_R};
+static const u8 rtc_parents[] = {_UNKNOWN_ID, _LSE, _LSI, _HSE};
 
 static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
 	STM32MP1_CLK_PARENT(_I2C12_SEL, RCC_I2C12CKSELR, 0, 0x7, i2c12_parents),
@@ -619,6 +624,9 @@
 	STM32MP1_CLK_PARENT(_DSI_SEL, RCC_DSICKSELR, 0, 0x1, dsi_parents),
 	STM32MP1_CLK_PARENT(_ADC12_SEL, RCC_ADCCKSELR, 0, 0x1, adc_parents),
 	STM32MP1_CLK_PARENT(_SPI1_SEL, RCC_SPI2S1CKSELR, 0, 0x7, spi_parents),
+	STM32MP1_CLK_PARENT(_RTC_SEL, RCC_BDCR, RCC_BDCR_RTCSRC_SHIFT,
+			    (RCC_BDCR_RTCSRC_MASK >> RCC_BDCR_RTCSRC_SHIFT),
+			    rtc_parents),
 };
 
 #ifdef STM32MP1_CLOCK_TREE_INIT
@@ -734,6 +742,7 @@
 	[_DSI_SEL] = "DSI",
 	[_ADC12_SEL] = "ADC12",
 	[_SPI1_SEL] = "SPI1",
+	[_RTC_SEL] = "RTC",
 };
 
 static const struct stm32mp1_clk_data stm32mp1_data = {
diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c
index aa6a8ad..d9950c1 100644
--- a/drivers/clk/rockchip/clk_rk3399.c
+++ b/drivers/clk/rockchip/clk_rk3399.c
@@ -38,8 +38,8 @@
 };
 
 #define RATE_TO_DIV(input_rate, output_rate) \
-	((input_rate) / (output_rate) - 1);
-#define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
+	((input_rate) / (output_rate) - 1)
+#define DIV_TO_RATE(input_rate, div)		((input_rate) / ((div) + 1))
 
 #define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\
 	.refdiv = _refdiv,\
@@ -53,15 +53,15 @@
 static const struct pll_div ppll_init_cfg = PLL_DIVISORS(PPLL_HZ, 2, 2, 1);
 #endif
 
-static const struct pll_div apll_l_1600_cfg = PLL_DIVISORS(1600*MHz, 3, 1, 1);
-static const struct pll_div apll_l_600_cfg = PLL_DIVISORS(600*MHz, 1, 2, 1);
+static const struct pll_div apll_l_1600_cfg = PLL_DIVISORS(1600 * MHz, 3, 1, 1);
+static const struct pll_div apll_l_600_cfg = PLL_DIVISORS(600 * MHz, 1, 2, 1);
 
 static const struct pll_div *apll_l_cfgs[] = {
 	[APLL_L_1600_MHZ] = &apll_l_1600_cfg,
 	[APLL_L_600_MHZ] = &apll_l_600_cfg,
 };
 
-static const struct pll_div apll_b_600_cfg = PLL_DIVISORS(600*MHz, 1, 2, 1);
+static const struct pll_div apll_b_600_cfg = PLL_DIVISORS(600 * MHz, 1, 2, 1);
 static const struct pll_div *apll_b_cfgs[] = {
 	[APLL_B_600_MHZ] = &apll_b_600_cfg,
 };
@@ -393,7 +393,7 @@
 		fref_khz = ref_khz / refdiv;
 
 		fbdiv = vco_khz / fref_khz;
-		if ((fbdiv >= max_fbdiv) || (fbdiv <= min_fbdiv))
+		if (fbdiv >= max_fbdiv || fbdiv <= min_fbdiv)
 			continue;
 		diff_khz = vco_khz - fbdiv * fref_khz;
 		if (fbdiv + 1 < max_fbdiv && diff_khz > fref_khz / 2) {
@@ -409,7 +409,7 @@
 		div->fbdiv = fbdiv;
 	}
 
-	if (best_diff_khz > 4 * (MHz/KHz)) {
+	if (best_diff_khz > 4 * (MHz / KHz)) {
 		printf("%s: Failed to match output frequency %u, "
 		       "difference is %u Hz,exceed 4MHZ\n", __func__, freq_hz,
 		       best_diff_khz * KHz);
@@ -489,28 +489,21 @@
 }
 
 #define I2C_CLK_REG_MASK(bus) \
-			(I2C_DIV_CON_MASK << \
-			CLK_I2C ##bus## _DIV_CON_SHIFT | \
-			CLK_I2C_PLL_SEL_MASK << \
-			CLK_I2C ##bus## _PLL_SEL_SHIFT)
+	(I2C_DIV_CON_MASK << CLK_I2C ##bus## _DIV_CON_SHIFT | \
+	 CLK_I2C_PLL_SEL_MASK << CLK_I2C ##bus## _PLL_SEL_SHIFT)
 
 #define I2C_CLK_REG_VALUE(bus, clk_div) \
-			      ((clk_div - 1) << \
-					CLK_I2C ##bus## _DIV_CON_SHIFT | \
-			      CLK_I2C_PLL_SEL_GPLL << \
-					CLK_I2C ##bus## _PLL_SEL_SHIFT)
+	((clk_div - 1) << CLK_I2C ##bus## _DIV_CON_SHIFT | \
+	 CLK_I2C_PLL_SEL_GPLL << CLK_I2C ##bus## _PLL_SEL_SHIFT)
 
 #define I2C_CLK_DIV_VALUE(con, bus) \
-			(con >> CLK_I2C ##bus## _DIV_CON_SHIFT) & \
-				I2C_DIV_CON_MASK;
+	((con >> CLK_I2C ##bus## _DIV_CON_SHIFT) & I2C_DIV_CON_MASK)
 
 #define I2C_PMUCLK_REG_MASK(bus) \
-			(I2C_DIV_CON_MASK << \
-			 CLK_I2C ##bus## _DIV_CON_SHIFT)
+	(I2C_DIV_CON_MASK << CLK_I2C ##bus## _DIV_CON_SHIFT)
 
 #define I2C_PMUCLK_REG_VALUE(bus, clk_div) \
-				((clk_div - 1) << \
-				CLK_I2C ##bus## _DIV_CON_SHIFT)
+	((clk_div - 1) << CLK_I2C ##bus## _DIV_CON_SHIFT)
 
 static ulong rk3399_i2c_get_clk(struct rk3399_cru *cru, ulong clk_id)
 {
@@ -597,9 +590,9 @@
  */
 
 struct spi_clkreg {
-	uint8_t reg;  /* CLKSEL_CON[reg] register in CRU */
-	uint8_t div_shift;
-	uint8_t sel_shift;
+	u8 reg;  /* CLKSEL_CON[reg] register in CRU */
+	u8 div_shift;
+	u8 sel_shift;
 };
 
 /*
@@ -678,7 +671,7 @@
 static ulong rk3399_vop_set_clk(struct rk3399_cru *cru, ulong clk_id, u32 hz)
 {
 	struct pll_div vpll_config = {0};
-	int aclk_vop = 198*MHz;
+	int aclk_vop = 198 * MHz;
 	void *aclkreg_addr, *dclkreg_addr;
 	u32 div;
 
@@ -710,7 +703,7 @@
 	rkclk_set_pll(&cru->vpll_con[0], &vpll_config);
 
 	rk_clrsetreg(dclkreg_addr,
-		     DCLK_VOP_DCLK_SEL_MASK | DCLK_VOP_PLL_SEL_MASK|
+		     DCLK_VOP_DCLK_SEL_MASK | DCLK_VOP_PLL_SEL_MASK |
 		     DCLK_VOP_DIV_CON_MASK,
 		     DCLK_VOP_DCLK_SEL_DIVOUT << DCLK_VOP_DCLK_SEL_SHIFT |
 		     DCLK_VOP_PLL_SEL_VPLL << DCLK_VOP_PLL_SEL_SHIFT |
@@ -750,7 +743,7 @@
 				ulong clk_id, ulong set_rate)
 {
 	int src_clk_div;
-	int aclk_emmc = 198*MHz;
+	int aclk_emmc = 198 * MHz;
 
 	switch (clk_id) {
 	case HCLK_SDMMC:
@@ -776,7 +769,7 @@
 		break;
 	case SCLK_EMMC:
 		/* Select aclk_emmc source from GPLL */
-		src_clk_div = DIV_ROUND_UP(GPLL_HZ , aclk_emmc);
+		src_clk_div = DIV_ROUND_UP(GPLL_HZ, aclk_emmc);
 		assert(src_clk_div - 1 < 32);
 
 		rk_clrsetreg(&cru->clksel_con[21],
@@ -834,23 +827,31 @@
 
 	/*  clk_ddrc == DPLL = 24MHz / refdiv * fbdiv / postdiv1 / postdiv2 */
 	switch (set_rate) {
-	case 200*MHz:
+	case 50 * MHz:
+		dpll_cfg = (struct pll_div)
+		{.refdiv = 1, .fbdiv = 12, .postdiv1 = 3, .postdiv2 = 2};
+		break;
+	case 200 * MHz:
 		dpll_cfg = (struct pll_div)
 		{.refdiv = 1, .fbdiv = 50, .postdiv1 = 6, .postdiv2 = 1};
 		break;
-	case 300*MHz:
+	case 300 * MHz:
 		dpll_cfg = (struct pll_div)
 		{.refdiv = 2, .fbdiv = 100, .postdiv1 = 4, .postdiv2 = 1};
 		break;
-	case 666*MHz:
+	case 400 * MHz:
+		dpll_cfg = (struct pll_div)
+		{.refdiv = 1, .fbdiv = 50, .postdiv1 = 3, .postdiv2 = 1};
+		break;
+	case 666 * MHz:
 		dpll_cfg = (struct pll_div)
 		{.refdiv = 2, .fbdiv = 111, .postdiv1 = 2, .postdiv2 = 1};
 		break;
-	case 800*MHz:
+	case 800 * MHz:
 		dpll_cfg = (struct pll_div)
 		{.refdiv = 1, .fbdiv = 100, .postdiv1 = 3, .postdiv2 = 1};
 		break;
-	case 933*MHz:
+	case 933 * MHz:
 		dpll_cfg = (struct pll_div)
 		{.refdiv = 1, .fbdiv = 116, .postdiv1 = 3, .postdiv2 = 1};
 		break;
@@ -916,7 +917,6 @@
 	case SCLK_UART2:
 	case SCLK_UART3:
 		return 24000000;
-		break;
 	case PCLK_HDMI_CTRL:
 		break;
 	case DCLK_VOP0:
@@ -1014,7 +1014,8 @@
 	return ret;
 }
 
-static int __maybe_unused rk3399_gmac_set_parent(struct clk *clk, struct clk *parent)
+static int __maybe_unused rk3399_gmac_set_parent(struct clk *clk,
+						 struct clk *parent)
 {
 	struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
 	const char *clock_output_name;
@@ -1024,7 +1025,7 @@
 	 * If the requested parent is in the same clock-controller and
 	 * the id is SCLK_MAC ("clk_gmac"), switch to the internal clock.
 	 */
-	if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC)) {
+	if (parent->dev == clk->dev && parent->id == SCLK_MAC) {
 		debug("%s: switching RGMII to SCLK_MAC\n", __func__);
 		rk_clrreg(&priv->cru->clksel_con[19], BIT(4));
 		return 0;
@@ -1049,7 +1050,8 @@
 	return -EINVAL;
 }
 
-static int __maybe_unused rk3399_clk_set_parent(struct clk *clk, struct clk *parent)
+static int __maybe_unused rk3399_clk_set_parent(struct clk *clk,
+						struct clk *parent)
 {
 	switch (clk->id) {
 	case SCLK_RMII_SRC:
@@ -1078,6 +1080,18 @@
 	case PCLK_GMAC:
 		/* Required to successfully probe the Designware GMAC driver */
 		return 0;
+
+	case SCLK_USB3OTG0_REF:
+	case SCLK_USB3OTG1_REF:
+	case SCLK_USB3OTG0_SUSPEND:
+	case SCLK_USB3OTG1_SUSPEND:
+	case ACLK_USB3OTG0:
+	case ACLK_USB3OTG1:
+	case ACLK_USB3_RKSOC_AXI_PERF:
+	case ACLK_USB3:
+	case ACLK_USB3_GRF:
+		/* Required to successfully probe the Designware USB3 driver */
+		return 0;
 	}
 
 	debug("%s: unsupported clk %ld\n", __func__, clk->id);
diff --git a/drivers/clk/sifive/Kconfig b/drivers/clk/sifive/Kconfig
index 644881b..c4d0a1f 100644
--- a/drivers/clk/sifive/Kconfig
+++ b/drivers/clk/sifive/Kconfig
@@ -1,8 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 
-config CLK_ANALOGBITS_WRPLL_CLN28HPC
-	bool
-
 config CLK_SIFIVE
 	bool "SiFive SoC driver support"
 	depends on CLK
@@ -17,10 +14,3 @@
 	  Supports the Power Reset Clock interface (PRCI) IP block found in
 	  FU540 SoCs.  If this kernel is meant to run on a SiFive FU540 SoC,
 	  enable this driver.
-
-config CLK_SIFIVE_GEMGXL_MGMT
-	bool "GEMGXL management for SiFive FU540 SoCs"
-	depends on CLK_SIFIVE
-	help
-	  Supports the GEMGXL management IP block found in FU540 SoCs to
-	  control GEM TX clock operation mode for 10/100/1000 Mbps.
diff --git a/drivers/clk/sifive/Makefile b/drivers/clk/sifive/Makefile
index f8263e7..b224279 100644
--- a/drivers/clk/sifive/Makefile
+++ b/drivers/clk/sifive/Makefile
@@ -1,7 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0+
 
-obj-$(CONFIG_CLK_ANALOGBITS_WRPLL_CLN28HPC)	+= wrpll-cln28hpc.o
-
 obj-$(CONFIG_CLK_SIFIVE_FU540_PRCI)		+= fu540-prci.o
-
-obj-$(CONFIG_CLK_SIFIVE_GEMGXL_MGMT)		+= gemgxl-mgmt.o
diff --git a/drivers/clk/sifive/analogbits-wrpll-cln28hpc.h b/drivers/clk/sifive/analogbits-wrpll-cln28hpc.h
deleted file mode 100644
index 4432e24..0000000
--- a/drivers/clk/sifive/analogbits-wrpll-cln28hpc.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) 2019 Western Digital Corporation or its affiliates.
- *
- * Copyright (C) 2018 SiFive, Inc.
- * Wesley Terpstra
- * Paul Walmsley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 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 __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H
-#define __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H
-
-#include <linux/types.h>
-
-/* DIVQ_VALUES: number of valid DIVQ values */
-#define DIVQ_VALUES				6
-
-/*
- * Bit definitions for struct analogbits_wrpll_cfg.flags
- *
- * WRPLL_FLAGS_BYPASS_FLAG: if set, the PLL is either in bypass, or should be
- *	programmed to enter bypass
- * WRPLL_FLAGS_RESET_FLAG: if set, the PLL is in reset
- * WRPLL_FLAGS_INT_FEEDBACK_FLAG: if set, the PLL is configured for internal
- *	feedback mode
- * WRPLL_FLAGS_EXT_FEEDBACK_FLAG: if set, the PLL is configured for external
- *	feedback mode (not yet supported by this driver)
- *
- * The flags WRPLL_FLAGS_INT_FEEDBACK_FLAG and WRPLL_FLAGS_EXT_FEEDBACK_FLAG are
- * mutually exclusive.  If both bits are set, or both are zero, the struct
- * analogbits_wrpll_cfg record is uninitialized or corrupt.
- */
-#define WRPLL_FLAGS_BYPASS_SHIFT		0
-#define WRPLL_FLAGS_BYPASS_MASK		BIT(WRPLL_FLAGS_BYPASS_SHIFT)
-#define WRPLL_FLAGS_RESET_SHIFT		1
-#define WRPLL_FLAGS_RESET_MASK		BIT(WRPLL_FLAGS_RESET_SHIFT)
-#define WRPLL_FLAGS_INT_FEEDBACK_SHIFT	2
-#define WRPLL_FLAGS_INT_FEEDBACK_MASK	BIT(WRPLL_FLAGS_INT_FEEDBACK_SHIFT)
-#define WRPLL_FLAGS_EXT_FEEDBACK_SHIFT	3
-#define WRPLL_FLAGS_EXT_FEEDBACK_MASK	BIT(WRPLL_FLAGS_EXT_FEEDBACK_SHIFT)
-
-/**
- * struct analogbits_wrpll_cfg - WRPLL configuration values
- * @divr: reference divider value (6 bits), as presented to the PLL signals.
- * @divf: feedback divider value (9 bits), as presented to the PLL signals.
- * @divq: output divider value (3 bits), as presented to the PLL signals.
- * @flags: PLL configuration flags.  See above for more information.
- * @range: PLL loop filter range.  See below for more information.
- * @_output_rate_cache: cached output rates, swept across DIVQ.
- * @_parent_rate: PLL refclk rate for which values are valid
- * @_max_r: maximum possible R divider value, given @parent_rate
- * @_init_r: initial R divider value to start the search from
- *
- * @divr, @divq, @divq, @range represent what the PLL expects to see
- * on its input signals.  Thus @divr and @divf are the actual divisors
- * minus one.  @divq is a power-of-two divider; for example, 1 =
- * divide-by-2 and 6 = divide-by-64.  0 is an invalid @divq value.
- *
- * When initially passing a struct analogbits_wrpll_cfg record, the
- * record should be zero-initialized with the exception of the @flags
- * field.  The only flag bits that need to be set are either
- * WRPLL_FLAGS_INT_FEEDBACK or WRPLL_FLAGS_EXT_FEEDBACK.
- *
- * Field names beginning with an underscore should be considered
- * private to the wrpll-cln28hpc.c code.
- */
-struct analogbits_wrpll_cfg {
-	u8 divr;
-	u8 divq;
-	u8 range;
-	u8 flags;
-	u16 divf;
-	u32 _output_rate_cache[DIVQ_VALUES];
-	unsigned long _parent_rate;
-	u8 _max_r;
-	u8 _init_r;
-};
-
-/*
- * Function prototypes
- */
-
-int analogbits_wrpll_configure_for_rate(struct analogbits_wrpll_cfg *c,
-					u32 target_rate,
-					unsigned long parent_rate);
-
-unsigned int analogbits_wrpll_calc_max_lock_us(struct analogbits_wrpll_cfg *c);
-
-unsigned long analogbits_wrpll_calc_output_rate(struct analogbits_wrpll_cfg *c,
-						unsigned long parent_rate);
-
-#endif /* __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H */
diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c
index 2d47ebc..ce0769f 100644
--- a/drivers/clk/sifive/fu540-prci.c
+++ b/drivers/clk/sifive/fu540-prci.c
@@ -37,9 +37,8 @@
 #include <errno.h>
 
 #include <linux/math64.h>
-#include <dt-bindings/clk/sifive-fu540-prci.h>
-
-#include "analogbits-wrpll-cln28hpc.h"
+#include <linux/clk/analogbits-wrpll-cln28hpc.h>
+#include <dt-bindings/clock/sifive-fu540-prci.h>
 
 /*
  * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects:
@@ -159,30 +158,32 @@
  * PRCI per-device instance data
  */
 struct __prci_data {
-	void *base;
-	struct clk parent;
+	void *va;
+	struct clk parent_hfclk;
+	struct clk parent_rtcclk;
 };
 
 /**
  * struct __prci_wrpll_data - WRPLL configuration and integration data
  * @c: WRPLL current configuration record
- * @bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL)
- * @no_bypass: fn ptr to code to not bypass the WRPLL (if applicable; else NULL)
+ * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL)
+ * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
  * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address
  *
- * @bypass and @no_bypass are used for WRPLL instances that contain a separate
- * external glitchless clock mux downstream from the PLL.  The WRPLL internal
- * bypass mux is not glitchless.
+ * @enable_bypass and @disable_bypass are used for WRPLL instances
+ * that contain a separate external glitchless clock mux downstream
+ * from the PLL.  The WRPLL internal bypass mux is not glitchless.
  */
 struct __prci_wrpll_data {
-	struct analogbits_wrpll_cfg c;
-	void (*bypass)(struct __prci_data *pd);
-	void (*no_bypass)(struct __prci_data *pd);
+	struct wrpll_cfg c;
+	void (*enable_bypass)(struct __prci_data *pd);
+	void (*disable_bypass)(struct __prci_data *pd);
 	u8 cfg0_offs;
 };
 
 struct __prci_clock;
 
+/* struct __prci_clock_ops - clock operations */
 struct __prci_clock_ops {
 	int (*set_rate)(struct __prci_clock *pc,
 			unsigned long rate,
@@ -198,8 +199,7 @@
  * struct __prci_clock - describes a clock device managed by PRCI
  * @name: user-readable clock name string - should match the manual
  * @parent_name: parent name for this clock
- * @ops: struct clk_ops for the Linux clock framework to use for control
- * @hw: Linux-private clock data
+ * @ops: struct __prci_clock_ops for control
  * @pwd: WRPLL-specific data, associated with this clock (if not NULL)
  * @pd: PRCI-specific data associated with this clock (if not NULL)
  *
@@ -233,19 +233,19 @@
  */
 static u32 __prci_readl(struct __prci_data *pd, u32 offs)
 {
-	return readl(pd->base + offs);
+	return readl(pd->va + offs);
 }
 
 static void __prci_writel(u32 v, u32 offs, struct __prci_data *pd)
 {
-	return writel(v, pd->base + offs);
+	writel(v, pd->va + offs);
 }
 
 /* WRPLL-related private functions */
 
 /**
  * __prci_wrpll_unpack() - unpack WRPLL configuration registers into parameters
- * @c: ptr to a struct analogbits_wrpll_cfg record to write config into
+ * @c: ptr to a struct wrpll_cfg record to write config into
  * @r: value read from the PRCI PLL configuration register
  *
  * Given a value @r read from an FU540 PRCI PLL configuration register,
@@ -257,7 +257,7 @@
  *
  * Context: Any context.
  */
-static void __prci_wrpll_unpack(struct analogbits_wrpll_cfg *c, u32 r)
+static void __prci_wrpll_unpack(struct wrpll_cfg *c, u32 r)
 {
 	u32 v;
 
@@ -280,15 +280,13 @@
 	c->flags &= (WRPLL_FLAGS_INT_FEEDBACK_MASK |
 		     WRPLL_FLAGS_EXT_FEEDBACK_MASK);
 
-	if (r & PRCI_COREPLLCFG0_FSE_MASK)
-		c->flags |= WRPLL_FLAGS_INT_FEEDBACK_MASK;
-	else
-		c->flags |= WRPLL_FLAGS_EXT_FEEDBACK_MASK;
+	/* external feedback mode not supported */
+	c->flags |= WRPLL_FLAGS_INT_FEEDBACK_MASK;
 }
 
 /**
  * __prci_wrpll_pack() - pack PLL configuration parameters into a register value
- * @c: pointer to a struct analogbits_wrpll_cfg record containing the PLL's cfg
+ * @c: pointer to a struct wrpll_cfg record containing the PLL's cfg
  *
  * Using a set of WRPLL configuration values pointed to by @c,
  * assemble a PRCI PLL configuration register value, and return it to
@@ -301,7 +299,7 @@
  * Returns: a value suitable for writing into a PRCI PLL configuration
  *          register
  */
-static u32 __prci_wrpll_pack(struct analogbits_wrpll_cfg *c)
+static u32 __prci_wrpll_pack(const struct wrpll_cfg *c)
 {
 	u32 r = 0;
 
@@ -309,8 +307,9 @@
 	r |= c->divf << PRCI_COREPLLCFG0_DIVF_SHIFT;
 	r |= c->divq << PRCI_COREPLLCFG0_DIVQ_SHIFT;
 	r |= c->range << PRCI_COREPLLCFG0_RANGE_SHIFT;
-	if (c->flags & WRPLL_FLAGS_INT_FEEDBACK_MASK)
-		r |= PRCI_COREPLLCFG0_FSE_MASK;
+
+	/* external feedback mode not supported */
+	r |= PRCI_COREPLLCFG0_FSE_MASK;
 
 	return r;
 }
@@ -349,11 +348,11 @@
  */
 static void __prci_wrpll_write_cfg(struct __prci_data *pd,
 				   struct __prci_wrpll_data *pwd,
-				   struct analogbits_wrpll_cfg *c)
+				   struct wrpll_cfg *c)
 {
 	__prci_writel(__prci_wrpll_pack(c), pwd->cfg0_offs, pd);
 
-	memcpy(&pwd->c, c, sizeof(struct analogbits_wrpll_cfg));
+	memcpy(&pwd->c, c, sizeof(*c));
 }
 
 /* Core clock mux control */
@@ -404,7 +403,7 @@
 {
 	struct __prci_wrpll_data *pwd = pc->pwd;
 
-	return analogbits_wrpll_calc_output_rate(&pwd->c, parent_rate);
+	return wrpll_calc_output_rate(&pwd->c, parent_rate);
 }
 
 static unsigned long sifive_fu540_prci_wrpll_round_rate(
@@ -413,13 +412,13 @@
 						unsigned long *parent_rate)
 {
 	struct __prci_wrpll_data *pwd = pc->pwd;
-	struct analogbits_wrpll_cfg c;
+	struct wrpll_cfg c;
 
 	memcpy(&c, &pwd->c, sizeof(c));
 
-	analogbits_wrpll_configure_for_rate(&c, rate, *parent_rate);
+	wrpll_configure_for_rate(&c, rate, *parent_rate);
 
-	return analogbits_wrpll_calc_output_rate(&c, *parent_rate);
+	return wrpll_calc_output_rate(&c, *parent_rate);
 }
 
 static int sifive_fu540_prci_wrpll_set_rate(struct __prci_clock *pc,
@@ -430,19 +429,19 @@
 	struct __prci_data *pd = pc->pd;
 	int r;
 
-	r = analogbits_wrpll_configure_for_rate(&pwd->c, rate, parent_rate);
+	r = wrpll_configure_for_rate(&pwd->c, rate, parent_rate);
 	if (r)
-		return -ERANGE;
+		return r;
 
-	if (pwd->bypass)
-		pwd->bypass(pd);
+	if (pwd->enable_bypass)
+		pwd->enable_bypass(pd);
 
 	__prci_wrpll_write_cfg(pd, pwd, &pwd->c);
 
-	udelay(analogbits_wrpll_calc_max_lock_us(&pwd->c));
+	udelay(wrpll_calc_max_lock_us(&pwd->c));
 
-	if (pwd->no_bypass)
-		pwd->no_bypass(pd);
+	if (pwd->disable_bypass)
+		pwd->disable_bypass(pd);
 
 	return 0;
 }
@@ -484,8 +483,8 @@
 
 static struct __prci_wrpll_data __prci_corepll_data = {
 	.cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
-	.bypass = __prci_coreclksel_use_hfclk,
-	.no_bypass = __prci_coreclksel_use_corepll,
+	.enable_bypass = __prci_coreclksel_use_hfclk,
+	.disable_bypass = __prci_coreclksel_use_corepll,
 };
 
 static struct __prci_wrpll_data __prci_ddrpll_data = {
@@ -526,6 +525,27 @@
 	},
 };
 
+static ulong sifive_fu540_prci_parent_rate(struct __prci_clock *pc)
+{
+	ulong parent_rate;
+	struct __prci_clock *p;
+
+	if (strcmp(pc->parent_name, "corepll") == 0) {
+		p = &__prci_init_clocks[PRCI_CLK_COREPLL];
+		if (!p->pd || !p->ops->recalc_rate)
+			return -ENXIO;
+
+		return p->ops->recalc_rate(p, sifive_fu540_prci_parent_rate(p));
+	}
+
+	if (strcmp(pc->parent_name, "rtcclk") == 0)
+		parent_rate = clk_get_rate(&pc->pd->parent_rtcclk);
+	else
+		parent_rate = clk_get_rate(&pc->pd->parent_hfclk);
+
+	return parent_rate;
+}
+
 static ulong sifive_fu540_prci_get_rate(struct clk *clk)
 {
 	struct __prci_clock *pc;
@@ -537,7 +557,7 @@
 	if (!pc->pd || !pc->ops->recalc_rate)
 		return -ENXIO;
 
-	return pc->ops->recalc_rate(pc, clk_get_rate(&pc->pd->parent));
+	return pc->ops->recalc_rate(pc, sifive_fu540_prci_parent_rate(pc));
 }
 
 static ulong sifive_fu540_prci_set_rate(struct clk *clk, ulong rate)
@@ -552,7 +572,7 @@
 	if (!pc->pd || !pc->ops->set_rate)
 		return -ENXIO;
 
-	err = pc->ops->set_rate(pc, rate, clk_get_rate(&pc->pd->parent));
+	err = pc->ops->set_rate(pc, rate, sifive_fu540_prci_parent_rate(pc));
 	if (err)
 		return err;
 
@@ -565,14 +585,18 @@
 	struct __prci_clock *pc;
 	struct __prci_data *pd = dev_get_priv(dev);
 
-	pd->base = (void *)dev_read_addr(dev);
-	if (IS_ERR(pd->base))
-		return PTR_ERR(pd->base);
+	pd->va = (void *)dev_read_addr(dev);
+	if (IS_ERR(pd->va))
+		return PTR_ERR(pd->va);
 
-	err = clk_get_by_index(dev, 0, &pd->parent);
+	err = clk_get_by_index(dev, 0, &pd->parent_hfclk);
 	if (err)
 		return err;
 
+	err = clk_get_by_index(dev, 1, &pd->parent_rtcclk);
+	if (err)
+		return err;
+
 	for (i = 0; i < ARRAY_SIZE(__prci_init_clocks); ++i) {
 		pc = &__prci_init_clocks[i];
 		pc->pd = pd;
@@ -589,8 +613,7 @@
 };
 
 static const struct udevice_id sifive_fu540_prci_ids[] = {
-	{ .compatible = "sifive,fu540-c000-prci0" },
-	{ .compatible = "sifive,aloeprci0" },
+	{ .compatible = "sifive,fu540-c000-prci" },
 	{ }
 };
 
diff --git a/drivers/clk/sifive/gemgxl-mgmt.c b/drivers/clk/sifive/gemgxl-mgmt.c
deleted file mode 100644
index eb37416..0000000
--- a/drivers/clk/sifive/gemgxl-mgmt.c
+++ /dev/null
@@ -1,60 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2019, Bin Meng <bmeng.cn@gmail.com>
- */
-
-#include <common.h>
-#include <clk-uclass.h>
-#include <dm.h>
-#include <asm/io.h>
-
-struct gemgxl_mgmt_regs {
-	__u32 tx_clk_sel;
-};
-
-struct gemgxl_mgmt_platdata {
-	struct gemgxl_mgmt_regs *regs;
-};
-
-static int gemgxl_mgmt_ofdata_to_platdata(struct udevice *dev)
-{
-	struct gemgxl_mgmt_platdata *plat = dev_get_platdata(dev);
-
-	plat->regs = (struct gemgxl_mgmt_regs *)dev_read_addr(dev);
-
-	return 0;
-}
-
-static ulong gemgxl_mgmt_set_rate(struct clk *clk, ulong rate)
-{
-	struct gemgxl_mgmt_platdata *plat = dev_get_platdata(clk->dev);
-
-	/*
-	 * GEMGXL TX clock operation mode:
-	 *
-	 * 0 = GMII mode. Use 125 MHz gemgxlclk from PRCI in TX logic
-	 *     and output clock on GMII output signal GTX_CLK
-	 * 1 = MII mode. Use MII input signal TX_CLK in TX logic
-	 */
-	writel(rate != 125000000, &plat->regs->tx_clk_sel);
-
-	return 0;
-}
-
-const struct clk_ops gemgxl_mgmt_ops = {
-	.set_rate = gemgxl_mgmt_set_rate,
-};
-
-static const struct udevice_id gemgxl_mgmt_match[] = {
-	{ .compatible = "sifive,cadencegemgxlmgmt0", },
-	{ /* sentinel */ }
-};
-
-U_BOOT_DRIVER(sifive_gemgxl_mgmt) = {
-	.name = "sifive-gemgxl-mgmt",
-	.id = UCLASS_CLK,
-	.of_match = gemgxl_mgmt_match,
-	.ofdata_to_platdata = gemgxl_mgmt_ofdata_to_platdata,
-	.platdata_auto_alloc_size = sizeof(struct gemgxl_mgmt_platdata),
-	.ops = &gemgxl_mgmt_ops,
-};
diff --git a/drivers/clk/sunxi/clk_h6.c b/drivers/clk/sunxi/clk_h6.c
index 0bb00f4..105c15d 100644
--- a/drivers/clk/sunxi/clk_h6.c
+++ b/drivers/clk/sunxi/clk_h6.c
@@ -28,6 +28,22 @@
 	[CLK_BUS_SPI1]		= GATE(0x96c, BIT(1)),
 
 	[CLK_BUS_EMAC]		= GATE(0x97c, BIT(0)),
+
+	[CLK_USB_PHY0]		= GATE(0xa70, BIT(29)),
+	[CLK_USB_OHCI0]		= GATE(0xa70, BIT(31)),
+
+	[CLK_USB_PHY1]		= GATE(0xa74, BIT(29)),
+
+	[CLK_USB_HSIC]		= GATE(0xa7c, BIT(26)),
+	[CLK_USB_HSIC_12M]	= GATE(0xa7c, BIT(27)),
+	[CLK_USB_PHY3]		= GATE(0xa7c, BIT(29)),
+	[CLK_USB_OHCI3]		= GATE(0xa7c, BIT(31)),
+
+	[CLK_BUS_OHCI0]		= GATE(0xa8c, BIT(0)),
+	[CLK_BUS_OHCI3]		= GATE(0xa8c, BIT(3)),
+	[CLK_BUS_EHCI0]		= GATE(0xa8c, BIT(4)),
+	[CLK_BUS_EHCI3]		= GATE(0xa8c, BIT(7)),
+	[CLK_BUS_OTG]		= GATE(0xa8c, BIT(8)),
 };
 
 static struct ccu_reset h6_resets[] = {
@@ -43,6 +59,19 @@
 	[RST_BUS_SPI1]		= RESET(0x96c, BIT(17)),
 
 	[RST_BUS_EMAC]		= RESET(0x97c, BIT(16)),
+
+	[RST_USB_PHY0]		= RESET(0xa70, BIT(30)),
+
+	[RST_USB_PHY1]		= RESET(0xa74, BIT(30)),
+
+	[RST_USB_HSIC]		= RESET(0xa7c, BIT(28)),
+	[RST_USB_PHY3]		= RESET(0xa7c, BIT(30)),
+
+	[RST_BUS_OHCI0]		= RESET(0xa8c, BIT(16)),
+	[RST_BUS_OHCI3]		= RESET(0xa8c, BIT(19)),
+	[RST_BUS_EHCI0]		= RESET(0xa8c, BIT(20)),
+	[RST_BUS_EHCI3]		= RESET(0xa8c, BIT(23)),
+	[RST_BUS_OTG]		= RESET(0xa8c, BIT(24)),
 };
 
 static const struct ccu_desc h6_ccu_desc = {
diff --git a/drivers/core/of_addr.c b/drivers/core/of_addr.c
index 1bfaaee..4e256d9 100644
--- a/drivers/core/of_addr.c
+++ b/drivers/core/of_addr.c
@@ -318,6 +318,10 @@
 	return __of_translate_address(dev, in_addr, "ranges");
 }
 
+u64 of_translate_dma_address(const struct device_node *dev, const __be32 *in_addr)
+{
+	return __of_translate_address(dev, in_addr, "dma-ranges");
+}
 
 static int __of_address_to_resource(const struct device_node *dev,
 		const __be32 *addrp, u64 size, unsigned int flags,
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index c72c6e2..179a644 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -770,6 +770,14 @@
 		return fdt_translate_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
 }
 
+u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr)
+{
+	if (ofnode_is_np(node))
+		return of_translate_dma_address(ofnode_to_np(node), in_addr);
+	else
+		return fdt_translate_dma_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
+}
+
 int ofnode_device_is_compatible(ofnode node, const char *compat)
 {
 	if (ofnode_is_np(node))
diff --git a/drivers/core/read.c b/drivers/core/read.c
index 6bda077..1a044b0 100644
--- a/drivers/core/read.c
+++ b/drivers/core/read.c
@@ -265,6 +265,11 @@
 	return ofnode_translate_address(dev_ofnode(dev), in_addr);
 }
 
+u64 dev_translate_dma_address(struct udevice *dev, const fdt32_t *in_addr)
+{
+	return ofnode_translate_dma_address(dev_ofnode(dev), in_addr);
+}
+
 int dev_read_alias_highest_id(const char *stem)
 {
 	if (of_live_active())
diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index 5ef0f71..d1d12ee 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -108,6 +108,48 @@
 	return 0;
 }
 
+int regmap_init_mem_index(ofnode node, struct regmap **mapp, int index)
+{
+	struct regmap *map;
+	int addr_len, size_len;
+	int ret;
+
+	addr_len = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
+	if (addr_len < 0) {
+		debug("%s: Error while reading the addr length (ret = %d)\n",
+		      ofnode_get_name(node), addr_len);
+		return addr_len;
+	}
+
+	size_len = ofnode_read_simple_size_cells(ofnode_get_parent(node));
+	if (size_len < 0) {
+		debug("%s: Error while reading the size length: (ret = %d)\n",
+		      ofnode_get_name(node), size_len);
+		return size_len;
+	}
+
+	map = regmap_alloc(1);
+	if (!map)
+		return -ENOMEM;
+
+	ret = init_range(node, map->ranges, addr_len, size_len, index);
+	if (ret)
+		return ret;
+
+	if (ofnode_read_bool(node, "little-endian"))
+		map->endianness = REGMAP_LITTLE_ENDIAN;
+	else if (ofnode_read_bool(node, "big-endian"))
+		map->endianness = REGMAP_BIG_ENDIAN;
+	else if (ofnode_read_bool(node, "native-endian"))
+		map->endianness = REGMAP_NATIVE_ENDIAN;
+	else /* Default: native endianness */
+		map->endianness = REGMAP_NATIVE_ENDIAN;
+
+	*mapp = map;
+
+	return ret;
+}
+
 int regmap_init_mem(ofnode node, struct regmap **mapp)
 {
 	struct regmap_range *range;
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 068c6d0..800584f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -215,6 +215,12 @@
 	  of 'anonymous' GPIOs that do not belong to any device or bank.
 	  Select a suitable value depending on your needs.
 
+config SUNXI_GPIO
+	bool "Allwinner GPIO driver"
+	depends on ARCH_SUNXI
+	help
+	  Support the GPIO device in Allwinner SoCs.
+
 config XILINX_GPIO
 	bool "Xilinx GPIO driver"
 	depends on DM_GPIO
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index cbed8d4..719efc2 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -354,12 +354,14 @@
 	ID("allwinner,sun8i-v3s-pinctrl",	a_all),
 	ID("allwinner,sun9i-a80-pinctrl",	a_all),
 	ID("allwinner,sun50i-a64-pinctrl",	a_all),
+	ID("allwinner,sun50i-h6-pinctrl",	a_all),
 	ID("allwinner,sun6i-a31-r-pinctrl",	l_2),
 	ID("allwinner,sun8i-a23-r-pinctrl",	l_1),
 	ID("allwinner,sun8i-a83t-r-pinctrl",	l_1),
 	ID("allwinner,sun8i-h3-r-pinctrl",	l_1),
 	ID("allwinner,sun9i-a80-r-pinctrl",	l_3),
 	ID("allwinner,sun50i-a64-r-pinctrl",	l_1),
+	ID("allwinner,sun50i-h6-r-pinctrl",	l_2),
 	{ }
 };
 
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 095a9bc..4772db3 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -330,7 +330,7 @@
 
 config SYS_I2C_OMAP24XX
 	bool "TI OMAP2+ I2C driver"
-	depends on ARCH_OMAP2PLUS
+	depends on ARCH_OMAP2PLUS || ARCH_K3
 	help
 	  Add support for the OMAP2+ I2C driver.
 
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 890ef35..4cdae41 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -468,14 +468,15 @@
 
 	  If unsure, say N.
 
-config MMC_SDHCI_K3_ARASAN
-	bool "Arasan SDHCI controller for TI's K3 based SoCs"
+config MMC_SDHCI_AM654
+	bool "SDHCI Controller on TI's Am654 devices"
 	depends on ARCH_K3
 	depends on MMC_SDHCI
 	depends on DM_MMC && OF_CONTROL && BLK
+	depends on REGMAP
 	help
-	  Support for Arasan SDHCI host controller on Texas Instruments'
-	  K3 family based SoC platforms
+	  Support for Secure Digital Host Controller Interface (SDHCI)
+	  controllers present on TI's AM654 SOCs.
 
 config MMC_SDHCI_KONA
 	bool "SDHCI support on Broadcom KONA platform"
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 3c8c53a..6cc018b 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -50,7 +50,7 @@
 obj-$(CONFIG_MMC_SDHCI_BCM2835)		+= bcm2835_sdhci.o
 obj-$(CONFIG_MMC_SDHCI_BCMSTB)		+= bcmstb_sdhci.o
 obj-$(CONFIG_MMC_SDHCI_CADENCE)		+= sdhci-cadence.o
-obj-$(CONFIG_MMC_SDHCI_K3_ARASAN)	+= k3_arsan_sdhci.o
+obj-$(CONFIG_MMC_SDHCI_AM654)		+= am654_sdhci.o
 obj-$(CONFIG_MMC_SDHCI_KONA)		+= kona_sdhci.o
 obj-$(CONFIG_MMC_SDHCI_MSM)		+= msm_sdhci.o
 obj-$(CONFIG_MMC_SDHCI_MV)		+= mv_sdhci.o
diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
new file mode 100644
index 0000000..fb0fb58
--- /dev/null
+++ b/drivers/mmc/am654_sdhci.c
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Texas Instruments' K3 SD Host Controller Interface
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <power-domain.h>
+#include <regmap.h>
+#include <sdhci.h>
+
+/* CTL_CFG Registers */
+#define CTL_CFG_2		0x14
+
+#define SLOTTYPE_MASK		GENMASK(31, 30)
+#define SLOTTYPE_EMBEDDED	BIT(30)
+
+/* PHY Registers */
+#define PHY_CTRL1	0x100
+#define PHY_CTRL2	0x104
+#define PHY_CTRL3	0x108
+#define PHY_CTRL4	0x10C
+#define PHY_CTRL5	0x110
+#define PHY_CTRL6	0x114
+#define PHY_STAT1	0x130
+#define PHY_STAT2	0x134
+
+#define IOMUX_ENABLE_SHIFT	31
+#define IOMUX_ENABLE_MASK	BIT(IOMUX_ENABLE_SHIFT)
+#define OTAPDLYENA_SHIFT	20
+#define OTAPDLYENA_MASK		BIT(OTAPDLYENA_SHIFT)
+#define OTAPDLYSEL_SHIFT	12
+#define OTAPDLYSEL_MASK		GENMASK(15, 12)
+#define STRBSEL_SHIFT		24
+#define STRBSEL_MASK		GENMASK(27, 24)
+#define SEL50_SHIFT		8
+#define SEL50_MASK		BIT(SEL50_SHIFT)
+#define SEL100_SHIFT		9
+#define SEL100_MASK		BIT(SEL100_SHIFT)
+#define DLL_TRIM_ICP_SHIFT	4
+#define DLL_TRIM_ICP_MASK	GENMASK(7, 4)
+#define DR_TY_SHIFT		20
+#define DR_TY_MASK		GENMASK(22, 20)
+#define ENDLL_SHIFT		1
+#define ENDLL_MASK		BIT(ENDLL_SHIFT)
+#define DLLRDY_SHIFT		0
+#define DLLRDY_MASK		BIT(DLLRDY_SHIFT)
+#define PDB_SHIFT		0
+#define PDB_MASK		BIT(PDB_SHIFT)
+#define CALDONE_SHIFT		1
+#define CALDONE_MASK		BIT(CALDONE_SHIFT)
+#define RETRIM_SHIFT		17
+#define RETRIM_MASK		BIT(RETRIM_SHIFT)
+
+#define DRIVER_STRENGTH_50_OHM	0x0
+#define DRIVER_STRENGTH_33_OHM	0x1
+#define DRIVER_STRENGTH_66_OHM	0x2
+#define DRIVER_STRENGTH_100_OHM	0x3
+#define DRIVER_STRENGTH_40_OHM	0x4
+
+#define AM654_SDHCI_MIN_FREQ	400000
+
+struct am654_sdhci_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+	struct regmap *base;
+	bool non_removable;
+	u32 otap_del_sel;
+	u32 trm_icp;
+	u32 drv_strength;
+	bool dll_on;
+};
+
+static void am654_sdhci_set_control_reg(struct sdhci_host *host)
+{
+	struct mmc *mmc = (struct mmc *)host->mmc;
+	u32 reg;
+
+	if (IS_SD(host->mmc) &&
+	    mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
+		reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+		reg |= SDHCI_CTRL_VDD_180;
+		sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
+	}
+
+	sdhci_set_uhs_timing(host);
+}
+
+static int am654_sdhci_set_ios_post(struct sdhci_host *host)
+{
+	struct udevice *dev = host->mmc->dev;
+	struct am654_sdhci_plat *plat = dev_get_platdata(dev);
+	unsigned int speed = host->mmc->clock;
+	int sel50, sel100;
+	u32 mask, val;
+	int ret;
+
+	/* Reset SD Clock Enable */
+	val = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+	val &= ~SDHCI_CLOCK_CARD_EN;
+	sdhci_writew(host, val, SDHCI_CLOCK_CONTROL);
+
+	/* power off phy */
+	if (plat->dll_on) {
+		regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK, 0);
+
+		plat->dll_on = false;
+	}
+
+	/* restart clock */
+	sdhci_set_clock(host->mmc, speed);
+
+	/* switch phy back on */
+	if (speed > AM654_SDHCI_MIN_FREQ) {
+		mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
+		val = (1 << OTAPDLYENA_SHIFT) |
+		      (plat->otap_del_sel << OTAPDLYSEL_SHIFT);
+		regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
+		switch (speed) {
+		case 200000000:
+			sel50 = 0;
+			sel100 = 0;
+			break;
+		case 100000000:
+			sel50 = 0;
+			sel100 = 1;
+			break;
+		default:
+			sel50 = 1;
+			sel100 = 0;
+		}
+
+		/* Configure PHY DLL frequency */
+		mask = SEL50_MASK | SEL100_MASK;
+		val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT);
+		regmap_update_bits(plat->base, PHY_CTRL5, mask, val);
+
+		/* Enable DLL */
+		regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK,
+				   0x1 << ENDLL_SHIFT);
+		/*
+		 * Poll for DLL ready. Use a one second timeout.
+		 * Works in all experiments done so far
+		 */
+		ret = regmap_read_poll_timeout(plat->base, PHY_STAT1, val,
+					 val & DLLRDY_MASK, 1000, 1000000);
+		if (ret)
+			return ret;
+
+		plat->dll_on = true;
+	}
+
+	return 0;
+}
+
+const struct sdhci_ops am654_sdhci_ops = {
+	.set_ios_post		= &am654_sdhci_set_ios_post,
+	.set_control_reg	= &am654_sdhci_set_control_reg,
+};
+
+int am654_sdhci_init(struct am654_sdhci_plat *plat)
+{
+	u32 ctl_cfg_2 = 0;
+	u32 mask, val;
+	int ret;
+
+	/* Reset OTAP to default value */
+	mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
+	regmap_update_bits(plat->base, PHY_CTRL4, mask, 0x0);
+
+	regmap_read(plat->base, PHY_STAT1, &val);
+	if (~val & CALDONE_MASK) {
+		/* Calibrate IO lines */
+		regmap_update_bits(plat->base, PHY_CTRL1, PDB_MASK, PDB_MASK);
+		ret = regmap_read_poll_timeout(plat->base, PHY_STAT1, val,
+					       val & CALDONE_MASK, 1, 20);
+		if (ret)
+			return ret;
+	}
+
+	/* Configure DLL TRIM */
+	mask = DLL_TRIM_ICP_MASK;
+	val = plat->trm_icp << DLL_TRIM_ICP_SHIFT;
+
+	/* Configure DLL driver strength */
+	mask |= DR_TY_MASK;
+	val |= plat->drv_strength << DR_TY_SHIFT;
+	regmap_update_bits(plat->base, PHY_CTRL1, mask, val);
+
+	/* Enable pins by setting IO mux to 0 */
+	regmap_update_bits(plat->base, PHY_CTRL1, IOMUX_ENABLE_MASK, 0);
+
+	/* Set slot type based on SD or eMMC */
+	if (plat->non_removable)
+		ctl_cfg_2 = SLOTTYPE_EMBEDDED;
+
+	regmap_update_bits(plat->base, CTL_CFG_2, SLOTTYPE_MASK, ctl_cfg_2);
+
+	return 0;
+}
+
+static int am654_sdhci_probe(struct udevice *dev)
+{
+	struct am654_sdhci_plat *plat = dev_get_platdata(dev);
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct sdhci_host *host = dev_get_priv(dev);
+	struct mmc_config *cfg = &plat->cfg;
+	struct power_domain sdhci_pwrdmn;
+	struct clk clk;
+	unsigned long clock;
+	int ret;
+
+	ret = power_domain_get_by_index(dev, &sdhci_pwrdmn, 0);
+	if (!ret) {
+		ret = power_domain_on(&sdhci_pwrdmn);
+		if (ret) {
+			dev_err(dev, "Power domain on failed (%d)\n", ret);
+			return ret;
+		}
+	} else if (ret != -ENOENT && ret != -ENODEV && ret != -ENOSYS) {
+		dev_err(dev, "failed to get power domain (%d)\n", ret);
+		return ret;
+	}
+
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret) {
+		dev_err(dev, "failed to get clock\n");
+		return ret;
+	}
+
+	clock = clk_get_rate(&clk);
+	if (IS_ERR_VALUE(clock)) {
+		dev_err(dev, "failed to get rate\n");
+		return clock;
+	}
+
+	host->max_clk = clock;
+	host->mmc = &plat->mmc;
+	host->mmc->dev = dev;
+	ret = sdhci_setup_cfg(cfg, host, cfg->f_max,
+			      AM654_SDHCI_MIN_FREQ);
+	if (ret)
+		return ret;
+	host->ops = &am654_sdhci_ops;
+	host->mmc->priv = host;
+	upriv->mmc = host->mmc;
+
+	regmap_init_mem_index(dev_ofnode(dev), &plat->base, 1);
+
+	am654_sdhci_init(plat);
+
+	return sdhci_probe(dev);
+}
+
+static int am654_sdhci_ofdata_to_platdata(struct udevice *dev)
+{
+	struct am654_sdhci_plat *plat = dev_get_platdata(dev);
+	struct sdhci_host *host = dev_get_priv(dev);
+	struct mmc_config *cfg = &plat->cfg;
+	u32 drv_strength;
+	int ret;
+
+	host->name = dev->name;
+	host->ioaddr = (void *)dev_read_addr(dev);
+	plat->non_removable = dev_read_bool(dev, "non-removable");
+
+	ret = dev_read_u32(dev, "ti,trm-icp", &plat->trm_icp);
+	if (ret)
+		return ret;
+
+	ret = dev_read_u32(dev, "ti,otap-del-sel", &plat->otap_del_sel);
+	if (ret)
+		return ret;
+
+	ret = dev_read_u32(dev, "ti,driver-strength-ohm", &drv_strength);
+	if (ret)
+		return ret;
+
+	switch (drv_strength) {
+	case 50:
+		plat->drv_strength = DRIVER_STRENGTH_50_OHM;
+		break;
+	case 33:
+		plat->drv_strength = DRIVER_STRENGTH_33_OHM;
+		break;
+	case 66:
+		plat->drv_strength = DRIVER_STRENGTH_66_OHM;
+		break;
+	case 100:
+		plat->drv_strength = DRIVER_STRENGTH_100_OHM;
+		break;
+	case 40:
+		plat->drv_strength = DRIVER_STRENGTH_40_OHM;
+		break;
+	default:
+		dev_err(dev, "Invalid driver strength\n");
+		return -EINVAL;
+	}
+
+	ret = mmc_of_parse(dev, cfg);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int am654_sdhci_bind(struct udevice *dev)
+{
+	struct am654_sdhci_plat *plat = dev_get_platdata(dev);
+
+	return sdhci_bind(dev, &plat->mmc, &plat->cfg);
+}
+
+static const struct udevice_id am654_sdhci_ids[] = {
+	{ .compatible = "ti,am654-sdhci-5.1" },
+	{ }
+};
+
+U_BOOT_DRIVER(am654_sdhci_drv) = {
+	.name		= "am654_sdhci",
+	.id		= UCLASS_MMC,
+	.of_match	= am654_sdhci_ids,
+	.ofdata_to_platdata = am654_sdhci_ofdata_to_platdata,
+	.ops		= &sdhci_ops,
+	.bind		= am654_sdhci_bind,
+	.probe		= am654_sdhci_probe,
+	.priv_auto_alloc_size = sizeof(struct sdhci_host),
+	.platdata_auto_alloc_size = sizeof(struct am654_sdhci_plat),
+};
diff --git a/drivers/mmc/k3_arsan_sdhci.c b/drivers/mmc/k3_arsan_sdhci.c
deleted file mode 100644
index d5f2857..0000000
--- a/drivers/mmc/k3_arsan_sdhci.c
+++ /dev/null
@@ -1,109 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
- *
- * Texas Instruments' K3 SD Host Controller Interface
- */
-
-#include <clk.h>
-#include <common.h>
-#include <dm.h>
-#include <malloc.h>
-#include <power-domain.h>
-#include <sdhci.h>
-
-#define K3_ARASAN_SDHCI_MIN_FREQ	0
-
-struct k3_arasan_sdhci_plat {
-	struct mmc_config cfg;
-	struct mmc mmc;
-	unsigned int f_max;
-};
-
-static int k3_arasan_sdhci_probe(struct udevice *dev)
-{
-	struct k3_arasan_sdhci_plat *plat = dev_get_platdata(dev);
-	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
-	struct sdhci_host *host = dev_get_priv(dev);
-	struct power_domain sdhci_pwrdmn;
-	struct clk clk;
-	unsigned long clock;
-	int ret;
-
-	ret = power_domain_get_by_index(dev, &sdhci_pwrdmn, 0);
-	if (ret) {
-		dev_err(dev, "failed to get power domain\n");
-		return ret;
-	}
-
-	ret = power_domain_on(&sdhci_pwrdmn);
-	if (ret) {
-		dev_err(dev, "Power domain on failed\n");
-		return ret;
-	}
-
-	ret = clk_get_by_index(dev, 0, &clk);
-	if (ret) {
-		dev_err(dev, "failed to get clock\n");
-		return ret;
-	}
-
-	clock = clk_get_rate(&clk);
-	if (IS_ERR_VALUE(clock)) {
-		dev_err(dev, "failed to get rate\n");
-		return clock;
-	}
-
-	host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD |
-		       SDHCI_QUIRK_BROKEN_R1B;
-
-	host->max_clk = clock;
-
-	ret = sdhci_setup_cfg(&plat->cfg, host, plat->f_max,
-			      K3_ARASAN_SDHCI_MIN_FREQ);
-	host->mmc = &plat->mmc;
-	if (ret)
-		return ret;
-	host->mmc->priv = host;
-	host->mmc->dev = dev;
-	upriv->mmc = host->mmc;
-
-	return sdhci_probe(dev);
-}
-
-static int k3_arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
-{
-	struct k3_arasan_sdhci_plat *plat = dev_get_platdata(dev);
-	struct sdhci_host *host = dev_get_priv(dev);
-
-	host->name = dev->name;
-	host->ioaddr = (void *)dev_read_addr(dev);
-	host->bus_width = dev_read_u32_default(dev, "bus-width", 4);
-	plat->f_max = dev_read_u32_default(dev, "max-frequency", 0);
-
-	return 0;
-}
-
-static int k3_arasan_sdhci_bind(struct udevice *dev)
-{
-	struct k3_arasan_sdhci_plat *plat = dev_get_platdata(dev);
-
-	return sdhci_bind(dev, &plat->mmc, &plat->cfg);
-}
-
-static const struct udevice_id k3_arasan_sdhci_ids[] = {
-	{ .compatible = "arasan,sdhci-5.1" },
-	{ }
-};
-
-U_BOOT_DRIVER(k3_arasan_sdhci_drv) = {
-	.name		= "k3_arasan_sdhci",
-	.id		= UCLASS_MMC,
-	.of_match	= k3_arasan_sdhci_ids,
-	.ofdata_to_platdata = k3_arasan_sdhci_ofdata_to_platdata,
-	.ops		= &sdhci_ops,
-	.bind		= k3_arasan_sdhci_bind,
-	.probe		= k3_arasan_sdhci_probe,
-	.priv_auto_alloc_size = sizeof(struct sdhci_host),
-	.platdata_auto_alloc_size = sizeof(struct k3_arasan_sdhci_plat),
-};
diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index cb623d5..dd3d557 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -68,15 +68,15 @@
 	if (host->bus_width == 8)
 		host->host_caps |= MMC_MODE_8BIT;
 
-	ret = sdhci_setup_cfg(&plat->cfg, host, 0, EMMC_MIN_FREQ);
-
 	host->mmc = &plat->mmc;
-	if (ret)
-		return ret;
 	host->mmc->priv = &prv->host;
 	host->mmc->dev = dev;
 	upriv->mmc = host->mmc;
 
+	ret = sdhci_setup_cfg(&plat->cfg, host, 0, EMMC_MIN_FREQ);
+	if (ret)
+		return ret;
+
 	return sdhci_probe(dev);
 }
 
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index c4e8879..0a0770c 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -8,6 +8,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <errno.h>
 #include <malloc.h>
 #include <mmc.h>
@@ -409,7 +410,7 @@
 	return 0;
 }
 #endif
-static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
+int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
 {
 	struct sdhci_host *host = mmc->priv;
 	unsigned int div, clk = 0, timeout;
@@ -533,6 +534,34 @@
 	sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
 }
 
+void sdhci_set_uhs_timing(struct sdhci_host *host)
+{
+	struct mmc *mmc = (struct mmc *)host->mmc;
+	u32 reg;
+
+	reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+	reg &= ~SDHCI_CTRL_UHS_MASK;
+
+	switch (mmc->selected_mode) {
+	case UHS_SDR50:
+	case MMC_HS_52:
+		reg |= SDHCI_CTRL_UHS_SDR50;
+		break;
+	case UHS_DDR50:
+	case MMC_DDR_52:
+		reg |= SDHCI_CTRL_UHS_DDR50;
+		break;
+	case UHS_SDR104:
+	case MMC_HS_200:
+		reg |= SDHCI_CTRL_UHS_SDR104;
+		break;
+	default:
+		reg |= SDHCI_CTRL_UHS_SDR12;
+	}
+
+	sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
+}
+
 #ifdef CONFIG_DM_MMC
 static int sdhci_set_ios(struct udevice *dev)
 {
@@ -583,7 +612,7 @@
 
 	/* If available, call the driver specific "post" set_ios() function */
 	if (host->ops && host->ops->set_ios_post)
-		host->ops->set_ios_post(host);
+		return host->ops->set_ios_post(host);
 
 	return 0;
 }
@@ -681,8 +710,18 @@
 		u32 f_max, u32 f_min)
 {
 	u32 caps, caps_1 = 0;
+#if CONFIG_IS_ENABLED(DM_MMC)
+	u32 mask[2] = {0};
+	int ret;
+	ret = dev_read_u32_array(host->mmc->dev, "sdhci-caps-mask",
+				 mask, 2);
+	if (ret && ret != -1)
+		return ret;
 
+	caps = ~mask[1] & sdhci_readl(host, SDHCI_CAPABILITIES);
+#else
 	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+#endif
 
 #ifdef CONFIG_MMC_SDHCI_SDMA
 	if (!(caps & SDHCI_CAN_DO_SDMA)) {
@@ -722,7 +761,11 @@
 
 	/* Check whether the clock multiplier is supported or not */
 	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
+#if CONFIG_IS_ENABLED(DM_MMC)
+		caps_1 = ~mask[0] & sdhci_readl(host, SDHCI_CAPABILITIES_1);
+#else
 		caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+#endif
 		host->clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >>
 				SDHCI_CLOCK_MUL_SHIFT;
 	}
@@ -779,9 +822,6 @@
 		cfg->host_caps &= ~MMC_MODE_HS_52MHz;
 	}
 
-	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
-		caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
-
 	if (!(cfg->voltages & MMC_VDD_165_195) ||
 	    (host->quirks & SDHCI_QUIRK_NO_1_8_V))
 		caps_1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
diff --git a/drivers/mmc/xenon_sdhci.c b/drivers/mmc/xenon_sdhci.c
index b576511..829b756 100644
--- a/drivers/mmc/xenon_sdhci.c
+++ b/drivers/mmc/xenon_sdhci.c
@@ -326,7 +326,7 @@
 }
 
 /* Platform specific function for post set_ios configuration */
-static void xenon_sdhci_set_ios_post(struct sdhci_host *host)
+static int xenon_sdhci_set_ios_post(struct sdhci_host *host)
 {
 	struct xenon_sdhci_priv *priv = host->mmc->priv;
 	uint speed = host->mmc->tran_speed;
@@ -364,6 +364,8 @@
 
 	/* Re-init the PHY */
 	xenon_mmc_phy_set(host);
+
+	return 0;
 }
 
 /* Install a driver specific handler for post set_ios configuration */
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 0802378..c525084 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -48,11 +48,6 @@
 	[MMC_HS_200] = MMC_HS200_BUS_SPEED,
 };
 
-#define SDHCI_HOST_CTRL2	0x3E
-#define SDHCI_CTRL2_MODE_MASK	0x7
-#define SDHCI_18V_SIGNAL	0x8
-#define SDHCI_CTRL_EXEC_TUNING	0x0040
-#define SDHCI_CTRL_TUNED_CLK	0x80
 #define SDHCI_TUNING_LOOP_COUNT	40
 
 static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
@@ -99,9 +94,9 @@
 	host = priv->host;
 	deviceid = priv->deviceid;
 
-	ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
+	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 	ctrl |= SDHCI_CTRL_EXEC_TUNING;
-	sdhci_writew(host, ctrl, SDHCI_HOST_CTRL2);
+	sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
 	mdelay(1);
 
@@ -133,7 +128,7 @@
 		sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
 
 		mmc_send_cmd(mmc, &cmd, NULL);
-		ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
+		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 
 		if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK)
 			udelay(1);
@@ -142,7 +137,7 @@
 
 	if (tuning_loop_counter < 0) {
 		ctrl &= ~SDHCI_CTRL_TUNED_CLK;
-		sdhci_writel(host, ctrl, SDHCI_HOST_CTRL2);
+		sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL2);
 	}
 
 	if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
@@ -184,36 +179,14 @@
 		return;
 
 	if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
-		reg = sdhci_readw(host, SDHCI_HOST_CTRL2);
-		reg |= SDHCI_18V_SIGNAL;
-		sdhci_writew(host, reg, SDHCI_HOST_CTRL2);
+		reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+		reg |= SDHCI_CTRL_VDD_180;
+		sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
 	}
 
 	if (mmc->selected_mode > SD_HS &&
-	    mmc->selected_mode <= UHS_DDR50) {
-		reg = sdhci_readw(host, SDHCI_HOST_CTRL2);
-		reg &= ~SDHCI_CTRL2_MODE_MASK;
-		switch (mmc->selected_mode) {
-		case UHS_SDR12:
-			reg |= UHS_SDR12_BUS_SPEED;
-			break;
-		case UHS_SDR25:
-			reg |= UHS_SDR25_BUS_SPEED;
-			break;
-		case UHS_SDR50:
-			reg |= UHS_SDR50_BUS_SPEED;
-			break;
-		case UHS_SDR104:
-			reg |= UHS_SDR104_BUS_SPEED;
-			break;
-		case UHS_DDR50:
-			reg |= UHS_DDR50_BUS_SPEED;
-			break;
-		default:
-			break;
-		}
-		sdhci_writew(host, reg, SDHCI_HOST_CTRL2);
-	}
+	    mmc->selected_mode <= UHS_DDR50)
+		sdhci_set_uhs_timing(host);
 }
 #endif
 
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 635f8d7..403df5e 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -24,6 +24,18 @@
 	  This is currently implemented in net/mdio-uclass.c
 	  Look in include/miiphy.h for details.
 
+config DM_MDIO_MUX
+	bool "Enable Driver Model for MDIO MUX devices"
+	depends on DM_MDIO
+	help
+	  Enable driver model for MDIO MUX devices
+
+	  Adds UCLASS_MDIO_MUX DM class supporting MDIO MUXes.  Useful for
+	  systems that support DM_MDIO and integrate one or multiple muxes on
+	  the MDIO bus.
+	  This is currently implemented in net/mdio-mux-uclass.c
+	  Look in include/miiphy.h for details.
+
 config MDIO_SANDBOX
 	depends on DM_MDIO && SANDBOX
 	default y
@@ -34,6 +46,16 @@
 
 	  This driver is used in for testing in test/dm/mdio.c
 
+config MDIO_MUX_SANDBOX
+	depends on DM_MDIO_MUX && MDIO_SANDBOX
+	default y
+	bool "Sandbox: Mocked MDIO-MUX driver"
+	help
+	  This driver implements dummy select/deselect ops mimicking a MUX on
+	  the MDIO bux.  It uses mdio_sandbox driver as parent MDIO.
+
+	  This driver is used for testing in test/dm/mdio.c
+
 menuconfig NETDEVICES
 	bool "Network device support"
 	depends on NET
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 4003842..3c473b2 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -37,6 +37,7 @@
 obj-$(CONFIG_LPC32XX_ETH) += lpc32xx_eth.o
 obj-$(CONFIG_MACB) += macb.o
 obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
+obj-$(CONFIG_MDIO_MUX_SANDBOX) += mdio_mux_sandbox.o
 obj-$(CONFIG_MPC8XX_FEC) += mpc8xx_fec.o
 obj-$(CONFIG_MT7628_ETH) += mt7628-eth.o
 obj-$(CONFIG_MVGBE) += mvgbe.o
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index 2c5d956..3b6cf5d 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -677,10 +677,10 @@
 	struct dw_eth_dev *priv = dev_get_priv(dev);
 	u32 iobase = pdata->iobase;
 	ulong ioaddr;
-	int ret;
+	int ret, err;
 	struct reset_ctl_bulk reset_bulk;
 #ifdef CONFIG_CLK
-	int i, err, clock_nb;
+	int i, clock_nb;
 
 	priv->clock_count = 0;
 	clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells");
@@ -753,13 +753,23 @@
 	priv->interface = pdata->phy_interface;
 	priv->max_speed = pdata->max_speed;
 
-	dw_mdio_init(dev->name, dev);
+	ret = dw_mdio_init(dev->name, dev);
+	if (ret) {
+		err = ret;
+		goto mdio_err;
+	}
 	priv->bus = miiphy_get_dev_by_name(dev->name);
 
 	ret = dw_phy_init(priv, dev);
 	debug("%s, ret=%d\n", __func__, ret);
+	if (!ret)
+		return 0;
 
-	return ret;
+	/* continue here for cleanup if no PHY found */
+	err = ret;
+	mdio_unregister(priv->bus);
+	mdio_free(priv->bus);
+mdio_err:
 
 #ifdef CONFIG_CLK
 clk_err:
@@ -767,8 +777,8 @@
 	if (ret)
 		pr_err("failed to disable all clocks\n");
 
-	return err;
 #endif
+	return err;
 }
 
 static int designware_eth_remove(struct udevice *dev)
diff --git a/drivers/net/mdio_mux_sandbox.c b/drivers/net/mdio_mux_sandbox.c
new file mode 100644
index 0000000..3dba4d1
--- /dev/null
+++ b/drivers/net/mdio_mux_sandbox.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019
+ * Alex Marginean, NXP
+ */
+
+#include <dm.h>
+#include <errno.h>
+#include <miiphy.h>
+
+/* macros copied over from mdio_sandbox.c */
+#define SANDBOX_PHY_ADDR	5
+#define SANDBOX_PHY_REG_CNT	2
+
+struct mdio_mux_sandbox_priv {
+	int enabled;
+	int sel;
+};
+
+static int mdio_mux_sandbox_mark_selection(struct udevice *dev, int sel)
+{
+	struct udevice *mdio;
+	struct mdio_ops *ops;
+	int err;
+
+	/*
+	 * find the sandbox parent mdio and write a register on the PHY there
+	 * so the mux test can verify selection.
+	 */
+	err = uclass_get_device_by_name(UCLASS_MDIO, "mdio-test", &mdio);
+	if (err)
+		return err;
+	ops = mdio_get_ops(mdio);
+	return ops->write(mdio, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE,
+			  SANDBOX_PHY_REG_CNT - 1, (u16)sel);
+}
+
+static int mdio_mux_sandbox_select(struct udevice *dev, int cur, int sel)
+{
+	struct mdio_mux_sandbox_priv *priv = dev_get_priv(dev);
+
+	if (!priv->enabled)
+		return -ENODEV;
+
+	if (cur != priv->sel)
+		return -EINVAL;
+
+	priv->sel = sel;
+	mdio_mux_sandbox_mark_selection(dev, priv->sel);
+
+	return 0;
+}
+
+static int mdio_mux_sandbox_deselect(struct udevice *dev, int sel)
+{
+	struct mdio_mux_sandbox_priv *priv = dev_get_priv(dev);
+
+	if (!priv->enabled)
+		return -ENODEV;
+
+	if (sel != priv->sel)
+		return -EINVAL;
+
+	priv->sel = -1;
+	mdio_mux_sandbox_mark_selection(dev, priv->sel);
+
+	return 0;
+}
+
+static const struct mdio_mux_ops mdio_mux_sandbox_ops = {
+	.select = mdio_mux_sandbox_select,
+	.deselect = mdio_mux_sandbox_deselect,
+};
+
+static int mdio_mux_sandbox_probe(struct udevice *dev)
+{
+	struct mdio_mux_sandbox_priv *priv = dev_get_priv(dev);
+
+	priv->enabled = 1;
+	priv->sel = -1;
+
+	return 0;
+}
+
+static const struct udevice_id mdio_mux_sandbox_ids[] = {
+	{ .compatible = "sandbox,mdio-mux" },
+	{ }
+};
+
+U_BOOT_DRIVER(mdio_mux_sandbox) = {
+	.name		= "mdio_mux_sandbox",
+	.id		= UCLASS_MDIO_MUX,
+	.of_match	= mdio_mux_sandbox_ids,
+	.probe		= mdio_mux_sandbox_probe,
+	.ops		= &mdio_mux_sandbox_ops,
+	.priv_auto_alloc_size = sizeof(struct mdio_mux_sandbox_priv),
+};
diff --git a/drivers/net/mdio_sandbox.c b/drivers/net/mdio_sandbox.c
index 07515e0..df053f5 100644
--- a/drivers/net/mdio_sandbox.c
+++ b/drivers/net/mdio_sandbox.c
@@ -9,11 +9,11 @@
 #include <miiphy.h>
 
 #define SANDBOX_PHY_ADDR	5
-#define SANDBOX_PHY_REG		0
+#define SANDBOX_PHY_REG_CNT	2
 
 struct mdio_sandbox_priv {
 	int enabled;
-	u16 reg;
+	u16 reg[SANDBOX_PHY_REG_CNT];
 };
 
 static int mdio_sandbox_read(struct udevice *dev, int addr, int devad, int reg)
@@ -27,10 +27,10 @@
 		return -ENODEV;
 	if (devad != MDIO_DEVAD_NONE)
 		return -ENODEV;
-	if (reg != SANDBOX_PHY_REG)
+	if (reg < 0 || reg > SANDBOX_PHY_REG_CNT)
 		return -ENODEV;
 
-	return priv->reg;
+	return priv->reg[reg];
 }
 
 static int mdio_sandbox_write(struct udevice *dev, int addr, int devad, int reg,
@@ -45,10 +45,10 @@
 		return -ENODEV;
 	if (devad != MDIO_DEVAD_NONE)
 		return -ENODEV;
-	if (reg != SANDBOX_PHY_REG)
+	if (reg < 0 || reg > SANDBOX_PHY_REG_CNT)
 		return -ENODEV;
 
-	priv->reg = val;
+	priv->reg[reg] = val;
 
 	return 0;
 }
@@ -56,8 +56,10 @@
 static int mdio_sandbox_reset(struct udevice *dev)
 {
 	struct mdio_sandbox_priv *priv = dev_get_priv(dev);
+	int i;
 
-	priv->reg = 0;
+	for (i = 0; i < SANDBOX_PHY_REG_CNT; i++)
+		priv->reg[i] = 0;
 
 	return 0;
 }
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c
index 5c3298d..465ec2d 100644
--- a/drivers/net/phy/aquantia.c
+++ b/drivers/net/phy/aquantia.c
@@ -461,6 +461,19 @@
 	.shutdown = &gen10g_shutdown,
 };
 
+struct phy_driver aqr112_driver = {
+	.name = "Aquantia AQR112",
+	.uid = 0x3a1b660,
+	.mask = 0xfffffff0,
+	.features = PHY_10G_FEATURES,
+	.mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS |
+		 MDIO_MMD_PHYXS | MDIO_MMD_AN |
+		 MDIO_MMD_VEND1),
+	.config = &aquantia_config,
+	.startup = &aquantia_startup,
+	.shutdown = &gen10g_shutdown,
+};
+
 struct phy_driver aqr405_driver = {
 	.name = "Aquantia AQR405",
 	.uid = 0x3a1b4b2,
@@ -474,6 +487,19 @@
 	.shutdown = &gen10g_shutdown,
 };
 
+struct phy_driver aqr412_driver = {
+	.name = "Aquantia AQR412",
+	.uid = 0x3a1b710,
+	.mask = 0xfffffff0,
+	.features = PHY_10G_FEATURES,
+	.mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS |
+		 MDIO_MMD_PHYXS | MDIO_MMD_AN |
+		 MDIO_MMD_VEND1),
+	.config = &aquantia_config,
+	.startup = &aquantia_startup,
+	.shutdown = &gen10g_shutdown,
+};
+
 int phy_aquantia_init(void)
 {
 	phy_register(&aq1202_driver);
@@ -481,7 +507,9 @@
 	phy_register(&aqr105_driver);
 	phy_register(&aqr106_driver);
 	phy_register(&aqr107_driver);
+	phy_register(&aqr112_driver);
 	phy_register(&aqr405_driver);
+	phy_register(&aqr412_driver);
 
 	return 0;
 }
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index c1c1af9..ae37dd6 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -727,12 +727,23 @@
 	while (phy_mask) {
 		int addr = ffs(phy_mask) - 1;
 		int r = get_phy_id(bus, addr, devad, &phy_id);
+
+		/*
+		 * If the PHY ID is flat 0 we ignore it.  There are C45 PHYs
+		 * that return all 0s for C22 reads (like Aquantia AQR112) and
+		 * there are C22 PHYs that return all 0s for C45 reads (like
+		 * Atheros AR8035).
+		 */
+		if (r == 0 && phy_id == 0)
+			goto next;
+
 		/* If the PHY ID is mostly f's, we didn't find anything */
 		if (r == 0 && (phy_id & 0x1fffffff) != 0x1fffffff) {
 			is_c45 = (devad == MDIO_DEVAD_NONE) ? false : true;
 			return phy_device_create(bus, addr, phy_id, is_c45,
 						 interface);
 		}
+next:
 		phy_mask &= ~(1 << addr);
 	}
 	return NULL;
diff --git a/drivers/pci_endpoint/sandbox-pci_ep.c b/drivers/pci_endpoint/sandbox-pci_ep.c
index 0258433..8e05d5b 100644
--- a/drivers/pci_endpoint/sandbox-pci_ep.c
+++ b/drivers/pci_endpoint/sandbox-pci_ep.c
@@ -83,14 +83,11 @@
 			    struct pci_bar *ep_bar, enum pci_barno barno)
 {
 	struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
-	int bar_idx;
 
 	if (fn > 0)
 		return -ENODEV;
 
-	bar_idx = ep_bar->barno;
-
-	memcpy(ep_bar, &priv->bars[bar_idx], sizeof(*ep_bar));
+	memcpy(ep_bar, &priv->bars[barno], sizeof(*ep_bar));
 
 	return 0;
 }
diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index f206fa3..5e8f877 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -75,6 +75,7 @@
 	sun8i_h3_phy,
 	sun8i_v3s_phy,
 	sun50i_a64_phy,
+	sun50i_h6_phy,
 };
 
 struct sun4i_usb_phy_cfg {
@@ -85,6 +86,7 @@
 	bool dedicated_clocks;
 	bool enable_pmu_unk1;
 	bool phy0_dual_route;
+	int missing_phys;
 };
 
 struct sun4i_usb_phy_info {
@@ -349,6 +351,9 @@
 	if (args->args_count >= data->cfg->num_phys)
 		return -EINVAL;
 
+	if (data->cfg->missing_phys & BIT(args->args[0]))
+		return -ENODEV;
+
 	if (args->args_count)
 		phy->id = args->args[0];
 	else
@@ -429,6 +434,9 @@
 		struct sun4i_usb_phy_info *info = &phy_info[i];
 		char name[16];
 
+		if (data->cfg->missing_phys & BIT(i))
+			continue;
+
 		phy->gpio_vbus = sunxi_name_to_gpio(info->gpio_vbus);
 		if (phy->gpio_vbus >= 0) {
 			ret = gpio_request(phy->gpio_vbus, "usb_vbus");
@@ -581,6 +589,17 @@
 	.dedicated_clocks = true,
 	.enable_pmu_unk1 = true,
 	.phy0_dual_route = true,
+};
+
+static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = {
+	.num_phys = 4,
+	.type = sun50i_h6_phy,
+	.disc_thresh = 3,
+	.phyctl_offset = REG_PHYCTL_A33,
+	.dedicated_clocks = true,
+	.enable_pmu_unk1 = true,
+	.phy0_dual_route = true,
+	.missing_phys = BIT(1) | BIT(2),
 };
 
 static const struct udevice_id sun4i_usb_phy_ids[] = {
@@ -594,6 +613,7 @@
 	{ .compatible = "allwinner,sun8i-h3-usb-phy", .data = (ulong)&sun8i_h3_cfg },
 	{ .compatible = "allwinner,sun8i-v3s-usb-phy", .data = (ulong)&sun8i_v3s_cfg },
 	{ .compatible = "allwinner,sun50i-a64-usb-phy", .data = (ulong)&sun50i_a64_cfg},
+	{ .compatible = "allwinner,sun50i-h6-usb-phy", .data = (ulong)&sun50i_h6_cfg},
 	{ }
 };
 
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index 147e68d..337e9e7 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -92,9 +92,18 @@
 	  or switching the mode is not supported by this driver (at
 	  this time).
 
+config DM_REGULATOR_COMMON
+	bool
+	depends on DM_REGULATOR
+
+config SPL_DM_REGULATOR_COMMON
+	bool
+	depends on DM_REGULATOR
+
 config DM_REGULATOR_FIXED
 	bool "Enable Driver Model for REGULATOR Fixed value"
 	depends on DM_REGULATOR
+	select DM_REGULATOR_COMMON
 	---help---
 	This config enables implementation of driver-model regulator uclass
 	features for fixed value regulators. The driver implements get/set api
@@ -103,6 +112,7 @@
 config SPL_DM_REGULATOR_FIXED
 	bool "Enable Driver Model for REGULATOR Fixed value in SPL"
 	depends on DM_REGULATOR_FIXED
+	select SPL_DM_REGULATOR_COMMON
 	---help---
 	This config enables implementation of driver-model regulator uclass
 	features for fixed value regulators in SPL.
@@ -110,6 +120,7 @@
 config DM_REGULATOR_GPIO
 	bool "Enable Driver Model for GPIO REGULATOR"
 	depends on DM_REGULATOR && DM_GPIO
+	select DM_REGULATOR_COMMON
 	---help---
 	This config enables implementation of driver-model regulator uclass
 	features for gpio regulators. The driver implements get/set for
@@ -118,6 +129,7 @@
 config SPL_DM_REGULATOR_GPIO
 	bool "Enable Driver Model for GPIO REGULATOR in SPL"
 	depends on DM_REGULATOR_GPIO && SPL_GPIO_SUPPORT
+	select SPL_DM_REGULATOR_COMMON
 	---help---
 	This config enables implementation of driver-model regulator uclass
 	features for gpio regulators in SPL.
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index 8c1506c..e728b73 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -11,6 +11,7 @@
 obj-$(CONFIG_$(SPL_)DM_PMIC_PFUZE100) += pfuze100.o
 obj-$(CONFIG_$(SPL_)REGULATOR_PWM) += pwm_regulator.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_FAN53555) += fan53555.o
+obj-$(CONFIG_$(SPL_)DM_REGULATOR_COMMON) += regulator_common.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_FIXED) += fixed.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_GPIO) += gpio-regulator.o
 obj-$(CONFIG_REGULATOR_RK8XX) += rk8xx.o
diff --git a/drivers/power/regulator/fixed.c b/drivers/power/regulator/fixed.c
index a99aa78..763e671 100644
--- a/drivers/power/regulator/fixed.c
+++ b/drivers/power/regulator/fixed.c
@@ -5,56 +5,26 @@
  *  Przemyslaw Marczak <p.marczak@samsung.com>
  */
 
+#include "regulator_common.h"
 #include <common.h>
 #include <errno.h>
 #include <dm.h>
-#include <i2c.h>
-#include <asm/gpio.h>
 #include <power/pmic.h>
 #include <power/regulator.h>
 
-struct fixed_regulator_platdata {
-	struct gpio_desc gpio; /* GPIO for regulator enable control */
-	unsigned int startup_delay_us;
-	unsigned int off_on_delay_us;
-};
-
 static int fixed_regulator_ofdata_to_platdata(struct udevice *dev)
 {
 	struct dm_regulator_uclass_platdata *uc_pdata;
-	struct fixed_regulator_platdata *dev_pdata;
-	struct gpio_desc *gpio;
-	int flags = GPIOD_IS_OUT;
-	int ret;
+	struct regulator_common_platdata *dev_pdata;
 
 	dev_pdata = dev_get_platdata(dev);
 	uc_pdata = dev_get_uclass_platdata(dev);
 	if (!uc_pdata)
 		return -ENXIO;
 
-	/* Set type to fixed */
 	uc_pdata->type = REGULATOR_TYPE_FIXED;
 
-	if (dev_read_bool(dev, "enable-active-high"))
-		flags |= GPIOD_IS_OUT_ACTIVE;
-
-	/* Get fixed regulator optional enable GPIO desc */
-	gpio = &dev_pdata->gpio;
-	ret = gpio_request_by_name(dev, "gpio", 0, gpio, flags);
-	if (ret) {
-		debug("Fixed regulator optional enable GPIO - not found! Error: %d\n",
-		      ret);
-		if (ret != -ENOENT)
-			return ret;
-	}
-
-	/* Get optional ramp up delay */
-	dev_pdata->startup_delay_us = dev_read_u32_default(dev,
-							"startup-delay-us", 0);
-	dev_pdata->off_on_delay_us =
-			dev_read_u32_default(dev, "u-boot,off-on-delay-us", 0);
-
-	return 0;
+	return regulator_common_ofdata_to_platdata(dev, dev_pdata, "gpio");
 }
 
 static int fixed_regulator_get_value(struct udevice *dev)
@@ -91,45 +61,12 @@
 
 static int fixed_regulator_get_enable(struct udevice *dev)
 {
-	struct fixed_regulator_platdata *dev_pdata = dev_get_platdata(dev);
-
-	/* Enable GPIO is optional */
-	if (!dev_pdata->gpio.dev)
-		return true;
-
-	return dm_gpio_get_value(&dev_pdata->gpio);
+	return regulator_common_get_enable(dev, dev_get_platdata(dev));
 }
 
 static int fixed_regulator_set_enable(struct udevice *dev, bool enable)
 {
-	struct fixed_regulator_platdata *dev_pdata = dev_get_platdata(dev);
-	int ret;
-
-	debug("%s: dev='%s', enable=%d, delay=%d, has_gpio=%d\n", __func__,
-	      dev->name, enable, dev_pdata->startup_delay_us,
-	      dm_gpio_is_valid(&dev_pdata->gpio));
-	/* Enable GPIO is optional */
-	if (!dm_gpio_is_valid(&dev_pdata->gpio)) {
-		if (!enable)
-			return -ENOSYS;
-		return 0;
-	}
-
-	ret = dm_gpio_set_value(&dev_pdata->gpio, enable);
-	if (ret) {
-		pr_err("Can't set regulator : %s gpio to: %d\n", dev->name,
-		      enable);
-		return ret;
-	}
-
-	if (enable && dev_pdata->startup_delay_us)
-		udelay(dev_pdata->startup_delay_us);
-	debug("%s: done\n", __func__);
-
-	if (!enable && dev_pdata->off_on_delay_us)
-		udelay(dev_pdata->off_on_delay_us);
-
-	return 0;
+	return regulator_common_set_enable(dev, dev_get_platdata(dev), enable);
 }
 
 static const struct dm_regulator_ops fixed_regulator_ops = {
@@ -150,5 +87,5 @@
 	.ops = &fixed_regulator_ops,
 	.of_match = fixed_regulator_ids,
 	.ofdata_to_platdata = fixed_regulator_ofdata_to_platdata,
-	.platdata_auto_alloc_size = sizeof(struct fixed_regulator_platdata),
+	.platdata_auto_alloc_size = sizeof(struct regulator_common_platdata),
 };
diff --git a/drivers/power/regulator/gpio-regulator.c b/drivers/power/regulator/gpio-regulator.c
index d18e5d8..ec1dcb6 100644
--- a/drivers/power/regulator/gpio-regulator.c
+++ b/drivers/power/regulator/gpio-regulator.c
@@ -4,6 +4,7 @@
  * Keerthy <j-keerthy@ti.com>
  */
 
+#include "regulator_common.h"
 #include <common.h>
 #include <fdtdec.h>
 #include <errno.h>
@@ -18,6 +19,7 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 struct gpio_regulator_platdata {
+	struct regulator_common_platdata common;
 	struct gpio_desc gpio; /* GPIO for regulator voltage control */
 	int states[GPIO_REGULATOR_MAX_STATES];
 	int voltages[GPIO_REGULATOR_MAX_STATES];
@@ -65,7 +67,7 @@
 		j++;
 	}
 
-	return 0;
+	return regulator_common_ofdata_to_platdata(dev, &dev_pdata->common, "enable-gpios");
 }
 
 static int gpio_regulator_get_value(struct udevice *dev)
@@ -116,9 +118,23 @@
 	return 0;
 }
 
+static int gpio_regulator_get_enable(struct udevice *dev)
+{
+	struct gpio_regulator_platdata *dev_pdata = dev_get_platdata(dev);
+	return regulator_common_get_enable(dev, &dev_pdata->common);
+}
+
+static int gpio_regulator_set_enable(struct udevice *dev, bool enable)
+{
+	struct gpio_regulator_platdata *dev_pdata = dev_get_platdata(dev);
+	return regulator_common_set_enable(dev, &dev_pdata->common, enable);
+}
+
 static const struct dm_regulator_ops gpio_regulator_ops = {
 	.get_value	= gpio_regulator_get_value,
 	.set_value	= gpio_regulator_set_value,
+	.get_enable	= gpio_regulator_get_enable,
+	.set_enable	= gpio_regulator_set_enable,
 };
 
 static const struct udevice_id gpio_regulator_ids[] = {
diff --git a/drivers/power/regulator/regulator_common.c b/drivers/power/regulator/regulator_common.c
new file mode 100644
index 0000000..3dabbe2
--- /dev/null
+++ b/drivers/power/regulator/regulator_common.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Disruptive Technologies Research AS
+ * Sven Schwermer <sven.svenschwermer@disruptive-technologies.com>
+ */
+
+#include "regulator_common.h"
+#include <common.h>
+#include <power/regulator.h>
+
+int regulator_common_ofdata_to_platdata(struct udevice *dev,
+	struct regulator_common_platdata *dev_pdata, const char *enable_gpio_name)
+{
+	struct gpio_desc *gpio;
+	int flags = GPIOD_IS_OUT;
+	int ret;
+
+	if (dev_read_bool(dev, "enable-active-high"))
+		flags |= GPIOD_IS_OUT_ACTIVE;
+
+	/* Get optional enable GPIO desc */
+	gpio = &dev_pdata->gpio;
+	ret = gpio_request_by_name(dev, enable_gpio_name, 0, gpio, flags);
+	if (ret) {
+		debug("Regulator '%s' optional enable GPIO - not found! Error: %d\n",
+		      dev->name, ret);
+		if (ret != -ENOENT)
+			return ret;
+	}
+
+	/* Get optional ramp up delay */
+	dev_pdata->startup_delay_us = dev_read_u32_default(dev,
+							"startup-delay-us", 0);
+	dev_pdata->off_on_delay_us =
+			dev_read_u32_default(dev, "u-boot,off-on-delay-us", 0);
+
+	return 0;
+}
+
+int regulator_common_get_enable(const struct udevice *dev,
+	struct regulator_common_platdata *dev_pdata)
+{
+	/* Enable GPIO is optional */
+	if (!dev_pdata->gpio.dev)
+		return true;
+
+	return dm_gpio_get_value(&dev_pdata->gpio);
+}
+
+int regulator_common_set_enable(const struct udevice *dev,
+	struct regulator_common_platdata *dev_pdata, bool enable)
+{
+	int ret;
+
+	debug("%s: dev='%s', enable=%d, delay=%d, has_gpio=%d\n", __func__,
+	      dev->name, enable, dev_pdata->startup_delay_us,
+	      dm_gpio_is_valid(&dev_pdata->gpio));
+	/* Enable GPIO is optional */
+	if (!dm_gpio_is_valid(&dev_pdata->gpio)) {
+		if (!enable)
+			return -ENOSYS;
+		return 0;
+	}
+
+	ret = dm_gpio_set_value(&dev_pdata->gpio, enable);
+	if (ret) {
+		pr_err("Can't set regulator : %s gpio to: %d\n", dev->name,
+		      enable);
+		return ret;
+	}
+
+	if (enable && dev_pdata->startup_delay_us)
+		udelay(dev_pdata->startup_delay_us);
+	debug("%s: done\n", __func__);
+
+	if (!enable && dev_pdata->off_on_delay_us)
+		udelay(dev_pdata->off_on_delay_us);
+
+	return 0;
+}
diff --git a/drivers/power/regulator/regulator_common.h b/drivers/power/regulator/regulator_common.h
new file mode 100644
index 0000000..18a5258
--- /dev/null
+++ b/drivers/power/regulator/regulator_common.h
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Disruptive Technologies Research AS
+ * Sven Schwermer <sven.svenschwermer@disruptive-technologies.com>
+ */
+
+#ifndef _REGULATOR_COMMON_H
+#define _REGULATOR_COMMON_H
+
+#include <common.h>
+#include <asm/gpio.h>
+#include <dm.h>
+
+struct regulator_common_platdata {
+	struct gpio_desc gpio; /* GPIO for regulator enable control */
+	unsigned int startup_delay_us;
+	unsigned int off_on_delay_us;
+};
+
+int regulator_common_ofdata_to_platdata(struct udevice *dev,
+	struct regulator_common_platdata *dev_pdata, const char *enable_gpio_name);
+int regulator_common_get_enable(const struct udevice *dev,
+	struct regulator_common_platdata *dev_pdata);
+int regulator_common_set_enable(const struct udevice *dev,
+	struct regulator_common_platdata *dev_pdata, bool enable);
+
+#endif /* _REGULATOR_COMMON_H */
diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig
index fbf7d7b..568d8f2 100644
--- a/drivers/ram/Kconfig
+++ b/drivers/ram/Kconfig
@@ -54,4 +54,5 @@
 	  config add support for the initialization of the external
 	  SDRAM devices connected to DDR subsystem.
 
+source "drivers/ram/rockchip/Kconfig"
 source "drivers/ram/stm32mp1/Kconfig"
diff --git a/drivers/ram/rockchip/Kconfig b/drivers/ram/rockchip/Kconfig
new file mode 100644
index 0000000..4f274e0
--- /dev/null
+++ b/drivers/ram/rockchip/Kconfig
@@ -0,0 +1,33 @@
+config RAM_ROCKCHIP
+	bool "Ram drivers support for Rockchip SoCs"
+	depends on RAM && ARCH_ROCKCHIP
+	default y
+	help
+	  This enables support for ram drivers Rockchip SoCs.
+
+if RAM_ROCKCHIP
+
+config RAM_ROCKCHIP_DEBUG
+	bool "Rockchip ram drivers debugging"
+	help
+	  This enables debugging ram driver API's for the platforms
+	  based on Rockchip SoCs.
+
+	  This is an option for developers to understand the ram drivers
+	  initialization, configurations and etc.
+
+config RAM_RK3399
+	bool "Ram driver for Rockchip RK3399"
+	default ROCKCHIP_RK3399
+	help
+	  This enables ram drivers support for the platforms based on
+	  Rockchip RK3399 SoC.
+
+config RAM_RK3399_LPDDR4
+	bool "LPDDR4 support for Rockchip RK3399"
+	depends on RAM_RK3399
+	help
+	  This enables LPDDR4 sdram code support for the platforms based
+	  on Rockchip RK3399 SoC.
+
+endif # RAM_ROCKCHIP
diff --git a/drivers/ram/rockchip/Makefile b/drivers/ram/rockchip/Makefile
index 5df1960..feb1f82 100644
--- a/drivers/ram/rockchip/Makefile
+++ b/drivers/ram/rockchip/Makefile
@@ -3,10 +3,11 @@
 # Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH
 #
 
+obj-$(CONFIG_RAM_ROCKCHIP_DEBUG) += sdram_debug.o
 obj-$(CONFIG_ROCKCHIP_RK3368) = dmc-rk3368.o
 obj-$(CONFIG_ROCKCHIP_RK3128) = sdram_rk3128.o
 obj-$(CONFIG_ROCKCHIP_RK3188) = sdram_rk3188.o
 obj-$(CONFIG_ROCKCHIP_RK322X) = sdram_rk322x.o
 obj-$(CONFIG_ROCKCHIP_RK3288) = sdram_rk3288.o
 obj-$(CONFIG_ROCKCHIP_RK3328) = sdram_rk3328.o
-obj-$(CONFIG_ROCKCHIP_RK3399) = sdram_rk3399.o
+obj-$(CONFIG_RAM_RK3399) += sdram_rk3399.o
diff --git a/drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc b/drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc
new file mode 100644
index 0000000..c50a03d
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc
@@ -0,0 +1,1570 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd.
+ * (C) Copyright 2019 Amarula Solutions
+ */
+
+{
+	{
+		{
+			{
+				.rank = 0x2,
+				.col = 0xA,
+				.bk = 0x3,
+				.bw = 0x2,
+				.dbw = 0x1,
+				.row_3_4 = 0x0,
+				.cs0_row = 0xF,
+				.cs1_row = 0xF,
+				.ddrconfig = 1,
+			},
+			{
+				.ddrtiminga0 = 0x80241d22,
+				.ddrtimingb0 = 0x15050f08,
+				.ddrtimingc0 = {
+					0x00000602,
+				},
+				.devtodev0 = 0x00002122,
+				.ddrmode = {
+					0x0000004c,
+				},
+				.agingx0 = 0x00000000,
+			}
+		},
+		{
+			{
+				.rank = 0x2,
+				.col = 0xA,
+				.bk = 0x3,
+				.bw = 0x2,
+				.dbw = 0x1,
+				.row_3_4 = 0x0,
+				.cs0_row = 0xF,
+				.cs1_row = 0xF,
+				.ddrconfig = 1,
+			},
+			{
+				.ddrtiminga0 = 0x80241d22,
+				.ddrtimingb0 = 0x15050f08,
+				.ddrtimingc0 = {
+					0x00000602,
+				},
+				.devtodev0 = 0x00002122,
+				.ddrmode = {
+					0x0000004c,
+				},
+				.agingx0 = 0x00000000,
+			}
+		}
+	},
+	{
+		.ddr_freq = 400 * MHz,
+		.dramtype = LPDDR4,
+		.num_channels = 2,
+		.stride = 13,
+		.odt = 1,
+	},
+	{
+		{
+			0x00000b00,	/* DENALI_CTL_00_DATA */
+			0x00000000,	/* DENALI_CTL_01_DATA */
+			0x00000000,	/* DENALI_CTL_02_DATA */
+			0x00000000,	/* DENALI_CTL_03_DATA */
+			0x00000000,	/* DENALI_CTL_04_DATA */
+			0x00013880,	/* DENALI_CTL_05_DATA */
+			0x000c3500,	/* DENALI_CTL_06_DATA */
+			0x00000005,	/* DENALI_CTL_07_DATA */
+			0x00000320,	/* DENALI_CTL_08_DATA */
+			0x00027100,	/* DENALI_CTL_09_DATA */
+			0x00186a00,	/* DENALI_CTL_10_DATA */
+			0x00000005,	/* DENALI_CTL_11_DATA */
+			0x00000640,	/* DENALI_CTL_12_DATA */
+			0x00002710,	/* DENALI_CTL_13_DATA */
+			0x000186a0,	/* DENALI_CTL_14_DATA */
+			0x00000005,	/* DENALI_CTL_15_DATA */
+			0x01000064,	/* DENALI_CTL_16_DATA */
+			0x00000000,	/* DENALI_CTL_17_DATA */
+			0x02020101,	/* DENALI_CTL_18_DATA */
+			0x00000102,	/* DENALI_CTL_19_DATA */
+			0x00000050,	/* DENALI_CTL_20_DATA */
+			0x000000c8,	/* DENALI_CTL_21_DATA */
+			0x00000000,	/* DENALI_CTL_22_DATA */
+			0x06140000,	/* DENALI_CTL_23_DATA */
+			0x00081c00,	/* DENALI_CTL_24_DATA */
+			0x0400040c,	/* DENALI_CTL_25_DATA */
+			0x19042008,	/* DENALI_CTL_26_DATA */
+			0x10080a11,	/* DENALI_CTL_27_DATA */
+			0x22310800,	/* DENALI_CTL_28_DATA */
+			0x00200f0a,	/* DENALI_CTL_29_DATA */
+			0x0a030704,	/* DENALI_CTL_30_DATA */
+			0x08000204,	/* DENALI_CTL_31_DATA */
+			0x00000a0a,	/* DENALI_CTL_32_DATA */
+			0x04006db0,	/* DENALI_CTL_33_DATA */
+			0x0a0a0804,	/* DENALI_CTL_34_DATA */
+			0x0600db60,	/* DENALI_CTL_35_DATA */
+			0x0a0a0806,	/* DENALI_CTL_36_DATA */
+			0x04000db6,	/* DENALI_CTL_37_DATA */
+			0x02030404,	/* DENALI_CTL_38_DATA */
+			0x0f0a0800,	/* DENALI_CTL_39_DATA */
+			0x08040411,	/* DENALI_CTL_40_DATA */
+			0x1400640a,	/* DENALI_CTL_41_DATA */
+			0x02010a0a,	/* DENALI_CTL_42_DATA */
+			0x00010001,	/* DENALI_CTL_43_DATA */
+			0x04082012,	/* DENALI_CTL_44_DATA */
+			0x00041109,	/* DENALI_CTL_45_DATA */
+			0x00000000,	/* DENALI_CTL_46_DATA */
+			0x03010000,	/* DENALI_CTL_47_DATA */
+			0x06100034,	/* DENALI_CTL_48_DATA */
+			0x0c280068,	/* DENALI_CTL_49_DATA */
+			0x00bb0007,	/* DENALI_CTL_50_DATA */
+			0x00000000,	/* DENALI_CTL_51_DATA */
+			0x00060003,	/* DENALI_CTL_52_DATA */
+			0x000a0003,	/* DENALI_CTL_53_DATA */
+			0x000a0014,	/* DENALI_CTL_54_DATA */
+			0x01000000,	/* DENALI_CTL_55_DATA */
+			0x030a0000,	/* DENALI_CTL_56_DATA */
+			0x0c000002,	/* DENALI_CTL_57_DATA */
+			0x00000103,	/* DENALI_CTL_58_DATA */
+			0x0003030a,	/* DENALI_CTL_59_DATA */
+			0x00060037,	/* DENALI_CTL_60_DATA */
+			0x0003006e,	/* DENALI_CTL_61_DATA */
+			0x05050007,	/* DENALI_CTL_62_DATA */
+			0x03020605,	/* DENALI_CTL_63_DATA */
+			0x06050301,	/* DENALI_CTL_64_DATA */
+			0x06020c05,	/* DENALI_CTL_65_DATA */
+			0x05050302,	/* DENALI_CTL_66_DATA */
+			0x03020305,	/* DENALI_CTL_67_DATA */
+			0x00000301,	/* DENALI_CTL_68_DATA */
+			0x00000301,	/* DENALI_CTL_69_DATA */
+			0x00000001,	/* DENALI_CTL_70_DATA */
+			0x00000000,	/* DENALI_CTL_71_DATA */
+			0x00000000,	/* DENALI_CTL_72_DATA */
+			0x01000000,	/* DENALI_CTL_73_DATA */
+			0x80104002,	/* DENALI_CTL_74_DATA */
+			0x00040003,	/* DENALI_CTL_75_DATA */
+			0x00040005,	/* DENALI_CTL_76_DATA */
+			0x00030000,	/* DENALI_CTL_77_DATA */
+			0x00050004,	/* DENALI_CTL_78_DATA */
+			0x00000004,	/* DENALI_CTL_79_DATA */
+			0x00040003,	/* DENALI_CTL_80_DATA */
+			0x00040005,	/* DENALI_CTL_81_DATA */
+			0x18400000,	/* DENALI_CTL_82_DATA */
+			0x00000c20,	/* DENALI_CTL_83_DATA */
+			0x185030a0,	/* DENALI_CTL_84_DATA */
+			0x02ec0000,	/* DENALI_CTL_85_DATA */
+			0x00000176,	/* DENALI_CTL_86_DATA */
+			0x00000000,	/* DENALI_CTL_87_DATA */
+			0x00000000,	/* DENALI_CTL_88_DATA */
+			0x00000000,	/* DENALI_CTL_89_DATA */
+			0x00000000,	/* DENALI_CTL_90_DATA */
+			0x00000000,	/* DENALI_CTL_91_DATA */
+			0x06030300,	/* DENALI_CTL_92_DATA */
+			0x00030303,	/* DENALI_CTL_93_DATA */
+			0x02030200,	/* DENALI_CTL_94_DATA */
+			0x00040703,	/* DENALI_CTL_95_DATA */
+			0x03020302,	/* DENALI_CTL_96_DATA */
+			0x02000407,	/* DENALI_CTL_97_DATA */
+			0x07030203,	/* DENALI_CTL_98_DATA */
+			0x00030f04,	/* DENALI_CTL_99_DATA */
+			0x00070004,	/* DENALI_CTL_100_DATA */
+			0x00000000,	/* DENALI_CTL_101_DATA */
+			0x00000000,	/* DENALI_CTL_102_DATA */
+			0x00000000,	/* DENALI_CTL_103_DATA */
+			0x00000000,	/* DENALI_CTL_104_DATA */
+			0x00000000,	/* DENALI_CTL_105_DATA */
+			0x00000000,	/* DENALI_CTL_106_DATA */
+			0x00000000,	/* DENALI_CTL_107_DATA */
+			0x00010000,	/* DENALI_CTL_108_DATA */
+			0x20040020,	/* DENALI_CTL_109_DATA */
+			0x00200400,	/* DENALI_CTL_110_DATA */
+			0x01000400,	/* DENALI_CTL_111_DATA */
+			0x00000b80,	/* DENALI_CTL_112_DATA */
+			0x00000000,	/* DENALI_CTL_113_DATA */
+			0x00000001,	/* DENALI_CTL_114_DATA */
+			0x00000002,	/* DENALI_CTL_115_DATA */
+			0x0000000e,	/* DENALI_CTL_116_DATA */
+			0x00000000,	/* DENALI_CTL_117_DATA */
+			0x00000000,	/* DENALI_CTL_118_DATA */
+			0x00000000,	/* DENALI_CTL_119_DATA */
+			0x00000000,	/* DENALI_CTL_120_DATA */
+			0x00000000,	/* DENALI_CTL_121_DATA */
+			0x00500000,	/* DENALI_CTL_122_DATA */
+			0x00640028,	/* DENALI_CTL_123_DATA */
+			0x00640404,	/* DENALI_CTL_124_DATA */
+			0x005000a0,	/* DENALI_CTL_125_DATA */
+			0x060600c8,	/* DENALI_CTL_126_DATA */
+			0x000a00c8,	/* DENALI_CTL_127_DATA */
+			0x000d0005,	/* DENALI_CTL_128_DATA */
+			0x000d0404,	/* DENALI_CTL_129_DATA */
+			0x00000000,	/* DENALI_CTL_130_DATA */
+			0x00000000,	/* DENALI_CTL_131_DATA */
+			0x00000000,	/* DENALI_CTL_132_DATA */
+			0x001400a3,	/* DENALI_CTL_133_DATA */
+			0x00e30009,	/* DENALI_CTL_134_DATA */
+			0x00120024,	/* DENALI_CTL_135_DATA */
+			0x00040063,	/* DENALI_CTL_136_DATA */
+			0x00000000,	/* DENALI_CTL_137_DATA */
+			0x00310031,	/* DENALI_CTL_138_DATA */
+			0x00000031,	/* DENALI_CTL_139_DATA */
+			0x004d0000,	/* DENALI_CTL_140_DATA */
+			0x004d004d,	/* DENALI_CTL_141_DATA */
+			0x004d0000,	/* DENALI_CTL_142_DATA */
+			0x004d004d,	/* DENALI_CTL_143_DATA */
+			0x00010101,	/* DENALI_CTL_144_DATA */
+			0x00000000,	/* DENALI_CTL_145_DATA */
+			0x00000000,	/* DENALI_CTL_146_DATA */
+			0x001400a3,	/* DENALI_CTL_147_DATA */
+			0x00e30009,	/* DENALI_CTL_148_DATA */
+			0x00120024,	/* DENALI_CTL_149_DATA */
+			0x00040063,	/* DENALI_CTL_150_DATA */
+			0x00000000,	/* DENALI_CTL_151_DATA */
+			0x00310031,	/* DENALI_CTL_152_DATA */
+			0x00000031,	/* DENALI_CTL_153_DATA */
+			0x004d0000,	/* DENALI_CTL_154_DATA */
+			0x004d004d,	/* DENALI_CTL_155_DATA */
+			0x004d0000,	/* DENALI_CTL_156_DATA */
+			0x004d004d,	/* DENALI_CTL_157_DATA */
+			0x00010101,	/* DENALI_CTL_158_DATA */
+			0x00000000,	/* DENALI_CTL_159_DATA */
+			0x00000000,	/* DENALI_CTL_160_DATA */
+			0x00000000,	/* DENALI_CTL_161_DATA */
+			0x00000001,	/* DENALI_CTL_162_DATA */
+			0x00000000,	/* DENALI_CTL_163_DATA */
+			0x18151100,	/* DENALI_CTL_164_DATA */
+			0x0000000c,	/* DENALI_CTL_165_DATA */
+			0x00000000,	/* DENALI_CTL_166_DATA */
+			0x00000000,	/* DENALI_CTL_167_DATA */
+			0x00000000,	/* DENALI_CTL_168_DATA */
+			0x00000000,	/* DENALI_CTL_169_DATA */
+			0x00000000,	/* DENALI_CTL_170_DATA */
+			0x00000000,	/* DENALI_CTL_171_DATA */
+			0x00000000,	/* DENALI_CTL_172_DATA */
+			0x00000000,	/* DENALI_CTL_173_DATA */
+			0x00000000,	/* DENALI_CTL_174_DATA */
+			0x00000000,	/* DENALI_CTL_175_DATA */
+			0x00000000,	/* DENALI_CTL_176_DATA */
+			0x00000000,	/* DENALI_CTL_177_DATA */
+			0x00000000,	/* DENALI_CTL_178_DATA */
+			0x00020003,	/* DENALI_CTL_179_DATA */
+			0x00400100,	/* DENALI_CTL_180_DATA */
+			0x000c0190,	/* DENALI_CTL_181_DATA */
+			0x01000200,	/* DENALI_CTL_182_DATA */
+			0x03200040,	/* DENALI_CTL_183_DATA */
+			0x00020018,	/* DENALI_CTL_184_DATA */
+			0x00400100,	/* DENALI_CTL_185_DATA */
+			0x00080032,	/* DENALI_CTL_186_DATA */
+			0x00140000,	/* DENALI_CTL_187_DATA */
+			0x00030028,	/* DENALI_CTL_188_DATA */
+			0x01010100,	/* DENALI_CTL_189_DATA */
+			0x02000202,	/* DENALI_CTL_190_DATA */
+			0x0b000002,	/* DENALI_CTL_191_DATA */
+			0x01000f0f,	/* DENALI_CTL_192_DATA */
+			0x00000000,	/* DENALI_CTL_193_DATA */
+			0x00000000,	/* DENALI_CTL_194_DATA */
+			0x00010003,	/* DENALI_CTL_195_DATA */
+			0x00000c03,	/* DENALI_CTL_196_DATA */
+			0x00040101,	/* DENALI_CTL_197_DATA */
+			0x04010100,	/* DENALI_CTL_198_DATA */
+			0x01000000,	/* DENALI_CTL_199_DATA */
+			0x02010000,	/* DENALI_CTL_200_DATA */
+			0x00000001,	/* DENALI_CTL_201_DATA */
+			0x00000000,	/* DENALI_CTL_202_DATA */
+			0x00000000,	/* DENALI_CTL_203_DATA */
+			0x00000000,	/* DENALI_CTL_204_DATA */
+			0x00000000,	/* DENALI_CTL_205_DATA */
+			0x00000000,	/* DENALI_CTL_206_DATA */
+			0x00000000,	/* DENALI_CTL_207_DATA */
+			0x00000000,	/* DENALI_CTL_208_DATA */
+			0x00000000,	/* DENALI_CTL_209_DATA */
+			0x00000000,	/* DENALI_CTL_210_DATA */
+			0x00010000,	/* DENALI_CTL_211_DATA */
+			0x00000001,	/* DENALI_CTL_212_DATA */
+			0x01010001,	/* DENALI_CTL_213_DATA */
+			0x05040001,	/* DENALI_CTL_214_DATA */
+			0x040a0703,	/* DENALI_CTL_215_DATA */
+			0x02080808,	/* DENALI_CTL_216_DATA */
+			0x020e000a,	/* DENALI_CTL_217_DATA */
+			0x020f010b,	/* DENALI_CTL_218_DATA */
+			0x000d0008,	/* DENALI_CTL_219_DATA */
+			0x00080b0a,	/* DENALI_CTL_220_DATA */
+			0x03000200,	/* DENALI_CTL_221_DATA */
+			0x00000100,	/* DENALI_CTL_222_DATA */
+			0x00000000,	/* DENALI_CTL_223_DATA */
+			0x00000000,	/* DENALI_CTL_224_DATA */
+			0x0d000001,	/* DENALI_CTL_225_DATA */
+			0x00000028,	/* DENALI_CTL_226_DATA */
+			0x00010000,	/* DENALI_CTL_227_DATA */
+			0x00000003,	/* DENALI_CTL_228_DATA */
+			0x00000000,	/* DENALI_CTL_229_DATA */
+			0x00000000,	/* DENALI_CTL_230_DATA */
+			0x00000000,	/* DENALI_CTL_231_DATA */
+			0x00000000,	/* DENALI_CTL_232_DATA */
+			0x00000000,	/* DENALI_CTL_233_DATA */
+			0x00000000,	/* DENALI_CTL_234_DATA */
+			0x00000000,	/* DENALI_CTL_235_DATA */
+			0x00000000,	/* DENALI_CTL_236_DATA */
+			0x00010100,	/* DENALI_CTL_237_DATA */
+			0x01000000,	/* DENALI_CTL_238_DATA */
+			0x00000001,	/* DENALI_CTL_239_DATA */
+			0x00000303,	/* DENALI_CTL_240_DATA */
+			0x00000000,	/* DENALI_CTL_241_DATA */
+			0x00000000,	/* DENALI_CTL_242_DATA */
+			0x00000000,	/* DENALI_CTL_243_DATA */
+			0x00000000,	/* DENALI_CTL_244_DATA */
+			0x00000000,	/* DENALI_CTL_245_DATA */
+			0x00000000,	/* DENALI_CTL_246_DATA */
+			0x00000000,	/* DENALI_CTL_247_DATA */
+			0x00000000,	/* DENALI_CTL_248_DATA */
+			0x00000000,	/* DENALI_CTL_249_DATA */
+			0x00000000,	/* DENALI_CTL_250_DATA */
+			0x00000000,	/* DENALI_CTL_251_DATA */
+			0x00000000,	/* DENALI_CTL_252_DATA */
+			0x00000000,	/* DENALI_CTL_253_DATA */
+			0x00000000,	/* DENALI_CTL_254_DATA */
+			0x00000000,	/* DENALI_CTL_255_DATA */
+			0x000556aa,	/* DENALI_CTL_256_DATA */
+			0x000aaaaa,	/* DENALI_CTL_257_DATA */
+			0x000aa955,	/* DENALI_CTL_258_DATA */
+			0x00055555,	/* DENALI_CTL_259_DATA */
+			0x000b3133,	/* DENALI_CTL_260_DATA */
+			0x0004cd33,	/* DENALI_CTL_261_DATA */
+			0x0004cecc,	/* DENALI_CTL_262_DATA */
+			0x000b32cc,	/* DENALI_CTL_263_DATA */
+			0x00010300,	/* DENALI_CTL_264_DATA */
+			0x03000100,	/* DENALI_CTL_265_DATA */
+			0x00000000,	/* DENALI_CTL_266_DATA */
+			0x00000000,	/* DENALI_CTL_267_DATA */
+			0x00000000,	/* DENALI_CTL_268_DATA */
+			0x00000000,	/* DENALI_CTL_269_DATA */
+			0x00000000,	/* DENALI_CTL_270_DATA */
+			0x00000000,	/* DENALI_CTL_271_DATA */
+			0x00000000,	/* DENALI_CTL_272_DATA */
+			0x00000000,	/* DENALI_CTL_273_DATA */
+			0x00ffff00,	/* DENALI_CTL_274_DATA */
+			0x1a160000,	/* DENALI_CTL_275_DATA */
+			0x08000012,	/* DENALI_CTL_276_DATA */
+			0x00000c20,	/* DENALI_CTL_277_DATA */
+			0x00000200,	/* DENALI_CTL_278_DATA */
+			0x00000200,	/* DENALI_CTL_279_DATA */
+			0x00000200,	/* DENALI_CTL_280_DATA */
+			0x00000200,	/* DENALI_CTL_281_DATA */
+			0x00000c20,	/* DENALI_CTL_282_DATA */
+			0x00007940,	/* DENALI_CTL_283_DATA */
+			0x18500409,	/* DENALI_CTL_284_DATA */
+			0x00000200,	/* DENALI_CTL_285_DATA */
+			0x00000200,	/* DENALI_CTL_286_DATA */
+			0x00000200,	/* DENALI_CTL_287_DATA */
+			0x00000200,	/* DENALI_CTL_288_DATA */
+			0x00001850,	/* DENALI_CTL_289_DATA */
+			0x0000f320,	/* DENALI_CTL_290_DATA */
+			0x0176060c,	/* DENALI_CTL_291_DATA */
+			0x00000200,	/* DENALI_CTL_292_DATA */
+			0x00000200,	/* DENALI_CTL_293_DATA */
+			0x00000200,	/* DENALI_CTL_294_DATA */
+			0x00000200,	/* DENALI_CTL_295_DATA */
+			0x00000176,	/* DENALI_CTL_296_DATA */
+			0x00000e9c,	/* DENALI_CTL_297_DATA */
+			0x02020205,	/* DENALI_CTL_298_DATA */
+			0x03030202,	/* DENALI_CTL_299_DATA */
+			0x00000018,	/* DENALI_CTL_300_DATA */
+			0x00000000,	/* DENALI_CTL_301_DATA */
+			0x00000000,	/* DENALI_CTL_302_DATA */
+			0x00001403,	/* DENALI_CTL_303_DATA */
+			0x00000000,	/* DENALI_CTL_304_DATA */
+			0x00000000,	/* DENALI_CTL_305_DATA */
+			0x00000000,	/* DENALI_CTL_306_DATA */
+			0x00030000,	/* DENALI_CTL_307_DATA */
+			0x000a001c,	/* DENALI_CTL_308_DATA */
+			0x000e0020,	/* DENALI_CTL_309_DATA */
+			0x00060018,	/* DENALI_CTL_310_DATA */
+			0x00000000,	/* DENALI_CTL_311_DATA */
+			0x00000000,	/* DENALI_CTL_312_DATA */
+			0x02000000,	/* DENALI_CTL_313_DATA */
+			0x00090305,	/* DENALI_CTL_314_DATA */
+			0x00050101,	/* DENALI_CTL_315_DATA */
+			0x00000000,	/* DENALI_CTL_316_DATA */
+			0x00000000,	/* DENALI_CTL_317_DATA */
+			0x00000000,	/* DENALI_CTL_318_DATA */
+			0x00000000,	/* DENALI_CTL_319_DATA */
+			0x00000000,	/* DENALI_CTL_320_DATA */
+			0x00000000,	/* DENALI_CTL_321_DATA */
+			0x00000000,	/* DENALI_CTL_322_DATA */
+			0x00000000,	/* DENALI_CTL_323_DATA */
+			0x01000001,	/* DENALI_CTL_324_DATA */
+			0x01010101,	/* DENALI_CTL_325_DATA */
+			0x01000101,	/* DENALI_CTL_326_DATA */
+			0x01000100,	/* DENALI_CTL_327_DATA */
+			0x00010001,	/* DENALI_CTL_328_DATA */
+			0x00010002,	/* DENALI_CTL_329_DATA */
+			0x00020100,	/* DENALI_CTL_330_DATA */
+			0x00000002	/* DENALI_CTL_331_DATA */
+		}
+	},
+	{
+		{
+			0x00000b00,	/* DENALI_PI_00_DATA */
+			0x00000000,	/* DENALI_PI_01_DATA */
+			0x000002ec,	/* DENALI_PI_02_DATA */
+			0x00000176,	/* DENALI_PI_03_DATA */
+			0x000030a0,	/* DENALI_PI_04_DATA */
+			0x00001850,	/* DENALI_PI_05_DATA */
+			0x00001840,	/* DENALI_PI_06_DATA */
+			0x01760c20,	/* DENALI_PI_07_DATA */
+			0x00000200,	/* DENALI_PI_08_DATA */
+			0x00000200,	/* DENALI_PI_09_DATA */
+			0x00000200,	/* DENALI_PI_10_DATA */
+			0x00000200,	/* DENALI_PI_11_DATA */
+			0x00001850,	/* DENALI_PI_12_DATA */
+			0x00000200,	/* DENALI_PI_13_DATA */
+			0x00000200,	/* DENALI_PI_14_DATA */
+			0x00000200,	/* DENALI_PI_15_DATA */
+			0x00000200,	/* DENALI_PI_16_DATA */
+			0x00000c20,	/* DENALI_PI_17_DATA */
+			0x00000200,	/* DENALI_PI_18_DATA */
+			0x00000200,	/* DENALI_PI_19_DATA */
+			0x00000200,	/* DENALI_PI_20_DATA */
+			0x00000200,	/* DENALI_PI_21_DATA */
+			0x00010000,	/* DENALI_PI_22_DATA */
+			0x00000007,	/* DENALI_PI_23_DATA */
+			0x01000001,	/* DENALI_PI_24_DATA */
+			0x00000000,	/* DENALI_PI_25_DATA */
+			0x3fffffff,	/* DENALI_PI_26_DATA */
+			0x00000000,	/* DENALI_PI_27_DATA */
+			0x00000000,	/* DENALI_PI_28_DATA */
+			0x00000000,	/* DENALI_PI_29_DATA */
+			0x00000000,	/* DENALI_PI_30_DATA */
+			0x00000000,	/* DENALI_PI_31_DATA */
+			0x00000000,	/* DENALI_PI_32_DATA */
+			0x00000000,	/* DENALI_PI_33_DATA */
+			0x00000000,	/* DENALI_PI_34_DATA */
+			0x00000000,	/* DENALI_PI_35_DATA */
+			0x00000000,	/* DENALI_PI_36_DATA */
+			0x00000000,	/* DENALI_PI_37_DATA */
+			0x00000000,	/* DENALI_PI_38_DATA */
+			0x00000000,	/* DENALI_PI_39_DATA */
+			0x00000000,	/* DENALI_PI_40_DATA */
+			0x0f000101,	/* DENALI_PI_41_DATA */
+			0x082b3223,	/* DENALI_PI_42_DATA */
+			0x080c0004,	/* DENALI_PI_43_DATA */
+			0x00061c00,	/* DENALI_PI_44_DATA */
+			0x00000214,	/* DENALI_PI_45_DATA */
+			0x00bb0007,	/* DENALI_PI_46_DATA */
+			0x0c280068,	/* DENALI_PI_47_DATA */
+			0x06100034,	/* DENALI_PI_48_DATA */
+			0x00000500,	/* DENALI_PI_49_DATA */
+			0x00000000,	/* DENALI_PI_50_DATA */
+			0x00000000,	/* DENALI_PI_51_DATA */
+			0x00000000,	/* DENALI_PI_52_DATA */
+			0x00000000,	/* DENALI_PI_53_DATA */
+			0x00000000,	/* DENALI_PI_54_DATA */
+			0x00000000,	/* DENALI_PI_55_DATA */
+			0x00000000,	/* DENALI_PI_56_DATA */
+			0x00000000,	/* DENALI_PI_57_DATA */
+			0x04040100,	/* DENALI_PI_58_DATA */
+			0x0a000004,	/* DENALI_PI_59_DATA */
+			0x00000128,	/* DENALI_PI_60_DATA */
+			0x00000000,	/* DENALI_PI_61_DATA */
+			0x0003000f,	/* DENALI_PI_62_DATA */
+			0x00000018,	/* DENALI_PI_63_DATA */
+			0x00000000,	/* DENALI_PI_64_DATA */
+			0x00000000,	/* DENALI_PI_65_DATA */
+			0x00060002,	/* DENALI_PI_66_DATA */
+			0x00010001,	/* DENALI_PI_67_DATA */
+			0x00000101,	/* DENALI_PI_68_DATA */
+			0x00020001,	/* DENALI_PI_69_DATA */
+			0x00080004,	/* DENALI_PI_70_DATA */
+			0x00000000,	/* DENALI_PI_71_DATA */
+			0x05030000,	/* DENALI_PI_72_DATA */
+			0x070a0404,	/* DENALI_PI_73_DATA */
+			0x00000000,	/* DENALI_PI_74_DATA */
+			0x00000000,	/* DENALI_PI_75_DATA */
+			0x00000000,	/* DENALI_PI_76_DATA */
+			0x000f0f00,	/* DENALI_PI_77_DATA */
+			0x0000001e,	/* DENALI_PI_78_DATA */
+			0x00000000,	/* DENALI_PI_79_DATA */
+			0x01010300,	/* DENALI_PI_80_DATA */
+			0x00000000,	/* DENALI_PI_81_DATA */
+			0x00000000,	/* DENALI_PI_82_DATA */
+			0x01000000,	/* DENALI_PI_83_DATA */
+			0x00000101,	/* DENALI_PI_84_DATA */
+			0x55555a5a,	/* DENALI_PI_85_DATA */
+			0x55555a5a,	/* DENALI_PI_86_DATA */
+			0x55555a5a,	/* DENALI_PI_87_DATA */
+			0x55555a5a,	/* DENALI_PI_88_DATA */
+			0x0c050001,	/* DENALI_PI_89_DATA */
+			0x06020009,	/* DENALI_PI_90_DATA */
+			0x00010004,	/* DENALI_PI_91_DATA */
+			0x00000203,	/* DENALI_PI_92_DATA */
+			0x00030000,	/* DENALI_PI_93_DATA */
+			0x170f0000,	/* DENALI_PI_94_DATA */
+			0x00060018,	/* DENALI_PI_95_DATA */
+			0x000e0020,	/* DENALI_PI_96_DATA */
+			0x000a001c,	/* DENALI_PI_97_DATA */
+			0x00000000,	/* DENALI_PI_98_DATA */
+			0x00000000,	/* DENALI_PI_99_DATA */
+			0x00000100,	/* DENALI_PI_100_DATA */
+			0x140a0000,	/* DENALI_PI_101_DATA */
+			0x000d010a,	/* DENALI_PI_102_DATA */
+			0x0100c802,	/* DENALI_PI_103_DATA */
+			0x010a0064,	/* DENALI_PI_104_DATA */
+			0x000e0100,	/* DENALI_PI_105_DATA */
+			0x0100000e,	/* DENALI_PI_106_DATA */
+			0x00c900c9,	/* DENALI_PI_107_DATA */
+			0x00650100,	/* DENALI_PI_108_DATA */
+			0x1e1a0065,	/* DENALI_PI_109_DATA */
+			0x10010204,	/* DENALI_PI_110_DATA */
+			0x06070605,	/* DENALI_PI_111_DATA */
+			0x20000202,	/* DENALI_PI_112_DATA */
+			0x00201000,	/* DENALI_PI_113_DATA */
+			0x00201000,	/* DENALI_PI_114_DATA */
+			0x04041000,	/* DENALI_PI_115_DATA */
+			0x10020100,	/* DENALI_PI_116_DATA */
+			0x0003010c,	/* DENALI_PI_117_DATA */
+			0x004b004a,	/* DENALI_PI_118_DATA */
+			0x1a0f0000,	/* DENALI_PI_119_DATA */
+			0x0102041e,	/* DENALI_PI_120_DATA */
+			0x34000000,	/* DENALI_PI_121_DATA */
+			0x00000000,	/* DENALI_PI_122_DATA */
+			0x00000000,	/* DENALI_PI_123_DATA */
+			0x00010000,	/* DENALI_PI_124_DATA */
+			0x00000400,	/* DENALI_PI_125_DATA */
+			0x00310000,	/* DENALI_PI_126_DATA */
+			0x004d4d00,	/* DENALI_PI_127_DATA */
+			0x00120024,	/* DENALI_PI_128_DATA */
+			0x4d000031,	/* DENALI_PI_129_DATA */
+			0x0000144d,	/* DENALI_PI_130_DATA */
+			0x00310009,	/* DENALI_PI_131_DATA */
+			0x004d4d00,	/* DENALI_PI_132_DATA */
+			0x00000004,	/* DENALI_PI_133_DATA */
+			0x4d000031,	/* DENALI_PI_134_DATA */
+			0x0000244d,	/* DENALI_PI_135_DATA */
+			0x00310012,	/* DENALI_PI_136_DATA */
+			0x004d4d00,	/* DENALI_PI_137_DATA */
+			0x00090014,	/* DENALI_PI_138_DATA */
+			0x4d000031,	/* DENALI_PI_139_DATA */
+			0x0004004d,	/* DENALI_PI_140_DATA */
+			0x00310000,	/* DENALI_PI_141_DATA */
+			0x004d4d00,	/* DENALI_PI_142_DATA */
+			0x00120024,	/* DENALI_PI_143_DATA */
+			0x4d000031,	/* DENALI_PI_144_DATA */
+			0x0000144d,	/* DENALI_PI_145_DATA */
+			0x00310009,	/* DENALI_PI_146_DATA */
+			0x004d4d00,	/* DENALI_PI_147_DATA */
+			0x00000004,	/* DENALI_PI_148_DATA */
+			0x4d000031,	/* DENALI_PI_149_DATA */
+			0x0000244d,	/* DENALI_PI_150_DATA */
+			0x00310012,	/* DENALI_PI_151_DATA */
+			0x004d4d00,	/* DENALI_PI_152_DATA */
+			0x00090014,	/* DENALI_PI_153_DATA */
+			0x4d000031,	/* DENALI_PI_154_DATA */
+			0x0200004d,	/* DENALI_PI_155_DATA */
+			0x00c8000d,	/* DENALI_PI_156_DATA */
+			0x08080064,	/* DENALI_PI_157_DATA */
+			0x040a0404,	/* DENALI_PI_158_DATA */
+			0x03000d92,	/* DENALI_PI_159_DATA */
+			0x010a2001,	/* DENALI_PI_160_DATA */
+			0x0f11080a,	/* DENALI_PI_161_DATA */
+			0x0000110a,	/* DENALI_PI_162_DATA */
+			0x2200d92e,	/* DENALI_PI_163_DATA */
+			0x080c2003,	/* DENALI_PI_164_DATA */
+			0x0809080a,	/* DENALI_PI_165_DATA */
+			0x00000a0a,	/* DENALI_PI_166_DATA */
+			0x11006c97,	/* DENALI_PI_167_DATA */
+			0x040a2002,	/* DENALI_PI_168_DATA */
+			0x0200020a,	/* DENALI_PI_169_DATA */
+			0x02000200,	/* DENALI_PI_170_DATA */
+			0x02000200,	/* DENALI_PI_171_DATA */
+			0x02000200,	/* DENALI_PI_172_DATA */
+			0x02000200,	/* DENALI_PI_173_DATA */
+			0x00000000,	/* DENALI_PI_174_DATA */
+			0x00000000,	/* DENALI_PI_175_DATA */
+			0x00000000,	/* DENALI_PI_176_DATA */
+			0x00000000,	/* DENALI_PI_177_DATA */
+			0x00000000,	/* DENALI_PI_178_DATA */
+			0x00000000,	/* DENALI_PI_179_DATA */
+			0x00000000,	/* DENALI_PI_180_DATA */
+			0x00000000,	/* DENALI_PI_181_DATA */
+			0x00000000,	/* DENALI_PI_182_DATA */
+			0x00000000,	/* DENALI_PI_183_DATA */
+			0x00000000,	/* DENALI_PI_184_DATA */
+			0x00000000,	/* DENALI_PI_185_DATA */
+			0x01000400,	/* DENALI_PI_186_DATA */
+			0x00017600,	/* DENALI_PI_187_DATA */
+			0x00000e9c,	/* DENALI_PI_188_DATA */
+			0x00001850,	/* DENALI_PI_189_DATA */
+			0x0000f320,	/* DENALI_PI_190_DATA */
+			0x00000c20,	/* DENALI_PI_191_DATA */
+			0x00007940,	/* DENALI_PI_192_DATA */
+			0x08000000,	/* DENALI_PI_193_DATA */
+			0x00000100,	/* DENALI_PI_194_DATA */
+			0x00000000,	/* DENALI_PI_195_DATA */
+			0x00000000,	/* DENALI_PI_196_DATA */
+			0x00000000,	/* DENALI_PI_197_DATA */
+			0x00000000,	/* DENALI_PI_198_DATA */
+			0x00000002	/* DENALI_PI_199_DATA */
+		}
+	},
+	{
+		{
+			0x76543210,	/* DENALI_PHY_00_DATA */
+			0x0004f008,	/* DENALI_PHY_01_DATA */
+			0x00020119,	/* DENALI_PHY_02_DATA */
+			0x00000000,	/* DENALI_PHY_03_DATA */
+			0x00000000,	/* DENALI_PHY_04_DATA */
+			0x00010000,	/* DENALI_PHY_05_DATA */
+			0x01665555,	/* DENALI_PHY_06_DATA */
+			0x03665555,	/* DENALI_PHY_07_DATA */
+			0x00010f00,	/* DENALI_PHY_08_DATA */
+			0x04000100,	/* DENALI_PHY_09_DATA */
+			0x00000001,	/* DENALI_PHY_10_DATA */
+			0x00170180,	/* DENALI_PHY_11_DATA */
+			0x00cc0201,	/* DENALI_PHY_12_DATA */
+			0x00030066,	/* DENALI_PHY_13_DATA */
+			0x00000000,	/* DENALI_PHY_14_DATA */
+			0x00000000,	/* DENALI_PHY_15_DATA */
+			0x00000000,	/* DENALI_PHY_16_DATA */
+			0x00000000,	/* DENALI_PHY_17_DATA */
+			0x00000000,	/* DENALI_PHY_18_DATA */
+			0x00000000,	/* DENALI_PHY_19_DATA */
+			0x00000000,	/* DENALI_PHY_20_DATA */
+			0x00000000,	/* DENALI_PHY_21_DATA */
+			0x04080000,	/* DENALI_PHY_22_DATA */
+			0x04080400,	/* DENALI_PHY_23_DATA */
+			0x30000000,	/* DENALI_PHY_24_DATA */
+			0x0c00c007,	/* DENALI_PHY_25_DATA */
+			0x00000100,	/* DENALI_PHY_26_DATA */
+			0x00000000,	/* DENALI_PHY_27_DATA */
+			0xfd02fe01,	/* DENALI_PHY_28_DATA */
+			0xf708fb04,	/* DENALI_PHY_29_DATA */
+			0xdf20ef10,	/* DENALI_PHY_30_DATA */
+			0x7f80bf40,	/* DENALI_PHY_31_DATA */
+			0x0001aaaa,	/* DENALI_PHY_32_DATA */
+			0x00000000,	/* DENALI_PHY_33_DATA */
+			0x00000000,	/* DENALI_PHY_34_DATA */
+			0x00000000,	/* DENALI_PHY_35_DATA */
+			0x00000000,	/* DENALI_PHY_36_DATA */
+			0x00000000,	/* DENALI_PHY_37_DATA */
+			0x00000000,	/* DENALI_PHY_38_DATA */
+			0x00000000,	/* DENALI_PHY_39_DATA */
+			0x00000000,	/* DENALI_PHY_40_DATA */
+			0x00000000,	/* DENALI_PHY_41_DATA */
+			0x00000000,	/* DENALI_PHY_42_DATA */
+			0x00000000,	/* DENALI_PHY_43_DATA */
+			0x00000000,	/* DENALI_PHY_44_DATA */
+			0x00000000,	/* DENALI_PHY_45_DATA */
+			0x00000000,	/* DENALI_PHY_46_DATA */
+			0x00000000,	/* DENALI_PHY_47_DATA */
+			0x00000000,	/* DENALI_PHY_48_DATA */
+			0x00000000,	/* DENALI_PHY_49_DATA */
+			0x00000000,	/* DENALI_PHY_50_DATA */
+			0x00000000,	/* DENALI_PHY_51_DATA */
+			0x00200000,	/* DENALI_PHY_52_DATA */
+			0x00000000,	/* DENALI_PHY_53_DATA */
+			0x00000000,	/* DENALI_PHY_54_DATA */
+			0x00000000,	/* DENALI_PHY_55_DATA */
+			0x00000000,	/* DENALI_PHY_56_DATA */
+			0x00000000,	/* DENALI_PHY_57_DATA */
+			0x00000000,	/* DENALI_PHY_58_DATA */
+			0x02800280,	/* DENALI_PHY_59_DATA */
+			0x02800280,	/* DENALI_PHY_60_DATA */
+			0x02800280,	/* DENALI_PHY_61_DATA */
+			0x02800280,	/* DENALI_PHY_62_DATA */
+			0x00000280,	/* DENALI_PHY_63_DATA */
+			0x00000000,	/* DENALI_PHY_64_DATA */
+			0x00000000,	/* DENALI_PHY_65_DATA */
+			0x00000000,	/* DENALI_PHY_66_DATA */
+			0x00000000,	/* DENALI_PHY_67_DATA */
+			0x00800000,	/* DENALI_PHY_68_DATA */
+			0x00800080,	/* DENALI_PHY_69_DATA */
+			0x00800080,	/* DENALI_PHY_70_DATA */
+			0x00800080,	/* DENALI_PHY_71_DATA */
+			0x00800080,	/* DENALI_PHY_72_DATA */
+			0x00800080,	/* DENALI_PHY_73_DATA */
+			0x00800080,	/* DENALI_PHY_74_DATA */
+			0x00800080,	/* DENALI_PHY_75_DATA */
+			0x00800080,	/* DENALI_PHY_76_DATA */
+			0x01190080,	/* DENALI_PHY_77_DATA */
+			0x00000001,	/* DENALI_PHY_78_DATA */
+			0x00000000,	/* DENALI_PHY_79_DATA */
+			0x00000000,	/* DENALI_PHY_80_DATA */
+			0x00000200,	/* DENALI_PHY_81_DATA */
+			0x00000000,	/* DENALI_PHY_82_DATA */
+			0x51315152,	/* DENALI_PHY_83_DATA */
+			0xc0003150,	/* DENALI_PHY_84_DATA */
+			0x010000c0,	/* DENALI_PHY_85_DATA */
+			0x00100000,	/* DENALI_PHY_86_DATA */
+			0x07044204,	/* DENALI_PHY_87_DATA */
+			0x000f0c18,	/* DENALI_PHY_88_DATA */
+			0x01000140,	/* DENALI_PHY_89_DATA */
+			0x00000c10,	/* DENALI_PHY_90_DATA */
+			0x00000000,	/* DENALI_PHY_91_DATA */
+			0x00000000,	/* DENALI_PHY_92_DATA */
+			0x00000000,	/* DENALI_PHY_93_DATA */
+			0x00000000,	/* DENALI_PHY_94_DATA */
+			0x00000000,	/* DENALI_PHY_95_DATA */
+			0x00000000,	/* DENALI_PHY_96_DATA */
+			0x00000000,	/* DENALI_PHY_97_DATA */
+			0x00000000,	/* DENALI_PHY_98_DATA */
+			0x00000000,	/* DENALI_PHY_99_DATA */
+			0x00000000,	/* DENALI_PHY_100_DATA */
+			0x00000000,	/* DENALI_PHY_101_DATA */
+			0x00000000,	/* DENALI_PHY_102_DATA */
+			0x00000000,	/* DENALI_PHY_103_DATA */
+			0x00000000,	/* DENALI_PHY_104_DATA */
+			0x00000000,	/* DENALI_PHY_105_DATA */
+			0x00000000,	/* DENALI_PHY_106_DATA */
+			0x00000000,	/* DENALI_PHY_107_DATA */
+			0x00000000,	/* DENALI_PHY_108_DATA */
+			0x00000000,	/* DENALI_PHY_109_DATA */
+			0x00000000,	/* DENALI_PHY_110_DATA */
+			0x00000000,	/* DENALI_PHY_111_DATA */
+			0x00000000,	/* DENALI_PHY_112_DATA */
+			0x00000000,	/* DENALI_PHY_113_DATA */
+			0x00000000,	/* DENALI_PHY_114_DATA */
+			0x00000000,	/* DENALI_PHY_115_DATA */
+			0x00000000,	/* DENALI_PHY_116_DATA */
+			0x00000000,	/* DENALI_PHY_117_DATA */
+			0x00000000,	/* DENALI_PHY_118_DATA */
+			0x00000000,	/* DENALI_PHY_119_DATA */
+			0x00000000,	/* DENALI_PHY_120_DATA */
+			0x00000000,	/* DENALI_PHY_121_DATA */
+			0x00000000,	/* DENALI_PHY_122_DATA */
+			0x00000000,	/* DENALI_PHY_123_DATA */
+			0x00000000,	/* DENALI_PHY_124_DATA */
+			0x00000000,	/* DENALI_PHY_125_DATA */
+			0x00000000,	/* DENALI_PHY_126_DATA */
+			0x00000000,	/* DENALI_PHY_127_DATA */
+			0x76543210,	/* DENALI_PHY_128_DATA */
+			0x0004f008,	/* DENALI_PHY_129_DATA */
+			0x00020119,	/* DENALI_PHY_130_DATA */
+			0x00000000,	/* DENALI_PHY_131_DATA */
+			0x00000000,	/* DENALI_PHY_132_DATA */
+			0x00010000,	/* DENALI_PHY_133_DATA */
+			0x01665555,	/* DENALI_PHY_134_DATA */
+			0x03665555,	/* DENALI_PHY_135_DATA */
+			0x00010f00,	/* DENALI_PHY_136_DATA */
+			0x04000100,	/* DENALI_PHY_137_DATA */
+			0x00000001,	/* DENALI_PHY_138_DATA */
+			0x00170180,	/* DENALI_PHY_139_DATA */
+			0x00cc0201,	/* DENALI_PHY_140_DATA */
+			0x00030066,	/* DENALI_PHY_141_DATA */
+			0x00000000,	/* DENALI_PHY_142_DATA */
+			0x00000000,	/* DENALI_PHY_143_DATA */
+			0x00000000,	/* DENALI_PHY_144_DATA */
+			0x00000000,	/* DENALI_PHY_145_DATA */
+			0x00000000,	/* DENALI_PHY_146_DATA */
+			0x00000000,	/* DENALI_PHY_147_DATA */
+			0x00000000,	/* DENALI_PHY_148_DATA */
+			0x00000000,	/* DENALI_PHY_149_DATA */
+			0x04080000,	/* DENALI_PHY_150_DATA */
+			0x04080400,	/* DENALI_PHY_151_DATA */
+			0x30000000,	/* DENALI_PHY_152_DATA */
+			0x0c00c007,	/* DENALI_PHY_153_DATA */
+			0x00000100,	/* DENALI_PHY_154_DATA */
+			0x00000000,	/* DENALI_PHY_155_DATA */
+			0xfd02fe01,	/* DENALI_PHY_156_DATA */
+			0xf708fb04,	/* DENALI_PHY_157_DATA */
+			0xdf20ef10,	/* DENALI_PHY_158_DATA */
+			0x7f80bf40,	/* DENALI_PHY_159_DATA */
+			0x0000aaaa,	/* DENALI_PHY_160_DATA */
+			0x00000000,	/* DENALI_PHY_161_DATA */
+			0x00000000,	/* DENALI_PHY_162_DATA */
+			0x00000000,	/* DENALI_PHY_163_DATA */
+			0x00000000,	/* DENALI_PHY_164_DATA */
+			0x00000000,	/* DENALI_PHY_165_DATA */
+			0x00000000,	/* DENALI_PHY_166_DATA */
+			0x00000000,	/* DENALI_PHY_167_DATA */
+			0x00000000,	/* DENALI_PHY_168_DATA */
+			0x00000000,	/* DENALI_PHY_169_DATA */
+			0x00000000,	/* DENALI_PHY_170_DATA */
+			0x00000000,	/* DENALI_PHY_171_DATA */
+			0x00000000,	/* DENALI_PHY_172_DATA */
+			0x00000000,	/* DENALI_PHY_173_DATA */
+			0x00000000,	/* DENALI_PHY_174_DATA */
+			0x00000000,	/* DENALI_PHY_175_DATA */
+			0x00000000,	/* DENALI_PHY_176_DATA */
+			0x00000000,	/* DENALI_PHY_177_DATA */
+			0x00000000,	/* DENALI_PHY_178_DATA */
+			0x00000000,	/* DENALI_PHY_179_DATA */
+			0x00200000,	/* DENALI_PHY_180_DATA */
+			0x00000000,	/* DENALI_PHY_181_DATA */
+			0x00000000,	/* DENALI_PHY_182_DATA */
+			0x00000000,	/* DENALI_PHY_183_DATA */
+			0x00000000,	/* DENALI_PHY_184_DATA */
+			0x00000000,	/* DENALI_PHY_185_DATA */
+			0x00000000,	/* DENALI_PHY_186_DATA */
+			0x02800280,	/* DENALI_PHY_187_DATA */
+			0x02800280,	/* DENALI_PHY_188_DATA */
+			0x02800280,	/* DENALI_PHY_189_DATA */
+			0x02800280,	/* DENALI_PHY_190_DATA */
+			0x00000280,	/* DENALI_PHY_191_DATA */
+			0x00000000,	/* DENALI_PHY_192_DATA */
+			0x00000000,	/* DENALI_PHY_193_DATA */
+			0x00000000,	/* DENALI_PHY_194_DATA */
+			0x00000000,	/* DENALI_PHY_195_DATA */
+			0x00800000,	/* DENALI_PHY_196_DATA */
+			0x00800080,	/* DENALI_PHY_197_DATA */
+			0x00800080,	/* DENALI_PHY_198_DATA */
+			0x00800080,	/* DENALI_PHY_199_DATA */
+			0x00800080,	/* DENALI_PHY_200_DATA */
+			0x00800080,	/* DENALI_PHY_201_DATA */
+			0x00800080,	/* DENALI_PHY_202_DATA */
+			0x00800080,	/* DENALI_PHY_203_DATA */
+			0x00800080,	/* DENALI_PHY_204_DATA */
+			0x01190080,	/* DENALI_PHY_205_DATA */
+			0x00000001,	/* DENALI_PHY_206_DATA */
+			0x00000000,	/* DENALI_PHY_207_DATA */
+			0x00000000,	/* DENALI_PHY_208_DATA */
+			0x00000200,	/* DENALI_PHY_209_DATA */
+			0x00000000,	/* DENALI_PHY_210_DATA */
+			0x51315152,	/* DENALI_PHY_211_DATA */
+			0xc0003150,	/* DENALI_PHY_212_DATA */
+			0x010000c0,	/* DENALI_PHY_213_DATA */
+			0x00100000,	/* DENALI_PHY_214_DATA */
+			0x07044204,	/* DENALI_PHY_215_DATA */
+			0x000f0c18,	/* DENALI_PHY_216_DATA */
+			0x01000140,	/* DENALI_PHY_217_DATA */
+			0x00000c10,	/* DENALI_PHY_218_DATA */
+			0x00000000,	/* DENALI_PHY_219_DATA */
+			0x00000000,	/* DENALI_PHY_220_DATA */
+			0x00000000,	/* DENALI_PHY_221_DATA */
+			0x00000000,	/* DENALI_PHY_222_DATA */
+			0x00000000,	/* DENALI_PHY_223_DATA */
+			0x00000000,	/* DENALI_PHY_224_DATA */
+			0x00000000,	/* DENALI_PHY_225_DATA */
+			0x00000000,	/* DENALI_PHY_226_DATA */
+			0x00000000,	/* DENALI_PHY_227_DATA */
+			0x00000000,	/* DENALI_PHY_228_DATA */
+			0x00000000,	/* DENALI_PHY_229_DATA */
+			0x00000000,	/* DENALI_PHY_230_DATA */
+			0x00000000,	/* DENALI_PHY_231_DATA */
+			0x00000000,	/* DENALI_PHY_232_DATA */
+			0x00000000,	/* DENALI_PHY_233_DATA */
+			0x00000000,	/* DENALI_PHY_234_DATA */
+			0x00000000,	/* DENALI_PHY_235_DATA */
+			0x00000000,	/* DENALI_PHY_236_DATA */
+			0x00000000,	/* DENALI_PHY_237_DATA */
+			0x00000000,	/* DENALI_PHY_238_DATA */
+			0x00000000,	/* DENALI_PHY_239_DATA */
+			0x00000000,	/* DENALI_PHY_240_DATA */
+			0x00000000,	/* DENALI_PHY_241_DATA */
+			0x00000000,	/* DENALI_PHY_242_DATA */
+			0x00000000,	/* DENALI_PHY_243_DATA */
+			0x00000000,	/* DENALI_PHY_244_DATA */
+			0x00000000,	/* DENALI_PHY_245_DATA */
+			0x00000000,	/* DENALI_PHY_246_DATA */
+			0x00000000,	/* DENALI_PHY_247_DATA */
+			0x00000000,	/* DENALI_PHY_248_DATA */
+			0x00000000,	/* DENALI_PHY_249_DATA */
+			0x00000000,	/* DENALI_PHY_250_DATA */
+			0x00000000,	/* DENALI_PHY_251_DATA */
+			0x00000000,	/* DENALI_PHY_252_DATA */
+			0x00000000,	/* DENALI_PHY_253_DATA */
+			0x00000000,	/* DENALI_PHY_254_DATA */
+			0x00000000,	/* DENALI_PHY_255_DATA */
+			0x76543210,	/* DENALI_PHY_256_DATA */
+			0x0004f008,	/* DENALI_PHY_257_DATA */
+			0x00020119,	/* DENALI_PHY_258_DATA */
+			0x00000000,	/* DENALI_PHY_259_DATA */
+			0x00000000,	/* DENALI_PHY_260_DATA */
+			0x00010000,	/* DENALI_PHY_261_DATA */
+			0x01665555,	/* DENALI_PHY_262_DATA */
+			0x03665555,	/* DENALI_PHY_263_DATA */
+			0x00010f00,	/* DENALI_PHY_264_DATA */
+			0x04000100,	/* DENALI_PHY_265_DATA */
+			0x00000001,	/* DENALI_PHY_266_DATA */
+			0x00170180,	/* DENALI_PHY_267_DATA */
+			0x00cc0201,	/* DENALI_PHY_268_DATA */
+			0x00030066,	/* DENALI_PHY_269_DATA */
+			0x00000000,	/* DENALI_PHY_270_DATA */
+			0x00000000,	/* DENALI_PHY_271_DATA */
+			0x00000000,	/* DENALI_PHY_272_DATA */
+			0x00000000,	/* DENALI_PHY_273_DATA */
+			0x00000000,	/* DENALI_PHY_274_DATA */
+			0x00000000,	/* DENALI_PHY_275_DATA */
+			0x00000000,	/* DENALI_PHY_276_DATA */
+			0x00000000,	/* DENALI_PHY_277_DATA */
+			0x04080000,	/* DENALI_PHY_278_DATA */
+			0x04080400,	/* DENALI_PHY_279_DATA */
+			0x30000000,	/* DENALI_PHY_280_DATA */
+			0x0c00c007,	/* DENALI_PHY_281_DATA */
+			0x00000100,	/* DENALI_PHY_282_DATA */
+			0x00000000,	/* DENALI_PHY_283_DATA */
+			0xfd02fe01,	/* DENALI_PHY_284_DATA */
+			0xf708fb04,	/* DENALI_PHY_285_DATA */
+			0xdf20ef10,	/* DENALI_PHY_286_DATA */
+			0x7f80bf40,	/* DENALI_PHY_287_DATA */
+			0x0001aaaa,	/* DENALI_PHY_288_DATA */
+			0x00000000,	/* DENALI_PHY_289_DATA */
+			0x00000000,	/* DENALI_PHY_290_DATA */
+			0x00000000,	/* DENALI_PHY_291_DATA */
+			0x00000000,	/* DENALI_PHY_292_DATA */
+			0x00000000,	/* DENALI_PHY_293_DATA */
+			0x00000000,	/* DENALI_PHY_294_DATA */
+			0x00000000,	/* DENALI_PHY_295_DATA */
+			0x00000000,	/* DENALI_PHY_296_DATA */
+			0x00000000,	/* DENALI_PHY_297_DATA */
+			0x00000000,	/* DENALI_PHY_298_DATA */
+			0x00000000,	/* DENALI_PHY_299_DATA */
+			0x00000000,	/* DENALI_PHY_300_DATA */
+			0x00000000,	/* DENALI_PHY_301_DATA */
+			0x00000000,	/* DENALI_PHY_302_DATA */
+			0x00000000,	/* DENALI_PHY_303_DATA */
+			0x00000000,	/* DENALI_PHY_304_DATA */
+			0x00000000,	/* DENALI_PHY_305_DATA */
+			0x00000000,	/* DENALI_PHY_306_DATA */
+			0x00000000,	/* DENALI_PHY_307_DATA */
+			0x00200000,	/* DENALI_PHY_308_DATA */
+			0x00000000,	/* DENALI_PHY_309_DATA */
+			0x00000000,	/* DENALI_PHY_310_DATA */
+			0x00000000,	/* DENALI_PHY_311_DATA */
+			0x00000000,	/* DENALI_PHY_312_DATA */
+			0x00000000,	/* DENALI_PHY_313_DATA */
+			0x00000000,	/* DENALI_PHY_314_DATA */
+			0x02800280,	/* DENALI_PHY_315_DATA */
+			0x02800280,	/* DENALI_PHY_316_DATA */
+			0x02800280,	/* DENALI_PHY_317_DATA */
+			0x02800280,	/* DENALI_PHY_318_DATA */
+			0x00000280,	/* DENALI_PHY_319_DATA */
+			0x00000000,	/* DENALI_PHY_320_DATA */
+			0x00000000,	/* DENALI_PHY_321_DATA */
+			0x00000000,	/* DENALI_PHY_322_DATA */
+			0x00000000,	/* DENALI_PHY_323_DATA */
+			0x00800000,	/* DENALI_PHY_324_DATA */
+			0x00800080,	/* DENALI_PHY_325_DATA */
+			0x00800080,	/* DENALI_PHY_326_DATA */
+			0x00800080,	/* DENALI_PHY_327_DATA */
+			0x00800080,	/* DENALI_PHY_328_DATA */
+			0x00800080,	/* DENALI_PHY_329_DATA */
+			0x00800080,	/* DENALI_PHY_330_DATA */
+			0x00800080,	/* DENALI_PHY_331_DATA */
+			0x00800080,	/* DENALI_PHY_332_DATA */
+			0x01190080,	/* DENALI_PHY_333_DATA */
+			0x00000001,	/* DENALI_PHY_334_DATA */
+			0x00000000,	/* DENALI_PHY_335_DATA */
+			0x00000000,	/* DENALI_PHY_336_DATA */
+			0x00000200,	/* DENALI_PHY_337_DATA */
+			0x00000000,	/* DENALI_PHY_338_DATA */
+			0x51315152,	/* DENALI_PHY_339_DATA */
+			0xc0003150,	/* DENALI_PHY_340_DATA */
+			0x010000c0,	/* DENALI_PHY_341_DATA */
+			0x00100000,	/* DENALI_PHY_342_DATA */
+			0x07044204,	/* DENALI_PHY_343_DATA */
+			0x000f0c18,	/* DENALI_PHY_344_DATA */
+			0x01000140,	/* DENALI_PHY_345_DATA */
+			0x00000c10,	/* DENALI_PHY_346_DATA */
+			0x00000000,	/* DENALI_PHY_347_DATA */
+			0x00000000,	/* DENALI_PHY_348_DATA */
+			0x00000000,	/* DENALI_PHY_349_DATA */
+			0x00000000,	/* DENALI_PHY_350_DATA */
+			0x00000000,	/* DENALI_PHY_351_DATA */
+			0x00000000,	/* DENALI_PHY_352_DATA */
+			0x00000000,	/* DENALI_PHY_353_DATA */
+			0x00000000,	/* DENALI_PHY_354_DATA */
+			0x00000000,	/* DENALI_PHY_355_DATA */
+			0x00000000,	/* DENALI_PHY_356_DATA */
+			0x00000000,	/* DENALI_PHY_357_DATA */
+			0x00000000,	/* DENALI_PHY_358_DATA */
+			0x00000000,	/* DENALI_PHY_359_DATA */
+			0x00000000,	/* DENALI_PHY_360_DATA */
+			0x00000000,	/* DENALI_PHY_361_DATA */
+			0x00000000,	/* DENALI_PHY_362_DATA */
+			0x00000000,	/* DENALI_PHY_363_DATA */
+			0x00000000,	/* DENALI_PHY_364_DATA */
+			0x00000000,	/* DENALI_PHY_365_DATA */
+			0x00000000,	/* DENALI_PHY_366_DATA */
+			0x00000000,	/* DENALI_PHY_367_DATA */
+			0x00000000,	/* DENALI_PHY_368_DATA */
+			0x00000000,	/* DENALI_PHY_369_DATA */
+			0x00000000,	/* DENALI_PHY_370_DATA */
+			0x00000000,	/* DENALI_PHY_371_DATA */
+			0x00000000,	/* DENALI_PHY_372_DATA */
+			0x00000000,	/* DENALI_PHY_373_DATA */
+			0x00000000,	/* DENALI_PHY_374_DATA */
+			0x00000000,	/* DENALI_PHY_375_DATA */
+			0x00000000,	/* DENALI_PHY_376_DATA */
+			0x00000000,	/* DENALI_PHY_377_DATA */
+			0x00000000,	/* DENALI_PHY_378_DATA */
+			0x00000000,	/* DENALI_PHY_379_DATA */
+			0x00000000,	/* DENALI_PHY_380_DATA */
+			0x00000000,	/* DENALI_PHY_381_DATA */
+			0x00000000,	/* DENALI_PHY_382_DATA */
+			0x00000000,	/* DENALI_PHY_383_DATA */
+			0x76543210,	/* DENALI_PHY_384_DATA */
+			0x0004f008,	/* DENALI_PHY_385_DATA */
+			0x00020119,	/* DENALI_PHY_386_DATA */
+			0x00000000,	/* DENALI_PHY_387_DATA */
+			0x00000000,	/* DENALI_PHY_388_DATA */
+			0x00010000,	/* DENALI_PHY_389_DATA */
+			0x01665555,	/* DENALI_PHY_390_DATA */
+			0x03665555,	/* DENALI_PHY_391_DATA */
+			0x00010f00,	/* DENALI_PHY_392_DATA */
+			0x04000100,	/* DENALI_PHY_393_DATA */
+			0x00000001,	/* DENALI_PHY_394_DATA */
+			0x00170180,	/* DENALI_PHY_395_DATA */
+			0x00cc0201,	/* DENALI_PHY_396_DATA */
+			0x00030066,	/* DENALI_PHY_397_DATA */
+			0x00000000,	/* DENALI_PHY_398_DATA */
+			0x00000000,	/* DENALI_PHY_399_DATA */
+			0x00000000,	/* DENALI_PHY_400_DATA */
+			0x00000000,	/* DENALI_PHY_401_DATA */
+			0x00000000,	/* DENALI_PHY_402_DATA */
+			0x00000000,	/* DENALI_PHY_403_DATA */
+			0x00000000,	/* DENALI_PHY_404_DATA */
+			0x00000000,	/* DENALI_PHY_405_DATA */
+			0x04080000,	/* DENALI_PHY_406_DATA */
+			0x04080400,	/* DENALI_PHY_407_DATA */
+			0x30000000,	/* DENALI_PHY_408_DATA */
+			0x0c00c007,	/* DENALI_PHY_409_DATA */
+			0x00000100,	/* DENALI_PHY_410_DATA */
+			0x00000000,	/* DENALI_PHY_411_DATA */
+			0xfd02fe01,	/* DENALI_PHY_412_DATA */
+			0xf708fb04,	/* DENALI_PHY_413_DATA */
+			0xdf20ef10,	/* DENALI_PHY_414_DATA */
+			0x7f80bf40,	/* DENALI_PHY_415_DATA */
+			0x0000aaaa,	/* DENALI_PHY_416_DATA */
+			0x00000000,	/* DENALI_PHY_417_DATA */
+			0x00000000,	/* DENALI_PHY_418_DATA */
+			0x00000000,	/* DENALI_PHY_419_DATA */
+			0x00000000,	/* DENALI_PHY_420_DATA */
+			0x00000000,	/* DENALI_PHY_421_DATA */
+			0x00000000,	/* DENALI_PHY_422_DATA */
+			0x00000000,	/* DENALI_PHY_423_DATA */
+			0x00000000,	/* DENALI_PHY_424_DATA */
+			0x00000000,	/* DENALI_PHY_425_DATA */
+			0x00000000,	/* DENALI_PHY_426_DATA */
+			0x00000000,	/* DENALI_PHY_427_DATA */
+			0x00000000,	/* DENALI_PHY_428_DATA */
+			0x00000000,	/* DENALI_PHY_429_DATA */
+			0x00000000,	/* DENALI_PHY_430_DATA */
+			0x00000000,	/* DENALI_PHY_431_DATA */
+			0x00000000,	/* DENALI_PHY_432_DATA */
+			0x00000000,	/* DENALI_PHY_433_DATA */
+			0x00000000,	/* DENALI_PHY_434_DATA */
+			0x00000000,	/* DENALI_PHY_435_DATA */
+			0x00200000,	/* DENALI_PHY_436_DATA */
+			0x00000000,	/* DENALI_PHY_437_DATA */
+			0x00000000,	/* DENALI_PHY_438_DATA */
+			0x00000000,	/* DENALI_PHY_439_DATA */
+			0x00000000,	/* DENALI_PHY_440_DATA */
+			0x00000000,	/* DENALI_PHY_441_DATA */
+			0x00000000,	/* DENALI_PHY_442_DATA */
+			0x02800280,	/* DENALI_PHY_443_DATA */
+			0x02800280,	/* DENALI_PHY_444_DATA */
+			0x02800280,	/* DENALI_PHY_445_DATA */
+			0x02800280,	/* DENALI_PHY_446_DATA */
+			0x00000280,	/* DENALI_PHY_447_DATA */
+			0x00000000,	/* DENALI_PHY_448_DATA */
+			0x00000000,	/* DENALI_PHY_449_DATA */
+			0x00000000,	/* DENALI_PHY_450_DATA */
+			0x00000000,	/* DENALI_PHY_451_DATA */
+			0x00800000,	/* DENALI_PHY_452_DATA */
+			0x00800080,	/* DENALI_PHY_453_DATA */
+			0x00800080,	/* DENALI_PHY_454_DATA */
+			0x00800080,	/* DENALI_PHY_455_DATA */
+			0x00800080,	/* DENALI_PHY_456_DATA */
+			0x00800080,	/* DENALI_PHY_457_DATA */
+			0x00800080,	/* DENALI_PHY_458_DATA */
+			0x00800080,	/* DENALI_PHY_459_DATA */
+			0x00800080,	/* DENALI_PHY_460_DATA */
+			0x01190080,	/* DENALI_PHY_461_DATA */
+			0x00000001,	/* DENALI_PHY_462_DATA */
+			0x00000000,	/* DENALI_PHY_463_DATA */
+			0x00000000,	/* DENALI_PHY_464_DATA */
+			0x00000200,	/* DENALI_PHY_465_DATA */
+			0x00000000,	/* DENALI_PHY_466_DATA */
+			0x51315152,	/* DENALI_PHY_467_DATA */
+			0xc0003150,	/* DENALI_PHY_468_DATA */
+			0x010000c0,	/* DENALI_PHY_469_DATA */
+			0x00100000,	/* DENALI_PHY_470_DATA */
+			0x07044204,	/* DENALI_PHY_471_DATA */
+			0x000f0c18,	/* DENALI_PHY_472_DATA */
+			0x01000140,	/* DENALI_PHY_473_DATA */
+			0x00000c10,	/* DENALI_PHY_474_DATA */
+			0x00000000,	/* DENALI_PHY_475_DATA */
+			0x00000000,	/* DENALI_PHY_476_DATA */
+			0x00000000,	/* DENALI_PHY_477_DATA */
+			0x00000000,	/* DENALI_PHY_478_DATA */
+			0x00000000,	/* DENALI_PHY_479_DATA */
+			0x00000000,	/* DENALI_PHY_480_DATA */
+			0x00000000,	/* DENALI_PHY_481_DATA */
+			0x00000000,	/* DENALI_PHY_482_DATA */
+			0x00000000,	/* DENALI_PHY_483_DATA */
+			0x00000000,	/* DENALI_PHY_484_DATA */
+			0x00000000,	/* DENALI_PHY_485_DATA */
+			0x00000000,	/* DENALI_PHY_486_DATA */
+			0x00000000,	/* DENALI_PHY_487_DATA */
+			0x00000000,	/* DENALI_PHY_488_DATA */
+			0x00000000,	/* DENALI_PHY_489_DATA */
+			0x00000000,	/* DENALI_PHY_490_DATA */
+			0x00000000,	/* DENALI_PHY_491_DATA */
+			0x00000000,	/* DENALI_PHY_492_DATA */
+			0x00000000,	/* DENALI_PHY_493_DATA */
+			0x00000000,	/* DENALI_PHY_494_DATA */
+			0x00000000,	/* DENALI_PHY_495_DATA */
+			0x00000000,	/* DENALI_PHY_496_DATA */
+			0x00000000,	/* DENALI_PHY_497_DATA */
+			0x00000000,	/* DENALI_PHY_498_DATA */
+			0x00000000,	/* DENALI_PHY_499_DATA */
+			0x00000000,	/* DENALI_PHY_500_DATA */
+			0x00000000,	/* DENALI_PHY_501_DATA */
+			0x00000000,	/* DENALI_PHY_502_DATA */
+			0x00000000,	/* DENALI_PHY_503_DATA */
+			0x00000000,	/* DENALI_PHY_504_DATA */
+			0x00000000,	/* DENALI_PHY_505_DATA */
+			0x00000000,	/* DENALI_PHY_506_DATA */
+			0x00000000,	/* DENALI_PHY_507_DATA */
+			0x00000000,	/* DENALI_PHY_508_DATA */
+			0x00000000,	/* DENALI_PHY_509_DATA */
+			0x00000000,	/* DENALI_PHY_510_DATA */
+			0x00000000,	/* DENALI_PHY_511_DATA */
+			0x00000000,	/* DENALI_PHY_512_DATA */
+			0x00000000,	/* DENALI_PHY_513_DATA */
+			0x00000000,	/* DENALI_PHY_514_DATA */
+			0x00000000,	/* DENALI_PHY_515_DATA */
+			0x00000000,	/* DENALI_PHY_516_DATA */
+			0x00000000,	/* DENALI_PHY_517_DATA */
+			0x00000000,	/* DENALI_PHY_518_DATA */
+			0x00000002,	/* DENALI_PHY_519_DATA */
+			0x00000000,	/* DENALI_PHY_520_DATA */
+			0x00000000,	/* DENALI_PHY_521_DATA */
+			0x00000000,	/* DENALI_PHY_522_DATA */
+			0x00400320,	/* DENALI_PHY_523_DATA */
+			0x00000040,	/* DENALI_PHY_524_DATA */
+			0x00dcba98,	/* DENALI_PHY_525_DATA */
+			0x00000000,	/* DENALI_PHY_526_DATA */
+			0x00dcba98,	/* DENALI_PHY_527_DATA */
+			0x01000000,	/* DENALI_PHY_528_DATA */
+			0x00020003,	/* DENALI_PHY_529_DATA */
+			0x00000000,	/* DENALI_PHY_530_DATA */
+			0x00000000,	/* DENALI_PHY_531_DATA */
+			0x00000000,	/* DENALI_PHY_532_DATA */
+			0x0000002a,	/* DENALI_PHY_533_DATA */
+			0x00000015,	/* DENALI_PHY_534_DATA */
+			0x00000015,	/* DENALI_PHY_535_DATA */
+			0x0000002a,	/* DENALI_PHY_536_DATA */
+			0x00000033,	/* DENALI_PHY_537_DATA */
+			0x0000000c,	/* DENALI_PHY_538_DATA */
+			0x0000000c,	/* DENALI_PHY_539_DATA */
+			0x00000033,	/* DENALI_PHY_540_DATA */
+			0x0a418820,	/* DENALI_PHY_541_DATA */
+			0x003f0000,	/* DENALI_PHY_542_DATA */
+			0x0000003f,	/* DENALI_PHY_543_DATA */
+			0x00030055,	/* DENALI_PHY_544_DATA */
+			0x03000300,	/* DENALI_PHY_545_DATA */
+			0x03000300,	/* DENALI_PHY_546_DATA */
+			0x00000300,	/* DENALI_PHY_547_DATA */
+			0x42080010,	/* DENALI_PHY_548_DATA */
+			0x00000003,	/* DENALI_PHY_549_DATA */
+			0x00000000,	/* DENALI_PHY_550_DATA */
+			0x00000000,	/* DENALI_PHY_551_DATA */
+			0x00000000,	/* DENALI_PHY_552_DATA */
+			0x00000000,	/* DENALI_PHY_553_DATA */
+			0x00000000,	/* DENALI_PHY_554_DATA */
+			0x00000000,	/* DENALI_PHY_555_DATA */
+			0x00000000,	/* DENALI_PHY_556_DATA */
+			0x00000000,	/* DENALI_PHY_557_DATA */
+			0x00000000,	/* DENALI_PHY_558_DATA */
+			0x00000000,	/* DENALI_PHY_559_DATA */
+			0x00000000,	/* DENALI_PHY_560_DATA */
+			0x00000000,	/* DENALI_PHY_561_DATA */
+			0x00000000,	/* DENALI_PHY_562_DATA */
+			0x00000000,	/* DENALI_PHY_563_DATA */
+			0x00000000,	/* DENALI_PHY_564_DATA */
+			0x00000000,	/* DENALI_PHY_565_DATA */
+			0x00000000,	/* DENALI_PHY_566_DATA */
+			0x00000000,	/* DENALI_PHY_567_DATA */
+			0x00000000,	/* DENALI_PHY_568_DATA */
+			0x00000000,	/* DENALI_PHY_569_DATA */
+			0x00000000,	/* DENALI_PHY_570_DATA */
+			0x00000000,	/* DENALI_PHY_571_DATA */
+			0x00000000,	/* DENALI_PHY_572_DATA */
+			0x00000000,	/* DENALI_PHY_573_DATA */
+			0x00000000,	/* DENALI_PHY_574_DATA */
+			0x00000000,	/* DENALI_PHY_575_DATA */
+			0x00000000,	/* DENALI_PHY_576_DATA */
+			0x00000000,	/* DENALI_PHY_577_DATA */
+			0x00000000,	/* DENALI_PHY_578_DATA */
+			0x00000000,	/* DENALI_PHY_579_DATA */
+			0x00000000,	/* DENALI_PHY_580_DATA */
+			0x00000000,	/* DENALI_PHY_581_DATA */
+			0x00000000,	/* DENALI_PHY_582_DATA */
+			0x00000000,	/* DENALI_PHY_583_DATA */
+			0x00000000,	/* DENALI_PHY_584_DATA */
+			0x00000000,	/* DENALI_PHY_585_DATA */
+			0x00000000,	/* DENALI_PHY_586_DATA */
+			0x00000000,	/* DENALI_PHY_587_DATA */
+			0x00000000,	/* DENALI_PHY_588_DATA */
+			0x00000000,	/* DENALI_PHY_589_DATA */
+			0x00000000,	/* DENALI_PHY_590_DATA */
+			0x00000000,	/* DENALI_PHY_591_DATA */
+			0x00000000,	/* DENALI_PHY_592_DATA */
+			0x00000000,	/* DENALI_PHY_593_DATA */
+			0x00000000,	/* DENALI_PHY_594_DATA */
+			0x00000000,	/* DENALI_PHY_595_DATA */
+			0x00000000,	/* DENALI_PHY_596_DATA */
+			0x00000000,	/* DENALI_PHY_597_DATA */
+			0x00000000,	/* DENALI_PHY_598_DATA */
+			0x00000000,	/* DENALI_PHY_599_DATA */
+			0x00000000,	/* DENALI_PHY_600_DATA */
+			0x00000000,	/* DENALI_PHY_601_DATA */
+			0x00000000,	/* DENALI_PHY_602_DATA */
+			0x00000000,	/* DENALI_PHY_603_DATA */
+			0x00000000,	/* DENALI_PHY_604_DATA */
+			0x00000000,	/* DENALI_PHY_605_DATA */
+			0x00000000,	/* DENALI_PHY_606_DATA */
+			0x00000000,	/* DENALI_PHY_607_DATA */
+			0x00000000,	/* DENALI_PHY_608_DATA */
+			0x00000000,	/* DENALI_PHY_609_DATA */
+			0x00000000,	/* DENALI_PHY_610_DATA */
+			0x00000000,	/* DENALI_PHY_611_DATA */
+			0x00000000,	/* DENALI_PHY_612_DATA */
+			0x00000000,	/* DENALI_PHY_613_DATA */
+			0x00000000,	/* DENALI_PHY_614_DATA */
+			0x00000000,	/* DENALI_PHY_615_DATA */
+			0x00000000,	/* DENALI_PHY_616_DATA */
+			0x00000000,	/* DENALI_PHY_617_DATA */
+			0x00000000,	/* DENALI_PHY_618_DATA */
+			0x00000000,	/* DENALI_PHY_619_DATA */
+			0x00000000,	/* DENALI_PHY_620_DATA */
+			0x00000000,	/* DENALI_PHY_621_DATA */
+			0x00000000,	/* DENALI_PHY_622_DATA */
+			0x00000000,	/* DENALI_PHY_623_DATA */
+			0x00000000,	/* DENALI_PHY_624_DATA */
+			0x00000000,	/* DENALI_PHY_625_DATA */
+			0x00000000,	/* DENALI_PHY_626_DATA */
+			0x00000000,	/* DENALI_PHY_627_DATA */
+			0x00000000,	/* DENALI_PHY_628_DATA */
+			0x00000000,	/* DENALI_PHY_629_DATA */
+			0x00000000,	/* DENALI_PHY_630_DATA */
+			0x00000000,	/* DENALI_PHY_631_DATA */
+			0x00000000,	/* DENALI_PHY_632_DATA */
+			0x00000000,	/* DENALI_PHY_633_DATA */
+			0x00000000,	/* DENALI_PHY_634_DATA */
+			0x00000000,	/* DENALI_PHY_635_DATA */
+			0x00000000,	/* DENALI_PHY_636_DATA */
+			0x00000000,	/* DENALI_PHY_637_DATA */
+			0x00000000,	/* DENALI_PHY_638_DATA */
+			0x00000000,	/* DENALI_PHY_639_DATA */
+			0x00000000,	/* DENALI_PHY_640_DATA */
+			0x00000000,	/* DENALI_PHY_641_DATA */
+			0x00000000,	/* DENALI_PHY_642_DATA */
+			0x00000000,	/* DENALI_PHY_643_DATA */
+			0x00000000,	/* DENALI_PHY_644_DATA */
+			0x00000000,	/* DENALI_PHY_645_DATA */
+			0x00000000,	/* DENALI_PHY_646_DATA */
+			0x00000002,	/* DENALI_PHY_647_DATA */
+			0x00000000,	/* DENALI_PHY_648_DATA */
+			0x00000000,	/* DENALI_PHY_649_DATA */
+			0x00000000,	/* DENALI_PHY_650_DATA */
+			0x00400320,	/* DENALI_PHY_651_DATA */
+			0x00000040,	/* DENALI_PHY_652_DATA */
+			0x00000000,	/* DENALI_PHY_653_DATA */
+			0x00000000,	/* DENALI_PHY_654_DATA */
+			0x00000000,	/* DENALI_PHY_655_DATA */
+			0x01000000,	/* DENALI_PHY_656_DATA */
+			0x00020003,	/* DENALI_PHY_657_DATA */
+			0x00000000,	/* DENALI_PHY_658_DATA */
+			0x00000000,	/* DENALI_PHY_659_DATA */
+			0x00000000,	/* DENALI_PHY_660_DATA */
+			0x0000002a,	/* DENALI_PHY_661_DATA */
+			0x00000015,	/* DENALI_PHY_662_DATA */
+			0x00000015,	/* DENALI_PHY_663_DATA */
+			0x0000002a,	/* DENALI_PHY_664_DATA */
+			0x00000033,	/* DENALI_PHY_665_DATA */
+			0x0000000c,	/* DENALI_PHY_666_DATA */
+			0x0000000c,	/* DENALI_PHY_667_DATA */
+			0x00000033,	/* DENALI_PHY_668_DATA */
+			0x00000000,	/* DENALI_PHY_669_DATA */
+			0x00000000,	/* DENALI_PHY_670_DATA */
+			0x00000000,	/* DENALI_PHY_671_DATA */
+			0x00030055,	/* DENALI_PHY_672_DATA */
+			0x03000300,	/* DENALI_PHY_673_DATA */
+			0x03000300,	/* DENALI_PHY_674_DATA */
+			0x00000300,	/* DENALI_PHY_675_DATA */
+			0x42080010,	/* DENALI_PHY_676_DATA */
+			0x00000003,	/* DENALI_PHY_677_DATA */
+			0x00000000,	/* DENALI_PHY_678_DATA */
+			0x00000000,	/* DENALI_PHY_679_DATA */
+			0x00000000,	/* DENALI_PHY_680_DATA */
+			0x00000000,	/* DENALI_PHY_681_DATA */
+			0x00000000,	/* DENALI_PHY_682_DATA */
+			0x00000000,	/* DENALI_PHY_683_DATA */
+			0x00000000,	/* DENALI_PHY_684_DATA */
+			0x00000000,	/* DENALI_PHY_685_DATA */
+			0x00000000,	/* DENALI_PHY_686_DATA */
+			0x00000000,	/* DENALI_PHY_687_DATA */
+			0x00000000,	/* DENALI_PHY_688_DATA */
+			0x00000000,	/* DENALI_PHY_689_DATA */
+			0x00000000,	/* DENALI_PHY_690_DATA */
+			0x00000000,	/* DENALI_PHY_691_DATA */
+			0x00000000,	/* DENALI_PHY_692_DATA */
+			0x00000000,	/* DENALI_PHY_693_DATA */
+			0x00000000,	/* DENALI_PHY_694_DATA */
+			0x00000000,	/* DENALI_PHY_695_DATA */
+			0x00000000,	/* DENALI_PHY_696_DATA */
+			0x00000000,	/* DENALI_PHY_697_DATA */
+			0x00000000,	/* DENALI_PHY_698_DATA */
+			0x00000000,	/* DENALI_PHY_699_DATA */
+			0x00000000,	/* DENALI_PHY_700_DATA */
+			0x00000000,	/* DENALI_PHY_701_DATA */
+			0x00000000,	/* DENALI_PHY_702_DATA */
+			0x00000000,	/* DENALI_PHY_703_DATA */
+			0x00000000,	/* DENALI_PHY_704_DATA */
+			0x00000000,	/* DENALI_PHY_705_DATA */
+			0x00000000,	/* DENALI_PHY_706_DATA */
+			0x00000000,	/* DENALI_PHY_707_DATA */
+			0x00000000,	/* DENALI_PHY_708_DATA */
+			0x00000000,	/* DENALI_PHY_709_DATA */
+			0x00000000,	/* DENALI_PHY_710_DATA */
+			0x00000000,	/* DENALI_PHY_711_DATA */
+			0x00000000,	/* DENALI_PHY_712_DATA */
+			0x00000000,	/* DENALI_PHY_713_DATA */
+			0x00000000,	/* DENALI_PHY_714_DATA */
+			0x00000000,	/* DENALI_PHY_715_DATA */
+			0x00000000,	/* DENALI_PHY_716_DATA */
+			0x00000000,	/* DENALI_PHY_717_DATA */
+			0x00000000,	/* DENALI_PHY_718_DATA */
+			0x00000000,	/* DENALI_PHY_719_DATA */
+			0x00000000,	/* DENALI_PHY_720_DATA */
+			0x00000000,	/* DENALI_PHY_721_DATA */
+			0x00000000,	/* DENALI_PHY_722_DATA */
+			0x00000000,	/* DENALI_PHY_723_DATA */
+			0x00000000,	/* DENALI_PHY_724_DATA */
+			0x00000000,	/* DENALI_PHY_725_DATA */
+			0x00000000,	/* DENALI_PHY_726_DATA */
+			0x00000000,	/* DENALI_PHY_727_DATA */
+			0x00000000,	/* DENALI_PHY_728_DATA */
+			0x00000000,	/* DENALI_PHY_729_DATA */
+			0x00000000,	/* DENALI_PHY_730_DATA */
+			0x00000000,	/* DENALI_PHY_731_DATA */
+			0x00000000,	/* DENALI_PHY_732_DATA */
+			0x00000000,	/* DENALI_PHY_733_DATA */
+			0x00000000,	/* DENALI_PHY_734_DATA */
+			0x00000000,	/* DENALI_PHY_735_DATA */
+			0x00000000,	/* DENALI_PHY_736_DATA */
+			0x00000000,	/* DENALI_PHY_737_DATA */
+			0x00000000,	/* DENALI_PHY_738_DATA */
+			0x00000000,	/* DENALI_PHY_739_DATA */
+			0x00000000,	/* DENALI_PHY_740_DATA */
+			0x00000000,	/* DENALI_PHY_741_DATA */
+			0x00000000,	/* DENALI_PHY_742_DATA */
+			0x00000000,	/* DENALI_PHY_743_DATA */
+			0x00000000,	/* DENALI_PHY_744_DATA */
+			0x00000000,	/* DENALI_PHY_745_DATA */
+			0x00000000,	/* DENALI_PHY_746_DATA */
+			0x00000000,	/* DENALI_PHY_747_DATA */
+			0x00000000,	/* DENALI_PHY_748_DATA */
+			0x00000000,	/* DENALI_PHY_749_DATA */
+			0x00000000,	/* DENALI_PHY_750_DATA */
+			0x00000000,	/* DENALI_PHY_751_DATA */
+			0x00000000,	/* DENALI_PHY_752_DATA */
+			0x00000000,	/* DENALI_PHY_753_DATA */
+			0x00000000,	/* DENALI_PHY_754_DATA */
+			0x00000000,	/* DENALI_PHY_755_DATA */
+			0x00000000,	/* DENALI_PHY_756_DATA */
+			0x00000000,	/* DENALI_PHY_757_DATA */
+			0x00000000,	/* DENALI_PHY_758_DATA */
+			0x00000000,	/* DENALI_PHY_759_DATA */
+			0x00000000,	/* DENALI_PHY_760_DATA */
+			0x00000000,	/* DENALI_PHY_761_DATA */
+			0x00000000,	/* DENALI_PHY_762_DATA */
+			0x00000000,	/* DENALI_PHY_763_DATA */
+			0x00000000,	/* DENALI_PHY_764_DATA */
+			0x00000000,	/* DENALI_PHY_765_DATA */
+			0x00000000,	/* DENALI_PHY_766_DATA */
+			0x00000000,	/* DENALI_PHY_767_DATA */
+			0x00000000,	/* DENALI_PHY_768_DATA */
+			0x00000000,	/* DENALI_PHY_769_DATA */
+			0x00000000,	/* DENALI_PHY_770_DATA */
+			0x00000000,	/* DENALI_PHY_771_DATA */
+			0x00000000,	/* DENALI_PHY_772_DATA */
+			0x00000000,	/* DENALI_PHY_773_DATA */
+			0x00000000,	/* DENALI_PHY_774_DATA */
+			0x00000002,	/* DENALI_PHY_775_DATA */
+			0x00000000,	/* DENALI_PHY_776_DATA */
+			0x00000000,	/* DENALI_PHY_777_DATA */
+			0x00000000,	/* DENALI_PHY_778_DATA */
+			0x00400320,	/* DENALI_PHY_779_DATA */
+			0x00000040,	/* DENALI_PHY_780_DATA */
+			0x00000000,	/* DENALI_PHY_781_DATA */
+			0x00000000,	/* DENALI_PHY_782_DATA */
+			0x00000000,	/* DENALI_PHY_783_DATA */
+			0x01000000,	/* DENALI_PHY_784_DATA */
+			0x00020003,	/* DENALI_PHY_785_DATA */
+			0x00000000,	/* DENALI_PHY_786_DATA */
+			0x00000000,	/* DENALI_PHY_787_DATA */
+			0x00000000,	/* DENALI_PHY_788_DATA */
+			0x0000002a,	/* DENALI_PHY_789_DATA */
+			0x00000015,	/* DENALI_PHY_790_DATA */
+			0x00000015,	/* DENALI_PHY_791_DATA */
+			0x0000002a,	/* DENALI_PHY_792_DATA */
+			0x00000033,	/* DENALI_PHY_793_DATA */
+			0x0000000c,	/* DENALI_PHY_794_DATA */
+			0x0000000c,	/* DENALI_PHY_795_DATA */
+			0x00000033,	/* DENALI_PHY_796_DATA */
+			0x1ee6b16a,	/* DENALI_PHY_797_DATA */
+			0x10000000,	/* DENALI_PHY_798_DATA */
+			0x00000000,	/* DENALI_PHY_799_DATA */
+			0x00030055,	/* DENALI_PHY_800_DATA */
+			0x03000300,	/* DENALI_PHY_801_DATA */
+			0x03000300,	/* DENALI_PHY_802_DATA */
+			0x00000300,	/* DENALI_PHY_803_DATA */
+			0x42080010,	/* DENALI_PHY_804_DATA */
+			0x00000003,	/* DENALI_PHY_805_DATA */
+			0x00000000,	/* DENALI_PHY_806_DATA */
+			0x00000000,	/* DENALI_PHY_807_DATA */
+			0x00000000,	/* DENALI_PHY_808_DATA */
+			0x00000000,	/* DENALI_PHY_809_DATA */
+			0x00000000,	/* DENALI_PHY_810_DATA */
+			0x00000000,	/* DENALI_PHY_811_DATA */
+			0x00000000,	/* DENALI_PHY_812_DATA */
+			0x00000000,	/* DENALI_PHY_813_DATA */
+			0x00000000,	/* DENALI_PHY_814_DATA */
+			0x00000000,	/* DENALI_PHY_815_DATA */
+			0x00000000,	/* DENALI_PHY_816_DATA */
+			0x00000000,	/* DENALI_PHY_817_DATA */
+			0x00000000,	/* DENALI_PHY_818_DATA */
+			0x00000000,	/* DENALI_PHY_819_DATA */
+			0x00000000,	/* DENALI_PHY_820_DATA */
+			0x00000000,	/* DENALI_PHY_821_DATA */
+			0x00000000,	/* DENALI_PHY_822_DATA */
+			0x00000000,	/* DENALI_PHY_823_DATA */
+			0x00000000,	/* DENALI_PHY_824_DATA */
+			0x00000000,	/* DENALI_PHY_825_DATA */
+			0x00000000,	/* DENALI_PHY_826_DATA */
+			0x00000000,	/* DENALI_PHY_827_DATA */
+			0x00000000,	/* DENALI_PHY_828_DATA */
+			0x00000000,	/* DENALI_PHY_829_DATA */
+			0x00000000,	/* DENALI_PHY_830_DATA */
+			0x00000000,	/* DENALI_PHY_831_DATA */
+			0x00000000,	/* DENALI_PHY_832_DATA */
+			0x00000000,	/* DENALI_PHY_833_DATA */
+			0x00000000,	/* DENALI_PHY_834_DATA */
+			0x00000000,	/* DENALI_PHY_835_DATA */
+			0x00000000,	/* DENALI_PHY_836_DATA */
+			0x00000000,	/* DENALI_PHY_837_DATA */
+			0x00000000,	/* DENALI_PHY_838_DATA */
+			0x00000000,	/* DENALI_PHY_839_DATA */
+			0x00000000,	/* DENALI_PHY_840_DATA */
+			0x00000000,	/* DENALI_PHY_841_DATA */
+			0x00000000,	/* DENALI_PHY_842_DATA */
+			0x00000000,	/* DENALI_PHY_843_DATA */
+			0x00000000,	/* DENALI_PHY_844_DATA */
+			0x00000000,	/* DENALI_PHY_845_DATA */
+			0x00000000,	/* DENALI_PHY_846_DATA */
+			0x00000000,	/* DENALI_PHY_847_DATA */
+			0x00000000,	/* DENALI_PHY_848_DATA */
+			0x00000000,	/* DENALI_PHY_849_DATA */
+			0x00000000,	/* DENALI_PHY_850_DATA */
+			0x00000000,	/* DENALI_PHY_851_DATA */
+			0x00000000,	/* DENALI_PHY_852_DATA */
+			0x00000000,	/* DENALI_PHY_853_DATA */
+			0x00000000,	/* DENALI_PHY_854_DATA */
+			0x00000000,	/* DENALI_PHY_855_DATA */
+			0x00000000,	/* DENALI_PHY_856_DATA */
+			0x00000000,	/* DENALI_PHY_857_DATA */
+			0x00000000,	/* DENALI_PHY_858_DATA */
+			0x00000000,	/* DENALI_PHY_859_DATA */
+			0x00000000,	/* DENALI_PHY_860_DATA */
+			0x00000000,	/* DENALI_PHY_861_DATA */
+			0x00000000,	/* DENALI_PHY_862_DATA */
+			0x00000000,	/* DENALI_PHY_863_DATA */
+			0x00000000,	/* DENALI_PHY_864_DATA */
+			0x00000000,	/* DENALI_PHY_865_DATA */
+			0x00000000,	/* DENALI_PHY_866_DATA */
+			0x00000000,	/* DENALI_PHY_867_DATA */
+			0x00000000,	/* DENALI_PHY_868_DATA */
+			0x00000000,	/* DENALI_PHY_869_DATA */
+			0x00000000,	/* DENALI_PHY_870_DATA */
+			0x00000000,	/* DENALI_PHY_871_DATA */
+			0x00000000,	/* DENALI_PHY_872_DATA */
+			0x00000000,	/* DENALI_PHY_873_DATA */
+			0x00000000,	/* DENALI_PHY_874_DATA */
+			0x00000000,	/* DENALI_PHY_875_DATA */
+			0x00000000,	/* DENALI_PHY_876_DATA */
+			0x00000000,	/* DENALI_PHY_877_DATA */
+			0x00000000,	/* DENALI_PHY_878_DATA */
+			0x00000000,	/* DENALI_PHY_879_DATA */
+			0x00000000,	/* DENALI_PHY_880_DATA */
+			0x00000000,	/* DENALI_PHY_881_DATA */
+			0x00000000,	/* DENALI_PHY_882_DATA */
+			0x00000000,	/* DENALI_PHY_883_DATA */
+			0x00000000,	/* DENALI_PHY_884_DATA */
+			0x00000000,	/* DENALI_PHY_885_DATA */
+			0x00000000,	/* DENALI_PHY_886_DATA */
+			0x00000000,	/* DENALI_PHY_887_DATA */
+			0x00000000,	/* DENALI_PHY_888_DATA */
+			0x00000000,	/* DENALI_PHY_889_DATA */
+			0x00000000,	/* DENALI_PHY_890_DATA */
+			0x00000000,	/* DENALI_PHY_891_DATA */
+			0x00000000,	/* DENALI_PHY_892_DATA */
+			0x00000000,	/* DENALI_PHY_893_DATA */
+			0x00000000,	/* DENALI_PHY_894_DATA */
+			0x00000000,	/* DENALI_PHY_895_DATA */
+			0x00000000,	/* DENALI_PHY_896_DATA */
+			0x00000000,	/* DENALI_PHY_897_DATA */
+			0x00000005,	/* DENALI_PHY_898_DATA */
+			0x04000f01,	/* DENALI_PHY_899_DATA */
+			0x00020040,	/* DENALI_PHY_900_DATA */
+			0x00020055,	/* DENALI_PHY_901_DATA */
+			0x00000000,	/* DENALI_PHY_902_DATA */
+			0x00000000,	/* DENALI_PHY_903_DATA */
+			0x00000000,	/* DENALI_PHY_904_DATA */
+			0x00000050,	/* DENALI_PHY_905_DATA */
+			0x00000000,	/* DENALI_PHY_906_DATA */
+			0x01010100,	/* DENALI_PHY_907_DATA */
+			0x00000600,	/* DENALI_PHY_908_DATA */
+			0x00000000,	/* DENALI_PHY_909_DATA */
+			0x00006400,	/* DENALI_PHY_910_DATA */
+			0x03221302,	/* DENALI_PHY_911_DATA */
+			0x00000000,	/* DENALI_PHY_912_DATA */
+			0x000d1f01,	/* DENALI_PHY_913_DATA */
+			0x0d1f0d1f,	/* DENALI_PHY_914_DATA */
+			0x0d1f0d1f,	/* DENALI_PHY_915_DATA */
+			0x00030003,	/* DENALI_PHY_916_DATA */
+			0x03000300,	/* DENALI_PHY_917_DATA */
+			0x00000300,	/* DENALI_PHY_918_DATA */
+			0x03221302,	/* DENALI_PHY_919_DATA */
+			0x00000000,	/* DENALI_PHY_920_DATA */
+			0x00000000,	/* DENALI_PHY_921_DATA */
+			0x01020000,	/* DENALI_PHY_922_DATA */
+			0x00000001,	/* DENALI_PHY_923_DATA */
+			0x00000411,	/* DENALI_PHY_924_DATA */
+			0x00000411,	/* DENALI_PHY_925_DATA */
+			0x00000040,	/* DENALI_PHY_926_DATA */
+			0x00000040,	/* DENALI_PHY_927_DATA */
+			0x00000411,	/* DENALI_PHY_928_DATA */
+			0x00000411,	/* DENALI_PHY_929_DATA */
+			0x00004410,	/* DENALI_PHY_930_DATA */
+			0x00004410,	/* DENALI_PHY_931_DATA */
+			0x00004410,	/* DENALI_PHY_932_DATA */
+			0x00004410,	/* DENALI_PHY_933_DATA */
+			0x00004410,	/* DENALI_PHY_934_DATA */
+			0x00000411,	/* DENALI_PHY_935_DATA */
+			0x00004410,	/* DENALI_PHY_936_DATA */
+			0x00000411,	/* DENALI_PHY_937_DATA */
+			0x00004410,	/* DENALI_PHY_938_DATA */
+			0x00000411,	/* DENALI_PHY_939_DATA */
+			0x00004410,	/* DENALI_PHY_940_DATA */
+			0x00000000,	/* DENALI_PHY_941_DATA */
+			0x00000000,	/* DENALI_PHY_942_DATA */
+			0x00000000,	/* DENALI_PHY_943_DATA */
+			0x64000000,	/* DENALI_PHY_944_DATA */
+			0x00000000,	/* DENALI_PHY_945_DATA */
+			0x00000000,	/* DENALI_PHY_946_DATA */
+			0x00000408,	/* DENALI_PHY_947_DATA */
+			0x00000000,	/* DENALI_PHY_948_DATA */
+			0x00000000,	/* DENALI_PHY_949_DATA */
+			0x00000000,	/* DENALI_PHY_950_DATA */
+			0x00000000,	/* DENALI_PHY_951_DATA */
+			0x00000000,	/* DENALI_PHY_952_DATA */
+			0x00000000,	/* DENALI_PHY_953_DATA */
+			0xe4000000,	/* DENALI_PHY_954_DATA */
+			0x00000000,	/* DENALI_PHY_955_DATA */
+			0x00000000,	/* DENALI_PHY_956_DATA */
+			0x01010000,	/* DENALI_PHY_957_DATA */
+			0x00000000	/* DENALI_PHY_958_DATA */
+		}
+	},
+},
diff --git a/drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc b/drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc
new file mode 100644
index 0000000..d8ae335
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc
@@ -0,0 +1,1570 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd.
+ * (C) Copyright 2019 Amarula Solutions
+ */
+
+{
+	{
+		{
+			{
+				.rank = 0x2,
+				.col = 0xA,
+				.bk = 0x3,
+				.bw = 0x2,
+				.dbw = 0x1,
+				.row_3_4 = 0x0,
+				.cs0_row = 0xF,
+				.cs1_row = 0xF,
+				.ddrconfig = 1,
+			},
+			{
+				.ddrtiminga0 = 0x80241d22,
+				.ddrtimingb0 = 0x15050f08,
+				.ddrtimingc0 = {
+					0x00000602,
+				},
+				.devtodev0 = 0x00002122,
+				.ddrmode = {
+					0x0000004c,
+				},
+				.agingx0 = 0x00000000,
+			}
+		},
+		{
+			{
+				.rank = 0x2,
+				.col = 0xA,
+				.bk = 0x3,
+				.bw = 0x2,
+				.dbw = 0x1,
+				.row_3_4 = 0x0,
+				.cs0_row = 0xF,
+				.cs1_row = 0xF,
+				.ddrconfig = 1,
+			},
+			{
+				.ddrtiminga0 = 0x80241d22,
+				.ddrtimingb0 = 0x15050f08,
+				.ddrtimingc0 = {
+					0x00000602,
+				},
+				.devtodev0 = 0x00002122,
+				.ddrmode = {
+					0x0000004c,
+				},
+				.agingx0 = 0x00000000,
+			}
+		}
+	},
+	{
+		.ddr_freq = 800 * MHz,
+		.dramtype = LPDDR4,
+		.num_channels = 2,
+		.stride = 13,
+		.odt = 1,
+	},
+	{
+		{
+			0x00000b00,	/* DENALI_CTL_00_DATA */
+			0x00000000,	/* DENALI_CTL_01_DATA */
+			0x00000000,	/* DENALI_CTL_02_DATA */
+			0x00000000,	/* DENALI_CTL_03_DATA */
+			0x00000000,	/* DENALI_CTL_04_DATA */
+			0x00013880,	/* DENALI_CTL_05_DATA */
+			0x000c3500,	/* DENALI_CTL_06_DATA */
+			0x00000005,	/* DENALI_CTL_07_DATA */
+			0x00000320,	/* DENALI_CTL_08_DATA */
+			0x00027100,	/* DENALI_CTL_09_DATA */
+			0x00186a00,	/* DENALI_CTL_10_DATA */
+			0x00000005,	/* DENALI_CTL_11_DATA */
+			0x00000640,	/* DENALI_CTL_12_DATA */
+			0x00002710,	/* DENALI_CTL_13_DATA */
+			0x000186a0,	/* DENALI_CTL_14_DATA */
+			0x00000005,	/* DENALI_CTL_15_DATA */
+			0x01000064,	/* DENALI_CTL_16_DATA */
+			0x00000000,	/* DENALI_CTL_17_DATA */
+			0x02020101,	/* DENALI_CTL_18_DATA */
+			0x00000102,	/* DENALI_CTL_19_DATA */
+			0x00000050,	/* DENALI_CTL_20_DATA */
+			0x000000c8,	/* DENALI_CTL_21_DATA */
+			0x00000000,	/* DENALI_CTL_22_DATA */
+			0x06140000,	/* DENALI_CTL_23_DATA */
+			0x00081c00,	/* DENALI_CTL_24_DATA */
+			0x0400040c,	/* DENALI_CTL_25_DATA */
+			0x19042008,	/* DENALI_CTL_26_DATA */
+			0x10080a11,	/* DENALI_CTL_27_DATA */
+			0x22310800,	/* DENALI_CTL_28_DATA */
+			0x00200f0a,	/* DENALI_CTL_29_DATA */
+			0x0a030704,	/* DENALI_CTL_30_DATA */
+			0x08000204,	/* DENALI_CTL_31_DATA */
+			0x00000a0a,	/* DENALI_CTL_32_DATA */
+			0x04006db0,	/* DENALI_CTL_33_DATA */
+			0x0a0a0804,	/* DENALI_CTL_34_DATA */
+			0x0600db60,	/* DENALI_CTL_35_DATA */
+			0x0a0a0806,	/* DENALI_CTL_36_DATA */
+			0x04000db6,	/* DENALI_CTL_37_DATA */
+			0x02030404,	/* DENALI_CTL_38_DATA */
+			0x0f0a0800,	/* DENALI_CTL_39_DATA */
+			0x08040411,	/* DENALI_CTL_40_DATA */
+			0x1400640a,	/* DENALI_CTL_41_DATA */
+			0x02010a0a,	/* DENALI_CTL_42_DATA */
+			0x00010001,	/* DENALI_CTL_43_DATA */
+			0x04082012,	/* DENALI_CTL_44_DATA */
+			0x00041109,	/* DENALI_CTL_45_DATA */
+			0x00000000,	/* DENALI_CTL_46_DATA */
+			0x03010000,	/* DENALI_CTL_47_DATA */
+			0x06100034,	/* DENALI_CTL_48_DATA */
+			0x0c280068,	/* DENALI_CTL_49_DATA */
+			0x00bb0007,	/* DENALI_CTL_50_DATA */
+			0x00000000,	/* DENALI_CTL_51_DATA */
+			0x00060003,	/* DENALI_CTL_52_DATA */
+			0x000a0003,	/* DENALI_CTL_53_DATA */
+			0x000a0014,	/* DENALI_CTL_54_DATA */
+			0x01000000,	/* DENALI_CTL_55_DATA */
+			0x030a0000,	/* DENALI_CTL_56_DATA */
+			0x0c000002,	/* DENALI_CTL_57_DATA */
+			0x00000103,	/* DENALI_CTL_58_DATA */
+			0x0003030a,	/* DENALI_CTL_59_DATA */
+			0x00060037,	/* DENALI_CTL_60_DATA */
+			0x0003006e,	/* DENALI_CTL_61_DATA */
+			0x05050007,	/* DENALI_CTL_62_DATA */
+			0x03020605,	/* DENALI_CTL_63_DATA */
+			0x06050301,	/* DENALI_CTL_64_DATA */
+			0x06020c05,	/* DENALI_CTL_65_DATA */
+			0x05050302,	/* DENALI_CTL_66_DATA */
+			0x03020305,	/* DENALI_CTL_67_DATA */
+			0x00000301,	/* DENALI_CTL_68_DATA */
+			0x00000301,	/* DENALI_CTL_69_DATA */
+			0x00000001,	/* DENALI_CTL_70_DATA */
+			0x00000000,	/* DENALI_CTL_71_DATA */
+			0x00000000,	/* DENALI_CTL_72_DATA */
+			0x01000000,	/* DENALI_CTL_73_DATA */
+			0x80104002,	/* DENALI_CTL_74_DATA */
+			0x00040003,	/* DENALI_CTL_75_DATA */
+			0x00040005,	/* DENALI_CTL_76_DATA */
+			0x00030000,	/* DENALI_CTL_77_DATA */
+			0x00050004,	/* DENALI_CTL_78_DATA */
+			0x00000004,	/* DENALI_CTL_79_DATA */
+			0x00040003,	/* DENALI_CTL_80_DATA */
+			0x00040005,	/* DENALI_CTL_81_DATA */
+			0x18400000,	/* DENALI_CTL_82_DATA */
+			0x00000c20,	/* DENALI_CTL_83_DATA */
+			0x185030a0,	/* DENALI_CTL_84_DATA */
+			0x02ec0000,	/* DENALI_CTL_85_DATA */
+			0x00000176,	/* DENALI_CTL_86_DATA */
+			0x00000000,	/* DENALI_CTL_87_DATA */
+			0x00000000,	/* DENALI_CTL_88_DATA */
+			0x00000000,	/* DENALI_CTL_89_DATA */
+			0x00000000,	/* DENALI_CTL_90_DATA */
+			0x00000000,	/* DENALI_CTL_91_DATA */
+			0x06030300,	/* DENALI_CTL_92_DATA */
+			0x00030303,	/* DENALI_CTL_93_DATA */
+			0x02030200,	/* DENALI_CTL_94_DATA */
+			0x00040703,	/* DENALI_CTL_95_DATA */
+			0x03020302,	/* DENALI_CTL_96_DATA */
+			0x02000407,	/* DENALI_CTL_97_DATA */
+			0x07030203,	/* DENALI_CTL_98_DATA */
+			0x00030f04,	/* DENALI_CTL_99_DATA */
+			0x00070004,	/* DENALI_CTL_100_DATA */
+			0x00000000,	/* DENALI_CTL_101_DATA */
+			0x00000000,	/* DENALI_CTL_102_DATA */
+			0x00000000,	/* DENALI_CTL_103_DATA */
+			0x00000000,	/* DENALI_CTL_104_DATA */
+			0x00000000,	/* DENALI_CTL_105_DATA */
+			0x00000000,	/* DENALI_CTL_106_DATA */
+			0x00000000,	/* DENALI_CTL_107_DATA */
+			0x00010000,	/* DENALI_CTL_108_DATA */
+			0x20040020,	/* DENALI_CTL_109_DATA */
+			0x00200400,	/* DENALI_CTL_110_DATA */
+			0x01000400,	/* DENALI_CTL_111_DATA */
+			0x00000b80,	/* DENALI_CTL_112_DATA */
+			0x00000000,	/* DENALI_CTL_113_DATA */
+			0x00000001,	/* DENALI_CTL_114_DATA */
+			0x00000002,	/* DENALI_CTL_115_DATA */
+			0x0000000e,	/* DENALI_CTL_116_DATA */
+			0x00000000,	/* DENALI_CTL_117_DATA */
+			0x00000000,	/* DENALI_CTL_118_DATA */
+			0x00000000,	/* DENALI_CTL_119_DATA */
+			0x00000000,	/* DENALI_CTL_120_DATA */
+			0x00000000,	/* DENALI_CTL_121_DATA */
+			0x00500000,	/* DENALI_CTL_122_DATA */
+			0x00640028,	/* DENALI_CTL_123_DATA */
+			0x00640404,	/* DENALI_CTL_124_DATA */
+			0x005000a0,	/* DENALI_CTL_125_DATA */
+			0x060600c8,	/* DENALI_CTL_126_DATA */
+			0x000a00c8,	/* DENALI_CTL_127_DATA */
+			0x000d0005,	/* DENALI_CTL_128_DATA */
+			0x000d0404,	/* DENALI_CTL_129_DATA */
+			0x00000000,	/* DENALI_CTL_130_DATA */
+			0x00000000,	/* DENALI_CTL_131_DATA */
+			0x00000000,	/* DENALI_CTL_132_DATA */
+			0x001400a3,	/* DENALI_CTL_133_DATA */
+			0x00e30009,	/* DENALI_CTL_134_DATA */
+			0x00120024,	/* DENALI_CTL_135_DATA */
+			0x00040063,	/* DENALI_CTL_136_DATA */
+			0x00000000,	/* DENALI_CTL_137_DATA */
+			0x00310031,	/* DENALI_CTL_138_DATA */
+			0x00000031,	/* DENALI_CTL_139_DATA */
+			0x004d0000,	/* DENALI_CTL_140_DATA */
+			0x004d004d,	/* DENALI_CTL_141_DATA */
+			0x004d0000,	/* DENALI_CTL_142_DATA */
+			0x004d004d,	/* DENALI_CTL_143_DATA */
+			0x00010101,	/* DENALI_CTL_144_DATA */
+			0x00000000,	/* DENALI_CTL_145_DATA */
+			0x00000000,	/* DENALI_CTL_146_DATA */
+			0x001400a3,	/* DENALI_CTL_147_DATA */
+			0x00e30009,	/* DENALI_CTL_148_DATA */
+			0x00120024,	/* DENALI_CTL_149_DATA */
+			0x00040063,	/* DENALI_CTL_150_DATA */
+			0x00000000,	/* DENALI_CTL_151_DATA */
+			0x00310031,	/* DENALI_CTL_152_DATA */
+			0x00000031,	/* DENALI_CTL_153_DATA */
+			0x004d0000,	/* DENALI_CTL_154_DATA */
+			0x004d004d,	/* DENALI_CTL_155_DATA */
+			0x004d0000,	/* DENALI_CTL_156_DATA */
+			0x004d004d,	/* DENALI_CTL_157_DATA */
+			0x00010101,	/* DENALI_CTL_158_DATA */
+			0x00000000,	/* DENALI_CTL_159_DATA */
+			0x00000000,	/* DENALI_CTL_160_DATA */
+			0x00000000,	/* DENALI_CTL_161_DATA */
+			0x00000001,	/* DENALI_CTL_162_DATA */
+			0x00000000,	/* DENALI_CTL_163_DATA */
+			0x18151100,	/* DENALI_CTL_164_DATA */
+			0x0000000c,	/* DENALI_CTL_165_DATA */
+			0x00000000,	/* DENALI_CTL_166_DATA */
+			0x00000000,	/* DENALI_CTL_167_DATA */
+			0x00000000,	/* DENALI_CTL_168_DATA */
+			0x00000000,	/* DENALI_CTL_169_DATA */
+			0x00000000,	/* DENALI_CTL_170_DATA */
+			0x00000000,	/* DENALI_CTL_171_DATA */
+			0x00000000,	/* DENALI_CTL_172_DATA */
+			0x00000000,	/* DENALI_CTL_173_DATA */
+			0x00000000,	/* DENALI_CTL_174_DATA */
+			0x00000000,	/* DENALI_CTL_175_DATA */
+			0x00000000,	/* DENALI_CTL_176_DATA */
+			0x00000000,	/* DENALI_CTL_177_DATA */
+			0x00000000,	/* DENALI_CTL_178_DATA */
+			0x00020003,	/* DENALI_CTL_179_DATA */
+			0x00400100,	/* DENALI_CTL_180_DATA */
+			0x000c0190,	/* DENALI_CTL_181_DATA */
+			0x01000200,	/* DENALI_CTL_182_DATA */
+			0x03200040,	/* DENALI_CTL_183_DATA */
+			0x00020018,	/* DENALI_CTL_184_DATA */
+			0x00400100,	/* DENALI_CTL_185_DATA */
+			0x00080032,	/* DENALI_CTL_186_DATA */
+			0x00140000,	/* DENALI_CTL_187_DATA */
+			0x00030028,	/* DENALI_CTL_188_DATA */
+			0x01010100,	/* DENALI_CTL_189_DATA */
+			0x02000202,	/* DENALI_CTL_190_DATA */
+			0x0b000002,	/* DENALI_CTL_191_DATA */
+			0x01000f0f,	/* DENALI_CTL_192_DATA */
+			0x00000000,	/* DENALI_CTL_193_DATA */
+			0x00000000,	/* DENALI_CTL_194_DATA */
+			0x00010003,	/* DENALI_CTL_195_DATA */
+			0x00000c03,	/* DENALI_CTL_196_DATA */
+			0x00040101,	/* DENALI_CTL_197_DATA */
+			0x04010100,	/* DENALI_CTL_198_DATA */
+			0x01000000,	/* DENALI_CTL_199_DATA */
+			0x02010000,	/* DENALI_CTL_200_DATA */
+			0x00000001,	/* DENALI_CTL_201_DATA */
+			0x00000000,	/* DENALI_CTL_202_DATA */
+			0x00000000,	/* DENALI_CTL_203_DATA */
+			0x00000000,	/* DENALI_CTL_204_DATA */
+			0x00000000,	/* DENALI_CTL_205_DATA */
+			0x00000000,	/* DENALI_CTL_206_DATA */
+			0x00000000,	/* DENALI_CTL_207_DATA */
+			0x00000000,	/* DENALI_CTL_208_DATA */
+			0x00000000,	/* DENALI_CTL_209_DATA */
+			0x00000000,	/* DENALI_CTL_210_DATA */
+			0x00010000,	/* DENALI_CTL_211_DATA */
+			0x00000001,	/* DENALI_CTL_212_DATA */
+			0x01010001,	/* DENALI_CTL_213_DATA */
+			0x05040001,	/* DENALI_CTL_214_DATA */
+			0x040a0703,	/* DENALI_CTL_215_DATA */
+			0x02080808,	/* DENALI_CTL_216_DATA */
+			0x020e000a,	/* DENALI_CTL_217_DATA */
+			0x020f010b,	/* DENALI_CTL_218_DATA */
+			0x000d0008,	/* DENALI_CTL_219_DATA */
+			0x00080b0a,	/* DENALI_CTL_220_DATA */
+			0x03000200,	/* DENALI_CTL_221_DATA */
+			0x00000100,	/* DENALI_CTL_222_DATA */
+			0x00000000,	/* DENALI_CTL_223_DATA */
+			0x00000000,	/* DENALI_CTL_224_DATA */
+			0x0d000001,	/* DENALI_CTL_225_DATA */
+			0x00000028,	/* DENALI_CTL_226_DATA */
+			0x00010000,	/* DENALI_CTL_227_DATA */
+			0x00000003,	/* DENALI_CTL_228_DATA */
+			0x00000000,	/* DENALI_CTL_229_DATA */
+			0x00000000,	/* DENALI_CTL_230_DATA */
+			0x00000000,	/* DENALI_CTL_231_DATA */
+			0x00000000,	/* DENALI_CTL_232_DATA */
+			0x00000000,	/* DENALI_CTL_233_DATA */
+			0x00000000,	/* DENALI_CTL_234_DATA */
+			0x00000000,	/* DENALI_CTL_235_DATA */
+			0x00000000,	/* DENALI_CTL_236_DATA */
+			0x00010100,	/* DENALI_CTL_237_DATA */
+			0x01000000,	/* DENALI_CTL_238_DATA */
+			0x00000001,	/* DENALI_CTL_239_DATA */
+			0x00000303,	/* DENALI_CTL_240_DATA */
+			0x00000000,	/* DENALI_CTL_241_DATA */
+			0x00000000,	/* DENALI_CTL_242_DATA */
+			0x00000000,	/* DENALI_CTL_243_DATA */
+			0x00000000,	/* DENALI_CTL_244_DATA */
+			0x00000000,	/* DENALI_CTL_245_DATA */
+			0x00000000,	/* DENALI_CTL_246_DATA */
+			0x00000000,	/* DENALI_CTL_247_DATA */
+			0x00000000,	/* DENALI_CTL_248_DATA */
+			0x00000000,	/* DENALI_CTL_249_DATA */
+			0x00000000,	/* DENALI_CTL_250_DATA */
+			0x00000000,	/* DENALI_CTL_251_DATA */
+			0x00000000,	/* DENALI_CTL_252_DATA */
+			0x00000000,	/* DENALI_CTL_253_DATA */
+			0x00000000,	/* DENALI_CTL_254_DATA */
+			0x00000000,	/* DENALI_CTL_255_DATA */
+			0x000556aa,	/* DENALI_CTL_256_DATA */
+			0x000aaaaa,	/* DENALI_CTL_257_DATA */
+			0x000aa955,	/* DENALI_CTL_258_DATA */
+			0x00055555,	/* DENALI_CTL_259_DATA */
+			0x000b3133,	/* DENALI_CTL_260_DATA */
+			0x0004cd33,	/* DENALI_CTL_261_DATA */
+			0x0004cecc,	/* DENALI_CTL_262_DATA */
+			0x000b32cc,	/* DENALI_CTL_263_DATA */
+			0x00010300,	/* DENALI_CTL_264_DATA */
+			0x03000100,	/* DENALI_CTL_265_DATA */
+			0x00000000,	/* DENALI_CTL_266_DATA */
+			0x00000000,	/* DENALI_CTL_267_DATA */
+			0x00000000,	/* DENALI_CTL_268_DATA */
+			0x00000000,	/* DENALI_CTL_269_DATA */
+			0x00000000,	/* DENALI_CTL_270_DATA */
+			0x00000000,	/* DENALI_CTL_271_DATA */
+			0x00000000,	/* DENALI_CTL_272_DATA */
+			0x00000000,	/* DENALI_CTL_273_DATA */
+			0x00ffff00,	/* DENALI_CTL_274_DATA */
+			0x1a160000,	/* DENALI_CTL_275_DATA */
+			0x08000012,	/* DENALI_CTL_276_DATA */
+			0x00000c20,	/* DENALI_CTL_277_DATA */
+			0x00000200,	/* DENALI_CTL_278_DATA */
+			0x00000200,	/* DENALI_CTL_279_DATA */
+			0x00000200,	/* DENALI_CTL_280_DATA */
+			0x00000200,	/* DENALI_CTL_281_DATA */
+			0x00000c20,	/* DENALI_CTL_282_DATA */
+			0x00007940,	/* DENALI_CTL_283_DATA */
+			0x18500409,	/* DENALI_CTL_284_DATA */
+			0x00000200,	/* DENALI_CTL_285_DATA */
+			0x00000200,	/* DENALI_CTL_286_DATA */
+			0x00000200,	/* DENALI_CTL_287_DATA */
+			0x00000200,	/* DENALI_CTL_288_DATA */
+			0x00001850,	/* DENALI_CTL_289_DATA */
+			0x0000f320,	/* DENALI_CTL_290_DATA */
+			0x0176060c,	/* DENALI_CTL_291_DATA */
+			0x00000200,	/* DENALI_CTL_292_DATA */
+			0x00000200,	/* DENALI_CTL_293_DATA */
+			0x00000200,	/* DENALI_CTL_294_DATA */
+			0x00000200,	/* DENALI_CTL_295_DATA */
+			0x00000176,	/* DENALI_CTL_296_DATA */
+			0x00000e9c,	/* DENALI_CTL_297_DATA */
+			0x02020205,	/* DENALI_CTL_298_DATA */
+			0x03030202,	/* DENALI_CTL_299_DATA */
+			0x00000018,	/* DENALI_CTL_300_DATA */
+			0x00000000,	/* DENALI_CTL_301_DATA */
+			0x00000000,	/* DENALI_CTL_302_DATA */
+			0x00001403,	/* DENALI_CTL_303_DATA */
+			0x00000000,	/* DENALI_CTL_304_DATA */
+			0x00000000,	/* DENALI_CTL_305_DATA */
+			0x00000000,	/* DENALI_CTL_306_DATA */
+			0x00030000,	/* DENALI_CTL_307_DATA */
+			0x000a001c,	/* DENALI_CTL_308_DATA */
+			0x000e0020,	/* DENALI_CTL_309_DATA */
+			0x00060018,	/* DENALI_CTL_310_DATA */
+			0x00000000,	/* DENALI_CTL_311_DATA */
+			0x00000000,	/* DENALI_CTL_312_DATA */
+			0x02000000,	/* DENALI_CTL_313_DATA */
+			0x00090305,	/* DENALI_CTL_314_DATA */
+			0x00050101,	/* DENALI_CTL_315_DATA */
+			0x00000000,	/* DENALI_CTL_316_DATA */
+			0x00000000,	/* DENALI_CTL_317_DATA */
+			0x00000000,	/* DENALI_CTL_318_DATA */
+			0x00000000,	/* DENALI_CTL_319_DATA */
+			0x00000000,	/* DENALI_CTL_320_DATA */
+			0x00000000,	/* DENALI_CTL_321_DATA */
+			0x00000000,	/* DENALI_CTL_322_DATA */
+			0x00000000,	/* DENALI_CTL_323_DATA */
+			0x01000001,	/* DENALI_CTL_324_DATA */
+			0x01010101,	/* DENALI_CTL_325_DATA */
+			0x01000101,	/* DENALI_CTL_326_DATA */
+			0x01000100,	/* DENALI_CTL_327_DATA */
+			0x00010001,	/* DENALI_CTL_328_DATA */
+			0x00010002,	/* DENALI_CTL_329_DATA */
+			0x00020100,	/* DENALI_CTL_330_DATA */
+			0x00000002	/* DENALI_CTL_331_DATA */
+		}
+	},
+	{
+		{
+			0x00000b00,	/* DENALI_PI_00_DATA */
+			0x00000000,	/* DENALI_PI_01_DATA */
+			0x000002ec,	/* DENALI_PI_02_DATA */
+			0x00000176,	/* DENALI_PI_03_DATA */
+			0x000030a0,	/* DENALI_PI_04_DATA */
+			0x00001850,	/* DENALI_PI_05_DATA */
+			0x00001840,	/* DENALI_PI_06_DATA */
+			0x01760c20,	/* DENALI_PI_07_DATA */
+			0x00000200,	/* DENALI_PI_08_DATA */
+			0x00000200,	/* DENALI_PI_09_DATA */
+			0x00000200,	/* DENALI_PI_10_DATA */
+			0x00000200,	/* DENALI_PI_11_DATA */
+			0x00001850,	/* DENALI_PI_12_DATA */
+			0x00000200,	/* DENALI_PI_13_DATA */
+			0x00000200,	/* DENALI_PI_14_DATA */
+			0x00000200,	/* DENALI_PI_15_DATA */
+			0x00000200,	/* DENALI_PI_16_DATA */
+			0x00000c20,	/* DENALI_PI_17_DATA */
+			0x00000200,	/* DENALI_PI_18_DATA */
+			0x00000200,	/* DENALI_PI_19_DATA */
+			0x00000200,	/* DENALI_PI_20_DATA */
+			0x00000200,	/* DENALI_PI_21_DATA */
+			0x00010000,	/* DENALI_PI_22_DATA */
+			0x00000007,	/* DENALI_PI_23_DATA */
+			0x01000001,	/* DENALI_PI_24_DATA */
+			0x00000000,	/* DENALI_PI_25_DATA */
+			0x3fffffff,	/* DENALI_PI_26_DATA */
+			0x00000000,	/* DENALI_PI_27_DATA */
+			0x00000000,	/* DENALI_PI_28_DATA */
+			0x00000000,	/* DENALI_PI_29_DATA */
+			0x00000000,	/* DENALI_PI_30_DATA */
+			0x00000000,	/* DENALI_PI_31_DATA */
+			0x00000000,	/* DENALI_PI_32_DATA */
+			0x00000000,	/* DENALI_PI_33_DATA */
+			0x00000000,	/* DENALI_PI_34_DATA */
+			0x00000000,	/* DENALI_PI_35_DATA */
+			0x00000000,	/* DENALI_PI_36_DATA */
+			0x00000000,	/* DENALI_PI_37_DATA */
+			0x00000000,	/* DENALI_PI_38_DATA */
+			0x00000000,	/* DENALI_PI_39_DATA */
+			0x00000000,	/* DENALI_PI_40_DATA */
+			0x0f000101,	/* DENALI_PI_41_DATA */
+			0x082b3223,	/* DENALI_PI_42_DATA */
+			0x080c0004,	/* DENALI_PI_43_DATA */
+			0x00061c00,	/* DENALI_PI_44_DATA */
+			0x00000214,	/* DENALI_PI_45_DATA */
+			0x00bb0007,	/* DENALI_PI_46_DATA */
+			0x0c280068,	/* DENALI_PI_47_DATA */
+			0x06100034,	/* DENALI_PI_48_DATA */
+			0x00000500,	/* DENALI_PI_49_DATA */
+			0x00000000,	/* DENALI_PI_50_DATA */
+			0x00000000,	/* DENALI_PI_51_DATA */
+			0x00000000,	/* DENALI_PI_52_DATA */
+			0x00000000,	/* DENALI_PI_53_DATA */
+			0x00000000,	/* DENALI_PI_54_DATA */
+			0x00000000,	/* DENALI_PI_55_DATA */
+			0x00000000,	/* DENALI_PI_56_DATA */
+			0x00000000,	/* DENALI_PI_57_DATA */
+			0x04040100,	/* DENALI_PI_58_DATA */
+			0x0a000004,	/* DENALI_PI_59_DATA */
+			0x00000128,	/* DENALI_PI_60_DATA */
+			0x00000000,	/* DENALI_PI_61_DATA */
+			0x0003000f,	/* DENALI_PI_62_DATA */
+			0x00000018,	/* DENALI_PI_63_DATA */
+			0x00000000,	/* DENALI_PI_64_DATA */
+			0x00000000,	/* DENALI_PI_65_DATA */
+			0x00060002,	/* DENALI_PI_66_DATA */
+			0x00010001,	/* DENALI_PI_67_DATA */
+			0x00000101,	/* DENALI_PI_68_DATA */
+			0x00020001,	/* DENALI_PI_69_DATA */
+			0x00080004,	/* DENALI_PI_70_DATA */
+			0x00000000,	/* DENALI_PI_71_DATA */
+			0x05030000,	/* DENALI_PI_72_DATA */
+			0x070a0404,	/* DENALI_PI_73_DATA */
+			0x00000000,	/* DENALI_PI_74_DATA */
+			0x00000000,	/* DENALI_PI_75_DATA */
+			0x00000000,	/* DENALI_PI_76_DATA */
+			0x000f0f00,	/* DENALI_PI_77_DATA */
+			0x0000001e,	/* DENALI_PI_78_DATA */
+			0x00000000,	/* DENALI_PI_79_DATA */
+			0x01010300,	/* DENALI_PI_80_DATA */
+			0x00000000,	/* DENALI_PI_81_DATA */
+			0x00000000,	/* DENALI_PI_82_DATA */
+			0x01000000,	/* DENALI_PI_83_DATA */
+			0x00000101,	/* DENALI_PI_84_DATA */
+			0x55555a5a,	/* DENALI_PI_85_DATA */
+			0x55555a5a,	/* DENALI_PI_86_DATA */
+			0x55555a5a,	/* DENALI_PI_87_DATA */
+			0x55555a5a,	/* DENALI_PI_88_DATA */
+			0x0c050001,	/* DENALI_PI_89_DATA */
+			0x06020009,	/* DENALI_PI_90_DATA */
+			0x00010004,	/* DENALI_PI_91_DATA */
+			0x00000203,	/* DENALI_PI_92_DATA */
+			0x00030000,	/* DENALI_PI_93_DATA */
+			0x170f0000,	/* DENALI_PI_94_DATA */
+			0x00060018,	/* DENALI_PI_95_DATA */
+			0x000e0020,	/* DENALI_PI_96_DATA */
+			0x000a001c,	/* DENALI_PI_97_DATA */
+			0x00000000,	/* DENALI_PI_98_DATA */
+			0x00000000,	/* DENALI_PI_99_DATA */
+			0x00000100,	/* DENALI_PI_100_DATA */
+			0x140a0000,	/* DENALI_PI_101_DATA */
+			0x000d010a,	/* DENALI_PI_102_DATA */
+			0x0100c802,	/* DENALI_PI_103_DATA */
+			0x010a0064,	/* DENALI_PI_104_DATA */
+			0x000e0100,	/* DENALI_PI_105_DATA */
+			0x0100000e,	/* DENALI_PI_106_DATA */
+			0x00c900c9,	/* DENALI_PI_107_DATA */
+			0x00650100,	/* DENALI_PI_108_DATA */
+			0x1e1a0065,	/* DENALI_PI_109_DATA */
+			0x10010204,	/* DENALI_PI_110_DATA */
+			0x06070605,	/* DENALI_PI_111_DATA */
+			0x20000202,	/* DENALI_PI_112_DATA */
+			0x00201000,	/* DENALI_PI_113_DATA */
+			0x00201000,	/* DENALI_PI_114_DATA */
+			0x04041000,	/* DENALI_PI_115_DATA */
+			0x10020100,	/* DENALI_PI_116_DATA */
+			0x0003010c,	/* DENALI_PI_117_DATA */
+			0x004b004a,	/* DENALI_PI_118_DATA */
+			0x1a0f0000,	/* DENALI_PI_119_DATA */
+			0x0102041e,	/* DENALI_PI_120_DATA */
+			0x34000000,	/* DENALI_PI_121_DATA */
+			0x00000000,	/* DENALI_PI_122_DATA */
+			0x00000000,	/* DENALI_PI_123_DATA */
+			0x00010000,	/* DENALI_PI_124_DATA */
+			0x00000400,	/* DENALI_PI_125_DATA */
+			0x00310000,	/* DENALI_PI_126_DATA */
+			0x004d4d00,	/* DENALI_PI_127_DATA */
+			0x00120024,	/* DENALI_PI_128_DATA */
+			0x4d000031,	/* DENALI_PI_129_DATA */
+			0x0000144d,	/* DENALI_PI_130_DATA */
+			0x00310009,	/* DENALI_PI_131_DATA */
+			0x004d4d00,	/* DENALI_PI_132_DATA */
+			0x00000004,	/* DENALI_PI_133_DATA */
+			0x4d000031,	/* DENALI_PI_134_DATA */
+			0x0000244d,	/* DENALI_PI_135_DATA */
+			0x00310012,	/* DENALI_PI_136_DATA */
+			0x004d4d00,	/* DENALI_PI_137_DATA */
+			0x00090014,	/* DENALI_PI_138_DATA */
+			0x4d000031,	/* DENALI_PI_139_DATA */
+			0x0004004d,	/* DENALI_PI_140_DATA */
+			0x00310000,	/* DENALI_PI_141_DATA */
+			0x004d4d00,	/* DENALI_PI_142_DATA */
+			0x00120024,	/* DENALI_PI_143_DATA */
+			0x4d000031,	/* DENALI_PI_144_DATA */
+			0x0000144d,	/* DENALI_PI_145_DATA */
+			0x00310009,	/* DENALI_PI_146_DATA */
+			0x004d4d00,	/* DENALI_PI_147_DATA */
+			0x00000004,	/* DENALI_PI_148_DATA */
+			0x4d000031,	/* DENALI_PI_149_DATA */
+			0x0000244d,	/* DENALI_PI_150_DATA */
+			0x00310012,	/* DENALI_PI_151_DATA */
+			0x004d4d00,	/* DENALI_PI_152_DATA */
+			0x00090014,	/* DENALI_PI_153_DATA */
+			0x4d000031,	/* DENALI_PI_154_DATA */
+			0x0200004d,	/* DENALI_PI_155_DATA */
+			0x00c8000d,	/* DENALI_PI_156_DATA */
+			0x08080064,	/* DENALI_PI_157_DATA */
+			0x040a0404,	/* DENALI_PI_158_DATA */
+			0x03000d92,	/* DENALI_PI_159_DATA */
+			0x010a2001,	/* DENALI_PI_160_DATA */
+			0x0f11080a,	/* DENALI_PI_161_DATA */
+			0x0000110a,	/* DENALI_PI_162_DATA */
+			0x2200d92e,	/* DENALI_PI_163_DATA */
+			0x080c2003,	/* DENALI_PI_164_DATA */
+			0x0809080a,	/* DENALI_PI_165_DATA */
+			0x00000a0a,	/* DENALI_PI_166_DATA */
+			0x11006c97,	/* DENALI_PI_167_DATA */
+			0x040a2002,	/* DENALI_PI_168_DATA */
+			0x0200020a,	/* DENALI_PI_169_DATA */
+			0x02000200,	/* DENALI_PI_170_DATA */
+			0x02000200,	/* DENALI_PI_171_DATA */
+			0x02000200,	/* DENALI_PI_172_DATA */
+			0x02000200,	/* DENALI_PI_173_DATA */
+			0x00000000,	/* DENALI_PI_174_DATA */
+			0x00000000,	/* DENALI_PI_175_DATA */
+			0x00000000,	/* DENALI_PI_176_DATA */
+			0x00000000,	/* DENALI_PI_177_DATA */
+			0x00000000,	/* DENALI_PI_178_DATA */
+			0x00000000,	/* DENALI_PI_179_DATA */
+			0x00000000,	/* DENALI_PI_180_DATA */
+			0x00000000,	/* DENALI_PI_181_DATA */
+			0x00000000,	/* DENALI_PI_182_DATA */
+			0x00000000,	/* DENALI_PI_183_DATA */
+			0x00000000,	/* DENALI_PI_184_DATA */
+			0x00000000,	/* DENALI_PI_185_DATA */
+			0x01000400,	/* DENALI_PI_186_DATA */
+			0x00017600,	/* DENALI_PI_187_DATA */
+			0x00000e9c,	/* DENALI_PI_188_DATA */
+			0x00001850,	/* DENALI_PI_189_DATA */
+			0x0000f320,	/* DENALI_PI_190_DATA */
+			0x00000c20,	/* DENALI_PI_191_DATA */
+			0x00007940,	/* DENALI_PI_192_DATA */
+			0x08000000,	/* DENALI_PI_193_DATA */
+			0x00000100,	/* DENALI_PI_194_DATA */
+			0x00000000,	/* DENALI_PI_195_DATA */
+			0x00000000,	/* DENALI_PI_196_DATA */
+			0x00000000,	/* DENALI_PI_197_DATA */
+			0x00000000,	/* DENALI_PI_198_DATA */
+			0x00000002	/* DENALI_PI_199_DATA */
+		}
+	},
+	{
+		{
+			0x76543210,	/* DENALI_PHY_00_DATA */
+			0x0004f008,	/* DENALI_PHY_01_DATA */
+			0x00020119,	/* DENALI_PHY_02_DATA */
+			0x00000000,	/* DENALI_PHY_03_DATA */
+			0x00000000,	/* DENALI_PHY_04_DATA */
+			0x00010000,	/* DENALI_PHY_05_DATA */
+			0x01665555,	/* DENALI_PHY_06_DATA */
+			0x03665555,	/* DENALI_PHY_07_DATA */
+			0x00010f00,	/* DENALI_PHY_08_DATA */
+			0x05010200,	/* DENALI_PHY_09_DATA */
+			0x00000002,	/* DENALI_PHY_10_DATA */
+			0x00170180,	/* DENALI_PHY_11_DATA */
+			0x00cc0201,	/* DENALI_PHY_12_DATA */
+			0x00030066,	/* DENALI_PHY_13_DATA */
+			0x00000000,	/* DENALI_PHY_14_DATA */
+			0x00000000,	/* DENALI_PHY_15_DATA */
+			0x00000000,	/* DENALI_PHY_16_DATA */
+			0x00000000,	/* DENALI_PHY_17_DATA */
+			0x00000000,	/* DENALI_PHY_18_DATA */
+			0x00000000,	/* DENALI_PHY_19_DATA */
+			0x00000000,	/* DENALI_PHY_20_DATA */
+			0x00000000,	/* DENALI_PHY_21_DATA */
+			0x04080000,	/* DENALI_PHY_22_DATA */
+			0x04080400,	/* DENALI_PHY_23_DATA */
+			0x30000000,	/* DENALI_PHY_24_DATA */
+			0x0c00c007,	/* DENALI_PHY_25_DATA */
+			0x00000100,	/* DENALI_PHY_26_DATA */
+			0x00000000,	/* DENALI_PHY_27_DATA */
+			0xfd02fe01,	/* DENALI_PHY_28_DATA */
+			0xf708fb04,	/* DENALI_PHY_29_DATA */
+			0xdf20ef10,	/* DENALI_PHY_30_DATA */
+			0x7f80bf40,	/* DENALI_PHY_31_DATA */
+			0x0001aaaa,	/* DENALI_PHY_32_DATA */
+			0x00000000,	/* DENALI_PHY_33_DATA */
+			0x00000000,	/* DENALI_PHY_34_DATA */
+			0x00000000,	/* DENALI_PHY_35_DATA */
+			0x00000000,	/* DENALI_PHY_36_DATA */
+			0x00000000,	/* DENALI_PHY_37_DATA */
+			0x00000000,	/* DENALI_PHY_38_DATA */
+			0x00000000,	/* DENALI_PHY_39_DATA */
+			0x00000000,	/* DENALI_PHY_40_DATA */
+			0x00000000,	/* DENALI_PHY_41_DATA */
+			0x00000000,	/* DENALI_PHY_42_DATA */
+			0x00000000,	/* DENALI_PHY_43_DATA */
+			0x00000000,	/* DENALI_PHY_44_DATA */
+			0x00000000,	/* DENALI_PHY_45_DATA */
+			0x00000000,	/* DENALI_PHY_46_DATA */
+			0x00000000,	/* DENALI_PHY_47_DATA */
+			0x00000000,	/* DENALI_PHY_48_DATA */
+			0x00000000,	/* DENALI_PHY_49_DATA */
+			0x00000000,	/* DENALI_PHY_50_DATA */
+			0x00000000,	/* DENALI_PHY_51_DATA */
+			0x00200000,	/* DENALI_PHY_52_DATA */
+			0x00000000,	/* DENALI_PHY_53_DATA */
+			0x00000000,	/* DENALI_PHY_54_DATA */
+			0x00000000,	/* DENALI_PHY_55_DATA */
+			0x00000000,	/* DENALI_PHY_56_DATA */
+			0x00000000,	/* DENALI_PHY_57_DATA */
+			0x00000000,	/* DENALI_PHY_58_DATA */
+			0x02800280,	/* DENALI_PHY_59_DATA */
+			0x02800280,	/* DENALI_PHY_60_DATA */
+			0x02800280,	/* DENALI_PHY_61_DATA */
+			0x02800280,	/* DENALI_PHY_62_DATA */
+			0x00000280,	/* DENALI_PHY_63_DATA */
+			0x00000000,	/* DENALI_PHY_64_DATA */
+			0x00000000,	/* DENALI_PHY_65_DATA */
+			0x00000000,	/* DENALI_PHY_66_DATA */
+			0x00000000,	/* DENALI_PHY_67_DATA */
+			0x00800000,	/* DENALI_PHY_68_DATA */
+			0x00800080,	/* DENALI_PHY_69_DATA */
+			0x00800080,	/* DENALI_PHY_70_DATA */
+			0x00800080,	/* DENALI_PHY_71_DATA */
+			0x00800080,	/* DENALI_PHY_72_DATA */
+			0x00800080,	/* DENALI_PHY_73_DATA */
+			0x00800080,	/* DENALI_PHY_74_DATA */
+			0x00800080,	/* DENALI_PHY_75_DATA */
+			0x00800080,	/* DENALI_PHY_76_DATA */
+			0x01190080,	/* DENALI_PHY_77_DATA */
+			0x00000002,	/* DENALI_PHY_78_DATA */
+			0x00000000,	/* DENALI_PHY_79_DATA */
+			0x00000000,	/* DENALI_PHY_80_DATA */
+			0x00000200,	/* DENALI_PHY_81_DATA */
+			0x00000000,	/* DENALI_PHY_82_DATA */
+			0x51315152,	/* DENALI_PHY_83_DATA */
+			0xc0013150,	/* DENALI_PHY_84_DATA */
+			0x020000c0,	/* DENALI_PHY_85_DATA */
+			0x00100001,	/* DENALI_PHY_86_DATA */
+			0x07054204,	/* DENALI_PHY_87_DATA */
+			0x000f0c18,	/* DENALI_PHY_88_DATA */
+			0x01000140,	/* DENALI_PHY_89_DATA */
+			0x00000c10,	/* DENALI_PHY_90_DATA */
+			0x00000000,	/* DENALI_PHY_91_DATA */
+			0x00000000,	/* DENALI_PHY_92_DATA */
+			0x00000000,	/* DENALI_PHY_93_DATA */
+			0x00000000,	/* DENALI_PHY_94_DATA */
+			0x00000000,	/* DENALI_PHY_95_DATA */
+			0x00000000,	/* DENALI_PHY_96_DATA */
+			0x00000000,	/* DENALI_PHY_97_DATA */
+			0x00000000,	/* DENALI_PHY_98_DATA */
+			0x00000000,	/* DENALI_PHY_99_DATA */
+			0x00000000,	/* DENALI_PHY_100_DATA */
+			0x00000000,	/* DENALI_PHY_101_DATA */
+			0x00000000,	/* DENALI_PHY_102_DATA */
+			0x00000000,	/* DENALI_PHY_103_DATA */
+			0x00000000,	/* DENALI_PHY_104_DATA */
+			0x00000000,	/* DENALI_PHY_105_DATA */
+			0x00000000,	/* DENALI_PHY_106_DATA */
+			0x00000000,	/* DENALI_PHY_107_DATA */
+			0x00000000,	/* DENALI_PHY_108_DATA */
+			0x00000000,	/* DENALI_PHY_109_DATA */
+			0x00000000,	/* DENALI_PHY_110_DATA */
+			0x00000000,	/* DENALI_PHY_111_DATA */
+			0x00000000,	/* DENALI_PHY_112_DATA */
+			0x00000000,	/* DENALI_PHY_113_DATA */
+			0x00000000,	/* DENALI_PHY_114_DATA */
+			0x00000000,	/* DENALI_PHY_115_DATA */
+			0x00000000,	/* DENALI_PHY_116_DATA */
+			0x00000000,	/* DENALI_PHY_117_DATA */
+			0x00000000,	/* DENALI_PHY_118_DATA */
+			0x00000000,	/* DENALI_PHY_119_DATA */
+			0x00000000,	/* DENALI_PHY_120_DATA */
+			0x00000000,	/* DENALI_PHY_121_DATA */
+			0x00000000,	/* DENALI_PHY_122_DATA */
+			0x00000000,	/* DENALI_PHY_123_DATA */
+			0x00000000,	/* DENALI_PHY_124_DATA */
+			0x00000000,	/* DENALI_PHY_125_DATA */
+			0x00000000,	/* DENALI_PHY_126_DATA */
+			0x00000000,	/* DENALI_PHY_127_DATA */
+			0x76543210,	/* DENALI_PHY_128_DATA */
+			0x0004f008,	/* DENALI_PHY_129_DATA */
+			0x00020119,	/* DENALI_PHY_130_DATA */
+			0x00000000,	/* DENALI_PHY_131_DATA */
+			0x00000000,	/* DENALI_PHY_132_DATA */
+			0x00010000,	/* DENALI_PHY_133_DATA */
+			0x01665555,	/* DENALI_PHY_134_DATA */
+			0x03665555,	/* DENALI_PHY_135_DATA */
+			0x00010f00,	/* DENALI_PHY_136_DATA */
+			0x05010200,	/* DENALI_PHY_137_DATA */
+			0x00000002,	/* DENALI_PHY_138_DATA */
+			0x00170180,	/* DENALI_PHY_139_DATA */
+			0x00cc0201,	/* DENALI_PHY_140_DATA */
+			0x00030066,	/* DENALI_PHY_141_DATA */
+			0x00000000,	/* DENALI_PHY_142_DATA */
+			0x00000000,	/* DENALI_PHY_143_DATA */
+			0x00000000,	/* DENALI_PHY_144_DATA */
+			0x00000000,	/* DENALI_PHY_145_DATA */
+			0x00000000,	/* DENALI_PHY_146_DATA */
+			0x00000000,	/* DENALI_PHY_147_DATA */
+			0x00000000,	/* DENALI_PHY_148_DATA */
+			0x00000000,	/* DENALI_PHY_149_DATA */
+			0x04080000,	/* DENALI_PHY_150_DATA */
+			0x04080400,	/* DENALI_PHY_151_DATA */
+			0x30000000,	/* DENALI_PHY_152_DATA */
+			0x0c00c007,	/* DENALI_PHY_153_DATA */
+			0x00000100,	/* DENALI_PHY_154_DATA */
+			0x00000000,	/* DENALI_PHY_155_DATA */
+			0xfd02fe01,	/* DENALI_PHY_156_DATA */
+			0xf708fb04,	/* DENALI_PHY_157_DATA */
+			0xdf20ef10,	/* DENALI_PHY_158_DATA */
+			0x7f80bf40,	/* DENALI_PHY_159_DATA */
+			0x0000aaaa,	/* DENALI_PHY_160_DATA */
+			0x00000000,	/* DENALI_PHY_161_DATA */
+			0x00000000,	/* DENALI_PHY_162_DATA */
+			0x00000000,	/* DENALI_PHY_163_DATA */
+			0x00000000,	/* DENALI_PHY_164_DATA */
+			0x00000000,	/* DENALI_PHY_165_DATA */
+			0x00000000,	/* DENALI_PHY_166_DATA */
+			0x00000000,	/* DENALI_PHY_167_DATA */
+			0x00000000,	/* DENALI_PHY_168_DATA */
+			0x00000000,	/* DENALI_PHY_169_DATA */
+			0x00000000,	/* DENALI_PHY_170_DATA */
+			0x00000000,	/* DENALI_PHY_171_DATA */
+			0x00000000,	/* DENALI_PHY_172_DATA */
+			0x00000000,	/* DENALI_PHY_173_DATA */
+			0x00000000,	/* DENALI_PHY_174_DATA */
+			0x00000000,	/* DENALI_PHY_175_DATA */
+			0x00000000,	/* DENALI_PHY_176_DATA */
+			0x00000000,	/* DENALI_PHY_177_DATA */
+			0x00000000,	/* DENALI_PHY_178_DATA */
+			0x00000000,	/* DENALI_PHY_179_DATA */
+			0x00200000,	/* DENALI_PHY_180_DATA */
+			0x00000000,	/* DENALI_PHY_181_DATA */
+			0x00000000,	/* DENALI_PHY_182_DATA */
+			0x00000000,	/* DENALI_PHY_183_DATA */
+			0x00000000,	/* DENALI_PHY_184_DATA */
+			0x00000000,	/* DENALI_PHY_185_DATA */
+			0x00000000,	/* DENALI_PHY_186_DATA */
+			0x02800280,	/* DENALI_PHY_187_DATA */
+			0x02800280,	/* DENALI_PHY_188_DATA */
+			0x02800280,	/* DENALI_PHY_189_DATA */
+			0x02800280,	/* DENALI_PHY_190_DATA */
+			0x00000280,	/* DENALI_PHY_191_DATA */
+			0x00000000,	/* DENALI_PHY_192_DATA */
+			0x00000000,	/* DENALI_PHY_193_DATA */
+			0x00000000,	/* DENALI_PHY_194_DATA */
+			0x00000000,	/* DENALI_PHY_195_DATA */
+			0x00800000,	/* DENALI_PHY_196_DATA */
+			0x00800080,	/* DENALI_PHY_197_DATA */
+			0x00800080,	/* DENALI_PHY_198_DATA */
+			0x00800080,	/* DENALI_PHY_199_DATA */
+			0x00800080,	/* DENALI_PHY_200_DATA */
+			0x00800080,	/* DENALI_PHY_201_DATA */
+			0x00800080,	/* DENALI_PHY_202_DATA */
+			0x00800080,	/* DENALI_PHY_203_DATA */
+			0x00800080,	/* DENALI_PHY_204_DATA */
+			0x01190080,	/* DENALI_PHY_205_DATA */
+			0x00000002,	/* DENALI_PHY_206_DATA */
+			0x00000000,	/* DENALI_PHY_207_DATA */
+			0x00000000,	/* DENALI_PHY_208_DATA */
+			0x00000200,	/* DENALI_PHY_209_DATA */
+			0x00000000,	/* DENALI_PHY_210_DATA */
+			0x51315152,	/* DENALI_PHY_211_DATA */
+			0xc0013150,	/* DENALI_PHY_212_DATA */
+			0x020000c0,	/* DENALI_PHY_213_DATA */
+			0x00100001,	/* DENALI_PHY_214_DATA */
+			0x07054204,	/* DENALI_PHY_215_DATA */
+			0x000f0c18,	/* DENALI_PHY_216_DATA */
+			0x01000140,	/* DENALI_PHY_217_DATA */
+			0x00000c10,	/* DENALI_PHY_218_DATA */
+			0x00000000,	/* DENALI_PHY_219_DATA */
+			0x00000000,	/* DENALI_PHY_220_DATA */
+			0x00000000,	/* DENALI_PHY_221_DATA */
+			0x00000000,	/* DENALI_PHY_222_DATA */
+			0x00000000,	/* DENALI_PHY_223_DATA */
+			0x00000000,	/* DENALI_PHY_224_DATA */
+			0x00000000,	/* DENALI_PHY_225_DATA */
+			0x00000000,	/* DENALI_PHY_226_DATA */
+			0x00000000,	/* DENALI_PHY_227_DATA */
+			0x00000000,	/* DENALI_PHY_228_DATA */
+			0x00000000,	/* DENALI_PHY_229_DATA */
+			0x00000000,	/* DENALI_PHY_230_DATA */
+			0x00000000,	/* DENALI_PHY_231_DATA */
+			0x00000000,	/* DENALI_PHY_232_DATA */
+			0x00000000,	/* DENALI_PHY_233_DATA */
+			0x00000000,	/* DENALI_PHY_234_DATA */
+			0x00000000,	/* DENALI_PHY_235_DATA */
+			0x00000000,	/* DENALI_PHY_236_DATA */
+			0x00000000,	/* DENALI_PHY_237_DATA */
+			0x00000000,	/* DENALI_PHY_238_DATA */
+			0x00000000,	/* DENALI_PHY_239_DATA */
+			0x00000000,	/* DENALI_PHY_240_DATA */
+			0x00000000,	/* DENALI_PHY_241_DATA */
+			0x00000000,	/* DENALI_PHY_242_DATA */
+			0x00000000,	/* DENALI_PHY_243_DATA */
+			0x00000000,	/* DENALI_PHY_244_DATA */
+			0x00000000,	/* DENALI_PHY_245_DATA */
+			0x00000000,	/* DENALI_PHY_246_DATA */
+			0x00000000,	/* DENALI_PHY_247_DATA */
+			0x00000000,	/* DENALI_PHY_248_DATA */
+			0x00000000,	/* DENALI_PHY_249_DATA */
+			0x00000000,	/* DENALI_PHY_250_DATA */
+			0x00000000,	/* DENALI_PHY_251_DATA */
+			0x00000000,	/* DENALI_PHY_252_DATA */
+			0x00000000,	/* DENALI_PHY_253_DATA */
+			0x00000000,	/* DENALI_PHY_254_DATA */
+			0x00000000,	/* DENALI_PHY_255_DATA */
+			0x76543210,	/* DENALI_PHY_256_DATA */
+			0x0004f008,	/* DENALI_PHY_257_DATA */
+			0x00020119,	/* DENALI_PHY_258_DATA */
+			0x00000000,	/* DENALI_PHY_259_DATA */
+			0x00000000,	/* DENALI_PHY_260_DATA */
+			0x00010000,	/* DENALI_PHY_261_DATA */
+			0x01665555,	/* DENALI_PHY_262_DATA */
+			0x03665555,	/* DENALI_PHY_263_DATA */
+			0x00010f00,	/* DENALI_PHY_264_DATA */
+			0x05010200,	/* DENALI_PHY_265_DATA */
+			0x00000002,	/* DENALI_PHY_266_DATA */
+			0x00170180,	/* DENALI_PHY_267_DATA */
+			0x00cc0201,	/* DENALI_PHY_268_DATA */
+			0x00030066,	/* DENALI_PHY_269_DATA */
+			0x00000000,	/* DENALI_PHY_270_DATA */
+			0x00000000,	/* DENALI_PHY_271_DATA */
+			0x00000000,	/* DENALI_PHY_272_DATA */
+			0x00000000,	/* DENALI_PHY_273_DATA */
+			0x00000000,	/* DENALI_PHY_274_DATA */
+			0x00000000,	/* DENALI_PHY_275_DATA */
+			0x00000000,	/* DENALI_PHY_276_DATA */
+			0x00000000,	/* DENALI_PHY_277_DATA */
+			0x04080000,	/* DENALI_PHY_278_DATA */
+			0x04080400,	/* DENALI_PHY_279_DATA */
+			0x30000000,	/* DENALI_PHY_280_DATA */
+			0x0c00c007,	/* DENALI_PHY_281_DATA */
+			0x00000100,	/* DENALI_PHY_282_DATA */
+			0x00000000,	/* DENALI_PHY_283_DATA */
+			0xfd02fe01,	/* DENALI_PHY_284_DATA */
+			0xf708fb04,	/* DENALI_PHY_285_DATA */
+			0xdf20ef10,	/* DENALI_PHY_286_DATA */
+			0x7f80bf40,	/* DENALI_PHY_287_DATA */
+			0x0001aaaa,	/* DENALI_PHY_288_DATA */
+			0x00000000,	/* DENALI_PHY_289_DATA */
+			0x00000000,	/* DENALI_PHY_290_DATA */
+			0x00000000,	/* DENALI_PHY_291_DATA */
+			0x00000000,	/* DENALI_PHY_292_DATA */
+			0x00000000,	/* DENALI_PHY_293_DATA */
+			0x00000000,	/* DENALI_PHY_294_DATA */
+			0x00000000,	/* DENALI_PHY_295_DATA */
+			0x00000000,	/* DENALI_PHY_296_DATA */
+			0x00000000,	/* DENALI_PHY_297_DATA */
+			0x00000000,	/* DENALI_PHY_298_DATA */
+			0x00000000,	/* DENALI_PHY_299_DATA */
+			0x00000000,	/* DENALI_PHY_300_DATA */
+			0x00000000,	/* DENALI_PHY_301_DATA */
+			0x00000000,	/* DENALI_PHY_302_DATA */
+			0x00000000,	/* DENALI_PHY_303_DATA */
+			0x00000000,	/* DENALI_PHY_304_DATA */
+			0x00000000,	/* DENALI_PHY_305_DATA */
+			0x00000000,	/* DENALI_PHY_306_DATA */
+			0x00000000,	/* DENALI_PHY_307_DATA */
+			0x00200000,	/* DENALI_PHY_308_DATA */
+			0x00000000,	/* DENALI_PHY_309_DATA */
+			0x00000000,	/* DENALI_PHY_310_DATA */
+			0x00000000,	/* DENALI_PHY_311_DATA */
+			0x00000000,	/* DENALI_PHY_312_DATA */
+			0x00000000,	/* DENALI_PHY_313_DATA */
+			0x00000000,	/* DENALI_PHY_314_DATA */
+			0x02800280,	/* DENALI_PHY_315_DATA */
+			0x02800280,	/* DENALI_PHY_316_DATA */
+			0x02800280,	/* DENALI_PHY_317_DATA */
+			0x02800280,	/* DENALI_PHY_318_DATA */
+			0x00000280,	/* DENALI_PHY_319_DATA */
+			0x00000000,	/* DENALI_PHY_320_DATA */
+			0x00000000,	/* DENALI_PHY_321_DATA */
+			0x00000000,	/* DENALI_PHY_322_DATA */
+			0x00000000,	/* DENALI_PHY_323_DATA */
+			0x00800000,	/* DENALI_PHY_324_DATA */
+			0x00800080,	/* DENALI_PHY_325_DATA */
+			0x00800080,	/* DENALI_PHY_326_DATA */
+			0x00800080,	/* DENALI_PHY_327_DATA */
+			0x00800080,	/* DENALI_PHY_328_DATA */
+			0x00800080,	/* DENALI_PHY_329_DATA */
+			0x00800080,	/* DENALI_PHY_330_DATA */
+			0x00800080,	/* DENALI_PHY_331_DATA */
+			0x00800080,	/* DENALI_PHY_332_DATA */
+			0x01190080,	/* DENALI_PHY_333_DATA */
+			0x00000002,	/* DENALI_PHY_334_DATA */
+			0x00000000,	/* DENALI_PHY_335_DATA */
+			0x00000000,	/* DENALI_PHY_336_DATA */
+			0x00000200,	/* DENALI_PHY_337_DATA */
+			0x00000000,	/* DENALI_PHY_338_DATA */
+			0x51315152,	/* DENALI_PHY_339_DATA */
+			0xc0013150,	/* DENALI_PHY_340_DATA */
+			0x020000c0,	/* DENALI_PHY_341_DATA */
+			0x00100001,	/* DENALI_PHY_342_DATA */
+			0x07054204,	/* DENALI_PHY_343_DATA */
+			0x000f0c18,	/* DENALI_PHY_344_DATA */
+			0x01000140,	/* DENALI_PHY_345_DATA */
+			0x00000c10,	/* DENALI_PHY_346_DATA */
+			0x00000000,	/* DENALI_PHY_347_DATA */
+			0x00000000,	/* DENALI_PHY_348_DATA */
+			0x00000000,	/* DENALI_PHY_349_DATA */
+			0x00000000,	/* DENALI_PHY_350_DATA */
+			0x00000000,	/* DENALI_PHY_351_DATA */
+			0x00000000,	/* DENALI_PHY_352_DATA */
+			0x00000000,	/* DENALI_PHY_353_DATA */
+			0x00000000,	/* DENALI_PHY_354_DATA */
+			0x00000000,	/* DENALI_PHY_355_DATA */
+			0x00000000,	/* DENALI_PHY_356_DATA */
+			0x00000000,	/* DENALI_PHY_357_DATA */
+			0x00000000,	/* DENALI_PHY_358_DATA */
+			0x00000000,	/* DENALI_PHY_359_DATA */
+			0x00000000,	/* DENALI_PHY_360_DATA */
+			0x00000000,	/* DENALI_PHY_361_DATA */
+			0x00000000,	/* DENALI_PHY_362_DATA */
+			0x00000000,	/* DENALI_PHY_363_DATA */
+			0x00000000,	/* DENALI_PHY_364_DATA */
+			0x00000000,	/* DENALI_PHY_365_DATA */
+			0x00000000,	/* DENALI_PHY_366_DATA */
+			0x00000000,	/* DENALI_PHY_367_DATA */
+			0x00000000,	/* DENALI_PHY_368_DATA */
+			0x00000000,	/* DENALI_PHY_369_DATA */
+			0x00000000,	/* DENALI_PHY_370_DATA */
+			0x00000000,	/* DENALI_PHY_371_DATA */
+			0x00000000,	/* DENALI_PHY_372_DATA */
+			0x00000000,	/* DENALI_PHY_373_DATA */
+			0x00000000,	/* DENALI_PHY_374_DATA */
+			0x00000000,	/* DENALI_PHY_375_DATA */
+			0x00000000,	/* DENALI_PHY_376_DATA */
+			0x00000000,	/* DENALI_PHY_377_DATA */
+			0x00000000,	/* DENALI_PHY_378_DATA */
+			0x00000000,	/* DENALI_PHY_379_DATA */
+			0x00000000,	/* DENALI_PHY_380_DATA */
+			0x00000000,	/* DENALI_PHY_381_DATA */
+			0x00000000,	/* DENALI_PHY_382_DATA */
+			0x00000000,	/* DENALI_PHY_383_DATA */
+			0x76543210,	/* DENALI_PHY_384_DATA */
+			0x0004f008,	/* DENALI_PHY_385_DATA */
+			0x00020119,	/* DENALI_PHY_386_DATA */
+			0x00000000,	/* DENALI_PHY_387_DATA */
+			0x00000000,	/* DENALI_PHY_388_DATA */
+			0x00010000,	/* DENALI_PHY_389_DATA */
+			0x01665555,	/* DENALI_PHY_390_DATA */
+			0x03665555,	/* DENALI_PHY_391_DATA */
+			0x00010f00,	/* DENALI_PHY_392_DATA */
+			0x05010200,	/* DENALI_PHY_393_DATA */
+			0x00000002,	/* DENALI_PHY_394_DATA */
+			0x00170180,	/* DENALI_PHY_395_DATA */
+			0x00cc0201,	/* DENALI_PHY_396_DATA */
+			0x00030066,	/* DENALI_PHY_397_DATA */
+			0x00000000,	/* DENALI_PHY_398_DATA */
+			0x00000000,	/* DENALI_PHY_399_DATA */
+			0x00000000,	/* DENALI_PHY_400_DATA */
+			0x00000000,	/* DENALI_PHY_401_DATA */
+			0x00000000,	/* DENALI_PHY_402_DATA */
+			0x00000000,	/* DENALI_PHY_403_DATA */
+			0x00000000,	/* DENALI_PHY_404_DATA */
+			0x00000000,	/* DENALI_PHY_405_DATA */
+			0x04080000,	/* DENALI_PHY_406_DATA */
+			0x04080400,	/* DENALI_PHY_407_DATA */
+			0x30000000,	/* DENALI_PHY_408_DATA */
+			0x0c00c007,	/* DENALI_PHY_409_DATA */
+			0x00000100,	/* DENALI_PHY_410_DATA */
+			0x00000000,	/* DENALI_PHY_411_DATA */
+			0xfd02fe01,	/* DENALI_PHY_412_DATA */
+			0xf708fb04,	/* DENALI_PHY_413_DATA */
+			0xdf20ef10,	/* DENALI_PHY_414_DATA */
+			0x7f80bf40,	/* DENALI_PHY_415_DATA */
+			0x0000aaaa,	/* DENALI_PHY_416_DATA */
+			0x00000000,	/* DENALI_PHY_417_DATA */
+			0x00000000,	/* DENALI_PHY_418_DATA */
+			0x00000000,	/* DENALI_PHY_419_DATA */
+			0x00000000,	/* DENALI_PHY_420_DATA */
+			0x00000000,	/* DENALI_PHY_421_DATA */
+			0x00000000,	/* DENALI_PHY_422_DATA */
+			0x00000000,	/* DENALI_PHY_423_DATA */
+			0x00000000,	/* DENALI_PHY_424_DATA */
+			0x00000000,	/* DENALI_PHY_425_DATA */
+			0x00000000,	/* DENALI_PHY_426_DATA */
+			0x00000000,	/* DENALI_PHY_427_DATA */
+			0x00000000,	/* DENALI_PHY_428_DATA */
+			0x00000000,	/* DENALI_PHY_429_DATA */
+			0x00000000,	/* DENALI_PHY_430_DATA */
+			0x00000000,	/* DENALI_PHY_431_DATA */
+			0x00000000,	/* DENALI_PHY_432_DATA */
+			0x00000000,	/* DENALI_PHY_433_DATA */
+			0x00000000,	/* DENALI_PHY_434_DATA */
+			0x00000000,	/* DENALI_PHY_435_DATA */
+			0x00200000,	/* DENALI_PHY_436_DATA */
+			0x00000000,	/* DENALI_PHY_437_DATA */
+			0x00000000,	/* DENALI_PHY_438_DATA */
+			0x00000000,	/* DENALI_PHY_439_DATA */
+			0x00000000,	/* DENALI_PHY_440_DATA */
+			0x00000000,	/* DENALI_PHY_441_DATA */
+			0x00000000,	/* DENALI_PHY_442_DATA */
+			0x02800280,	/* DENALI_PHY_443_DATA */
+			0x02800280,	/* DENALI_PHY_444_DATA */
+			0x02800280,	/* DENALI_PHY_445_DATA */
+			0x02800280,	/* DENALI_PHY_446_DATA */
+			0x00000280,	/* DENALI_PHY_447_DATA */
+			0x00000000,	/* DENALI_PHY_448_DATA */
+			0x00000000,	/* DENALI_PHY_449_DATA */
+			0x00000000,	/* DENALI_PHY_450_DATA */
+			0x00000000,	/* DENALI_PHY_451_DATA */
+			0x00800000,	/* DENALI_PHY_452_DATA */
+			0x00800080,	/* DENALI_PHY_453_DATA */
+			0x00800080,	/* DENALI_PHY_454_DATA */
+			0x00800080,	/* DENALI_PHY_455_DATA */
+			0x00800080,	/* DENALI_PHY_456_DATA */
+			0x00800080,	/* DENALI_PHY_457_DATA */
+			0x00800080,	/* DENALI_PHY_458_DATA */
+			0x00800080,	/* DENALI_PHY_459_DATA */
+			0x00800080,	/* DENALI_PHY_460_DATA */
+			0x01190080,	/* DENALI_PHY_461_DATA */
+			0x00000002,	/* DENALI_PHY_462_DATA */
+			0x00000000,	/* DENALI_PHY_463_DATA */
+			0x00000000,	/* DENALI_PHY_464_DATA */
+			0x00000200,	/* DENALI_PHY_465_DATA */
+			0x00000000,	/* DENALI_PHY_466_DATA */
+			0x51315152,	/* DENALI_PHY_467_DATA */
+			0xc0013150,	/* DENALI_PHY_468_DATA */
+			0x020000c0,	/* DENALI_PHY_469_DATA */
+			0x00100001,	/* DENALI_PHY_470_DATA */
+			0x07054204,	/* DENALI_PHY_471_DATA */
+			0x000f0c18,	/* DENALI_PHY_472_DATA */
+			0x01000140,	/* DENALI_PHY_473_DATA */
+			0x00000c10,	/* DENALI_PHY_474_DATA */
+			0x00000000,	/* DENALI_PHY_475_DATA */
+			0x00000000,	/* DENALI_PHY_476_DATA */
+			0x00000000,	/* DENALI_PHY_477_DATA */
+			0x00000000,	/* DENALI_PHY_478_DATA */
+			0x00000000,	/* DENALI_PHY_479_DATA */
+			0x00000000,	/* DENALI_PHY_480_DATA */
+			0x00000000,	/* DENALI_PHY_481_DATA */
+			0x00000000,	/* DENALI_PHY_482_DATA */
+			0x00000000,	/* DENALI_PHY_483_DATA */
+			0x00000000,	/* DENALI_PHY_484_DATA */
+			0x00000000,	/* DENALI_PHY_485_DATA */
+			0x00000000,	/* DENALI_PHY_486_DATA */
+			0x00000000,	/* DENALI_PHY_487_DATA */
+			0x00000000,	/* DENALI_PHY_488_DATA */
+			0x00000000,	/* DENALI_PHY_489_DATA */
+			0x00000000,	/* DENALI_PHY_490_DATA */
+			0x00000000,	/* DENALI_PHY_491_DATA */
+			0x00000000,	/* DENALI_PHY_492_DATA */
+			0x00000000,	/* DENALI_PHY_493_DATA */
+			0x00000000,	/* DENALI_PHY_494_DATA */
+			0x00000000,	/* DENALI_PHY_495_DATA */
+			0x00000000,	/* DENALI_PHY_496_DATA */
+			0x00000000,	/* DENALI_PHY_497_DATA */
+			0x00000000,	/* DENALI_PHY_498_DATA */
+			0x00000000,	/* DENALI_PHY_499_DATA */
+			0x00000000,	/* DENALI_PHY_500_DATA */
+			0x00000000,	/* DENALI_PHY_501_DATA */
+			0x00000000,	/* DENALI_PHY_502_DATA */
+			0x00000000,	/* DENALI_PHY_503_DATA */
+			0x00000000,	/* DENALI_PHY_504_DATA */
+			0x00000000,	/* DENALI_PHY_505_DATA */
+			0x00000000,	/* DENALI_PHY_506_DATA */
+			0x00000000,	/* DENALI_PHY_507_DATA */
+			0x00000000,	/* DENALI_PHY_508_DATA */
+			0x00000000,	/* DENALI_PHY_509_DATA */
+			0x00000000,	/* DENALI_PHY_510_DATA */
+			0x00000000,	/* DENALI_PHY_511_DATA */
+			0x00000000,	/* DENALI_PHY_512_DATA */
+			0x00000000,	/* DENALI_PHY_513_DATA */
+			0x00000000,	/* DENALI_PHY_514_DATA */
+			0x00000000,	/* DENALI_PHY_515_DATA */
+			0x00000000,	/* DENALI_PHY_516_DATA */
+			0x00000000,	/* DENALI_PHY_517_DATA */
+			0x00000000,	/* DENALI_PHY_518_DATA */
+			0x00000002,	/* DENALI_PHY_519_DATA */
+			0x00000000,	/* DENALI_PHY_520_DATA */
+			0x00000000,	/* DENALI_PHY_521_DATA */
+			0x00000000,	/* DENALI_PHY_522_DATA */
+			0x00400320,	/* DENALI_PHY_523_DATA */
+			0x00000040,	/* DENALI_PHY_524_DATA */
+			0x00dcba98,	/* DENALI_PHY_525_DATA */
+			0x00000000,	/* DENALI_PHY_526_DATA */
+			0x00dcba98,	/* DENALI_PHY_527_DATA */
+			0x01000000,	/* DENALI_PHY_528_DATA */
+			0x00020003,	/* DENALI_PHY_529_DATA */
+			0x00000000,	/* DENALI_PHY_530_DATA */
+			0x00000000,	/* DENALI_PHY_531_DATA */
+			0x00000000,	/* DENALI_PHY_532_DATA */
+			0x0000002a,	/* DENALI_PHY_533_DATA */
+			0x00000015,	/* DENALI_PHY_534_DATA */
+			0x00000015,	/* DENALI_PHY_535_DATA */
+			0x0000002a,	/* DENALI_PHY_536_DATA */
+			0x00000033,	/* DENALI_PHY_537_DATA */
+			0x0000000c,	/* DENALI_PHY_538_DATA */
+			0x0000000c,	/* DENALI_PHY_539_DATA */
+			0x00000033,	/* DENALI_PHY_540_DATA */
+			0x0a418820,	/* DENALI_PHY_541_DATA */
+			0x003f0000,	/* DENALI_PHY_542_DATA */
+			0x0000003f,	/* DENALI_PHY_543_DATA */
+			0x00030055,	/* DENALI_PHY_544_DATA */
+			0x03000300,	/* DENALI_PHY_545_DATA */
+			0x03000300,	/* DENALI_PHY_546_DATA */
+			0x00000300,	/* DENALI_PHY_547_DATA */
+			0x42080010,	/* DENALI_PHY_548_DATA */
+			0x00000003,	/* DENALI_PHY_549_DATA */
+			0x00000000,	/* DENALI_PHY_550_DATA */
+			0x00000000,	/* DENALI_PHY_551_DATA */
+			0x00000000,	/* DENALI_PHY_552_DATA */
+			0x00000000,	/* DENALI_PHY_553_DATA */
+			0x00000000,	/* DENALI_PHY_554_DATA */
+			0x00000000,	/* DENALI_PHY_555_DATA */
+			0x00000000,	/* DENALI_PHY_556_DATA */
+			0x00000000,	/* DENALI_PHY_557_DATA */
+			0x00000000,	/* DENALI_PHY_558_DATA */
+			0x00000000,	/* DENALI_PHY_559_DATA */
+			0x00000000,	/* DENALI_PHY_560_DATA */
+			0x00000000,	/* DENALI_PHY_561_DATA */
+			0x00000000,	/* DENALI_PHY_562_DATA */
+			0x00000000,	/* DENALI_PHY_563_DATA */
+			0x00000000,	/* DENALI_PHY_564_DATA */
+			0x00000000,	/* DENALI_PHY_565_DATA */
+			0x00000000,	/* DENALI_PHY_566_DATA */
+			0x00000000,	/* DENALI_PHY_567_DATA */
+			0x00000000,	/* DENALI_PHY_568_DATA */
+			0x00000000,	/* DENALI_PHY_569_DATA */
+			0x00000000,	/* DENALI_PHY_570_DATA */
+			0x00000000,	/* DENALI_PHY_571_DATA */
+			0x00000000,	/* DENALI_PHY_572_DATA */
+			0x00000000,	/* DENALI_PHY_573_DATA */
+			0x00000000,	/* DENALI_PHY_574_DATA */
+			0x00000000,	/* DENALI_PHY_575_DATA */
+			0x00000000,	/* DENALI_PHY_576_DATA */
+			0x00000000,	/* DENALI_PHY_577_DATA */
+			0x00000000,	/* DENALI_PHY_578_DATA */
+			0x00000000,	/* DENALI_PHY_579_DATA */
+			0x00000000,	/* DENALI_PHY_580_DATA */
+			0x00000000,	/* DENALI_PHY_581_DATA */
+			0x00000000,	/* DENALI_PHY_582_DATA */
+			0x00000000,	/* DENALI_PHY_583_DATA */
+			0x00000000,	/* DENALI_PHY_584_DATA */
+			0x00000000,	/* DENALI_PHY_585_DATA */
+			0x00000000,	/* DENALI_PHY_586_DATA */
+			0x00000000,	/* DENALI_PHY_587_DATA */
+			0x00000000,	/* DENALI_PHY_588_DATA */
+			0x00000000,	/* DENALI_PHY_589_DATA */
+			0x00000000,	/* DENALI_PHY_590_DATA */
+			0x00000000,	/* DENALI_PHY_591_DATA */
+			0x00000000,	/* DENALI_PHY_592_DATA */
+			0x00000000,	/* DENALI_PHY_593_DATA */
+			0x00000000,	/* DENALI_PHY_594_DATA */
+			0x00000000,	/* DENALI_PHY_595_DATA */
+			0x00000000,	/* DENALI_PHY_596_DATA */
+			0x00000000,	/* DENALI_PHY_597_DATA */
+			0x00000000,	/* DENALI_PHY_598_DATA */
+			0x00000000,	/* DENALI_PHY_599_DATA */
+			0x00000000,	/* DENALI_PHY_600_DATA */
+			0x00000000,	/* DENALI_PHY_601_DATA */
+			0x00000000,	/* DENALI_PHY_602_DATA */
+			0x00000000,	/* DENALI_PHY_603_DATA */
+			0x00000000,	/* DENALI_PHY_604_DATA */
+			0x00000000,	/* DENALI_PHY_605_DATA */
+			0x00000000,	/* DENALI_PHY_606_DATA */
+			0x00000000,	/* DENALI_PHY_607_DATA */
+			0x00000000,	/* DENALI_PHY_608_DATA */
+			0x00000000,	/* DENALI_PHY_609_DATA */
+			0x00000000,	/* DENALI_PHY_610_DATA */
+			0x00000000,	/* DENALI_PHY_611_DATA */
+			0x00000000,	/* DENALI_PHY_612_DATA */
+			0x00000000,	/* DENALI_PHY_613_DATA */
+			0x00000000,	/* DENALI_PHY_614_DATA */
+			0x00000000,	/* DENALI_PHY_615_DATA */
+			0x00000000,	/* DENALI_PHY_616_DATA */
+			0x00000000,	/* DENALI_PHY_617_DATA */
+			0x00000000,	/* DENALI_PHY_618_DATA */
+			0x00000000,	/* DENALI_PHY_619_DATA */
+			0x00000000,	/* DENALI_PHY_620_DATA */
+			0x00000000,	/* DENALI_PHY_621_DATA */
+			0x00000000,	/* DENALI_PHY_622_DATA */
+			0x00000000,	/* DENALI_PHY_623_DATA */
+			0x00000000,	/* DENALI_PHY_624_DATA */
+			0x00000000,	/* DENALI_PHY_625_DATA */
+			0x00000000,	/* DENALI_PHY_626_DATA */
+			0x00000000,	/* DENALI_PHY_627_DATA */
+			0x00000000,	/* DENALI_PHY_628_DATA */
+			0x00000000,	/* DENALI_PHY_629_DATA */
+			0x00000000,	/* DENALI_PHY_630_DATA */
+			0x00000000,	/* DENALI_PHY_631_DATA */
+			0x00000000,	/* DENALI_PHY_632_DATA */
+			0x00000000,	/* DENALI_PHY_633_DATA */
+			0x00000000,	/* DENALI_PHY_634_DATA */
+			0x00000000,	/* DENALI_PHY_635_DATA */
+			0x00000000,	/* DENALI_PHY_636_DATA */
+			0x00000000,	/* DENALI_PHY_637_DATA */
+			0x00000000,	/* DENALI_PHY_638_DATA */
+			0x00000000,	/* DENALI_PHY_639_DATA */
+			0x00000000,	/* DENALI_PHY_640_DATA */
+			0x00000000,	/* DENALI_PHY_641_DATA */
+			0x00000000,	/* DENALI_PHY_642_DATA */
+			0x00000000,	/* DENALI_PHY_643_DATA */
+			0x00000000,	/* DENALI_PHY_644_DATA */
+			0x00000000,	/* DENALI_PHY_645_DATA */
+			0x00000000,	/* DENALI_PHY_646_DATA */
+			0x00000002,	/* DENALI_PHY_647_DATA */
+			0x00000000,	/* DENALI_PHY_648_DATA */
+			0x00000000,	/* DENALI_PHY_649_DATA */
+			0x00000000,	/* DENALI_PHY_650_DATA */
+			0x00400320,	/* DENALI_PHY_651_DATA */
+			0x00000040,	/* DENALI_PHY_652_DATA */
+			0x00000000,	/* DENALI_PHY_653_DATA */
+			0x00000000,	/* DENALI_PHY_654_DATA */
+			0x00000000,	/* DENALI_PHY_655_DATA */
+			0x01000000,	/* DENALI_PHY_656_DATA */
+			0x00020003,	/* DENALI_PHY_657_DATA */
+			0x00000000,	/* DENALI_PHY_658_DATA */
+			0x00000000,	/* DENALI_PHY_659_DATA */
+			0x00000000,	/* DENALI_PHY_660_DATA */
+			0x0000002a,	/* DENALI_PHY_661_DATA */
+			0x00000015,	/* DENALI_PHY_662_DATA */
+			0x00000015,	/* DENALI_PHY_663_DATA */
+			0x0000002a,	/* DENALI_PHY_664_DATA */
+			0x00000033,	/* DENALI_PHY_665_DATA */
+			0x0000000c,	/* DENALI_PHY_666_DATA */
+			0x0000000c,	/* DENALI_PHY_667_DATA */
+			0x00000033,	/* DENALI_PHY_668_DATA */
+			0x00000000,	/* DENALI_PHY_669_DATA */
+			0x00000000,	/* DENALI_PHY_670_DATA */
+			0x00000000,	/* DENALI_PHY_671_DATA */
+			0x00030055,	/* DENALI_PHY_672_DATA */
+			0x03000300,	/* DENALI_PHY_673_DATA */
+			0x03000300,	/* DENALI_PHY_674_DATA */
+			0x00000300,	/* DENALI_PHY_675_DATA */
+			0x42080010,	/* DENALI_PHY_676_DATA */
+			0x00000003,	/* DENALI_PHY_677_DATA */
+			0x00000000,	/* DENALI_PHY_678_DATA */
+			0x00000000,	/* DENALI_PHY_679_DATA */
+			0x00000000,	/* DENALI_PHY_680_DATA */
+			0x00000000,	/* DENALI_PHY_681_DATA */
+			0x00000000,	/* DENALI_PHY_682_DATA */
+			0x00000000,	/* DENALI_PHY_683_DATA */
+			0x00000000,	/* DENALI_PHY_684_DATA */
+			0x00000000,	/* DENALI_PHY_685_DATA */
+			0x00000000,	/* DENALI_PHY_686_DATA */
+			0x00000000,	/* DENALI_PHY_687_DATA */
+			0x00000000,	/* DENALI_PHY_688_DATA */
+			0x00000000,	/* DENALI_PHY_689_DATA */
+			0x00000000,	/* DENALI_PHY_690_DATA */
+			0x00000000,	/* DENALI_PHY_691_DATA */
+			0x00000000,	/* DENALI_PHY_692_DATA */
+			0x00000000,	/* DENALI_PHY_693_DATA */
+			0x00000000,	/* DENALI_PHY_694_DATA */
+			0x00000000,	/* DENALI_PHY_695_DATA */
+			0x00000000,	/* DENALI_PHY_696_DATA */
+			0x00000000,	/* DENALI_PHY_697_DATA */
+			0x00000000,	/* DENALI_PHY_698_DATA */
+			0x00000000,	/* DENALI_PHY_699_DATA */
+			0x00000000,	/* DENALI_PHY_700_DATA */
+			0x00000000,	/* DENALI_PHY_701_DATA */
+			0x00000000,	/* DENALI_PHY_702_DATA */
+			0x00000000,	/* DENALI_PHY_703_DATA */
+			0x00000000,	/* DENALI_PHY_704_DATA */
+			0x00000000,	/* DENALI_PHY_705_DATA */
+			0x00000000,	/* DENALI_PHY_706_DATA */
+			0x00000000,	/* DENALI_PHY_707_DATA */
+			0x00000000,	/* DENALI_PHY_708_DATA */
+			0x00000000,	/* DENALI_PHY_709_DATA */
+			0x00000000,	/* DENALI_PHY_710_DATA */
+			0x00000000,	/* DENALI_PHY_711_DATA */
+			0x00000000,	/* DENALI_PHY_712_DATA */
+			0x00000000,	/* DENALI_PHY_713_DATA */
+			0x00000000,	/* DENALI_PHY_714_DATA */
+			0x00000000,	/* DENALI_PHY_715_DATA */
+			0x00000000,	/* DENALI_PHY_716_DATA */
+			0x00000000,	/* DENALI_PHY_717_DATA */
+			0x00000000,	/* DENALI_PHY_718_DATA */
+			0x00000000,	/* DENALI_PHY_719_DATA */
+			0x00000000,	/* DENALI_PHY_720_DATA */
+			0x00000000,	/* DENALI_PHY_721_DATA */
+			0x00000000,	/* DENALI_PHY_722_DATA */
+			0x00000000,	/* DENALI_PHY_723_DATA */
+			0x00000000,	/* DENALI_PHY_724_DATA */
+			0x00000000,	/* DENALI_PHY_725_DATA */
+			0x00000000,	/* DENALI_PHY_726_DATA */
+			0x00000000,	/* DENALI_PHY_727_DATA */
+			0x00000000,	/* DENALI_PHY_728_DATA */
+			0x00000000,	/* DENALI_PHY_729_DATA */
+			0x00000000,	/* DENALI_PHY_730_DATA */
+			0x00000000,	/* DENALI_PHY_731_DATA */
+			0x00000000,	/* DENALI_PHY_732_DATA */
+			0x00000000,	/* DENALI_PHY_733_DATA */
+			0x00000000,	/* DENALI_PHY_734_DATA */
+			0x00000000,	/* DENALI_PHY_735_DATA */
+			0x00000000,	/* DENALI_PHY_736_DATA */
+			0x00000000,	/* DENALI_PHY_737_DATA */
+			0x00000000,	/* DENALI_PHY_738_DATA */
+			0x00000000,	/* DENALI_PHY_739_DATA */
+			0x00000000,	/* DENALI_PHY_740_DATA */
+			0x00000000,	/* DENALI_PHY_741_DATA */
+			0x00000000,	/* DENALI_PHY_742_DATA */
+			0x00000000,	/* DENALI_PHY_743_DATA */
+			0x00000000,	/* DENALI_PHY_744_DATA */
+			0x00000000,	/* DENALI_PHY_745_DATA */
+			0x00000000,	/* DENALI_PHY_746_DATA */
+			0x00000000,	/* DENALI_PHY_747_DATA */
+			0x00000000,	/* DENALI_PHY_748_DATA */
+			0x00000000,	/* DENALI_PHY_749_DATA */
+			0x00000000,	/* DENALI_PHY_750_DATA */
+			0x00000000,	/* DENALI_PHY_751_DATA */
+			0x00000000,	/* DENALI_PHY_752_DATA */
+			0x00000000,	/* DENALI_PHY_753_DATA */
+			0x00000000,	/* DENALI_PHY_754_DATA */
+			0x00000000,	/* DENALI_PHY_755_DATA */
+			0x00000000,	/* DENALI_PHY_756_DATA */
+			0x00000000,	/* DENALI_PHY_757_DATA */
+			0x00000000,	/* DENALI_PHY_758_DATA */
+			0x00000000,	/* DENALI_PHY_759_DATA */
+			0x00000000,	/* DENALI_PHY_760_DATA */
+			0x00000000,	/* DENALI_PHY_761_DATA */
+			0x00000000,	/* DENALI_PHY_762_DATA */
+			0x00000000,	/* DENALI_PHY_763_DATA */
+			0x00000000,	/* DENALI_PHY_764_DATA */
+			0x00000000,	/* DENALI_PHY_765_DATA */
+			0x00000000,	/* DENALI_PHY_766_DATA */
+			0x00000000,	/* DENALI_PHY_767_DATA */
+			0x00000000,	/* DENALI_PHY_768_DATA */
+			0x00000000,	/* DENALI_PHY_769_DATA */
+			0x00000000,	/* DENALI_PHY_770_DATA */
+			0x00000000,	/* DENALI_PHY_771_DATA */
+			0x00000000,	/* DENALI_PHY_772_DATA */
+			0x00000000,	/* DENALI_PHY_773_DATA */
+			0x00000000,	/* DENALI_PHY_774_DATA */
+			0x00000002,	/* DENALI_PHY_775_DATA */
+			0x00000000,	/* DENALI_PHY_776_DATA */
+			0x00000000,	/* DENALI_PHY_777_DATA */
+			0x00000000,	/* DENALI_PHY_778_DATA */
+			0x00400320,	/* DENALI_PHY_779_DATA */
+			0x00000040,	/* DENALI_PHY_780_DATA */
+			0x00000000,	/* DENALI_PHY_781_DATA */
+			0x00000000,	/* DENALI_PHY_782_DATA */
+			0x00000000,	/* DENALI_PHY_783_DATA */
+			0x01000000,	/* DENALI_PHY_784_DATA */
+			0x00020003,	/* DENALI_PHY_785_DATA */
+			0x00000000,	/* DENALI_PHY_786_DATA */
+			0x00000000,	/* DENALI_PHY_787_DATA */
+			0x00000000,	/* DENALI_PHY_788_DATA */
+			0x0000002a,	/* DENALI_PHY_789_DATA */
+			0x00000015,	/* DENALI_PHY_790_DATA */
+			0x00000015,	/* DENALI_PHY_791_DATA */
+			0x0000002a,	/* DENALI_PHY_792_DATA */
+			0x00000033,	/* DENALI_PHY_793_DATA */
+			0x0000000c,	/* DENALI_PHY_794_DATA */
+			0x0000000c,	/* DENALI_PHY_795_DATA */
+			0x00000033,	/* DENALI_PHY_796_DATA */
+			0x1ee6b16a,	/* DENALI_PHY_797_DATA */
+			0x10000000,	/* DENALI_PHY_798_DATA */
+			0x00000000,	/* DENALI_PHY_799_DATA */
+			0x00030055,	/* DENALI_PHY_800_DATA */
+			0x03000300,	/* DENALI_PHY_801_DATA */
+			0x03000300,	/* DENALI_PHY_802_DATA */
+			0x00000300,	/* DENALI_PHY_803_DATA */
+			0x42080010,	/* DENALI_PHY_804_DATA */
+			0x00000003,	/* DENALI_PHY_805_DATA */
+			0x00000000,	/* DENALI_PHY_806_DATA */
+			0x00000000,	/* DENALI_PHY_807_DATA */
+			0x00000000,	/* DENALI_PHY_808_DATA */
+			0x00000000,	/* DENALI_PHY_809_DATA */
+			0x00000000,	/* DENALI_PHY_810_DATA */
+			0x00000000,	/* DENALI_PHY_811_DATA */
+			0x00000000,	/* DENALI_PHY_812_DATA */
+			0x00000000,	/* DENALI_PHY_813_DATA */
+			0x00000000,	/* DENALI_PHY_814_DATA */
+			0x00000000,	/* DENALI_PHY_815_DATA */
+			0x00000000,	/* DENALI_PHY_816_DATA */
+			0x00000000,	/* DENALI_PHY_817_DATA */
+			0x00000000,	/* DENALI_PHY_818_DATA */
+			0x00000000,	/* DENALI_PHY_819_DATA */
+			0x00000000,	/* DENALI_PHY_820_DATA */
+			0x00000000,	/* DENALI_PHY_821_DATA */
+			0x00000000,	/* DENALI_PHY_822_DATA */
+			0x00000000,	/* DENALI_PHY_823_DATA */
+			0x00000000,	/* DENALI_PHY_824_DATA */
+			0x00000000,	/* DENALI_PHY_825_DATA */
+			0x00000000,	/* DENALI_PHY_826_DATA */
+			0x00000000,	/* DENALI_PHY_827_DATA */
+			0x00000000,	/* DENALI_PHY_828_DATA */
+			0x00000000,	/* DENALI_PHY_829_DATA */
+			0x00000000,	/* DENALI_PHY_830_DATA */
+			0x00000000,	/* DENALI_PHY_831_DATA */
+			0x00000000,	/* DENALI_PHY_832_DATA */
+			0x00000000,	/* DENALI_PHY_833_DATA */
+			0x00000000,	/* DENALI_PHY_834_DATA */
+			0x00000000,	/* DENALI_PHY_835_DATA */
+			0x00000000,	/* DENALI_PHY_836_DATA */
+			0x00000000,	/* DENALI_PHY_837_DATA */
+			0x00000000,	/* DENALI_PHY_838_DATA */
+			0x00000000,	/* DENALI_PHY_839_DATA */
+			0x00000000,	/* DENALI_PHY_840_DATA */
+			0x00000000,	/* DENALI_PHY_841_DATA */
+			0x00000000,	/* DENALI_PHY_842_DATA */
+			0x00000000,	/* DENALI_PHY_843_DATA */
+			0x00000000,	/* DENALI_PHY_844_DATA */
+			0x00000000,	/* DENALI_PHY_845_DATA */
+			0x00000000,	/* DENALI_PHY_846_DATA */
+			0x00000000,	/* DENALI_PHY_847_DATA */
+			0x00000000,	/* DENALI_PHY_848_DATA */
+			0x00000000,	/* DENALI_PHY_849_DATA */
+			0x00000000,	/* DENALI_PHY_850_DATA */
+			0x00000000,	/* DENALI_PHY_851_DATA */
+			0x00000000,	/* DENALI_PHY_852_DATA */
+			0x00000000,	/* DENALI_PHY_853_DATA */
+			0x00000000,	/* DENALI_PHY_854_DATA */
+			0x00000000,	/* DENALI_PHY_855_DATA */
+			0x00000000,	/* DENALI_PHY_856_DATA */
+			0x00000000,	/* DENALI_PHY_857_DATA */
+			0x00000000,	/* DENALI_PHY_858_DATA */
+			0x00000000,	/* DENALI_PHY_859_DATA */
+			0x00000000,	/* DENALI_PHY_860_DATA */
+			0x00000000,	/* DENALI_PHY_861_DATA */
+			0x00000000,	/* DENALI_PHY_862_DATA */
+			0x00000000,	/* DENALI_PHY_863_DATA */
+			0x00000000,	/* DENALI_PHY_864_DATA */
+			0x00000000,	/* DENALI_PHY_865_DATA */
+			0x00000000,	/* DENALI_PHY_866_DATA */
+			0x00000000,	/* DENALI_PHY_867_DATA */
+			0x00000000,	/* DENALI_PHY_868_DATA */
+			0x00000000,	/* DENALI_PHY_869_DATA */
+			0x00000000,	/* DENALI_PHY_870_DATA */
+			0x00000000,	/* DENALI_PHY_871_DATA */
+			0x00000000,	/* DENALI_PHY_872_DATA */
+			0x00000000,	/* DENALI_PHY_873_DATA */
+			0x00000000,	/* DENALI_PHY_874_DATA */
+			0x00000000,	/* DENALI_PHY_875_DATA */
+			0x00000000,	/* DENALI_PHY_876_DATA */
+			0x00000000,	/* DENALI_PHY_877_DATA */
+			0x00000000,	/* DENALI_PHY_878_DATA */
+			0x00000000,	/* DENALI_PHY_879_DATA */
+			0x00000000,	/* DENALI_PHY_880_DATA */
+			0x00000000,	/* DENALI_PHY_881_DATA */
+			0x00000000,	/* DENALI_PHY_882_DATA */
+			0x00000000,	/* DENALI_PHY_883_DATA */
+			0x00000000,	/* DENALI_PHY_884_DATA */
+			0x00000000,	/* DENALI_PHY_885_DATA */
+			0x00000000,	/* DENALI_PHY_886_DATA */
+			0x00000000,	/* DENALI_PHY_887_DATA */
+			0x00000000,	/* DENALI_PHY_888_DATA */
+			0x00000000,	/* DENALI_PHY_889_DATA */
+			0x00000000,	/* DENALI_PHY_890_DATA */
+			0x00000000,	/* DENALI_PHY_891_DATA */
+			0x00000000,	/* DENALI_PHY_892_DATA */
+			0x00000000,	/* DENALI_PHY_893_DATA */
+			0x00000000,	/* DENALI_PHY_894_DATA */
+			0x00000000,	/* DENALI_PHY_895_DATA */
+			0x00000000,	/* DENALI_PHY_896_DATA */
+			0x00000000,	/* DENALI_PHY_897_DATA */
+			0x00000005,	/* DENALI_PHY_898_DATA */
+			0x04000f01,	/* DENALI_PHY_899_DATA */
+			0x00020040,	/* DENALI_PHY_900_DATA */
+			0x00020055,	/* DENALI_PHY_901_DATA */
+			0x00000000,	/* DENALI_PHY_902_DATA */
+			0x00000000,	/* DENALI_PHY_903_DATA */
+			0x00000000,	/* DENALI_PHY_904_DATA */
+			0x00000050,	/* DENALI_PHY_905_DATA */
+			0x00000000,	/* DENALI_PHY_906_DATA */
+			0x01010100,	/* DENALI_PHY_907_DATA */
+			0x00000600,	/* DENALI_PHY_908_DATA */
+			0x00000000,	/* DENALI_PHY_909_DATA */
+			0x00006400,	/* DENALI_PHY_910_DATA */
+			0x01221102,	/* DENALI_PHY_911_DATA */
+			0x00000000,	/* DENALI_PHY_912_DATA */
+			0x000d1f00,	/* DENALI_PHY_913_DATA */
+			0x0d1f0d1f,	/* DENALI_PHY_914_DATA */
+			0x0d1f0d1f,	/* DENALI_PHY_915_DATA */
+			0x00030003,	/* DENALI_PHY_916_DATA */
+			0x03000300,	/* DENALI_PHY_917_DATA */
+			0x00000300,	/* DENALI_PHY_918_DATA */
+			0x01221102,	/* DENALI_PHY_919_DATA */
+			0x00000000,	/* DENALI_PHY_920_DATA */
+			0x00000000,	/* DENALI_PHY_921_DATA */
+			0x03020000,	/* DENALI_PHY_922_DATA */
+			0x00000001,	/* DENALI_PHY_923_DATA */
+			0x00000411,	/* DENALI_PHY_924_DATA */
+			0x00000411,	/* DENALI_PHY_925_DATA */
+			0x00000040,	/* DENALI_PHY_926_DATA */
+			0x00000040,	/* DENALI_PHY_927_DATA */
+			0x00000411,	/* DENALI_PHY_928_DATA */
+			0x00000411,	/* DENALI_PHY_929_DATA */
+			0x00004410,	/* DENALI_PHY_930_DATA */
+			0x00004410,	/* DENALI_PHY_931_DATA */
+			0x00004410,	/* DENALI_PHY_932_DATA */
+			0x00004410,	/* DENALI_PHY_933_DATA */
+			0x00004410,	/* DENALI_PHY_934_DATA */
+			0x00000411,	/* DENALI_PHY_935_DATA */
+			0x00004410,	/* DENALI_PHY_936_DATA */
+			0x00000411,	/* DENALI_PHY_937_DATA */
+			0x00004410,	/* DENALI_PHY_938_DATA */
+			0x00000411,	/* DENALI_PHY_939_DATA */
+			0x00004410,	/* DENALI_PHY_940_DATA */
+			0x00000000,	/* DENALI_PHY_941_DATA */
+			0x00000000,	/* DENALI_PHY_942_DATA */
+			0x00000000,	/* DENALI_PHY_943_DATA */
+			0x64000000,	/* DENALI_PHY_944_DATA */
+			0x00000000,	/* DENALI_PHY_945_DATA */
+			0x00000000,	/* DENALI_PHY_946_DATA */
+			0x00000508,	/* DENALI_PHY_947_DATA */
+			0x00000000,	/* DENALI_PHY_948_DATA */
+			0x00000000,	/* DENALI_PHY_949_DATA */
+			0x00000000,	/* DENALI_PHY_950_DATA */
+			0x00000000,	/* DENALI_PHY_951_DATA */
+			0x00000000,	/* DENALI_PHY_952_DATA */
+			0x00000000,	/* DENALI_PHY_953_DATA */
+			0xe4000000,	/* DENALI_PHY_954_DATA */
+			0x00000000,	/* DENALI_PHY_955_DATA */
+			0x00000000,	/* DENALI_PHY_956_DATA */
+			0x01010000,	/* DENALI_PHY_957_DATA */
+			0x00000000	/* DENALI_PHY_958_DATA */
+		}
+	},
+},
diff --git a/drivers/ram/rockchip/sdram_debug.c b/drivers/ram/rockchip/sdram_debug.c
new file mode 100644
index 0000000..9cf6626
--- /dev/null
+++ b/drivers/ram/rockchip/sdram_debug.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ * (C) Copyright 2019 Amarula Solutions.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <asm/arch-rockchip/sdram_common.h>
+
+void sdram_print_dram_type(unsigned char dramtype)
+{
+	switch (dramtype) {
+	case DDR3:
+		printascii("DDR3");
+		break;
+	case DDR4:
+		printascii("DDR4");
+		break;
+	case LPDDR2:
+		printascii("LPDDR2");
+		break;
+	case LPDDR3:
+		printascii("LPDDR3");
+		break;
+	case LPDDR4:
+		printascii("LPDDR4");
+		break;
+	default:
+		printascii("Unknown Device");
+		break;
+	}
+}
+
+/**
+ * cs  = 0, cs0
+ * cs  = 1, cs1
+ * cs => 2, cs0+cs1
+ * note: it didn't consider about row_3_4
+ */
+u64 sdram_get_cs_cap(struct sdram_cap_info *cap_info, u32 cs, u32 dram_type)
+{
+	u32 bg;
+	u64 cap[2];
+
+	if (dram_type == DDR4)
+		/* DDR4 8bit dram BG = 2(4bank groups),
+		 * 16bit dram BG = 1 (2 bank groups)
+		 */
+		bg = (cap_info->dbw == 0) ? 2 : 1;
+	else
+		bg = 0;
+
+	cap[0] = 1llu << (cap_info->bw + cap_info->col +
+		 bg + cap_info->bk + cap_info->cs0_row);
+
+	if (cap_info->rank == 2)
+		cap[1] = 1llu << (cap_info->bw + cap_info->col +
+			 bg + cap_info->bk + cap_info->cs1_row);
+	else
+		cap[1] = 0;
+
+	if (cs == 0)
+		return cap[0];
+	else if (cs == 1)
+		return cap[1];
+	else
+		return (cap[0] + cap[1]);
+}
+
+void sdram_print_ddr_info(struct sdram_cap_info *cap_info,
+			  struct sdram_base_params *base)
+{
+	u32 bg, cap;
+
+	bg = (cap_info->dbw == 0) ? 2 : 1;
+
+	sdram_print_dram_type(base->dramtype);
+
+	printascii(", ");
+	printdec(base->ddr_freq);
+	printascii("MHz\n");
+
+	printascii("BW=");
+	printdec(8 << cap_info->bw);
+
+	printascii(" Col=");
+	printdec(cap_info->col);
+
+	printascii(" Bk=");
+	printdec(0x1 << cap_info->bk);
+	if (base->dramtype == DDR4) {
+		printascii(" BG=");
+		printdec(1 << bg);
+	}
+
+	printascii(" CS0 Row=");
+	printdec(cap_info->cs0_row);
+	if (cap_info->rank > 1) {
+		printascii(" CS1 Row=");
+		printdec(cap_info->cs1_row);
+	}
+
+	printascii(" CS=");
+	printdec(cap_info->rank);
+
+	printascii(" Die BW=");
+	printdec(8 << cap_info->dbw);
+
+	cap = sdram_get_cs_cap(cap_info, 3, base->dramtype);
+	if (cap_info->row_3_4)
+		cap = cap * 3 / 4;
+
+	printascii(" Size=");
+	printdec(cap >> 20);
+	printascii("MB\n");
+}
+
+void sdram_print_stride(unsigned int stride)
+{
+	switch (stride) {
+	case 0xc:
+		printf("128B stride\n");
+		break;
+	case 5:
+	case 9:
+	case 0xd:
+	case 0x11:
+	case 0x19:
+		printf("256B stride\n");
+		break;
+	case 0xa:
+	case 0xe:
+	case 0x12:
+		printf("512B stride\n");
+		break;
+	case 0xf:
+		printf("4K stride\n");
+		break;
+	case 0x1f:
+		printf("32MB + 256B stride\n");
+		break;
+	default:
+		printf("no stride\n");
+	}
+}
diff --git a/drivers/ram/rockchip/sdram_rk322x.c b/drivers/ram/rockchip/sdram_rk322x.c
index e96ac54..94893e1 100644
--- a/drivers/ram/rockchip/sdram_rk322x.c
+++ b/drivers/ram/rockchip/sdram_rk322x.c
@@ -16,7 +16,6 @@
 #include <asm/arch-rockchip/grf_rk322x.h>
 #include <asm/arch-rockchip/hardware.h>
 #include <asm/arch-rockchip/sdram_rk322x.h>
-#include <asm/arch-rockchip/timer.h>
 #include <asm/arch-rockchip/uart.h>
 #include <asm/arch-rockchip/sdram_common.h>
 #include <asm/types.h>
@@ -96,26 +95,26 @@
 			1 << DDRCTRL_PSRST_SHIFT | 1 << DDRCTRL_SRST_SHIFT |
 			1 << DDRPHY_PSRST_SHIFT | 1 << DDRPHY_SRST_SHIFT);
 
-	rockchip_udelay(10);
+	udelay(10);
 
 	rk_clrreg(&cru->cru_softrst_con[5], 1 << DDRPHY_PSRST_SHIFT |
 						  1 << DDRPHY_SRST_SHIFT);
-	rockchip_udelay(10);
+	udelay(10);
 
 	rk_clrreg(&cru->cru_softrst_con[5], 1 << DDRCTRL_PSRST_SHIFT |
 						  1 << DDRCTRL_SRST_SHIFT);
-	rockchip_udelay(10);
+	udelay(10);
 
 	clrbits_le32(&ddr_phy->ddrphy_reg[0],
 		     SOFT_RESET_MASK << SOFT_RESET_SHIFT);
-	rockchip_udelay(10);
+	udelay(10);
 	setbits_le32(&ddr_phy->ddrphy_reg[0],
 		     SOFT_DERESET_ANALOG);
-	rockchip_udelay(5);
+	udelay(5);
 	setbits_le32(&ddr_phy->ddrphy_reg[0],
 		     SOFT_DERESET_DIGITAL);
 
-	rockchip_udelay(1);
+	udelay(1);
 }
 
 void phy_dll_bypass_set(struct rk322x_ddr_phy *ddr_phy, u32 freq)
@@ -154,7 +153,7 @@
 			 u32 rank, u32 cmd, u32 arg)
 {
 	writel((START_CMD | (rank << 20) | arg | cmd), &pctl->mcmd);
-	rockchip_udelay(1);
+	udelay(1);
 	while (readl(&pctl->mcmd) & START_CMD)
 		;
 }
@@ -167,7 +166,7 @@
 
 	if (dramtype == DDR3) {
 		send_command(pctl, 3, DESELECT_CMD, 0);
-		rockchip_udelay(1);
+		udelay(1);
 		send_command(pctl, 3, PREA_CMD, 0);
 		send_command(pctl, 3, MRS_CMD,
 			     (0x02 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT |
@@ -196,17 +195,17 @@
 			     (0x63 & LPDDR23_MA_MASK) << LPDDR23_MA_SHIFT |
 			     (0 & LPDDR23_OP_MASK) <<
 			     LPDDR23_OP_SHIFT);
-		rockchip_udelay(10);
+		udelay(10);
 		send_command(pctl, 3, MRS_CMD,
 			     (0x10 & LPDDR23_MA_MASK) << LPDDR23_MA_SHIFT |
 			     (0xff & LPDDR23_OP_MASK) <<
 			     LPDDR23_OP_SHIFT);
-		rockchip_udelay(1);
+		udelay(1);
 		send_command(pctl, 3, MRS_CMD,
 			     (0x10 & LPDDR23_MA_MASK) << LPDDR23_MA_SHIFT |
 			     (0xff & LPDDR23_OP_MASK) <<
 			     LPDDR23_OP_SHIFT);
-		rockchip_udelay(1);
+		udelay(1);
 		send_command(pctl, 3, MRS_CMD,
 			     (1 & LPDDR23_MA_MASK) << LPDDR23_MA_SHIFT |
 			     (sdram_params->phy_timing.mr[1] &
@@ -243,7 +242,7 @@
 			DQS_SQU_CAL_SEL_CS0);
 	setbits_le32(&ddr_phy->ddrphy_reg[2], DQS_SQU_CAL_START);
 
-	rockchip_udelay(30);
+	udelay(30);
 	ret = readl(&ddr_phy->ddrphy_reg[0xff]);
 
 	clrbits_le32(&ddr_phy->ddrphy_reg[2],
@@ -367,9 +366,9 @@
 
 	writel(GRF_DDRPHY_BUFFEREN_CORE_EN, &grf->soc_con[0]);
 	clrbits_le32(&ddr_phy->ddrphy_reg[0], 0x3 << 2);
-	rockchip_udelay(1);
+	udelay(1);
 	setbits_le32(&ddr_phy->ddrphy_reg[0], 1 << 2);
-	rockchip_udelay(5);
+	udelay(5);
 	setbits_le32(&ddr_phy->ddrphy_reg[0], 1 << 3);
 	writel(GRF_DDRPHY_BUFFEREN_CORE_DIS, &grf->soc_con[0]);
 }
diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c
index 5251865..81fc71c 100644
--- a/drivers/ram/rockchip/sdram_rk3399.c
+++ b/drivers/ram/rockchip/sdram_rk3399.c
@@ -14,14 +14,40 @@
 #include <syscon.h>
 #include <asm/io.h>
 #include <asm/arch-rockchip/clock.h>
-#include <asm/arch-rockchip/sdram_common.h>
-#include <asm/arch-rockchip/sdram_rk3399.h>
 #include <asm/arch-rockchip/cru_rk3399.h>
 #include <asm/arch-rockchip/grf_rk3399.h>
+#include <asm/arch-rockchip/pmu_rk3399.h>
 #include <asm/arch-rockchip/hardware.h>
+#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_rk3399.h>
 #include <linux/err.h>
 #include <time.h>
 
+#define PRESET_SGRF_HOLD(n)	((0x1 << (6 + 16)) | ((n) << 6))
+#define PRESET_GPIO0_HOLD(n)	((0x1 << (7 + 16)) | ((n) << 7))
+#define PRESET_GPIO1_HOLD(n)	((0x1 << (8 + 16)) | ((n) << 8))
+
+#define PHY_DRV_ODT_HI_Z	0x0
+#define PHY_DRV_ODT_240		0x1
+#define PHY_DRV_ODT_120		0x8
+#define PHY_DRV_ODT_80		0x9
+#define PHY_DRV_ODT_60		0xc
+#define PHY_DRV_ODT_48		0xd
+#define PHY_DRV_ODT_40		0xe
+#define PHY_DRV_ODT_34_3	0xf
+
+#define PHY_BOOSTP_EN		0x1
+#define PHY_BOOSTN_EN		0x1
+#define PHY_SLEWP_EN		0x1
+#define PHY_SLEWN_EN		0x1
+#define PHY_RX_CM_INPUT		0x1
+#define CS0_MR22_VAL		0
+#define CS1_MR22_VAL		3
+
+#define CRU_SFTRST_DDR_CTRL(ch, n)	((0x1 << (8 + 16 + (ch) * 4)) | \
+					((n) << (8 + (ch) * 4)))
+#define CRU_SFTRST_DDR_PHY(ch, n)	((0x1 << (9 + 16 + (ch) * 4)) | \
+					((n) << (9 + (ch) * 4)))
 struct chan_info {
 	struct rk3399_ddr_pctl_regs *pctl;
 	struct rk3399_ddr_pi_regs *pi;
@@ -32,29 +58,27 @@
 struct dram_info {
 #if defined(CONFIG_TPL_BUILD) || \
 	(!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD))
+	u32 pwrup_srefresh_exit[2];
 	struct chan_info chan[2];
 	struct clk ddr_clk;
 	struct rk3399_cru *cru;
+	struct rk3399_grf_regs *grf;
+	struct rk3399_pmu_regs *pmu;
 	struct rk3399_pmucru *pmucru;
 	struct rk3399_pmusgrf_regs *pmusgrf;
 	struct rk3399_ddr_cic_regs *cic;
+	const struct sdram_rk3399_ops *ops;
 #endif
 	struct ram_info info;
 	struct rk3399_pmugrf_regs *pmugrf;
 };
 
-#define PRESET_SGRF_HOLD(n)	((0x1 << (6 + 16)) | ((n) << 6))
-#define PRESET_GPIO0_HOLD(n)	((0x1 << (7 + 16)) | ((n) << 7))
-#define PRESET_GPIO1_HOLD(n)	((0x1 << (8 + 16)) | ((n) << 8))
-
-#define PHY_DRV_ODT_Hi_Z	0x0
-#define PHY_DRV_ODT_240		0x1
-#define PHY_DRV_ODT_120		0x8
-#define PHY_DRV_ODT_80		0x9
-#define PHY_DRV_ODT_60		0xc
-#define PHY_DRV_ODT_48		0xd
-#define PHY_DRV_ODT_40		0xe
-#define PHY_DRV_ODT_34_3	0xf
+struct sdram_rk3399_ops {
+	int (*data_training)(struct dram_info *dram, u32 channel, u8 rank,
+			     struct rk3399_sdram_params *sdram);
+	int (*set_rate)(struct dram_info *dram,
+			struct rk3399_sdram_params *params);
+};
 
 #if defined(CONFIG_TPL_BUILD) || \
 	(!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD))
@@ -68,6 +92,154 @@
 	struct regmap *map;
 };
 
+struct io_setting {
+	u32 mhz;
+	u32 mr5;
+	/* dram side */
+	u32 dq_odt;
+	u32 ca_odt;
+	u32 pdds;
+	u32 dq_vref;
+	u32 ca_vref;
+	/* phy side */
+	u32 rd_odt;
+	u32 wr_dq_drv;
+	u32 wr_ca_drv;
+	u32 wr_ckcs_drv;
+	u32 rd_odt_en;
+	u32 rd_vref;
+} lpddr4_io_setting[] = {
+	{
+		50 * MHz,
+		0,
+		/* dram side */
+		0,	/* dq_odt; */
+		0,	/* ca_odt; */
+		6,	/* pdds; */
+		0x72,	/* dq_vref; */
+		0x72,	/* ca_vref; */
+		/* phy side */
+		PHY_DRV_ODT_HI_Z,	/* rd_odt; */
+		PHY_DRV_ODT_40,	/* wr_dq_drv; */
+		PHY_DRV_ODT_40,	/* wr_ca_drv; */
+		PHY_DRV_ODT_40,	/* wr_ckcs_drv; */
+		0,	/* rd_odt_en;*/
+		41,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
+	},
+	{
+		600 * MHz,
+		0,
+		/* dram side */
+		1,	/* dq_odt; */
+		0,	/* ca_odt; */
+		6,	/* pdds; */
+		0x72,	/* dq_vref; */
+		0x72,	/* ca_vref; */
+		/* phy side */
+		PHY_DRV_ODT_HI_Z,	/* rd_odt; */
+		PHY_DRV_ODT_48,	/* wr_dq_drv; */
+		PHY_DRV_ODT_40,	/* wr_ca_drv; */
+		PHY_DRV_ODT_40,	/* wr_ckcs_drv; */
+		0,	/* rd_odt_en; */
+		32,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
+	},
+	{
+		800 * MHz,
+		0,
+		/* dram side */
+		1,	/* dq_odt; */
+		0,	/* ca_odt; */
+		1,	/* pdds; */
+		0x72,	/* dq_vref; */
+		0x72,	/* ca_vref; */
+		/* phy side */
+		PHY_DRV_ODT_40,	/* rd_odt; */
+		PHY_DRV_ODT_48,	/* wr_dq_drv; */
+		PHY_DRV_ODT_40,	/* wr_ca_drv; */
+		PHY_DRV_ODT_40,	/* wr_ckcs_drv; */
+		1,	/* rd_odt_en; */
+		17,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
+	},
+	{
+		933 * MHz,
+		0,
+		/* dram side */
+		3,	/* dq_odt; */
+		0,	/* ca_odt; */
+		6,	/* pdds; */
+		0x59,	/* dq_vref; 32% */
+		0x72,	/* ca_vref; */
+		/* phy side */
+		PHY_DRV_ODT_HI_Z,	/* rd_odt; */
+		PHY_DRV_ODT_48,	/* wr_dq_drv; */
+		PHY_DRV_ODT_40,	/* wr_ca_drv; */
+		PHY_DRV_ODT_40,	/* wr_ckcs_drv; */
+		0,	/* rd_odt_en; */
+		32,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
+	},
+	{
+		1066 * MHz,
+		0,
+		/* dram side */
+		6,	/* dq_odt; */
+		0,	/* ca_odt; */
+		1,	/* pdds; */
+		0x10,	/* dq_vref; */
+		0x72,	/* ca_vref; */
+		/* phy side */
+		PHY_DRV_ODT_40,	/* rd_odt; */
+		PHY_DRV_ODT_60,	/* wr_dq_drv; */
+		PHY_DRV_ODT_40,	/* wr_ca_drv; */
+		PHY_DRV_ODT_40,	/* wr_ckcs_drv; */
+		1,	/* rd_odt_en; */
+		17,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
+	},
+};
+
+/**
+ * phy = 0, PHY boot freq
+ * phy = 1, PHY index 0
+ * phy = 2, PHY index 1
+ */
+static struct io_setting *
+lpddr4_get_io_settings(const struct rk3399_sdram_params *params, u32 mr5)
+{
+	struct io_setting *io = NULL;
+	u32 n;
+
+	for (n = 0; n < ARRAY_SIZE(lpddr4_io_setting); n++) {
+		io = &lpddr4_io_setting[n];
+
+		if (io->mr5 != 0) {
+			if (io->mhz >= params->base.ddr_freq &&
+			    io->mr5 == mr5)
+				break;
+		} else {
+			if (io->mhz >= params->base.ddr_freq)
+				break;
+		}
+	}
+
+	return io;
+}
+
+static void *get_denali_phy(const struct chan_info *chan,
+			    struct rk3399_sdram_params *params, bool reg)
+{
+	return reg ? &chan->publ->denali_phy : &params->phy_regs.denali_phy;
+}
+
+static void *get_denali_ctl(const struct chan_info *chan,
+			    struct rk3399_sdram_params *params, bool reg)
+{
+	return reg ? &chan->pctl->denali_ctl : &params->pctl_regs.denali_ctl;
+}
+
+static void *get_ddrc0_con(struct dram_info *dram, u8 channel)
+{
+	return (channel == 0) ? &dram->grf->ddrc0_con0 : &dram->grf->ddrc0_con1;
+}
+
 static void copy_to_reg(u32 *dest, const u32 *src, u32 n)
 {
 	int i;
@@ -79,6 +251,29 @@
 	}
 }
 
+static void rkclk_ddr_reset(struct rk3399_cru *cru, u32 channel, u32 ctl,
+			    u32 phy)
+{
+	channel &= 0x1;
+	ctl &= 0x1;
+	phy &= 0x1;
+	writel(CRU_SFTRST_DDR_CTRL(channel, ctl) |
+				   CRU_SFTRST_DDR_PHY(channel, phy),
+				   &cru->softrst_con[4]);
+}
+
+static void phy_pctrl_reset(struct rk3399_cru *cru,  u32 channel)
+{
+	rkclk_ddr_reset(cru, channel, 1, 1);
+	udelay(10);
+
+	rkclk_ddr_reset(cru, channel, 1, 0);
+	udelay(10);
+
+	rkclk_ddr_reset(cru, channel, 0, 0);
+	udelay(10);
+}
+
 static void phy_dll_bypass_set(struct rk3399_ddr_publ_regs *ddr_publ_regs,
 			       u32 freq)
 {
@@ -111,10 +306,9 @@
 }
 
 static void set_memory_map(const struct chan_info *chan, u32 channel,
-			   const struct rk3399_sdram_params *sdram_params)
+			   const struct rk3399_sdram_params *params)
 {
-	const struct rk3399_sdram_channel *sdram_ch =
-		&sdram_params->ch[channel];
+	const struct rk3399_sdram_channel *sdram_ch = &params->ch[channel];
 	u32 *denali_ctl = chan->pctl->denali_ctl;
 	u32 *denali_pi = chan->pi->denali_pi;
 	u32 cs_map;
@@ -122,179 +316,51 @@
 	u32 row;
 
 	/* Get row number from ddrconfig setting */
-	if (sdram_ch->ddrconfig < 2 || sdram_ch->ddrconfig == 4)
+	if (sdram_ch->cap_info.ddrconfig < 2 ||
+	    sdram_ch->cap_info.ddrconfig == 4)
 		row = 16;
-	else if (sdram_ch->ddrconfig == 3)
+	else if (sdram_ch->cap_info.ddrconfig == 3)
 		row = 14;
 	else
 		row = 15;
 
-	cs_map = (sdram_ch->rank > 1) ? 3 : 1;
-	reduc = (sdram_ch->bw == 2) ? 0 : 1;
+	cs_map = (sdram_ch->cap_info.rank > 1) ? 3 : 1;
+	reduc = (sdram_ch->cap_info.bw == 2) ? 0 : 1;
 
 	/* Set the dram configuration to ctrl */
-	clrsetbits_le32(&denali_ctl[191], 0xF, (12 - sdram_ch->col));
+	clrsetbits_le32(&denali_ctl[191], 0xF, (12 - sdram_ch->cap_info.col));
 	clrsetbits_le32(&denali_ctl[190], (0x3 << 16) | (0x7 << 24),
-			((3 - sdram_ch->bk) << 16) |
+			((3 - sdram_ch->cap_info.bk) << 16) |
 			((16 - row) << 24));
 
 	clrsetbits_le32(&denali_ctl[196], 0x3 | (1 << 16),
 			cs_map | (reduc << 16));
 
 	/* PI_199 PI_COL_DIFF:RW:0:4 */
-	clrsetbits_le32(&denali_pi[199], 0xF, (12 - sdram_ch->col));
+	clrsetbits_le32(&denali_pi[199], 0xF, (12 - sdram_ch->cap_info.col));
 
 	/* PI_155 PI_ROW_DIFF:RW:24:3 PI_BANK_DIFF:RW:16:2 */
 	clrsetbits_le32(&denali_pi[155], (0x3 << 16) | (0x7 << 24),
-			((3 - sdram_ch->bk) << 16) |
+			((3 - sdram_ch->cap_info.bk) << 16) |
 			((16 - row) << 24));
-	/* PI_41 PI_CS_MAP:RW:24:4 */
-	clrsetbits_le32(&denali_pi[41], 0xf << 24, cs_map << 24);
-	if ((sdram_ch->rank == 1) && (sdram_params->base.dramtype == DDR3))
-		writel(0x2EC7FFFF, &denali_pi[34]);
-}
-
-static void set_ds_odt(const struct chan_info *chan,
-		       const struct rk3399_sdram_params *sdram_params)
-{
-	u32 *denali_phy = chan->publ->denali_phy;
-
-	u32 tsel_idle_en, tsel_wr_en, tsel_rd_en;
-	u32 tsel_idle_select_p, tsel_wr_select_p, tsel_rd_select_p;
-	u32 ca_tsel_wr_select_p, ca_tsel_wr_select_n;
-	u32 tsel_idle_select_n, tsel_wr_select_n, tsel_rd_select_n;
-	u32 reg_value;
-
-	if (sdram_params->base.dramtype == LPDDR4) {
-		tsel_rd_select_p = PHY_DRV_ODT_Hi_Z;
-		tsel_wr_select_p = PHY_DRV_ODT_40;
-		ca_tsel_wr_select_p = PHY_DRV_ODT_40;
-		tsel_idle_select_p = PHY_DRV_ODT_Hi_Z;
-
-		tsel_rd_select_n = PHY_DRV_ODT_240;
-		tsel_wr_select_n = PHY_DRV_ODT_40;
-		ca_tsel_wr_select_n = PHY_DRV_ODT_40;
-		tsel_idle_select_n = PHY_DRV_ODT_240;
-	} else if (sdram_params->base.dramtype == LPDDR3) {
-		tsel_rd_select_p = PHY_DRV_ODT_240;
-		tsel_wr_select_p = PHY_DRV_ODT_34_3;
-		ca_tsel_wr_select_p = PHY_DRV_ODT_48;
-		tsel_idle_select_p = PHY_DRV_ODT_240;
-
-		tsel_rd_select_n = PHY_DRV_ODT_Hi_Z;
-		tsel_wr_select_n = PHY_DRV_ODT_34_3;
-		ca_tsel_wr_select_n = PHY_DRV_ODT_48;
-		tsel_idle_select_n = PHY_DRV_ODT_Hi_Z;
-	} else {
-		tsel_rd_select_p = PHY_DRV_ODT_240;
-		tsel_wr_select_p = PHY_DRV_ODT_34_3;
-		ca_tsel_wr_select_p = PHY_DRV_ODT_34_3;
-		tsel_idle_select_p = PHY_DRV_ODT_240;
 
-		tsel_rd_select_n = PHY_DRV_ODT_240;
-		tsel_wr_select_n = PHY_DRV_ODT_34_3;
-		ca_tsel_wr_select_n = PHY_DRV_ODT_34_3;
-		tsel_idle_select_n = PHY_DRV_ODT_240;
+	if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) {
+		if (cs_map == 1)
+			cs_map = 0x5;
+		else if (cs_map == 2)
+			cs_map = 0xa;
+		else
+			cs_map = 0xF;
 	}
 
-	if (sdram_params->base.odt == 1)
-		tsel_rd_en = 1;
-	else
-		tsel_rd_en = 0;
-
-	tsel_wr_en = 0;
-	tsel_idle_en = 0;
-
-	/*
-	 * phy_dq_tsel_select_X 24bits DENALI_PHY_6/134/262/390 offset_0
-	 * sets termination values for read/idle cycles and drive strength
-	 * for write cycles for DQ/DM
-	 */
-	reg_value = tsel_rd_select_n | (tsel_rd_select_p << 0x4) |
-		    (tsel_wr_select_n << 8) | (tsel_wr_select_p << 12) |
-		    (tsel_idle_select_n << 16) | (tsel_idle_select_p << 20);
-	clrsetbits_le32(&denali_phy[6], 0xffffff, reg_value);
-	clrsetbits_le32(&denali_phy[134], 0xffffff, reg_value);
-	clrsetbits_le32(&denali_phy[262], 0xffffff, reg_value);
-	clrsetbits_le32(&denali_phy[390], 0xffffff, reg_value);
-
-	/*
-	 * phy_dqs_tsel_select_X 24bits DENALI_PHY_7/135/263/391 offset_0
-	 * sets termination values for read/idle cycles and drive strength
-	 * for write cycles for DQS
-	 */
-	clrsetbits_le32(&denali_phy[7], 0xffffff, reg_value);
-	clrsetbits_le32(&denali_phy[135], 0xffffff, reg_value);
-	clrsetbits_le32(&denali_phy[263], 0xffffff, reg_value);
-	clrsetbits_le32(&denali_phy[391], 0xffffff, reg_value);
-
-	/* phy_adr_tsel_select_ 8bits DENALI_PHY_544/672/800 offset_0 */
-	reg_value = ca_tsel_wr_select_n | (ca_tsel_wr_select_p << 0x4);
-	clrsetbits_le32(&denali_phy[544], 0xff, reg_value);
-	clrsetbits_le32(&denali_phy[672], 0xff, reg_value);
-	clrsetbits_le32(&denali_phy[800], 0xff, reg_value);
-
-	/* phy_pad_addr_drive 8bits DENALI_PHY_928 offset_0 */
-	clrsetbits_le32(&denali_phy[928], 0xff, reg_value);
-
-	/* phy_pad_rst_drive 8bits DENALI_PHY_937 offset_0 */
-	clrsetbits_le32(&denali_phy[937], 0xff, reg_value);
-
-	/* phy_pad_cke_drive 8bits DENALI_PHY_935 offset_0 */
-	clrsetbits_le32(&denali_phy[935], 0xff, reg_value);
-
-	/* phy_pad_cs_drive 8bits DENALI_PHY_939 offset_0 */
-	clrsetbits_le32(&denali_phy[939], 0xff, reg_value);
-
-	/* phy_pad_clk_drive 8bits DENALI_PHY_929 offset_0 */
-	clrsetbits_le32(&denali_phy[929], 0xff, reg_value);
-
-	/* phy_pad_fdbk_drive 23bit DENALI_PHY_924/925 */
-	clrsetbits_le32(&denali_phy[924], 0xff,
-			tsel_wr_select_n | (tsel_wr_select_p << 4));
-	clrsetbits_le32(&denali_phy[925], 0xff,
-			tsel_rd_select_n | (tsel_rd_select_p << 4));
-
-	/* phy_dq_tsel_enable_X 3bits DENALI_PHY_5/133/261/389 offset_16 */
-	reg_value = (tsel_rd_en | (tsel_wr_en << 1) | (tsel_idle_en << 2))
-		<< 16;
-	clrsetbits_le32(&denali_phy[5], 0x7 << 16, reg_value);
-	clrsetbits_le32(&denali_phy[133], 0x7 << 16, reg_value);
-	clrsetbits_le32(&denali_phy[261], 0x7 << 16, reg_value);
-	clrsetbits_le32(&denali_phy[389], 0x7 << 16, reg_value);
-
-	/* phy_dqs_tsel_enable_X 3bits DENALI_PHY_6/134/262/390 offset_24 */
-	reg_value = (tsel_rd_en | (tsel_wr_en << 1) | (tsel_idle_en << 2))
-		<< 24;
-	clrsetbits_le32(&denali_phy[6], 0x7 << 24, reg_value);
-	clrsetbits_le32(&denali_phy[134], 0x7 << 24, reg_value);
-	clrsetbits_le32(&denali_phy[262], 0x7 << 24, reg_value);
-	clrsetbits_le32(&denali_phy[390], 0x7 << 24, reg_value);
-
-	/* phy_adr_tsel_enable_ 1bit DENALI_PHY_518/646/774 offset_8 */
-	reg_value = tsel_wr_en << 8;
-	clrsetbits_le32(&denali_phy[518], 0x1 << 8, reg_value);
-	clrsetbits_le32(&denali_phy[646], 0x1 << 8, reg_value);
-	clrsetbits_le32(&denali_phy[774], 0x1 << 8, reg_value);
-
-	/* phy_pad_addr_term tsel 1bit DENALI_PHY_933 offset_17 */
-	reg_value = tsel_wr_en << 17;
-	clrsetbits_le32(&denali_phy[933], 0x1 << 17, reg_value);
-	/*
-	 * pad_rst/cke/cs/clk_term tsel 1bits
-	 * DENALI_PHY_938/936/940/934 offset_17
-	 */
-	clrsetbits_le32(&denali_phy[938], 0x1 << 17, reg_value);
-	clrsetbits_le32(&denali_phy[936], 0x1 << 17, reg_value);
-	clrsetbits_le32(&denali_phy[940], 0x1 << 17, reg_value);
-	clrsetbits_le32(&denali_phy[934], 0x1 << 17, reg_value);
-
-	/* phy_pad_fdbk_term 1bit DENALI_PHY_930 offset_17 */
-	clrsetbits_le32(&denali_phy[930], 0x1 << 17, reg_value);
+	/* PI_41 PI_CS_MAP:RW:24:4 */
+	clrsetbits_le32(&denali_pi[41], 0xf << 24, cs_map << 24);
+	if (sdram_ch->cap_info.rank == 1 && params->base.dramtype == DDR3)
+		writel(0x2EC7FFFF, &denali_pi[34]);
 }
 
 static int phy_io_config(const struct chan_info *chan,
-			  const struct rk3399_sdram_params *sdram_params)
+			 const struct rk3399_sdram_params *params, u32 mr5)
 {
 	u32 *denali_phy = chan->publ->denali_phy;
 	u32 vref_mode_dq, vref_value_dq, vref_mode_ac, vref_value_ac;
@@ -303,15 +369,29 @@
 	u32 drv_value, odt_value;
 	u32 speed;
 
-	/* vref setting */
-	if (sdram_params->base.dramtype == LPDDR4) {
-		/* LPDDR4 */
-		vref_mode_dq = 0x6;
-		vref_value_dq = 0x1f;
+	/* vref setting & mode setting */
+	if (params->base.dramtype == LPDDR4) {
+		struct io_setting *io = lpddr4_get_io_settings(params, mr5);
+		u32 rd_vref = io->rd_vref * 1000;
+
+		if (rd_vref < 36700) {
+			/* MODE_LV[2:0] = LPDDR4 (Range 2)*/
+			vref_mode_dq = 0x7;
+			/* MODE[2:0]= LPDDR4 Range 2(0.4*VDDQ) */
+			mode_sel = 0x5;
+			vref_value_dq = (rd_vref - 3300) / 521;
+		} else {
+			/* MODE_LV[2:0] = LPDDR4 (Range 1)*/
+			vref_mode_dq = 0x6;
+			/* MODE[2:0]= LPDDR4 Range 1(0.33*VDDQ) */
+			mode_sel = 0x4;
+			vref_value_dq = (rd_vref - 15300) / 521;
+		}
 		vref_mode_ac = 0x6;
-		vref_value_ac = 0x1f;
-	} else if (sdram_params->base.dramtype == LPDDR3) {
-		if (sdram_params->base.odt == 1) {
+		/* VDDQ/3/2=16.8% */
+		vref_value_ac = 0x3;
+	} else if (params->base.dramtype == LPDDR3) {
+		if (params->base.odt == 1) {
 			vref_mode_dq = 0x5;  /* LPDDR3 ODT */
 			drv_value = (readl(&denali_phy[6]) >> 12) & 0xf;
 			odt_value = (readl(&denali_phy[6]) >> 4) & 0xf;
@@ -370,12 +450,14 @@
 		}
 		vref_mode_ac = 0x2;
 		vref_value_ac = 0x1f;
-	} else if (sdram_params->base.dramtype == DDR3) {
+		mode_sel = 0x0;
+	} else if (params->base.dramtype == DDR3) {
 		/* DDR3L */
 		vref_mode_dq = 0x1;
 		vref_value_dq = 0x1f;
 		vref_mode_ac = 0x1;
 		vref_value_ac = 0x1f;
+		mode_sel = 0x1;
 	} else {
 		debug("Unknown DRAM type.\n");
 		return -EINVAL;
@@ -397,15 +479,6 @@
 	/* PHY_915 PHY_PAD_VREF_CTRL_AC 12bits offset_16 */
 	clrsetbits_le32(&denali_phy[915], 0xfff << 16, reg_value << 16);
 
-	if (sdram_params->base.dramtype == LPDDR4)
-		mode_sel = 0x6;
-	else if (sdram_params->base.dramtype == LPDDR3)
-		mode_sel = 0x0;
-	else if (sdram_params->base.dramtype == DDR3)
-		mode_sel = 0x1;
-	else
-		return -EINVAL;
-
 	/* PHY_924 PHY_PAD_FDBK_DRIVE */
 	clrsetbits_le32(&denali_phy[924], 0x7 << 15, mode_sel << 15);
 	/* PHY_926 PHY_PAD_DATA_DRIVE */
@@ -423,13 +496,52 @@
 	/* PHY_939 PHY_PAD_CS_DRIVE */
 	clrsetbits_le32(&denali_phy[939], 0x7 << 14, mode_sel << 14);
 
+	if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) {
+		/* BOOSTP_EN & BOOSTN_EN */
+		reg_value = ((PHY_BOOSTP_EN << 4) | PHY_BOOSTN_EN);
+		/* PHY_925 PHY_PAD_FDBK_DRIVE2 */
+		clrsetbits_le32(&denali_phy[925], 0xff << 8, reg_value << 8);
+		/* PHY_926 PHY_PAD_DATA_DRIVE */
+		clrsetbits_le32(&denali_phy[926], 0xff << 12, reg_value << 12);
+		/* PHY_927 PHY_PAD_DQS_DRIVE */
+		clrsetbits_le32(&denali_phy[927], 0xff << 14, reg_value << 14);
+		/* PHY_928 PHY_PAD_ADDR_DRIVE */
+		clrsetbits_le32(&denali_phy[928], 0xff << 20, reg_value << 20);
+		/* PHY_929 PHY_PAD_CLK_DRIVE */
+		clrsetbits_le32(&denali_phy[929], 0xff << 22, reg_value << 22);
+		/* PHY_935 PHY_PAD_CKE_DRIVE */
+		clrsetbits_le32(&denali_phy[935], 0xff << 20, reg_value << 20);
+		/* PHY_937 PHY_PAD_RST_DRIVE */
+		clrsetbits_le32(&denali_phy[937], 0xff << 20, reg_value << 20);
+		/* PHY_939 PHY_PAD_CS_DRIVE */
+		clrsetbits_le32(&denali_phy[939], 0xff << 20, reg_value << 20);
+
+		/* SLEWP_EN & SLEWN_EN */
+		reg_value = ((PHY_SLEWP_EN << 3) | PHY_SLEWN_EN);
+		/* PHY_924 PHY_PAD_FDBK_DRIVE */
+		clrsetbits_le32(&denali_phy[924], 0x3f << 8, reg_value << 8);
+		/* PHY_926 PHY_PAD_DATA_DRIVE */
+		clrsetbits_le32(&denali_phy[926], 0x3f, reg_value);
+		/* PHY_927 PHY_PAD_DQS_DRIVE */
+		clrsetbits_le32(&denali_phy[927], 0x3f, reg_value);
+		/* PHY_928 PHY_PAD_ADDR_DRIVE */
+		clrsetbits_le32(&denali_phy[928], 0x3f << 8, reg_value << 8);
+		/* PHY_929 PHY_PAD_CLK_DRIVE */
+		clrsetbits_le32(&denali_phy[929], 0x3f << 8, reg_value << 8);
+		/* PHY_935 PHY_PAD_CKE_DRIVE */
+		clrsetbits_le32(&denali_phy[935], 0x3f << 8, reg_value << 8);
+		/* PHY_937 PHY_PAD_RST_DRIVE */
+		clrsetbits_le32(&denali_phy[937], 0x3f << 8, reg_value << 8);
+		/* PHY_939 PHY_PAD_CS_DRIVE */
+		clrsetbits_le32(&denali_phy[939], 0x3f << 8, reg_value << 8);
+	}
 
 	/* speed setting */
-	if (sdram_params->base.ddr_freq < 400)
+	if (params->base.ddr_freq < 400)
 		speed = 0x0;
-	else if (sdram_params->base.ddr_freq < 800)
+	else if (params->base.ddr_freq < 800)
 		speed = 0x1;
-	else if (sdram_params->base.ddr_freq < 1200)
+	else if (params->base.ddr_freq < 1200)
 		speed = 0x2;
 	else
 		speed = 0x3;
@@ -451,115 +563,406 @@
 	/* PHY_939 PHY_PAD_CS_DRIVE */
 	clrsetbits_le32(&denali_phy[939], 0x3 << 17, speed << 17);
 
+	if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) {
+		/* RX_CM_INPUT */
+		reg_value = PHY_RX_CM_INPUT;
+		/* PHY_924 PHY_PAD_FDBK_DRIVE */
+		clrsetbits_le32(&denali_phy[924], 0x1 << 14, reg_value << 14);
+		/* PHY_926 PHY_PAD_DATA_DRIVE */
+		clrsetbits_le32(&denali_phy[926], 0x1 << 11, reg_value << 11);
+		/* PHY_927 PHY_PAD_DQS_DRIVE */
+		clrsetbits_le32(&denali_phy[927], 0x1 << 13, reg_value << 13);
+		/* PHY_928 PHY_PAD_ADDR_DRIVE */
+		clrsetbits_le32(&denali_phy[928], 0x1 << 19, reg_value << 19);
+		/* PHY_929 PHY_PAD_CLK_DRIVE */
+		clrsetbits_le32(&denali_phy[929], 0x1 << 21, reg_value << 21);
+		/* PHY_935 PHY_PAD_CKE_DRIVE */
+		clrsetbits_le32(&denali_phy[935], 0x1 << 19, reg_value << 19);
+		/* PHY_937 PHY_PAD_RST_DRIVE */
+		clrsetbits_le32(&denali_phy[937], 0x1 << 19, reg_value << 19);
+		/* PHY_939 PHY_PAD_CS_DRIVE */
+		clrsetbits_le32(&denali_phy[939], 0x1 << 19, reg_value << 19);
+	}
+
 	return 0;
 }
 
-static int pctl_cfg(const struct chan_info *chan, u32 channel,
-		    const struct rk3399_sdram_params *sdram_params)
+static void set_ds_odt(const struct chan_info *chan,
+		       struct rk3399_sdram_params *params,
+		       bool ctl_phy_reg, u32 mr5)
 {
-	u32 *denali_ctl = chan->pctl->denali_ctl;
-	u32 *denali_pi = chan->pi->denali_pi;
-	u32 *denali_phy = chan->publ->denali_phy;
-	const u32 *params_ctl = sdram_params->pctl_regs.denali_ctl;
-	const u32 *params_phy = sdram_params->phy_regs.denali_phy;
-	u32 tmp, tmp1, tmp2;
-	u32 pwrup_srefresh_exit;
-	int ret;
-	const ulong timeout_ms = 200;
+	u32 *denali_phy = get_denali_phy(chan, params, ctl_phy_reg);
+	u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);
+	u32 tsel_idle_en, tsel_wr_en, tsel_rd_en;
+	u32 tsel_idle_select_p, tsel_rd_select_p;
+	u32 tsel_idle_select_n, tsel_rd_select_n;
+	u32 tsel_wr_select_dq_p, tsel_wr_select_ca_p;
+	u32 tsel_wr_select_dq_n, tsel_wr_select_ca_n;
+	u32 tsel_ckcs_select_p, tsel_ckcs_select_n;
+	struct io_setting *io = NULL;
+	u32 soc_odt = 0;
+	u32 reg_value;
 
-	/*
-	 * work around controller bug:
-	 * Do not program DRAM_CLASS until NO_PHY_IND_TRAIN_INT is programmed
-	 */
-	copy_to_reg(&denali_ctl[1], &params_ctl[1],
-		    sizeof(struct rk3399_ddr_pctl_regs) - 4);
-	writel(params_ctl[0], &denali_ctl[0]);
-	copy_to_reg(denali_pi, &sdram_params->pi_regs.denali_pi[0],
-		    sizeof(struct rk3399_ddr_pi_regs));
-	/* rank count need to set for init */
-	set_memory_map(chan, channel, sdram_params);
+	if (params->base.dramtype == LPDDR4) {
+		io = lpddr4_get_io_settings(params, mr5);
 
-	writel(sdram_params->phy_regs.denali_phy[910], &denali_phy[910]);
-	writel(sdram_params->phy_regs.denali_phy[911], &denali_phy[911]);
-	writel(sdram_params->phy_regs.denali_phy[912], &denali_phy[912]);
+		tsel_rd_select_p = PHY_DRV_ODT_HI_Z;
+		tsel_rd_select_n = io->rd_odt;
 
-	pwrup_srefresh_exit = readl(&denali_ctl[68]) & PWRUP_SREFRESH_EXIT;
-	clrbits_le32(&denali_ctl[68], PWRUP_SREFRESH_EXIT);
+		tsel_idle_select_p = PHY_DRV_ODT_HI_Z;
+		tsel_idle_select_n = PHY_DRV_ODT_240;
 
-	/* PHY_DLL_RST_EN */
-	clrsetbits_le32(&denali_phy[957], 0x3 << 24, 1 << 24);
+		tsel_wr_select_dq_p = io->wr_dq_drv;
+		tsel_wr_select_dq_n = PHY_DRV_ODT_40;
 
-	setbits_le32(&denali_pi[0], START);
-	setbits_le32(&denali_ctl[0], START);
+		tsel_wr_select_ca_p = io->wr_ca_drv;
+		tsel_wr_select_ca_n = PHY_DRV_ODT_40;
 
-	/* Wating for phy DLL lock */
-	while (1) {
-		tmp = readl(&denali_phy[920]);
-		tmp1 = readl(&denali_phy[921]);
-		tmp2 = readl(&denali_phy[922]);
-		if ((((tmp >> 16) & 0x1) == 0x1) &&
-		    (((tmp1 >> 16) & 0x1) == 0x1) &&
-		    (((tmp1 >> 0) & 0x1) == 0x1) &&
-		    (((tmp2 >> 0) & 0x1) == 0x1))
+		tsel_ckcs_select_p = io->wr_ckcs_drv;
+		tsel_ckcs_select_n = PHY_DRV_ODT_34_3;
+		switch (tsel_rd_select_n) {
+		case PHY_DRV_ODT_240:
+			soc_odt = 1;
 			break;
-	}
+		case PHY_DRV_ODT_120:
+			soc_odt = 2;
+			break;
+		case PHY_DRV_ODT_80:
+			soc_odt = 3;
+			break;
+		case PHY_DRV_ODT_60:
+			soc_odt = 4;
+			break;
+		case PHY_DRV_ODT_48:
+			soc_odt = 5;
+			break;
+		case PHY_DRV_ODT_40:
+			soc_odt = 6;
+			break;
+		case PHY_DRV_ODT_34_3:
+			soc_odt = 6;
+			printf("%s: Unable to support LPDDR4 MR22 Soc ODT\n",
+			       __func__);
+			break;
+		case PHY_DRV_ODT_HI_Z:
+		default:
+			soc_odt = 0;
+			break;
+		}
+	} else if (params->base.dramtype == LPDDR3) {
+		tsel_rd_select_p = PHY_DRV_ODT_240;
+		tsel_rd_select_n = PHY_DRV_ODT_HI_Z;
 
-	copy_to_reg(&denali_phy[896], &params_phy[896], (958 - 895) * 4);
-	copy_to_reg(&denali_phy[0], &params_phy[0], (90 - 0 + 1) * 4);
-	copy_to_reg(&denali_phy[128], &params_phy[128], (218 - 128 + 1) * 4);
-	copy_to_reg(&denali_phy[256], &params_phy[256], (346 - 256 + 1) * 4);
-	copy_to_reg(&denali_phy[384], &params_phy[384], (474 - 384 + 1) * 4);
-	copy_to_reg(&denali_phy[512], &params_phy[512], (549 - 512 + 1) * 4);
-	copy_to_reg(&denali_phy[640], &params_phy[640], (677 - 640 + 1) * 4);
-	copy_to_reg(&denali_phy[768], &params_phy[768], (805 - 768 + 1) * 4);
-	set_ds_odt(chan, sdram_params);
+		tsel_idle_select_p = PHY_DRV_ODT_240;
+		tsel_idle_select_n = PHY_DRV_ODT_HI_Z;
 
-	/*
-	 * phy_dqs_tsel_wr_timing_X 8bits DENALI_PHY_84/212/340/468 offset_8
-	 * dqs_tsel_wr_end[7:4] add Half cycle
-	 */
-	tmp = (readl(&denali_phy[84]) >> 8) & 0xff;
-	clrsetbits_le32(&denali_phy[84], 0xff << 8, (tmp + 0x10) << 8);
-	tmp = (readl(&denali_phy[212]) >> 8) & 0xff;
-	clrsetbits_le32(&denali_phy[212], 0xff << 8, (tmp + 0x10) << 8);
-	tmp = (readl(&denali_phy[340]) >> 8) & 0xff;
-	clrsetbits_le32(&denali_phy[340], 0xff << 8, (tmp + 0x10) << 8);
-	tmp = (readl(&denali_phy[468]) >> 8) & 0xff;
-	clrsetbits_le32(&denali_phy[468], 0xff << 8, (tmp + 0x10) << 8);
+		tsel_wr_select_dq_p = PHY_DRV_ODT_34_3;
+		tsel_wr_select_dq_n = PHY_DRV_ODT_34_3;
 
-	/*
-	 * phy_dqs_tsel_wr_timing_X 8bits DENALI_PHY_83/211/339/467 offset_8
-	 * dq_tsel_wr_end[7:4] add Half cycle
-	 */
-	tmp = (readl(&denali_phy[83]) >> 16) & 0xff;
-	clrsetbits_le32(&denali_phy[83], 0xff << 16, (tmp + 0x10) << 16);
-	tmp = (readl(&denali_phy[211]) >> 16) & 0xff;
-	clrsetbits_le32(&denali_phy[211], 0xff << 16, (tmp + 0x10) << 16);
-	tmp = (readl(&denali_phy[339]) >> 16) & 0xff;
-	clrsetbits_le32(&denali_phy[339], 0xff << 16, (tmp + 0x10) << 16);
-	tmp = (readl(&denali_phy[467]) >> 16) & 0xff;
-	clrsetbits_le32(&denali_phy[467], 0xff << 16, (tmp + 0x10) << 16);
+		tsel_wr_select_ca_p = PHY_DRV_ODT_48;
+		tsel_wr_select_ca_n = PHY_DRV_ODT_48;
 
-	ret = phy_io_config(chan, sdram_params);
-	if (ret)
-		return ret;
+		tsel_ckcs_select_p = PHY_DRV_ODT_34_3;
+		tsel_ckcs_select_n = PHY_DRV_ODT_34_3;
+	} else {
+		tsel_rd_select_p = PHY_DRV_ODT_240;
+		tsel_rd_select_n = PHY_DRV_ODT_240;
 
-	/* PHY_DLL_RST_EN */
+		tsel_idle_select_p = PHY_DRV_ODT_240;
+		tsel_idle_select_n = PHY_DRV_ODT_240;
+
+		tsel_wr_select_dq_p = PHY_DRV_ODT_34_3;
+		tsel_wr_select_dq_n = PHY_DRV_ODT_34_3;
+
+		tsel_wr_select_ca_p = PHY_DRV_ODT_34_3;
+		tsel_wr_select_ca_n = PHY_DRV_ODT_34_3;
+
+		tsel_ckcs_select_p = PHY_DRV_ODT_34_3;
+		tsel_ckcs_select_n = PHY_DRV_ODT_34_3;
+	}
+
+	if (params->base.odt == 1) {
+		tsel_rd_en = 1;
+
+		if (params->base.dramtype == LPDDR4)
+			tsel_rd_en = io->rd_odt_en;
+	} else {
+		tsel_rd_en = 0;
+	}
+
+	tsel_wr_en = 0;
+	tsel_idle_en = 0;
+
+	/* F0_0 */
+	clrsetbits_le32(&denali_ctl[145], 0xFF << 16,
+			(soc_odt | (CS0_MR22_VAL << 3)) << 16);
+	/* F2_0, F1_0 */
+	clrsetbits_le32(&denali_ctl[146], 0xFF00FF,
+			((soc_odt | (CS0_MR22_VAL << 3)) << 16) |
+			(soc_odt | (CS0_MR22_VAL << 3)));
+	/* F0_1 */
+	clrsetbits_le32(&denali_ctl[159], 0xFF << 16,
+			(soc_odt | (CS1_MR22_VAL << 3)) << 16);
+	/* F2_1, F1_1 */
+	clrsetbits_le32(&denali_ctl[160], 0xFF00FF,
+			((soc_odt | (CS1_MR22_VAL << 3)) << 16) |
+			(soc_odt | (CS1_MR22_VAL << 3)));
+
+	/*
+	 * phy_dq_tsel_select_X 24bits DENALI_PHY_6/134/262/390 offset_0
+	 * sets termination values for read/idle cycles and drive strength
+	 * for write cycles for DQ/DM
+	 */
+	reg_value = tsel_rd_select_n | (tsel_rd_select_p << 0x4) |
+		    (tsel_wr_select_dq_n << 8) | (tsel_wr_select_dq_p << 12) |
+		    (tsel_idle_select_n << 16) | (tsel_idle_select_p << 20);
+	clrsetbits_le32(&denali_phy[6], 0xffffff, reg_value);
+	clrsetbits_le32(&denali_phy[134], 0xffffff, reg_value);
+	clrsetbits_le32(&denali_phy[262], 0xffffff, reg_value);
+	clrsetbits_le32(&denali_phy[390], 0xffffff, reg_value);
+
+	/*
+	 * phy_dqs_tsel_select_X 24bits DENALI_PHY_7/135/263/391 offset_0
+	 * sets termination values for read/idle cycles and drive strength
+	 * for write cycles for DQS
+	 */
+	clrsetbits_le32(&denali_phy[7], 0xffffff, reg_value);
+	clrsetbits_le32(&denali_phy[135], 0xffffff, reg_value);
+	clrsetbits_le32(&denali_phy[263], 0xffffff, reg_value);
+	clrsetbits_le32(&denali_phy[391], 0xffffff, reg_value);
+
+	/* phy_adr_tsel_select_ 8bits DENALI_PHY_544/672/800 offset_0 */
+	reg_value = tsel_wr_select_ca_n | (tsel_wr_select_ca_p << 0x4);
+	if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) {
+		/* LPDDR4 these register read always return 0, so
+		 * can not use clrsetbits_le32(), need to write32
+		 */
+		writel((0x300 << 8) | reg_value, &denali_phy[544]);
+		writel((0x300 << 8) | reg_value, &denali_phy[672]);
+		writel((0x300 << 8) | reg_value, &denali_phy[800]);
+	} else {
+		clrsetbits_le32(&denali_phy[544], 0xff, reg_value);
+		clrsetbits_le32(&denali_phy[672], 0xff, reg_value);
+		clrsetbits_le32(&denali_phy[800], 0xff, reg_value);
+	}
+
+	/* phy_pad_addr_drive 8bits DENALI_PHY_928 offset_0 */
+	clrsetbits_le32(&denali_phy[928], 0xff, reg_value);
+
+	/* phy_pad_rst_drive 8bits DENALI_PHY_937 offset_0 */
+	if (!ctl_phy_reg)
+		clrsetbits_le32(&denali_phy[937], 0xff, reg_value);
+
+	/* phy_pad_cke_drive 8bits DENALI_PHY_935 offset_0 */
+	clrsetbits_le32(&denali_phy[935], 0xff, reg_value);
+
+	/* phy_pad_cs_drive 8bits DENALI_PHY_939 offset_0 */
+	clrsetbits_le32(&denali_phy[939], 0xff,
+			tsel_ckcs_select_n | (tsel_ckcs_select_p << 0x4));
+
+	/* phy_pad_clk_drive 8bits DENALI_PHY_929 offset_0 */
+	clrsetbits_le32(&denali_phy[929], 0xff,
+			tsel_ckcs_select_n | (tsel_ckcs_select_p << 0x4));
+
+	/* phy_pad_fdbk_drive 23bit DENALI_PHY_924/925 */
+	clrsetbits_le32(&denali_phy[924], 0xff,
+			tsel_wr_select_dq_n | (tsel_wr_select_dq_p << 4));
+	clrsetbits_le32(&denali_phy[925], 0xff,
+			tsel_rd_select_n | (tsel_rd_select_p << 4));
+
+	/* phy_dq_tsel_enable_X 3bits DENALI_PHY_5/133/261/389 offset_16 */
+	reg_value = (tsel_rd_en | (tsel_wr_en << 1) | (tsel_idle_en << 2))
+		<< 16;
+	clrsetbits_le32(&denali_phy[5], 0x7 << 16, reg_value);
+	clrsetbits_le32(&denali_phy[133], 0x7 << 16, reg_value);
+	clrsetbits_le32(&denali_phy[261], 0x7 << 16, reg_value);
+	clrsetbits_le32(&denali_phy[389], 0x7 << 16, reg_value);
+
+	/* phy_dqs_tsel_enable_X 3bits DENALI_PHY_6/134/262/390 offset_24 */
+	reg_value = (tsel_rd_en | (tsel_wr_en << 1) | (tsel_idle_en << 2))
+		<< 24;
+	clrsetbits_le32(&denali_phy[6], 0x7 << 24, reg_value);
+	clrsetbits_le32(&denali_phy[134], 0x7 << 24, reg_value);
+	clrsetbits_le32(&denali_phy[262], 0x7 << 24, reg_value);
+	clrsetbits_le32(&denali_phy[390], 0x7 << 24, reg_value);
+
+	/* phy_adr_tsel_enable_ 1bit DENALI_PHY_518/646/774 offset_8 */
+	reg_value = tsel_wr_en << 8;
+	clrsetbits_le32(&denali_phy[518], 0x1 << 8, reg_value);
+	clrsetbits_le32(&denali_phy[646], 0x1 << 8, reg_value);
+	clrsetbits_le32(&denali_phy[774], 0x1 << 8, reg_value);
+
+	/* phy_pad_addr_term tsel 1bit DENALI_PHY_933 offset_17 */
+	reg_value = tsel_wr_en << 17;
+	clrsetbits_le32(&denali_phy[933], 0x1 << 17, reg_value);
+	/*
+	 * pad_rst/cke/cs/clk_term tsel 1bits
+	 * DENALI_PHY_938/936/940/934 offset_17
+	 */
+	clrsetbits_le32(&denali_phy[938], 0x1 << 17, reg_value);
+	clrsetbits_le32(&denali_phy[936], 0x1 << 17, reg_value);
+	clrsetbits_le32(&denali_phy[940], 0x1 << 17, reg_value);
+	clrsetbits_le32(&denali_phy[934], 0x1 << 17, reg_value);
+
+	/* phy_pad_fdbk_term 1bit DENALI_PHY_930 offset_17 */
+	clrsetbits_le32(&denali_phy[930], 0x1 << 17, reg_value);
+
+	phy_io_config(chan, params, mr5);
+}
+
+static void pctl_start(struct dram_info *dram, u8 channel)
+{
+	const struct chan_info *chan = &dram->chan[channel];
+	u32 *denali_ctl = chan->pctl->denali_ctl;
+	u32 *denali_phy = chan->publ->denali_phy;
+	u32 *ddrc0_con = get_ddrc0_con(dram, channel);
+	u32 count = 0;
+	u32 byte, tmp;
+
+	writel(0x01000000, &ddrc0_con);
+
 	clrsetbits_le32(&denali_phy[957], 0x3 << 24, 0x2 << 24);
 
-	/* Wating for PHY and DRAM init complete */
-	tmp = get_timer(0);
-	do {
-		if (get_timer(tmp) > timeout_ms) {
-			pr_err("DRAM (%s): phy failed to lock within  %ld ms\n",
-			      __func__, timeout_ms);
-			return -ETIME;
+	while (!(readl(&denali_ctl[203]) & (1 << 3))) {
+		if (count > 1000) {
+			printf("%s: Failed to init pctl for channel %d\n",
+			       __func__, channel);
+			while (1)
+				;
 		}
-	} while (!(readl(&denali_ctl[203]) & (1 << 3)));
-	debug("DRAM (%s): phy locked after %ld ms\n", __func__, get_timer(tmp));
+
+		udelay(1);
+		count++;
+	}
+
+	writel(0x01000100, &ddrc0_con);
+
+	for (byte = 0; byte < 4; byte++) {
+		tmp = 0x820;
+		writel((tmp << 16) | tmp, &denali_phy[53 + (128 * byte)]);
+		writel((tmp << 16) | tmp, &denali_phy[54 + (128 * byte)]);
+		writel((tmp << 16) | tmp, &denali_phy[55 + (128 * byte)]);
+		writel((tmp << 16) | tmp, &denali_phy[56 + (128 * byte)]);
+		writel((tmp << 16) | tmp, &denali_phy[57 + (128 * byte)]);
+
+		clrsetbits_le32(&denali_phy[58 + (128 * byte)], 0xffff, tmp);
+	}
 
 	clrsetbits_le32(&denali_ctl[68], PWRUP_SREFRESH_EXIT,
-			pwrup_srefresh_exit);
+			dram->pwrup_srefresh_exit[channel]);
+}
+
+static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,
+		    u32 channel, struct rk3399_sdram_params *params)
+{
+	u32 *denali_ctl = chan->pctl->denali_ctl;
+	u32 *denali_pi = chan->pi->denali_pi;
+	u32 *denali_phy = chan->publ->denali_phy;
+	const u32 *params_ctl = params->pctl_regs.denali_ctl;
+	const u32 *params_phy = params->phy_regs.denali_phy;
+	u32 tmp, tmp1, tmp2;
+
+	/*
+	 * work around controller bug:
+	 * Do not program DRAM_CLASS until NO_PHY_IND_TRAIN_INT is programmed
+	 */
+	copy_to_reg(&denali_ctl[1], &params_ctl[1],
+		    sizeof(struct rk3399_ddr_pctl_regs) - 4);
+	writel(params_ctl[0], &denali_ctl[0]);
+
+	/*
+	 * two channel init at the same time, then ZQ Cal Start
+	 * at the same time, it will use the same RZQ, but cannot
+	 * start at the same time.
+	 *
+	 * So, increase tINIT3 for channel 1, will avoid two
+	 * channel ZQ Cal Start at the same time
+	 */
+	if (params->base.dramtype == LPDDR4 && channel == 1) {
+		tmp = ((params->base.ddr_freq * MHz + 999) / 1000);
+		tmp1 = readl(&denali_ctl[14]);
+		writel(tmp + tmp1, &denali_ctl[14]);
+	}
+
+	copy_to_reg(denali_pi, &params->pi_regs.denali_pi[0],
+		    sizeof(struct rk3399_ddr_pi_regs));
+
+	/* rank count need to set for init */
+	set_memory_map(chan, channel, params);
+
+	writel(params->phy_regs.denali_phy[910], &denali_phy[910]);
+	writel(params->phy_regs.denali_phy[911], &denali_phy[911]);
+	writel(params->phy_regs.denali_phy[912], &denali_phy[912]);
+
+	if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) {
+		writel(params->phy_regs.denali_phy[898], &denali_phy[898]);
+		writel(params->phy_regs.denali_phy[919], &denali_phy[919]);
+	}
+
+	dram->pwrup_srefresh_exit[channel] = readl(&denali_ctl[68]) &
+					     PWRUP_SREFRESH_EXIT;
+	clrbits_le32(&denali_ctl[68], PWRUP_SREFRESH_EXIT);
+
+	/* PHY_DLL_RST_EN */
+	clrsetbits_le32(&denali_phy[957], 0x3 << 24, 1 << 24);
+
+	setbits_le32(&denali_pi[0], START);
+	setbits_le32(&denali_ctl[0], START);
+
+	/**
+	 * LPDDR4 use PLL bypass mode for init
+	 * not need to wait for the PLL to lock
+	 */
+	if (params->base.dramtype != LPDDR4) {
+		/* Waiting for phy DLL lock */
+		while (1) {
+			tmp = readl(&denali_phy[920]);
+			tmp1 = readl(&denali_phy[921]);
+			tmp2 = readl(&denali_phy[922]);
+			if ((((tmp >> 16) & 0x1) == 0x1) &&
+			    (((tmp1 >> 16) & 0x1) == 0x1) &&
+			    (((tmp1 >> 0) & 0x1) == 0x1) &&
+			    (((tmp2 >> 0) & 0x1) == 0x1))
+				break;
+		}
+	}
+
+	copy_to_reg(&denali_phy[896], &params_phy[896], (958 - 895) * 4);
+	copy_to_reg(&denali_phy[0], &params_phy[0], (90 - 0 + 1) * 4);
+	copy_to_reg(&denali_phy[128], &params_phy[128], (218 - 128 + 1) * 4);
+	copy_to_reg(&denali_phy[256], &params_phy[256], (346 - 256 + 1) * 4);
+	copy_to_reg(&denali_phy[384], &params_phy[384], (474 - 384 + 1) * 4);
+	copy_to_reg(&denali_phy[512], &params_phy[512], (549 - 512 + 1) * 4);
+	copy_to_reg(&denali_phy[640], &params_phy[640], (677 - 640 + 1) * 4);
+	copy_to_reg(&denali_phy[768], &params_phy[768], (805 - 768 + 1) * 4);
+	set_ds_odt(chan, params, true, 0);
+
+	/*
+	 * phy_dqs_tsel_wr_timing_X 8bits DENALI_PHY_84/212/340/468 offset_8
+	 * dqs_tsel_wr_end[7:4] add Half cycle
+	 */
+	tmp = (readl(&denali_phy[84]) >> 8) & 0xff;
+	clrsetbits_le32(&denali_phy[84], 0xff << 8, (tmp + 0x10) << 8);
+	tmp = (readl(&denali_phy[212]) >> 8) & 0xff;
+	clrsetbits_le32(&denali_phy[212], 0xff << 8, (tmp + 0x10) << 8);
+	tmp = (readl(&denali_phy[340]) >> 8) & 0xff;
+	clrsetbits_le32(&denali_phy[340], 0xff << 8, (tmp + 0x10) << 8);
+	tmp = (readl(&denali_phy[468]) >> 8) & 0xff;
+	clrsetbits_le32(&denali_phy[468], 0xff << 8, (tmp + 0x10) << 8);
+
+	/*
+	 * phy_dqs_tsel_wr_timing_X 8bits DENALI_PHY_83/211/339/467 offset_8
+	 * dq_tsel_wr_end[7:4] add Half cycle
+	 */
+	tmp = (readl(&denali_phy[83]) >> 16) & 0xff;
+	clrsetbits_le32(&denali_phy[83], 0xff << 16, (tmp + 0x10) << 16);
+	tmp = (readl(&denali_phy[211]) >> 16) & 0xff;
+	clrsetbits_le32(&denali_phy[211], 0xff << 16, (tmp + 0x10) << 16);
+	tmp = (readl(&denali_phy[339]) >> 16) & 0xff;
+	clrsetbits_le32(&denali_phy[339], 0xff << 16, (tmp + 0x10) << 16);
+	tmp = (readl(&denali_phy[467]) >> 16) & 0xff;
+	clrsetbits_le32(&denali_phy[467], 0xff << 16, (tmp + 0x10) << 16);
+
 	return 0;
 }
 
@@ -569,7 +972,7 @@
 	u32 *denali_phy = chan->publ->denali_phy;
 
 	/* PHY_84 PHY_PER_CS_TRAINING_EN_0 1bit offset_16 */
-	if ((readl(&denali_phy[84])>>16) & 1) {
+	if ((readl(&denali_phy[84]) >> 16) & 1) {
 		/*
 		 * PHY_8/136/264/392
 		 * phy_per_cs_training_index_X 1bit offset_24
@@ -611,18 +1014,32 @@
 }
 
 static int data_training_ca(const struct chan_info *chan, u32 channel,
-			    const struct rk3399_sdram_params *sdram_params)
+			    const struct rk3399_sdram_params *params)
 {
 	u32 *denali_pi = chan->pi->denali_pi;
 	u32 *denali_phy = chan->publ->denali_phy;
 	u32 i, tmp;
 	u32 obs_0, obs_1, obs_2, obs_err = 0;
-	u32 rank = sdram_params->ch[channel].rank;
+	u32 rank = params->ch[channel].cap_info.rank;
+	u32 rank_mask;
 
-	for (i = 0; i < rank; i++) {
+	/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
+	writel(0x00003f7c, (&denali_pi[175]));
+
+	if (params->base.dramtype == LPDDR4)
+		rank_mask = (rank == 1) ? 0x5 : 0xf;
+	else
+		rank_mask = (rank == 1) ? 0x1 : 0x3;
+
+	for (i = 0; i < 4; i++) {
+		if (!(rank_mask & (1 << i)))
+			continue;
+
 		select_per_cs_training_index(chan, i);
+
 		/* PI_100 PI_CALVL_EN:RW:8:2 */
 		clrsetbits_le32(&denali_pi[100], 0x3 << 8, 0x2 << 8);
+
 		/* PI_92 PI_CALVL_REQ:WR:16:1,PI_CALVL_CS:RW:24:2 */
 		clrsetbits_le32(&denali_pi[92],
 				(0x1 << 16) | (0x3 << 24),
@@ -646,33 +1063,40 @@
 			if ((((tmp >> 11) & 0x1) == 0x1) &&
 			    (((tmp >> 13) & 0x1) == 0x1) &&
 			    (((tmp >> 5) & 0x1) == 0x0) &&
-			    (obs_err == 0))
+			    obs_err == 0)
 				break;
 			else if ((((tmp >> 5) & 0x1) == 0x1) ||
 				 (obs_err == 1))
 				return -EIO;
 		}
+
 		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
 		writel(0x00003f7c, (&denali_pi[175]));
 	}
+
 	clrbits_le32(&denali_pi[100], 0x3 << 8);
 
 	return 0;
 }
 
 static int data_training_wl(const struct chan_info *chan, u32 channel,
-			    const struct rk3399_sdram_params *sdram_params)
+			    const struct rk3399_sdram_params *params)
 {
 	u32 *denali_pi = chan->pi->denali_pi;
 	u32 *denali_phy = chan->publ->denali_phy;
 	u32 i, tmp;
 	u32 obs_0, obs_1, obs_2, obs_3, obs_err = 0;
-	u32 rank = sdram_params->ch[channel].rank;
+	u32 rank = params->ch[channel].cap_info.rank;
+
+	/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
+	writel(0x00003f7c, (&denali_pi[175]));
 
 	for (i = 0; i < rank; i++) {
 		select_per_cs_training_index(chan, i);
+
 		/* PI_60 PI_WRLVL_EN:RW:8:2 */
 		clrsetbits_le32(&denali_pi[60], 0x3 << 8, 0x2 << 8);
+
 		/* PI_59 PI_WRLVL_REQ:WR:8:1,PI_WRLVL_CS:RW:16:2 */
 		clrsetbits_le32(&denali_pi[59],
 				(0x1 << 8) | (0x3 << 16),
@@ -700,12 +1124,13 @@
 			if ((((tmp >> 10) & 0x1) == 0x1) &&
 			    (((tmp >> 13) & 0x1) == 0x1) &&
 			    (((tmp >> 4) & 0x1) == 0x0) &&
-			    (obs_err == 0))
+			    obs_err == 0)
 				break;
 			else if ((((tmp >> 4) & 0x1) == 0x1) ||
 				 (obs_err == 1))
 				return -EIO;
 		}
+
 		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
 		writel(0x00003f7c, (&denali_pi[175]));
 	}
@@ -717,18 +1142,23 @@
 }
 
 static int data_training_rg(const struct chan_info *chan, u32 channel,
-			    const struct rk3399_sdram_params *sdram_params)
+			    const struct rk3399_sdram_params *params)
 {
 	u32 *denali_pi = chan->pi->denali_pi;
 	u32 *denali_phy = chan->publ->denali_phy;
 	u32 i, tmp;
 	u32 obs_0, obs_1, obs_2, obs_3, obs_err = 0;
-	u32 rank = sdram_params->ch[channel].rank;
+	u32 rank = params->ch[channel].cap_info.rank;
+
+	/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
+	writel(0x00003f7c, (&denali_pi[175]));
 
 	for (i = 0; i < rank; i++) {
 		select_per_cs_training_index(chan, i);
+
 		/* PI_80 PI_RDLVL_GATE_EN:RW:24:2 */
 		clrsetbits_le32(&denali_pi[80], 0x3 << 24, 0x2 << 24);
+
 		/*
 		 * PI_74 PI_RDLVL_GATE_REQ:WR:16:1
 		 * PI_RDLVL_CS:RW:24:2
@@ -759,31 +1189,38 @@
 			if ((((tmp >> 9) & 0x1) == 0x1) &&
 			    (((tmp >> 13) & 0x1) == 0x1) &&
 			    (((tmp >> 3) & 0x1) == 0x0) &&
-			    (obs_err == 0))
+			    obs_err == 0)
 				break;
 			else if ((((tmp >> 3) & 0x1) == 0x1) ||
 				 (obs_err == 1))
 				return -EIO;
 		}
+
 		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
 		writel(0x00003f7c, (&denali_pi[175]));
 	}
+
 	clrbits_le32(&denali_pi[80], 0x3 << 24);
 
 	return 0;
 }
 
 static int data_training_rl(const struct chan_info *chan, u32 channel,
-			    const struct rk3399_sdram_params *sdram_params)
+			    const struct rk3399_sdram_params *params)
 {
 	u32 *denali_pi = chan->pi->denali_pi;
 	u32 i, tmp;
-	u32 rank = sdram_params->ch[channel].rank;
+	u32 rank = params->ch[channel].cap_info.rank;
+
+	/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
+	writel(0x00003f7c, (&denali_pi[175]));
 
 	for (i = 0; i < rank; i++) {
 		select_per_cs_training_index(chan, i);
+
 		/* PI_80 PI_RDLVL_EN:RW:16:2 */
 		clrsetbits_le32(&denali_pi[80], 0x3 << 16, 0x2 << 16);
+
 		/* PI_74 PI_RDLVL_REQ:WR:8:1,PI_RDLVL_CS:RW:24:2 */
 		clrsetbits_le32(&denali_pi[74],
 				(0x1 << 8) | (0x3 << 24),
@@ -806,30 +1243,47 @@
 			else if (((tmp >> 2) & 0x1) == 0x1)
 				return -EIO;
 		}
+
 		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
 		writel(0x00003f7c, (&denali_pi[175]));
 	}
+
 	clrbits_le32(&denali_pi[80], 0x3 << 16);
 
 	return 0;
 }
 
 static int data_training_wdql(const struct chan_info *chan, u32 channel,
-			      const struct rk3399_sdram_params *sdram_params)
+			      const struct rk3399_sdram_params *params)
 {
 	u32 *denali_pi = chan->pi->denali_pi;
 	u32 i, tmp;
-	u32 rank = sdram_params->ch[channel].rank;
+	u32 rank = params->ch[channel].cap_info.rank;
+	u32 rank_mask;
 
-	for (i = 0; i < rank; i++) {
+	/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
+	writel(0x00003f7c, (&denali_pi[175]));
+
+	if (params->base.dramtype == LPDDR4)
+		rank_mask = (rank == 1) ? 0x5 : 0xf;
+	else
+		rank_mask = (rank == 1) ? 0x1 : 0x3;
+
+	for (i = 0; i < 4; i++) {
+		if (!(rank_mask & (1 << i)))
+			continue;
+
 		select_per_cs_training_index(chan, i);
+
 		/*
 		 * disable PI_WDQLVL_VREF_EN before wdq leveling?
 		 * PI_181 PI_WDQLVL_VREF_EN:RW:8:1
 		 */
 		clrbits_le32(&denali_pi[181], 0x1 << 8);
+
 		/* PI_124 PI_WDQLVL_EN:RW:16:2 */
 		clrsetbits_le32(&denali_pi[124], 0x3 << 16, 0x2 << 16);
+
 		/* PI_121 PI_WDQLVL_REQ:WR:8:1,PI_WDQLVL_CS:RW:16:2 */
 		clrsetbits_le32(&denali_pi[121],
 				(0x1 << 8) | (0x3 << 16),
@@ -846,32 +1300,36 @@
 			else if (((tmp >> 6) & 0x1) == 0x1)
 				return -EIO;
 		}
+
 		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
 		writel(0x00003f7c, (&denali_pi[175]));
 	}
+
 	clrbits_le32(&denali_pi[124], 0x3 << 16);
 
 	return 0;
 }
 
-static int data_training(const struct chan_info *chan, u32 channel,
-			 const struct rk3399_sdram_params *sdram_params,
+static int data_training(struct dram_info *dram, u32 channel,
+			 const struct rk3399_sdram_params *params,
 			 u32 training_flag)
 {
+	struct chan_info *chan = &dram->chan[channel];
 	u32 *denali_phy = chan->publ->denali_phy;
+	int ret;
 
 	/* PHY_927 PHY_PAD_DQS_DRIVE  RPULL offset_22 */
 	setbits_le32(&denali_phy[927], (1 << 22));
 
 	if (training_flag == PI_FULL_TRAINING) {
-		if (sdram_params->base.dramtype == LPDDR4) {
-			training_flag = PI_CA_TRAINING | PI_WRITE_LEVELING |
+		if (params->base.dramtype == LPDDR4) {
+			training_flag = PI_WRITE_LEVELING |
 					PI_READ_GATE_TRAINING |
 					PI_READ_LEVELING | PI_WDQ_LEVELING;
-		} else if (sdram_params->base.dramtype == LPDDR3) {
+		} else if (params->base.dramtype == LPDDR3) {
 			training_flag = PI_CA_TRAINING | PI_WRITE_LEVELING |
 					PI_READ_GATE_TRAINING;
-		} else if (sdram_params->base.dramtype == DDR3) {
+		} else if (params->base.dramtype == DDR3) {
 			training_flag = PI_WRITE_LEVELING |
 					PI_READ_GATE_TRAINING |
 					PI_READ_LEVELING;
@@ -879,24 +1337,49 @@
 	}
 
 	/* ca training(LPDDR4,LPDDR3 support) */
-	if ((training_flag & PI_CA_TRAINING) == PI_CA_TRAINING)
-		data_training_ca(chan, channel, sdram_params);
+	if ((training_flag & PI_CA_TRAINING) == PI_CA_TRAINING) {
+		ret = data_training_ca(chan, channel, params);
+		if (ret < 0) {
+			debug("%s: data training ca failed\n", __func__);
+			return ret;
+		}
+	}
 
 	/* write leveling(LPDDR4,LPDDR3,DDR3 support) */
-	if ((training_flag & PI_WRITE_LEVELING) == PI_WRITE_LEVELING)
-		data_training_wl(chan, channel, sdram_params);
+	if ((training_flag & PI_WRITE_LEVELING) == PI_WRITE_LEVELING) {
+		ret = data_training_wl(chan, channel, params);
+		if (ret < 0) {
+			debug("%s: data training wl failed\n", __func__);
+			return ret;
+		}
+	}
 
 	/* read gate training(LPDDR4,LPDDR3,DDR3 support) */
-	if ((training_flag & PI_READ_GATE_TRAINING) == PI_READ_GATE_TRAINING)
-		data_training_rg(chan, channel, sdram_params);
+	if ((training_flag & PI_READ_GATE_TRAINING) == PI_READ_GATE_TRAINING) {
+		ret = data_training_rg(chan, channel, params);
+		if (ret < 0) {
+			debug("%s: data training rg failed\n", __func__);
+			return ret;
+		}
+	}
 
 	/* read leveling(LPDDR4,LPDDR3,DDR3 support) */
-	if ((training_flag & PI_READ_LEVELING) == PI_READ_LEVELING)
-		data_training_rl(chan, channel, sdram_params);
+	if ((training_flag & PI_READ_LEVELING) == PI_READ_LEVELING) {
+		ret = data_training_rl(chan, channel, params);
+		if (ret < 0) {
+			debug("%s: data training rl failed\n", __func__);
+			return ret;
+		}
+	}
 
 	/* wdq leveling(LPDDR4 support) */
-	if ((training_flag & PI_WDQ_LEVELING) == PI_WDQ_LEVELING)
-		data_training_wdql(chan, channel, sdram_params);
+	if ((training_flag & PI_WDQ_LEVELING) == PI_WDQ_LEVELING) {
+		ret = data_training_wdql(chan, channel, params);
+		if (ret < 0) {
+			debug("%s: data training wdql failed\n", __func__);
+			return ret;
+		}
+	}
 
 	/* PHY_927 PHY_PAD_DQS_DRIVE  RPULL offset_22 */
 	clrbits_le32(&denali_phy[927], (1 << 22));
@@ -905,7 +1388,7 @@
 }
 
 static void set_ddrconfig(const struct chan_info *chan,
-			  const struct rk3399_sdram_params *sdram_params,
+			  const struct rk3399_sdram_params *params,
 			  unsigned char channel, u32 ddrconfig)
 {
 	/* only need to set ddrconfig */
@@ -913,14 +1396,14 @@
 	unsigned int cs0_cap = 0;
 	unsigned int cs1_cap = 0;
 
-	cs0_cap = (1 << (sdram_params->ch[channel].cs0_row
-			+ sdram_params->ch[channel].col
-			+ sdram_params->ch[channel].bk
-			+ sdram_params->ch[channel].bw - 20));
-	if (sdram_params->ch[channel].rank > 1)
-		cs1_cap = cs0_cap >> (sdram_params->ch[channel].cs0_row
-				- sdram_params->ch[channel].cs1_row);
-	if (sdram_params->ch[channel].row_3_4) {
+	cs0_cap = (1 << (params->ch[channel].cap_info.cs0_row
+			+ params->ch[channel].cap_info.col
+			+ params->ch[channel].cap_info.bk
+			+ params->ch[channel].cap_info.bw - 20));
+	if (params->ch[channel].cap_info.rank > 1)
+		cs1_cap = cs0_cap >> (params->ch[channel].cap_info.cs0_row
+				- params->ch[channel].cap_info.cs1_row);
+	if (params->ch[channel].cap_info.row_3_4) {
 		cs0_cap = cs0_cap * 3 / 4;
 		cs1_cap = cs1_cap * 3 / 4;
 	}
@@ -931,57 +1414,72 @@
 }
 
 static void dram_all_config(struct dram_info *dram,
-			    const struct rk3399_sdram_params *sdram_params)
+			    const struct rk3399_sdram_params *params)
 {
-	u32 sys_reg = 0;
+	u32 sys_reg2 = 0;
+	u32 sys_reg3 = 0;
 	unsigned int channel, idx;
 
-	sys_reg |= sdram_params->base.dramtype << SYS_REG_DDRTYPE_SHIFT;
-	sys_reg |= (sdram_params->base.num_channels - 1)
-		    << SYS_REG_NUM_CH_SHIFT;
+	sys_reg2 |= SYS_REG_ENC_DDRTYPE(params->base.dramtype);
+	sys_reg2 |= SYS_REG_ENC_NUM_CH(params->base.num_channels);
+
 	for (channel = 0, idx = 0;
-	     (idx < sdram_params->base.num_channels) && (channel < 2);
+	     (idx < params->base.num_channels) && (channel < 2);
 	     channel++) {
-		const struct rk3399_sdram_channel *info =
-			&sdram_params->ch[channel];
+		const struct rk3399_sdram_channel *info = &params->ch[channel];
 		struct rk3399_msch_regs *ddr_msch_regs;
 		const struct rk3399_msch_timings *noc_timing;
 
-		if (sdram_params->ch[channel].col == 0)
+		if (params->ch[channel].cap_info.col == 0)
 			continue;
 		idx++;
-		sys_reg |= info->row_3_4 << SYS_REG_ROW_3_4_SHIFT(channel);
-		sys_reg |= 1 << SYS_REG_CHINFO_SHIFT(channel);
-		sys_reg |= (info->rank - 1) << SYS_REG_RANK_SHIFT(channel);
-		sys_reg |= (info->col - 9) << SYS_REG_COL_SHIFT(channel);
-		sys_reg |= info->bk == 3 ? 0 : 1 << SYS_REG_BK_SHIFT(channel);
-		sys_reg |= (info->cs0_row - 13) << SYS_REG_CS0_ROW_SHIFT(channel);
-		sys_reg |= (info->cs1_row - 13) << SYS_REG_CS1_ROW_SHIFT(channel);
-		sys_reg |= (2 >> info->bw) << SYS_REG_BW_SHIFT(channel);
-		sys_reg |= (2 >> info->dbw) << SYS_REG_DBW_SHIFT(channel);
+		sys_reg2 |= SYS_REG_ENC_ROW_3_4(info->cap_info.row_3_4, channel);
+		sys_reg2 |= SYS_REG_ENC_CHINFO(channel);
+		sys_reg2 |= SYS_REG_ENC_RANK(info->cap_info.rank, channel);
+		sys_reg2 |= SYS_REG_ENC_COL(info->cap_info.col, channel);
+		sys_reg2 |= SYS_REG_ENC_BK(info->cap_info.bk, channel);
+		sys_reg2 |= SYS_REG_ENC_BW(info->cap_info.bw, channel);
+		sys_reg2 |= SYS_REG_ENC_DBW(info->cap_info.dbw, channel);
+		SYS_REG_ENC_CS0_ROW(info->cap_info.cs0_row, sys_reg2, sys_reg3, channel);
+		if (info->cap_info.cs1_row)
+			SYS_REG_ENC_CS1_ROW(info->cap_info.cs1_row, sys_reg2,
+					    sys_reg3, channel);
+		sys_reg3 |= SYS_REG_ENC_CS1_COL(info->cap_info.col, channel);
+		sys_reg3 |= SYS_REG_ENC_VERSION(DDR_SYS_REG_VERSION);
 
 		ddr_msch_regs = dram->chan[channel].msch;
-		noc_timing = &sdram_params->ch[channel].noc_timings;
+		noc_timing = &params->ch[channel].noc_timings;
 		writel(noc_timing->ddrtiminga0,
 		       &ddr_msch_regs->ddrtiminga0);
 		writel(noc_timing->ddrtimingb0,
 		       &ddr_msch_regs->ddrtimingb0);
-		writel(noc_timing->ddrtimingc0,
+		writel(noc_timing->ddrtimingc0.d32,
 		       &ddr_msch_regs->ddrtimingc0);
 		writel(noc_timing->devtodev0,
 		       &ddr_msch_regs->devtodev0);
-		writel(noc_timing->ddrmode,
+		writel(noc_timing->ddrmode.d32,
 		       &ddr_msch_regs->ddrmode);
 
-		/* rank 1 memory clock disable (dfi_dram_clk_disable = 1) */
-		if (sdram_params->ch[channel].rank == 1)
+		/**
+		 * rank 1 memory clock disable (dfi_dram_clk_disable = 1)
+		 *
+		 * The hardware for LPDDR4 with
+		 * - CLK0P/N connect to lower 16-bits
+		 * - CLK1P/N connect to higher 16-bits
+		 *
+		 * dfi dram clk is configured via CLK1P/N, so disabling
+		 * dfi dram clk will disable the CLK1P/N as well for lpddr4.
+		 */
+		if (params->ch[channel].cap_info.rank == 1 &&
+		    params->base.dramtype != LPDDR4)
 			setbits_le32(&dram->chan[channel].pctl->denali_ctl[276],
 				     1 << 17);
 	}
 
-	writel(sys_reg, &dram->pmugrf->os_reg2);
+	writel(sys_reg2, &dram->pmugrf->os_reg2);
+	writel(sys_reg3, &dram->pmugrf->os_reg3);
 	rk_clrsetreg(&dram->pmusgrf->soc_con4, 0x1f << 10,
-		     sdram_params->base.stride << 10);
+		     params->base.stride << 10);
 
 	/* reboot hold register set */
 	writel(PRESET_SGRF_HOLD(0) | PRESET_GPIO0_HOLD(1) |
@@ -990,12 +1488,30 @@
 	clrsetbits_le32(&dram->cru->glb_rst_con, 0x3, 0x3);
 }
 
+#if !defined(CONFIG_RAM_RK3399_LPDDR4)
+static int default_data_training(struct dram_info *dram, u32 channel, u8 rank,
+				 struct rk3399_sdram_params *params)
+{
+	u8 training_flag = PI_READ_GATE_TRAINING;
+
+	/*
+	 * LPDDR3 CA training msut be trigger before
+	 * other training.
+	 * DDR3 is not have CA training.
+	 */
+
+	if (params->base.dramtype == LPDDR3)
+		training_flag |= PI_CA_TRAINING;
+
+	return data_training(dram, channel, params, training_flag);
+}
+
 static int switch_to_phy_index1(struct dram_info *dram,
-				 const struct rk3399_sdram_params *sdram_params)
+				struct rk3399_sdram_params *params)
 {
 	u32 channel;
 	u32 *denali_phy;
-	u32 ch_count = sdram_params->base.num_channels;
+	u32 ch_count = params->base.num_channels;
 	int ret;
 	int i = 0;
 
@@ -1025,9 +1541,8 @@
 	for (channel = 0; channel < ch_count; channel++) {
 		denali_phy = dram->chan[channel].publ->denali_phy;
 		clrsetbits_le32(&denali_phy[896], (0x3 << 8) | 1, 1 << 8);
-		ret = data_training(&dram->chan[channel], channel,
-				  sdram_params, PI_FULL_TRAINING);
-		if (ret) {
+		ret = data_training(dram, channel, params, PI_FULL_TRAINING);
+		if (ret < 0) {
 			debug("index1 training failed\n");
 			return ret;
 		}
@@ -1036,12 +1551,979 @@
 	return 0;
 }
 
-static int sdram_init(struct dram_info *dram,
-		      const struct rk3399_sdram_params *sdram_params)
-{
-	unsigned char dramtype = sdram_params->base.dramtype;
-	unsigned int ddr_freq = sdram_params->base.ddr_freq;
-	int channel;
+#else
+
+struct rk3399_sdram_params lpddr4_timings[] = {
+	#include "sdram-rk3399-lpddr4-400.inc"
+	#include "sdram-rk3399-lpddr4-800.inc"
+};
+
+static void *get_denali_pi(const struct chan_info *chan,
+			   struct rk3399_sdram_params *params, bool reg)
+{
+	return reg ? &chan->pi->denali_pi : &params->pi_regs.denali_pi;
+}
+
+static u32 lpddr4_get_phy(struct rk3399_sdram_params *params, u32 ctl)
+{
+	u32 lpddr4_phy[] = {1, 0, 0xb};
+
+	return lpddr4_phy[ctl];
+}
+
+static u32 lpddr4_get_ctl(struct rk3399_sdram_params *params, u32 phy)
+{
+	u32 lpddr4_ctl[] = {1, 0, 2};
+
+	return lpddr4_ctl[phy];
+}
+
+static u32 get_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf)
+{
+	return ((readl(&pmusgrf->soc_con4) >> 10) & 0x1F);
+}
+
+static void set_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf, u32 stride)
+{
+	rk_clrsetreg(&pmusgrf->soc_con4, 0x1f << 10, stride << 10);
+}
+
+static void set_cap_relate_config(const struct chan_info *chan,
+				  struct rk3399_sdram_params *params,
+				  unsigned int channel)
+{
+	u32 *denali_ctl = chan->pctl->denali_ctl;
+	u32 tmp;
+	struct rk3399_msch_timings *noc_timing;
+
+	if (params->base.dramtype == LPDDR3) {
+		tmp = (8 << params->ch[channel].cap_info.bw) /
+			(8 << params->ch[channel].cap_info.dbw);
+
+		/**
+		 * memdata_ratio
+		 * 1 -> 0, 2 -> 1, 4 -> 2
+		 */
+		clrsetbits_le32(&denali_ctl[197], 0x7,
+				(tmp >> 1));
+		clrsetbits_le32(&denali_ctl[198], 0x7 << 8,
+				(tmp >> 1) << 8);
+	}
+
+	noc_timing = &params->ch[channel].noc_timings;
+
+	/*
+	 * noc timing bw relate timing is 32 bit, and real bw is 16bit
+	 * actually noc reg is setting at function dram_all_config
+	 */
+	if (params->ch[channel].cap_info.bw == 16 &&
+	    noc_timing->ddrmode.b.mwrsize == 2) {
+		if (noc_timing->ddrmode.b.burstsize)
+			noc_timing->ddrmode.b.burstsize -= 1;
+		noc_timing->ddrmode.b.mwrsize -= 1;
+		noc_timing->ddrtimingc0.b.burstpenalty *= 2;
+		noc_timing->ddrtimingc0.b.wrtomwr *= 2;
+	}
+}
+
+static u32 calculate_ddrconfig(struct rk3399_sdram_params *params, u32 channel)
+{
+	unsigned int cs0_row = params->ch[channel].cap_info.cs0_row;
+	unsigned int col = params->ch[channel].cap_info.col;
+	unsigned int bw = params->ch[channel].cap_info.bw;
+	u16  ddr_cfg_2_rbc[] = {
+		/*
+		 * [6]	  highest bit col
+		 * [5:3]  max row(14+n)
+		 * [2]    insertion row
+		 * [1:0]  col(9+n),col, data bus 32bit
+		 *
+		 * highbitcol, max_row, insertion_row,  col
+		 */
+		((0 << 6) | (2 << 3) | (0 << 2) | 0), /* 0 */
+		((0 << 6) | (2 << 3) | (0 << 2) | 1), /* 1 */
+		((0 << 6) | (1 << 3) | (0 << 2) | 2), /* 2 */
+		((0 << 6) | (0 << 3) | (0 << 2) | 3), /* 3 */
+		((0 << 6) | (2 << 3) | (1 << 2) | 1), /* 4 */
+		((0 << 6) | (1 << 3) | (1 << 2) | 2), /* 5 */
+		((1 << 6) | (0 << 3) | (0 << 2) | 2), /* 6 */
+		((1 << 6) | (1 << 3) | (0 << 2) | 2), /* 7 */
+	};
+	u32 i;
+
+	col -= (bw == 2) ? 0 : 1;
+	col -= 9;
+
+	for (i = 0; i < 4; i++) {
+		if ((col == (ddr_cfg_2_rbc[i] & 0x3)) &&
+		    (cs0_row <= (((ddr_cfg_2_rbc[i] >> 3) & 0x7) + 14)))
+			break;
+	}
+
+	if (i >= 4)
+		i = -EINVAL;
+
+	return i;
+}
+
+/**
+ * read mr_num mode register
+ * rank = 1: cs0
+ * rank = 2: cs1
+ */
+static int read_mr(struct rk3399_ddr_pctl_regs *ddr_pctl_regs, u32 rank,
+		   u32 mr_num, u32 *buf)
+{
+	s32 timeout = 100;
+
+	writel(((1 << 16) | (((rank == 2) ? 1 : 0) << 8) | mr_num) << 8,
+	       &ddr_pctl_regs->denali_ctl[118]);
+
+	while (0 == (readl(&ddr_pctl_regs->denali_ctl[203]) &
+			((1 << 21) | (1 << 12)))) {
+		udelay(1);
+
+		if (timeout <= 0) {
+			printf("%s: pctl timeout!\n", __func__);
+			return -ETIMEDOUT;
+		}
+
+		timeout--;
+	}
+
+	if (!(readl(&ddr_pctl_regs->denali_ctl[203]) & (1 << 12))) {
+		*buf = readl(&ddr_pctl_regs->denali_ctl[119]) & 0xFF;
+	} else {
+		printf("%s: read mr failed with 0x%x status\n", __func__,
+		       readl(&ddr_pctl_regs->denali_ctl[17]) & 0x3);
+		*buf = 0;
+	}
+
+	setbits_le32(&ddr_pctl_regs->denali_ctl[205], (1 << 21) | (1 << 12));
+
+	return 0;
+}
+
+static int lpddr4_mr_detect(struct dram_info *dram, u32 channel, u8 rank,
+			    struct rk3399_sdram_params *params)
+{
+	u64 cs0_cap;
+	u32 stride;
+	u32 cs = 0, col = 0, bk = 0, bw = 0, row_3_4 = 0;
+	u32 cs0_row = 0, cs1_row = 0, ddrconfig = 0;
+	u32 mr5, mr12, mr14;
+	struct chan_info *chan = &dram->chan[channel];
+	struct rk3399_ddr_pctl_regs *ddr_pctl_regs = chan->pctl;
+	void __iomem *addr = NULL;
+	int ret = 0;
+	u32 val;
+
+	stride = get_ddr_stride(dram->pmusgrf);
+
+	if (params->ch[channel].cap_info.col == 0) {
+		ret = -EPERM;
+		goto end;
+	}
+
+	cs = params->ch[channel].cap_info.rank;
+	col = params->ch[channel].cap_info.col;
+	bk = params->ch[channel].cap_info.bk;
+	bw = params->ch[channel].cap_info.bw;
+	row_3_4 = params->ch[channel].cap_info.row_3_4;
+	cs0_row = params->ch[channel].cap_info.cs0_row;
+	cs1_row = params->ch[channel].cap_info.cs1_row;
+	ddrconfig = params->ch[channel].cap_info.ddrconfig;
+
+	/* 2GB */
+	params->ch[channel].cap_info.rank = 2;
+	params->ch[channel].cap_info.col = 10;
+	params->ch[channel].cap_info.bk = 3;
+	params->ch[channel].cap_info.bw = 2;
+	params->ch[channel].cap_info.row_3_4 = 0;
+	params->ch[channel].cap_info.cs0_row = 15;
+	params->ch[channel].cap_info.cs1_row = 15;
+	params->ch[channel].cap_info.ddrconfig = 1;
+
+	set_memory_map(chan, channel, params);
+	params->ch[channel].cap_info.ddrconfig =
+			calculate_ddrconfig(params, channel);
+	set_ddrconfig(chan, params, channel,
+		      params->ch[channel].cap_info.ddrconfig);
+	set_cap_relate_config(chan, params, channel);
+
+	cs0_cap = (1 << (params->ch[channel].cap_info.bw
+			+ params->ch[channel].cap_info.col
+			+ params->ch[channel].cap_info.bk
+			+ params->ch[channel].cap_info.cs0_row));
+
+	if (params->ch[channel].cap_info.row_3_4)
+		cs0_cap = cs0_cap * 3 / 4;
+
+	if (channel == 0)
+		set_ddr_stride(dram->pmusgrf, 0x17);
+	else
+		set_ddr_stride(dram->pmusgrf, 0x18);
+
+	/* read and write data to DRAM, avoid be optimized by compiler. */
+	if (rank == 1)
+		addr = (void __iomem *)0x100;
+	else if (rank == 2)
+		addr = (void __iomem *)(cs0_cap + 0x100);
+
+	val = readl(addr);
+	writel(val + 1, addr);
+
+	read_mr(ddr_pctl_regs, rank, 5, &mr5);
+	read_mr(ddr_pctl_regs, rank, 12, &mr12);
+	read_mr(ddr_pctl_regs, rank, 14, &mr14);
+
+	if (mr5 == 0 || mr12 != 0x4d || mr14 != 0x4d) {
+		ret = -EINVAL;
+		goto end;
+	}
+end:
+	params->ch[channel].cap_info.rank = cs;
+	params->ch[channel].cap_info.col = col;
+	params->ch[channel].cap_info.bk = bk;
+	params->ch[channel].cap_info.bw = bw;
+	params->ch[channel].cap_info.row_3_4 = row_3_4;
+	params->ch[channel].cap_info.cs0_row = cs0_row;
+	params->ch[channel].cap_info.cs1_row = cs1_row;
+	params->ch[channel].cap_info.ddrconfig = ddrconfig;
+
+	set_ddr_stride(dram->pmusgrf, stride);
+
+	return ret;
+}
+
+static void set_lpddr4_dq_odt(const struct chan_info *chan,
+			      struct rk3399_sdram_params *params, u32 ctl,
+			      bool en, bool ctl_phy_reg, u32 mr5)
+{
+	u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);
+	u32 *denali_pi = get_denali_pi(chan, params, ctl_phy_reg);
+	struct io_setting *io;
+	u32 reg_value;
+
+	if (!en)
+		return;
+
+	io = lpddr4_get_io_settings(params, mr5);
+
+	reg_value = io->dq_odt;
+
+	switch (ctl) {
+	case 0:
+		clrsetbits_le32(&denali_ctl[139], 0x7 << 24, reg_value << 24);
+		clrsetbits_le32(&denali_ctl[153], 0x7 << 24, reg_value << 24);
+
+		clrsetbits_le32(&denali_pi[132], 0x7 << 0, (reg_value << 0));
+		clrsetbits_le32(&denali_pi[139], 0x7 << 16, (reg_value << 16));
+		clrsetbits_le32(&denali_pi[147], 0x7 << 0, (reg_value << 0));
+		clrsetbits_le32(&denali_pi[154], 0x7 << 16, (reg_value << 16));
+		break;
+	case 1:
+		clrsetbits_le32(&denali_ctl[140], 0x7 << 0, reg_value << 0);
+		clrsetbits_le32(&denali_ctl[154], 0x7 << 0, reg_value << 0);
+
+		clrsetbits_le32(&denali_pi[129], 0x7 << 16, (reg_value << 16));
+		clrsetbits_le32(&denali_pi[137], 0x7 << 0, (reg_value << 0));
+		clrsetbits_le32(&denali_pi[144], 0x7 << 16, (reg_value << 16));
+		clrsetbits_le32(&denali_pi[152], 0x7 << 0, (reg_value << 0));
+		break;
+	case 2:
+	default:
+		clrsetbits_le32(&denali_ctl[140], 0x7 << 8, (reg_value << 8));
+		clrsetbits_le32(&denali_ctl[154], 0x7 << 8, (reg_value << 8));
+
+		clrsetbits_le32(&denali_pi[127], 0x7 << 0, (reg_value << 0));
+		clrsetbits_le32(&denali_pi[134], 0x7 << 16, (reg_value << 16));
+		clrsetbits_le32(&denali_pi[142], 0x7 << 0, (reg_value << 0));
+		clrsetbits_le32(&denali_pi[149], 0x7 << 16, (reg_value << 16));
+		break;
+	}
+}
+
+static void set_lpddr4_ca_odt(const struct chan_info *chan,
+			      struct rk3399_sdram_params *params, u32 ctl,
+			      bool en, bool ctl_phy_reg, u32 mr5)
+{
+	u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);
+	u32 *denali_pi = get_denali_pi(chan, params, ctl_phy_reg);
+	struct io_setting *io;
+	u32 reg_value;
+
+	if (!en)
+		return;
+
+	io = lpddr4_get_io_settings(params, mr5);
+
+	reg_value = io->ca_odt;
+
+	switch (ctl) {
+	case 0:
+		clrsetbits_le32(&denali_ctl[139], 0x7 << 28, reg_value << 28);
+		clrsetbits_le32(&denali_ctl[153], 0x7 << 28, reg_value << 28);
+
+		clrsetbits_le32(&denali_pi[132], 0x7 << 4, reg_value << 4);
+		clrsetbits_le32(&denali_pi[139], 0x7 << 20, reg_value << 20);
+		clrsetbits_le32(&denali_pi[147], 0x7 << 4, reg_value << 4);
+		clrsetbits_le32(&denali_pi[154], 0x7 << 20, reg_value << 20);
+		break;
+	case 1:
+		clrsetbits_le32(&denali_ctl[140], 0x7 << 4, reg_value << 4);
+		clrsetbits_le32(&denali_ctl[154], 0x7 << 4, reg_value << 4);
+
+		clrsetbits_le32(&denali_pi[129], 0x7 << 20, reg_value << 20);
+		clrsetbits_le32(&denali_pi[137], 0x7 << 4, reg_value << 4);
+		clrsetbits_le32(&denali_pi[144], 0x7 << 20, reg_value << 20);
+		clrsetbits_le32(&denali_pi[152], 0x7 << 4, reg_value << 4);
+		break;
+	case 2:
+	default:
+		clrsetbits_le32(&denali_ctl[140], 0x7 << 12, (reg_value << 12));
+		clrsetbits_le32(&denali_ctl[154], 0x7 << 12, (reg_value << 12));
+
+		clrsetbits_le32(&denali_pi[127], 0x7 << 4, reg_value << 4);
+		clrsetbits_le32(&denali_pi[134], 0x7 << 20, reg_value << 20);
+		clrsetbits_le32(&denali_pi[142], 0x7 << 4, reg_value << 4);
+		clrsetbits_le32(&denali_pi[149], 0x7 << 20, reg_value << 20);
+		break;
+	}
+}
+
+static void set_lpddr4_MR3(const struct chan_info *chan,
+			   struct rk3399_sdram_params *params, u32 ctl,
+			   bool ctl_phy_reg, u32 mr5)
+{
+	u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);
+	u32 *denali_pi = get_denali_pi(chan, params, ctl_phy_reg);
+	struct io_setting *io;
+	u32 reg_value;
+
+	io = lpddr4_get_io_settings(params, mr5);
+
+	reg_value = ((io->pdds << 3) | 1);
+
+	switch (ctl) {
+	case 0:
+		clrsetbits_le32(&denali_ctl[138], 0xFFFF, reg_value);
+		clrsetbits_le32(&denali_ctl[152], 0xFFFF, reg_value);
+
+		clrsetbits_le32(&denali_pi[131], 0xFFFF << 16, reg_value << 16);
+		clrsetbits_le32(&denali_pi[139], 0xFFFF, reg_value);
+		clrsetbits_le32(&denali_pi[146], 0xFFFF << 16, reg_value << 16);
+		clrsetbits_le32(&denali_pi[154], 0xFFFF, reg_value);
+		break;
+	case 1:
+		clrsetbits_le32(&denali_ctl[138], 0xFFFF << 16,
+				reg_value << 16);
+		clrsetbits_le32(&denali_ctl[152], 0xFFFF << 16,
+				reg_value << 16);
+
+		clrsetbits_le32(&denali_pi[129], 0xFFFF, reg_value);
+		clrsetbits_le32(&denali_pi[136], 0xFFFF << 16, reg_value << 16);
+		clrsetbits_le32(&denali_pi[144], 0xFFFF, reg_value);
+		clrsetbits_le32(&denali_pi[151], 0xFFFF << 16, reg_value << 16);
+		break;
+	case 2:
+	default:
+		clrsetbits_le32(&denali_ctl[139], 0xFFFF, reg_value);
+		clrsetbits_le32(&denali_ctl[153], 0xFFFF, reg_value);
+
+		clrsetbits_le32(&denali_pi[126], 0xFFFF << 16, reg_value << 16);
+		clrsetbits_le32(&denali_pi[134], 0xFFFF, reg_value);
+		clrsetbits_le32(&denali_pi[141], 0xFFFF << 16, reg_value << 16);
+		clrsetbits_le32(&denali_pi[149], 0xFFFF, reg_value);
+		break;
+	}
+}
+
+static void set_lpddr4_MR12(const struct chan_info *chan,
+			    struct rk3399_sdram_params *params, u32 ctl,
+			    bool ctl_phy_reg, u32 mr5)
+{
+	u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);
+	u32 *denali_pi = get_denali_pi(chan, params, ctl_phy_reg);
+	struct io_setting *io;
+	u32 reg_value;
+
+	io = lpddr4_get_io_settings(params, mr5);
+
+	reg_value = io->ca_vref;
+
+	switch (ctl) {
+	case 0:
+		clrsetbits_le32(&denali_ctl[140], 0xFFFF << 16,
+				reg_value << 16);
+		clrsetbits_le32(&denali_ctl[154], 0xFFFF << 16,
+				reg_value << 16);
+
+		clrsetbits_le32(&denali_pi[132], 0xFF << 8, reg_value << 8);
+		clrsetbits_le32(&denali_pi[139], 0xFF << 24, reg_value << 24);
+		clrsetbits_le32(&denali_pi[147], 0xFF << 8, reg_value << 8);
+		clrsetbits_le32(&denali_pi[154], 0xFF << 24, reg_value << 24);
+		break;
+	case 1:
+		clrsetbits_le32(&denali_ctl[141], 0xFFFF, reg_value);
+		clrsetbits_le32(&denali_ctl[155], 0xFFFF, reg_value);
+
+		clrsetbits_le32(&denali_pi[129], 0xFF << 24, reg_value << 24);
+		clrsetbits_le32(&denali_pi[137], 0xFF << 8, reg_value << 8);
+		clrsetbits_le32(&denali_pi[144], 0xFF << 24, reg_value << 24);
+		clrsetbits_le32(&denali_pi[152], 0xFF << 8, reg_value << 8);
+		break;
+	case 2:
+	default:
+		clrsetbits_le32(&denali_ctl[141], 0xFFFF << 16,
+				reg_value << 16);
+		clrsetbits_le32(&denali_ctl[155], 0xFFFF << 16,
+				reg_value << 16);
+
+		clrsetbits_le32(&denali_pi[127], 0xFF << 8, reg_value << 8);
+		clrsetbits_le32(&denali_pi[134], 0xFF << 24, reg_value << 24);
+		clrsetbits_le32(&denali_pi[142], 0xFF << 8, reg_value << 8);
+		clrsetbits_le32(&denali_pi[149], 0xFF << 24, reg_value << 24);
+		break;
+	}
+}
+
+static void set_lpddr4_MR14(const struct chan_info *chan,
+			    struct rk3399_sdram_params *params, u32 ctl,
+			    bool ctl_phy_reg, u32 mr5)
+{
+	u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);
+	u32 *denali_pi = get_denali_pi(chan, params, ctl_phy_reg);
+	struct io_setting *io;
+	u32 reg_value;
+
+	io = lpddr4_get_io_settings(params, mr5);
+
+	reg_value = io->dq_vref;
+
+	switch (ctl) {
+	case 0:
+		clrsetbits_le32(&denali_ctl[142], 0xFFFF << 16,
+				reg_value << 16);
+		clrsetbits_le32(&denali_ctl[156], 0xFFFF << 16,
+				reg_value << 16);
+
+		clrsetbits_le32(&denali_pi[132], 0xFF << 16, reg_value << 16);
+		clrsetbits_le32(&denali_pi[140], 0xFF << 0, reg_value << 0);
+		clrsetbits_le32(&denali_pi[147], 0xFF << 16, reg_value << 16);
+		clrsetbits_le32(&denali_pi[155], 0xFF << 0, reg_value << 0);
+		break;
+	case 1:
+		clrsetbits_le32(&denali_ctl[143], 0xFFFF, reg_value);
+		clrsetbits_le32(&denali_ctl[157], 0xFFFF, reg_value);
+
+		clrsetbits_le32(&denali_pi[130], 0xFF << 0, reg_value << 0);
+		clrsetbits_le32(&denali_pi[137], 0xFF << 16, reg_value << 16);
+		clrsetbits_le32(&denali_pi[145], 0xFF << 0, reg_value << 0);
+		clrsetbits_le32(&denali_pi[152], 0xFF << 16, reg_value << 16);
+		break;
+	case 2:
+	default:
+		clrsetbits_le32(&denali_ctl[143], 0xFFFF << 16,
+				reg_value << 16);
+		clrsetbits_le32(&denali_ctl[157], 0xFFFF << 16,
+				reg_value << 16);
+
+		clrsetbits_le32(&denali_pi[127], 0xFF << 16, reg_value << 16);
+		clrsetbits_le32(&denali_pi[135], 0xFF << 0, reg_value << 0);
+		clrsetbits_le32(&denali_pi[142], 0xFF << 16, reg_value << 16);
+		clrsetbits_le32(&denali_pi[150], 0xFF << 0, reg_value << 0);
+		break;
+	}
+}
+
+static void lpddr4_copy_phy(struct dram_info *dram,
+			    struct rk3399_sdram_params *params, u32 phy,
+			    struct rk3399_sdram_params *timings,
+			    u32 channel)
+{
+	u32 *denali_ctl, *denali_phy;
+	u32 *denali_phy_params;
+	u32 speed = 0;
+	u32 ctl, mr5;
+
+	denali_ctl = dram->chan[channel].pctl->denali_ctl;
+	denali_phy = dram->chan[channel].publ->denali_phy;
+	denali_phy_params = timings->phy_regs.denali_phy;
+
+	/* switch index */
+	clrsetbits_le32(&denali_phy_params[896], 0x3 << 8, phy << 8);
+	writel(denali_phy_params[896], &denali_phy[896]);
+
+	/* phy_pll_ctrl_ca, phy_pll_ctrl */
+	writel(denali_phy_params[911], &denali_phy[911]);
+
+	/* phy_low_freq_sel */
+	clrsetbits_le32(&denali_phy[913], 0x1,
+			denali_phy_params[913] & 0x1);
+
+	/* phy_grp_slave_delay_x, phy_cslvl_dly_step */
+	writel(denali_phy_params[916], &denali_phy[916]);
+	writel(denali_phy_params[917], &denali_phy[917]);
+	writel(denali_phy_params[918], &denali_phy[918]);
+
+	/* phy_adrz_sw_wraddr_shift_x  */
+	writel(denali_phy_params[512], &denali_phy[512]);
+	clrsetbits_le32(&denali_phy[513], 0xffff,
+			denali_phy_params[513] & 0xffff);
+	writel(denali_phy_params[640], &denali_phy[640]);
+	clrsetbits_le32(&denali_phy[641], 0xffff,
+			denali_phy_params[641] & 0xffff);
+	writel(denali_phy_params[768], &denali_phy[768]);
+	clrsetbits_le32(&denali_phy[769], 0xffff,
+			denali_phy_params[769] & 0xffff);
+
+	writel(denali_phy_params[544], &denali_phy[544]);
+	writel(denali_phy_params[545], &denali_phy[545]);
+	writel(denali_phy_params[546], &denali_phy[546]);
+	writel(denali_phy_params[547], &denali_phy[547]);
+
+	writel(denali_phy_params[672], &denali_phy[672]);
+	writel(denali_phy_params[673], &denali_phy[673]);
+	writel(denali_phy_params[674], &denali_phy[674]);
+	writel(denali_phy_params[675], &denali_phy[675]);
+
+	writel(denali_phy_params[800], &denali_phy[800]);
+	writel(denali_phy_params[801], &denali_phy[801]);
+	writel(denali_phy_params[802], &denali_phy[802]);
+	writel(denali_phy_params[803], &denali_phy[803]);
+
+	/*
+	 * phy_adr_master_delay_start_x
+	 * phy_adr_master_delay_step_x
+	 * phy_adr_master_delay_wait_x
+	 */
+	writel(denali_phy_params[548], &denali_phy[548]);
+	writel(denali_phy_params[676], &denali_phy[676]);
+	writel(denali_phy_params[804], &denali_phy[804]);
+
+	/* phy_adr_calvl_dly_step_x */
+	writel(denali_phy_params[549], &denali_phy[549]);
+	writel(denali_phy_params[677], &denali_phy[677]);
+	writel(denali_phy_params[805], &denali_phy[805]);
+
+	/*
+	 * phy_clk_wrdm_slave_delay_x
+	 * phy_clk_wrdqz_slave_delay_x
+	 * phy_clk_wrdqs_slave_delay_x
+	 */
+	copy_to_reg((u32 *)&denali_phy[59], (u32 *)&denali_phy_params[59],
+		    (63 - 58) * 4);
+	copy_to_reg((u32 *)&denali_phy[187], (u32 *)&denali_phy_params[187],
+		    (191 - 186) * 4);
+	copy_to_reg((u32 *)&denali_phy[315], (u32 *)&denali_phy_params[315],
+		    (319 - 314) * 4);
+	copy_to_reg((u32 *)&denali_phy[443], (u32 *)&denali_phy_params[443],
+		    (447 - 442) * 4);
+
+	/*
+	 * phy_dqs_tsel_wr_timing_x 8bits denali_phy_84/212/340/468 offset_8
+	 * dqs_tsel_wr_end[7:4] add half cycle
+	 * phy_dq_tsel_wr_timing_x 8bits denali_phy_83/211/339/467 offset_8
+	 * dq_tsel_wr_end[7:4] add half cycle
+	 */
+	writel(denali_phy_params[83] + (0x10 << 16), &denali_phy[83]);
+	writel(denali_phy_params[84] + (0x10 << 8), &denali_phy[84]);
+	writel(denali_phy_params[85], &denali_phy[85]);
+
+	writel(denali_phy_params[211] + (0x10 << 16), &denali_phy[211]);
+	writel(denali_phy_params[212] + (0x10 << 8), &denali_phy[212]);
+	writel(denali_phy_params[213], &denali_phy[213]);
+
+	writel(denali_phy_params[339] + (0x10 << 16), &denali_phy[339]);
+	writel(denali_phy_params[340] + (0x10 << 8), &denali_phy[340]);
+	writel(denali_phy_params[341], &denali_phy[341]);
+
+	writel(denali_phy_params[467] + (0x10 << 16), &denali_phy[467]);
+	writel(denali_phy_params[468] + (0x10 << 8), &denali_phy[468]);
+	writel(denali_phy_params[469], &denali_phy[469]);
+
+	/*
+	 * phy_gtlvl_resp_wait_cnt_x
+	 * phy_gtlvl_dly_step_x
+	 * phy_wrlvl_resp_wait_cnt_x
+	 * phy_gtlvl_final_step_x
+	 * phy_gtlvl_back_step_x
+	 * phy_rdlvl_dly_step_x
+	 *
+	 * phy_master_delay_step_x
+	 * phy_master_delay_wait_x
+	 * phy_wrlvl_dly_step_x
+	 * phy_rptr_update_x
+	 * phy_wdqlvl_dly_step_x
+	 */
+	writel(denali_phy_params[87], &denali_phy[87]);
+	writel(denali_phy_params[88], &denali_phy[88]);
+	writel(denali_phy_params[89], &denali_phy[89]);
+	writel(denali_phy_params[90], &denali_phy[90]);
+
+	writel(denali_phy_params[215], &denali_phy[215]);
+	writel(denali_phy_params[216], &denali_phy[216]);
+	writel(denali_phy_params[217], &denali_phy[217]);
+	writel(denali_phy_params[218], &denali_phy[218]);
+
+	writel(denali_phy_params[343], &denali_phy[343]);
+	writel(denali_phy_params[344], &denali_phy[344]);
+	writel(denali_phy_params[345], &denali_phy[345]);
+	writel(denali_phy_params[346], &denali_phy[346]);
+
+	writel(denali_phy_params[471], &denali_phy[471]);
+	writel(denali_phy_params[472], &denali_phy[472]);
+	writel(denali_phy_params[473], &denali_phy[473]);
+	writel(denali_phy_params[474], &denali_phy[474]);
+
+	/*
+	 * phy_gtlvl_lat_adj_start_x
+	 * phy_gtlvl_rddqs_slv_dly_start_x
+	 * phy_rdlvl_rddqs_dq_slv_dly_start_x
+	 * phy_wdqlvl_dqdm_slv_dly_start_x
+	 */
+	writel(denali_phy_params[80], &denali_phy[80]);
+	writel(denali_phy_params[81], &denali_phy[81]);
+
+	writel(denali_phy_params[208], &denali_phy[208]);
+	writel(denali_phy_params[209], &denali_phy[209]);
+
+	writel(denali_phy_params[336], &denali_phy[336]);
+	writel(denali_phy_params[337], &denali_phy[337]);
+
+	writel(denali_phy_params[464], &denali_phy[464]);
+	writel(denali_phy_params[465], &denali_phy[465]);
+
+	/*
+	 * phy_master_delay_start_x
+	 * phy_sw_master_mode_x
+	 * phy_rddata_en_tsel_dly_x
+	 */
+	writel(denali_phy_params[86], &denali_phy[86]);
+	writel(denali_phy_params[214], &denali_phy[214]);
+	writel(denali_phy_params[342], &denali_phy[342]);
+	writel(denali_phy_params[470], &denali_phy[470]);
+
+	/*
+	 * phy_rddqz_slave_delay_x
+	 * phy_rddqs_dqz_fall_slave_delay_x
+	 * phy_rddqs_dqz_rise_slave_delay_x
+	 * phy_rddqs_dm_fall_slave_delay_x
+	 * phy_rddqs_dm_rise_slave_delay_x
+	 * phy_rddqs_gate_slave_delay_x
+	 * phy_wrlvl_delay_early_threshold_x
+	 * phy_write_path_lat_add_x
+	 * phy_rddqs_latency_adjust_x
+	 * phy_wrlvl_delay_period_threshold_x
+	 * phy_wrlvl_early_force_zero_x
+	 */
+	copy_to_reg((u32 *)&denali_phy[64], (u32 *)&denali_phy_params[64],
+		    (67 - 63) * 4);
+	clrsetbits_le32(&denali_phy[68], 0xfffffc00,
+			denali_phy_params[68] & 0xfffffc00);
+	copy_to_reg((u32 *)&denali_phy[69], (u32 *)&denali_phy_params[69],
+		    (79 - 68) * 4);
+	copy_to_reg((u32 *)&denali_phy[192], (u32 *)&denali_phy_params[192],
+		    (195 - 191) * 4);
+	clrsetbits_le32(&denali_phy[196], 0xfffffc00,
+			denali_phy_params[196] & 0xfffffc00);
+	copy_to_reg((u32 *)&denali_phy[197], (u32 *)&denali_phy_params[197],
+		    (207 - 196) * 4);
+	copy_to_reg((u32 *)&denali_phy[320], (u32 *)&denali_phy_params[320],
+		    (323 - 319) * 4);
+	clrsetbits_le32(&denali_phy[324], 0xfffffc00,
+			denali_phy_params[324] & 0xfffffc00);
+	copy_to_reg((u32 *)&denali_phy[325], (u32 *)&denali_phy_params[325],
+		    (335 - 324) * 4);
+
+	copy_to_reg((u32 *)&denali_phy[448], (u32 *)&denali_phy_params[448],
+		    (451 - 447) * 4);
+	clrsetbits_le32(&denali_phy[452], 0xfffffc00,
+			denali_phy_params[452] & 0xfffffc00);
+	copy_to_reg((u32 *)&denali_phy[453], (u32 *)&denali_phy_params[453],
+		    (463 - 452) * 4);
+
+	/* phy_two_cyc_preamble_x */
+	clrsetbits_le32(&denali_phy[7], 0x3 << 24,
+			denali_phy_params[7] & (0x3 << 24));
+	clrsetbits_le32(&denali_phy[135], 0x3 << 24,
+			denali_phy_params[135] & (0x3 << 24));
+	clrsetbits_le32(&denali_phy[263], 0x3 << 24,
+			denali_phy_params[263] & (0x3 << 24));
+	clrsetbits_le32(&denali_phy[391], 0x3 << 24,
+			denali_phy_params[391] & (0x3 << 24));
+
+	/* speed */
+	if (timings->base.ddr_freq < 400 * MHz)
+		speed = 0x0;
+	else if (timings->base.ddr_freq < 800 * MHz)
+		speed = 0x1;
+	else if (timings->base.ddr_freq < 1200 * MHz)
+		speed = 0x2;
+
+	/* phy_924 phy_pad_fdbk_drive */
+	clrsetbits_le32(&denali_phy[924], 0x3 << 21, speed << 21);
+	/* phy_926 phy_pad_data_drive */
+	clrsetbits_le32(&denali_phy[926], 0x3 << 9, speed << 9);
+	/* phy_927 phy_pad_dqs_drive */
+	clrsetbits_le32(&denali_phy[927], 0x3 << 9, speed << 9);
+	/* phy_928 phy_pad_addr_drive */
+	clrsetbits_le32(&denali_phy[928], 0x3 << 17, speed << 17);
+	/* phy_929 phy_pad_clk_drive */
+	clrsetbits_le32(&denali_phy[929], 0x3 << 17, speed << 17);
+	/* phy_935 phy_pad_cke_drive */
+	clrsetbits_le32(&denali_phy[935], 0x3 << 17, speed << 17);
+	/* phy_937 phy_pad_rst_drive */
+	clrsetbits_le32(&denali_phy[937], 0x3 << 17, speed << 17);
+	/* phy_939 phy_pad_cs_drive */
+	clrsetbits_le32(&denali_phy[939], 0x3 << 17, speed << 17);
+
+	read_mr(dram->chan[channel].pctl, 1, 5, &mr5);
+	set_ds_odt(&dram->chan[channel], timings, true, mr5);
+
+	ctl = lpddr4_get_ctl(timings, phy);
+	set_lpddr4_dq_odt(&dram->chan[channel], timings, ctl, true, true, mr5);
+	set_lpddr4_ca_odt(&dram->chan[channel], timings, ctl, true, true, mr5);
+	set_lpddr4_MR3(&dram->chan[channel], timings, ctl, true, mr5);
+	set_lpddr4_MR12(&dram->chan[channel], timings, ctl, true, mr5);
+	set_lpddr4_MR14(&dram->chan[channel], timings, ctl, true, mr5);
+
+	/*
+	 * if phy_sw_master_mode_x not bypass mode,
+	 * clear phy_slice_pwr_rdc_disable.
+	 * note: need use timings, not ddr_publ_regs
+	 */
+	if (!((denali_phy_params[86] >> 8) & (1 << 2))) {
+		clrbits_le32(&denali_phy[10], 1 << 16);
+		clrbits_le32(&denali_phy[138], 1 << 16);
+		clrbits_le32(&denali_phy[266], 1 << 16);
+		clrbits_le32(&denali_phy[394], 1 << 16);
+	}
+
+	/*
+	 * when PHY_PER_CS_TRAINING_EN=1, W2W_DIFFCS_DLY_Fx can't
+	 * smaller than 8
+	 * NOTE: need use timings, not ddr_publ_regs
+	 */
+	if ((denali_phy_params[84] >> 16) & 1) {
+		if (((readl(&denali_ctl[217 + ctl]) >> 16) & 0x1f) < 8)
+			clrsetbits_le32(&denali_ctl[217 + ctl],
+					0x1f << 16, 8 << 16);
+	}
+}
+
+static void lpddr4_set_phy(struct dram_info *dram,
+			   struct rk3399_sdram_params *params, u32 phy,
+			   struct rk3399_sdram_params *timings)
+{
+	u32 channel;
+
+	for (channel = 0; channel < 2; channel++)
+		lpddr4_copy_phy(dram, params, phy, timings, channel);
+}
+
+static int lpddr4_set_ctl(struct dram_info *dram,
+			  struct rk3399_sdram_params *params, u32 ctl, u32 hz)
+{
+	u32 channel;
+	int ret_clk, ret;
+
+	/* cci idle req stall */
+	writel(0x70007, &dram->grf->soc_con0);
+
+	/* enable all clk */
+	setbits_le32(&dram->pmu->pmu_noc_auto_ena, (0x3 << 7));
+
+	/* idle */
+	setbits_le32(&dram->pmu->pmu_bus_idle_req, (0x3 << 18));
+	while ((readl(&dram->pmu->pmu_bus_idle_st) & (0x3 << 18))
+	       != (0x3 << 18))
+		;
+
+	/* change freq */
+	writel((((0x3 << 4) | (1 << 2) | 1) << 16) |
+		(ctl << 4) | (1 << 2) | 1, &dram->cic->cic_ctrl0);
+	while (!(readl(&dram->cic->cic_status0) & (1 << 2)))
+		;
+
+	ret_clk = clk_set_rate(&dram->ddr_clk, hz);
+	if (ret_clk < 0) {
+		printf("%s clk set failed %d\n", __func__, ret_clk);
+		return ret_clk;
+	}
+
+	writel(0x20002, &dram->cic->cic_ctrl0);
+	while (!(readl(&dram->cic->cic_status0) & (1 << 0)))
+		;
+
+	/* deidle */
+	clrbits_le32(&dram->pmu->pmu_bus_idle_req, (0x3 << 18));
+	while (readl(&dram->pmu->pmu_bus_idle_st) & (0x3 << 18))
+		;
+
+	/* clear enable all clk */
+	clrbits_le32(&dram->pmu->pmu_noc_auto_ena, (0x3 << 7));
+
+	/* lpddr4 ctl2 can not do training, all training will fail */
+	if (!(params->base.dramtype == LPDDR4 && ctl == 2)) {
+		for (channel = 0; channel < 2; channel++) {
+			if (!(params->ch[channel].cap_info.col))
+				continue;
+			ret = data_training(dram, channel, params,
+						     PI_FULL_TRAINING);
+			if (ret)
+				printf("%s: channel %d training failed!\n",
+				       __func__, channel);
+			else
+				debug("%s: channel %d training pass\n",
+				      __func__, channel);
+		}
+	}
+
+	return 0;
+}
+
+static int lpddr4_set_rate(struct dram_info *dram,
+			   struct rk3399_sdram_params *params)
+{
+	u32 ctl;
+	u32 phy;
+
+	for (ctl = 0; ctl < 2; ctl++) {
+		phy = lpddr4_get_phy(params, ctl);
+
+		lpddr4_set_phy(dram, params, phy, &lpddr4_timings[ctl]);
+		lpddr4_set_ctl(dram, params, ctl,
+			       lpddr4_timings[ctl].base.ddr_freq);
+
+		debug("%s: change freq to %d mhz %d, %d\n", __func__,
+		      lpddr4_timings[ctl].base.ddr_freq / MHz, ctl, phy);
+	}
+
+	return 0;
+}
+#endif /* CONFIG_RAM_RK3399_LPDDR4 */
+
+static unsigned char calculate_stride(struct rk3399_sdram_params *params)
+{
+	unsigned int stride = params->base.stride;
+	unsigned int channel, chinfo = 0;
+	unsigned int ch_cap[2] = {0, 0};
+	u64 cap;
+
+	for (channel = 0; channel < 2; channel++) {
+		unsigned int cs0_cap = 0;
+		unsigned int cs1_cap = 0;
+		struct sdram_cap_info *cap_info = &params->ch[channel].cap_info;
+
+		if (cap_info->col == 0)
+			continue;
+
+		cs0_cap = (1 << (cap_info->cs0_row + cap_info->col +
+				 cap_info->bk + cap_info->bw - 20));
+		if (cap_info->rank > 1)
+			cs1_cap = cs0_cap >> (cap_info->cs0_row
+					      - cap_info->cs1_row);
+		if (cap_info->row_3_4) {
+			cs0_cap = cs0_cap * 3 / 4;
+			cs1_cap = cs1_cap * 3 / 4;
+		}
+		ch_cap[channel] = cs0_cap + cs1_cap;
+		chinfo |= 1 << channel;
+	}
+
+	/* stride calculation for 1 channel */
+	if (params->base.num_channels == 1 && chinfo & 1)
+		return 0x17;	/* channel a */
+
+	/* stride calculation for 2 channels, default gstride type is 256B */
+	if (ch_cap[0] == ch_cap[1]) {
+		cap = ch_cap[0] + ch_cap[1];
+		switch (cap) {
+		/* 512MB */
+		case 512:
+			stride = 0;
+			break;
+		/* 1GB */
+		case 1024:
+			stride = 0x5;
+			break;
+		/*
+		 * 768MB + 768MB same as total 2GB memory
+		 * useful space: 0-768MB 1GB-1792MB
+		 */
+		case 1536:
+		/* 2GB */
+		case 2048:
+			stride = 0x9;
+			break;
+		/* 1536MB + 1536MB */
+		case 3072:
+			stride = 0x11;
+			break;
+		/* 4GB */
+		case 4096:
+			stride = 0xD;
+			break;
+		default:
+			printf("%s: Unable to calculate stride for ", __func__);
+			print_size((cap * (1 << 20)), " capacity\n");
+			break;
+		}
+	}
+
+	sdram_print_stride(stride);
+
+	return stride;
+}
+
+static void clear_channel_params(struct rk3399_sdram_params *params, u8 channel)
+{
+	params->ch[channel].cap_info.rank = 0;
+	params->ch[channel].cap_info.col = 0;
+	params->ch[channel].cap_info.bk = 0;
+	params->ch[channel].cap_info.bw = 32;
+	params->ch[channel].cap_info.dbw = 32;
+	params->ch[channel].cap_info.row_3_4 = 0;
+	params->ch[channel].cap_info.cs0_row = 0;
+	params->ch[channel].cap_info.cs1_row = 0;
+	params->ch[channel].cap_info.ddrconfig = 0;
+}
+
+static int pctl_init(struct dram_info *dram, struct rk3399_sdram_params *params)
+{
+	int channel;
+	int ret;
+
+	for (channel = 0; channel < 2; channel++) {
+		const struct chan_info *chan = &dram->chan[channel];
+		struct rk3399_cru *cru = dram->cru;
+		struct rk3399_ddr_publ_regs *publ = chan->publ;
+
+		phy_pctrl_reset(cru, channel);
+		phy_dll_bypass_set(publ, params->base.ddr_freq);
+
+		ret = pctl_cfg(dram, chan, channel, params);
+		if (ret < 0) {
+			printf("%s: pctl config failed\n", __func__);
+			return ret;
+		}
+
+		/* start to trigger initialization */
+		pctl_start(dram, channel);
+	}
+
+	return 0;
+}
+
+static int sdram_init(struct dram_info *dram,
+		      struct rk3399_sdram_params *params)
+{
+	unsigned char dramtype = params->base.dramtype;
+	unsigned int ddr_freq = params->base.ddr_freq;
+	int channel, ch, rank;
+	int ret;
 
 	debug("Starting SDRAM initialization...\n");
 
@@ -1052,35 +2534,78 @@
 		return -E2BIG;
 	}
 
+	for (ch = 0; ch < 2; ch++) {
+		params->ch[ch].cap_info.rank = 2;
+		for (rank = 2; rank != 0; rank--) {
+			ret = pctl_init(dram, params);
+			if (ret < 0) {
+				printf("%s: pctl init failed\n", __func__);
+				return ret;
+			}
+
+			/* LPDDR2/LPDDR3 need to wait DAI complete, max 10us */
+			if (dramtype == LPDDR3)
+				udelay(10);
+
+			params->ch[ch].cap_info.rank = rank;
+
+			ret = dram->ops->data_training(dram, ch, rank, params);
+			if (!ret) {
+				debug("%s: data trained for rank %d, ch %d\n",
+				      __func__, rank, ch);
+				break;
+			}
+		}
+		/* Computed rank with associated channel number */
+		params->ch[ch].cap_info.rank = rank;
+	}
+
+	params->base.num_channels = 0;
 	for (channel = 0; channel < 2; channel++) {
 		const struct chan_info *chan = &dram->chan[channel];
-		struct rk3399_ddr_publ_regs *publ = chan->publ;
-
-		phy_dll_bypass_set(publ, ddr_freq);
+		struct sdram_cap_info *cap_info = &params->ch[channel].cap_info;
+		u8 training_flag = PI_FULL_TRAINING;
 
-		if (channel >= sdram_params->base.num_channels)
+		if (cap_info->rank == 0) {
+			clear_channel_params(params, channel);
 			continue;
-
-		if (pctl_cfg(chan, channel, sdram_params) != 0) {
-			printf("pctl_cfg fail, reset\n");
-			return -EIO;
+		} else {
+			params->base.num_channels++;
 		}
 
-		/* LPDDR2/LPDDR3 need to wait DAI complete, max 10us */
-		if (dramtype == LPDDR3)
-			udelay(10);
+		debug("Channel ");
+		debug(channel ? "1: " : "0: ");
+
+		/* LPDDR3 should have write and read gate training */
+		if (params->base.dramtype == LPDDR3)
+			training_flag = PI_WRITE_LEVELING |
+					PI_READ_GATE_TRAINING;
 
-		if (data_training(chan, channel,
-				  sdram_params, PI_FULL_TRAINING)) {
-			printf("SDRAM initialization failed, reset\n");
-			return -EIO;
+		if (params->base.dramtype != LPDDR4) {
+			ret = data_training(dram, channel, params,
+					    training_flag);
+			if (!ret) {
+				debug("%s: data train failed for channel %d\n",
+				      __func__, ret);
+				continue;
+			}
 		}
 
-		set_ddrconfig(chan, sdram_params, channel,
-			      sdram_params->ch[channel].ddrconfig);
+		sdram_print_ddr_info(cap_info, &params->base);
+
+		set_ddrconfig(chan, params, channel, cap_info->ddrconfig);
+	}
+
+	if (params->base.num_channels == 0) {
+		printf("%s: ", __func__);
+		sdram_print_dram_type(params->base.dramtype);
+		printf(" - %dMHz failed!\n", params->base.ddr_freq);
+		return -EINVAL;
 	}
-	dram_all_config(dram, sdram_params);
-	switch_to_phy_index1(dram, sdram_params);
+
+	params->base.stride = calculate_stride(params);
+	dram_all_config(dram, params);
+	dram->ops->set_rate(dram, params);
 
 	debug("Finish SDRAM initialization...\n");
 	return 0;
@@ -1116,8 +2641,8 @@
 	int ret;
 
 	ret = regmap_init_mem_platdata(dev, dtplat->reg,
-			ARRAY_SIZE(dtplat->reg) / 2,
-			&plat->map);
+				       ARRAY_SIZE(dtplat->reg) / 2,
+				       &plat->map);
 	if (ret)
 		return ret;
 
@@ -1125,6 +2650,16 @@
 }
 #endif
 
+static const struct sdram_rk3399_ops rk3399_ops = {
+#if !defined(CONFIG_RAM_RK3399_LPDDR4)
+	.data_training = default_data_training,
+	.set_rate = switch_to_phy_index1,
+#else
+	.data_training = lpddr4_mr_detect,
+	.set_rate = lpddr4_set_rate,
+#endif
+};
+
 static int rk3399_dmc_init(struct udevice *dev)
 {
 	struct dram_info *priv = dev_get_priv(dev);
@@ -1142,7 +2677,10 @@
 		return ret;
 #endif
 
+	priv->ops = &rk3399_ops;
 	priv->cic = syscon_get_first_range(ROCKCHIP_SYSCON_CIC);
+	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
 	priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
 	priv->pmusgrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUSGRF);
 	priv->pmucru = rockchip_get_pmucru();
@@ -1161,8 +2699,9 @@
 	      priv->chan[0].publ, priv->chan[0].msch,
 	      priv->chan[1].pctl, priv->chan[1].pi,
 	      priv->chan[1].publ, priv->chan[1].msch);
-	debug("cru %p, cic %p, grf %p, sgrf %p, pmucru %p\n", priv->cru,
-	      priv->cic, priv->pmugrf, priv->pmusgrf, priv->pmucru);
+	debug("cru %p, cic %p, grf %p, sgrf %p, pmucru %p, pmu %p\n", priv->cru,
+	      priv->cic, priv->pmugrf, priv->pmusgrf, priv->pmucru, priv->pmu);
+
 #if CONFIG_IS_ENABLED(OF_PLATDATA)
 	ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->ddr_clk);
 #else
@@ -1172,14 +2711,16 @@
 		printf("%s clk get failed %d\n", __func__, ret);
 		return ret;
 	}
+
 	ret = clk_set_rate(&priv->ddr_clk, params->base.ddr_freq * MHz);
 	if (ret < 0) {
 		printf("%s clk set failed %d\n", __func__, ret);
 		return ret;
 	}
+
 	ret = sdram_init(priv, params);
 	if (ret < 0) {
-		printf("%s DRAM init failed%d\n", __func__, ret);
+		printf("%s DRAM init failed %d\n", __func__, ret);
 		return ret;
 	}
 
@@ -1197,10 +2738,10 @@
 	struct dram_info *priv = dev_get_priv(dev);
 
 	priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
-	debug("%s: pmugrf=%p\n", __func__, priv->pmugrf);
+	debug("%s: pmugrf = %p\n", __func__, priv->pmugrf);
 	priv->info.base = CONFIG_SYS_SDRAM_BASE;
-	priv->info.size = rockchip_sdram_size(
-			(phys_addr_t)&priv->pmugrf->os_reg2);
+	priv->info.size =
+		rockchip_sdram_size((phys_addr_t)&priv->pmugrf->os_reg2);
 #endif
 	return 0;
 }
@@ -1218,7 +2759,6 @@
 	.get_info = rk3399_dmc_get_info,
 };
 
-
 static const struct udevice_id rk3399_dmc_ids[] = {
 	{ .compatible = "rockchip,rk3399-dmc" },
 	{ }
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 9eb532b..fa6f111 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -40,6 +40,16 @@
 	  Say 'y' here to add support for test processor which does dummy
 	  operations for sandbox platform.
 
+config REMOTEPROC_STM32_COPRO
+	bool "Support for STM32 coprocessor"
+	select REMOTEPROC
+	depends on DM
+	depends on ARCH_STM32MP
+	depends on OF_CONTROL
+	help
+	  Say 'y' here to add support for STM32 Cortex-M4 coprocessors via the
+	  remoteproc framework.
+
 config REMOTEPROC_TI_POWER
 	bool "Support for TI Power processor"
 	select REMOTEPROC
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 77eb708..b9a06ac 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -4,10 +4,11 @@
 # Texas Instruments Incorporated - http://www.ti.com/
 #
 
-obj-$(CONFIG_$(SPL_)REMOTEPROC) += rproc-uclass.o
+obj-$(CONFIG_$(SPL_)REMOTEPROC) += rproc-uclass.o rproc-elf-loader.o
 
 # Remote proc drivers - Please keep this list alphabetically sorted.
 obj-$(CONFIG_K3_SYSTEM_CONTROLLER) += k3_system_controller.o
 obj-$(CONFIG_REMOTEPROC_K3) += k3_rproc.o
 obj-$(CONFIG_REMOTEPROC_SANDBOX) += sandbox_testproc.o
+obj-$(CONFIG_REMOTEPROC_STM32_COPRO) += stm32_copro.o
 obj-$(CONFIG_REMOTEPROC_TI_POWER) += ti_power_proc.o
diff --git a/drivers/remoteproc/rproc-elf-loader.c b/drivers/remoteproc/rproc-elf-loader.c
new file mode 100644
index 0000000..67937a7
--- /dev/null
+++ b/drivers/remoteproc/rproc-elf-loader.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+#include <common.h>
+#include <dm.h>
+#include <elf.h>
+#include <remoteproc.h>
+
+/* Basic function to verify ELF32 image format */
+int rproc_elf32_sanity_check(ulong addr, ulong size)
+{
+	Elf32_Ehdr *ehdr;
+	char class;
+
+	if (!addr) {
+		pr_debug("Invalid fw address?\n");
+		return -EFAULT;
+	}
+
+	if (size < sizeof(Elf32_Ehdr)) {
+		pr_debug("Image is too small\n");
+		return -ENOSPC;
+	}
+
+	ehdr = (Elf32_Ehdr *)addr;
+	class = ehdr->e_ident[EI_CLASS];
+
+	if (!IS_ELF(*ehdr) || ehdr->e_type != ET_EXEC || class != ELFCLASS32) {
+		pr_debug("Not an executable ELF32 image\n");
+		return -EPROTONOSUPPORT;
+	}
+
+	/* We assume the firmware has the same endianness as the host */
+# ifdef __LITTLE_ENDIAN
+	if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
+# else /* BIG ENDIAN */
+	if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) {
+# endif
+		pr_debug("Unsupported firmware endianness\n");
+		return -EILSEQ;
+	}
+
+	if (size < ehdr->e_shoff + sizeof(Elf32_Shdr)) {
+		pr_debug("Image is too small\n");
+		return -ENOSPC;
+	}
+
+	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
+		pr_debug("Image is corrupted (bad magic)\n");
+		return -EBADF;
+	}
+
+	if (ehdr->e_phnum == 0) {
+		pr_debug("No loadable segments\n");
+		return -ENOEXEC;
+	}
+
+	if (ehdr->e_phoff > size) {
+		pr_debug("Firmware size is too small\n");
+		return -ENOSPC;
+	}
+
+	return 0;
+}
+
+/* A very simple elf loader, assumes the image is valid */
+int rproc_elf32_load_image(struct udevice *dev, unsigned long addr)
+{
+	Elf32_Ehdr *ehdr; /* Elf header structure pointer */
+	Elf32_Phdr *phdr; /* Program header structure pointer */
+	const struct dm_rproc_ops *ops;
+	unsigned int i;
+
+	ehdr = (Elf32_Ehdr *)addr;
+	phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
+
+	ops = rproc_get_ops(dev);
+
+	/* Load each program header */
+	for (i = 0; i < ehdr->e_phnum; ++i) {
+		void *dst = (void *)(uintptr_t)phdr->p_paddr;
+		void *src = (void *)addr + phdr->p_offset;
+
+		if (phdr->p_type != PT_LOAD)
+			continue;
+
+		if (ops->device_to_virt)
+			dst = ops->device_to_virt(dev, (ulong)dst);
+
+		dev_dbg(dev, "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(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
+			    roundup((unsigned long)dst + phdr->p_filesz,
+				    ARCH_DMA_MINALIGN) -
+			    rounddown((unsigned long)dst, ARCH_DMA_MINALIGN));
+		++phdr;
+	}
+
+	return 0;
+}
diff --git a/drivers/remoteproc/sandbox_testproc.c b/drivers/remoteproc/sandbox_testproc.c
index 51a67e6..5f35119 100644
--- a/drivers/remoteproc/sandbox_testproc.c
+++ b/drivers/remoteproc/sandbox_testproc.c
@@ -8,6 +8,7 @@
 #include <dm.h>
 #include <errno.h>
 #include <remoteproc.h>
+#include <asm/io.h>
 
 /**
  * enum sandbox_state - different device states
@@ -300,6 +301,23 @@
 	return ret;
 }
 
+#define SANDBOX_RPROC_DEV_TO_PHY_OFFSET	0x1000
+/**
+ * sandbox_testproc_device_to_virt() - Convert device address to virtual address
+ * @dev:	device to operate upon
+ * @da:		device address
+ * @return converted virtual address
+ */
+static void *sandbox_testproc_device_to_virt(struct udevice *dev, ulong da)
+{
+	u64 paddr;
+
+	/* Use a simple offset conversion */
+	paddr = da + SANDBOX_RPROC_DEV_TO_PHY_OFFSET;
+
+	return phys_to_virt(paddr);
+}
+
 static const struct dm_rproc_ops sandbox_testproc_ops = {
 	.init = sandbox_testproc_init,
 	.reset = sandbox_testproc_reset,
@@ -308,6 +326,7 @@
 	.stop = sandbox_testproc_stop,
 	.is_running = sandbox_testproc_is_running,
 	.ping = sandbox_testproc_ping,
+	.device_to_virt = sandbox_testproc_device_to_virt,
 };
 
 static const struct udevice_id sandbox_ids[] = {
diff --git a/drivers/remoteproc/stm32_copro.c b/drivers/remoteproc/stm32_copro.c
new file mode 100644
index 0000000..de3b972
--- /dev/null
+++ b/drivers/remoteproc/stm32_copro.c
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+#define pr_fmt(fmt) "%s: " fmt, __func__
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <regmap.h>
+#include <remoteproc.h>
+#include <reset.h>
+#include <syscon.h>
+#include <asm/io.h>
+
+#define RCC_GCR_HOLD_BOOT	0
+#define RCC_GCR_RELEASE_BOOT	1
+
+/**
+ * struct stm32_copro_privdata - power processor private data
+ * @reset_ctl:		reset controller handle
+ * @hold_boot_regmap:	regmap for remote processor reset hold boot
+ * @hold_boot_offset:	offset of the register controlling the hold boot setting
+ * @hold_boot_mask:	bitmask of the register for the hold boot field
+ * @is_running:		is the remote processor running
+ */
+struct stm32_copro_privdata {
+	struct reset_ctl reset_ctl;
+	struct regmap *hold_boot_regmap;
+	uint hold_boot_offset;
+	uint hold_boot_mask;
+	bool is_running;
+};
+
+/**
+ * stm32_copro_probe() - Basic probe
+ * @dev:	corresponding STM32 remote processor device
+ * @return 0 if all went ok, else corresponding -ve error
+ */
+static int stm32_copro_probe(struct udevice *dev)
+{
+	struct stm32_copro_privdata *priv;
+	struct regmap *regmap;
+	const fdt32_t *cell;
+	int len, ret;
+
+	priv = dev_get_priv(dev);
+
+	regmap = syscon_regmap_lookup_by_phandle(dev, "st,syscfg-holdboot");
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "unable to find holdboot regmap (%ld)\n",
+			PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	cell = dev_read_prop(dev, "st,syscfg-holdboot", &len);
+	if (len < 3 * sizeof(fdt32_t)) {
+		dev_err(dev, "holdboot offset and mask not available\n");
+		return -EINVAL;
+	}
+
+	priv->hold_boot_regmap = regmap;
+	priv->hold_boot_offset = fdtdec_get_number(cell + 1, 1);
+	priv->hold_boot_mask = fdtdec_get_number(cell + 2, 1);
+
+	ret = reset_get_by_index(dev, 0, &priv->reset_ctl);
+	if (ret) {
+		dev_err(dev, "failed to get reset (%d)\n", ret);
+		return ret;
+	}
+
+	dev_dbg(dev, "probed\n");
+
+	return 0;
+}
+
+/**
+ * stm32_copro_set_hold_boot() - Hold boot bit management
+ * @dev:	corresponding STM32 remote processor device
+ * @hold:	hold boot value
+ * @return 0 if all went ok, else corresponding -ve error
+ */
+static int stm32_copro_set_hold_boot(struct udevice *dev, bool hold)
+{
+	struct stm32_copro_privdata *priv;
+	uint val;
+	int ret;
+
+	priv = dev_get_priv(dev);
+
+	val = hold ? RCC_GCR_HOLD_BOOT : RCC_GCR_RELEASE_BOOT;
+
+	/*
+	 * Note: shall run an SMC call (STM32_SMC_RCC) if platform is secured.
+	 * To be updated when the code for this SMC service is available which
+	 * is not the case for the time being.
+	 */
+	ret = regmap_update_bits(priv->hold_boot_regmap, priv->hold_boot_offset,
+				 priv->hold_boot_mask, val);
+	if (ret)
+		dev_err(dev, "failed to set hold boot\n");
+
+	return ret;
+}
+
+/**
+ * stm32_copro_device_to_virt() - Convert device address to virtual address
+ * @dev:	corresponding STM32 remote processor device
+ * @da:		device address
+ * @return converted virtual address
+ */
+static void *stm32_copro_device_to_virt(struct udevice *dev, ulong da)
+{
+	fdt32_t in_addr = cpu_to_be32(da);
+	u64 paddr;
+
+	paddr = dev_translate_dma_address(dev, &in_addr);
+	if (paddr == OF_BAD_ADDR) {
+		dev_err(dev, "Unable to convert address %ld\n", da);
+		return NULL;
+	}
+
+	return phys_to_virt(paddr);
+}
+
+/**
+ * stm32_copro_load() - Loadup the STM32 remote processor
+ * @dev:	corresponding STM32 remote processor device
+ * @addr:	Address in memory where image is stored
+ * @size:	Size in bytes of the image
+ * @return 0 if all went ok, else corresponding -ve error
+ */
+static int stm32_copro_load(struct udevice *dev, ulong addr, ulong size)
+{
+	struct stm32_copro_privdata *priv;
+	int ret;
+
+	priv = dev_get_priv(dev);
+
+	ret = stm32_copro_set_hold_boot(dev, true);
+	if (ret)
+		return ret;
+
+	ret = reset_assert(&priv->reset_ctl);
+	if (ret) {
+		dev_err(dev, "Unable to assert reset line (ret=%d)\n", ret);
+		return ret;
+	}
+
+	/* Support only ELF32 image */
+	ret = rproc_elf32_sanity_check(addr, size);
+	if (ret) {
+		dev_err(dev, "Invalid ELF32 image (%d)\n", ret);
+		return ret;
+	}
+
+	return rproc_elf32_load_image(dev, addr);
+}
+
+/**
+ * stm32_copro_start() - Start the STM32 remote processor
+ * @dev:	corresponding STM32 remote processor device
+ * @return 0 if all went ok, else corresponding -ve error
+ */
+static int stm32_copro_start(struct udevice *dev)
+{
+	struct stm32_copro_privdata *priv;
+	int ret;
+
+	priv = dev_get_priv(dev);
+
+	/* move hold boot from true to false start the copro */
+	ret = stm32_copro_set_hold_boot(dev, false);
+	if (ret)
+		return ret;
+
+	/*
+	 * Once copro running, reset hold boot flag to avoid copro
+	 * rebooting autonomously
+	 */
+	ret = stm32_copro_set_hold_boot(dev, true);
+	priv->is_running = !ret;
+	return ret;
+}
+
+/**
+ * stm32_copro_reset() - Reset the STM32 remote processor
+ * @dev:	corresponding STM32 remote processor device
+ * @return 0 if all went ok, else corresponding -ve error
+ */
+static int stm32_copro_reset(struct udevice *dev)
+{
+	struct stm32_copro_privdata *priv;
+	int ret;
+
+	priv = dev_get_priv(dev);
+
+	ret = stm32_copro_set_hold_boot(dev, true);
+	if (ret)
+		return ret;
+
+	ret = reset_assert(&priv->reset_ctl);
+	if (ret) {
+		dev_err(dev, "Unable to assert reset line (ret=%d)\n", ret);
+		return ret;
+	}
+
+	priv->is_running = false;
+
+	return 0;
+}
+
+/**
+ * stm32_copro_stop() - Stop the STM32 remote processor
+ * @dev:	corresponding STM32 remote processor device
+ * @return 0 if all went ok, else corresponding -ve error
+ */
+static int stm32_copro_stop(struct udevice *dev)
+{
+	return stm32_copro_reset(dev);
+}
+
+/**
+ * stm32_copro_is_running() - Is the STM32 remote processor running
+ * @dev:	corresponding STM32 remote processor device
+ * @return 1 if the remote processor is running, 0 otherwise
+ */
+static int stm32_copro_is_running(struct udevice *dev)
+{
+	struct stm32_copro_privdata *priv;
+
+	priv = dev_get_priv(dev);
+	return priv->is_running;
+}
+
+static const struct dm_rproc_ops stm32_copro_ops = {
+	.load = stm32_copro_load,
+	.start = stm32_copro_start,
+	.stop =  stm32_copro_stop,
+	.reset = stm32_copro_reset,
+	.is_running = stm32_copro_is_running,
+	.device_to_virt = stm32_copro_device_to_virt,
+};
+
+static const struct udevice_id stm32_copro_ids[] = {
+	{.compatible = "st,stm32mp1-rproc"},
+	{}
+};
+
+U_BOOT_DRIVER(stm32_copro) = {
+	.name = "stm32_m4_proc",
+	.of_match = stm32_copro_ids,
+	.id = UCLASS_REMOTEPROC,
+	.ops = &stm32_copro_ops,
+	.probe = stm32_copro_probe,
+	.priv_auto_alloc_size = sizeof(struct stm32_copro_privdata),
+};
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 532e94d..0b58a18 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -120,4 +120,10 @@
 	  Enable driver for ST's M41T62 compatible RTC devices (like RV-4162).
 	  It is a serial (I2C) real-time clock (RTC) with alarm.
 
+config RTC_STM32
+	bool "Enable STM32 RTC driver"
+	depends on DM_RTC
+	help
+	  Enable STM32 RTC driver. This driver supports the rtc that is present
+	  on some STM32 SoCs.
 endmenu
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 915adb8..f97a669 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -51,5 +51,6 @@
 obj-$(CONFIG_RTC_RX8010SJ) += rx8010sj.o
 obj-$(CONFIG_RTC_S3C24X0) += s3c24x0_rtc.o
 obj-$(CONFIG_RTC_S35392A) += s35392a.o
+obj-$(CONFIG_RTC_STM32) += stm32_rtc.o
 obj-$(CONFIG_SANDBOX) += sandbox_rtc.o
 obj-$(CONFIG_RTC_X1205) += x1205.o
diff --git a/drivers/rtc/ds3231.c b/drivers/rtc/ds3231.c
index 9352ff8..79b026a 100644
--- a/drivers/rtc/ds3231.c
+++ b/drivers/rtc/ds3231.c
@@ -2,6 +2,9 @@
 /*
  * (C) Copyright 2006
  * Markus Klotzbuecher, mk@denx.de
+ *
+ * (C) Copyright 2019 NXP
+ * Chuanhua Han <chuanhua.han@nxp.com>
  */
 
 /*
@@ -13,6 +16,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <dm.h>
 #include <rtc.h>
 #include <i2c.h>
 
@@ -50,6 +54,7 @@
 #define RTC_STAT_BIT_EN32KHZ	0x8	/* Enable 32KHz Output  */
 
 
+#if !CONFIG_IS_ENABLED(DM_RTC)
 static uchar rtc_read (uchar reg);
 static void rtc_write (uchar reg, uchar val);
 
@@ -164,3 +169,105 @@
 {
 	i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
 }
+#else
+static int ds3231_rtc_get(struct udevice *dev, struct rtc_time *tmp)
+{
+	uchar sec, min, hour, mday, wday, mon_cent, year, status;
+
+	status = dm_i2c_reg_read(dev, RTC_STAT_REG_ADDR);
+	sec = dm_i2c_reg_read(dev, RTC_SEC_REG_ADDR);
+	min = dm_i2c_reg_read(dev, RTC_MIN_REG_ADDR);
+	hour = dm_i2c_reg_read(dev, RTC_HR_REG_ADDR);
+	wday = dm_i2c_reg_read(dev, RTC_DAY_REG_ADDR);
+	mday = dm_i2c_reg_read(dev, RTC_DATE_REG_ADDR);
+	mon_cent = dm_i2c_reg_read(dev, RTC_MON_REG_ADDR);
+	year = dm_i2c_reg_read(dev, RTC_YR_REG_ADDR);
+
+	if (status & RTC_STAT_BIT_OSF) {
+		printf("### Warning: RTC oscillator has stopped\n");
+		/* clear the OSF flag */
+		dm_i2c_reg_write(dev, RTC_STAT_REG_ADDR,
+				 dm_i2c_reg_read(dev, RTC_STAT_REG_ADDR)
+						& ~RTC_STAT_BIT_OSF);
+		return -EINVAL;
+	}
+
+	tmp->tm_sec  = bcd2bin(sec & 0x7F);
+	tmp->tm_min  = bcd2bin(min & 0x7F);
+	tmp->tm_hour = bcd2bin(hour & 0x3F);
+	tmp->tm_mday = bcd2bin(mday & 0x3F);
+	tmp->tm_mon  = bcd2bin(mon_cent & 0x1F);
+	tmp->tm_year = bcd2bin(year) + ((mon_cent & 0x80) ? 2000 : 1900);
+	tmp->tm_wday = bcd2bin((wday - 1) & 0x07);
+	tmp->tm_yday = 0;
+	tmp->tm_isdst = 0;
+
+	debug("Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
+	      tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+	      tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+
+	return 0;
+}
+
+static int ds3231_rtc_set(struct udevice *dev, const struct rtc_time *tmp)
+{
+	uchar century;
+
+	debug("Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
+	      tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+	      tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+
+	dm_i2c_reg_write(dev, RTC_YR_REG_ADDR, bin2bcd(tmp->tm_year % 100));
+
+	century = (tmp->tm_year >= 2000) ? 0x80 : 0;
+	dm_i2c_reg_write(dev, RTC_MON_REG_ADDR, bin2bcd(tmp->tm_mon) | century);
+
+	dm_i2c_reg_write(dev, RTC_DAY_REG_ADDR, bin2bcd(tmp->tm_wday + 1));
+	dm_i2c_reg_write(dev, RTC_DATE_REG_ADDR, bin2bcd(tmp->tm_mday));
+	dm_i2c_reg_write(dev, RTC_HR_REG_ADDR, bin2bcd(tmp->tm_hour));
+	dm_i2c_reg_write(dev, RTC_MIN_REG_ADDR, bin2bcd(tmp->tm_min));
+	dm_i2c_reg_write(dev, RTC_SEC_REG_ADDR, bin2bcd(tmp->tm_sec));
+
+	return 0;
+}
+
+static int ds3231_rtc_reset(struct udevice *dev)
+{
+	int ret;
+
+	ret = dm_i2c_reg_write(dev, RTC_CTL_REG_ADDR,
+			       RTC_CTL_BIT_RS1 | RTC_CTL_BIT_RS2);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int ds3231_probe(struct udevice *dev)
+{
+	i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS |
+			DM_I2C_CHIP_WR_ADDRESS);
+
+	return 0;
+}
+
+static const struct rtc_ops ds3231_rtc_ops = {
+	.get = ds3231_rtc_get,
+	.set = ds3231_rtc_set,
+	.reset = ds3231_rtc_reset,
+};
+
+static const struct udevice_id ds3231_rtc_ids[] = {
+	{ .compatible = "dallas,ds3231" },
+	{ .compatible = "dallas,ds3232" },
+	{ }
+};
+
+U_BOOT_DRIVER(rtc_ds3231) = {
+	.name   = "rtc-ds3231",
+	.id     = UCLASS_RTC,
+	.probe  = ds3231_probe,
+	.of_match = ds3231_rtc_ids,
+	.ops    = &ds3231_rtc_ops,
+};
+#endif
diff --git a/drivers/rtc/stm32_rtc.c b/drivers/rtc/stm32_rtc.c
new file mode 100644
index 0000000..abd3390
--- /dev/null
+++ b/drivers/rtc/stm32_rtc.c
@@ -0,0 +1,323 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <rtc.h>
+#include <asm/io.h>
+#include <linux/iopoll.h>
+
+#define STM32_RTC_TR		0x00
+#define STM32_RTC_DR		0x04
+#define STM32_RTC_ISR		0x0C
+#define STM32_RTC_PRER		0x10
+#define STM32_RTC_CR		0x18
+#define STM32_RTC_WPR		0x24
+
+/* STM32_RTC_TR bit fields  */
+#define STM32_RTC_SEC_SHIFT	0
+#define STM32_RTC_SEC		GENMASK(6, 0)
+#define STM32_RTC_MIN_SHIFT	8
+#define STM32_RTC_MIN		GENMASK(14, 8)
+#define STM32_RTC_HOUR_SHIFT	16
+#define STM32_RTC_HOUR		GENMASK(21, 16)
+
+/* STM32_RTC_DR bit fields */
+#define STM32_RTC_DATE_SHIFT	0
+#define STM32_RTC_DATE		GENMASK(5, 0)
+#define STM32_RTC_MONTH_SHIFT	8
+#define STM32_RTC_MONTH		GENMASK(12, 8)
+#define STM32_RTC_WDAY_SHIFT	13
+#define STM32_RTC_WDAY		GENMASK(15, 13)
+#define STM32_RTC_YEAR_SHIFT	16
+#define STM32_RTC_YEAR		GENMASK(23, 16)
+
+/* STM32_RTC_CR bit fields */
+#define STM32_RTC_CR_FMT	BIT(6)
+
+/* STM32_RTC_ISR/STM32_RTC_ICSR bit fields */
+#define STM32_RTC_ISR_INITS	BIT(4)
+#define STM32_RTC_ISR_RSF	BIT(5)
+#define STM32_RTC_ISR_INITF	BIT(6)
+#define STM32_RTC_ISR_INIT	BIT(7)
+
+/* STM32_RTC_PRER bit fields */
+#define STM32_RTC_PRER_PRED_S_SHIFT	0
+#define STM32_RTC_PRER_PRED_S		GENMASK(14, 0)
+#define STM32_RTC_PRER_PRED_A_SHIFT	16
+#define STM32_RTC_PRER_PRED_A		GENMASK(22, 16)
+
+/* STM32_RTC_WPR key constants */
+#define RTC_WPR_1ST_KEY		0xCA
+#define RTC_WPR_2ND_KEY		0x53
+#define RTC_WPR_WRONG_KEY	0xFF
+
+struct stm32_rtc_priv {
+	fdt_addr_t base;
+};
+
+static int stm32_rtc_get(struct udevice *dev, struct rtc_time *tm)
+{
+	struct stm32_rtc_priv *priv = dev_get_priv(dev);
+	u32 tr, dr;
+
+	tr = readl(priv->base + STM32_RTC_TR);
+	dr = readl(priv->base + STM32_RTC_DR);
+
+	tm->tm_sec = bcd2bin((tr & STM32_RTC_SEC) >> STM32_RTC_SEC_SHIFT);
+	tm->tm_min = bcd2bin((tr & STM32_RTC_MIN) >> STM32_RTC_MIN_SHIFT);
+	tm->tm_hour = bcd2bin((tr & STM32_RTC_HOUR) >> STM32_RTC_HOUR_SHIFT);
+
+	tm->tm_mday = bcd2bin((dr & STM32_RTC_DATE) >> STM32_RTC_DATE_SHIFT);
+	tm->tm_mon = bcd2bin((dr & STM32_RTC_MONTH) >> STM32_RTC_MONTH_SHIFT);
+	tm->tm_year = bcd2bin((dr & STM32_RTC_YEAR) >> STM32_RTC_YEAR_SHIFT);
+	tm->tm_wday = bcd2bin((dr & STM32_RTC_WDAY) >> STM32_RTC_WDAY_SHIFT);
+	tm->tm_yday = 0;
+	tm->tm_isdst = 0;
+
+	dev_dbg(dev, "Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
+		tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	return 0;
+}
+
+static void stm32_rtc_unlock(struct udevice *dev)
+{
+	struct stm32_rtc_priv *priv = dev_get_priv(dev);
+
+	writel(RTC_WPR_1ST_KEY, priv->base + STM32_RTC_WPR);
+	writel(RTC_WPR_2ND_KEY, priv->base + STM32_RTC_WPR);
+}
+
+static void stm32_rtc_lock(struct udevice *dev)
+{
+	struct stm32_rtc_priv *priv = dev_get_priv(dev);
+
+	writel(RTC_WPR_WRONG_KEY, priv->base + STM32_RTC_WPR);
+}
+
+static int stm32_rtc_enter_init_mode(struct udevice *dev)
+{
+	struct stm32_rtc_priv *priv = dev_get_priv(dev);
+	u32 isr = readl(priv->base + STM32_RTC_ISR);
+
+	if (!(isr & STM32_RTC_ISR_INITF)) {
+		isr |= STM32_RTC_ISR_INIT;
+		writel(isr, priv->base + STM32_RTC_ISR);
+
+		return readl_poll_timeout(priv->base + STM32_RTC_ISR,
+					  isr,
+					  (isr & STM32_RTC_ISR_INITF),
+					  100000);
+	}
+
+	return 0;
+}
+
+static int stm32_rtc_wait_sync(struct udevice *dev)
+{
+	struct stm32_rtc_priv *priv = dev_get_priv(dev);
+	u32 isr = readl(priv->base + STM32_RTC_ISR);
+
+	isr &= ~STM32_RTC_ISR_RSF;
+	writel(isr, priv->base + STM32_RTC_ISR);
+
+	/*
+	 * Wait for RSF to be set to ensure the calendar registers are
+	 * synchronised, it takes around 2 rtc_ck clock cycles
+	 */
+	return readl_poll_timeout(priv->base + STM32_RTC_ISR,
+				  isr, (isr & STM32_RTC_ISR_RSF),
+				  100000);
+}
+
+static void stm32_rtc_exit_init_mode(struct udevice *dev)
+{
+	struct stm32_rtc_priv *priv = dev_get_priv(dev);
+	u32 isr = readl(priv->base + STM32_RTC_ISR);
+
+	isr &= ~STM32_RTC_ISR_INIT;
+	writel(isr, priv->base + STM32_RTC_ISR);
+}
+
+static int stm32_rtc_set_time(struct udevice *dev, u32 time, u32 date)
+{
+	struct stm32_rtc_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	stm32_rtc_unlock(dev);
+
+	ret = stm32_rtc_enter_init_mode(dev);
+	if (ret)
+		goto lock;
+
+	writel(time, priv->base + STM32_RTC_TR);
+	writel(date, priv->base + STM32_RTC_DR);
+
+	stm32_rtc_exit_init_mode(dev);
+
+	ret = stm32_rtc_wait_sync(dev);
+
+lock:
+	stm32_rtc_lock(dev);
+	return ret;
+}
+
+static int stm32_rtc_set(struct udevice *dev, const struct rtc_time *tm)
+{
+	u32 t, d;
+
+	dev_dbg(dev, "Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
+		tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	/* Time in BCD format */
+	t = (bin2bcd(tm->tm_sec) << STM32_RTC_SEC_SHIFT) & STM32_RTC_SEC;
+	t |= (bin2bcd(tm->tm_min) << STM32_RTC_MIN_SHIFT) & STM32_RTC_MIN;
+	t |= (bin2bcd(tm->tm_hour) << STM32_RTC_HOUR_SHIFT) & STM32_RTC_HOUR;
+
+	/* Date in BCD format */
+	d = (bin2bcd(tm->tm_mday) << STM32_RTC_DATE_SHIFT) & STM32_RTC_DATE;
+	d |= (bin2bcd(tm->tm_mon) << STM32_RTC_MONTH_SHIFT) & STM32_RTC_MONTH;
+	d |= (bin2bcd(tm->tm_year) << STM32_RTC_YEAR_SHIFT) & STM32_RTC_YEAR;
+	d |= (bin2bcd(tm->tm_wday) << STM32_RTC_WDAY_SHIFT) & STM32_RTC_WDAY;
+
+	return stm32_rtc_set_time(dev, t, d);
+}
+
+static int stm32_rtc_reset(struct udevice *dev)
+{
+	dev_dbg(dev, "Reset DATE\n");
+
+	return stm32_rtc_set_time(dev, 0, 0);
+}
+
+static int stm32_rtc_init(struct udevice *dev)
+{
+	struct stm32_rtc_priv *priv = dev_get_priv(dev);
+	unsigned int prer, pred_a, pred_s, pred_a_max, pred_s_max, cr;
+	unsigned int rate;
+	struct clk clk;
+	int ret;
+	u32 isr = readl(priv->base + STM32_RTC_ISR);
+
+	if (isr & STM32_RTC_ISR_INITS)
+		return  0;
+
+	ret = clk_get_by_index(dev, 1, &clk);
+	if (ret)
+		return ret;
+
+	ret = clk_enable(&clk);
+	if (ret) {
+		clk_free(&clk);
+		return ret;
+	}
+
+	rate = clk_get_rate(&clk);
+
+	/* Find prediv_a and prediv_s to obtain the 1Hz calendar clock */
+	pred_a_max = STM32_RTC_PRER_PRED_A >> STM32_RTC_PRER_PRED_A_SHIFT;
+	pred_s_max = STM32_RTC_PRER_PRED_S >> STM32_RTC_PRER_PRED_S_SHIFT;
+
+	for (pred_a = pred_a_max; pred_a + 1 > 0; pred_a--) {
+		pred_s = (rate / (pred_a + 1)) - 1;
+
+		if (((pred_s + 1) * (pred_a + 1)) == rate)
+			break;
+	}
+
+	/*
+	 * Can't find a 1Hz, so give priority to RTC power consumption
+	 * by choosing the higher possible value for prediv_a
+	 */
+	if (pred_s > pred_s_max || pred_a > pred_a_max) {
+		pred_a = pred_a_max;
+		pred_s = (rate / (pred_a + 1)) - 1;
+	}
+
+	stm32_rtc_unlock(dev);
+
+	ret = stm32_rtc_enter_init_mode(dev);
+	if (ret) {
+		dev_err(dev,
+			"Can't enter in init mode. Prescaler config failed.\n");
+		goto unlock;
+	}
+
+	prer = (pred_s << STM32_RTC_PRER_PRED_S_SHIFT) & STM32_RTC_PRER_PRED_S;
+	prer |= (pred_a << STM32_RTC_PRER_PRED_A_SHIFT) & STM32_RTC_PRER_PRED_A;
+	writel(prer, priv->base + STM32_RTC_PRER);
+
+	/* Force 24h time format */
+	cr = readl(priv->base + STM32_RTC_CR);
+	cr &= ~STM32_RTC_CR_FMT;
+	writel(cr, priv->base + STM32_RTC_CR);
+
+	stm32_rtc_exit_init_mode(dev);
+
+	ret = stm32_rtc_wait_sync(dev);
+
+unlock:
+	stm32_rtc_lock(dev);
+
+	if (ret) {
+		clk_disable(&clk);
+		clk_free(&clk);
+	}
+
+	return ret;
+}
+
+static int stm32_rtc_probe(struct udevice *dev)
+{
+	struct stm32_rtc_priv *priv = dev_get_priv(dev);
+	struct clk clk;
+	int ret;
+
+	priv->base = dev_read_addr(dev);
+	if (priv->base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret)
+		return ret;
+
+	ret = clk_enable(&clk);
+	if (ret) {
+		clk_free(&clk);
+		return ret;
+	}
+
+	ret = stm32_rtc_init(dev);
+
+	if (ret) {
+		clk_disable(&clk);
+		clk_free(&clk);
+	}
+
+	return ret;
+}
+
+static const struct rtc_ops stm32_rtc_ops = {
+	.get = stm32_rtc_get,
+	.set = stm32_rtc_set,
+	.reset = stm32_rtc_reset,
+};
+
+static const struct udevice_id stm32_rtc_ids[] = {
+	{ .compatible = "st,stm32mp1-rtc" },
+	{ }
+};
+
+U_BOOT_DRIVER(rtc_stm32) = {
+	.name	= "rtc-stm32",
+	.id	= UCLASS_RTC,
+	.probe	= stm32_rtc_probe,
+	.of_match = stm32_rtc_ids,
+	.ops	= &stm32_rtc_ops,
+	.priv_auto_alloc_size = sizeof(struct stm32_rtc_priv),
+};
diff --git a/drivers/spi/stm32_qspi.c b/drivers/spi/stm32_qspi.c
index 8d612f2..958c394 100644
--- a/drivers/spi/stm32_qspi.c
+++ b/drivers/spi/stm32_qspi.c
@@ -526,7 +526,6 @@
 };
 
 static const struct udevice_id stm32_qspi_ids[] = {
-	{ .compatible = "st,stm32-qspi" },
 	{ .compatible = "st,stm32f469-qspi" },
 	{ }
 };
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index b1188bc..ac68aa2 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -24,6 +24,7 @@
 config USB_XHCI_DWC3_OF_SIMPLE
 	bool "DesignWare USB3 DRD Generic OF Simple Glue Layer"
 	depends on DM_USB
+	default y if ARCH_ROCKCHIP
 	default y if DRA7XX
 	help
 	  Support USB2/3 functionality in simple SoC integrations with
diff --git a/drivers/usb/host/dwc3-of-simple.c b/drivers/usb/host/dwc3-of-simple.c
index b118997..45df614 100644
--- a/drivers/usb/host/dwc3-of-simple.c
+++ b/drivers/usb/host/dwc3-of-simple.c
@@ -92,6 +92,7 @@
 
 static const struct udevice_id dwc3_of_simple_ids[] = {
 	{ .compatible = "amlogic,meson-gxl-dwc3" },
+	{ .compatible = "rockchip,rk3399-dwc3" },
 	{ .compatible = "ti,dwc3" },
 	{ }
 };
diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c
index 83b9f11..9e8cae7 100644
--- a/drivers/usb/host/xhci-dwc3.c
+++ b/drivers/usb/host/xhci-dwc3.c
@@ -118,6 +118,8 @@
 	struct dwc3 *dwc3_reg;
 	enum usb_dr_mode dr_mode;
 	struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
+	const char *phy;
+	u32 reg;
 	int ret;
 
 	hccr = (struct xhci_hccr *)((uintptr_t)dev_read_addr(dev));
@@ -132,6 +134,24 @@
 
 	dwc3_core_init(dwc3_reg);
 
+	/* Set dwc3 usb2 phy config */
+	reg = readl(&dwc3_reg->g_usb2phycfg[0]);
+
+	phy = dev_read_string(dev, "phy_type");
+	if (phy && strcmp(phy, "utmi_wide") == 0) {
+		reg |= DWC3_GUSB2PHYCFG_PHYIF;
+		reg &= ~DWC3_GUSB2PHYCFG_USBTRDTIM_MASK;
+		reg |= DWC3_GUSB2PHYCFG_USBTRDTIM_16BIT;
+	}
+
+	if (dev_read_bool(dev, "snps,dis_enblslpm-quirk"))
+		reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
+
+	if (dev_read_bool(dev, "snps,dis-u2-freeclk-exists-quirk"))
+		reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS;
+
+	writel(reg, &dwc3_reg->g_usb2phycfg[0]);
+
 	dr_mode = usb_get_dr_mode(dev_of_offset(dev));
 	if (dr_mode == USB_DR_MODE_UNKNOWN)
 		/* by default set dual role mode to HOST */
diff --git a/drivers/usb/host/xhci-rockchip.c b/drivers/usb/host/xhci-rockchip.c
index f19bea3..e7b0dbc 100644
--- a/drivers/usb/host/xhci-rockchip.c
+++ b/drivers/usb/host/xhci-rockchip.c
@@ -167,7 +167,6 @@
 }
 
 static const struct udevice_id xhci_usb_ids[] = {
-	{ .compatible = "rockchip,rk3399-xhci" },
 	{ .compatible = "rockchip,rk3328-xhci" },
 	{ }
 };
@@ -187,7 +186,6 @@
 };
 
 static const struct udevice_id usb_phy_ids[] = {
-	{ .compatible = "rockchip,rk3399-usb3-phy" },
 	{ .compatible = "rockchip,rk3328-usb3-phy" },
 	{ }
 };
diff --git a/drivers/video/rockchip/rk3288_hdmi.c b/drivers/video/rockchip/rk3288_hdmi.c
index 315d3ad..3d25ce9 100644
--- a/drivers/video/rockchip/rk3288_hdmi.c
+++ b/drivers/video/rockchip/rk3288_hdmi.c
@@ -33,7 +33,7 @@
 	/* hdmi data from vop id */
 	rk_clrsetreg(&grf->soc_con6, 1 << 4, (vop_id == 1) ? (1 << 4) : 0);
 
-	return 0;
+	return dw_hdmi_enable(&priv->hdmi, edid);
 }
 
 static int rk3288_hdmi_ofdata_to_platdata(struct udevice *dev)
diff --git a/env/env.c b/env/env.c
index 4b417b9..d3cbe2f 100644
--- a/env/env.c
+++ b/env/env.c
@@ -24,6 +24,8 @@
 			entry->load += gd->reloc_off;
 		if (entry->save)
 			entry->save += gd->reloc_off;
+		if (entry->erase)
+			entry->erase += gd->reloc_off;
 		if (entry->init)
 			entry->init += gd->reloc_off;
 	}
@@ -254,6 +256,34 @@
 	return -ENODEV;
 }
 
+int env_erase(void)
+{
+	struct env_driver *drv;
+
+	drv = env_driver_lookup(ENVOP_ERASE, gd->env_load_prio);
+	if (drv) {
+		int ret;
+
+		if (!drv->erase)
+			return -ENODEV;
+
+		if (!env_has_inited(drv->location))
+			return -ENODEV;
+
+		printf("Erasing Environment on %s... ", drv->name);
+		ret = drv->erase();
+		if (ret)
+			printf("Failed (%d)\n", ret);
+		else
+			printf("OK\n");
+
+		if (!ret)
+			return 0;
+	}
+
+	return -ENODEV;
+}
+
 int env_init(void)
 {
 	struct env_driver *drv;
diff --git a/env/mmc.c b/env/mmc.c
index c3cf35d..b7b833f 100644
--- a/env/mmc.c
+++ b/env/mmc.c
@@ -242,6 +242,54 @@
 	fini_mmc_for_env(mmc);
 	return ret;
 }
+
+#if defined(CONFIG_CMD_ERASEENV)
+static inline int erase_env(struct mmc *mmc, unsigned long size,
+			    unsigned long offset)
+{
+	uint blk_start, blk_cnt, n;
+	struct blk_desc *desc = mmc_get_blk_desc(mmc);
+
+	blk_start	= ALIGN(offset, mmc->write_bl_len) / mmc->write_bl_len;
+	blk_cnt		= ALIGN(size, mmc->write_bl_len) / mmc->write_bl_len;
+
+	n = blk_derase(desc, blk_start, blk_cnt);
+	printf("%d blocks erased: %s\n", n, (n == blk_cnt) ? "OK" : "ERROR");
+
+	return (n == blk_cnt) ? 0 : 1;
+}
+
+static int env_mmc_erase(void)
+{
+	int dev = mmc_get_env_dev();
+	struct mmc *mmc = find_mmc_device(dev);
+	int	ret, copy = 0;
+	u32	offset;
+	const char *errmsg;
+
+	errmsg = init_mmc_for_env(mmc);
+	if (errmsg) {
+		printf("%s\n", errmsg);
+		return 1;
+	}
+
+	if (mmc_get_env_addr(mmc, copy, &offset))
+		return CMD_RET_FAILURE;
+
+	ret = erase_env(mmc, CONFIG_ENV_SIZE, offset);
+
+#ifdef CONFIG_ENV_OFFSET_REDUND
+	copy = 1;
+
+	if (mmc_get_env_addr(mmc, copy, &offset))
+		return CMD_RET_FAILURE;
+
+	ret |= erase_env(mmc, CONFIG_ENV_SIZE, offset);
+#endif
+
+	return ret;
+}
+#endif /* CONFIG_CMD_ERASEENV */
 #endif /* CONFIG_CMD_SAVEENV && !CONFIG_SPL_BUILD */
 
 static inline int read_env(struct mmc *mmc, unsigned long size,
@@ -351,5 +399,8 @@
 	.load		= env_mmc_load,
 #ifndef CONFIG_SPL_BUILD
 	.save		= env_save_ptr(env_mmc_save),
+#if defined(CONFIG_CMD_ERASEENV)
+	.erase		= env_mmc_erase,
+#endif
 #endif
 };
diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 464c33d..5bf78b5 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -570,7 +570,7 @@
 				g_parent_inode->size = cpu_to_le32(new_size);
 
 				new_blockcnt = le32_to_cpu(g_parent_inode->blockcnt);
-				new_blockcnt += fs->sect_perblk;
+				new_blockcnt += fs->blksz >> LOG2_SECTOR_SIZE;
 				g_parent_inode->blockcnt = cpu_to_le32(new_blockcnt);
 
 				if (ext4fs_put_metadata
@@ -1571,8 +1571,12 @@
 	int log2blksz = get_fs()->dev_desc->log2blksz;
 	int desc_size = get_fs()->gdsize;
 
+	if (desc_size == 0)
+		return 0;
 	desc_per_blk = EXT2_BLOCK_SIZE(data) / desc_size;
 
+	if (desc_per_blk == 0)
+		return 0;
 	blkno = le32_to_cpu(data->sblock.first_data_block) + 1 +
 			group / desc_per_blk;
 	blkoff = (group % desc_per_blk) * desc_size;
@@ -1602,6 +1606,10 @@
 
 	/* It is easier to calculate if the first inode is 0. */
 	ino--;
+	if ( le32_to_cpu(sblock->inodes_per_group) == 0 || fs->inodesz == 0) {
+		free(blkgrp);
+		return 0;
+	}
 	status = ext4fs_blockgroup(data, ino / le32_to_cpu
 				   (sblock->inodes_per_group), blkgrp);
 	if (status == 0) {
@@ -1610,6 +1618,10 @@
 	}
 
 	inodes_per_block = EXT2_BLOCK_SIZE(data) / fs->inodesz;
+	if ( inodes_per_block == 0 ) {
+		free(blkgrp);
+		return 0;
+	}
 	blkno = ext4fs_bg_get_inode_table_id(blkgrp, fs) +
 	    (ino % le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block;
 	blkoff = (ino % inodes_per_block) * fs->inodesz;
diff --git a/fs/ext4/ext4_journal.c b/fs/ext4/ext4_journal.c
index 6adbab9..3559daf 100644
--- a/fs/ext4/ext4_journal.c
+++ b/fs/ext4/ext4_journal.c
@@ -645,6 +645,10 @@
 	struct ext_filesystem *fs = get_fs();
 	long int blknr;
 	int i;
+
+	if (!(fs->sb->feature_compatibility & EXT4_FEATURE_COMPAT_HAS_JOURNAL))
+		return;
+
 	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
 	blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++, NULL);
 	update_descriptor_block(blknr);
diff --git a/fs/ext4/ext4_journal.h b/fs/ext4/ext4_journal.h
index c9cf195..43fb8e7 100644
--- a/fs/ext4/ext4_journal.h
+++ b/fs/ext4/ext4_journal.h
@@ -17,6 +17,8 @@
 #ifndef __EXT4_JRNL__
 #define __EXT4_JRNL__
 
+#define EXT4_FEATURE_COMPAT_HAS_JOURNAL		0x0004
+
 #define EXT2_JOURNAL_INO		8	/* Journal inode */
 #define EXT2_JOURNAL_SUPERBLOCK	0	/* Journal  Superblock number */
 
diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c
index 504d23a..3368bd8 100644
--- a/fs/ext4/ext4_write.c
+++ b/fs/ext4/ext4_write.c
@@ -957,7 +957,7 @@
 	ext4fs_allocate_blocks(file_inode, blocks_remaining,
 			       &blks_reqd_for_file);
 	file_inode->blockcnt = cpu_to_le32((blks_reqd_for_file * fs->blksz) >>
-		fs->dev_desc->log2blksz);
+					   LOG2_SECTOR_SIZE);
 
 	temp_ptr = zalloc(fs->blksz);
 	if (!temp_ptr)
diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c
index 26db677..37b31d9 100644
--- a/fs/ext4/ext4fs.c
+++ b/fs/ext4/ext4fs.c
@@ -61,18 +61,21 @@
 	lbaint_t delayed_skipfirst = 0;
 	lbaint_t delayed_next = 0;
 	char *delayed_buf = NULL;
+	char *start_buf = buf;
 	short status;
 	struct ext_block_cache cache;
 
 	ext_cache_init(&cache);
 
-	if (blocksize <= 0)
-		return -1;
-
 	/* Adjust len so it we can't read past the end of the file. */
 	if (len + pos > filesize)
 		len = (filesize - pos);
 
+	if (blocksize <= 0 || len <= 0) {
+		ext_cache_fini(&cache);
+		return -1;
+	}
+
 	blockcnt = lldiv(((len + pos) + blocksize - 1), blocksize);
 
 	for (i = lldiv(pos, blocksize); i < blockcnt; i++) {
@@ -137,6 +140,7 @@
 			}
 		} else {
 			int n;
+			int n_left;
 			if (previous_block_number != -1) {
 				/* spill */
 				status = ext4fs_devread(delayed_start,
@@ -151,8 +155,9 @@
 			}
 			/* Zero no more than `len' bytes. */
 			n = blocksize - skipfirst;
-			if (n > len)
-				n = len;
+			n_left = len - ( buf - start_buf );
+			if (n > n_left)
+				n = n_left;
 			memset(buf, 0, n);
 		}
 		buf += blocksize - skipfirst;
@@ -286,7 +291,7 @@
 	if (!cache->buf)
 		return 0;
 	if (!ext4fs_devread(block, 0, size, cache->buf)) {
-		free(cache->buf);
+		ext_cache_fini(cache);
 		return 0;
 	}
 	cache->block = block;
diff --git a/include/configs/am65x_evm.h b/include/configs/am65x_evm.h
index b043bf8..1415bb1 100644
--- a/include/configs/am65x_evm.h
+++ b/include/configs/am65x_evm.h
@@ -19,6 +19,32 @@
 #define CONFIG_SYS_SDRAM_BASE1		0x880000000
 
 /* SPL Loader Configuration */
+#ifdef CONFIG_TARGET_AM654_A53_EVM
+#define CONFIG_SYS_INIT_SP_ADDR         (CONFIG_SPL_TEXT_BASE +	\
+					 CONFIG_SYS_K3_NON_SECURE_MSRAM_SIZE)
+#else
+/*
+ * Maximum size in memory allocated to the SPL BSS. Keep it as tight as
+ * possible (to allow the build to go through), as this directly affects
+ * our memory footprint. The less we use for BSS the more we have available
+ * for everything else.
+ */
+#define CONFIG_SPL_BSS_MAX_SIZE		0x5000
+/*
+ * Link BSS to be within SPL in a dedicated region located near the top of
+ * the MCU SRAM, this way making it available also before relocation. Note
+ * that we are not using the actual top of the MCU SRAM as there is a memory
+ * location filled in by the boot ROM that we want to read out without any
+ * interference from the C context.
+ */
+#define CONFIG_SPL_BSS_START_ADDR	(CONFIG_SYS_K3_BOOT_PARAM_TABLE_INDEX -\
+					 CONFIG_SPL_BSS_MAX_SIZE)
+/* Set the stack right below the SPL BSS section */
+#define CONFIG_SYS_INIT_SP_ADDR         CONFIG_SPL_BSS_START_ADDR
+/* Configure R5 SPL post-relocation malloc pool in DDR */
+#define CONFIG_SYS_SPL_MALLOC_START	0x84000000
+#define CONFIG_SYS_SPL_MALLOC_SIZE	SZ_16M
+#endif
 
 #ifdef CONFIG_SYS_K3_SPL_ATF
 #define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME	"tispl.bin"
@@ -29,26 +55,26 @@
 #endif
 
 #define CONFIG_SPL_MAX_SIZE		CONFIG_SYS_K3_MAX_DOWNLODABLE_IMAGE_SIZE
-#define CONFIG_SYS_INIT_SP_ADDR         (CONFIG_SPL_TEXT_BASE +	\
-					CONFIG_SYS_K3_NON_SECURE_MSRAM_SIZE - 4)
 
 #define CONFIG_SYS_BOOTM_LEN		SZ_64M
 
+#define PARTS_DEFAULT \
+	/* Linux partitions */ \
+	"name=rootfs,start=0,size=-,uuid=${uuid_gpt_rootfs}\0"
+
 /* U-Boot general configuration */
 #define EXTRA_ENV_AM65X_BOARD_SETTINGS					\
 	"findfdt="							\
-		"if test $board_name = am65x; then "			\
-			"setenv name_fdt k3-am654-base-board.dtb; "	\
-		"else if test $name_fdt = undefined; then "		\
-			"echo WARNING: Could not determine device tree to use;"\
-		"fi; fi; "						\
-		"setenv fdtfile ${name_fdt}\0"				\
+		"setenv name_fdt k3-am654-base-board.dtb;"		\
+		"setenv fdtfile ${name_fdt};"				\
+		"setenv overlay_files ${name_overlays}\0"		\
 	"loadaddr=0x80080000\0"						\
 	"fdtaddr=0x82000000\0"						\
+	"overlayaddr=0x83000000\0"					\
 	"name_kern=Image\0"						\
 	"console=ttyS2,115200n8\0"					\
 	"args_all=setenv optargs earlycon=ns16550a,mmio32,0x02800000\0" \
-	"run_kern=booti ${loadaddr} ${rd_spec} ${fdtaddr}\0"
+	"run_kern=booti ${loadaddr} ${rd_spec} ${fdtaddr}\0"		\
 
 /* U-Boot MMC-specific configuration */
 #define EXTRA_ENV_AM65X_BOARD_SETTINGS_MMC				\
@@ -59,8 +85,17 @@
 	"rd_spec=-\0"							\
 	"init_mmc=run args_all args_mmc\0"				\
 	"get_fdt_mmc=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${name_fdt}\0" \
+	"get_overlay_mmc="						\
+		"fdt address ${fdtaddr};"				\
+		"fdt resize 0x100000;"					\
+		"for overlay in $overlay_files;"			\
+		"do;"							\
+		"load mmc ${bootpart} ${overlayaddr} ${bootdir}/${overlay};"	\
+		"fdt apply ${overlayaddr};"				\
+		"done;\0"						\
 	"get_kern_mmc=load mmc ${bootpart} ${loadaddr} "		\
-		"${bootdir}/${name_kern}\0"
+		"${bootdir}/${name_kern}\0"				\
+	"partitions=" PARTS_DEFAULT
 
 /* Incorporate settings into the U-Boot environment */
 #define CONFIG_EXTRA_ENV_SETTINGS					\
@@ -68,6 +103,18 @@
 	EXTRA_ENV_AM65X_BOARD_SETTINGS					\
 	EXTRA_ENV_AM65X_BOARD_SETTINGS_MMC
 
+/* MMC ENV related defines */
+#ifdef CONFIG_ENV_IS_IN_MMC
+#define CONFIG_SYS_MMC_ENV_DEV		0
+#define CONFIG_SYS_MMC_ENV_PART	1
+#define CONFIG_ENV_SIZE		(128 << 10)
+#define CONFIG_ENV_OFFSET		0x680000
+#define CONFIG_ENV_OFFSET_REDUND	(CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
+#define CONFIG_SYS_REDUNDAND_ENVIRONMENT
+#endif
+
+#define CONFIG_SUPPORT_EMMC_BOOT
+
 /* Now for the remaining common defines */
 #include <configs/ti_armv7_common.h>
 
diff --git a/include/configs/qemu-arm.h b/include/configs/qemu-arm.h
index 65fdb1e..35e3c5a 100644
--- a/include/configs/qemu-arm.h
+++ b/include/configs/qemu-arm.h
@@ -46,8 +46,13 @@
 #define CONFIG_SYS_CBSIZE 512
 
 #define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
+#ifdef CONFIG_TFABOOT
+#define CONFIG_SYS_FLASH_BASE		0x4000000
+#define CONFIG_SYS_MAX_FLASH_BANKS	1
+#else
 #define CONFIG_SYS_FLASH_BASE		0x0
 #define CONFIG_SYS_MAX_FLASH_BANKS	2
+#endif
 #define CONFIG_SYS_MAX_FLASH_SECT	256 /* Sector: 256K, Bank: 64M */
 
 #endif /* __CONFIG_H */
diff --git a/include/configs/rk3036_common.h b/include/configs/rk3036_common.h
index f5d09d1..73be079 100644
--- a/include/configs/rk3036_common.h
+++ b/include/configs/rk3036_common.h
@@ -12,9 +12,10 @@
 #define CONFIG_SYS_CBSIZE		1024
 #define CONFIG_SKIP_LOWLEVEL_INIT
 
-#define CONFIG_SYS_TIMER_RATE		(24 * 1000 * 1000)
-#define CONFIG_SYS_TIMER_BASE		0x200440a0 /* TIMER5 */
-#define CONFIG_SYS_TIMER_COUNTER	(CONFIG_SYS_TIMER_BASE + 8)
+#define CONFIG_ROCKCHIP_STIMER_BASE	0x200440a0
+#define COUNTER_FREQUENCY		24000000
+#define CONFIG_SYS_ARCH_TIMER
+#define CONFIG_SYS_HZ_CLOCK		24000000
 
 #define CONFIG_SYS_INIT_SP_ADDR		0x60100000
 #define CONFIG_SYS_LOAD_ADDR		0x60800800
diff --git a/include/configs/rk3128_common.h b/include/configs/rk3128_common.h
index 0c08d7a..20d6243 100644
--- a/include/configs/rk3128_common.h
+++ b/include/configs/rk3128_common.h
@@ -14,9 +14,10 @@
 #define CONFIG_SYS_CBSIZE		1024
 #define CONFIG_SKIP_LOWLEVEL_INIT
 
-#define CONFIG_SYS_TIMER_RATE		(24 * 1000 * 1000)
-#define CONFIG_SYS_TIMER_BASE		0x200440a0 /* TIMER5 */
-#define CONFIG_SYS_TIMER_COUNTER	(CONFIG_SYS_TIMER_BASE + 8)
+#define CONFIG_ROCKCHIP_STIMER_BASE	0x200440a0
+#define COUNTER_FREQUENCY		24000000
+#define CONFIG_SYS_ARCH_TIMER
+#define CONFIG_SYS_HZ_CLOCK		24000000
 
 #define CONFIG_SYS_INIT_SP_ADDR		0x60100000
 #define CONFIG_SYS_LOAD_ADDR		0x60800800
diff --git a/include/configs/rk322x_common.h b/include/configs/rk322x_common.h
index 15bb8d6..cc08699 100644
--- a/include/configs/rk322x_common.h
+++ b/include/configs/rk322x_common.h
@@ -13,9 +13,10 @@
 #define CONFIG_SYS_CBSIZE		1024
 #define CONFIG_SYS_BOOTM_LEN	(64 << 20)	/*  64M */
 
-#define CONFIG_SYS_TIMER_RATE		(24 * 1000 * 1000)
-#define CONFIG_SYS_TIMER_BASE		0x110c00a0 /* TIMER5 */
-#define CONFIG_SYS_TIMER_COUNTER	(CONFIG_SYS_TIMER_BASE + 8)
+#define CONFIG_ROCKCHIP_STIMER_BASE	0x110d0020
+#define COUNTER_FREQUENCY		24000000
+#define CONFIG_SYS_ARCH_TIMER
+#define CONFIG_SYS_HZ_CLOCK		24000000
 
 #define CONFIG_SYS_INIT_SP_ADDR		0x61100000
 #define CONFIG_SYS_LOAD_ADDR		0x61800800
diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h
index 7c79ed6..5472a90 100644
--- a/include/configs/rk3288_common.h
+++ b/include/configs/rk3288_common.h
@@ -13,9 +13,10 @@
 #define CONFIG_SYS_MALLOC_LEN		(32 << 20)
 #define CONFIG_SYS_CBSIZE		1024
 
-#define CONFIG_SYS_TIMER_RATE		(24 * 1000 * 1000)
-#define	CONFIG_SYS_TIMER_BASE		0xff810020 /* TIMER7 */
-#define CONFIG_SYS_TIMER_COUNTER	(CONFIG_SYS_TIMER_BASE + 8)
+#define CONFIG_ROCKCHIP_STIMER_BASE	0xff810020
+#define COUNTER_FREQUENCY		24000000
+#define CONFIG_SYS_ARCH_TIMER
+#define CONFIG_SYS_HZ_CLOCK		24000000
 
 #ifdef CONFIG_SPL_ROCKCHIP_BACK_TO_BROM
 /* Bootrom will load u-boot binary to 0x0 once return from SPL */
@@ -35,6 +36,8 @@
 #define SDRAM_BANK_SIZE			(2UL << 30)
 #define SDRAM_MAX_SIZE			0xfe000000
 
+#define CONFIG_SYS_MONITOR_LEN (600 * 1024)
+
 #ifndef CONFIG_SPL_BUILD
 /* usb otg */
 
diff --git a/include/configs/rk3368_common.h b/include/configs/rk3368_common.h
index 13630ba..8a1e311 100644
--- a/include/configs/rk3368_common.h
+++ b/include/configs/rk3368_common.h
@@ -20,7 +20,8 @@
 #define CONFIG_SYS_CBSIZE		1024
 #define CONFIG_SKIP_LOWLEVEL_INIT
 
-#define COUNTER_FREQUENCY               24000000
+#define CONFIG_ROCKCHIP_STIMER_BASE	0xff830020
+#define COUNTER_FREQUENCY		24000000
 
 #define CONFIG_SYS_NS16550_MEM32
 
diff --git a/include/configs/rk3399_common.h b/include/configs/rk3399_common.h
index f31f265..8df0180 100644
--- a/include/configs/rk3399_common.h
+++ b/include/configs/rk3399_common.h
@@ -13,6 +13,7 @@
 #define CONFIG_SKIP_LOWLEVEL_INIT
 
 #define COUNTER_FREQUENCY               24000000
+#define CONFIG_ROCKCHIP_STIMER_BASE	0xff8680a0
 
 #define CONFIG_SYS_NS16550_MEM32
 
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index fceb812..7be94ee 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -257,9 +257,6 @@
 #endif
 #endif /* ifdef CONFIG_REQUIRE_SERIAL_CONSOLE */
 
-/* GPIO */
-#define CONFIG_SUNXI_GPIO
-
 #ifdef CONFIG_VIDEO_SUNXI
 /*
  * The amount of RAM to keep free at the top of RAM when relocating u-boot,
diff --git a/include/configs/tinker_rk3288.h b/include/configs/tinker_rk3288.h
index 32057b3..5adae68 100644
--- a/include/configs/tinker_rk3288.h
+++ b/include/configs/tinker_rk3288.h
@@ -18,6 +18,5 @@
 	func(DHCP, dchp, na)
 
 #define CONFIG_SYS_MMC_ENV_DEV 1
-#define CONFIG_SYS_MONITOR_LEN (600 * 1024)
 
 #endif
diff --git a/include/debug_uart.h b/include/debug_uart.h
index 34e8b2f..cd70ae1 100644
--- a/include/debug_uart.h
+++ b/include/debug_uart.h
@@ -104,6 +104,13 @@
  */
 void printhex8(uint value);
 
+/**
+ * printdec() - Output a decimalism value
+ *
+ * @value:	Value to output
+ */
+void printdec(uint value);
+
 #ifdef CONFIG_DEBUG_UART_ANNOUNCE
 #define _DEBUG_UART_ANNOUNCE	printascii("<debug_uart> ");
 #else
@@ -171,6 +178,18 @@
 		printhex(value, 8); \
 	} \
 \
+	void printdec(uint value) \
+	{ \
+		if (value > 10) { \
+			printdec(value / 10); \
+			value %= 10; \
+		} else if (value == 10) { \
+			_debug_uart_putc('1'); \
+			value = 0; \
+		} \
+		_debug_uart_putc('0' + value); \
+	} \
+\
 	void debug_uart_init(void) \
 	{ \
 		board_debug_uart_init(); \
diff --git a/include/dm/of_addr.h b/include/dm/of_addr.h
index 12b1a99..3fa1ffc 100644
--- a/include/dm/of_addr.h
+++ b/include/dm/of_addr.h
@@ -27,6 +27,24 @@
 u64 of_translate_address(const struct device_node *no, const __be32 *in_addr);
 
 /**
+ * of_translate_dma_address() - translate a device-tree DMA address to a CPU
+ *				address
+ *
+ * Translate a DMA address from the device-tree into a CPU physical address,
+ * this walks up the tree and applies the various bus mappings on the way.
+ *
+ * Note: We consider that crossing any level with #size-cells == 0 to mean
+ * that translation is impossible (that is we are not dealing with a value
+ * that can be mapped to a cpu physical address). This is not really specified
+ * that way, but this is traditionally the way IBM at least do things
+ *
+ * @np: node to check
+ * @in_addr: pointer to input DMA address
+ * @return translated DMA address or OF_BAD_ADDR on error
+ */
+u64 of_translate_dma_address(const struct device_node *no, const __be32 *in_addr);
+
+/**
  * of_get_address() - obtain an address from a node
  *
  * Extract an address from a node, returns the region size and the address
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 704f915..4f89db44 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -767,7 +767,7 @@
 	     node = ofnode_next_subnode(node))
 
 /**
- * ofnode_translate_address() - Tranlate a device-tree address
+ * ofnode_translate_address() - Translate a device-tree address
  *
  * Translate an address from the device-tree into a CPU physical address. This
  * function walks up the tree and applies the various bus mappings along the
@@ -781,6 +781,20 @@
 u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr);
 
 /**
+ * ofnode_translate_dma_address() - Translate a device-tree DMA address
+ *
+ * Translate a DMA address from the device-tree into a CPU physical address.
+ * This function walks up the tree and applies the various bus mappings along
+ * the way.
+ *
+ * @ofnode: Device tree node giving the context in which to translate the
+ *          DMA address
+ * @in_addr: pointer to the DMA address to translate
+ * @return the translated DMA address; OF_BAD_ADDR on error
+ */
+u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr);
+
+/**
  * ofnode_device_is_compatible() - check if the node is compatible with compat
  *
  * This allows to check whether the node is comaptible with the compat.
diff --git a/include/dm/read.h b/include/dm/read.h
index 60b727c..62d4be6 100644
--- a/include/dm/read.h
+++ b/include/dm/read.h
@@ -499,7 +499,7 @@
 			     struct resource *res);
 
 /**
- * dev_translate_address() - Tranlate a device-tree address
+ * dev_translate_address() - Translate a device-tree address
  *
  * Translate an address from the device-tree into a CPU physical address.  This
  * function walks up the tree and applies the various bus mappings along the
@@ -512,6 +512,19 @@
 u64 dev_translate_address(struct udevice *dev, const fdt32_t *in_addr);
 
 /**
+ * dev_translate_dma_address() - Translate a device-tree DMA address
+ *
+ * Translate a DMA address from the device-tree into a CPU physical address.
+ * This function walks up the tree and applies the various bus mappings along
+ * the way.
+ *
+ * @dev: device giving the context in which to translate the DMA address
+ * @in_addr: pointer to the DMA address to translate
+ * @return the translated DMA address; OF_BAD_ADDR on error
+ */
+u64 dev_translate_dma_address(struct udevice *dev, const fdt32_t *in_addr);
+
+/**
  * dev_read_alias_highest_id - Get highest alias id for the given stem
  * @stem:	Alias stem to be examined
  *
@@ -751,6 +764,11 @@
 	return ofnode_translate_address(dev_ofnode(dev), in_addr);
 }
 
+static inline u64 dev_translate_dma_address(struct udevice *dev, const fdt32_t *in_addr)
+{
+	return ofnode_translate_dma_address(dev_ofnode(dev), in_addr);
+}
+
 static inline int dev_read_alias_highest_id(const char *stem)
 {
 	return fdtdec_get_alias_highest_id(gd->fdt_blob, stem);
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index f9300a6..d4d9610 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -59,6 +59,7 @@
 	UCLASS_MAILBOX,		/* Mailbox controller */
 	UCLASS_MASS_STORAGE,	/* Mass storage device */
 	UCLASS_MDIO,		/* MDIO bus */
+	UCLASS_MDIO_MUX,	/* MDIO MUX/switch */
 	UCLASS_MISC,		/* Miscellaneous device */
 	UCLASS_MMC,		/* SD / MMC card or chip */
 	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
diff --git a/include/dt-bindings/clk/sifive-fu540-prci.h b/include/dt-bindings/clk/sifive-fu540-prci.h
deleted file mode 100644
index 531523e..0000000
--- a/include/dt-bindings/clk/sifive-fu540-prci.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) 2019 Western Digital Corporation or its affiliates.
- *
- * Copyright (C) 2018 SiFive, Inc.
- * Wesley Terpstra
- * Paul Walmsley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 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 __LINUX_CLK_SIFIVE_FU540_PRCI_H
-#define __LINUX_CLK_SIFIVE_FU540_PRCI_H
-
-/* Clock indexes for use by Device Tree data */
-
-#define PRCI_CLK_COREPLL		0
-#define PRCI_CLK_DDRPLL			1
-#define PRCI_CLK_GEMGXLPLL		2
-#define PRCI_CLK_TLCLK			3
-
-#endif
diff --git a/include/dt-bindings/clock/sifive-fu540-prci.h b/include/dt-bindings/clock/sifive-fu540-prci.h
new file mode 100644
index 0000000..6a0b70a
--- /dev/null
+++ b/include/dt-bindings/clock/sifive-fu540-prci.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018-2019 SiFive, Inc.
+ * Wesley Terpstra
+ * Paul Walmsley
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_SIFIVE_FU540_PRCI_H
+#define __DT_BINDINGS_CLOCK_SIFIVE_FU540_PRCI_H
+
+/* Clock indexes for use by Device Tree data and the PRCI driver */
+
+#define PRCI_CLK_COREPLL	       0
+#define PRCI_CLK_DDRPLL		       1
+#define PRCI_CLK_GEMGXLPLL	       2
+#define PRCI_CLK_TLCLK		       3
+
+#endif
diff --git a/include/environment.h b/include/environment.h
index cd96676..de67cf4 100644
--- a/include/environment.h
+++ b/include/environment.h
@@ -200,6 +200,7 @@
 	ENVOP_INIT,	/* we want to call the init function */
 	ENVOP_LOAD,	/* we want to call the load function */
 	ENVOP_SAVE,	/* we want to call the save function */
+	ENVOP_ERASE,	/* we want to call the erase function */
 };
 
 struct env_driver {
@@ -226,6 +227,15 @@
 	int (*save)(void);
 
 	/**
+	 * erase() - Erase the environment on storage
+	 *
+	 * This method is optional and required for 'eraseenv' to work.
+	 *
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*erase)(void);
+
+	/**
 	 * init() - Set up the initial pre-relocation environment
 	 *
 	 * This method is optional.
@@ -304,6 +314,13 @@
 int env_save(void);
 
 /**
+ * env_erase() - Erase the environment on storage
+ *
+ * @return 0 if OK, -ve on error
+ */
+int env_erase(void);
+
+/**
  * env_fix_drivers() - Updates envdriver as per relocation
  */
 void env_fix_drivers(void);
diff --git a/include/ext_common.h b/include/ext_common.h
index 17c92f1..1c10c50 100644
--- a/include/ext_common.h
+++ b/include/ext_common.h
@@ -21,6 +21,7 @@
 #define __EXT_COMMON__
 #include <command.h>
 #define SECTOR_SIZE		0x200
+#define LOG2_SECTOR_SIZE	9
 
 /* Magic value used to identify an ext2 filesystem.  */
 #define	EXT2_MAGIC			0xEF53
diff --git a/include/fdt_support.h b/include/fdt_support.h
index 27fe564..cefb2b2 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -218,8 +218,32 @@
 #endif
 
 void fdt_del_node_and_alias(void *blob, const char *alias);
+
+/**
+ * Translate an address from the DT into a CPU physical address
+ *
+ * The translation relies on the "ranges" property.
+ *
+ * @param blob		Pointer to device tree blob
+ * @param node_offset	Node DT offset
+ * @param in_addr	Pointer to the address to translate
+ * @return translated address or OF_BAD_ADDR on error
+ */
 u64 fdt_translate_address(const void *blob, int node_offset,
 			  const __be32 *in_addr);
+/**
+ * Translate a DMA address from the DT into a CPU physical address
+ *
+ * The translation relies on the "dma-ranges" property.
+ *
+ * @param blob		Pointer to device tree blob
+ * @param node_offset	Node DT offset
+ * @param in_addr	Pointer to the DMA address to translate
+ * @return translated DMA address or OF_BAD_ADDR on error
+ */
+u64 fdt_translate_dma_address(const void *blob, int node_offset,
+			      const __be32 *in_addr);
+
 int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
 					phys_addr_t compat_off);
 int fdt_alloc_phandle(void *blob);
diff --git a/include/linux/clk/analogbits-wrpll-cln28hpc.h b/include/linux/clk/analogbits-wrpll-cln28hpc.h
new file mode 100644
index 0000000..0327909
--- /dev/null
+++ b/include/linux/clk/analogbits-wrpll-cln28hpc.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018-2019 SiFive, Inc.
+ * Wesley Terpstra
+ * Paul Walmsley
+ */
+
+#ifndef __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H
+#define __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H
+
+#include <linux/types.h>
+
+/* DIVQ_VALUES: number of valid DIVQ values */
+#define DIVQ_VALUES				6
+
+/*
+ * Bit definitions for struct wrpll_cfg.flags
+ *
+ * WRPLL_FLAGS_BYPASS_FLAG: if set, the PLL is either in bypass, or should be
+ *	programmed to enter bypass
+ * WRPLL_FLAGS_RESET_FLAG: if set, the PLL is in reset
+ * WRPLL_FLAGS_INT_FEEDBACK_FLAG: if set, the PLL is configured for internal
+ *	feedback mode
+ * WRPLL_FLAGS_EXT_FEEDBACK_FLAG: if set, the PLL is configured for external
+ *	feedback mode (not yet supported by this driver)
+ */
+#define WRPLL_FLAGS_BYPASS_SHIFT		0
+#define WRPLL_FLAGS_BYPASS_MASK		BIT(WRPLL_FLAGS_BYPASS_SHIFT)
+#define WRPLL_FLAGS_RESET_SHIFT		1
+#define WRPLL_FLAGS_RESET_MASK		BIT(WRPLL_FLAGS_RESET_SHIFT)
+#define WRPLL_FLAGS_INT_FEEDBACK_SHIFT	2
+#define WRPLL_FLAGS_INT_FEEDBACK_MASK	BIT(WRPLL_FLAGS_INT_FEEDBACK_SHIFT)
+#define WRPLL_FLAGS_EXT_FEEDBACK_SHIFT	3
+#define WRPLL_FLAGS_EXT_FEEDBACK_MASK	BIT(WRPLL_FLAGS_EXT_FEEDBACK_SHIFT)
+
+/**
+ * struct wrpll_cfg - WRPLL configuration values
+ * @divr: reference divider value (6 bits), as presented to the PLL signals
+ * @divf: feedback divider value (9 bits), as presented to the PLL signals
+ * @divq: output divider value (3 bits), as presented to the PLL signals
+ * @flags: PLL configuration flags.  See above for more information
+ * @range: PLL loop filter range.  See below for more information
+ * @output_rate_cache: cached output rates, swept across DIVQ
+ * @parent_rate: PLL refclk rate for which values are valid
+ * @max_r: maximum possible R divider value, given @parent_rate
+ * @init_r: initial R divider value to start the search from
+ *
+ * @divr, @divq, @divq, @range represent what the PLL expects to see
+ * on its input signals.  Thus @divr and @divf are the actual divisors
+ * minus one.  @divq is a power-of-two divider; for example, 1 =
+ * divide-by-2 and 6 = divide-by-64.  0 is an invalid @divq value.
+ *
+ * When initially passing a struct wrpll_cfg record, the
+ * record should be zero-initialized with the exception of the @flags
+ * field.  The only flag bits that need to be set are either
+ * WRPLL_FLAGS_INT_FEEDBACK or WRPLL_FLAGS_EXT_FEEDBACK.
+ */
+struct wrpll_cfg {
+	u8 divr;
+	u8 divq;
+	u8 range;
+	u8 flags;
+	u16 divf;
+/* private: */
+	u32 output_rate_cache[DIVQ_VALUES];
+	unsigned long parent_rate;
+	u8 max_r;
+	u8 init_r;
+};
+
+int wrpll_configure_for_rate(struct wrpll_cfg *c, u32 target_rate,
+			     unsigned long parent_rate);
+
+unsigned int wrpll_calc_max_lock_us(const struct wrpll_cfg *c);
+
+unsigned long wrpll_calc_output_rate(const struct wrpll_cfg *c,
+				     unsigned long parent_rate);
+
+#endif /* __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H */
diff --git a/include/miiphy.h b/include/miiphy.h
index e6dd441..9b97d09 100644
--- a/include/miiphy.h
+++ b/include/miiphy.h
@@ -167,4 +167,24 @@
 
 #endif
 
+#ifdef CONFIG_DM_MDIO_MUX
+
+/* indicates none of the child buses is selected */
+#define MDIO_MUX_SELECT_NONE	-1
+
+/**
+ * struct mdio_mux_ops - MDIO MUX operations
+ *
+ * @select: Selects a child bus
+ * @deselect: Clean up selection.  Optional, can be NULL
+ */
+struct mdio_mux_ops {
+	int (*select)(struct udevice *mux, int cur, int sel);
+	int (*deselect)(struct udevice *mux, int sel);
+};
+
+#define mdio_mux_get_ops(dev) ((struct mdio_mux_ops *)(dev)->driver->ops)
+
+#endif
+
 #endif
diff --git a/include/net.h b/include/net.h
index 44b3238..7684076 100644
--- a/include/net.h
+++ b/include/net.h
@@ -728,7 +728,7 @@
 }
 
 /* return ulong *in network byteorder* */
-static inline u32 net_read_u32(u32 *from)
+static inline u32 net_read_u32(void *from)
 {
 	u32 l;
 
@@ -749,7 +749,7 @@
 }
 
 /* copy ulong */
-static inline void net_copy_u32(u32 *to, u32 *from)
+static inline void net_copy_u32(void *to, void *from)
 {
 	memcpy((void *)to, (void *)from, sizeof(u32));
 }
diff --git a/include/phy.h b/include/phy.h
index d01435d..f4530fa 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -246,15 +246,71 @@
 
 #endif
 
+/**
+ * phy_init() - Initializes the PHY drivers
+ *
+ * This function registers all available PHY drivers
+ *
+ * @return 0 if OK, -ve on error
+ */
 int phy_init(void);
+
+/**
+ * phy_reset() - Resets the specified PHY
+ *
+ * Issues a reset of the PHY and waits for it to complete
+ *
+ * @phydev:	PHY to reset
+ * @return 0 if OK, -ve on error
+ */
 int phy_reset(struct phy_device *phydev);
+
+/**
+ * phy_find_by_mask() - Searches for a PHY on the specified MDIO bus
+ *
+ * The function checks the PHY addresses flagged in phy_mask and returns a
+ * phy_device pointer if it detects a PHY.
+ * This function should only be called if just one PHY is expected to be present
+ * in the set of addresses flagged in phy_mask.  If multiple PHYs are present,
+ * it is undefined which of these PHYs is returned.
+ *
+ * @bus:	MII/MDIO bus to scan
+ * @phy_mask:	bitmap of PYH addresses to scan
+ * @interface:	type of MAC-PHY interface
+ * @return pointer to phy_device if a PHY is found, or NULL otherwise
+ */
 struct phy_device *phy_find_by_mask(struct mii_dev *bus, unsigned phy_mask,
 		phy_interface_t interface);
+
 #ifdef CONFIG_DM_ETH
+
+/**
+ * phy_connect_dev() - Associates the given pair of PHY and Ethernet devices
+ * @phydev:	PHY device
+ * @dev:	Ethernet device
+ */
 void phy_connect_dev(struct phy_device *phydev, struct udevice *dev);
+
+/**
+ * phy_connect() - Creates a PHY device for the Ethernet interface
+ *
+ * Creates a PHY device for the PHY at the given address, if one doesn't exist
+ * already, and associates it with the Ethernet device.
+ * The function may be called with addr <= 0, in this case addr value is ignored
+ * and the bus is scanned to detect a PHY.  Scanning should only be used if only
+ * one PHY is expected to be present on the MDIO bus, otherwise it is undefined
+ * which PHY is returned.
+ *
+ * @bus:	MII/MDIO bus that hosts the PHY
+ * @addr:	PHY address on MDIO bus
+ * @dev:	Ethernet device to associate to the PHY
+ * @interface:	type of MAC-PHY interface
+ * @return pointer to phy_device if a PHY is found, or NULL otherwise
+ */
 struct phy_device *phy_connect(struct mii_dev *bus, int addr,
 				struct udevice *dev,
 				phy_interface_t interface);
+
 static inline ofnode phy_get_ofnode(struct phy_device *phydev)
 {
 	if (ofnode_valid(phydev->node))
@@ -263,10 +319,34 @@
 		return dev_ofnode(phydev->dev);
 }
 #else
+
+/**
+ * phy_connect_dev() - Associates the given pair of PHY and Ethernet devices
+ * @phydev:	PHY device
+ * @dev:	Ethernet device
+ */
 void phy_connect_dev(struct phy_device *phydev, struct eth_device *dev);
+
+/**
+ * phy_connect() - Creates a PHY device for the Ethernet interface
+ *
+ * Creates a PHY device for the PHY at the given address, if one doesn't exist
+ * already, and associates it with the Ethernet device.
+ * The function may be called with addr <= 0, in this case addr value is ignored
+ * and the bus is scanned to detect a PHY.  Scanning should only be used if only
+ * one PHY is expected to be present on the MDIO bus, otherwise it is undefined
+ * which PHY is returned.
+ *
+ * @bus:	MII/MDIO bus that hosts the PHY
+ * @addr:	PHY address on MDIO bus
+ * @dev:	Ethernet device to associate to the PHY
+ * @interface:	type of MAC-PHY interface
+ * @return pointer to phy_device if a PHY is found, or NULL otherwise
+ */
 struct phy_device *phy_connect(struct mii_dev *bus, int addr,
 				struct eth_device *dev,
 				phy_interface_t interface);
+
 static inline ofnode phy_get_ofnode(struct phy_device *phydev)
 {
 	return ofnode_null();
diff --git a/include/power-domain.h b/include/power-domain.h
index 0099605..0737070 100644
--- a/include/power-domain.h
+++ b/include/power-domain.h
@@ -151,7 +151,7 @@
 #endif
 
 /**
- * power_domain_off - Disable power ot a power domain.
+ * power_domain_off - Disable power to a power domain.
  *
  * @power_domain:	A power domain struct that was previously successfully
  *		requested by power_domain_get().
diff --git a/include/regmap.h b/include/regmap.h
index 3cd7a66..0854200 100644
--- a/include/regmap.h
+++ b/include/regmap.h
@@ -330,6 +330,8 @@
 int regmap_init_mem_platdata(struct udevice *dev, fdt_val_t *reg, int count,
 			     struct regmap **mapp);
 
+int regmap_init_mem_index(ofnode node, struct regmap **mapp, int index);
+
 /**
  * regmap_get_range() - Obtain the base memory address of a regmap range
  *
diff --git a/include/remoteproc.h b/include/remoteproc.h
index a59dba8..c29c086 100644
--- a/include/remoteproc.h
+++ b/include/remoteproc.h
@@ -45,33 +45,86 @@
 };
 
 /**
- * struct dm_rproc_ops - Operations that are provided by remote proc driver
- * @init:	Initialize the remoteproc device invoked after probe (optional)
- *		Return 0 on success, -ve error on fail
- * @load:	Load the remoteproc device using data provided(mandatory)
- *		This takes the following additional arguments.
- *			addr- Address of the binary image to be loaded
- *			size- Size of the binary image to be loaded
- *		Return 0 on success, -ve error on fail
- * @start:	Start the remoteproc device (mandatory)
- *		Return 0 on success, -ve error on fail
- * @stop:	Stop the remoteproc device (optional)
- *		Return 0 on success, -ve error on fail
- * @reset:	Reset the remote proc device (optional)
- *		Return 0 on success, -ve error on fail
- * @is_running:	Check if the remote processor is running(optional)
- *		Return 0 on success, 1 if not running, -ve on others errors
- * @ping:	Ping the remote device for basic communication check(optional)
- *		Return 0 on success, 1 if not responding, -ve on other errors
+ * struct dm_rproc_ops - Driver model remote proc operations.
+ *
+ * This defines the operations provided by remote proc driver.
  */
 struct dm_rproc_ops {
+	/**
+	 * init() - Initialize the remoteproc device (optional)
+	 *
+	 * This is called after the probe is completed allowing the remote
+	 * processor drivers to split up the initializations between probe and
+	 * init if needed.
+	 *
+	 * @dev:	Remote proc device
+	 * @return 0 if all ok, else appropriate error value.
+	 */
 	int (*init)(struct udevice *dev);
+
+	/**
+	 * load() - Load the remoteproc device using data provided (mandatory)
+	 *
+	 * Load the remoteproc device with an image, do not start the device.
+	 *
+	 * @dev:	Remote proc device
+	 * @addr:	Address of the image to be loaded
+	 * @size:	Size of the image to be loaded
+	 * @return 0 if all ok, else appropriate error value.
+	 */
 	int (*load)(struct udevice *dev, ulong addr, ulong size);
+
+	/**
+	 * start() - Start the remoteproc device (mandatory)
+	 *
+	 * @dev:	Remote proc device
+	 * @return 0 if all ok, else appropriate error value.
+	 */
 	int (*start)(struct udevice *dev);
+
+	/**
+	 * stop() - Stop the remoteproc device (optional)
+	 *
+	 * @dev:	Remote proc device
+	 * @return 0 if all ok, else appropriate error value.
+	 */
 	int (*stop)(struct udevice *dev);
+
+	/**
+	 * reset() - Reset the remoteproc device (optional)
+	 *
+	 * @dev:	Remote proc device
+	 * @return 0 if all ok, else appropriate error value.
+	 */
 	int (*reset)(struct udevice *dev);
+
+	/**
+	 * is_running() - Check if the remote processor is running (optional)
+	 *
+	 * @dev:	Remote proc device
+	 * @return 0 if running, 1 if not running, -ve on error.
+	 */
 	int (*is_running)(struct udevice *dev);
+
+	/**
+	 * ping() - Ping the remote device for basic communication (optional)
+	 *
+	 * @dev:	Remote proc device
+	 * @return 0 on success, 1 if not responding, -ve on other errors.
+	 */
 	int (*ping)(struct udevice *dev);
+
+	/**
+	 * device_to_virt() - Return translated virtual address (optional)
+	 *
+	 * Translate a device address (remote processor view) to virtual
+	 * address (main processor view).
+	 *
+	 * @dev:	Remote proc device
+	 * @da:		Device address
+	 * @return virtual address.
+	 */
+	void * (*device_to_virt)(struct udevice *dev, ulong da);
 };
 
 /* Accessor */
@@ -80,82 +133,93 @@
 #ifdef CONFIG_REMOTEPROC
 /**
  * rproc_init() - Initialize all bound remote proc devices
- *
- * Return: 0 if all ok, else appropriate error value.
+ * @return 0 if all ok, else appropriate error value.
  */
 int rproc_init(void);
 
 /**
  * rproc_dev_init() - Initialize a remote proc device based on id
  * @id:		id of the remote processor
- *
- * Return: 0 if all ok, else appropriate error value.
+ * @return 0 if all ok, else appropriate error value.
  */
 int rproc_dev_init(int id);
 
 /**
  * rproc_is_initialized() - check to see if remoteproc devices are initialized
- *
- * Return: 0 if all devices are initialized, else appropriate error value.
+ * @return true if all devices are initialized, false otherwise.
  */
 bool rproc_is_initialized(void);
 
 /**
- * rproc_load() - load binary to a remote processor
+ * rproc_load() - load binary or elf to a remote processor
  * @id:		id of the remote processor
- * @addr:	address in memory where the binary image is located
- * @size:	size of the binary image
- *
- * Return: 0 if all ok, else appropriate error value.
+ * @addr:	address in memory where the image is located
+ * @size:	size of the image
+ * @return 0 if all ok, else appropriate error value.
  */
 int rproc_load(int id, ulong addr, ulong size);
 
 /**
  * rproc_start() - Start a remote processor
  * @id:		id of the remote processor
- *
- * Return: 0 if all ok, else appropriate error value.
+ * @return 0 if all ok, else appropriate error value.
  */
 int rproc_start(int id);
 
 /**
  * rproc_stop() - Stop a remote processor
  * @id:		id of the remote processor
- *
- * Return: 0 if all ok, else appropriate error value.
+ * @return 0 if all ok, else appropriate error value.
  */
 int rproc_stop(int id);
 
 /**
  * rproc_reset() - reset a remote processor
  * @id:		id of the remote processor
- *
- * Return: 0 if all ok, else appropriate error value.
+ * @return 0 if all ok, else appropriate error value.
  */
 int rproc_reset(int id);
 
 /**
  * rproc_ping() - ping a remote processor to check if it can communicate
  * @id:		id of the remote processor
+ * @return 0 if all ok, else appropriate error value.
  *
  * NOTE: this might need communication path available, which is not implemented
  * as part of remoteproc framework - hook on to appropriate bus architecture to
  * do the same
- *
- * Return: 0 if all ok, else appropriate error value.
  */
 int rproc_ping(int id);
 
 /**
  * rproc_is_running() - check to see if remote processor is running
  * @id:		id of the remote processor
+ * @return 0 if running, 1 if not running, -ve on error.
  *
  * NOTE: this may not involve actual communication capability of the remote
  * processor, but just ensures that it is out of reset and executing code.
- *
- * Return: 0 if all ok, else appropriate error value.
  */
 int rproc_is_running(int id);
+
+/**
+ * rproc_elf32_sanity_check() - Verify if an image is a valid ELF32 one
+ *
+ * Check if a valid ELF32 image exists at the given memory location. Verify
+ * basic ELF32 format requirements like magic number and sections size.
+ *
+ * @addr:	address of the image to verify
+ * @size:	size of the image
+ * @return 0 if the image looks good, else appropriate error value.
+ */
+int rproc_elf32_sanity_check(ulong addr, ulong size);
+
+/**
+ * rproc_elf32_load_image() - load an ELF32 image
+ * @dev:	device loading the ELF32 image
+ * @addr:	valid ELF32 image address
+ * @return 0 if the image is successfully loaded, else appropriate error value.
+ */
+int rproc_elf32_load_image(struct udevice *dev, unsigned long addr);
 #else
 static inline int rproc_init(void) { return -ENOSYS; }
 static inline int rproc_dev_init(int id) { return -ENOSYS; }
@@ -166,6 +230,10 @@
 static inline int rproc_reset(int id) { return -ENOSYS; }
 static inline int rproc_ping(int id) { return -ENOSYS; }
 static inline int rproc_is_running(int id) { return -ENOSYS; }
+static inline int rproc_elf32_sanity_check(ulong addr,
+					   ulong size) { return -ENOSYS; }
+static inline int rproc_elf32_load_image(struct udevice *dev,
+					 unsigned long addr) { return -ENOSYS; }
 #endif
 
 #endif	/* _RPROC_H_ */
diff --git a/include/sdhci.h b/include/sdhci.h
index eee493a..01addb7 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -144,7 +144,23 @@
 
 #define SDHCI_ACMD12_ERR	0x3C
 
-/* 3E-3F reserved */
+#define SDHCI_HOST_CONTROL2	0x3E
+#define  SDHCI_CTRL_UHS_MASK	0x0007
+#define  SDHCI_CTRL_UHS_SDR12	0x0000
+#define  SDHCI_CTRL_UHS_SDR25	0x0001
+#define  SDHCI_CTRL_UHS_SDR50	0x0002
+#define  SDHCI_CTRL_UHS_SDR104	0x0003
+#define  SDHCI_CTRL_UHS_DDR50	0x0004
+#define  SDHCI_CTRL_HS400	0x0005 /* Non-standard */
+#define  SDHCI_CTRL_VDD_180	0x0008
+#define  SDHCI_CTRL_DRV_TYPE_MASK	0x0030
+#define  SDHCI_CTRL_DRV_TYPE_B	0x0000
+#define  SDHCI_CTRL_DRV_TYPE_A	0x0010
+#define  SDHCI_CTRL_DRV_TYPE_C	0x0020
+#define  SDHCI_CTRL_DRV_TYPE_D	0x0030
+#define  SDHCI_CTRL_EXEC_TUNING	0x0040
+#define  SDHCI_CTRL_TUNED_CLK	0x0080
+#define  SDHCI_CTRL_PRESET_VAL_ENABLE	0x8000
 
 #define SDHCI_CAPABILITIES	0x40
 #define  SDHCI_TIMEOUT_CLK_MASK	0x0000003F
@@ -247,7 +263,7 @@
 #endif
 	int	(*get_cd)(struct sdhci_host *host);
 	void	(*set_control_reg)(struct sdhci_host *host);
-	void	(*set_ios_post)(struct sdhci_host *host);
+	int	(*set_ios_post)(struct sdhci_host *host);
 	void	(*set_clock)(struct sdhci_host *host, u32 div);
 	int (*platform_execute_tuning)(struct mmc *host, u8 opcode);
 	void (*set_delay)(struct sdhci_host *host);
@@ -467,9 +483,11 @@
 int add_sdhci(struct sdhci_host *host, u32 f_max, u32 f_min);
 #endif /* !CONFIG_BLK */
 
+void sdhci_set_uhs_timing(struct sdhci_host *host);
 #ifdef CONFIG_DM_MMC
 /* Export the operations to drivers */
 int sdhci_probe(struct udevice *dev);
+int sdhci_set_clock(struct mmc *mmc, unsigned int clock);
 extern const struct dm_mmc_ops sdhci_ops;
 #else
 #endif
diff --git a/include/spl.h b/include/spl.h
index a9aaef3..a90f971 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -109,6 +109,15 @@
 binman_sym_extern(ulong, u_boot_any, image_pos);
 
 /**
+ * spl_load_simple_fit_skip_processing() - Hook to allow skipping the FIT
+ *	image processing during spl_load_simple_fit().
+ *
+ * Return true to skip FIT processing, false to preserve the full code flow
+ * of spl_load_simple_fit().
+ */
+bool spl_load_simple_fit_skip_processing(void);
+
+/**
  * spl_load_simple_fit() - Loads a fit image from a device.
  * @spl_image:	Image description to set up
  * @info:	Structure containing the information required to load data.
@@ -331,6 +340,23 @@
 		       struct spl_boot_device *bootdev);
 
 /**
+ * spl_mmc_load() - Load an image file from MMC/SD media
+ *
+ * @param spl_image	Image data filled in by loading process
+ * @param bootdev	Describes which device to load from
+ * @param filename	Name of file to load (in FS mode)
+ * @param raw_part	Partition to load from (in RAW mode)
+ * @param raw_sect	Sector to load from (in RAW mode)
+ *
+ * @return 0 on success, otherwise error code
+ */
+int spl_mmc_load(struct spl_image_info *spl_image,
+		 struct spl_boot_device *bootdev,
+		 const char *filename,
+		 int raw_part,
+		 unsigned long raw_sect);
+
+/**
  * spl_invoke_atf - boot using an ARM trusted firmware image
  */
 void spl_invoke_atf(struct spl_image_info *spl_image);
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
index fb5e07b..5b5905a 100644
--- a/lib/rsa/rsa-sign.c
+++ b/lib/rsa/rsa-sign.c
@@ -141,6 +141,15 @@
 			snprintf(key_id, sizeof(key_id),
 				 "pkcs11:object=%s;type=public",
 				 name);
+	} else if (engine_id) {
+		if (keydir)
+			snprintf(key_id, sizeof(key_id),
+				 "%s%s",
+				 keydir, name);
+		else
+			snprintf(key_id, sizeof(key_id),
+				 "%s",
+				 name);
 	} else {
 		fprintf(stderr, "Engine not supported\n");
 		return -ENOTSUP;
@@ -252,6 +261,15 @@
 			snprintf(key_id, sizeof(key_id),
 				 "pkcs11:object=%s;type=private",
 				 name);
+	} else if (engine_id) {
+		if (keydir)
+			snprintf(key_id, sizeof(key_id),
+				 "%s%s",
+				 keydir, name);
+		else
+			snprintf(key_id, sizeof(key_id),
+				 "%s",
+				 name);
 	} else {
 		fprintf(stderr, "Engine not supported\n");
 		return -ENOTSUP;
diff --git a/net/Makefile b/net/Makefile
index 6251ff3..826544f 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -16,6 +16,7 @@
 obj-$(CONFIG_NET)      += eth_legacy.o
 endif
 obj-$(CONFIG_DM_MDIO)  += mdio-uclass.o
+obj-$(CONFIG_DM_MDIO_MUX) += mdio-mux-uclass.o
 obj-$(CONFIG_NET)      += eth_common.o
 obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o
 obj-$(CONFIG_NET)      += net.o
diff --git a/net/mdio-mux-uclass.c b/net/mdio-mux-uclass.c
new file mode 100644
index 0000000..e425207
--- /dev/null
+++ b/net/mdio-mux-uclass.c
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019
+ * Alex Marginean, NXP
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <miiphy.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+#include <dm/lists.h>
+
+#define MDIO_MUX_CHILD_DRV_NAME	"mdio-mux-bus-drv"
+
+/**
+ * struct mdio_mux_perdev_priv - Per-device class data for MDIO MUX DM
+ *
+ * @parent_mdio: Parent DM MDIO device, this is called for actual MDIO I/O after
+ *               setting up the mux.  Typically this is a real MDIO device,
+ *               unless there are cascaded muxes.
+ * @selected:    Current child bus selection.  Defaults to -1
+ */
+struct mdio_mux_perdev_priv {
+	struct udevice *mdio_parent;
+	int selected;
+};
+
+/*
+ * This source file uses three types of devices, as follows:
+ * - mux is the hardware MDIO MUX which selects between the existing child MDIO
+ * buses, this is the device relevant for MDIO MUX class of drivers.
+ * - ch is a child MDIO bus, this is just a representation of a mux selection,
+ * not a real piece of hardware.
+ * - mdio_parent is the actual MDIO bus called to perform reads/writes after
+ * the MUX is configured.  Typically this is a real MDIO device, unless there
+ * are cascaded muxes.
+ */
+
+/**
+ * struct mdio_mux_ch_data - Per-device data for child MDIOs
+ *
+ * @sel: Selection value used by the MDIO MUX to access this child MDIO bus
+ */
+struct mdio_mux_ch_data {
+	int sel;
+};
+
+static struct udevice *mmux_get_parent_mdio(struct udevice *mux)
+{
+	struct mdio_mux_perdev_priv *pdata = dev_get_uclass_priv(mux);
+
+	return pdata->mdio_parent;
+}
+
+static struct mdio_ops *mmux_get_mdio_parent_ops(struct udevice *mux)
+{
+	return mdio_get_ops(mmux_get_parent_mdio(mux));
+}
+
+/* call driver select function before performing MDIO r/w */
+static int mmux_change_sel(struct udevice *ch, bool sel)
+{
+	struct udevice *mux = ch->parent;
+	struct mdio_mux_perdev_priv *priv = dev_get_uclass_priv(mux);
+	struct mdio_mux_ops *ops = mdio_mux_get_ops(mux);
+	struct mdio_mux_ch_data *ch_data = dev_get_parent_platdata(ch);
+	int err = 0;
+
+	if (sel) {
+		err = ops->select(mux, priv->selected, ch_data->sel);
+		if (err)
+			return err;
+
+		priv->selected = ch_data->sel;
+	} else {
+		if (ops->deselect) {
+			ops->deselect(mux, ch_data->sel);
+			priv->selected = MDIO_MUX_SELECT_NONE;
+		}
+	}
+
+	return 0;
+}
+
+/* Read wrapper, sets up the mux before issuing a read on parent MDIO bus */
+static int mmux_read(struct udevice *ch, int addr, int devad,
+		     int reg)
+{
+	struct udevice *mux = ch->parent;
+	struct udevice *parent_mdio = mmux_get_parent_mdio(mux);
+	struct mdio_ops *parent_ops = mmux_get_mdio_parent_ops(mux);
+	int err;
+
+	err = mmux_change_sel(ch, true);
+	if (err)
+		return err;
+
+	err = parent_ops->read(parent_mdio, addr, devad, reg);
+	mmux_change_sel(ch, false);
+
+	return err;
+}
+
+/* Write wrapper, sets up the mux before issuing a write on parent MDIO bus */
+static int mmux_write(struct udevice *ch, int addr, int devad,
+		      int reg, u16 val)
+{
+	struct udevice *mux = ch->parent;
+	struct udevice *parent_mdio = mmux_get_parent_mdio(mux);
+	struct mdio_ops *parent_ops = mmux_get_mdio_parent_ops(mux);
+	int err;
+
+	err = mmux_change_sel(ch, true);
+	if (err)
+		return err;
+
+	err = parent_ops->write(parent_mdio, addr, devad, reg, val);
+	mmux_change_sel(ch, false);
+
+	return err;
+}
+
+/* Reset wrapper, sets up the mux before issuing a reset on parent MDIO bus */
+static int mmux_reset(struct udevice *ch)
+{
+	struct udevice *mux = ch->parent;
+	struct udevice *parent_mdio = mmux_get_parent_mdio(mux);
+	struct mdio_ops *parent_ops = mmux_get_mdio_parent_ops(mux);
+	int err;
+
+	/* reset is optional, if it's not implemented just exit */
+	if (!parent_ops->reset)
+		return 0;
+
+	err = mmux_change_sel(ch, true);
+	if (err)
+		return err;
+
+	err = parent_ops->reset(parent_mdio);
+	mmux_change_sel(ch, false);
+
+	return err;
+}
+
+/* Picks up the mux selection value for each child */
+static int dm_mdio_mux_child_post_bind(struct udevice *ch)
+{
+	struct mdio_mux_ch_data *ch_data = dev_get_parent_platdata(ch);
+
+	ch_data->sel = dev_read_u32_default(ch, "reg", MDIO_MUX_SELECT_NONE);
+
+	if (ch_data->sel == MDIO_MUX_SELECT_NONE)
+		return -EINVAL;
+
+	return 0;
+}
+
+/* Explicitly bind child MDIOs after binding the mux */
+static int dm_mdio_mux_post_bind(struct udevice *mux)
+{
+	ofnode ch_node;
+	int err, first_err = 0;
+
+	if (!ofnode_valid(mux->node)) {
+		debug("%s: no mux node found, no child MDIO busses set up\n",
+		      __func__);
+		return 0;
+	}
+
+	/*
+	 * we're going by Linux bindings so the child nodes do not have
+	 * compatible strings.  We're going through them here and binding to
+	 * them.
+	 */
+	dev_for_each_subnode(ch_node, mux) {
+		struct udevice *ch_dev;
+		const char *ch_name;
+
+		ch_name = ofnode_get_name(ch_node);
+
+		err = device_bind_driver_to_node(mux, MDIO_MUX_CHILD_DRV_NAME,
+						 ch_name, ch_node, &ch_dev);
+		/* try to bind all, but keep 1st error */
+		if (err && !first_err)
+			first_err = err;
+	}
+
+	return first_err;
+}
+
+/* Get a reference to the parent MDIO bus, it should be bound by now */
+static int dm_mdio_mux_post_probe(struct udevice *mux)
+{
+	struct mdio_mux_perdev_priv *priv = dev_get_uclass_priv(mux);
+	int err;
+
+	priv->selected = MDIO_MUX_SELECT_NONE;
+
+	/* pick up mdio parent from device tree */
+	err = uclass_get_device_by_phandle(UCLASS_MDIO, mux, "mdio-parent-bus",
+					   &priv->mdio_parent);
+	if (err) {
+		debug("%s: didn't find mdio-parent-bus\n", __func__);
+		return err;
+	}
+
+	return 0;
+}
+
+const struct mdio_ops mmux_child_mdio_ops = {
+	.read = mmux_read,
+	.write = mmux_write,
+	.reset = mmux_reset,
+};
+
+/* MDIO class driver used for MUX child MDIO buses */
+U_BOOT_DRIVER(mdio_mux_child) = {
+	.name		= MDIO_MUX_CHILD_DRV_NAME,
+	.id		= UCLASS_MDIO,
+	.ops		= &mmux_child_mdio_ops,
+};
+
+UCLASS_DRIVER(mdio_mux) = {
+	.id = UCLASS_MDIO_MUX,
+	.name = "mdio-mux",
+	.child_post_bind = dm_mdio_mux_child_post_bind,
+	.post_bind  = dm_mdio_mux_post_bind,
+	.post_probe = dm_mdio_mux_post_probe,
+	.per_device_auto_alloc_size = sizeof(struct mdio_mux_perdev_priv),
+	.per_child_platdata_auto_alloc_size = sizeof(struct mdio_mux_ch_data),
+};
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index 44c0396..e616f72 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -61,7 +61,6 @@
 CONFIG_ARM_GIC_BASE_ADDRESS
 CONFIG_ARM_PL180_MMCI_BASE
 CONFIG_ARM_PL180_MMCI_CLOCK_FREQ
-CONFIG_ARM_THUMB
 CONFIG_ARP_TIMEOUT
 CONFIG_ASTRO_COFDMDUOS2
 CONFIG_ASTRO_TWIN7S2
@@ -1533,6 +1532,7 @@
 CONFIG_ROCKCHIP_CHIP_TAG
 CONFIG_ROCKCHIP_MAX_INIT_SIZE
 CONFIG_ROCKCHIP_SDHCI_MAX_FREQ
+CONFIG_ROCKCHIP_STIMER_BASE
 CONFIG_ROM_STUBS
 CONFIG_ROOTFS_OFFSET
 CONFIG_ROOTPATH
@@ -1826,7 +1826,6 @@
 CONFIG_STV0991_HZ
 CONFIG_STV0991_HZ_CLOCK
 CONFIG_ST_SMI
-CONFIG_SUNXI_GPIO
 CONFIG_SUNXI_MAX_FB_SIZE
 CONFIG_SUVD3
 CONFIG_SXNI855T
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 6a36cc0..7b4dd6e 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -63,4 +63,5 @@
 obj-$(CONFIG_VIRTIO_SANDBOX) += virtio.o
 obj-$(CONFIG_DMA) += dma.o
 obj-$(CONFIG_DM_MDIO) += mdio.o
+obj-$(CONFIG_DM_MDIO_MUX) += mdio_mux.o
 endif
diff --git a/test/dm/mdio.c b/test/dm/mdio.c
index 5b66255..dc229ae 100644
--- a/test/dm/mdio.c
+++ b/test/dm/mdio.c
@@ -13,6 +13,9 @@
 
 /* macros copied over from mdio_sandbox.c */
 #define SANDBOX_PHY_ADDR	5
+#define SANDBOX_PHY_REG_CNT	2
+
+/* test using 1st register, 0 */
 #define SANDBOX_PHY_REG		0
 
 #define TEST_REG_VALUE		0xabcd
diff --git a/test/dm/mdio_mux.c b/test/dm/mdio_mux.c
new file mode 100644
index 0000000..f962e09
--- /dev/null
+++ b/test/dm/mdio_mux.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019
+ * Alex Marginean, NXP
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <misc.h>
+#include <test/ut.h>
+#include <miiphy.h>
+
+/* macros copied over from mdio_sandbox.c */
+#define SANDBOX_PHY_ADDR	5
+#define SANDBOX_PHY_REG_CNT	2
+
+#define TEST_REG_VALUE		0xabcd
+
+static int dm_test_mdio_mux(struct unit_test_state *uts)
+{
+	struct uclass *uc;
+	struct udevice *mux;
+	struct udevice *mdio_ch0, *mdio_ch1, *mdio;
+	struct mdio_ops *ops, *ops_parent;
+	struct mdio_mux_ops *mmops;
+	u16 reg;
+
+	ut_assertok(uclass_get(UCLASS_MDIO_MUX, &uc));
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_MDIO_MUX, "mdio-mux-test",
+					      &mux));
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_MDIO, "mdio-ch-test@0",
+					      &mdio_ch0));
+	ut_assertok(uclass_get_device_by_name(UCLASS_MDIO, "mdio-ch-test@1",
+					      &mdio_ch1));
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_MDIO, "mdio-test", &mdio));
+
+	ops = mdio_get_ops(mdio_ch0);
+	ut_assertnonnull(ops);
+	ut_assertnonnull(ops->read);
+	ut_assertnonnull(ops->write);
+
+	mmops = mdio_mux_get_ops(mux);
+	ut_assertnonnull(mmops);
+	ut_assertnonnull(mmops->select);
+
+	ops_parent = mdio_get_ops(mdio);
+	ut_assertnonnull(ops);
+	ut_assertnonnull(ops->read);
+
+	/*
+	 * mux driver sets last register on the emulated PHY whenever a group
+	 * is selected to the selection #.  Just reading that register from
+	 * either of the child buses should return the id of the child bus
+	 */
+	reg = ops->read(mdio_ch0, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE,
+			SANDBOX_PHY_REG_CNT - 1);
+	ut_asserteq(reg, 0);
+
+	reg = ops->read(mdio_ch1, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE,
+			SANDBOX_PHY_REG_CNT - 1);
+	ut_asserteq(reg, 1);
+
+	mmops->select(mux, MDIO_MUX_SELECT_NONE, 5);
+	reg = ops_parent->read(mdio, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE,
+			SANDBOX_PHY_REG_CNT - 1);
+	ut_asserteq(reg, 5);
+
+	mmops->deselect(mux, 5);
+	reg = ops_parent->read(mdio, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE,
+			SANDBOX_PHY_REG_CNT - 1);
+	ut_asserteq(reg, (u16)MDIO_MUX_SELECT_NONE);
+
+	return 0;
+}
+
+DM_TEST(dm_test_mdio_mux, DM_TESTF_SCAN_FDT);
diff --git a/test/dm/remoteproc.c b/test/dm/remoteproc.c
index 3975c67..a2c4be7 100644
--- a/test/dm/remoteproc.c
+++ b/test/dm/remoteproc.c
@@ -5,8 +5,10 @@
  */
 #include <common.h>
 #include <dm.h>
+#include <elf.h>
 #include <errno.h>
 #include <remoteproc.h>
+#include <asm/io.h>
 #include <dm/test.h>
 #include <test/ut.h>
 /**
@@ -65,3 +67,123 @@
 	return 0;
 }
 DM_TEST(dm_test_remoteproc_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+#define DEVICE_TO_PHYSICAL_OFFSET	0x1000
+/**
+ * dm_test_remoteproc_elf() - test the ELF operations
+ * @uts:	unit test state
+ *
+ * Return:	0 if test passed, else error
+ */
+static int dm_test_remoteproc_elf(struct unit_test_state *uts)
+{
+	u8 valid_elf32[] = {
+		/* @0x00 - ELF HEADER - */
+		/* ELF magic */
+		0x7f, 0x45, 0x4c, 0x46,
+		/* 32 Bits */
+		0x01,
+		/* Endianness */
+#ifdef __LITTLE_ENDIAN
+		0x01,
+#else
+		0x02,
+#endif
+		/* Version */
+		0x01,
+		/* Padding */
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		/* Type : executable */
+		0x02, 0x00,
+		/* Machine: ARM */
+		0x28, 0x00,
+		/* Version */
+		0x01, 0x00, 0x00, 0x00,
+		/* Entry */
+		0x00, 0x00, 0x00, 0x08,
+		/* phoff (program header offset @ 0x40)*/
+		0x40, 0x00, 0x00, 0x00,
+		/* shoff (section header offset : none) */
+		0x00, 0x00, 0x00, 0x00,
+		/* flags */
+		0x00, 0x00, 0x00, 0x00,
+		/* ehsize (elf header size = 0x34) */
+		0x34, 0x00,
+		/* phentsize (program header size = 0x20) */
+		0x20, 0x00,
+		/* phnum (program header number : 1) */
+		0x01, 0x00,
+		/* shentsize (section heade size : none) */
+		0x00, 0x00,
+		/* shnum (section header number: none) */
+		0x00, 0x00,
+		/* shstrndx (section header name section index: none) */
+		0x00, 0x00,
+		/* padding */
+		0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00,
+		/* @0x40 - PROGRAM HEADER TABLE - */
+		/* type : PT_LOAD */
+		0x01, 0x00, 0x00, 0x00,
+		/* offset */
+		0x00, 0x00, 0x00, 0x00,
+		/* vaddr */
+		0x00, 0x00, 0x00, 0x00,
+		/* paddr : physical address */
+		0x00, 0x00, 0x00, 0x00,
+		/* filesz : 0x20 bytes (program header size) */
+		0x20, 0x00, 0x00, 0x00,
+		/* memsz = filesz */
+		0x20, 0x00, 0x00, 0x00,
+		/* flags : readable and exectuable */
+		0x05, 0x00, 0x00, 0x00,
+		/* padding */
+		0x00, 0x00, 0x00, 0x00,
+	};
+	unsigned int size = ARRAY_SIZE(valid_elf32);
+	struct udevice *dev;
+	phys_addr_t loaded_firmware_paddr;
+	void *loaded_firmware;
+	u32 loaded_firmware_size;
+	Elf32_Ehdr *ehdr = (Elf32_Ehdr *)valid_elf32;
+	Elf32_Phdr *phdr = (Elf32_Phdr *)(valid_elf32 + ehdr->e_phoff);
+
+	ut_assertok(uclass_get_device(UCLASS_REMOTEPROC, 0, &dev));
+
+	/*
+	 * In its Program Header Table, let the firmware specifies to be loaded
+	 * at SDRAM_BASE *device* address (p_paddr field).
+	 * Its size is defined by the p_filesz field.
+	 */
+	phdr->p_paddr = CONFIG_SYS_SDRAM_BASE;
+	loaded_firmware_size = phdr->p_filesz;
+
+	/*
+	 * This *device* address is converted to a *physical* address by the
+	 * device_to_virt() operation of sandbox_test_rproc which returns
+	 * DeviceAddress + DEVICE_TO_PHYSICAL_OFFSET.
+	 * This is where we expect to get the firmware loaded.
+	 */
+	loaded_firmware_paddr = phdr->p_paddr + DEVICE_TO_PHYSICAL_OFFSET;
+	loaded_firmware = map_physmem(loaded_firmware_paddr,
+				      loaded_firmware_size, MAP_NOCACHE);
+	ut_assertnonnull(loaded_firmware);
+	memset(loaded_firmware, 0, loaded_firmware_size);
+
+	/* Verify valid ELF format */
+	ut_assertok(rproc_elf32_sanity_check((ulong)valid_elf32, size));
+
+	/* Load firmware in loaded_firmware, and verify it */
+	ut_assertok(rproc_elf32_load_image(dev, (unsigned long)valid_elf32));
+	ut_assertok(memcmp(loaded_firmware, valid_elf32, loaded_firmware_size));
+	unmap_physmem(loaded_firmware, MAP_NOCACHE);
+
+	/* Invalid ELF Magic */
+	valid_elf32[0] = 0;
+	ut_asserteq(-EPROTONOSUPPORT,
+		    rproc_elf32_sanity_check((ulong)valid_elf32, size));
+
+	return 0;
+}
+DM_TEST(dm_test_remoteproc_elf, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index be16c99..ad85916 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -490,6 +490,7 @@
 static int dm_test_fdt_translation(struct unit_test_state *uts)
 {
 	struct udevice *dev;
+	fdt32_t dma_addr[2];
 
 	/* Some simple translations */
 	ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev));
@@ -509,6 +510,17 @@
 	ut_asserteq_str("dev@42", dev->name);
 	ut_asserteq(0x42, dev_read_addr(dev));
 
+	/* dma address translation */
+	ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev));
+	dma_addr[0] = cpu_to_be32(0);
+	dma_addr[1] = cpu_to_be32(0);
+	ut_asserteq(0x10000000, dev_translate_dma_address(dev, dma_addr));
+
+	ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 1, true, &dev));
+	dma_addr[0] = cpu_to_be32(1);
+	dma_addr[1] = cpu_to_be32(0x100);
+	ut_asserteq(0x20000000, dev_translate_dma_address(dev, dma_addr));
+
 	return 0;
 }
 DM_TEST(dm_test_fdt_translation, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index c8edb33..229d7eb 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -40,16 +40,19 @@
                 fd = os.open(persistent, os.O_RDWR | os.O_CREAT)
                 os.ftruncate(fd, 4194304)
                 os.close(fd)
-                cmd = ('sgdisk', '-U', '375a56f7-d6c9-4e81-b5f0-09d41ca89efe',
+                cmd = ('sgdisk',
+                    '--disk-guid=375a56f7-d6c9-4e81-b5f0-09d41ca89efe',
                     persistent)
                 u_boot_utils.run_and_log(u_boot_console, cmd)
                 # part1 offset 1MB size 1MB
-                cmd = ('sgdisk', '--new=1:2048:4095', '-c 1:part1', persistent)
+                cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1',
+                    persistent)
                 # part2 offset 2MB size 1.5MB
                 u_boot_utils.run_and_log(u_boot_console, cmd)
-                cmd = ('sgdisk', '--new=2:4096:7167', '-c 2:part2', persistent)
+                cmd = ('sgdisk', '--new=2:4096:7167', '--change-name=2:part2',
+                    persistent)
                 u_boot_utils.run_and_log(u_boot_console, cmd)
-                cmd = ('sgdisk', '-l', persistent)
+                cmd = ('sgdisk', '--load-backup=' + persistent)
                 u_boot_utils.run_and_log(u_boot_console, cmd)
 
         cmd = ('cp', persistent, self.path)
diff --git a/tools/mkenvimage.c b/tools/mkenvimage.c
index 75967d0..a8eebab 100644
--- a/tools/mkenvimage.c
+++ b/tools/mkenvimage.c
@@ -65,10 +65,12 @@
 	exit(EXIT_FAILURE);
 }
 
+#define CHUNK_SIZE 4096
+
 int main(int argc, char **argv)
 {
 	uint32_t crc, targetendian_crc;
-	const char *txt_filename = NULL, *bin_filename = NULL;
+	const char *bin_filename = NULL;
 	int txt_fd, bin_fd;
 	unsigned char *dataptr, *envptr;
 	unsigned char *filebuf = NULL;
@@ -76,12 +78,11 @@
 	int bigendian = 0;
 	int redundant = 0;
 	unsigned char padbyte = 0xff;
+	int readbytes = 0;
 
 	int option;
 	int ret = EXIT_SUCCESS;
 
-	struct stat txt_file_stat;
-
 	int fp, ep;
 	const char *prg;
 
@@ -156,63 +157,33 @@
 
 	/* Open the input file ... */
 	if (optind >= argc || strcmp(argv[optind], "-") == 0) {
-		int readbytes = 0;
-		int readlen = sizeof(*envptr) * 4096;
 		txt_fd = STDIN_FILENO;
-
-		do {
-			filebuf = realloc(filebuf, filesize + readlen);
-			if (!filebuf) {
-				fprintf(stderr, "Can't realloc memory for the input file buffer\n");
-				return EXIT_FAILURE;
-			}
-			readbytes = read(txt_fd, filebuf + filesize, readlen);
-			if (readbytes < 0) {
-				fprintf(stderr, "Error while reading stdin: %s\n",
-						strerror(errno));
-				return EXIT_FAILURE;
-			}
-			filesize += readbytes;
-		} while (readbytes == readlen);
-
 	} else {
-		txt_filename = argv[optind];
-		txt_fd = open(txt_filename, O_RDONLY);
+		txt_fd = open(argv[optind], O_RDONLY);
 		if (txt_fd == -1) {
 			fprintf(stderr, "Can't open \"%s\": %s\n",
-					txt_filename, strerror(errno));
+					argv[optind], strerror(errno));
 			return EXIT_FAILURE;
 		}
-		/* ... and check it */
-		ret = fstat(txt_fd, &txt_file_stat);
-		if (ret == -1) {
-			fprintf(stderr, "Can't stat() on \"%s\": %s\n",
-					txt_filename, strerror(errno));
+	}
+
+	do {
+		filebuf = realloc(filebuf, filesize + CHUNK_SIZE);
+		if (!filebuf) {
+			fprintf(stderr, "Can't realloc memory for the input file buffer\n");
 			return EXIT_FAILURE;
 		}
-
-		filesize = txt_file_stat.st_size;
-
-		filebuf = mmap(NULL, sizeof(*envptr) * filesize, PROT_READ,
-			       MAP_PRIVATE, txt_fd, 0);
-		if (filebuf == MAP_FAILED) {
-			fprintf(stderr, "mmap (%zu bytes) failed: %s\n",
-					sizeof(*envptr) * filesize,
-					strerror(errno));
-			fprintf(stderr, "Falling back to read()\n");
-
-			filebuf = malloc(sizeof(*envptr) * filesize);
-			ret = read(txt_fd, filebuf, sizeof(*envptr) * filesize);
-			if (ret != sizeof(*envptr) * filesize) {
-				fprintf(stderr, "Can't read the whole input file (%zu bytes): %s\n",
-					sizeof(*envptr) * filesize,
-					strerror(errno));
-
-				return EXIT_FAILURE;
-			}
+		readbytes = read(txt_fd, filebuf + filesize, CHUNK_SIZE);
+		if (readbytes < 0) {
+			fprintf(stderr, "Error while reading: %s\n",
+				strerror(errno));
+			return EXIT_FAILURE;
 		}
+		filesize += readbytes;
+	} while (readbytes > 0);
+
+	if (txt_fd != STDIN_FILENO)
 		ret = close(txt_fd);
-	}
 
 	/* Parse a byte at time until reaching the file OR until the environment fills
 	 * up. Check ep against envsize - 1 to allow for extra trailing '\0'. */
diff --git a/tools/mkimage.c b/tools/mkimage.c
index d1e1a67..4217188 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -105,7 +105,7 @@
 		"          -F => re-sign existing FIT image\n"
 		"          -p => place external data at a static position\n"
 		"          -r => mark keys used as 'required' in dtb\n"
-		"          -N => engine to use for signing (pkcs11)\n");
+		"          -N => openssl engine to use for signing\n");
 #else
 	fprintf(stderr,
 		"Signing / verified boot not supported (CONFIG_FIT_SIGNATURE undefined)\n");