Merge branch 'master' of git://git.denx.de/u-boot-net
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/arch/arm/Kconfig b/arch/arm/Kconfig
index 05606d9..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
@@ -1100,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
@@ -1115,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
@@ -1133,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
@@ -1165,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.
@@ -1178,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.
@@ -1218,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.
@@ -1229,6 +1236,7 @@
 	bool "Support ls1012ardb"
 	select ARCH_LS1012A
 	select ARM64
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_LATE_INIT
 	imply SCSI
 	imply SCSI_AHCI
@@ -1242,6 +1250,7 @@
 	bool "Support ls1012a2g5rdb"
 	select ARCH_LS1012A
 	select ARM64
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_LATE_INIT
 	imply SCSI
 	help
@@ -1254,6 +1263,7 @@
 	bool "Support ls1012afrwy"
 	select ARCH_LS1012A
 	select ARM64
+	select ARCH_SUPPORT_TFABOOT
 	select BOARD_LATE_INIT
 	imply SCSI
 	imply SCSI_AHCI
@@ -1267,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
@@ -1278,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
@@ -1289,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
@@ -1301,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
@@ -1359,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
@@ -1373,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
@@ -1384,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
@@ -1403,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
@@ -1422,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
@@ -1565,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/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";
@@ -252,6 +222,14 @@
 	u-boot,dm-spl;
 };
 
+&wkup_pmx0 {
+	u-boot,dm-spl;
+
+	wkup_i2c0_pins_default {
+		u-boot,dm-spl;
+	};
+};
+
 &main_pmx0 {
 	u-boot,dm-spl;
 	main_uart0_pins_default: main_uart0_pins_default {
@@ -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,6 +136,32 @@
 		>;
 		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 {
@@ -137,3 +169,23 @@
 	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/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/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/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;
@@ -391,6 +596,34 @@
 		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
+		env_set("board_serial", unknown);
+}
+
 static u64 mac_to_u64(u8 mac[6])
 {
 	int i;
@@ -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,6 +226,37 @@
 #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
@@ -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/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/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/spl/Kconfig b/common/spl/Kconfig
index 7122c06..5978fb2 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -248,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/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/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/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/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/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.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/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)
 
-The following examples use the Nitrokey Pro. Instructions for other devices may vary.
+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 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/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/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/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/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/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/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/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/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/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/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/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index 79872ba..bd16795 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
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,64 +157,34 @@
 
 	/* 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));
-			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;
-			}
-		}
-		ret = close(txt_fd);
 	}
 
+	do {
+		filebuf = realloc(filebuf, filesize + CHUNK_SIZE);
+		if (!filebuf) {
+			fprintf(stderr, "Can't realloc memory for the input file buffer\n");
+			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'. */
 	for (fp = 0, ep = 0 ; fp < filesize && ep < envsize - 1; fp++) {
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");