Merge branch 'rmobile' of git://git.denx.de/u-boot-sh

[trini: Drop CMD_BOOTI as it's now on by default on ARM64]
Signed-off-by: Tom Rini <trini@konsulko.com>
diff --git a/Kconfig b/Kconfig
index 3ceff25..45a0669 100644
--- a/Kconfig
+++ b/Kconfig
@@ -57,7 +57,8 @@
 	bool "Select defaults suitable for booting general purpose Linux distributions"
 	default y if ARCH_SUNXI
 	default n
-	select CMD_BOOTZ
+	select CMD_BOOTZ if ARM && !ARM64
+	select CMD_BOOTI if ARM64
 	select CMD_DHCP
 	select CMD_EXT2
 	select CMD_EXT4
@@ -114,7 +115,24 @@
 	  Warning:
 	  When disabling this, please check if malloc calls, maybe
 	  should be replaced by calloc - if one expects zeroed memory.
+
+config TOOLS_DEBUG
+	bool "Enable debug information for tools"
+	help
+	  Enable generation of debug information for tools such as mkimage.
+	  This can be used for debugging purposes. With debug information
+	  it is possible to set breakpoints on particular lines, single-step
+	  debug through the source code, etc.
+
 endif
+
+config PHYS_64BIT
+	bool "64bit physical address support"
+	help
+	  Say Y here to support 64bit physical memory address.
+	  This can be used not only for 64bit SoCs, but also for
+	  large physical address extention on 32bit SoCs.
+
 endmenu		# General setup
 
 menu "Boot images"
@@ -313,12 +331,49 @@
 	  particular it can handle selecting from multiple device tree
 	  and passing the correct one to U-Boot.
 
+config SPL_FIT_IMAGE_POST_PROCESS
+	bool "Enable post-processing of FIT artifacts after loading by the SPL"
+	depends on SPL_LOAD_FIT && TI_SECURE_DEVICE
+	help
+	  Allows doing any sort of manipulation to blobs after they got extracted
+	  from the U-Boot FIT image like stripping off headers or modifying the
+	  size of the blob, verification, authentication, decryption etc. in a
+	  platform or board specific way. In order to use this feature a platform
+	  or board-specific implementation of board_fit_image_post_process() must
+	  be provided. Also, anything done during this post-processing step would
+	  need to be comprehended in how the images were prepared before being
+	  injected into the FIT creation (i.e. the blobs would have been pre-
+	  processed before being added to the FIT image).
+
+config FIT_IMAGE_POST_PROCESS
+	bool "Enable post-processing of FIT artifacts after loading by U-Boot"
+	depends on FIT && TI_SECURE_DEVICE
+	help
+	  Allows doing any sort of manipulation to blobs after they got extracted
+	  from FIT images like stripping off headers or modifying the size of the
+	  blob, verification, authentication, decryption etc. in a platform or
+	  board specific way. In order to use this feature a platform or board-
+	  specific implementation of board_fit_image_post_process() must be
+	  provided. Also, anything done during this post-processing step would
+	  need to be comprehended in how the images were prepared before being
+	  injected into the FIT creation (i.e. the blobs would have been pre-
+	  processed before being added to the FIT image).
+
 config SYS_CLK_FREQ
 	depends on ARC || ARCH_SUNXI
 	int "CPU clock frequency"
 	help
 	  TODO: Move CONFIG_SYS_CLK_FREQ for all the architecture
 
+config ARCH_FIXUP_FDT
+	bool "Enable arch_fixup_fdt() call"
+	depends on ARM || MIPS
+	default y
+	help
+	  Enable FDT memory map syncup before OS boot. This feature can be
+	  used for booting OS with different memory setup where the part of
+	  the memory location should be used for different purpose.
+
 endmenu		# Boot images
 
 source "common/Kconfig"
diff --git a/MAINTAINERS b/MAINTAINERS
index e9ded5e..8e67202 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -102,6 +102,7 @@
 F:	arch/arm/include/asm/arch-mx*/
 F:	arch/arm/include/asm/arch-vf610/
 F:	arch/arm/include/asm/imx-common/
+F:	board/freescale/*mx*/
 
 ARM HISILICON
 M:	Peter Griffin <peter.griffin@linaro.org>
@@ -304,7 +305,7 @@
 F:	arch/mips/
 
 MMC
-M:	Pantelis Antoniou <panto@antoniou-consulting.com>
+M:	Jaehoon Chung <jh80.chung@samsung.com>
 S:	Maintained
 T:	git git://git.denx.de/u-boot-mmc.git
 F:	drivers/mmc/
@@ -459,6 +460,11 @@
 T:	git git://git.denx.de/u-boot-x86.git
 F:	arch/x86/
 
+XTENSA
+M:	Max Filippov <jcmvbkbc@gmail.com>
+S:	Maintained
+F:	arch/xtensa/
+
 THE REST
 M:	Tom Rini <trini@konsulko.com>
 L:	u-boot@lists.denx.de
diff --git a/MAKEALL b/MAKEALL
deleted file mode 100755
index 7e42f10..0000000
--- a/MAKEALL
+++ /dev/null
@@ -1,850 +0,0 @@
-#!/bin/bash
-# Tool mainly for U-Boot Quality Assurance: build one or more board
-# configurations with minimal verbosity, showing only warnings and
-# errors.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-
-usage()
-{
-	# if exiting with 0, write to stdout, else write to stderr
-	local ret=${1:-0}
-	[ "${ret}" -eq 1 ] && exec 1>&2
-	cat <<-EOF
-	Usage: MAKEALL [options] [--] [boards-to-build]
-
-	Options:
-	  -a ARCH,   --arch ARCH       Build all boards with arch ARCH
-	  -c CPU,    --cpu CPU         Build all boards with cpu CPU
-	  -v VENDOR, --vendor VENDOR   Build all boards with vendor VENDOR
-	  -s SOC,    --soc SOC         Build all boards with soc SOC
-	  -b BOARD,  --board BOARD     Build all boards with board name BOARD
-	  -l,        --list            List all targets to be built
-	  -m,        --maintainers     List all targets and maintainer email
-	  -M,        --mails           List all targets and all affilated emails
-	  -C,        --check           Enable build checking
-	  -n,        --continue        Continue (skip boards already built)
-	  -r,        --rebuild-errors  Rebuild any boards that errored
-	  -h,        --help            This help output
-
-	Selections by these options are logically ANDed; if the same option
-	is used repeatedly, such selections are ORed.  So "-v FOO -v BAR"
-	will select all configurations where the vendor is either FOO or
-	BAR.  Any additional arguments specified on the command line are
-	always build additionally.  See the boards.cfg file for more info.
-
-	If no boards are specified, then the default is "powerpc".
-
-	Environment variables:
-	  BUILD_NCPUS      number of parallel make jobs (default: auto)
-	  CROSS_COMPILE    cross-compiler toolchain prefix (default: "")
-	  CROSS_COMPILE_<ARCH> cross-compiler toolchain prefix for
-			   architecture "ARCH".  Substitute "ARCH" for any
-			   supported architecture (default: "")
-	  MAKEALL_LOGDIR   output all logs to here (default: ./LOG/)
-	  BUILD_DIR        output build directory (default: ./)
-	  BUILD_NBUILDS	   number of parallel targets (default: 1)
-
-	Examples:
-	  - build all Power Architecture boards:
-	      MAKEALL -a powerpc
-	      MAKEALL --arch powerpc
-	      MAKEALL powerpc
-	  - build all PowerPC boards manufactured by vendor "esd":
-	      MAKEALL -a powerpc -v esd
-	  - build all PowerPC boards manufactured either by "keymile" or "siemens":
-	      MAKEALL -a powerpc -v keymile -v siemens
-	  - build all Freescale boards with MPC83xx CPUs, plus all 4xx boards:
-	      MAKEALL -c mpc83xx -v freescale 4xx
-	EOF
-	exit ${ret}
-}
-
-deprecation() {
-	echo "** Note: MAKEALL is deprecated - please use buildman instead"
-	echo "** See tools/buildman/README for details"
-	echo
-}
-
-deprecation
-
-SHORT_OPTS="ha:c:v:s:b:lmMCnr"
-LONG_OPTS="help,arch:,cpu:,vendor:,soc:,board:,list,maintainers,mails,check,continue,rebuild-errors"
-
-# Option processing based on util-linux-2.13/getopt-parse.bash
-
-# Note that we use `"$@"' to let each command-line parameter expand to a
-# separate word. The quotes around `$@' are essential!
-# We need TEMP as the `eval set --' would nuke the return value of
-# getopt.
-TEMP=`getopt -o ${SHORT_OPTS} --long ${LONG_OPTS} \
-     -n 'MAKEALL' -- "$@"`
-
-[ $? != 0 ] && usage 1
-
-# Note the quotes around `$TEMP': they are essential!
-eval set -- "$TEMP"
-
-SELECTED=''
-ONLY_LIST=''
-PRINT_MAINTS=''
-MAINTAINERS_ONLY=''
-CONTINUE=''
-REBUILD_ERRORS=''
-
-while true ; do
-	case "$1" in
-	-a|--arch)
-		# echo "Option ARCH: argument \`$2'"
-		if [ "$opt_a" ] ; then
-			opt_a="${opt_a%)} || \$2 == \"$2\")"
-		else
-			opt_a="(\$2 == \"$2\")"
-		fi
-		SELECTED='y'
-		shift 2 ;;
-	-c|--cpu)
-		# echo "Option CPU: argument \`$2'"
-		if [ "$opt_c" ] ; then
-			opt_c="${opt_c%)} || \$3 == \"$2\" || \$3 ~ /$2:/)"
-		else
-			opt_c="(\$3 == \"$2\" || \$3 ~ /$2:/)"
-		fi
-		SELECTED='y'
-		shift 2 ;;
-	-s|--soc)
-		# echo "Option SoC: argument \`$2'"
-		if [ "$opt_s" ] ; then
-			opt_s="${opt_s%)} || \$4 == \"$2\" || \$4 ~ /$2/)"
-		else
-			opt_s="(\$4 == \"$2\" || \$4 ~ /$2/)"
-		fi
-		SELECTED='y'
-		shift 2 ;;
-	-v|--vendor)
-		# echo "Option VENDOR: argument \`$2'"
-		if [ "$opt_v" ] ; then
-			opt_v="${opt_v%)} || \$5 == \"$2\")"
-		else
-			opt_v="(\$5 == \"$2\")"
-		fi
-		SELECTED='y'
-		shift 2 ;;
-	-b|--board)
-		# echo "Option BOARD: argument \`$2'"
-		if [ "$opt_b" ] ; then
-			opt_b="${opt_b%)} || \$6 == \"$2\" || \$7 == \"$2\")"
-		else
-			# We need to check the 7th field too
-			# for boards whose 6th field is "-"
-			opt_b="(\$6 == \"$2\" || \$7 == \"$2\")"
-		fi
-		SELECTED='y'
-		shift 2 ;;
-	-C|--check)
-		CHECK='C=1'
-		shift ;;
-	-n|--continue)
-		CONTINUE='y'
-		shift ;;
-	-r|--rebuild-errors)
-		REBUILD_ERRORS='y'
-		shift ;;
-	-l|--list)
-		ONLY_LIST='y'
-		shift ;;
-	-m|--maintainers)
-		ONLY_LIST='y'
-		PRINT_MAINTS='y'
-		MAINTAINERS_ONLY='y'
-		shift ;;
-	-M|--mails)
-		ONLY_LIST='y'
-		PRINT_MAINTS='y'
-		shift ;;
-	-h|--help)
-		usage ;;
-	--)
-		shift ; break ;;
-	*)
-		echo "Internal error!" >&2 ; exit 1 ;;
-	esac
-done
-
-GNU_MAKE=$(scripts/show-gnu-make) || {
-	echo "GNU Make not found" >&2
-	exit 1
-}
-
-# echo "Remaining arguments:"
-# for arg do echo '--> '"\`$arg'" ; done
-
-tools/genboardscfg.py || {
-	echo "Failed to generate boards.cfg" >&2
-	exit 1
-}
-
-FILTER="\$1 !~ /^#/"
-[ "$opt_a" ] && FILTER="${FILTER} && $opt_a"
-[ "$opt_c" ] && FILTER="${FILTER} && $opt_c"
-[ "$opt_s" ] && FILTER="${FILTER} && $opt_s"
-[ "$opt_v" ] && FILTER="${FILTER} && $opt_v"
-[ "$opt_b" ] && FILTER="${FILTER} && $opt_b"
-
-if [ "$SELECTED" ] ; then
-	SELECTED=$(awk '('"$FILTER"') { print $7 }' boards.cfg)
-
-	# Make sure some boards from boards.cfg are actually found
-	if [ -z "$SELECTED" ] ; then
-		echo "Error: No boards selected, invalid arguments"
-		exit 1
-	fi
-fi
-
-#########################################################################
-
-# Print statistics when we exit
-trap exit 1 2 3 15
-trap print_stats 0
-
-# Determine number of CPU cores if no default was set
-: ${BUILD_NCPUS:="`getconf _NPROCESSORS_ONLN`"}
-
-if [ "$BUILD_NCPUS" -gt 1 ]
-then
-	JOBS="-j $((BUILD_NCPUS + 1))"
-else
-	JOBS=""
-fi
-
-if [ "${MAKEALL_LOGDIR}" ] ; then
-	LOG_DIR=${MAKEALL_LOGDIR}
-else
-	LOG_DIR="LOG"
-fi
-
-: ${BUILD_NBUILDS:=1}
-BUILD_MANY=0
-
-if [ "${BUILD_NBUILDS}" -gt 1 ] ; then
-	BUILD_MANY=1
-	: ${BUILD_DIR:=./build}
-	mkdir -p "${BUILD_DIR}/ERR"
-	find "${BUILD_DIR}/ERR/" -type f -exec rm -f {} +
-fi
-
-: ${BUILD_DIR:=.}
-
-OUTPUT_PREFIX="${BUILD_DIR}"
-
-[ -d ${LOG_DIR} ] || mkdir "${LOG_DIR}" || exit 1
-if [ "$CONTINUE" != 'y' -a "$REBUILD_ERRORS" != 'y' ] ; then
-	find "${LOG_DIR}/" -type f -exec rm -f {} +
-fi
-
-LIST=""
-
-# Keep track of the number of builds and errors
-ERR_CNT=0
-ERR_LIST=""
-WRN_CNT=0
-WRN_LIST=""
-TOTAL_CNT=0
-SKIP_CNT=0
-CURRENT_CNT=0
-OLDEST_IDX=1
-RC=0
-
-# Helper funcs for parsing boards.cfg
-targets_by_field()
-{
-	field=$1
-	regexp=$2
-
-	awk '($1 !~ /^#/ && $'"$field"' ~ /^'"$regexp"'$/) { print $7 }' \
-								boards.cfg
-}
-
-targets_by_arch() { targets_by_field 2 "$@" ; }
-targets_by_cpu()  { targets_by_field 3 "$@" ; targets_by_field 3 "$@:.*" ; }
-targets_by_soc()  { targets_by_field 4 "$@" ; }
-
-#########################################################################
-## MPC5xx Systems
-#########################################################################
-
-LIST_5xx="$(targets_by_cpu mpc5xx)"
-
-#########################################################################
-## MPC5xxx Systems
-#########################################################################
-
-LIST_5xxx="$(targets_by_cpu mpc5xxx)"
-
-#########################################################################
-## MPC512x Systems
-#########################################################################
-
-LIST_512x="$(targets_by_cpu mpc512x)"
-
-#########################################################################
-## MPC8xx Systems
-#########################################################################
-
-LIST_8xx="$(targets_by_cpu mpc8xx)"
-
-#########################################################################
-## PPC4xx Systems
-#########################################################################
-
-LIST_4xx="$(targets_by_cpu ppc4xx)"
-
-#########################################################################
-## MPC8260 Systems (includes 8250, 8255 etc.)
-#########################################################################
-
-LIST_8260="$(targets_by_cpu mpc8260)"
-
-#########################################################################
-## MPC83xx Systems (includes 8349, etc.)
-#########################################################################
-
-LIST_83xx="$(targets_by_cpu mpc83xx)"
-
-#########################################################################
-## MPC85xx Systems (includes 8540, 8560 etc.)
-#########################################################################
-
-LIST_85xx="$(targets_by_cpu mpc85xx)"
-
-#########################################################################
-## MPC86xx Systems
-#########################################################################
-
-LIST_86xx="$(targets_by_cpu mpc86xx)"
-
-#########################################################################
-## PowerPC groups
-#########################################################################
-
-LIST_TSEC="		\
-	${LIST_83xx}	\
-	${LIST_85xx}	\
-	${LIST_86xx}	\
-"
-
-LIST_powerpc="		\
-	${LIST_5xx}	\
-	${LIST_512x}	\
-	${LIST_5xxx}	\
-	${LIST_8xx}	\
-	${LIST_824x}	\
-	${LIST_8260}	\
-	${LIST_83xx}	\
-	${LIST_85xx}	\
-	${LIST_86xx}	\
-	${LIST_4xx}	\
-"
-
-# Alias "ppc" -> "powerpc" to not break compatibility with older scripts
-# still using "ppc" instead of "powerpc"
-LIST_ppc="		\
-	${LIST_powerpc}	\
-"
-
-#########################################################################
-## StrongARM Systems
-#########################################################################
-
-LIST_SA="$(targets_by_cpu sa1100)"
-
-#########################################################################
-## ARM7 Systems
-#########################################################################
-
-LIST_ARM7="$(targets_by_cpu arm720t)"
-
-#########################################################################
-## ARM9 Systems
-#########################################################################
-
-LIST_ARM9="$(targets_by_cpu arm920t)	\
-	$(targets_by_cpu arm926ejs)	\
-	$(targets_by_cpu arm946es)	\
-"
-
-#########################################################################
-## ARM11 Systems
-#########################################################################
-LIST_ARM11="$(targets_by_cpu arm1136)	\
-	$(targets_by_cpu arm1176)	\
-"
-
-#########################################################################
-## ARMV7 Systems
-#########################################################################
-
-LIST_ARMV7="$(targets_by_cpu armv7)"
-
-#########################################################################
-## ARMV8 Systems
-#########################################################################
-
-LIST_ARMV8="$(targets_by_cpu armv8)"
-
-#########################################################################
-## AT91 Systems
-#########################################################################
-
-LIST_at91="$(targets_by_soc at91)"
-
-#########################################################################
-## Xscale Systems
-#########################################################################
-
-LIST_pxa="$(targets_by_cpu pxa)"
-
-#########################################################################
-## SPEAr Systems
-#########################################################################
-
-LIST_spear="$(targets_by_soc spear)"
-
-#########################################################################
-## ARM groups
-#########################################################################
-
-LIST_arm="$(targets_by_arch arm |		\
-	for ARMV8_TARGET in $LIST_ARMV8;	\
-		do sed "/$ARMV8_TARGET/d";	\
-	done)					\
-"
-
-#########################################################################
-## MIPS Systems		(default = big endian)
-#########################################################################
-
-LIST_mips="$(targets_by_arch mips)"
-
-#########################################################################
-## OpenRISC Systems
-#########################################################################
-
-LIST_openrisc="$(targets_by_arch openrisc)"
-
-#########################################################################
-## x86 Systems
-#########################################################################
-
-LIST_x86="$(targets_by_arch x86)"
-
-#########################################################################
-## Nios-II Systems
-#########################################################################
-
-LIST_nios2="$(targets_by_arch nios2)"
-
-#########################################################################
-## MicroBlaze Systems
-#########################################################################
-
-LIST_microblaze="$(targets_by_arch microblaze)"
-
-#########################################################################
-## ColdFire Systems
-#########################################################################
-
-LIST_m68k="$(targets_by_arch m68k)"
-LIST_coldfire=${LIST_m68k}
-
-#########################################################################
-## AVR32 Systems
-#########################################################################
-
-LIST_avr32="$(targets_by_arch avr32)"
-
-#########################################################################
-## Blackfin Systems
-#########################################################################
-
-LIST_blackfin="$(targets_by_arch blackfin)"
-
-#########################################################################
-## SH Systems
-#########################################################################
-
-LIST_sh2="$(targets_by_cpu sh2)"
-LIST_sh3="$(targets_by_cpu sh3)"
-LIST_sh4="$(targets_by_cpu sh4)"
-
-LIST_sh="$(targets_by_arch sh)"
-
-#########################################################################
-## SPARC Systems
-#########################################################################
-
-LIST_sparc="$(targets_by_arch sparc)"
-
-#########################################################################
-## NDS32 Systems
-#########################################################################
-
-LIST_nds32="$(targets_by_arch nds32)"
-
-#########################################################################
-## ARC Systems
-#########################################################################
-
-LIST_arc="$(targets_by_arch arc)"
-
-#-----------------------------------------------------------------------
-
-get_target_location() {
-	local target=$1
-	local BOARD_NAME=""
-	local CONFIG_NAME=""
-	local board=""
-	local vendor=""
-
-	# Automatic mode
-	local line=`awk '\$7 == "'"$target"'" { print \$0 }' boards.cfg`
-	if [ -z "${line}" ] ; then echo "" ; return ; fi
-
-	set ${line}
-
-	CONFIG_NAME="${7%_defconfig}"
-
-	[ "${BOARD_NAME}" ] || BOARD_NAME="${7%_defconfig}"
-
-	if [ $# -gt 5 ]; then
-		if [ "$6" = "-" ] ; then
-			board=${BOARD_NAME}
-		else
-			board="$6"
-		fi
-	fi
-
-	[ $# -gt 4 ] && [ "$5" != "-" ] && vendor="$5"
-	[ $# -gt 6 ] && [ "$8" != "-" ] && {
-		tmp="${8%:*}"
-		if [ "$tmp" ] ; then
-			CONFIG_NAME="$tmp"
-		fi
-	}
-
-	# Assign board directory to BOARDIR variable
-	if [ "${vendor}" == "-" ] ; then
-	    BOARDDIR=${board}
-	else
-	    BOARDDIR=${vendor}/${board}
-	fi
-
-	echo "${CONFIG_NAME}:${BOARDDIR}:${BOARD_NAME}"
-}
-
-get_target_maintainers() {
-	local name=`echo $1 | cut -d : -f 3`
-
-	local line=`awk '\$7 == "'"$target"'" { print \$0 }' boards.cfg`
-	if [ -z "${line}" ]; then
-		echo ""
-		return ;
-	fi
-
-	local mails=`echo ${line} | cut -d ' ' -f 9- | sed -e 's/[^<]*<//' -e 's/>.*</ /' -e 's/>[^>]*$//'`
-	[ "$mails" == "-" ] && mails=""
-	echo "$mails"
-}
-
-get_target_arch() {
-	local target=$1
-
-	awk '$7 == "'$target'" { print $2 }' boards.cfg
-}
-
-list_target() {
-	if [ "$PRINT_MAINTS" != 'y' ] ; then
-		echo "$1"
-		return
-	fi
-
-	echo -n "$1:"
-
-	local loc=`get_target_location $1`
-
-	if [ -z "${loc}" ] ; then echo "ERROR" ; return ; fi
-
-	local maintainers_result=`get_target_maintainers ${loc} | tr " " "\n"`
-
-	if [ "$MAINTAINERS_ONLY" != 'y' ] ; then
-
-		local dir=`echo ${loc} | cut -d ":" -f 2`
-		local cfg=`echo ${loc} | cut -d ":" -f 1`
-		local git_result=`git log --format=%aE board/${dir} \
-				include/configs/${cfg}.h | grep "@"`
-		local git_result_recent=`echo ${git_result} | tr " " "\n" | \
-						head -n 3`
-		local git_result_top=`echo ${git_result} | tr " " "\n" | \
-			sort | uniq -c | sort -nr | head -n 3 | \
-			sed "s/^ \+[0-9]\+ \+//"`
-
-		echo -e "$git_result_recent\n$git_result_top\n$maintainers_result" | \
-			sort -u | tr "\n" " " | sed "s/ $//" ;
-	else
-		echo -e "$maintainers_result" | sort -u | tr "\n" " " | \
-						sed "s/ $//" ;
-	fi
-
-	echo ""
-}
-
-# Each finished build will have a file called ${donep}${n},
-# where n is the index of the build. Each build
-# we've already noted as finished will have ${skipp}${n}.
-# The code managing the build process will use this information
-# to ensure that only BUILD_NBUILDS builds are in flight at once
-donep="${LOG_DIR}/._done_"
-skipp="${LOG_DIR}/._skip_"
-
-build_target_killed() {
-	echo "Aborted $target build."
-	# Remove the logs for this board since it was aborted
-	rm -f ${LOG_DIR}/$target.MAKELOG ${LOG_DIR}/$target.ERR
-	exit
-}
-
-build_target() {
-	target=$1
-	build_idx=$2
-
-	if [ "$ONLY_LIST" == 'y' ] ; then
-		list_target ${target}
-		return
-	fi
-
-	if [ $BUILD_MANY == 1 ] ; then
-		output_dir="${OUTPUT_PREFIX}/${target}"
-		mkdir -p "${output_dir}"
-		trap build_target_killed TERM
-	else
-		output_dir="${OUTPUT_PREFIX}"
-	fi
-
-	target_arch=$(get_target_arch ${target})
-	eval cross_toolchain=\$CROSS_COMPILE_`echo $target_arch | tr '[:lower:]' '[:upper:]'`
-	if [ "${cross_toolchain}" ] ; then
-	    MAKE="$GNU_MAKE CROSS_COMPILE=${cross_toolchain}"
-	elif [ "${CROSS_COMPILE}" ] ; then
-	    MAKE="$GNU_MAKE CROSS_COMPILE=${CROSS_COMPILE}"
-	else
-	    MAKE=$GNU_MAKE
-	fi
-
-	if [  "${output_dir}" != "." ] ; then
-		MAKE="${MAKE} O=${output_dir}"
-	fi
-
-	${MAKE} mrproper >/dev/null
-
-	echo "Building ${target} board..."
-	${MAKE} -s ${target}_defconfig >/dev/null
-
-	${MAKE} ${JOBS} ${CHECK} all \
-		>${LOG_DIR}/$target.MAKELOG 2> ${LOG_DIR}/$target.ERR
-
-	# Check for 'make' errors
-	if [ ${PIPESTATUS[0]} -ne 0 ] ; then
-		RC=1
-	fi
-
-	OBJS=${output_dir}/u-boot
-	if [ -e ${output_dir}/spl/u-boot-spl ]; then
-		OBJS="${OBJS} ${output_dir}/spl/u-boot-spl"
-	fi
-
-	${CROSS_COMPILE}size ${OBJS} | tee -a ${LOG_DIR}/$target.MAKELOG
-
-	if [ $BUILD_MANY == 1 ] ; then
-		trap - TERM
-
-		${MAKE} -s clean
-
-		if [ -s ${LOG_DIR}/${target}.ERR ] ; then
-			cp ${LOG_DIR}/${target}.ERR ${OUTPUT_PREFIX}/ERR/${target}
-		else
-			rm ${LOG_DIR}/${target}.ERR
-		fi
-	else
-		if [ -s ${LOG_DIR}/${target}.ERR ] ; then
-			if grep -iw error ${LOG_DIR}/${target}.ERR ; then
-				: $(( ERR_CNT += 1 ))
-				ERR_LIST="${ERR_LIST} $target"
-			else
-				: $(( WRN_CNT += 1 ))
-				WRN_LIST="${WRN_LIST} $target"
-			fi
-		else
-			rm ${LOG_DIR}/${target}.ERR
-		fi
-	fi
-
-	[ -e "${LOG_DIR}/${target}.ERR" ] && cat "${LOG_DIR}/${target}.ERR"
-
-	touch "${donep}${build_idx}"
-}
-
-manage_builds() {
-	search_idx=${OLDEST_IDX}
-	if [ "$ONLY_LIST" == 'y' ] ; then return ; fi
-
-	while true; do
-		if [ -e "${donep}${search_idx}" ] ; then
-			: $(( CURRENT_CNT-- ))
-			[ ${OLDEST_IDX} -eq ${search_idx} ] &&
-				: $(( OLDEST_IDX++ ))
-
-			# Only want to count it once
-			rm -f "${donep}${search_idx}"
-			touch "${skipp}${search_idx}"
-		elif [ -e "${skipp}${search_idx}" ] ; then
-			[ ${OLDEST_IDX} -eq ${search_idx} ] &&
-				: $(( OLDEST_IDX++ ))
-		fi
-		: $(( search_idx++ ))
-		if [ ${search_idx} -gt ${TOTAL_CNT} ] ; then
-			if [ ${CURRENT_CNT} -ge ${BUILD_NBUILDS} ] ; then
-				search_idx=${OLDEST_IDX}
-				sleep 1
-			else
-				break
-			fi
-		fi
-	done
-}
-
-build_targets() {
-	for t in "$@" ; do
-		# If a LIST_xxx var exists, use it.  But avoid variable
-		# expansion in the eval when a board name contains certain
-		# characters that the shell interprets.
-		case ${t} in
-			*[-+=]*) list= ;;
-			*)       list=$(eval echo '${LIST_'$t'}') ;;
-		esac
-		if [ -n "${list}" ] ; then
-			build_targets ${list}
-		else
-			: $((TOTAL_CNT += 1))
-			: $((CURRENT_CNT += 1))
-			rm -f "${donep}${TOTAL_CNT}"
-			rm -f "${skipp}${TOTAL_CNT}"
-			if [ "$CONTINUE" = 'y' -a -e ${LOG_DIR}/$t.MAKELOG ] ; then
-				: $((SKIP_CNT += 1))
-				touch "${donep}${TOTAL_CNT}"
-			elif [ "$REBUILD_ERRORS" = 'y' -a ! -e ${LOG_DIR}/$t.ERR ] ; then
-				: $((SKIP_CNT += 1))
-				touch "${donep}${TOTAL_CNT}"
-			else
-				if [ $BUILD_MANY == 1 ] ; then
-					build_target ${t} ${TOTAL_CNT} &
-				else
-					CUR_TGT="${t}"
-					build_target ${t} ${TOTAL_CNT}
-					CUR_TGT=''
-				fi
-			fi
-		fi
-
-		# We maintain a running count of all the builds we have done.
-		# Each finished build will have a file called ${donep}${n},
-		# where n is the index of the build. Each build
-		# we've already noted as finished will have ${skipp}${n}.
-		# We track the current index via TOTAL_CNT, and the oldest
-		# index. When we exceed the maximum number of parallel builds,
-		# We look from oldest to current for builds that have completed,
-		# and update the current count and oldest index as appropriate.
-		# If we've gone through the entire list, wait a second, and
-		# reprocess the entire list until we find a build that has
-		# completed
-		if [ ${CURRENT_CNT} -ge ${BUILD_NBUILDS} ] ; then
-			manage_builds
-		fi
-	done
-}
-
-#-----------------------------------------------------------------------
-
-kill_children() {
-	local OS=$(uname -s)
-	local children=""
-	case "${OS}" in
-		"Darwin")
-			# Mac OS X is known to have BSD style ps
-			local pgid=$(ps -p $$ -o pgid | sed -e "/PGID/d")
-			children=$(ps -g $pgid -o pid | sed -e "/PID\|$$\|$pgid/d")
-			;;
-		*)
-			# everything else tries the GNU style
-			local pgid=$(ps -p $$ --no-headers -o "%r" | tr -d ' ')
-			children=$(pgrep -g $pgid | sed -e "/$$\|$pgid/d")
-			;;
-	esac
-
-	kill $children 2> /dev/null
-	wait $children 2> /dev/null
-
-	exit
-}
-
-print_stats() {
-	if [ "$ONLY_LIST" == 'y' ] ; then return ; fi
-
-	# Only count boards that completed
-	: $((TOTAL_CNT = `find ${skipp}* 2> /dev/null | wc -l`))
-
-	rm -f ${donep}* ${skipp}*
-
-	if [ $BUILD_MANY == 1 ] && [ -e "${OUTPUT_PREFIX}/ERR" ] ; then
-		ERR_LIST=`grep -riwl error ${OUTPUT_PREFIX}/ERR/`
-		ERR_LIST=`for f in $ERR_LIST ; do echo -n " $(basename $f)" ; done`
-		ERR_CNT=`echo $ERR_LIST | wc -w | awk '{print $1}'`
-		WRN_LIST=`grep -riwL error ${OUTPUT_PREFIX}/ERR/`
-		WRN_LIST=`for f in $WRN_LIST ; do echo -n " $(basename $f)" ; done`
-		WRN_CNT=`echo $WRN_LIST | wc -w | awk '{print $1}'`
-	else
-		# Remove the logs for any board that was interrupted
-		rm -f ${LOG_DIR}/${CUR_TGT}.MAKELOG ${LOG_DIR}/${CUR_TGT}.ERR
-	fi
-
-	: $((TOTAL_CNT -= ${SKIP_CNT}))
-	echo ""
-	echo "--------------------- SUMMARY ----------------------------"
-	if [ "$CONTINUE" = 'y' -o "$REBUILD_ERRORS" = 'y' ] ; then
-		echo "Boards skipped: ${SKIP_CNT}"
-	fi
-	echo "Boards compiled: ${TOTAL_CNT}"
-	if [ ${ERR_CNT} -gt 0 ] ; then
-		echo "Boards with errors: ${ERR_CNT} (${ERR_LIST} )"
-	fi
-	if [ ${WRN_CNT} -gt 0 ] ; then
-		echo "Boards with warnings but no errors: ${WRN_CNT} (${WRN_LIST} )"
-	fi
-	echo "----------------------------------------------------------"
-
-	if [ $BUILD_MANY == 1 ] ; then
-		kill_children
-	fi
-
-	deprecation
-
-	exit $RC
-}
-
-#-----------------------------------------------------------------------
-
-# Build target groups selected by options, plus any command line args
-set -- ${SELECTED} "$@"
-# run PowerPC by default
-[ $# = 0 ] && set -- powerpc
-build_targets "$@"
-wait
diff --git a/Makefile b/Makefile
index 09a18e1..1625743 100644
--- a/Makefile
+++ b/Makefile
@@ -3,9 +3,9 @@
 #
 
 VERSION = 2016
-PATCHLEVEL = 07
+PATCHLEVEL = 09
 SUBLEVEL =
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc1
 NAME =
 
 # *DOCUMENTATION*
@@ -256,7 +256,8 @@
 
 HOSTCC       = cc
 HOSTCXX      = c++
-HOSTCFLAGS   = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
+HOSTCFLAGS   = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer \
+		$(if $(CONFIG_TOOLS_DEBUG),-g)
 HOSTCXXFLAGS = -O2
 
 ifeq ($(HOSTOS),cygwin)
@@ -424,7 +425,7 @@
 
 no-dot-config-targets := clean clobber mrproper distclean \
 			 help %docs check% coccicheck \
-			 ubootversion backup
+			 ubootversion backup tests
 
 config-targets := 0
 mixed-targets  := 0
@@ -556,6 +557,14 @@
 include/config/auto.conf: ;
 endif # $(dot-config)
 
+#
+# Xtensa linker script cannot be preprocessed with -ansi because of
+# preprocessor operations on strings that don't make C identifiers.
+#
+ifeq ($(CONFIG_XTENSA),)
+LDPPFLAGS	+= -ansi
+endif
+
 ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
 KBUILD_CFLAGS	+= -Os
 else
@@ -637,6 +646,7 @@
 libs-y += drivers/net/phy/
 libs-y += drivers/pci/
 libs-y += drivers/power/ \
+	drivers/power/domain/ \
 	drivers/power/fuel_gauge/ \
 	drivers/power/mfd/ \
 	drivers/power/pmic/ \
@@ -665,6 +675,7 @@
 libs-y += test/
 libs-y += test/dm/
 libs-$(CONFIG_UT_ENV) += test/env/
+libs-$(CONFIG_UT_OVERLAY) += test/overlay/
 
 libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/)
 
@@ -801,7 +812,7 @@
 cmd_pad_cat = $(cmd_objcopy) && $(append) || rm -f $@
 
 all:		$(ALL-y)
-ifeq ($(CONFIG_DM_I2C_COMPAT),y)
+ifeq ($(CONFIG_DM_I2C_COMPAT)$(CONFIG_SANDBOX),y)
 	@echo "===================== WARNING ======================"
 	@echo "This board uses CONFIG_DM_I2C_COMPAT. Please remove"
 	@echo "(possibly in a subsequent patch in your series)"
@@ -1310,7 +1321,7 @@
 
 # ---------------------------------------------------------------------------
 quiet_cmd_cpp_lds = LDS     $@
-cmd_cpp_lds = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) -ansi \
+cmd_cpp_lds = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) \
 		-D__ASSEMBLY__ -x assembler-with-cpp -P -o $@ $<
 
 u-boot.lds: $(LDSCRIPT) prepare FORCE
@@ -1318,7 +1329,8 @@
 
 spl/u-boot-spl.bin: spl/u-boot-spl
 	@:
-spl/u-boot-spl: tools prepare $(if $(CONFIG_OF_SEPARATE),dts/dt.dtb)
+spl/u-boot-spl: tools prepare \
+		$(if $(CONFIG_OF_SEPARATE)$(CONFIG_SPL_OF_PLATDATA),dts/dt.dtb)
 	$(Q)$(MAKE) obj=spl -f $(srctree)/scripts/Makefile.spl all
 
 spl/sunxi-spl.bin: spl/u-boot-spl
@@ -1415,7 +1427,7 @@
 MRPROPER_DIRS  += include/config include/generated spl tpl \
 		  .tmp_objdiff
 MRPROPER_FILES += .config .config.old include/autoconf.mk* include/config.h \
-		  ctags etags TAGS cscope* GPATH GTAGS GRTAGS GSYMS
+		  ctags etags tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS
 
 # clean - Delete most, but leave enough to build external modules
 #
@@ -1486,6 +1498,7 @@
 	@echo  ''
 	@echo  'Other generic targets:'
 	@echo  '  all		  - Build all necessary images depending on configuration'
+	@echo  '  tests		  - Build U-Boot for sandbox and run tests'
 	@echo  '* u-boot	  - Build the bare u-boot'
 	@echo  '  dir/            - Build all files in dir and below'
 	@echo  '  dir/file.[oisS] - Build specified target only'
@@ -1518,6 +1531,8 @@
 	@echo  'Execute "make" or "make all" to build all targets marked with [*] '
 	@echo  'For further info see the ./README file'
 
+tests:
+	$(srctree)/test/run
 
 # Documentation targets
 # ---------------------------------------------------------------------------
diff --git a/README b/README
index 26d5ad2..30d7ee3 100644
--- a/README
+++ b/README
@@ -511,7 +511,7 @@
 		implemetation.
 
 		CONFIG_SYS_FSL_DDR2
-		Board config to use DDR2. It can be eanbeld for SoCs with
+		Board config to use DDR2. It can be enabled for SoCs with
 		Freescale DDR2 or DDR3 controllers, depending on the board
 		implementation.
 
@@ -840,6 +840,9 @@
 			CONFIG_CONSOLE_EXTRA_INFO
 						additional board info beside
 						the logo
+			CONFIG_HIDE_LOGO_VERSION
+						do not display bootloader
+						version string
 
 		When CONFIG_CFB_CONSOLE_ANSI is defined, console will support
 		a limited number of ANSI escape sequences (cursor control,
@@ -2753,7 +2756,7 @@
 		with a special header) as build targets. By defining
 		CONFIG_BUILD_TARGET in the SoC / board header, this
 		special image will be automatically built upon calling
-		make / MAKEALL.
+		make / buildman.
 
 		CONFIG_IDENT_STRING
 
@@ -3583,6 +3586,10 @@
 		Support for NAND boot using simple NAND drivers that
 		expose the cmd_ctrl() interface.
 
+		CONFIG_SPL_UBI
+		Support for a lightweight UBI (fastmap) scanner and
+		loader
+
 		CONFIG_SPL_MTD_SUPPORT
 		Support for the MTD subsystem within SPL.  Useful for
 		environment on NAND support within SPL.
@@ -3766,10 +3773,11 @@
 		You only need to set this if address zero isn't writeable
 
 - CONFIG_SYS_MEM_RESERVE_SECURE
+		Only implemented for ARMv8 for now.
 		If defined, the size of CONFIG_SYS_MEM_RESERVE_SECURE memory
 		is substracted from total RAM and won't be reported to OS.
 		This memory can be used as secure memory. A variable
-		gd->secure_ram is used to track the location. In systems
+		gd->arch.secure_ram is used to track the location. In systems
 		the RAM base is not zero, or RAM is divided into banks,
 		this variable needs to be recalcuated to get the address.
 
@@ -3835,9 +3843,6 @@
 		The memory will be freed (or in fact just forgotten) when
 		U-Boot relocates itself.
 
-		Pre-relocation malloc() is only supported on ARM and sandbox
-		at present but is fairly easy to enable for other archs.
-
 - CONFIG_SYS_MALLOC_SIMPLE
 		Provides a simple and small malloc() and calloc() for those
 		boards which do not use the full malloc in SPL (which is
@@ -4809,7 +4814,7 @@
 
 - CONFIG_SKIP_LOWLEVEL_INIT_ONLY
 		[ARM926EJ-S only] This allows just the call to lowlevel_init()
-		to be skipped. The normal CPU15 init (such as enabling the
+		to be skipped. The normal CP15 init (such as enabling the
 		instruction cache) is still performed.
 
 - CONFIG_SPL_BUILD
@@ -5078,34 +5083,11 @@
 But before you submit such a patch, please verify that your modifi-
 cation did not break existing code. At least make sure that *ALL* of
 the supported boards compile WITHOUT ANY compiler warnings. To do so,
-just run the "MAKEALL" script, which will configure and build U-Boot
-for ALL supported system. Be warned, this will take a while. You can
-select which (cross) compiler to use by passing a `CROSS_COMPILE'
-environment variable to the script, i. e. to use the ELDK cross tools
-you can type
-
-	CROSS_COMPILE=ppc_8xx- MAKEALL
-
-or to build on a native PowerPC system you can type
+just run the buildman script (tools/buildman/buildman), which will
+configure and build U-Boot for ALL supported system. Be warned, this
+will take a while. Please see the buildman README, or run 'buildman -H'
+for documentation.
 
-	CROSS_COMPILE=' ' MAKEALL
-
-When using the MAKEALL script, the default behaviour is to build
-U-Boot in the source directory. This location can be changed by
-setting the BUILD_DIR environment variable. Also, for each target
-built, the MAKEALL script saves two log files (<target>.ERR and
-<target>.MAKEALL) in the <source dir>/LOG directory. This default
-location can be changed by setting the MAKEALL_LOGDIR environment
-variable. For example:
-
-	export BUILD_DIR=/tmp/build
-	export MAKEALL_LOGDIR=/tmp/log
-	CROSS_COMPILE=ppc_8xx- MAKEALL
-
-With the above settings build objects are saved in the /tmp/build,
-log files are saved in the /tmp/log and the source tree remains clean
-during the whole build process.
-
 
 See also "U-Boot Porting Guide" below.
 
@@ -6560,7 +6542,7 @@
 
 Notes:
 
-* Before sending the patch, run the MAKEALL script on your patched
+* Before sending the patch, run the buildman script on your patched
   source tree and make sure that no errors or warnings are reported
   for any of the boards.
 
diff --git a/api/api_net.c b/api/api_net.c
index 04e4f4a..67c2916 100644
--- a/api/api_net.c
+++ b/api/api_net.c
@@ -25,7 +25,7 @@
 
 #define errf(fmt, args...) do { printf("ERROR @ %s(): ", __func__); printf(fmt, ##args); } while (0)
 
-#ifdef CONFIG_CMD_NET
+#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
 
 static int dev_valid_net(void *cookie)
 {
diff --git a/arch/Kconfig b/arch/Kconfig
index 566f044..d718a68 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -1,6 +1,9 @@
 config CREATE_ARCH_SYMLINK
 	bool
 
+config HAVE_ARCH_IOREMAP
+	bool
+
 choice
 	prompt "Architecture select"
 	default SANDBOX
@@ -33,6 +36,7 @@
 
 config MIPS
 	bool "MIPS architecture"
+	select HAVE_ARCH_IOREMAP
 	select HAVE_PRIVATE_LIBGCC
 	select SUPPORT_OF_CONTROL
 
@@ -63,6 +67,7 @@
 	select DM_I2C
 	select DM_SPI
 	select DM_GPIO
+	select DM_MMC
 
 config SH
 	bool "SuperH architecture"
@@ -83,6 +88,11 @@
 	select DM_SPI
 	select DM_SPI_FLASH
 
+config XTENSA
+	bool "Xtensa architecture"
+	select CREATE_ARCH_SYMLINK
+	select SUPPORT_OF_CONTROL
+
 endchoice
 
 config SYS_ARCH
@@ -156,3 +166,4 @@
 source "arch/sh/Kconfig"
 source "arch/sparc/Kconfig"
 source "arch/x86/Kconfig"
+source "arch/xtensa/Kconfig"
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index f1dc6c8..4c5696b 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -118,21 +118,21 @@
 
 choice
 	prompt "Target select"
-	default TARGET_AXS101
+	default TARGET_AXS10X
 
 config TARGET_TB100
 	bool "Support tb100"
 
-config TARGET_ARCANGEL4
-	bool "Support arcangel4"
+config TARGET_NSIM
+	bool "Support standalone nSIM & Free nSIM"
 
-config TARGET_AXS101
-	bool "Support axs101"
+config TARGET_AXS10X
+	bool "Support Synopsys Designware SDP board (AXS101 & AXS103)"
 
 endchoice
 
 source "board/abilis/tb100/Kconfig"
 source "board/synopsys/Kconfig"
-source "board/synopsys/axs101/Kconfig"
+source "board/synopsys/axs10x/Kconfig"
 
 endmenu
diff --git a/arch/arc/cpu/arcv2/ivt.S b/arch/arc/cpu/arcv2/ivt.S
index d110b5b..7924375 100644
--- a/arch/arc/cpu/arcv2/ivt.S
+++ b/arch/arc/cpu/arcv2/ivt.S
@@ -7,21 +7,26 @@
 .section .ivt, "a",@progbits
 .align 4
 	/* Critical system events */
-.word	_start			/* 0 - 0x000 */
-.word	memory_error		/* 1 - 0x008 */
-.word	instruction_error	/* 2 - 0x010 */
+.word	_start			/* 0x00 - Reset */
+.word	memory_error		/* 0x01 - Memory Error */
+.word	instruction_error	/* 0x02 - Instruction Error */
 
 	/* Exceptions */
-.word	EV_MachineCheck		/* 0x100, Fatal Machine check  (0x20) */
-.word	EV_TLBMissI		/* 0x108, Intruction TLB miss  (0x21) */
-.word	EV_TLBMissD		/* 0x110, Data TLB miss        (0x22) */
-.word	EV_TLBProtV		/* 0x118, Protection Violation (0x23)
-							or Misaligned Access  */
-.word	EV_PrivilegeV		/* 0x120, Privilege Violation  (0x24) */
-.word	EV_Trap			/* 0x128, Trap exception       (0x25) */
-.word	EV_Extension		/* 0x130, Extn Intruction Excp (0x26) */
+.word	EV_MachineCheck		/* 0x03 - Fatal Machine check */
+.word	EV_TLBMissI		/* 0x04 - Intruction TLB miss */
+.word	EV_TLBMissD		/* 0x05 - Data TLB miss */
+.word	EV_TLBProtV		/* 0x06 - Protection Violation or Misaligned Access */
+.word	EV_PrivilegeV		/* 0x07 - Privilege Violation */
+.word	EV_SWI			/* 0x08 - Software Interrupt */
+.word	EV_Trap			/* 0x09 - Trap */
+.word	EV_Extension		/* 0x0A - Extension Intruction Exception */
+.word	EV_DivZero		/* 0x0B - Division by Zero */
+.word	EV_DCError		/* 0x0C - Data cache consistency error */
+.word	EV_Maligned		/* 0x0D - Misaligned data access */
+.word	0			/* 0x0E - Unused */
+.word	0			/* 0x0F - Unused */
 
 	/* Device interrupts */
-.rept	29
-	j	interrupt_handler	/* 3:31 - 0x018:0xF8 */
+.rept	240
+.word	interrupt_handler	/* 0x10 - 0xFF */
 .endr
diff --git a/arch/arc/cpu/u-boot.lds b/arch/arc/cpu/u-boot.lds
index 693df74..d3d0a53 100644
--- a/arch/arc/cpu/u-boot.lds
+++ b/arch/arc/cpu/u-boot.lds
@@ -4,38 +4,29 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#include <config.h>
+
 OUTPUT_FORMAT("elf32-littlearc", "elf32-littlearc", "elf32-littlearc")
 OUTPUT_ARCH(arc)
 ENTRY(_start)
 SECTIONS
 {
-	. = ALIGN(4);
+	. = CONFIG_SYS_TEXT_BASE;
+	__image_copy_start = .;
+	__text_start = .;
 	.text :	{
-		*(.__text_start)
-		*(.__image_copy_start)
 		arch/arc/lib/start.o (.text*)
 		*(.text*)
 	}
-
-	. = ALIGN(4);
-	.text_end :
-	{
-		*(.__text_end)
-	}
+	__text_end = .;
 
 	. = ALIGN(1024);
-	.ivt_start : {
-		*(.__ivt_start)
-	}
-
+	__ivt_start = .;
 	.ivt :
 	{
 		*(.ivt)
 	}
-
-	.ivt_end : {
-		*(.__ivt_end)
-	}
+	__ivt_end = .;
 
 	. = ALIGN(4);
 	.rodata : {
@@ -53,34 +44,20 @@
 	}
 
 	. = ALIGN(4);
-	.rel_dyn_start : {
-		*(.__rel_dyn_start)
-	}
-
+	__rel_dyn_start = .;
 	.rela.dyn : {
 		*(.rela.dyn)
 	}
-
-	.rel_dyn_end : {
-		*(.__rel_dyn_end)
-	}
+	__rel_dyn_end = .;
 
 	. = ALIGN(4);
-	.bss_start : {
-		*(.__bss_start);
-	}
-
+	__bss_start = .;
 	.bss : {
 		*(.bss*)
 	}
-
-	.bss_end : {
-		*(.__bss_end);
-	}
+	__bss_end = .;
 
 	. = ALIGN(4);
-	.image_copy_end : {
-		*(.__image_copy_end)
-		*(.__init_end)
-	}
+	__image_copy_end = .;
+	__init_end = .;
 }
diff --git a/arch/arc/dts/Makefile b/arch/arc/dts/Makefile
index d4772ec..1d94c08 100644
--- a/arch/arc/dts/Makefile
+++ b/arch/arc/dts/Makefile
@@ -2,8 +2,8 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-dtb-$(CONFIG_TARGET_AXS101) +=  axs10x.dtb
-dtb-$(CONFIG_TARGET_ARCANGEL4) +=  arcangel4.dtb
+dtb-$(CONFIG_TARGET_AXS10X) +=  axs10x.dtb
+dtb-$(CONFIG_TARGET_NSIM) +=  nsim.dtb
 dtb-$(CONFIG_TARGET_TB100) +=  abilis_tb100.dtb
 
 targets += $(dtb-y)
diff --git a/arch/arc/dts/arcangel4.dts b/arch/arc/dts/nsim.dts
similarity index 83%
rename from arch/arc/dts/arcangel4.dts
rename to arch/arc/dts/nsim.dts
index bfcb9d8..69e16c2 100644
--- a/arch/arc/dts/arcangel4.dts
+++ b/arch/arc/dts/nsim.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Synopsys, Inc. (www.synopsys.com)
+ * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
diff --git a/arch/arc/include/asm/sections.h b/arch/arc/include/asm/sections.h
index b8f2a85..00f1217 100644
--- a/arch/arc/include/asm/sections.h
+++ b/arch/arc/include/asm/sections.h
@@ -9,9 +9,7 @@
 
 #include <asm-generic/sections.h>
 
-extern ulong __text_end;
 extern ulong __ivt_start;
 extern ulong __ivt_end;
-extern ulong __image_copy_start;
 
 #endif /* __ASM_ARC_SECTIONS_H */
diff --git a/arch/arc/lib/Makefile b/arch/arc/lib/Makefile
index e592802..eb62b3c 100644
--- a/arch/arc/lib/Makefile
+++ b/arch/arc/lib/Makefile
@@ -9,7 +9,6 @@
 obj-y += cache.o
 obj-y += cpu.o
 obj-y += interrupts.o
-obj-y += sections.o
 obj-y += relocate.o
 obj-y += strchr-700.o
 obj-y += strcmp.o
diff --git a/arch/arc/lib/interrupts.c b/arch/arc/lib/interrupts.c
index d7cab3b..ee638d5 100644
--- a/arch/arc/lib/interrupts.c
+++ b/arch/arc/lib/interrupts.c
@@ -141,3 +141,29 @@
 	printf("Extension instruction exception\n");
 	bad_mode(regs);
 }
+
+#ifdef CONFIG_ISA_ARCV2
+void do_swi(struct pt_regs *regs)
+{
+	printf("Software Interrupt exception\n");
+	bad_mode(regs);
+}
+
+void do_divzero(unsigned long address, struct pt_regs *regs)
+{
+	printf("Division by zero exception @ 0x%lx\n", address);
+	bad_mode(regs);
+}
+
+void do_dcerror(struct pt_regs *regs)
+{
+	printf("Data cache consistency error exception\n");
+	bad_mode(regs);
+}
+
+void do_maligned(unsigned long address, struct pt_regs *regs)
+{
+	printf("Misaligned data access exception @ 0x%lx\n", address);
+	bad_mode(regs);
+}
+#endif
diff --git a/arch/arc/lib/ints_low.S b/arch/arc/lib/ints_low.S
index 161cf37..e377884 100644
--- a/arch/arc/lib/ints_low.S
+++ b/arch/arc/lib/ints_low.S
@@ -149,3 +149,31 @@
 	mov	%r0, %sp
 	j	do_extension
 ENDPROC(EV_Extension)
+
+#ifdef CONFIG_ISA_ARCV2
+ENTRY(EV_SWI)
+	SAVE_ALL_SYS
+	mov	%r0, %sp
+	j	do_swi
+ENDPROC(EV_SWI)
+
+ENTRY(EV_DivZero)
+	SAVE_ALL_SYS
+	SAVE_EXCEPTION_SOURCE
+	mov	%r1, %sp
+	j	do_divzero
+ENDPROC(EV_DivZero)
+
+ENTRY(EV_DCError)
+	SAVE_ALL_SYS
+	mov	%r0, %sp
+	j	do_dcerror
+ENDPROC(EV_DCError)
+
+ENTRY(EV_Maligned)
+	SAVE_ALL_SYS
+	SAVE_EXCEPTION_SOURCE
+	mov	%r1, %sp
+	j	do_maligned
+ENDPROC(EV_Maligned)
+#endif
diff --git a/arch/arc/lib/relocate.c b/arch/arc/lib/relocate.c
index 5c2c2d1..7802f40 100644
--- a/arch/arc/lib/relocate.c
+++ b/arch/arc/lib/relocate.c
@@ -6,7 +6,10 @@
 
 #include <common.h>
 #include <elf.h>
-#include <asm/sections.h>
+#include <asm-generic/sections.h>
+
+extern ulong __image_copy_start;
+extern ulong __ivt_end;
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -37,6 +40,9 @@
 	Elf32_Rela *re_src = (Elf32_Rela *)(&__rel_dyn_start);
 	Elf32_Rela *re_end = (Elf32_Rela *)(&__rel_dyn_end);
 
+	debug("Section .rela.dyn is located at %08x-%08x\n",
+	      (unsigned int)re_src, (unsigned int)re_end);
+
 	Elf32_Addr *offset_ptr_rom, *last_offset = NULL;
 	Elf32_Addr *offset_ptr_ram;
 
@@ -52,6 +58,10 @@
 			offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom +
 							gd->reloc_off);
 
+			debug("Patching value @ %08x (relocated to %08x)\n",
+			      (unsigned int)offset_ptr_rom,
+			      (unsigned int)offset_ptr_ram);
+
 			/*
 			 * Use "memcpy" because target location might be
 			 * 16-bit aligned on ARC so we may need to read
diff --git a/arch/arc/lib/sections.c b/arch/arc/lib/sections.c
deleted file mode 100644
index a72c694..0000000
--- a/arch/arc/lib/sections.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-/*
- * For some reason linker sets linker-generated symbols to zero in PIE mode.
- * A work-around is substitution of linker-generated symbols with
- * compiler-generated symbols which are properly handled by linker in PAE mode.
- */
-
-char __bss_start[0] __attribute__((section(".__bss_start")));
-char __bss_end[0] __attribute__((section(".__bss_end")));
-char __image_copy_start[0] __attribute__((section(".__image_copy_start")));
-char __image_copy_end[0] __attribute__((section(".__image_copy_end")));
-char __rel_dyn_start[0] __attribute__((section(".__rel_dyn_start")));
-char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end")));
-char __text_start[0] __attribute__((section(".__text_start")));
-char __text_end[0] __attribute__((section(".__text_end")));
-char __init_end[0] __attribute__((section(".__init_end")));
-char __ivt_start[0] __attribute__((section(".__ivt_start")));
-char __ivt_end[0] __attribute__((section(".__ivt_end")));
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 8c867b2..aef901c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -6,6 +6,7 @@
 
 config ARM64
 	bool
+	select PHYS_64BIT
 
 config DMA_ADDR_T_64BIT
 	bool
@@ -553,11 +554,14 @@
 config OMAP34XX
 	bool "OMAP34XX SoC"
 	select CPU_V7
+	select SUPPORT_SPL
+	select USE_TINY_PRINTF
 
 config OMAP44XX
 	bool "OMAP44XX SoC"
 	select CPU_V7
 	select SUPPORT_SPL
+	select USE_TINY_PRINTF
 
 config OMAP54XX
 	bool "OMAP54XX SoC"
@@ -658,10 +662,13 @@
 	select DM_GPIO
 	select SPL_DM if SPL
 	select DM_MMC
+	select DM_MMC_OPS
 	select DM_SPI
 	select DM_SERIAL
 	select DM_SPI_FLASH
 	select SPL_SEPARATE_BSS if SPL
+	select DM_USB if USB
+	select BLK
 
 config ARCH_ZYNQMP
 	bool "Support Xilinx ZynqMP Platform"
@@ -670,6 +677,9 @@
 	select OF_CONTROL
 	select DM_SERIAL
 	select SUPPORT_SPL
+	select CLK
+	select SPL_CLK
+	select DM_USB if USB
 
 config TEGRA
 	bool "NVIDIA Tegra"
@@ -839,11 +849,19 @@
 
 config ARCH_ROCKCHIP
 	bool "Support Rockchip SoCs"
-	select SUPPORT_SPL
-	select SPL
 	select OF_CONTROL
-	select CPU_V7
+	select BLK
 	select DM
+	select SPL_DM if SPL
+	select SYS_MALLOC_F
+	select SPL_SYS_MALLOC_SIMPLE if SPL
+	select DM_GPIO
+	select DM_I2C
+	select DM_MMC
+	select DM_MMC_OPS
+	select DM_SERIAL
+	select DM_SPI
+	select DM_SPI_FLASH
 
 config TARGET_THUNDERX_88XX
 	bool "Support ThunderX 88xx"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 5000d87..42093c2 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -20,6 +20,14 @@
 				 $(call cc-option, -march=armv7, -march=armv5))
 arch-$(CONFIG_ARM64)		=-march=armv8-a
 
+# On Tegra systems we must build SPL for the armv4 core on the device
+# but otherwise we can use the value in CONFIG_SYS_ARM_ARCH
+ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TEGRA),yy)
+arch-y += -D__LINUX_ARM_ARCH__=4
+else
+arch-y += -D__LINUX_ARM_ARCH__=$(CONFIG_SYS_ARM_ARCH)
+endif
+
 # Evaluate arch cc-option calls now
 arch-y := $(arch-y)
 
diff --git a/arch/arm/config.mk b/arch/arm/config.mk
index 9a5a974..8f85862 100644
--- a/arch/arm/config.mk
+++ b/arch/arm/config.mk
@@ -120,8 +120,8 @@
 ifdef CONFIG_ARM64
 OBJCOPYFLAGS += -j .text -j .rodata -j .data -j .u_boot_list -j .rela.dyn
 else
-OBJCOPYFLAGS += -j .text -j .secure_text -j .rodata -j .hash -j .data -j \
-	.got -j .got.plt -j .u_boot_list -j .rel.dyn
+OBJCOPYFLAGS += -j .text -j .secure_text -j .secure_data -j .rodata -j .hash \
+		-j .data -j .got -j .got.plt -j .u_boot_list -j .rel.dyn
 endif
 
 ifdef CONFIG_OF_EMBED
diff --git a/arch/arm/cpu/arm11/cpu.c b/arch/arm/cpu/arm11/cpu.c
index 1e4c214..7244c2e 100644
--- a/arch/arm/cpu/arm11/cpu.c
+++ b/arch/arm/cpu/arm11/cpu.c
@@ -69,23 +69,6 @@
 	asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
 }
 
-static int check_cache_range(unsigned long start, unsigned long stop)
-{
-	int ok = 1;
-
-	if (start & (CONFIG_SYS_CACHELINE_SIZE - 1))
-		ok = 0;
-
-	if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1))
-		ok = 0;
-
-	if (!ok)
-		debug("CACHE: Misaligned operation at range [%08lx, %08lx]\n",
-			start, stop);
-
-	return ok;
-}
-
 void invalidate_dcache_range(unsigned long start, unsigned long stop)
 {
 	if (!check_cache_range(start, stop))
diff --git a/arch/arm/cpu/arm926ejs/cache.c b/arch/arm/cpu/arm926ejs/cache.c
index 2839c86..2119382 100644
--- a/arch/arm/cpu/arm926ejs/cache.c
+++ b/arch/arm/cpu/arm926ejs/cache.c
@@ -29,23 +29,6 @@
 	);
 }
 
-static int check_cache_range(unsigned long start, unsigned long stop)
-{
-	int ok = 1;
-
-	if (start & (CONFIG_SYS_CACHELINE_SIZE - 1))
-		ok = 0;
-
-	if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1))
-		ok = 0;
-
-	if (!ok)
-		debug("CACHE: Misaligned operation at range [%08lx, %08lx]\n",
-			start, stop);
-
-	return ok;
-}
-
 void invalidate_dcache_range(unsigned long start, unsigned long stop)
 {
 	if (!check_cache_range(start, stop))
diff --git a/arch/arm/cpu/armv7/Kconfig b/arch/arm/cpu/armv7/Kconfig
index afeaac8..41c6639 100644
--- a/arch/arm/cpu/armv7/Kconfig
+++ b/arch/arm/cpu/armv7/Kconfig
@@ -7,32 +7,32 @@
         bool
 
 config ARMV7_NONSEC
-	boolean "Enable support for booting in non-secure mode" if EXPERT
+	bool "Enable support for booting in non-secure mode" if EXPERT
 	depends on CPU_V7_HAS_NONSEC
 	default y
 	---help---
 	Say Y here to enable support for booting in non-secure / SVC mode.
 
 config ARMV7_BOOT_SEC_DEFAULT
-	boolean "Boot in secure mode by default" if EXPERT
+	bool "Boot in secure mode by default" if EXPERT
 	depends on ARMV7_NONSEC
 	default y if TEGRA
 	---help---
 	Say Y here to boot in secure mode by default even if non-secure mode
 	is supported. This option is useful to boot kernels which do not
 	suppport booting in non-secure mode. Only set this if you need it.
-	This can be overriden at run-time by setting the bootm_boot_mode env.
+	This can be overridden at run-time by setting the bootm_boot_mode env.
 	variable to "sec" or "nonsec".
 
 config ARMV7_VIRT
-	boolean "Enable support for hardware virtualization" if EXPERT
+	bool "Enable support for hardware virtualization" if EXPERT
 	depends on CPU_V7_HAS_VIRT && ARMV7_NONSEC
 	default y
 	---help---
 	Say Y here to boot in hypervisor (HYP) mode when booting non-secure.
 
 config ARMV7_LPAE
-	boolean "Use LPAE page table format" if EXPERT
+	bool "Use LPAE page table format" if EXPERT
 	depends on CPU_V7
 	default n
 	---help---
diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
index ddd8d12..0d4bfbc 100644
--- a/arch/arm/cpu/armv7/Makefile
+++ b/arch/arm/cpu/armv7/Makefile
@@ -19,7 +19,7 @@
 endif
 
 obj-$(CONFIG_ARMV7_NONSEC)	+= nonsec_virt.o virt-v7.o virt-dt.o
-obj-$(CONFIG_ARMV7_PSCI)	+= psci.o
+obj-$(CONFIG_ARMV7_PSCI)	+= psci.o psci-common.o
 
 obj-$(CONFIG_IPROC) += iproc-common/
 obj-$(CONFIG_KONA) += kona-common/
diff --git a/arch/arm/cpu/armv7/am33xx/config.mk b/arch/arm/cpu/armv7/am33xx/config.mk
index 6d95d32..d4eb21c 100644
--- a/arch/arm/cpu/armv7/am33xx/config.mk
+++ b/arch/arm/cpu/armv7/am33xx/config.mk
@@ -26,6 +26,7 @@
 else
 ifeq ($(CONFIG_TI_SECURE_DEVICE),y)
 ALL-$(CONFIG_QSPI_BOOT) += u-boot_HS_XIP_X-LOADER
+ALL-$(CONFIG_SPL_LOAD_FIT) += u-boot_HS.img
 endif
 ALL-y	+= u-boot.img
 endif
diff --git a/arch/arm/cpu/armv7/am33xx/ddr.c b/arch/arm/cpu/armv7/am33xx/ddr.c
index 888cf1f..6acf30c 100644
--- a/arch/arm/cpu/armv7/am33xx/ddr.c
+++ b/arch/arm/cpu/armv7/am33xx/ddr.c
@@ -120,12 +120,15 @@
 
 	writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config);
 	writel(regs->sdram_config, &cstat->secure_emif_sdram_config);
+
+	/* Wait 1ms because of L3 timeout error */
+	udelay(1000);
+
 	writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl);
 	writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw);
 
 	/* Perform hardware leveling for DDR3 */
 	if (emif_sdram_type(regs->sdram_config) == EMIF_SDRAM_TYPE_DDR3) {
-		udelay(1000);
 		writel(readl(&emif_reg[nr]->emif_ddr_ext_phy_ctrl_36) |
 		       0x100, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_36);
 		writel(readl(&emif_reg[nr]->emif_ddr_ext_phy_ctrl_36_shdw) |
@@ -289,19 +292,14 @@
 void config_ddr_phy(const struct emif_regs *regs, int nr)
 {
 	/*
-	 * Disable initialization and refreshes for now until we
-	 * finish programming EMIF regs.
-	 * Also set time between rising edge of DDR_RESET to rising
-	 * edge of DDR_CKE to > 500us per memory spec.
+	 * Disable initialization and refreshes for now until we finish
+	 * programming EMIF regs and set time between rising edge of
+	 * DDR_RESET to rising edge of DDR_CKE to > 500us per memory spec.
+	 * We currently hardcode a value based on a max expected frequency
+	 * of 400MHz.
 	 */
-#ifndef CONFIG_AM43XX
-	setbits_le32(&emif_reg[nr]->emif_sdram_ref_ctrl,
-		     EMIF_REG_INITREF_DIS_MASK);
-#endif
-	if (regs->zq_config)
-		/* Set time between rising edge of DDR_RESET to rising
-		 * edge of DDR_CKE to > 500us per memory spec. */
-		writel(0x00003100, &emif_reg[nr]->emif_sdram_ref_ctrl);
+	writel(EMIF_REG_INITREF_DIS_MASK | 0x3100,
+		&emif_reg[nr]->emif_sdram_ref_ctrl);
 
 	writel(regs->emif_ddr_phy_ctlr_1,
 		&emif_reg[nr]->emif_ddr_phy_ctrl_1);
diff --git a/arch/arm/cpu/armv7/cache_v7.c b/arch/arm/cpu/armv7/cache_v7.c
index dc309da..c4bbcc3 100644
--- a/arch/arm/cpu/armv7/cache_v7.c
+++ b/arch/arm/cpu/armv7/cache_v7.c
@@ -19,23 +19,6 @@
 void v7_flush_dcache_all(void);
 void v7_invalidate_dcache_all(void);
 
-static int check_cache_range(unsigned long start, unsigned long stop)
-{
-	int ok = 1;
-
-	if (start & (CONFIG_SYS_CACHELINE_SIZE - 1))
-		ok = 0;
-
-	if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1))
-		ok = 0;
-
-	if (!ok)
-		debug("CACHE: Misaligned operation at range [%08lx, %08lx]\n",
-			start, stop);
-
-	return ok;
-}
-
 static u32 get_ccsidr(void)
 {
 	u32 ccsidr;
@@ -61,27 +44,8 @@
 {
 	u32 mva;
 
-	/*
-	 * If start address is not aligned to cache-line do not
-	 * invalidate the first cache-line
-	 */
-	if (start & (line_len - 1)) {
-		printf("ERROR: %s - start address is not aligned - 0x%08x\n",
-			__func__, start);
-		/* move to next cache line */
-		start = (start + line_len - 1) & ~(line_len - 1);
-	}
-
-	/*
-	 * If stop address is not aligned to cache-line do not
-	 * invalidate the last cache-line
-	 */
-	if (stop & (line_len - 1)) {
-		printf("ERROR: %s - stop address is not aligned - 0x%08x\n",
-			__func__, stop);
-		/* align to the beginning of this cache line */
-		stop &= ~(line_len - 1);
-	}
+	if (!check_cache_range(start, stop))
+		return;
 
 	for (mva = start; mva < stop; mva = mva + line_len) {
 		/* DCIMVAC - Invalidate data cache by MVA to PoC */
@@ -111,7 +75,7 @@
 	}
 
 	/* DSB to make sure the operation is complete */
-	DSB;
+	dsb();
 }
 
 /* Invalidate TLB */
@@ -124,9 +88,9 @@
 	/* Invalidate entire instruction TLB */
 	asm volatile ("mcr p15, 0, %0, c8, c5, 0" : : "r" (0));
 	/* Full system DSB - make sure that the invalidation is complete */
-	DSB;
+	dsb();
 	/* Full system ISB - make sure the instruction stream sees it */
-	ISB;
+	isb();
 }
 
 void invalidate_dcache_all(void)
@@ -195,6 +159,14 @@
 {
 }
 
+void invalidate_dcache_range(unsigned long start, unsigned long stop)
+{
+}
+
+void flush_dcache_range(unsigned long start, unsigned long stop)
+{
+}
+
 void arm_init_before_mmu(void)
 {
 }
@@ -222,10 +194,10 @@
 	asm volatile ("mcr p15, 0, %0, c7, c5, 6" : : "r" (0));
 
 	/* Full system DSB - make sure that the invalidation is complete */
-	DSB;
+	dsb();
 
 	/* ISB - make sure the instruction stream sees it */
-	ISB;
+	isb();
 }
 #else
 void invalidate_icache_all(void)
diff --git a/arch/arm/cpu/armv7/ls102xa/psci.S b/arch/arm/cpu/armv7/ls102xa/psci.S
index cf5cd48..8f38680 100644
--- a/arch/arm/cpu/armv7/ls102xa/psci.S
+++ b/arch/arm/cpu/armv7/ls102xa/psci.S
@@ -12,33 +12,118 @@
 #include <asm/arch-armv7/generictimer.h>
 #include <asm/psci.h>
 
+#define RCPM_TWAITSR		0x04C
+
 #define SCFG_CORE0_SFT_RST      0x130
 #define SCFG_CORESRENCR         0x204
 
-#define DCFG_CCSR_BRR           0x0E4
-#define DCFG_CCSR_SCRATCHRW1    0x200
+#define DCFG_CCSR_RSTCR			0x0B0
+#define DCFG_CCSR_RSTCR_RESET_REQ	0x2
+#define DCFG_CCSR_BRR			0x0E4
+#define DCFG_CCSR_SCRATCHRW1		0x200
+
+#define PSCI_FN_PSCI_VERSION_FEATURE_MASK	0x0
+#define PSCI_FN_CPU_SUSPEND_FEATURE_MASK	0x0
+#define PSCI_FN_CPU_OFF_FEATURE_MASK		0x0
+#define PSCI_FN_CPU_ON_FEATURE_MASK		0x0
+#define PSCI_FN_AFFINITY_INFO_FEATURE_MASK	0x0
+#define PSCI_FN_SYSTEM_OFF_FEATURE_MASK		0x0
+#define PSCI_FN_SYSTEM_RESET_FEATURE_MASK	0x0
 
 	.pushsection ._secure.text, "ax"
 
 	.arch_extension sec
 
+	.align	5
+
 #define	ONE_MS		(GENERIC_TIMER_CLK / 1000)
 #define	RESET_WAIT	(30 * ONE_MS)
 
+.globl	psci_version
+psci_version:
+	movw	r0, #0
+	movt	r0, #1
+
+	bx	lr
+
+_ls102x_psci_supported_table:
+	.word	ARM_PSCI_0_2_FN_PSCI_VERSION
+	.word	PSCI_FN_PSCI_VERSION_FEATURE_MASK
+	.word	ARM_PSCI_0_2_FN_CPU_SUSPEND
+	.word	PSCI_FN_CPU_SUSPEND_FEATURE_MASK
+	.word	ARM_PSCI_0_2_FN_CPU_OFF
+	.word	PSCI_FN_CPU_OFF_FEATURE_MASK
+	.word	ARM_PSCI_0_2_FN_CPU_ON
+	.word	PSCI_FN_CPU_ON_FEATURE_MASK
+	.word	ARM_PSCI_0_2_FN_AFFINITY_INFO
+	.word	PSCI_FN_AFFINITY_INFO_FEATURE_MASK
+	.word	ARM_PSCI_0_2_FN_SYSTEM_OFF
+	.word	PSCI_FN_SYSTEM_OFF_FEATURE_MASK
+	.word	ARM_PSCI_0_2_FN_SYSTEM_RESET
+	.word	PSCI_FN_SYSTEM_RESET_FEATURE_MASK
+	.word	0
+	.word	ARM_PSCI_RET_NI
+
+.globl	psci_features
+psci_features:
+	adr	r2, _ls102x_psci_supported_table
+1:	ldr	r3, [r2]
+	cmp	r3, #0
+	beq	out_psci_features
+	cmp	r1, r3
+	addne	r2, r2, #8
+	bne	1b
+
+out_psci_features:
+	ldr	r0, [r2, #4]
+	bx	lr
+
+@ r0: return value ARM_PSCI_RET_SUCCESS or ARM_PSCI_RET_INVAL
+@ r1: input target CPU ID in MPIDR format, original value in r1 may be dropped
+@ r4: output validated CPU ID if ARM_PSCI_RET_SUCCESS returns, meaningless for
+@ ARM_PSCI_RET_INVAL,suppose caller saves r4 before calling
+LENTRY(psci_check_target_cpu_id)
+	@ Get the real CPU number
+	and	r4, r1, #0xff
+	mov	r0, #ARM_PSCI_RET_INVAL
+
+	@ Bit[31:24], bits must be zero.
+	tst	r1, #0xff000000
+	bxne	lr
+
+	@ Affinity level 2 - Cluster: only one cluster in LS1021xa.
+	tst	r1, #0xff0000
+	bxne	lr
+
+	@ Affinity level 1 - Processors: should be in 0xf00 format.
+	lsr	r1, r1, #8
+	teq	r1, #0xf
+	bxne	lr
+
+	@ Affinity level 0 - CPU: only 0, 1 are valid in LS1021xa.
+	cmp	r4, #2
+	bxge	lr
+
+	mov	r0, #ARM_PSCI_RET_SUCCESS
+	bx	lr
+ENDPROC(psci_check_target_cpu_id)
+
 	@ r1 = target CPU
 	@ r2 = target PC
 .globl	psci_cpu_on
 psci_cpu_on:
-	push	{lr}
+	push	{r4, r5, r6, lr}
 
 	@ Clear and Get the correct CPU number
 	@ r1 = 0xf01
-	and	r1, r1, #0xff
+	bl	psci_check_target_cpu_id
+	cmp	r0, #ARM_PSCI_RET_INVAL
+	beq	out_psci_cpu_on
 
-	mov	r0, r1
-	bl	psci_get_cpu_stack_top
-	str	r2, [r0]
-	dsb
+	mov	r0, r4
+	mov	r1, r2
+	bl	psci_save_target_pc
+	mov	r1, r4
 
 	@ Get DCFG base address
 	movw	r4, #(CONFIG_SYS_FSL_GUTS_ADDR & 0xffff)
@@ -101,7 +186,8 @@
 	@ Return
 	mov	r0, #ARM_PSCI_RET_SUCCESS
 
-	pop	{lr}
+out_psci_cpu_on:
+	pop	{r4, r5, r6, lr}
 	bx	lr
 
 .globl	psci_cpu_off
@@ -111,16 +197,50 @@
 1:	wfi
 	b	1b
 
+.globl	psci_affinity_info
+psci_affinity_info:
+	push	{lr}
+
+	mov	r0, #ARM_PSCI_RET_INVAL
+
+	@ Verify Affinity level
+	cmp	r2, #0
+	bne	out_affinity_info
+
-.globl	psci_arch_init
-psci_arch_init:
-	mov	r6, lr
+	bl	psci_check_target_cpu_id
+	cmp	r0, #ARM_PSCI_RET_INVAL
+	beq	out_affinity_info
+	mov	r1, r4
 
-	bl	psci_get_cpu_id
-	bl	psci_get_cpu_stack_top
-	mov	sp, r0
+	@ Get RCPM base address
+	movw	r4, #(CONFIG_SYS_FSL_RCPM_ADDR & 0xffff)
+	movt	r4, #(CONFIG_SYS_FSL_RCPM_ADDR >> 16)
 
-	bx	r6
+	mov	r0, #PSCI_AFFINITY_LEVEL_ON
+
+	@ Detect target CPU state
+	ldr	r2, [r4, #RCPM_TWAITSR]
+	rev	r2, r2
+	lsr	r2, r2, r1
+	ands	r2, r2, #1
+	beq	out_affinity_info
+
+	mov	r0, #PSCI_AFFINITY_LEVEL_OFF
+
+out_affinity_info:
+	pop	{pc}
+
+.globl	psci_system_reset
+psci_system_reset:
+	@ Get DCFG base address
+	movw	r1, #(CONFIG_SYS_FSL_GUTS_ADDR & 0xffff)
+	movt	r1, #(CONFIG_SYS_FSL_GUTS_ADDR >> 16)
+
+	mov	r2, #DCFG_CCSR_RSTCR_RESET_REQ
+	rev	r2, r2
+	str	r2, [r1, #DCFG_CCSR_RSTCR]
+
+1:	wfi
+	b	1b
 
-	.globl psci_text_end
-psci_text_end:
 	.popsection
diff --git a/arch/arm/cpu/armv7/mx6/Kconfig b/arch/arm/cpu/armv7/mx6/Kconfig
index 663f970..78383f0 100644
--- a/arch/arm/cpu/armv7/mx6/Kconfig
+++ b/arch/arm/cpu/armv7/mx6/Kconfig
@@ -148,6 +148,10 @@
 	bool "platinum-titanium"
 	select SUPPORT_SPL
 
+config TARGET_PCM058
+	bool "Phytec PCM058 i.MX6 Quad"
+	select SUPPORT_SPL
+
 config TARGET_SECOMX6
 	bool "secomx6 boards"
 
@@ -176,7 +180,19 @@
 	select MX6UL
 	select DM
 	select DM_THERMAL
+	select SUPPORT_SPL
+
+config TARGET_ZC5202
+	bool "zc5202"
+	select SUPPORT_SPL
+	select DM
+	select DM_THERMAL
+
+config TARGET_ZC5601
+	bool "zc5601"
 	select SUPPORT_SPL
+	select DM
+	select DM_THERMAL
 
 endchoice
 
@@ -192,6 +208,7 @@
 source "board/ccv/xpress/Kconfig"
 source "board/compulab/cm_fx6/Kconfig"
 source "board/congatec/cgtqmx6eval/Kconfig"
+source "board/el/el6x/Kconfig"
 source "board/embest/mx6boards/Kconfig"
 source "board/freescale/mx6qarm2/Kconfig"
 source "board/freescale/mx6qsabreauto/Kconfig"
@@ -200,6 +217,7 @@
 source "board/freescale/mx6sxsabresd/Kconfig"
 source "board/freescale/mx6sxsabreauto/Kconfig"
 source "board/freescale/mx6ul_14x14_evk/Kconfig"
+source "board/phytec/pcm058/Kconfig"
 source "board/gateworks/gw_ventana/Kconfig"
 source "board/kosagi/novena/Kconfig"
 source "board/seco/Kconfig"
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c
index ff932aa..b3c9dcc 100644
--- a/arch/arm/cpu/armv7/mx6/clock.c
+++ b/arch/arm/cpu/armv7/mx6/clock.c
@@ -281,7 +281,7 @@
 	case PLL_BUS:
 		if (!is_mx6ul()) {
 			if (pfd_num == 3) {
-				/* No PFD3 on PPL2 */
+				/* No PFD3 on PLL2 */
 				return 0;
 			}
 		}
@@ -433,9 +433,9 @@
 
 	if (cbcdr & MXC_CCM_CBCDR_AXI_SEL) {
 		if (cbcdr & MXC_CCM_CBCDR_AXI_ALT_SEL)
-			root_freq = mxc_get_pll_pfd(PLL_BUS, 2);
-		else
 			root_freq = mxc_get_pll_pfd(PLL_USBOTG, 1);
+		else
+			root_freq = mxc_get_pll_pfd(PLL_BUS, 2);
 	} else
 		root_freq = get_periph_clk();
 
diff --git a/arch/arm/cpu/armv7/mx7/Kconfig b/arch/arm/cpu/armv7/mx7/Kconfig
index ecfa4a2..5fdc8dd 100644
--- a/arch/arm/cpu/armv7/mx7/Kconfig
+++ b/arch/arm/cpu/armv7/mx7/Kconfig
@@ -3,6 +3,8 @@
 config MX7
 	bool
 	select ROM_UNIFIED_SECTIONS
+	select CPU_V7_HAS_VIRT
+	select CPU_V7_HAS_NONSEC
 	default y
 
 config MX7D
@@ -25,12 +27,19 @@
 	select DM
 	select DM_THERMAL
 
+config TARGET_COLIBRI_IMX7
+	bool "Support Colibri iMX7S/iMX7D modules"
+	select DM
+	select DM_SERIAL
+	select DM_THERMAL
+
 endchoice
 
 config SYS_SOC
 	default "mx7"
 
 source "board/freescale/mx7dsabresd/Kconfig"
+source "board/toradex/colibri_imx7/Kconfig"
 source "board/warp7/Kconfig"
 
 endif
diff --git a/arch/arm/cpu/armv7/mx7/psci-mx7.c b/arch/arm/cpu/armv7/mx7/psci-mx7.c
index 9a33047..502552d 100644
--- a/arch/arm/cpu/armv7/mx7/psci-mx7.c
+++ b/arch/arm/cpu/armv7/mx7/psci-mx7.c
@@ -1,9 +1,9 @@
 #include <asm/io.h>
 #include <asm/psci.h>
+#include <asm/secure.h>
 #include <asm/arch/imx-regs.h>
 #include <common.h>
 
-#define __secure __attribute__((section("._secure.text")))
 
 #define GPC_CPU_PGC_SW_PDN_REQ	0xfc
 #define GPC_CPU_PGC_SW_PUP_REQ	0xf0
diff --git a/arch/arm/cpu/armv7/mx7/psci.S b/arch/arm/cpu/armv7/mx7/psci.S
index 34c6ab3..96e88d6 100644
--- a/arch/arm/cpu/armv7/mx7/psci.S
+++ b/arch/arm/cpu/armv7/mx7/psci.S
@@ -9,35 +9,22 @@
 
 	.arch_extension sec
 
-	@ r1 = target CPU
-	@ r2 = target PC
-
-.globl	psci_arch_init
-psci_arch_init:
-	mov	r6, lr
-
-	bl	psci_get_cpu_id
-	bl	psci_get_cpu_stack_top
-	mov	sp, r0
-
-	bx	r6
-
-	@ r1 = target CPU
-	@ r2 = target PC
-
 .globl psci_cpu_on
 psci_cpu_on:
-	push	{lr}
+	push	{r4, r5, lr}
 
+	mov	r4, r0
+	mov	r5, r1
 	mov	r0, r1
-	bl	psci_get_cpu_stack_top
-	str	r2, [r0]
-	dsb
+	mov	r1, r2
+	bl	psci_save_target_pc
 
+	mov	r0, r4
+	mov	r1, r5
 	ldr	r2, =psci_cpu_entry
 	bl	imx_cpu_on
 
-	pop	{pc}
+	pop	{r4, r5, pc}
 
 .globl psci_cpu_off
 psci_cpu_off:
@@ -49,6 +36,4 @@
 1: 	wfi
 	b 1b
 
-	.globl psci_text_end
-psci_text_end:
 	.popsection
diff --git a/arch/arm/cpu/armv7/mx7/soc.c b/arch/arm/cpu/armv7/mx7/soc.c
index ef46c92..dead1d3 100644
--- a/arch/arm/cpu/armv7/mx7/soc.c
+++ b/arch/arm/cpu/armv7/mx7/soc.c
@@ -248,6 +248,20 @@
 	return 0;
 }
 
+#ifdef CONFIG_ARCH_MISC_INIT
+int arch_misc_init(void)
+{
+#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+	if (is_mx7d())
+		setenv("soc", "imx7d");
+	else
+		setenv("soc", "imx7s");
+#endif
+
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_SERIAL_TAG
 void get_board_serial(struct tag_serialnr *serialnr)
 {
diff --git a/arch/arm/cpu/armv7/nonsec_virt.S b/arch/arm/cpu/armv7/nonsec_virt.S
index b7563ed..95ce938 100644
--- a/arch/arm/cpu/armv7/nonsec_virt.S
+++ b/arch/arm/cpu/armv7/nonsec_virt.S
@@ -49,8 +49,13 @@
 	mcr	p15, 0, r5, c12, c0, 1
 	isb
 
-	@ Obtain a secure stack, and configure the PSCI backend
+	@ Obtain a secure stack
+	bl	psci_stack_setup
+
+	@ Configure the PSCI backend
+	push	{r0, r1, r2, ip}
 	bl	psci_arch_init
+	pop	{r0, r1, r2, ip}
 #endif
 
 #ifdef CONFIG_ARM_ERRATA_773022
diff --git a/arch/arm/cpu/armv7/omap-common/Makefile b/arch/arm/cpu/armv7/omap-common/Makefile
index 87a7ac0..3172bae 100644
--- a/arch/arm/cpu/armv7/omap-common/Makefile
+++ b/arch/arm/cpu/armv7/omap-common/Makefile
@@ -36,3 +36,5 @@
 obj-y	+= lowlevel_init.o
 
 obj-y	+= mem-common.o
+
+obj-$(CONFIG_TI_SECURE_DEVICE) += sec-common.o
diff --git a/arch/arm/cpu/armv7/omap-common/clocks-common.c b/arch/arm/cpu/armv7/omap-common/clocks-common.c
index 2de9935..9b97583 100644
--- a/arch/arm/cpu/armv7/omap-common/clocks-common.c
+++ b/arch/arm/cpu/armv7/omap-common/clocks-common.c
@@ -443,15 +443,12 @@
 {
 	u32 offset_code;
 	u32 offset = volt_mv;
-#ifndef	CONFIG_DRA7XX
 	int ret = 0;
-#endif
 
 	if (!volt_mv)
 		return;
 
 	pmic->pmic_bus_init();
-#ifndef	CONFIG_DRA7XX
 	/* See if we can first get the GPIO if needed */
 	if (pmic->gpio_en)
 		ret = gpio_request(pmic->gpio, "PMIC_GPIO");
@@ -465,7 +462,7 @@
 	/* Pull the GPIO low to select SET0 register, while we program SET1 */
 	if (pmic->gpio_en)
 		gpio_direction_output(pmic->gpio, 0);
-#endif
+
 	/* convert to uV for better accuracy in the calculations */
 	offset *= 1000;
 
@@ -476,10 +473,8 @@
 
 	if (pmic->pmic_write(pmic->i2c_slave_addr, vcore_reg, offset_code))
 		printf("Scaling voltage failed for 0x%x\n", vcore_reg);
-#ifndef	CONFIG_DRA7XX
 	if (pmic->gpio_en)
 		gpio_direction_output(pmic->gpio, 1);
-#endif
 }
 
 static u32 optimize_vcore_voltage(struct volts const *v)
@@ -534,7 +529,6 @@
  */
 void scale_vcores(struct vcores_data const *vcores)
 {
-#if defined(CONFIG_DRA7XX)
 	int i;
 	struct volts *pv = (struct volts *)vcores;
 	struct volts *px;
@@ -594,7 +588,16 @@
 		  vcores->mpu.abb_tx_done_mask,
 		  OMAP_ABB_FAST_OPP);
 
-	/* The .mm member is not used for the DRA7xx */
+	debug("mm: %d\n", vcores->mm.value);
+	do_scale_vcore(vcores->mm.addr, vcores->mm.value, vcores->mm.pmic);
+	/* Configure MM ABB LDO after scale */
+	abb_setup(vcores->mm.efuse.reg,
+		  (*ctrl)->control_wkup_ldovbb_mm_voltage_ctrl,
+		  (*prcm)->prm_abbldo_mm_setup,
+		  (*prcm)->prm_abbldo_mm_ctrl,
+		  (*prcm)->prm_irqstatus_mpu,
+		  vcores->mm.abb_tx_done_mask,
+		  OMAP_ABB_FAST_OPP);
 
 	debug("gpu: %d\n", vcores->gpu.value);
 	do_scale_vcore(vcores->gpu.addr, vcores->gpu.value, vcores->gpu.pmic);
@@ -626,56 +629,6 @@
 		  (*prcm)->prm_irqstatus_mpu,
 		  vcores->iva.abb_tx_done_mask,
 		  OMAP_ABB_FAST_OPP);
-	/* Might need udelay(1000) here if debug is enabled to see all prints */
-#else
-	u32 val;
-
-	val = optimize_vcore_voltage(&vcores->core);
-	do_scale_vcore(vcores->core.addr, val, vcores->core.pmic);
-
-	/*
-	 * IO delay recalibration should be done immediately after
-	 * adjusting AVS voltages for VDD_CORE_L.
-	 * Respective boards should call __recalibrate_iodelay()
-	 * with proper mux, virtual and manual mode configurations.
-	 */
-#ifdef CONFIG_IODELAY_RECALIBRATION
-	recalibrate_iodelay();
-#endif
-
-	val = optimize_vcore_voltage(&vcores->mpu);
-	do_scale_vcore(vcores->mpu.addr, val, vcores->mpu.pmic);
-
-	/* Configure MPU ABB LDO after scale */
-	abb_setup(vcores->mpu.efuse.reg,
-		  (*ctrl)->control_wkup_ldovbb_mpu_voltage_ctrl,
-		  (*prcm)->prm_abbldo_mpu_setup,
-		  (*prcm)->prm_abbldo_mpu_ctrl,
-		  (*prcm)->prm_irqstatus_mpu_2,
-		  vcores->mpu.abb_tx_done_mask,
-		  OMAP_ABB_FAST_OPP);
-
-	val = optimize_vcore_voltage(&vcores->mm);
-	do_scale_vcore(vcores->mm.addr, val, vcores->mm.pmic);
-
-	/* Configure MM ABB LDO after scale */
-	abb_setup(vcores->mm.efuse.reg,
-		  (*ctrl)->control_wkup_ldovbb_mm_voltage_ctrl,
-		  (*prcm)->prm_abbldo_mm_setup,
-		  (*prcm)->prm_abbldo_mm_ctrl,
-		  (*prcm)->prm_irqstatus_mpu,
-		  vcores->mm.abb_tx_done_mask,
-		  OMAP_ABB_FAST_OPP);
-
-	val = optimize_vcore_voltage(&vcores->gpu);
-	do_scale_vcore(vcores->gpu.addr, val, vcores->gpu.pmic);
-
-	val = optimize_vcore_voltage(&vcores->eve);
-	do_scale_vcore(vcores->eve.addr, val, vcores->eve.pmic);
-
-	val = optimize_vcore_voltage(&vcores->iva);
-	do_scale_vcore(vcores->iva.addr, val, vcores->iva.pmic);
-#endif
 }
 
 static inline void enable_clock_domain(u32 const clkctrl_reg, u32 enable_mode)
diff --git a/arch/arm/cpu/armv7/omap-common/config_secure.mk b/arch/arm/cpu/armv7/omap-common/config_secure.mk
index c7bb101..1122439 100644
--- a/arch/arm/cpu/armv7/omap-common/config_secure.mk
+++ b/arch/arm/cpu/armv7/omap-common/config_secure.mk
@@ -12,8 +12,8 @@
 	$(if $(KBUILD_VERBOSE:1=), >/dev/null)
 else
 cmd_mkomapsecimg = $(TI_SECURE_DEV_PKG)/scripts/create-boot-image.sh \
-    $(patsubst u-boot_HS_%,%,$(@F)) $< $@ $(CONFIG_ISW_ENTRY_ADDR) \
-    $(if $(KBUILD_VERBOSE:1=), >/dev/null)
+	$(patsubst u-boot_HS_%,%,$(@F)) $< $@ $(CONFIG_ISW_ENTRY_ADDR) \
+	$(if $(KBUILD_VERBOSE:1=), >/dev/null)
 endif
 else
 cmd_mkomapsecimg = echo "WARNING:" \
@@ -25,14 +25,33 @@
 	"variable must be defined for TI secure devices. $@ was NOT created!"
 endif
 
+ifdef CONFIG_SPL_LOAD_FIT
+quiet_cmd_omapsecureimg = SECURE  $@
+ifneq ($(TI_SECURE_DEV_PKG),)
+ifneq ($(wildcard $(TI_SECURE_DEV_PKG)/scripts/secure-binary-image.sh),)
+cmd_omapsecureimg = $(TI_SECURE_DEV_PKG)/scripts/secure-binary-image.sh \
+	$< $@ \
+	$(if $(KBUILD_VERBOSE:1=), >/dev/null)
+else
+cmd_omapsecureimg = echo "WARNING:" \
+	"$(TI_SECURE_DEV_PKG)/scripts/secure-binary-image.sh not found." \
+	"$@ was NOT created!"; cp $< $@
+endif
+else
+cmd_omapsecureimg = echo "WARNING: TI_SECURE_DEV_PKG environment" \
+	"variable must be defined for TI secure devices." \
+	"$@ was NOT created!"; cp $< $@
+endif
+endif
+
+
 # Standard X-LOADER target (QPSI, NOR flash)
 u-boot-spl_HS_X-LOADER: $(obj)/u-boot-spl.bin
 	$(call if_changed,mkomapsecimg)
 
-# For MLO targets (SD card boot) the final file name
-# that is copied to the SD card fAT partition must
-# be MLO, so we make a copy of the output file to a
-# new file with that name
+# For MLO targets (SD card boot) the final file name that is copied to the SD
+# card FAT partition must be MLO, so we make a copy of the output file to a new
+# file with that name
 u-boot-spl_HS_MLO: $(obj)/u-boot-spl.bin
 	$(call if_changed,mkomapsecimg)
 	@if [ -f $@ ]; then \
@@ -51,16 +70,44 @@
 u-boot-spl_HS_ISSW: $(obj)/u-boot-spl.bin
 	$(call if_changed,mkomapsecimg)
 
-# For SPI flash on AM335x and AM43xx, these
-# require special byte swap handling so we use
-# the SPI_X-LOADER target instead of X-LOADER
-# and let the create-boot-image.sh script handle
-# that
+# For SPI flash on AM335x and AM43xx, these require special byte swap handling
+# so we use the SPI_X-LOADER target instead of X-LOADER and let the
+# create-boot-image.sh script handle that
 u-boot-spl_HS_SPI_X-LOADER: $(obj)/u-boot-spl.bin
 	$(call if_changed,mkomapsecimg)
 
-# For supporting single stage XiP QSPI on AM43xx, the
-# image is a full u-boot file, not an SPL. In this case
-# the mkomapsecimg command looks for a u-boot-HS_* prefix
+# For supporting single stage XiP QSPI on AM43xx, the image is a full u-boot
+# file, not an SPL. In this case the mkomapsecimg command looks for a
+# u-boot-HS_* prefix
 u-boot_HS_XIP_X-LOADER: $(obj)/u-boot.bin
 	$(call if_changed,mkomapsecimg)
+
+# For supporting the SPL loading and interpreting of FIT images whose
+# components are pre-processed before being integrated into the FIT image in
+# order to secure them in some way
+ifdef CONFIG_SPL_LOAD_FIT
+
+MKIMAGEFLAGS_u-boot_HS.img = -f auto -A $(ARCH) -T firmware -C none -O u-boot \
+	-a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_UBOOT_START) \
+	-n "U-Boot $(UBOOTRELEASE) for $(BOARD) board" -E \
+	$(patsubst %,-b arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST)))
+
+OF_LIST_TARGETS = $(patsubst %,arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST)))
+$(OF_LIST_TARGETS): dtbs
+
+%_HS.dtb: %.dtb
+	$(call if_changed,omapsecureimg)
+	$(Q)if [ -f $@ ]; then \
+		cp -f $@ $<; \
+	fi
+
+u-boot-nodtb_HS.bin: u-boot-nodtb.bin
+	$(call if_changed,omapsecureimg)
+
+u-boot_HS.img: u-boot-nodtb_HS.bin u-boot.img $(patsubst %.dtb,%_HS.dtb,$(OF_LIST_TARGETS))
+	$(call if_changed,mkimage)
+	$(Q)if [ -f $@ ]; then \
+		cp -f $@ u-boot.img; \
+	fi
+
+endif
diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c
index 9a9c764..2b79010 100644
--- a/arch/arm/cpu/armv7/omap-common/emif-common.c
+++ b/arch/arm/cpu/armv7/omap-common/emif-common.c
@@ -37,7 +37,8 @@
 void force_emif_self_refresh()
 {
 	set_lpmode_selfrefresh(EMIF1_BASE);
-	set_lpmode_selfrefresh(EMIF2_BASE);
+	if (!is_dra72x())
+		set_lpmode_selfrefresh(EMIF2_BASE);
 }
 
 inline u32 emif_num(u32 base)
diff --git a/arch/arm/cpu/armv7/omap-common/hwinit-common.c b/arch/arm/cpu/armv7/omap-common/hwinit-common.c
index 2f9693f..f317293 100644
--- a/arch/arm/cpu/armv7/omap-common/hwinit-common.c
+++ b/arch/arm/cpu/armv7/omap-common/hwinit-common.c
@@ -147,8 +147,7 @@
 	hw_data_init();
 
 #ifdef CONFIG_SPL_BUILD
-	if (warm_reset() &&
-	    (is_omap44xx() || (omap_revision() == OMAP5430_ES1_0)))
+	if (warm_reset())
 		force_emif_self_refresh();
 #endif
 	watchdog_init();
diff --git a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S
index 5283135..66a3b3d 100644
--- a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S
+++ b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S
@@ -16,9 +16,10 @@
 #include <asm/arch/spl.h>
 #include <linux/linkage.h>
 
+.arch_extension sec
+
 #ifdef CONFIG_SPL
 ENTRY(save_boot_params)
-
 	ldr	r1, =OMAP_SRAM_SCRATCH_BOOT_PARAMS
 	str	r0, [r1]
 	b	save_boot_params_ret
@@ -26,14 +27,40 @@
 #endif
 
 ENTRY(omap_smc1)
-	PUSH	{r4-r12, lr}	@ save registers - ROM code may pollute
+	push	{r4-r12, lr}	@ save registers - ROM code may pollute
 				@ our registers
-	MOV	r12, r0		@ Service
-	MOV	r0, r1		@ Argument
-	DSB
-	DMB
-	.word	0xe1600070	@ SMC #0 - hand assembled for GCC versions
-				@ call ROM Code API for the service requested
+	mov	r12, r0		@ Service
+	mov	r0, r1		@ Argument
 
-	POP	{r4-r12, pc}
+	dsb
+	dmb
+	smc	0		@ SMC #0 to enter monitor mode
+				@ call ROM Code API for the service requested
+	pop	{r4-r12, pc}
 ENDPROC(omap_smc1)
+
+ENTRY(omap_smc_sec)
+	push	{r4-r12, lr}	@ save registers - ROM code may pollute
+				@ our registers
+	mov	r6, #0xFF	@ Indicate new Task call
+	mov	r12, #0x00	@ Secure Service ID in R12
+
+	dsb
+	dmb
+	smc	0		@ SMC #0 to enter monitor mode
+
+	b	omap_smc_sec_end @ exit at end of the service execution
+	nop
+
+	@ In case of IRQ happening in Secure, then ARM will branch here.
+	@ At that moment, IRQ will be pending and ARM will jump to Non Secure
+	@ IRQ handler
+	mov	r12, #0xFE
+
+	dsb
+	dmb
+	smc	0		@ SMC #0 to enter monitor mode
+
+omap_smc_sec_end:
+	pop	{r4-r12, pc}
+ENDPROC(omap_smc_sec)
diff --git a/arch/arm/cpu/armv7/omap-common/mem-common.c b/arch/arm/cpu/armv7/omap-common/mem-common.c
index fc4290c..d72e82e 100644
--- a/arch/arm/cpu/armv7/omap-common/mem-common.c
+++ b/arch/arm/cpu/armv7/omap-common/mem-common.c
@@ -20,8 +20,19 @@
 #include <asm/arch/sys_proto.h>
 #include <command.h>
 #include <linux/mtd/omap_gpmc.h>
+#include <jffs2/load_kernel.h>
 
-struct gpmc *gpmc_cfg;
+const struct gpmc *gpmc_cfg = (struct gpmc *)GPMC_BASE;
+
+#if defined(CONFIG_NOR)
+char gpmc_cs0_flash = MTD_DEV_TYPE_NOR;
+#elif defined(CONFIG_NAND) || defined(CONFIG_CMD_NAND)
+char gpmc_cs0_flash = MTD_DEV_TYPE_NAND;
+#elif defined(CONFIG_CMD_ONENAND)
+char gpmc_cs0_flash = MTD_DEV_TYPE_ONENAND;
+#else
+char gpmc_cs0_flash = -1;
+#endif
 
 #if defined(CONFIG_OMAP34XX)
 /********************************************************
@@ -50,8 +61,8 @@
 }
 #endif
 
-void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base,
-			u32 size)
+void enable_gpmc_cs_config(const u32 *gpmc_config, const struct gpmc_cs *cs,
+				u32 base, u32 size)
 {
 	writel(0, &cs->config7);
 	sdelay(1000);
@@ -68,6 +79,81 @@
 	sdelay(2000);
 }
 
+void set_gpmc_cs0(int flash_type)
+{
+	const u32 *gpmc_regs;
+	u32 base, size;
+#if defined(CONFIG_NOR)
+	const u32 gpmc_regs_nor[GPMC_MAX_REG] = {
+		STNOR_GPMC_CONFIG1,
+		STNOR_GPMC_CONFIG2,
+		STNOR_GPMC_CONFIG3,
+		STNOR_GPMC_CONFIG4,
+		STNOR_GPMC_CONFIG5,
+		STNOR_GPMC_CONFIG6,
+		STNOR_GPMC_CONFIG7
+	};
+#endif
+#if defined(CONFIG_NAND) || defined(CONFIG_CMD_NAND)
+	const u32 gpmc_regs_nand[GPMC_MAX_REG] = {
+		M_NAND_GPMC_CONFIG1,
+		M_NAND_GPMC_CONFIG2,
+		M_NAND_GPMC_CONFIG3,
+		M_NAND_GPMC_CONFIG4,
+		M_NAND_GPMC_CONFIG5,
+		M_NAND_GPMC_CONFIG6,
+		0
+	};
+#endif
+#if defined(CONFIG_CMD_ONENAND)
+	const u32 gpmc_regs_onenand[GPMC_MAX_REG] = {
+		ONENAND_GPMC_CONFIG1,
+		ONENAND_GPMC_CONFIG2,
+		ONENAND_GPMC_CONFIG3,
+		ONENAND_GPMC_CONFIG4,
+		ONENAND_GPMC_CONFIG5,
+		ONENAND_GPMC_CONFIG6,
+		0
+	};
+#endif
+
+	switch (flash_type) {
+#if defined(CONFIG_NOR)
+	case MTD_DEV_TYPE_NOR:
+		gpmc_regs = gpmc_regs_nor;
+		base = CONFIG_SYS_FLASH_BASE;
+		size = (CONFIG_SYS_FLASH_SIZE > 0x08000000) ? GPMC_SIZE_256M :
+		      ((CONFIG_SYS_FLASH_SIZE > 0x04000000) ? GPMC_SIZE_128M :
+		      ((CONFIG_SYS_FLASH_SIZE > 0x02000000) ? GPMC_SIZE_64M  :
+		      ((CONFIG_SYS_FLASH_SIZE > 0x01000000) ? GPMC_SIZE_32M  :
+		                                              GPMC_SIZE_16M)));
+		break;
+#endif
+#if defined(CONFIG_NAND) || defined(CONFIG_CMD_NAND)
+	case MTD_DEV_TYPE_NAND:
+		gpmc_regs = gpmc_regs_nand;
+		base = CONFIG_SYS_NAND_BASE;
+		size = GPMC_SIZE_16M;
+		break;
+#endif
+#if defined(CONFIG_CMD_ONENAND)
+	case MTD_DEV_TYPE_ONENAND:
+		gpmc_regs = gpmc_regs_onenand;
+		base = CONFIG_SYS_ONENAND_BASE;
+		size = GPMC_SIZE_128M;
+		break;
+#endif
+	default:
+		/* disable the GPMC0 config set by ROM code */
+		writel(0, &gpmc_cfg->cs[0].config7);
+		sdelay(1000);
+		return;
+	}
+
+	/* enable chip-select specific configurations */
+	enable_gpmc_cs_config(gpmc_regs, &gpmc_cfg->cs[0], base, size);
+}
+
 /*****************************************************
  * gpmc_init(): init gpmc bus
  * Init GPMC for x16, MuxMode (SDRAM in x32).
@@ -75,70 +161,14 @@
  *****************************************************/
 void gpmc_init(void)
 {
-	/* putting a blanket check on GPMC based on ZeBu for now */
-	gpmc_cfg = (struct gpmc *)GPMC_BASE;
-#if defined(CONFIG_NOR)
-/* configure GPMC for NOR */
-	const u32 gpmc_regs[GPMC_MAX_REG] = {	STNOR_GPMC_CONFIG1,
-						STNOR_GPMC_CONFIG2,
-						STNOR_GPMC_CONFIG3,
-						STNOR_GPMC_CONFIG4,
-						STNOR_GPMC_CONFIG5,
-						STNOR_GPMC_CONFIG6,
-						STNOR_GPMC_CONFIG7
-						};
-	u32 base = CONFIG_SYS_FLASH_BASE;
-	u32 size =	(CONFIG_SYS_FLASH_SIZE  > 0x08000000) ? GPMC_SIZE_256M :
-	/* > 64MB */	((CONFIG_SYS_FLASH_SIZE > 0x04000000) ? GPMC_SIZE_128M :
-	/* > 32MB */	((CONFIG_SYS_FLASH_SIZE > 0x02000000) ? GPMC_SIZE_64M  :
-	/* > 16MB */	((CONFIG_SYS_FLASH_SIZE > 0x01000000) ? GPMC_SIZE_32M  :
-	/* min 16MB */	GPMC_SIZE_16M)));
-#elif defined(CONFIG_NAND) || defined(CONFIG_CMD_NAND)
-/* configure GPMC for NAND */
-	const u32  gpmc_regs[GPMC_MAX_REG] = {	M_NAND_GPMC_CONFIG1,
-						M_NAND_GPMC_CONFIG2,
-						M_NAND_GPMC_CONFIG3,
-						M_NAND_GPMC_CONFIG4,
-						M_NAND_GPMC_CONFIG5,
-						M_NAND_GPMC_CONFIG6,
-						0
-						};
-	u32 base = CONFIG_SYS_NAND_BASE;
-	u32 size = GPMC_SIZE_16M;
-
-#elif defined(CONFIG_CMD_ONENAND)
-	const u32 gpmc_regs[GPMC_MAX_REG] = {	ONENAND_GPMC_CONFIG1,
-						ONENAND_GPMC_CONFIG2,
-						ONENAND_GPMC_CONFIG3,
-						ONENAND_GPMC_CONFIG4,
-						ONENAND_GPMC_CONFIG5,
-						ONENAND_GPMC_CONFIG6,
-						0
-						};
-	u32 size = GPMC_SIZE_128M;
-	u32 base = CONFIG_SYS_ONENAND_BASE;
-#else
-	const u32 gpmc_regs[GPMC_MAX_REG] = { 0, 0, 0, 0, 0, 0, 0 };
-	u32 size = 0;
-	u32 base = 0;
-#endif
 	/* global settings */
 	writel(0x00000008, &gpmc_cfg->sysconfig);
 	writel(0x00000000, &gpmc_cfg->irqstatus);
 	writel(0x00000000, &gpmc_cfg->irqenable);
 	/* disable timeout, set a safe reset value */
 	writel(0x00001ff0, &gpmc_cfg->timeout_control);
-#ifdef CONFIG_NOR
-	writel(0x00000200, &gpmc_cfg->config);
-#else
-	writel(0x00000012, &gpmc_cfg->config);
-#endif
-	/*
-	 * Disable the GPMC0 config set by ROM code
-	 */
-	writel(0, &gpmc_cfg->cs[0].config7);
-	sdelay(1000);
-	/* enable chip-select specific configurations */
-	if (base != 0)
-		enable_gpmc_cs_config(gpmc_regs, &gpmc_cfg->cs[0], base, size);
+	writel(gpmc_cs0_flash == MTD_DEV_TYPE_NOR ?
+		0x00000200 : 0x00000012, &gpmc_cfg->config);
+
+	set_gpmc_cs0(gpmc_cs0_flash);
 }
diff --git a/arch/arm/cpu/armv7/omap-common/sec-common.c b/arch/arm/cpu/armv7/omap-common/sec-common.c
new file mode 100644
index 0000000..246a239
--- /dev/null
+++ b/arch/arm/cpu/armv7/omap-common/sec-common.c
@@ -0,0 +1,139 @@
+/*
+ *
+ * Common security related functions for OMAP devices
+ *
+ * (C) Copyright 2016
+ * Texas Instruments, <www.ti.com>
+ *
+ * Daniel Allred <d-allred@ti.com>
+ * Andreas Dannenberg <dannenberg@ti.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <stdarg.h>
+
+#include <asm/arch/sys_proto.h>
+#include <asm/omap_common.h>
+#include <asm/omap_sec_common.h>
+#include <asm/spl.h>
+#include <spl.h>
+
+/* Index for signature verify ROM API */
+#define API_HAL_KM_VERIFYCERTIFICATESIGNATURE_INDEX	(0x0000000E)
+
+static uint32_t secure_rom_call_args[5] __aligned(ARCH_DMA_MINALIGN);
+
+u32 secure_rom_call(u32 service, u32 proc_id, u32 flag, ...)
+{
+	int i;
+	u32 num_args;
+	va_list ap;
+
+	va_start(ap, flag);
+
+	num_args = va_arg(ap, u32);
+
+	if (num_args > 4)
+		return 1;
+
+	/* Copy args to aligned args structure */
+	for (i = 0; i < num_args; i++)
+		secure_rom_call_args[i + 1] = va_arg(ap, u32);
+
+	secure_rom_call_args[0] = num_args;
+
+	va_end(ap);
+
+	/* if data cache is enabled, flush the aligned args structure */
+	flush_dcache_range(
+		(unsigned int)&secure_rom_call_args[0],
+		(unsigned int)&secure_rom_call_args[0] +
+		roundup(sizeof(secure_rom_call_args), ARCH_DMA_MINALIGN));
+
+	return omap_smc_sec(service, proc_id, flag, secure_rom_call_args);
+}
+
+static u32 find_sig_start(char *image, size_t size)
+{
+	char *image_end = image + size;
+	char *sig_start_magic = "CERT_";
+	int magic_str_len = strlen(sig_start_magic);
+	char *ch;
+
+	while (--image_end > image) {
+		if (*image_end == '_') {
+			ch = image_end - magic_str_len + 1;
+			if (!strncmp(ch, sig_start_magic, magic_str_len))
+				return (u32)ch;
+		}
+	}
+	return 0;
+}
+
+int secure_boot_verify_image(void **image, size_t *size)
+{
+	int result = 1;
+	u32 cert_addr, sig_addr;
+	size_t cert_size;
+
+	/* Perform cache writeback on input buffer */
+	flush_dcache_range(
+		(u32)*image,
+		(u32)*image + roundup(*size, ARCH_DMA_MINALIGN));
+
+	cert_addr = (uint32_t)*image;
+	sig_addr = find_sig_start((char *)*image, *size);
+
+	if (sig_addr == 0) {
+		printf("No signature found in image!\n");
+		result = 1;
+		goto auth_exit;
+	}
+
+	*size = sig_addr - cert_addr;	/* Subtract out the signature size */
+	cert_size = *size;
+
+	/* Check if image load address is 32-bit aligned */
+	if (!IS_ALIGNED(cert_addr, 4)) {
+		printf("Image is not 4-byte aligned!\n");
+		result = 1;
+		goto auth_exit;
+	}
+
+	/* Image size also should be multiple of 4 */
+	if (!IS_ALIGNED(cert_size, 4)) {
+		printf("Image size is not 4-byte aligned!\n");
+		result = 1;
+		goto auth_exit;
+	}
+
+	/* Call ROM HAL API to verify certificate signature */
+	debug("%s: load_addr = %x, size = %x, sig_addr = %x\n", __func__,
+	      cert_addr, cert_size, sig_addr);
+
+	result = secure_rom_call(
+		API_HAL_KM_VERIFYCERTIFICATESIGNATURE_INDEX, 0, 0,
+		4, cert_addr, cert_size, sig_addr, 0xFFFFFFFF);
+auth_exit:
+	if (result != 0) {
+		printf("Authentication failed!\n");
+		printf("Return Value = %08X\n", result);
+		hang();
+	}
+
+	/*
+	 * Output notification of successful authentication as well the name of
+	 * the signing certificate used to re-assure the user that the secure
+	 * code is being processed as expected. However suppress any such log
+	 * output in case of building for SPL and booting via YMODEM. This is
+	 * done to avoid disturbing the YMODEM serial protocol transactions.
+	 */
+	if (!(IS_ENABLED(CONFIG_SPL_BUILD) &&
+	      IS_ENABLED(CONFIG_SPL_YMODEM_SUPPORT) &&
+	      spl_boot_device() == BOOT_DEVICE_UART))
+		printf("Authentication passed: %s\n", (char *)sig_addr);
+
+	return result;
+}
diff --git a/arch/arm/cpu/armv7/omap3/Kconfig b/arch/arm/cpu/armv7/omap3/Kconfig
index 85d6436..99a25f9 100644
--- a/arch/arm/cpu/armv7/omap3/Kconfig
+++ b/arch/arm/cpu/armv7/omap3/Kconfig
@@ -6,55 +6,39 @@
 
 config TARGET_AM3517_EVM
 	bool "AM3517 EVM"
-	select SUPPORT_SPL
 
 config TARGET_MT_VENTOUX
 	bool "TeeJet Mt.Ventoux"
-	select SUPPORT_SPL
 
 config TARGET_OMAP3_BEAGLE
 	bool "TI OMAP3 BeagleBoard"
-	select SUPPORT_SPL
 	select DM
 	select DM_SERIAL
 	select DM_GPIO
 
 config TARGET_CM_T35
 	bool "CompuLab CM-T3530 and CM-T3730 boards"
-	select SUPPORT_SPL
 
 config TARGET_CM_T3517
 	bool "CompuLab CM-T3517 boards"
 
 config TARGET_DEVKIT8000
 	bool "TimLL OMAP3 Devkit8000"
-	select SUPPORT_SPL
 	select DM
 	select DM_SERIAL
 	select DM_GPIO
 
 config TARGET_OMAP3_EVM
 	bool "TI OMAP3 EVM"
-	select SUPPORT_SPL
-
-config TARGET_OMAP3_EVM_QUICK_MMC
-	bool "TI OMAP3 EVM Quick MMC"
-	select SUPPORT_SPL
-
-config TARGET_OMAP3_EVM_QUICK_NAND
-	bool "TI OMAP3 EVM Quick NAND"
-	select SUPPORT_SPL
 
 config TARGET_OMAP3_IGEP00X0
 	bool "IGEP"
-	select SUPPORT_SPL
 	select DM
 	select DM_SERIAL
 	select DM_GPIO
 
 config TARGET_OMAP3_OVERO
 	bool "OMAP35xx Gumstix Overo"
-	select SUPPORT_SPL
 	select DM
 	select DM_SERIAL
 	select DM_GPIO
@@ -67,51 +51,42 @@
 
 config TARGET_AM3517_CRANE
 	bool "am3517_crane"
-	select SUPPORT_SPL
 
 config TARGET_OMAP3_PANDORA
 	bool "OMAP3 Pandora"
 
 config TARGET_ECO5PK
 	bool "ECO5PK"
-	select SUPPORT_SPL
 
 config TARGET_TRICORDER
 	bool "Tricorder"
-	select SUPPORT_SPL
 
 config TARGET_MCX
 	bool "MCX"
-	select SUPPORT_SPL
 
 config TARGET_OMAP3_LOGIC
 	bool "OMAP3 Logic"
 	select DM
 	select DM_SERIAL
 	select DM_GPIO
-	select SUPPORT_SPL
 
 config TARGET_NOKIA_RX51
 	bool "Nokia RX51"
 
 config TARGET_TAO3530
 	bool "TAO3530"
-	select SUPPORT_SPL
 
 config TARGET_TWISTER
 	bool "Twister"
-	select SUPPORT_SPL
 
 config TARGET_OMAP3_CAIRO
 	bool "QUIPOS CAIRO"
-	select SUPPORT_SPL
 	select DM
 	select DM_SERIAL
 	select DM_GPIO
 
 config TARGET_SNIPER
 	bool "LG Optimus Black"
-	select SUPPORT_SPL
 	select DM
 	select DM_SERIAL
 	select DM_GPIO
diff --git a/arch/arm/cpu/armv7/omap3/spl_id_nand.c b/arch/arm/cpu/armv7/omap3/spl_id_nand.c
index db6de09..0e2f0a2 100644
--- a/arch/arm/cpu/armv7/omap3/spl_id_nand.c
+++ b/arch/arm/cpu/armv7/omap3/spl_id_nand.c
@@ -13,62 +13,45 @@
  */
 
 #include <common.h>
+#include <jffs2/load_kernel.h>
 #include <linux/mtd/nand.h>
+#include <linux/mtd/omap_gpmc.h>
 #include <asm/io.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/mem.h>
 
-static struct gpmc *gpmc_config = (struct gpmc *)GPMC_BASE;
-
-/* nand_command: Send a flash command to the flash chip */
-static void nand_command(u8 command)
-{
-	writeb(command, &gpmc_config->cs[0].nand_cmd);
-
-	if (command == NAND_CMD_RESET) {
-		unsigned char ret_val;
-		writeb(NAND_CMD_STATUS, &gpmc_config->cs[0].nand_cmd);
-		do {
-			/* Wait until ready */
-			ret_val = readl(&gpmc_config->cs[0].nand_dat);
-		} while ((ret_val & NAND_STATUS_READY) != NAND_STATUS_READY);
-	}
-}
-
 /*
  * Many boards will want to know the results of the NAND_CMD_READID command
  * in order to decide what to do about DDR initialization.  This function
  * allows us to do that very early and to pass those results back to the
  * board so it can make whatever decisions need to be made.
  */
-void identify_nand_chip(int *mfr, int *id)
+int identify_nand_chip(int *mfr, int *id)
 {
-	/* Make sure that we have setup GPMC for NAND correctly. */
-	writel(M_NAND_GPMC_CONFIG1, &gpmc_config->cs[0].config1);
-	writel(M_NAND_GPMC_CONFIG2, &gpmc_config->cs[0].config2);
-	writel(M_NAND_GPMC_CONFIG3, &gpmc_config->cs[0].config3);
-	writel(M_NAND_GPMC_CONFIG4, &gpmc_config->cs[0].config4);
-	writel(M_NAND_GPMC_CONFIG5, &gpmc_config->cs[0].config5);
-	writel(M_NAND_GPMC_CONFIG6, &gpmc_config->cs[0].config6);
+	int loops = 1000;
 
-	/*
-	 * Enable the config.  The CS size goes in bits 11:8.  We set
-	 * bit 6 to enable the CS and the base address goes into bits 5:0.
-	 */
-	writel((GPMC_SIZE_128M << 8) | (GPMC_CS_ENABLE << 6) |
-				((NAND_BASE >> 24) & GPMC_BASEADDR_MASK),
-			&gpmc_config->cs[0].config7);
+	/* Make sure that we have setup GPMC for NAND correctly. */
+	set_gpmc_cs0(MTD_DEV_TYPE_NAND);
 
 	sdelay(2000);
 
 	/* Issue a RESET and then READID */
-	nand_command(NAND_CMD_RESET);
-	nand_command(NAND_CMD_READID);
+	writeb(NAND_CMD_RESET, &gpmc_cfg->cs[0].nand_cmd);
+	writeb(NAND_CMD_STATUS, &gpmc_cfg->cs[0].nand_cmd);
+	while ((readl(&gpmc_cfg->cs[0].nand_dat) & NAND_STATUS_READY)
+	                                        != NAND_STATUS_READY) {
+		sdelay(100);
+		if (--loops == 0)
+			return 1;
+	}
+	writeb(NAND_CMD_READID, &gpmc_cfg->cs[0].nand_cmd);
 
 	/* Set the address to read to 0x0 */
-	writeb(0x0, &gpmc_config->cs[0].nand_adr);
+	writeb(0x0, &gpmc_cfg->cs[0].nand_adr);
 
 	/* Read off the manufacturer and device id. */
-	*mfr = readb(&gpmc_config->cs[0].nand_dat);
-	*id = readb(&gpmc_config->cs[0].nand_dat);
+	*mfr = readb(&gpmc_cfg->cs[0].nand_dat);
+	*id = readb(&gpmc_cfg->cs[0].nand_dat);
+
+	return 0;
 }
diff --git a/arch/arm/cpu/armv7/omap5/Kconfig b/arch/arm/cpu/armv7/omap5/Kconfig
index 4fb5ef9..a8600b1 100644
--- a/arch/arm/cpu/armv7/omap5/Kconfig
+++ b/arch/arm/cpu/armv7/omap5/Kconfig
@@ -13,6 +13,7 @@
 config TARGET_DRA7XX_EVM
 	bool "TI DRA7XX"
 	select TI_I2C_BOARD_DETECT
+	select PHYS_64BIT
 
 config TARGET_AM57XX_EVM
 	bool "AM57XX"
diff --git a/arch/arm/cpu/armv7/omap5/config.mk b/arch/arm/cpu/armv7/omap5/config.mk
index a7e55a5..286ca86 100644
--- a/arch/arm/cpu/armv7/omap5/config.mk
+++ b/arch/arm/cpu/armv7/omap5/config.mk
@@ -15,5 +15,8 @@
 ALL-y	+= MLO
 endif
 else
+ifeq ($(CONFIG_TI_SECURE_DEVICE),y)
+ALL-$(CONFIG_SPL_LOAD_FIT) += u-boot_HS.img
+endif
 ALL-y	+= u-boot.img
 endif
diff --git a/arch/arm/cpu/armv7/omap5/hw_data.c b/arch/arm/cpu/armv7/omap5/hw_data.c
index 62dd275..fc99135 100644
--- a/arch/arm/cpu/armv7/omap5/hw_data.c
+++ b/arch/arm/cpu/armv7/omap5/hw_data.c
@@ -160,7 +160,7 @@
 
 static const struct dpll_params per_dpll_params_768mhz_dra7xx[NUM_SYS_CLKS] = {
 	{32, 0, 4, 1, 3, 4, 4, 2, -1, -1, -1, -1},		/* 12 MHz   */
-	{96, 4, 4, 1, 3, 4, 4, 2, -1, -1, -1, -1},		/* 20 MHz   */
+	{96, 4, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1},		/* 20 MHz   */
 	{160, 6, 4, 1, 3, 4, 4, 2, -1, -1, -1, -1},		/* 16.8 MHz */
 	{20, 0, 4, 1, 3, 4, 4, 2, -1, -1, -1, -1},		/* 19.2 MHz */
 	{192, 12, 4, 1, 3, 4, 4, 2, -1, -1, -1, -1},		/* 26 MHz   */
@@ -318,6 +318,7 @@
 	.i2c_slave_addr	= SMPS_I2C_SLAVE_ADDR,
 	.pmic_bus_init	= sri2c_init,
 	.pmic_write	= omap_vc_bypass_send_value,
+	.gpio_en = 0,
 };
 
 /* The TPS659038 and TPS65917 are software-compatible, use common struct */
@@ -332,6 +333,7 @@
 	.i2c_slave_addr	= TPS659038_I2C_SLAVE_ADDR,
 	.pmic_bus_init	= gpi2c_init,
 	.pmic_write	= palmas_i2c_write_u8,
+	.gpio_en = 0,
 };
 
 struct vcores_data omap5430_volts = {
diff --git a/arch/arm/cpu/armv7/psci-common.c b/arch/arm/cpu/armv7/psci-common.c
new file mode 100644
index 0000000..8cb4107
--- /dev/null
+++ b/arch/arm/cpu/armv7/psci-common.c
@@ -0,0 +1,39 @@
+/*
+ * Common PSCI functions
+ *
+ * Copyright (C) 2016 Chen-Yu Tsai
+ * Author: Chen-Yu Tsai <wens@csie.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <asm/armv7.h>
+#include <asm/macro.h>
+#include <asm/psci.h>
+#include <asm/secure.h>
+#include <linux/linkage.h>
+
+static u32 psci_target_pc[CONFIG_ARMV7_PSCI_NR_CPUS] __secure_data = { 0 };
+
+void __secure psci_save_target_pc(int cpu, u32 pc)
+{
+	psci_target_pc[cpu] = pc;
+	dsb();
+}
+
+u32 __secure psci_get_target_pc(int cpu)
+{
+	return psci_target_pc[cpu];
+}
+
diff --git a/arch/arm/cpu/armv7/psci.S b/arch/arm/cpu/armv7/psci.S
index ab40837..f80f6e2 100644
--- a/arch/arm/cpu/armv7/psci.S
+++ b/arch/arm/cpu/armv7/psci.S
@@ -46,20 +46,62 @@
 ENDPROC(default_psci_vector)
 .weak default_psci_vector
 
+ENTRY(psci_version)
 ENTRY(psci_cpu_suspend)
 ENTRY(psci_cpu_off)
 ENTRY(psci_cpu_on)
+ENTRY(psci_affinity_info)
 ENTRY(psci_migrate)
+ENTRY(psci_migrate_info_type)
+ENTRY(psci_migrate_info_up_cpu)
+ENTRY(psci_system_off)
+ENTRY(psci_system_reset)
+ENTRY(psci_features)
+ENTRY(psci_cpu_freeze)
+ENTRY(psci_cpu_default_suspend)
+ENTRY(psci_node_hw_state)
+ENTRY(psci_system_suspend)
+ENTRY(psci_set_suspend_mode)
+ENTRY(psi_stat_residency)
+ENTRY(psci_stat_count)
 	mov	r0, #ARM_PSCI_RET_NI	@ Return -1 (Not Implemented)
 	mov	pc, lr
+ENDPROC(psci_stat_count)
+ENDPROC(psi_stat_residency)
+ENDPROC(psci_set_suspend_mode)
+ENDPROC(psci_system_suspend)
+ENDPROC(psci_node_hw_state)
+ENDPROC(psci_cpu_default_suspend)
+ENDPROC(psci_cpu_freeze)
+ENDPROC(psci_features)
+ENDPROC(psci_system_reset)
+ENDPROC(psci_system_off)
+ENDPROC(psci_migrate_info_up_cpu)
+ENDPROC(psci_migrate_info_type)
 ENDPROC(psci_migrate)
+ENDPROC(psci_affinity_info)
 ENDPROC(psci_cpu_on)
 ENDPROC(psci_cpu_off)
 ENDPROC(psci_cpu_suspend)
+ENDPROC(psci_version)
+.weak psci_version
 .weak psci_cpu_suspend
 .weak psci_cpu_off
 .weak psci_cpu_on
+.weak psci_affinity_info
 .weak psci_migrate
+.weak psci_migrate_info_type
+.weak psci_migrate_info_up_cpu
+.weak psci_system_off
+.weak psci_system_reset
+.weak psci_features
+.weak psci_cpu_freeze
+.weak psci_cpu_default_suspend
+.weak psci_node_hw_state
+.weak psci_system_suspend
+.weak psci_set_suspend_mode
+.weak psi_stat_residency
+.weak psci_stat_count
 
 _psci_table:
 	.word	ARM_PSCI_FN_CPU_SUSPEND
@@ -70,6 +112,42 @@
 	.word	psci_cpu_on
 	.word	ARM_PSCI_FN_MIGRATE
 	.word	psci_migrate
+	.word	ARM_PSCI_0_2_FN_PSCI_VERSION
+	.word	psci_version
+	.word	ARM_PSCI_0_2_FN_CPU_SUSPEND
+	.word	psci_cpu_suspend
+	.word	ARM_PSCI_0_2_FN_CPU_OFF
+	.word	psci_cpu_off
+	.word	ARM_PSCI_0_2_FN_CPU_ON
+	.word	psci_cpu_on
+	.word	ARM_PSCI_0_2_FN_AFFINITY_INFO
+	.word	psci_affinity_info
+	.word	ARM_PSCI_0_2_FN_MIGRATE
+	.word	psci_migrate
+	.word	ARM_PSCI_0_2_FN_MIGRATE_INFO_TYPE
+	.word	psci_migrate_info_type
+	.word	ARM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU
+	.word	psci_migrate_info_up_cpu
+	.word	ARM_PSCI_0_2_FN_SYSTEM_OFF
+	.word	psci_system_off
+	.word	ARM_PSCI_0_2_FN_SYSTEM_RESET
+	.word	psci_system_reset
+	.word	ARM_PSCI_1_0_FN_PSCI_FEATURES
+	.word	psci_features
+	.word	ARM_PSCI_1_0_FN_CPU_FREEZE
+	.word	psci_cpu_freeze
+	.word	ARM_PSCI_1_0_FN_CPU_DEFAULT_SUSPEND
+	.word	psci_cpu_default_suspend
+	.word	ARM_PSCI_1_0_FN_NODE_HW_STATE
+	.word	psci_node_hw_state
+	.word	ARM_PSCI_1_0_FN_SYSTEM_SUSPEND
+	.word	psci_system_suspend
+	.word	ARM_PSCI_1_0_FN_SET_SUSPEND_MODE
+	.word	psci_set_suspend_mode
+	.word	ARM_PSCI_1_0_FN_STAT_RESIDENCY
+	.word	psi_stat_residency
+	.word	ARM_PSCI_1_0_FN_STAT_COUNT
+	.word	psci_stat_count
 	.word	0
 	.word	0
 
@@ -196,29 +274,56 @@
 	bx	lr
 ENDPROC(psci_cpu_off_common)
 
-@ expects CPU ID in r0 and returns stack top in r0
-ENTRY(psci_get_cpu_stack_top)
-	mov	r3, #0x400			@ 1kB of stack per CPU
-	mul	r0, r0, r3
-
-	ldr	r3, =psci_text_end		@ end of monitor text
-	add	r3, r3, #0x2000			@ Skip two pages
-	lsr	r3, r3, #12			@ Align to start of page
-	lsl	r3, r3, #12
-	sub	r3, r3, #4			@ reserve 1 word for target PC
-	sub	r0, r3, r0			@ here's our stack!
-
+@ The stacks are allocated in reverse order, i.e.
+@ the stack for CPU0 has the highest memory address.
+@
+@ --------------------  __secure_stack_end
+@ |  CPU0 target PC  |
+@ |------------------|
+@ |                  |
+@ |    CPU0 stack    |
+@ |                  |
+@ |------------------|  __secure_stack_end - 1KB
+@ |        .         |
+@ |        .         |
+@ |        .         |
+@ |        .         |
+@ --------------------  __secure_stack_start
+@
+@ This expects CPU ID in r0 and returns stack top in r0
+LENTRY(psci_get_cpu_stack_top)
+	@ stack top = __secure_stack_end - (cpuid << ARM_PSCI_STACK_SHIFT)
+	ldr	r3, =__secure_stack_end
+	sub	r0, r3, r0, LSL #ARM_PSCI_STACK_SHIFT
+	sub	r0, r0, #4		@ Save space for target PC
 	bx	lr
 ENDPROC(psci_get_cpu_stack_top)
 
+@ {r0, r1, r2, ip} from _do_nonsec_entry(kernel_entry, 0, machid, r2) in
+@ arch/arm/lib/bootm.c:boot_jump_linux() must remain unchanged across
+@ this function.
+ENTRY(psci_stack_setup)
+	mov	r6, lr
+	mov	r7, r0
+	bl	psci_get_cpu_id		@ CPU ID => r0
+	bl	psci_get_cpu_stack_top	@ stack top => r0
+	mov	sp, r0
+	mov	r0, r7
+	bx	r6
+ENDPROC(psci_stack_setup)
+
+ENTRY(psci_arch_init)
+	mov	pc, lr
+ENDPROC(psci_arch_init)
+.weak psci_arch_init
+
 ENTRY(psci_cpu_entry)
 	bl	psci_enable_smp
 
 	bl	_nonsec_init
 
 	bl	psci_get_cpu_id			@ CPU ID => r0
-	bl	psci_get_cpu_stack_top		@ stack top => r0
-	ldr	r0, [r0]			@ target PC at stack top
+	bl	psci_get_target_pc		@ target PC => r0
 	b	_do_nonsec_entry
 ENDPROC(psci_cpu_entry)
 
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
index c208510..b35b9df 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -14,7 +14,6 @@
 
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_ARMV7_PSCI)	+= psci.o
-obj-$(CONFIG_ARMV7_PSCI)	+= psci_head.o
 endif
 
 ifdef CONFIG_SPL_BUILD
diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c
index a118e9d..766b8c7 100644
--- a/arch/arm/cpu/armv7/sunxi/psci.c
+++ b/arch/arm/cpu/armv7/sunxi/psci.c
@@ -17,11 +17,11 @@
 #include <asm/gic.h>
 #include <asm/io.h>
 #include <asm/psci.h>
+#include <asm/secure.h>
 #include <asm/system.h>
 
 #include <linux/bitops.h>
 
-#define __secure	__attribute__ ((section ("._secure.text")))
 #define __irq		__attribute__ ((interrupt ("IRQ")))
 
 #define	GICD_BASE	(SUNXI_GIC400_BASE + GIC_DIST_OFFSET)
@@ -53,16 +53,16 @@
 	u32 reg = ONE_MS * ms;
 
 	cp15_write_cntp_tval(reg);
-	ISB;
+	isb();
 	cp15_write_cntp_ctl(3);
 
 	do {
-		ISB;
+		isb();
 		reg = cp15_read_cntp_ctl();
 	} while (!(reg & BIT(2)));
 
 	cp15_write_cntp_ctl(0);
-	ISB;
+	isb();
 }
 
 static void __secure clamp_release(u32 __maybe_unused *clamp)
@@ -164,7 +164,7 @@
 static void __secure cp15_write_scr(u32 scr)
 {
 	asm volatile ("mcr p15, 0, %0, c1, c1, 0" : : "r" (scr));
-	ISB;
+	isb();
 }
 
 /*
@@ -190,7 +190,7 @@
 
 	/* End of interrupt */
 	writel(reg, GICC_BASE + GICC_EOIR);
-	DSB;
+	dsb();
 
 	/* Get CPU number */
 	cpu = (reg >> 10) & 0x7;
@@ -209,9 +209,8 @@
 		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
 	u32 cpu = (mpidr & 0x3);
 
-	/* store target PC at target CPU stack top */
-	writel(pc, psci_get_cpu_stack_top(cpu));
-	DSB;
+	/* store target PC */
+	psci_save_target_pc(cpu, pc);
 
 	/* Set secondary core power on PC */
 	writel((u32)&psci_cpu_entry, &cpucfg->priv0);
@@ -243,14 +242,14 @@
 
 	/* Ask CPU0 via SGI15 to pull the rug... */
 	writel(BIT(16) | 15, GICD_BASE + GICD_SGIR);
-	DSB;
+	dsb();
 
 	/* Wait to be turned off */
 	while (1)
 		wfi();
 }
 
-void __secure sunxi_gic_init(void)
+void __secure psci_arch_init(void)
 {
 	u32 reg;
 
diff --git a/arch/arm/cpu/armv7/sunxi/psci_head.S b/arch/arm/cpu/armv7/sunxi/psci_head.S
deleted file mode 100644
index 8fa823d..0000000
--- a/arch/arm/cpu/armv7/sunxi/psci_head.S
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2013 - ARM Ltd
- * Author: Marc Zyngier <marc.zyngier@arm.com>
- *
- * Based on code by Carl van Schaik <carl@ok-labs.com>.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include <linux/linkage.h>
-
-#include <asm/arch-armv7/generictimer.h>
-#include <asm/gic.h>
-#include <asm/macro.h>
-#include <asm/psci.h>
-#include <asm/arch/cpu.h>
-
-/*
- * Memory layout:
- *
- * SECURE_RAM to text_end :
- *	._secure_text section
- * text_end to ALIGN_PAGE(text_end):
- *	nothing
- * ALIGN_PAGE(text_end) to ALIGN_PAGE(text_end) + 0x1000)
- *	1kB of stack per CPU (4 CPUs max).
- */
-
-	.pushsection ._secure.text, "ax"
-
-	.arch_extension sec
-
-#define	GICD_BASE		(SUNXI_GIC400_BASE +  0x1000)
-#define	GICC_BASE		(SUNXI_GIC400_BASE +  0x2000)
-
-@ {r0, r1, r2, ip} from _do_nonsec_entry(kernel_entry, 0, machid, r2) in
-@ arch/arm/lib/bootm.c:boot_jump_linux() must remain unchanged across
-@ this function.
-ENTRY(psci_arch_init)
-	mov	r6, lr
-	mov	r7, r0
-	bl	psci_get_cpu_id		@ CPU ID => r0
-	bl	psci_get_cpu_stack_top	@ stack top => r0
-	sub	r0, r0, #4		@ Save space for target PC
-	mov	sp, r0
-	mov	r0, r7
-	mov	lr, r6
-
-	push	{r0, r1, r2, ip, lr}
-	bl	sunxi_gic_init
-	pop	{r0, r1, r2, ip, pc}
-ENDPROC(psci_arch_init)
-
-ENTRY(psci_text_end)
-	.popsection
diff --git a/arch/arm/cpu/armv7/virt-dt.c b/arch/arm/cpu/armv7/virt-dt.c
index 32c368f..707dad4 100644
--- a/arch/arm/cpu/armv7/virt-dt.c
+++ b/arch/arm/cpu/armv7/virt-dt.c
@@ -26,69 +26,6 @@
 #include <asm/armv7.h>
 #include <asm/psci.h>
 
-static int fdt_psci(void *fdt)
-{
-#ifdef CONFIG_ARMV7_PSCI
-	int nodeoff;
-	int tmp;
-
-	nodeoff = fdt_path_offset(fdt, "/cpus");
-	if (nodeoff < 0) {
-		printf("couldn't find /cpus\n");
-		return nodeoff;
-	}
-
-	/* add 'enable-method = "psci"' to each cpu node */
-	for (tmp = fdt_first_subnode(fdt, nodeoff);
-	     tmp >= 0;
-	     tmp = fdt_next_subnode(fdt, tmp)) {
-		const struct fdt_property *prop;
-		int len;
-
-		prop = fdt_get_property(fdt, tmp, "device_type", &len);
-		if (!prop)
-			continue;
-		if (len < 4)
-			continue;
-		if (strcmp(prop->data, "cpu"))
-			continue;
-
-		fdt_setprop_string(fdt, tmp, "enable-method", "psci");
-	}
-
-	nodeoff = fdt_path_offset(fdt, "/psci");
-	if (nodeoff < 0) {
-		nodeoff = fdt_path_offset(fdt, "/");
-		if (nodeoff < 0)
-			return nodeoff;
-
-		nodeoff = fdt_add_subnode(fdt, nodeoff, "psci");
-		if (nodeoff < 0)
-			return nodeoff;
-	}
-
-	tmp = fdt_setprop_string(fdt, nodeoff, "compatible", "arm,psci");
-	if (tmp)
-		return tmp;
-	tmp = fdt_setprop_string(fdt, nodeoff, "method", "smc");
-	if (tmp)
-		return tmp;
-	tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_suspend", ARM_PSCI_FN_CPU_SUSPEND);
-	if (tmp)
-		return tmp;
-	tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_off", ARM_PSCI_FN_CPU_OFF);
-	if (tmp)
-		return tmp;
-	tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_on", ARM_PSCI_FN_CPU_ON);
-	if (tmp)
-		return tmp;
-	tmp = fdt_setprop_u32(fdt, nodeoff, "migrate", ARM_PSCI_FN_MIGRATE);
-	if (tmp)
-		return tmp;
-#endif
-	return 0;
-}
-
 int armv7_apply_memory_carveout(u64 *start, u64 *size)
 {
 #ifdef CONFIG_ARMV7_SECURE_RESERVE_SIZE
diff --git a/arch/arm/cpu/armv7/virt-v7.c b/arch/arm/cpu/armv7/virt-v7.c
index 9c53306..d33e5c6 100644
--- a/arch/arm/cpu/armv7/virt-v7.c
+++ b/arch/arm/cpu/armv7/virt-v7.c
@@ -54,10 +54,12 @@
 {
 #ifdef CONFIG_ARMV7_SECURE_BASE
 	size_t sz = __secure_end - __secure_start;
+	unsigned long szflush = ALIGN(sz + 1, CONFIG_SYS_CACHELINE_SIZE);
 
 	memcpy((void *)CONFIG_ARMV7_SECURE_BASE, __secure_start, sz);
+
 	flush_dcache_range(CONFIG_ARMV7_SECURE_BASE,
-			   CONFIG_ARMV7_SECURE_BASE + sz + 1);
+			   CONFIG_ARMV7_SECURE_BASE + szflush);
 	protect_secure_section();
 	invalidate_icache_all();
 #endif
diff --git a/arch/arm/cpu/armv7m/config.mk b/arch/arm/cpu/armv7m/config.mk
index 4a53006..db4660e 100644
--- a/arch/arm/cpu/armv7m/config.mk
+++ b/arch/arm/cpu/armv7m/config.mk
@@ -5,4 +5,4 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-PLATFORM_CPPFLAGS += -march=armv7-m -mthumb
+PLATFORM_CPPFLAGS += -march=armv7-m -mthumb -mno-unaligned-access
diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig
index 3d19bbf..7e1fc4c 100644
--- a/arch/arm/cpu/armv8/Kconfig
+++ b/arch/arm/cpu/armv8/Kconfig
@@ -1,6 +1,24 @@
 if ARM64
 
 config ARMV8_MULTIENTRY
-        boolean "Enable multiple CPUs to enter into U-Boot"
+        bool "Enable multiple CPUs to enter into U-Boot"
+
+config ARMV8_SPIN_TABLE
+	bool "Support spin-table enable method"
+	depends on ARMV8_MULTIENTRY && OF_LIBFDT
+	help
+	  Say Y here to support "spin-table" enable method for booting Linux.
+
+	  To use this feature, you must do:
+	    - Specify enable-method = "spin-table" in each CPU node in the
+	      Device Tree you are using to boot the kernel
+	    - Let secondary CPUs in U-Boot (in a board specific manner)
+	      before the master CPU jumps to the kernel
+
+	  U-Boot automatically does:
+	    - Set "cpu-release-addr" property of each CPU node
+	      (overwrites it if already exists).
+	    - Reserve the code for the spin-table and the release address
+	      via a /memreserve/ region in the Device Tree.
 
 endif
diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile
index bf8644c..dea1465 100644
--- a/arch/arm/cpu/armv8/Makefile
+++ b/arch/arm/cpu/armv8/Makefile
@@ -15,6 +15,11 @@
 obj-y	+= tlb.o
 obj-y	+= transition.o
 obj-y	+= fwcall.o
+obj-y	+= cpu-dt.o
+ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_ARMV8_SPIN_TABLE) += spin_table.o spin_table_v8.o
+endif
+obj-$(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT) += sec_firmware.o sec_firmware_asm.o
 
 obj-$(CONFIG_FSL_LAYERSCAPE) += fsl-layerscape/
 obj-$(CONFIG_S32V234) += s32v234/
diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
index 1615542..cd3f6c1 100644
--- a/arch/arm/cpu/armv8/cache_v8.c
+++ b/arch/arm/cpu/armv8/cache_v8.c
@@ -35,7 +35,7 @@
  *    off:          FFF
  */
 
-static u64 get_tcr(int el, u64 *pips, u64 *pva_bits)
+u64 get_tcr(int el, u64 *pips, u64 *pva_bits)
 {
 	u64 max_addr = 0;
 	u64 ips, va_bits;
@@ -44,7 +44,7 @@
 
 	/* Find the largest address we need to support */
 	for (i = 0; mem_map[i].size || mem_map[i].attrs; i++)
-		max_addr = max(max_addr, mem_map[i].base + mem_map[i].size);
+		max_addr = max(max_addr, mem_map[i].virt + mem_map[i].size);
 
 	/* Calculate the maximum physical (and thus virtual) address */
 	if (max_addr > (1ULL << 44)) {
@@ -167,49 +167,6 @@
 	*pte = PTE_TYPE_TABLE | (ulong)table;
 }
 
-/* Add one mm_region map entry to the page tables */
-static void add_map(struct mm_region *map)
-{
-	u64 *pte;
-	u64 addr = map->base;
-	u64 size = map->size;
-	u64 attrs = map->attrs | PTE_TYPE_BLOCK | PTE_BLOCK_AF;
-	u64 blocksize;
-	int level;
-	u64 *new_table;
-
-	while (size) {
-		pte = find_pte(addr, 0);
-		if (pte && (pte_type(pte) == PTE_TYPE_FAULT)) {
-			debug("Creating table for addr 0x%llx\n", addr);
-			new_table = create_table();
-			set_pte_table(pte, new_table);
-		}
-
-		for (level = 1; level < 4; level++) {
-			pte = find_pte(addr, level);
-			blocksize = 1ULL << level2shift(level);
-			debug("Checking if pte fits for addr=%llx size=%llx "
-			      "blocksize=%llx\n", addr, size, blocksize);
-			if (size >= blocksize && !(addr & (blocksize - 1))) {
-				/* Page fits, create block PTE */
-				debug("Setting PTE %p to block addr=%llx\n",
-				      pte, addr);
-				*pte = addr | attrs;
-				addr += blocksize;
-				size -= blocksize;
-				break;
-			} else if ((pte_type(pte) == PTE_TYPE_FAULT)) {
-				/* Page doesn't fit, create subpages */
-				debug("Creating subtable for addr 0x%llx "
-				      "blksize=%llx\n", addr, blocksize);
-				new_table = create_table();
-				set_pte_table(pte, new_table);
-			}
-		}
-	}
-}
-
 /* Splits a block PTE into table with subpages spanning the old block */
 static void split_block(u64 *pte, int level)
 {
@@ -241,6 +198,58 @@
 	set_pte_table(pte, new_table);
 }
 
+/* Add one mm_region map entry to the page tables */
+static void add_map(struct mm_region *map)
+{
+	u64 *pte;
+	u64 virt = map->virt;
+	u64 phys = map->phys;
+	u64 size = map->size;
+	u64 attrs = map->attrs | PTE_TYPE_BLOCK | PTE_BLOCK_AF;
+	u64 blocksize;
+	int level;
+	u64 *new_table;
+
+	while (size) {
+		pte = find_pte(virt, 0);
+		if (pte && (pte_type(pte) == PTE_TYPE_FAULT)) {
+			debug("Creating table for virt 0x%llx\n", virt);
+			new_table = create_table();
+			set_pte_table(pte, new_table);
+		}
+
+		for (level = 1; level < 4; level++) {
+			pte = find_pte(virt, level);
+			if (!pte)
+				panic("pte not found\n");
+
+			blocksize = 1ULL << level2shift(level);
+			debug("Checking if pte fits for virt=%llx size=%llx blocksize=%llx\n",
+			      virt, size, blocksize);
+			if (size >= blocksize && !(virt & (blocksize - 1))) {
+				/* Page fits, create block PTE */
+				debug("Setting PTE %p to block virt=%llx\n",
+				      pte, virt);
+				*pte = phys | attrs;
+				virt += blocksize;
+				phys += blocksize;
+				size -= blocksize;
+				break;
+			} else if (pte_type(pte) == PTE_TYPE_FAULT) {
+				/* Page doesn't fit, create subpages */
+				debug("Creating subtable for virt 0x%llx blksize=%llx\n",
+				      virt, blocksize);
+				new_table = create_table();
+				set_pte_table(pte, new_table);
+			} else if (pte_type(pte) == PTE_TYPE_BLOCK) {
+				debug("Split block into subtable for virt 0x%llx blksize=0x%llx\n",
+				      virt, blocksize);
+				split_block(pte, level);
+			}
+		}
+	}
+}
+
 enum pte_type {
 	PTE_INVAL,
 	PTE_BLOCK,
@@ -265,7 +274,7 @@
 
 	for (i = 0; mem_map[i].size || mem_map[i].attrs; i++) {
 		struct mm_region *map = &mem_map[i];
-		u64 start = map->base;
+		u64 start = map->virt;
 		u64 end = start + map->size;
 
 		/* Check if the PTE would overlap with the map */
@@ -349,10 +358,13 @@
 	return size;
 }
 
-static void setup_pgtables(void)
+void setup_pgtables(void)
 {
 	int i;
 
+	if (!gd->arch.tlb_fillptr || !gd->arch.tlb_addr)
+		panic("Page table pointer not setup.");
+
 	/*
 	 * Allocate the first level we're on with invalidate entries.
 	 * If the starting level is 0 (va_bits >= 39), then this is our
@@ -363,14 +375,12 @@
 	/* Now add all MMU table entries one after another to the table */
 	for (i = 0; mem_map[i].size || mem_map[i].attrs; i++)
 		add_map(&mem_map[i]);
-
-	/* Create the same thing once more for our emergency page table */
-	create_table();
 }
 
 static void setup_all_pgtables(void)
 {
 	u64 tlb_addr = gd->arch.tlb_addr;
+	u64 tlb_size = gd->arch.tlb_size;
 
 	/* Reset the fill ptr */
 	gd->arch.tlb_fillptr = tlb_addr;
@@ -379,10 +389,13 @@
 	setup_pgtables();
 
 	/* Create emergency page tables */
+	gd->arch.tlb_size -= (uintptr_t)gd->arch.tlb_fillptr -
+			     (uintptr_t)gd->arch.tlb_addr;
 	gd->arch.tlb_addr = gd->arch.tlb_fillptr;
 	setup_pgtables();
 	gd->arch.tlb_emerg = gd->arch.tlb_addr;
 	gd->arch.tlb_addr = tlb_addr;
+	gd->arch.tlb_size = tlb_size;
 }
 
 /* to activate the MMU we need to set up virtual memory */
@@ -527,6 +540,9 @@
 
 	debug("start=%lx size=%lx\n", (ulong)start, (ulong)size);
 
+	if (!gd->arch.tlb_emerg)
+		panic("Emergency page table not setup.");
+
 	/*
 	 * We can not modify page tables that we're currently running on,
 	 * so we first need to switch to the "emergency" page tables where
diff --git a/arch/arm/cpu/armv8/cpu-dt.c b/arch/arm/cpu/armv8/cpu-dt.c
new file mode 100644
index 0000000..9ffb49c
--- /dev/null
+++ b/arch/arm/cpu/armv8/cpu-dt.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016 NXP Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/psci.h>
+#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
+#include <asm/armv8/sec_firmware.h>
+#endif
+
+int psci_update_dt(void *fdt)
+{
+#ifdef CONFIG_MP
+#if defined(CONFIG_ARMV8_PSCI)
+#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
+	/*
+	 * If the PSCI in SEC Firmware didn't work, avoid to update the
+	 * device node of PSCI. But still return 0 instead of an error
+	 * number to support detecting PSCI dynamically and then switching
+	 * the SMP boot method between PSCI and spin-table.
+	 */
+	if (sec_firmware_support_psci_version() == 0xffffffff)
+		return 0;
+#endif
+	fdt_psci(fdt);
+#endif
+#endif
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Makefile b/arch/arm/cpu/armv8/fsl-layerscape/Makefile
index eb2cbc3..8c1317f 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Makefile
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Makefile
@@ -10,6 +10,7 @@
 obj-$(CONFIG_MP) += mp.o
 obj-$(CONFIG_OF_LIBFDT) += fdt.o
 obj-$(CONFIG_SPL) += spl.o
+obj-$(CONFIG_FSL_LS_PPA) += ppa.o
 
 ifneq ($(CONFIG_FSL_LSCH3),)
 obj-y += fsl_lsch3_speed.o
@@ -32,3 +33,7 @@
 ifneq ($(CONFIG_LS1012A),)
 obj-$(CONFIG_SYS_HAS_SERDES) += ls1012a_serdes.o
 endif
+
+ifneq ($(CONFIG_LS1046A),)
+obj-$(CONFIG_SYS_HAS_SERDES) += ls1046a_serdes.o
+endif
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
index 8062106..e12b773 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
@@ -23,16 +23,13 @@
 #ifdef CONFIG_FSL_ESDHC
 #include <fsl_esdhc.h>
 #endif
+#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
+#include <asm/armv8/sec_firmware.h>
+#endif
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static struct mm_region layerscape_mem_map[] = {
-	{
-		/* List terminator */
-		0,
-	}
-};
-struct mm_region *mem_map = layerscape_mem_map;
+struct mm_region *mem_map = early_map;
 
 void cpu_name(char *name)
 {
@@ -56,355 +53,106 @@
 }
 
 #ifndef CONFIG_SYS_DCACHE_OFF
-static void set_pgtable_section(u64 *page_table, u64 index, u64 section,
-			u64 memory_type, u64 attribute)
-{
-       u64 value;
-
-       value = section | PTE_TYPE_BLOCK | PTE_BLOCK_AF;
-       value |= PMD_ATTRINDX(memory_type);
-       value |= attribute;
-       page_table[index] = value;
-}
-
-static void set_pgtable_table(u64 *page_table, u64 index, u64 *table_addr)
-{
-       u64 value;
-
-       value = (u64)table_addr | PTE_TYPE_TABLE;
-       page_table[index] = value;
-}
-
-/*
- * Set the block entries according to the information of the table.
- */
-static int set_block_entry(const struct sys_mmu_table *list,
-			   struct table_info *table)
-{
-	u64 block_size = 0, block_shift = 0;
-	u64 block_addr, index;
-	int j;
-
-	if (table->entry_size == BLOCK_SIZE_L1) {
-		block_size = BLOCK_SIZE_L1;
-		block_shift = SECTION_SHIFT_L1;
-	} else if (table->entry_size == BLOCK_SIZE_L2) {
-		block_size = BLOCK_SIZE_L2;
-		block_shift = SECTION_SHIFT_L2;
-	} else {
-		return -EINVAL;
-	}
-
-	block_addr = list->phys_addr;
-	index = (list->virt_addr - table->table_base) >> block_shift;
-
-	for (j = 0; j < (list->size >> block_shift); j++) {
-		set_pgtable_section(table->ptr,
-				    index,
-				    block_addr,
-				    list->memory_type,
-				    list->attribute);
-		block_addr += block_size;
-		index++;
-	}
-
-	return 0;
-}
-
-/*
- * Find the corresponding table entry for the list.
- */
-static int find_table(const struct sys_mmu_table *list,
-		      struct table_info *table, u64 *level0_table)
-{
-	u64 index = 0, level = 0;
-	u64 *level_table = level0_table;
-	u64 temp_base = 0, block_size = 0, block_shift = 0;
-
-	while (level < 3) {
-		if (level == 0) {
-			block_size = BLOCK_SIZE_L0;
-			block_shift = SECTION_SHIFT_L0;
-		} else if (level == 1) {
-			block_size = BLOCK_SIZE_L1;
-			block_shift = SECTION_SHIFT_L1;
-		} else if (level == 2) {
-			block_size = BLOCK_SIZE_L2;
-			block_shift = SECTION_SHIFT_L2;
-		}
-
-		index = 0;
-		while (list->virt_addr >= temp_base) {
-			index++;
-			temp_base += block_size;
-		}
-
-		temp_base -= block_size;
-
-		if ((level_table[index - 1] & PTE_TYPE_MASK) ==
-		    PTE_TYPE_TABLE) {
-			level_table = (u64 *)(level_table[index - 1] &
-				      ~PTE_TYPE_MASK);
-			level++;
-			continue;
-		} else {
-			if (level == 0)
-				return -EINVAL;
-
-			if ((list->phys_addr + list->size) >
-			    (temp_base + block_size * NUM_OF_ENTRY))
-				return -EINVAL;
-
-			/*
-			 * Check the address and size of the list member is
-			 * aligned with the block size.
-			 */
-			if (((list->phys_addr & (block_size - 1)) != 0) ||
-			    ((list->size & (block_size - 1)) != 0))
-				return -EINVAL;
-
-			table->ptr = level_table;
-			table->table_base = temp_base -
-					    ((index - 1) << block_shift);
-			table->entry_size = block_size;
-
-			return 0;
-		}
-	}
-	return -EINVAL;
-}
-
 /*
  * To start MMU before DDR is available, we create MMU table in SRAM.
  * The base address of SRAM is CONFIG_SYS_FSL_OCRAM_BASE. We use three
  * levels of translation tables here to cover 40-bit address space.
  * We use 4KB granule size, with 40 bits physical address, T0SZ=24
- * Level 0 IA[39], table address @0
- * Level 1 IA[38:30], table address @0x1000, 0x2000
- * Level 2 IA[29:21], table address @0x3000, 0x4000
- * Address above 0x5000 is free for other purpose.
+ * Address above EARLY_PGTABLE_SIZE (0x5000) is free for other purpose.
+ * Note, the debug print in cache_v8.c is not usable for debugging
+ * these early MMU tables because UART is not yet available.
  */
 static inline void early_mmu_setup(void)
 {
-	unsigned int el, i;
-	u64 *level0_table = (u64 *)CONFIG_SYS_FSL_OCRAM_BASE;
-	u64 *level1_table0 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x1000);
-	u64 *level1_table1 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x2000);
-	u64 *level2_table0 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x3000);
-	u64 *level2_table1 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x4000);
-
-	struct table_info table = {level0_table, 0, BLOCK_SIZE_L0};
+	unsigned int el = current_el();
 
-	/* Invalidate all table entries */
-	memset(level0_table, 0, 0x5000);
+	/* global data is already setup, no allocation yet */
+	gd->arch.tlb_addr = CONFIG_SYS_FSL_OCRAM_BASE;
+	gd->arch.tlb_fillptr = gd->arch.tlb_addr;
+	gd->arch.tlb_size = EARLY_PGTABLE_SIZE;
 
-	/* Fill in the table entries */
-	set_pgtable_table(level0_table, 0, level1_table0);
-	set_pgtable_table(level0_table, 1, level1_table1);
-	set_pgtable_table(level1_table0, 0, level2_table0);
+	/* Create early page tables */
+	setup_pgtables();
 
-#ifdef CONFIG_FSL_LSCH3
-	set_pgtable_table(level1_table0,
-			  CONFIG_SYS_FLASH_BASE >> SECTION_SHIFT_L1,
-			  level2_table1);
-#elif defined(CONFIG_FSL_LSCH2)
-	set_pgtable_table(level1_table0, 1, level2_table1);
-#endif
-	/* Find the table and fill in the block entries */
-	for (i = 0; i < ARRAY_SIZE(early_mmu_table); i++) {
-		if (find_table(&early_mmu_table[i],
-			       &table, level0_table) == 0) {
-			/*
-			 * If find_table() returns error, it cannot be dealt
-			 * with here. Breakpoint can be added for debugging.
-			 */
-			set_block_entry(&early_mmu_table[i], &table);
-			/*
-			 * If set_block_entry() returns error, it cannot be
-			 * dealt with here too.
-			 */
-		}
-	}
-
-	el = current_el();
-
-	set_ttbr_tcr_mair(el, (u64)level0_table, LAYERSCAPE_TCR,
+	/* point TTBR to the new table */
+	set_ttbr_tcr_mair(el, gd->arch.tlb_addr,
+			  get_tcr(el, NULL, NULL) &
+			  ~(TCR_ORGN_MASK | TCR_IRGN_MASK),
 			  MEMORY_ATTRIBUTES);
-	set_sctlr(get_sctlr() | CR_M);
-}
-
-#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
-/*
- * Called from final mmu setup. The phys_addr is new, non-existing
- * address. A new sub table is created @level2_table_secure to cover
- * size of CONFIG_SYS_MEM_RESERVE_SECURE memory.
- */
-static inline int final_secure_ddr(u64 *level0_table,
-				   u64 *level2_table_secure,
-				   phys_addr_t phys_addr)
-{
-	int ret = -EINVAL;
-	struct table_info table = {};
-	struct sys_mmu_table ddr_entry = {
-		0, 0, BLOCK_SIZE_L1, MT_NORMAL,
-		PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
-	};
-	u64 index;
-
-	/* Need to create a new table */
-	ddr_entry.virt_addr = phys_addr & ~(BLOCK_SIZE_L1 - 1);
-	ddr_entry.phys_addr = phys_addr & ~(BLOCK_SIZE_L1 - 1);
-	ret = find_table(&ddr_entry, &table, level0_table);
-	if (ret)
-		return ret;
-	index = (ddr_entry.virt_addr - table.table_base) >> SECTION_SHIFT_L1;
-	set_pgtable_table(table.ptr, index, level2_table_secure);
-	table.ptr = level2_table_secure;
-	table.table_base = ddr_entry.virt_addr;
-	table.entry_size = BLOCK_SIZE_L2;
-	ret = set_block_entry(&ddr_entry, &table);
-	if (ret) {
-		printf("MMU error: could not fill non-secure ddr block entries\n");
-		return ret;
-	}
-	ddr_entry.virt_addr = phys_addr;
-	ddr_entry.phys_addr = phys_addr;
-	ddr_entry.size = CONFIG_SYS_MEM_RESERVE_SECURE;
-	ddr_entry.attribute = PTE_BLOCK_OUTER_SHARE;
-	ret = find_table(&ddr_entry, &table, level0_table);
-	if (ret) {
-		printf("MMU error: could not find secure ddr table\n");
-		return ret;
-	}
-	ret = set_block_entry(&ddr_entry, &table);
-	if (ret)
-		printf("MMU error: could not set secure ddr block entry\n");
 
-	return ret;
+	set_sctlr(get_sctlr() | CR_M);
 }
-#endif
 
 /*
  * The final tables look similar to early tables, but different in detail.
  * These tables are in DRAM. Sub tables are added to enable cache for
  * QBMan and OCRAM.
  *
- * Put the MMU table in secure memory if gd->secure_ram is valid.
- * OCRAM will be not used for this purpose so gd->secure_ram can't be 0.
- *
- * Level 1 table 0 contains 512 entries for each 1GB from 0 to 512GB.
- * Level 1 table 1 contains 512 entries for each 1GB from 512GB to 1TB.
- * Level 2 table 0 contains 512 entries for each 2MB from 0 to 1GB.
- *
- * For LSCH3:
- * Level 2 table 1 contains 512 entries for each 2MB from 32GB to 33GB.
- * For LSCH2:
- * Level 2 table 1 contains 512 entries for each 2MB from 1GB to 2GB.
- * Level 2 table 2 contains 512 entries for each 2MB from 20GB to 21GB.
+ * Put the MMU table in secure memory if gd->arch.secure_ram is valid.
+ * OCRAM will be not used for this purpose so gd->arch.secure_ram can't be 0.
  */
 static inline void final_mmu_setup(void)
 {
+	u64 tlb_addr_save = gd->arch.tlb_addr;
 	unsigned int el = current_el();
-	unsigned int i;
-	u64 *level0_table = (u64 *)gd->arch.tlb_addr;
-	u64 *level1_table0;
-	u64 *level1_table1;
-	u64 *level2_table0;
-	u64 *level2_table1;
-#ifdef CONFIG_FSL_LSCH2
-	u64 *level2_table2;
-#endif
-	struct table_info table = {NULL, 0, BLOCK_SIZE_L0};
-
 #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
-	u64 *level2_table_secure;
-
-	if (el == 3) {
-		/*
-		 * Only use gd->secure_ram if the address is recalculated
-		 * Align to 4KB for MMU table
-		 */
-		if (gd->secure_ram & MEM_RESERVE_SECURE_MAINTAINED)
-			level0_table = (u64 *)(gd->secure_ram & ~0xfff);
-		else
-			printf("MMU warning: gd->secure_ram is not maintained, disabled.\n");
-	}
-#endif
-	level1_table0 = level0_table + 512;
-	level1_table1 = level1_table0 + 512;
-	level2_table0 = level1_table1 + 512;
-	level2_table1 = level2_table0 + 512;
-#ifdef CONFIG_FSL_LSCH2
-	level2_table2 = level2_table1 + 512;
-#endif
-	table.ptr = level0_table;
-
-	/* Invalidate all table entries */
-	memset(level0_table, 0, PGTABLE_SIZE);
-
-	/* Fill in the table entries */
-	set_pgtable_table(level0_table, 0, level1_table0);
-	set_pgtable_table(level0_table, 1, level1_table1);
-	set_pgtable_table(level1_table0, 0, level2_table0);
-#ifdef CONFIG_FSL_LSCH3
-	set_pgtable_table(level1_table0,
-			  CONFIG_SYS_FSL_QBMAN_BASE >> SECTION_SHIFT_L1,
-			  level2_table1);
-#elif defined(CONFIG_FSL_LSCH2)
-	set_pgtable_table(level1_table0, 1, level2_table1);
-	set_pgtable_table(level1_table0,
-			  CONFIG_SYS_FSL_QBMAN_BASE >> SECTION_SHIFT_L1,
-			  level2_table2);
+	int index;
 #endif
 
-	/* Find the table and fill in the block entries */
-	for (i = 0; i < ARRAY_SIZE(final_mmu_table); i++) {
-		if (find_table(&final_mmu_table[i],
-			       &table, level0_table) == 0) {
-			if (set_block_entry(&final_mmu_table[i],
-					    &table) != 0) {
-				printf("MMU error: could not set block entry for %p\n",
-				       &final_mmu_table[i]);
-			}
+	mem_map = final_map;
 
-		} else {
-			printf("MMU error: could not find the table for %p\n",
-			       &final_mmu_table[i]);
-		}
-	}
-	/* Set the secure memory to secure in MMU */
 #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
-	if (el == 3 && gd->secure_ram & MEM_RESERVE_SECURE_MAINTAINED) {
-#ifdef CONFIG_FSL_LSCH3
-		level2_table_secure = level2_table1 + 512;
-#elif defined(CONFIG_FSL_LSCH2)
-		level2_table_secure = level2_table2 + 512;
-#endif
-		if (!final_secure_ddr(level0_table,
-				      level2_table_secure,
-				      gd->secure_ram & ~0x3)) {
-			gd->secure_ram |= MEM_RESERVE_SECURE_SECURED;
-			debug("Now MMU table is in secured memory at 0x%llx\n",
-			      gd->secure_ram & ~0x3);
+	if (gd->arch.secure_ram & MEM_RESERVE_SECURE_MAINTAINED) {
+		if (el == 3) {
+			/*
+			 * Only use gd->arch.secure_ram if the address is
+			 * recalculated. Align to 4KB for MMU table.
+			 */
+			/* put page tables in secure ram */
+			index = ARRAY_SIZE(final_map) - 2;
+			gd->arch.tlb_addr = gd->arch.secure_ram & ~0xfff;
+			final_map[index].virt = gd->arch.secure_ram & ~0x3;
+			final_map[index].phys = final_map[index].virt;
+			final_map[index].size = CONFIG_SYS_MEM_RESERVE_SECURE;
+			final_map[index].attrs = PTE_BLOCK_OUTER_SHARE;
+			gd->arch.secure_ram |= MEM_RESERVE_SECURE_SECURED;
+			tlb_addr_save = gd->arch.tlb_addr;
 		} else {
-			printf("MMU warning: Failed to secure DDR\n");
+			/* Use allocated (board_f.c) memory for TLB */
+			tlb_addr_save = gd->arch.tlb_allocated;
+			gd->arch.tlb_addr = tlb_addr_save;
 		}
 	}
 #endif
 
+	/* Reset the fill ptr */
+	gd->arch.tlb_fillptr = tlb_addr_save;
+
+	/* Create normal system page tables */
+	setup_pgtables();
+
+	/* Create emergency page tables */
+	gd->arch.tlb_addr = gd->arch.tlb_fillptr;
+	gd->arch.tlb_emerg = gd->arch.tlb_addr;
+	setup_pgtables();
+	gd->arch.tlb_addr = tlb_addr_save;
+
 	/* flush new MMU table */
-	flush_dcache_range((ulong)level0_table,
-			   (ulong)level0_table + gd->arch.tlb_size);
+	flush_dcache_range(gd->arch.tlb_addr,
+			   gd->arch.tlb_addr + gd->arch.tlb_size);
 
 	/* point TTBR to the new table */
-	set_ttbr_tcr_mair(el, (u64)level0_table, LAYERSCAPE_TCR_FINAL,
+	set_ttbr_tcr_mair(el, gd->arch.tlb_addr, get_tcr(el, NULL, NULL),
 			  MEMORY_ATTRIBUTES);
 	/*
-	 * MMU is already enabled, just need to invalidate TLB to load the
+	 * EL3 MMU is already enabled, just need to invalidate TLB to load the
 	 * new table. The new table is compatible with the current table, if
 	 * MMU somehow walks through the new table before invalidation TLB,
 	 * it still works. So we don't need to turn off MMU here.
+	 * When EL2 MMU table is created by calling this function, MMU needs
+	 * to be enabled.
 	 */
+	set_sctlr(get_sctlr() | CR_M);
 }
 
 u64 get_page_table_size(void)
@@ -422,15 +170,21 @@
 	return 0;
 }
 
+void mmu_setup(void)
+{
+	final_mmu_setup();
+}
+
 /*
- * This function is called from lib/board.c.
- * It recreates MMU table in main memory. MMU and d-cache are enabled earlier.
- * There is no need to disable d-cache for this operation.
+ * This function is called from common/board_r.c.
+ * It recreates MMU table in main memory.
  */
 void enable_caches(void)
 {
-	final_mmu_setup();
+	mmu_setup();
 	__asm_invalidate_tlb_all();
+	icache_enable();
+	dcache_enable();
 }
 #endif
 
@@ -558,7 +312,8 @@
 		printf("CPU%d(%s):%-4s MHz  ", core,
 		       type == TY_ITYP_VER_A7 ? "A7 " :
 		       (type == TY_ITYP_VER_A53 ? "A53" :
-			(type == TY_ITYP_VER_A57 ? "A57" : "   ")),
+		       (type == TY_ITYP_VER_A57 ? "A57" :
+		       (type == TY_ITYP_VER_A72 ? "A72" : "   "))),
 		       strmhz(buf, sysinfo.freq_processor[core]));
 	}
 	printf("\n       Bus:      %-4s MHz  ",
@@ -616,6 +371,7 @@
 {
 #ifdef CONFIG_MP
 	int rv = 1;
+	u32 psci_ver = 0xffffffff;
 #endif
 
 #ifdef CONFIG_SYS_FSL_ERRATUM_A009635
@@ -623,9 +379,15 @@
 #endif
 
 #ifdef CONFIG_MP
-	rv = fsl_layerscape_wake_seconday_cores();
-	if (rv)
-		printf("Did not wake secondary cores\n");
+#if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT) && defined(CONFIG_ARMV8_PSCI)
+	/* Check the psci version to determine if the psci is supported */
+	psci_ver = sec_firmware_support_psci_version();
+#endif
+	if (psci_ver == 0xffffffff) {
+		rv = fsl_layerscape_wake_seconday_cores();
+		if (rv)
+			printf("Did not wake secondary cores\n");
+	}
 #endif
 
 #ifdef CONFIG_SYS_HAS_SERDES
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3 b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3
index da5e052..7867c37 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3
+++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3
@@ -128,7 +128,7 @@
 		during U-boot booting.However the MC, DPC and DPL can be applied from
 		console independently.
 		The variable needs to be set from the console once and then on
-		rebooting the parameters set in the varible will automatically be
+		rebooting the parameters set in the variable will automatically be
 		executed. The commmand is demostrated taking an example of mc boot
 		using NOR Flash i.e. MC, DPL, and DPC is stored in the NOR flash:
 
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc
index 8eee016..f7b949a 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc
+++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc
@@ -3,6 +3,7 @@
 	1. LS1043A
 	2. LS2080A
 	3. LS1012A
+	4. LS1046A
 
 LS1043A
 ---------
@@ -127,3 +128,44 @@
     - Two WatchDog timers
     - ARM generic timer
  - QorIQ platform's trust architecture 2.1
+
+LS1046A
+--------
+The LS1046A integrated multicore processor combines four ARM Cortex-A72
+processor cores with datapath acceleration optimized for L2/3 packet
+processing, single pass security offload and robust traffic management
+and quality of service.
+
+The LS1046A SoC includes the following function and features:
+ - Four 64-bit ARM Cortex-A72 CPUs
+ - 2 MB unified L2 Cache
+ - One 64-bit DDR4 SDRAM memory controllers with ECC and interleaving
+   support
+ - Data Path Acceleration Architecture (DPAA) incorporating acceleration the
+   the following functions:
+   - Packet parsing, classification, and distribution (FMan)
+   - Queue management for scheduling, packet sequencing, and congestion
+     management (QMan)
+   - Hardware buffer management for buffer allocation and de-allocation (BMan)
+   - Cryptography acceleration (SEC)
+ - Two Configurable x4 SerDes
+   - Two PLLs per four-lane SerDes
+   - Support for 10G operation
+ - Ethernet interfaces by FMan
+   - Up to 2 x XFI supporting 10G interface (MAC 9, 10)
+   - Up to 1 x QSGMII (MAC 5, 6, 10, 1)
+   - Up to 4 x SGMII supporting 1000Mbps (MAC 5, 6, 9, 10)
+   - Up to 3 x SGMII supporting 2500Mbps (MAC 5, 9, 10)
+   - Up to 2 x RGMII supporting 1000Mbps (MAC 3, 4)
+ - High-speed peripheral interfaces
+   - Three PCIe 3.0 controllers, one supporting x4 operation
+   - One serial ATA (SATA 3.0) controllers
+ - Additional peripheral interfaces
+   - Three high-speed USB 3.0 controllers with integrated PHY
+   - Enhanced secure digital host controller (eSDXC/eMMC)
+   - Quad Serial Peripheral Interface (QSPI) Controller
+   - Serial peripheral interface (SPI) controller
+   - Four I2C controllers
+   - Two DUARTs
+   - Integrated flash controller (IFC) supporting NAND and NOR flash
+ - QorIQ platform's trust architecture 2.1
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
index d17227a..40d6a76 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
@@ -22,6 +22,9 @@
 #endif
 #include <fsl_sec.h>
 #include <asm/arch-fsl-layerscape/soc.h>
+#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
+#include <asm/armv8/sec_firmware.h>
+#endif
 
 int fdt_fixup_phy_connection(void *blob, int offset, phy_interface_t phyc)
 {
@@ -38,7 +41,37 @@
 	int addr_cells;
 	u64 val, core_id;
 	size_t *boot_code_size = &(__secondary_boot_code_size);
+#if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT) && defined(CONFIG_ARMV8_PSCI)
+	int node;
+	u32 psci_ver;
+
+	/* Check the psci version to determine if the psci is supported */
+	psci_ver = sec_firmware_support_psci_version();
+	if (psci_ver == 0xffffffff) {
+		/* remove psci DT node */
+		node = fdt_path_offset(blob, "/psci");
+		if (node >= 0)
+			goto remove_psci_node;
+
+		node = fdt_node_offset_by_compatible(blob, -1, "arm,psci");
+		if (node >= 0)
+			goto remove_psci_node;
+
+		node = fdt_node_offset_by_compatible(blob, -1, "arm,psci-0.2");
+		if (node >= 0)
+			goto remove_psci_node;
+
+		node = fdt_node_offset_by_compatible(blob, -1, "arm,psci-1.0");
+		if (node >= 0)
+			goto remove_psci_node;
 
+remove_psci_node:
+		if (node >= 0)
+			fdt_del_node(blob, node);
+	} else {
+		return;
+	}
+#endif
 	off = fdt_path_offset(blob, "/cpus");
 	if (off < 0) {
 		puts("couldn't find /cpus node\n");
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c
index fe3444a..f73092a 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c
@@ -13,6 +13,9 @@
 #ifdef CONFIG_SYS_FSL_SRDS_1
 static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT];
 #endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT];
+#endif
 
 int is_serdes_configured(enum srds_prtcl device)
 {
@@ -21,6 +24,9 @@
 #ifdef CONFIG_SYS_FSL_SRDS_1
 	ret |= serdes1_prtcl_map[device];
 #endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	ret |= serdes2_prtcl_map[device];
+#endif
 
 	return !!ret;
 }
@@ -38,6 +44,12 @@
 		cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
 		break;
 #endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	case FSL_SRDS_2:
+		cfg &= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
+		cfg >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
+		break;
+#endif
 	default:
 		printf("invalid SerDes%d\n", sd);
 		break;
@@ -114,4 +126,11 @@
 		    FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT,
 		    serdes1_prtcl_map);
 #endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	serdes_init(FSL_SRDS_2,
+		    CONFIG_SYS_FSL_SERDES_ADDR,
+		    FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK,
+		    FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT,
+		    serdes2_prtcl_map);
+#endif
 }
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c
index d0dc58d..8922197 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c
@@ -107,6 +107,12 @@
 	case 3:
 		sys_info->freq_fman[0] = freq_c_pll[0] / 3;
 		break;
+	case 4:
+		sys_info->freq_fman[0] = freq_c_pll[0] / 4;
+		break;
+	case 5:
+		sys_info->freq_fman[0] = sys_info->freq_systembus;
+		break;
 	case 6:
 		sys_info->freq_fman[0] = freq_c_pll[1] / 2;
 		break;
@@ -124,8 +130,23 @@
 #ifdef CONFIG_FSL_ESDHC
 #ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
 	rcw_tmp = in_be32(&gur->rcwsr[15]);
-	rcw_tmp = (rcw_tmp & HWA_CGA_M2_CLK_SEL) >> HWA_CGA_M2_CLK_SHIFT;
-	sys_info->freq_sdhc = freq_c_pll[1] / rcw_tmp;
+	switch ((rcw_tmp & HWA_CGA_M2_CLK_SEL) >> HWA_CGA_M2_CLK_SHIFT) {
+	case 1:
+		sys_info->freq_sdhc = freq_c_pll[1];
+		break;
+	case 2:
+		sys_info->freq_sdhc = freq_c_pll[1] / 2;
+		break;
+	case 3:
+		sys_info->freq_sdhc = freq_c_pll[1] / 3;
+		break;
+	case 6:
+		sys_info->freq_sdhc = freq_c_pll[0] / 2;
+		break;
+	default:
+		printf("Error: Unknown ESDHC clock select!\n");
+		break;
+	}
 #else
 	sys_info->freq_sdhc = sys_info->freq_systembus;
 #endif
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1046a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/ls1046a_serdes.c
new file mode 100644
index 0000000..1da6b71
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1046a_serdes.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/immap_lsch2.h>
+
+struct serdes_config {
+	u32 protocol;
+	u8 lanes[SRDS_MAX_LANES];
+};
+
+static struct serdes_config serdes1_cfg_tbl[] = {
+	/* SerDes 1 */
+	{0x3333, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC10, SGMII_FM1_DTSEC5,
+		  SGMII_FM1_DTSEC6} },
+	{0x1133, {XFI_FM1_MAC9, XFI_FM1_MAC10, SGMII_FM1_DTSEC5,
+		  SGMII_FM1_DTSEC6} },
+	{0x1333, {XFI_FM1_MAC9, SGMII_FM1_DTSEC10, SGMII_FM1_DTSEC5,
+		  SGMII_FM1_DTSEC6} },
+	{0x2333, {SGMII_2500_FM1_DTSEC9, SGMII_FM1_DTSEC10, SGMII_FM1_DTSEC5,
+		  SGMII_FM1_DTSEC6} },
+	{0x2233, {SGMII_2500_FM1_DTSEC9, SGMII_2500_FM1_DTSEC10,
+		  SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6} },
+	{0x1040, {XFI_FM1_MAC9, NONE, QSGMII_FM1_A, NONE} },
+	{0x2040, {SGMII_2500_FM1_DTSEC9, NONE, QSGMII_FM1_A, NONE} },
+	{0x1163, {XFI_FM1_MAC9, XFI_FM1_MAC10, PCIE1, SGMII_FM1_DTSEC6} },
+	{0x2263, {SGMII_2500_FM1_DTSEC9, SGMII_2500_FM1_DTSEC10, PCIE1,
+		  SGMII_FM1_DTSEC6} },
+	{0x3363, {SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6, PCIE1,
+		  SGMII_FM1_DTSEC6} },
+	{0x2223, {SGMII_2500_FM1_DTSEC9, SGMII_2500_FM1_DTSEC10,
+		  SGMII_2500_FM1_DTSEC5, SGMII_FM1_DTSEC6} },
+	{}
+};
+
+static struct serdes_config serdes2_cfg_tbl[] = {
+	/* SerDes 2 */
+	{0x8888, {PCIE1, PCIE1, PCIE1, PCIE1} },
+	{0x5559, {PCIE1, PCIE2, PCIE3, SATA1} },
+	{0x5577, {PCIE1, PCIE2, PCIE3, PCIE3} },
+	{0x5506, {PCIE1, PCIE2, NONE, PCIE3} },
+	{0x0506, {NONE, PCIE2, NONE, PCIE3} },
+	{0x0559, {NONE, PCIE2, PCIE3, SATA1} },
+	{0x5A59, {PCIE1, SGMII_FM1_DTSEC2, PCIE3, SATA1} },
+	{0x5A06, {PCIE1, SGMII_FM1_DTSEC2, NONE, PCIE3} },
+	{}
+};
+
+static struct serdes_config *serdes_cfg_tbl[] = {
+	serdes1_cfg_tbl,
+	serdes2_cfg_tbl,
+};
+
+enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane)
+{
+	struct serdes_config *ptr;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+	while (ptr->protocol) {
+		if (ptr->protocol == cfg)
+			return ptr->lanes[lane];
+		ptr++;
+	}
+
+	return 0;
+}
+
+int is_serdes_prtcl_valid(int serdes, u32 prtcl)
+{
+	int i;
+	struct serdes_config *ptr;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+	while (ptr->protocol) {
+		if (ptr->protocol == prtcl)
+			break;
+		ptr++;
+	}
+
+	if (!ptr->protocol)
+		return 0;
+
+	for (i = 0; i < SRDS_MAX_LANES; i++) {
+		if (ptr->lanes[i] != NONE)
+			return 1;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ppa.c b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c
new file mode 100644
index 0000000..f54ac3f
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016 NXP Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+#include <config.h>
+#include <errno.h>
+#include <asm/system.h>
+#include <asm/types.h>
+#include <asm/arch/soc.h>
+#ifdef CONFIG_FSL_LSCH3
+#include <asm/arch/immap_lsch3.h>
+#elif defined(CONFIG_FSL_LSCH2)
+#include <asm/arch/immap_lsch2.h>
+#endif
+#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
+#include <asm/armv8/sec_firmware.h>
+#endif
+
+int ppa_init(void)
+{
+	const void *ppa_fit_addr;
+	u32 *boot_loc_ptr_l, *boot_loc_ptr_h;
+	int ret;
+
+#ifdef CONFIG_SYS_LS_PPA_FW_IN_XIP
+	ppa_fit_addr = (void *)CONFIG_SYS_LS_PPA_FW_ADDR;
+#else
+#error "No CONFIG_SYS_LS_PPA_FW_IN_xxx defined"
+#endif
+
+#ifdef CONFIG_FSL_LSCH3
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	boot_loc_ptr_l = &gur->bootlocptrl;
+	boot_loc_ptr_h = &gur->bootlocptrh;
+#elif defined(CONFIG_FSL_LSCH2)
+	struct ccsr_scfg __iomem *scfg = (void *)(CONFIG_SYS_FSL_SCFG_ADDR);
+	boot_loc_ptr_l = &scfg->scratchrw[1];
+	boot_loc_ptr_h = &scfg->scratchrw[0];
+#endif
+
+	debug("fsl-ppa: boot_loc_ptr_l = 0x%p, boot_loc_ptr_h =0x%p\n",
+	      boot_loc_ptr_l, boot_loc_ptr_h);
+	ret = sec_firmware_init(ppa_fit_addr, boot_loc_ptr_l, boot_loc_ptr_h);
+
+	return ret;
+}
diff --git a/arch/arm/cpu/armv8/s32v234/cpu.c b/arch/arm/cpu/armv8/s32v234/cpu.c
index dac12a2..5c97e0e 100644
--- a/arch/arm/cpu/armv8/s32v234/cpu.c
+++ b/arch/arm/cpu/armv8/s32v234/cpu.c
@@ -32,24 +32,28 @@
 
 static struct mm_region s32v234_mem_map[] = {
 	{
-		.base = S32V234_IRAM_BASE,
+		.virt = S32V234_IRAM_BASE,
+		.phys = S32V234_IRAM_BASE,
 		.size = S32V234_IRAM_SIZE,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_OUTER_SHARE
 	}, {
-		.base = S32V234_DRAM_BASE1,
+		.virt = S32V234_DRAM_BASE1,
+		.phys = S32V234_DRAM_BASE1,
 		.size = S32V234_DRAM_SIZE1,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_OUTER_SHARE
 	}, {
-		.base = S32V234_PERIPH_BASE,
+		.virt = S32V234_PERIPH_BASE,
+		.phys = S32V234_PERIPH_BASE,
 		.size = S32V234_PERIPH_SIZE,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE
 			 /* TODO: Do we need these? */
 			 /* | PTE_BLOCK_PXN | PTE_BLOCK_UXN */
 	}, {
-		.base = S32V234_DRAM_BASE2,
+		.virt = S32V234_DRAM_BASE2,
+		.phys = S32V234_DRAM_BASE2,
 		.size = S32V234_DRAM_SIZE2,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) |
 			 PTE_BLOCK_OUTER_SHARE
diff --git a/arch/arm/cpu/armv8/sec_firmware.c b/arch/arm/cpu/armv8/sec_firmware.c
new file mode 100644
index 0000000..e21e199
--- /dev/null
+++ b/arch/arm/cpu/armv8/sec_firmware.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2016 NXP Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/types.h>
+#include <asm/macro.h>
+#include <asm/armv8/sec_firmware.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+extern void c_runtime_cpu_setup(void);
+
+#define SEC_FIRMWARE_LOADED	0x1
+#define SEC_FIRMWARE_RUNNING	0x2
+#define SEC_FIRMWARE_ADDR_MASK	(~0x3)
+	/*
+	 * Secure firmware load addr
+	 * Flags used: 0x1 secure firmware has been loaded to secure memory
+	 *             0x2 secure firmware is running
+	 */
+	phys_addr_t sec_firmware_addr;
+
+static int sec_firmware_get_data(const void *sec_firmware_img,
+				const void **data, size_t *size)
+{
+	int conf_node_off, fw_node_off;
+	char *conf_node_name = NULL;
+	char *desc;
+	int ret;
+
+	conf_node_name = SEC_FIRMEWARE_FIT_CNF_NAME;
+
+	conf_node_off = fit_conf_get_node(sec_firmware_img, conf_node_name);
+	if (conf_node_off < 0) {
+		printf("SEC Firmware: %s: no such config\n", conf_node_name);
+		return -ENOENT;
+	}
+
+	fw_node_off = fit_conf_get_prop_node(sec_firmware_img, conf_node_off,
+			SEC_FIRMWARE_FIT_IMAGE);
+	if (fw_node_off < 0) {
+		printf("SEC Firmware: No '%s' in config\n",
+		       SEC_FIRMWARE_FIT_IMAGE);
+		return -ENOLINK;
+	}
+
+	/* Verify secure firmware image */
+	if (!(fit_image_verify(sec_firmware_img, fw_node_off))) {
+		printf("SEC Firmware: Bad firmware image (bad CRC)\n");
+		return -EINVAL;
+	}
+
+	if (fit_image_get_data(sec_firmware_img, fw_node_off, data, size)) {
+		printf("SEC Firmware: Can't get %s subimage data/size",
+		       SEC_FIRMWARE_FIT_IMAGE);
+		return -ENOENT;
+	}
+
+	ret = fit_get_desc(sec_firmware_img, fw_node_off, &desc);
+	if (ret)
+		printf("SEC Firmware: Can't get description\n");
+	else
+		printf("%s\n", desc);
+
+	return ret;
+}
+
+/*
+ * SEC Firmware FIT image parser checks if the image is in FIT
+ * format, verifies integrity of the image and calculates raw
+ * image address and size values.
+ *
+ * Returns 0 on success and a negative errno on error task fail.
+ */
+static int sec_firmware_parse_image(const void *sec_firmware_img,
+					const void **raw_image_addr,
+					size_t *raw_image_size)
+{
+	int ret;
+
+	ret = sec_firmware_get_data(sec_firmware_img, raw_image_addr,
+					raw_image_size);
+	if (ret)
+		return ret;
+
+	debug("SEC Firmware: raw_image_addr = 0x%p, raw_image_size = 0x%lx\n",
+	      *raw_image_addr, *raw_image_size);
+
+	return 0;
+}
+
+static int sec_firmware_copy_image(const char *title,
+			 u64 image_addr, u32 image_size, u64 sec_firmware)
+{
+	debug("%s copied to address 0x%p\n", title, (void *)sec_firmware);
+	memcpy((void *)sec_firmware, (void *)image_addr, image_size);
+	flush_dcache_range(sec_firmware, sec_firmware + image_size);
+
+	return 0;
+}
+
+/*
+ * This function will parse the SEC Firmware image, and then load it
+ * to secure memory.
+ */
+static int sec_firmware_load_image(const void *sec_firmware_img)
+{
+	const void *raw_image_addr;
+	size_t raw_image_size = 0;
+	int ret;
+
+	/*
+	 * The Excetpion Level must be EL3 to load and initialize
+	 * the SEC Firmware.
+	 */
+	if (current_el() != 3) {
+		ret = -EACCES;
+		goto out;
+	}
+
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+	/*
+	 * The SEC Firmware must be stored in secure memory.
+	 * Append SEC Firmware to secure mmu table.
+	 */
+	if (!(gd->arch.secure_ram & MEM_RESERVE_SECURE_MAINTAINED)) {
+		ret = -ENXIO;
+		goto out;
+	}
+
+	sec_firmware_addr = (gd->arch.secure_ram & MEM_RESERVE_SECURE_ADDR_MASK) +
+			gd->arch.tlb_size;
+#else
+#error "The CONFIG_SYS_MEM_RESERVE_SECURE must be defined when enabled SEC Firmware support"
+#endif
+
+	/* Align SEC Firmware base address to 4K */
+	sec_firmware_addr = (sec_firmware_addr + 0xfff) & ~0xfff;
+	debug("SEC Firmware: Load address: 0x%llx\n",
+	      sec_firmware_addr & SEC_FIRMWARE_ADDR_MASK);
+
+	ret = sec_firmware_parse_image(sec_firmware_img, &raw_image_addr,
+			&raw_image_size);
+	if (ret)
+		goto out;
+
+	/* TODO:
+	 * Check if the end addr of SEC Firmware has been extend the secure
+	 * memory.
+	 */
+
+	/* Copy the secure firmware to secure memory */
+	ret = sec_firmware_copy_image("SEC Firmware", (u64)raw_image_addr,
+			raw_image_size, sec_firmware_addr &
+			SEC_FIRMWARE_ADDR_MASK);
+	if (ret)
+		goto out;
+
+	sec_firmware_addr |= SEC_FIRMWARE_LOADED;
+	debug("SEC Firmware: Entry point: 0x%llx\n",
+	      sec_firmware_addr & SEC_FIRMWARE_ADDR_MASK);
+
+	return 0;
+
+out:
+	printf("SEC Firmware: error (%d)\n", ret);
+	sec_firmware_addr = 0;
+
+	return ret;
+}
+
+static int sec_firmware_entry(u32 *eret_hold_l, u32 *eret_hold_h)
+{
+	const void *entry = (void *)(sec_firmware_addr &
+				SEC_FIRMWARE_ADDR_MASK);
+
+	return _sec_firmware_entry(entry, eret_hold_l, eret_hold_h);
+}
+
+/* Check the secure firmware FIT image */
+__weak bool sec_firmware_is_valid(const void *sec_firmware_img)
+{
+	if (fdt_check_header(sec_firmware_img)) {
+		printf("SEC Firmware: Bad firmware image (not a FIT image)\n");
+		return false;
+	}
+
+	if (!fit_check_format(sec_firmware_img)) {
+		printf("SEC Firmware: Bad firmware image (bad FIT header)\n");
+		return false;
+	}
+
+	return true;
+}
+
+#ifdef CONFIG_ARMV8_PSCI
+/*
+ * The PSCI_VERSION function is added from PSCI v0.2. When the PSCI
+ * v0.1 received this function, the NOT_SUPPORTED (0xffff_ffff) error
+ * number will be returned according to SMC Calling Conventions. But
+ * when getting the NOT_SUPPORTED error number, we cannot ensure if
+ * the PSCI version is v0.1 or other error occurred. So, PSCI v0.1
+ * won't be supported by this framework.
+ * And if the secure firmware isn't running, return NOT_SUPPORTED.
+ *
+ * The return value on success is PSCI version in format
+ * major[31:16]:minor[15:0].
+ */
+unsigned int sec_firmware_support_psci_version(void)
+{
+	if (sec_firmware_addr & SEC_FIRMWARE_RUNNING)
+		return _sec_firmware_support_psci_version();
+
+	return 0xffffffff;
+}
+#endif
+
+/*
+ * sec_firmware_init - Initialize the SEC Firmware
+ * @sec_firmware_img:	the SEC Firmware image address
+ * @eret_hold_l:	the address to hold exception return address low
+ * @eret_hold_h:	the address to hold exception return address high
+ */
+int sec_firmware_init(const void *sec_firmware_img,
+			u32 *eret_hold_l,
+			u32 *eret_hold_h)
+{
+	int ret;
+
+	if (!sec_firmware_is_valid(sec_firmware_img))
+		return -EINVAL;
+
+	ret = sec_firmware_load_image(sec_firmware_img);
+	if (ret) {
+		printf("SEC Firmware: Failed to load image\n");
+		return ret;
+	} else if (sec_firmware_addr & SEC_FIRMWARE_LOADED) {
+		ret = sec_firmware_entry(eret_hold_l, eret_hold_h);
+		if (ret) {
+			printf("SEC Firmware: Failed to initialize\n");
+			return ret;
+		}
+	}
+
+	debug("SEC Firmware: Return from SEC Firmware: current_el = %d\n",
+	      current_el());
+
+	/*
+	 * The PE will be turned into target EL when returned from
+	 * SEC Firmware.
+	 */
+	if (current_el() != SEC_FIRMWARE_TARGET_EL)
+		return -EACCES;
+
+	sec_firmware_addr |= SEC_FIRMWARE_RUNNING;
+
+	/* Set exception table and enable caches if it isn't EL3 */
+	if (current_el() != 3) {
+		c_runtime_cpu_setup();
+		enable_caches();
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/sec_firmware_asm.S b/arch/arm/cpu/armv8/sec_firmware_asm.S
new file mode 100644
index 0000000..0c6a462
--- /dev/null
+++ b/arch/arm/cpu/armv8/sec_firmware_asm.S
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016 NXP Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+#include <asm/system.h>
+#include <asm/macro.h>
+
+WEAK(_sec_firmware_entry)
+	/*
+	 * x0: Secure Firmware entry point
+	 * x1: Exception return address Low
+	 * x2: Exception return address High
+	 */
+
+	/* Save stack pointer for EL2 */
+	mov	x3, sp
+	msr	sp_el2, x3
+
+	/* Set exception return address hold pointer */
+        adr	x4, 1f
+        mov	x3, x4
+#ifdef SEC_FIRMWARE_ERET_ADDR_REVERT
+        rev	w3, w3
+#endif
+        str	w3, [x1]
+        lsr	x3, x4, #32
+#ifdef SEC_FIRMWARE_ERET_ADDR_REVERT
+        rev	w3, w3
+#endif
+        str	w3, [x2]
+
+	/* Call SEC monitor */
+        br	x0
+
+1:
+        mov	x0, #0
+        ret
+ENDPROC(_sec_firmware_entry)
+
+#ifdef CONFIG_ARMV8_PSCI
+ENTRY(_sec_firmware_support_psci_version)
+	mov	x0, 0x84000000
+	mov	x1, 0x0
+	mov	x2, 0x0
+	mov	x3, 0x0
+	smc	#0
+	ret
+ENDPROC(_sec_firmware_support_psci_version)
+#endif
diff --git a/arch/arm/cpu/armv8/spin_table.c b/arch/arm/cpu/armv8/spin_table.c
new file mode 100644
index 0000000..ec1c9b8
--- /dev/null
+++ b/arch/arm/cpu/armv8/spin_table.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <asm/spin_table.h>
+
+int spin_table_update_dt(void *fdt)
+{
+	int cpus_offset, offset;
+	const char *prop;
+	int ret;
+	unsigned long rsv_addr = (unsigned long)&spin_table_reserve_begin;
+	unsigned long rsv_size = &spin_table_reserve_end -
+						&spin_table_reserve_begin;
+
+	cpus_offset = fdt_path_offset(fdt, "/cpus");
+	if (cpus_offset < 0)
+		return -ENODEV;
+
+	for (offset = fdt_first_subnode(fdt, cpus_offset);
+	     offset >= 0;
+	     offset = fdt_next_subnode(fdt, offset)) {
+		prop = fdt_getprop(fdt, offset, "device_type", NULL);
+		if (!prop || strcmp(prop, "cpu"))
+			continue;
+
+		/*
+		 * In the first loop, we check if every CPU node specifies
+		 * spin-table.  Otherwise, just return successfully to not
+		 * disturb other methods, like psci.
+		 */
+		prop = fdt_getprop(fdt, offset, "enable-method", NULL);
+		if (!prop || strcmp(prop, "spin-table"))
+			return 0;
+	}
+
+	for (offset = fdt_first_subnode(fdt, cpus_offset);
+	     offset >= 0;
+	     offset = fdt_next_subnode(fdt, offset)) {
+		prop = fdt_getprop(fdt, offset, "device_type", NULL);
+		if (!prop || strcmp(prop, "cpu"))
+			continue;
+
+		ret = fdt_setprop_u64(fdt, offset, "cpu-release-addr",
+				(unsigned long)&spin_table_cpu_release_addr);
+		if (ret)
+			return -ENOSPC;
+	}
+
+	ret = fdt_add_mem_rsv(fdt, rsv_addr, rsv_size);
+	if (ret)
+		return -ENOSPC;
+
+	printf("   Reserved memory region for spin-table: addr=%lx size=%lx\n",
+	       rsv_addr, rsv_size);
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/spin_table_v8.S b/arch/arm/cpu/armv8/spin_table_v8.S
new file mode 100644
index 0000000..d7f78a6
--- /dev/null
+++ b/arch/arm/cpu/armv8/spin_table_v8.S
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <linux/linkage.h>
+
+ENTRY(spin_table_secondary_jump)
+.globl spin_table_reserve_begin
+spin_table_reserve_begin:
+0:	wfe
+	ldr	x0, spin_table_cpu_release_addr
+	cbz	x0, 0b
+	br	x0
+.globl spin_table_cpu_release_addr
+	.align	3
+spin_table_cpu_release_addr:
+	.quad	0
+.globl spin_table_reserve_end
+spin_table_reserve_end:
+ENDPROC(spin_table_secondary_jump)
diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S
index 670e323..19c771d 100644
--- a/arch/arm/cpu/armv8/start.S
+++ b/arch/arm/cpu/armv8/start.S
@@ -53,6 +53,11 @@
 	.quad	__bss_end - _start
 
 reset:
+	/* Allow the board to save important registers */
+	b	save_boot_params
+.globl	save_boot_params_ret
+save_boot_params_ret:
+
 #ifdef CONFIG_SYS_RESET_SCTRL
 	bl reset_sctrl
 #endif
@@ -94,7 +99,11 @@
 	/* Processor specific initialization */
 	bl	lowlevel_init
 
-#ifdef CONFIG_ARMV8_MULTIENTRY
+#if CONFIG_IS_ENABLED(ARMV8_SPIN_TABLE)
+	branch_if_master x0, x1, master_cpu
+	b	spin_table_secondary_jump
+	/* never return */
+#elif defined(CONFIG_ARMV8_MULTIENTRY)
 	branch_if_master x0, x1, master_cpu
 
 	/*
@@ -106,10 +115,8 @@
 	ldr	x0, [x1]
 	cbz	x0, slave_cpu
 	br	x0			/* branch to the given address */
-master_cpu:
-	/* On the master CPU */
 #endif /* CONFIG_ARMV8_MULTIENTRY */
-
+master_cpu:
 	bl	_main
 
 #ifdef CONFIG_SYS_RESET_SCTRL
@@ -280,3 +287,7 @@
 
 	ret
 ENDPROC(c_runtime_cpu_setup)
+
+WEAK(save_boot_params)
+	b	save_boot_params_ret	/* back to my caller */
+ENDPROC(save_boot_params)
diff --git a/arch/arm/cpu/armv8/zynqmp/Kconfig b/arch/arm/cpu/armv8/zynqmp/Kconfig
index 6c71d78..ed3305d 100644
--- a/arch/arm/cpu/armv8/zynqmp/Kconfig
+++ b/arch/arm/cpu/armv8/zynqmp/Kconfig
@@ -20,4 +20,8 @@
 config ZYNQMP_USB
 	bool "Configure ZynqMP USB"
 
+config SYS_MALLOC_F_LEN
+	default 0x600
+
+
 endif
diff --git a/arch/arm/cpu/armv8/zynqmp/clk.c b/arch/arm/cpu/armv8/zynqmp/clk.c
index 690c72d..f7e5ebf 100644
--- a/arch/arm/cpu/armv8/zynqmp/clk.c
+++ b/arch/arm/cpu/armv8/zynqmp/clk.c
@@ -12,22 +12,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-unsigned long get_uart_clk(int dev_id)
-{
-	u32 ver = zynqmp_get_silicon_version();
-
-	switch (ver) {
-	case ZYNQMP_CSU_VERSION_VELOCE:
-		return 48000;
-	case ZYNQMP_CSU_VERSION_EP108:
-		return 25000000;
-	case ZYNQMP_CSU_VERSION_QEMU:
-		return 133000000;
-	}
-
-	return 100000000;
-}
-
 unsigned long zynqmp_get_system_timer_freq(void)
 {
 	u32 ver = zynqmp_get_silicon_version();
diff --git a/arch/arm/cpu/armv8/zynqmp/cpu.c b/arch/arm/cpu/armv8/zynqmp/cpu.c
index 509f0aa..b0f1295 100644
--- a/arch/arm/cpu/armv8/zynqmp/cpu.c
+++ b/arch/arm/cpu/armv8/zynqmp/cpu.c
@@ -18,40 +18,47 @@
 
 static struct mm_region zynqmp_mem_map[] = {
 	{
-		.base = 0x0UL,
+		.virt = 0x0UL,
+		.phys = 0x0UL,
 		.size = 0x80000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_INNER_SHARE
 	}, {
-		.base = 0x80000000UL,
+		.virt = 0x80000000UL,
+		.phys = 0x80000000UL,
 		.size = 0x70000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE |
 			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
 	}, {
-		.base = 0xf8000000UL,
+		.virt = 0xf8000000UL,
+		.phys = 0xf8000000UL,
 		.size = 0x07e00000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE |
 			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
 	}, {
-		.base = 0xffe00000UL,
+		.virt = 0xffe00000UL,
+		.phys = 0xffe00000UL,
 		.size = 0x00200000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_INNER_SHARE
 	}, {
-		.base = 0x400000000UL,
+		.virt = 0x400000000UL,
+		.phys = 0x400000000UL,
 		.size = 0x200000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE |
 			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
 	}, {
-		.base = 0x600000000UL,
+		.virt = 0x600000000UL,
+		.phys = 0x600000000UL,
 		.size = 0x800000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_INNER_SHARE
 	}, {
-		.base = 0xe00000000UL,
+		.virt = 0xe00000000UL,
+		.phys = 0xe00000000UL,
 		.size = 0xf200000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE |
diff --git a/arch/arm/cpu/armv8/zynqmp/mp.c b/arch/arm/cpu/armv8/zynqmp/mp.c
index 58312a7..e10fc31 100644
--- a/arch/arm/cpu/armv8/zynqmp/mp.c
+++ b/arch/arm/cpu/armv8/zynqmp/mp.c
@@ -128,7 +128,7 @@
 	writel(tmp, &crlapb_base->cpu_r5_ctrl);
 
 	/* Give some delay for clock
-	 * to propogate */
+	 * to propagate */
 	udelay(0x500);
 }
 
diff --git a/arch/arm/cpu/u-boot.lds b/arch/arm/cpu/u-boot.lds
index 1769b6e..36c9fd0 100644
--- a/arch/arm/cpu/u-boot.lds
+++ b/arch/arm/cpu/u-boot.lds
@@ -8,6 +8,7 @@
  */
 
 #include <config.h>
+#include <asm/psci.h>
 
 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
 OUTPUT_ARCH(arm)
@@ -48,34 +49,67 @@
 
 #ifdef CONFIG_ARMV7_NONSEC
 
+	/* Align the secure section only if we're going to use it in situ */
+	.__secure_start :
+#ifndef CONFIG_ARMV7_SECURE_BASE
+		ALIGN(CONSTANT(COMMONPAGESIZE))
+#endif
+	{
+		KEEP(*(.__secure_start))
+	}
+
 #ifndef CONFIG_ARMV7_SECURE_BASE
 #define CONFIG_ARMV7_SECURE_BASE
 #define __ARMV7_PSCI_STACK_IN_RAM
 #endif
 
-	.__secure_start : {
-		. = ALIGN(0x1000);
-		*(.__secure_start)
-	}
-
 	.secure_text CONFIG_ARMV7_SECURE_BASE :
 		AT(ADDR(.__secure_start) + SIZEOF(.__secure_start))
 	{
 		*(._secure.text)
 	}
 
-	. = LOADADDR(.__secure_start) +
-		SIZEOF(.__secure_start) +
-		SIZEOF(.secure_text);
+	.secure_data : AT(LOADADDR(.secure_text) + SIZEOF(.secure_text))
+	{
+		*(._secure.data)
+	}
 
+	.secure_stack ALIGN(ADDR(.secure_data) + SIZEOF(.secure_data),
+			    CONSTANT(COMMONPAGESIZE)) (NOLOAD) :
 #ifdef __ARMV7_PSCI_STACK_IN_RAM
-	/* Align to page boundary and skip 2 pages */
-	. = (. & ~ 0xfff) + 0x2000;
-#undef __ARMV7_PSCI_STACK_IN_RAM
+		AT(ADDR(.secure_stack))
+#else
+		AT(LOADADDR(.secure_data) + SIZEOF(.secure_data))
+#endif
+	{
+		KEEP(*(.__secure_stack_start))
+
+		/* Skip addreses for stack */
+		. = . + CONFIG_ARMV7_PSCI_NR_CPUS * ARM_PSCI_STACK_SIZE;
+
+		/* Align end of stack section to page boundary */
+		. = ALIGN(CONSTANT(COMMONPAGESIZE));
+
+		KEEP(*(.__secure_stack_end))
+
+#ifdef CONFIG_ARMV7_SECURE_MAX_SIZE
+		/*
+		 * We are not checking (__secure_end - __secure_start) here,
+		 * as these are the load addresses, and do not include the
+		 * stack section. Instead, use the end of the stack section
+		 * and the start of the text section.
+		 */
+		ASSERT((. - ADDR(.secure_text)) <= CONFIG_ARMV7_SECURE_MAX_SIZE,
+		       "Error: secure section exceeds secure memory size");
+#endif
+	}
+
+#ifndef __ARMV7_PSCI_STACK_IN_RAM
+	/* Reset VMA but don't allocate space if we have secure SRAM */
+	. = LOADADDR(.secure_stack);
 #endif
 
-	__secure_end_lma = .;
-	.__secure_end : AT(__secure_end_lma) {
+	.__secure_end : AT(ADDR(.__secure_end)) {
 		*(.__secure_end)
 		LONG(0x1d1071c);	/* Must output something to reset LMA */
 	}
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index ef573ec..223124e 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -31,7 +31,12 @@
 	rk3288-firefly.dtb \
 	rk3288-jerry.dtb \
 	rk3288-rock2-square.dtb \
-	rk3036-sdk.dtb
+	rk3288-evb.dtb \
+	rk3288-fennec.dtb \
+	rk3288-miniarm.dtb \
+	rk3288-popmetal.dtb \
+	rk3036-sdk.dtb \
+	rk3399-evb.dtb
 dtb-$(CONFIG_ARCH_MESON) += \
 	meson-gxbb-odroidc2.dtb
 dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \
@@ -53,7 +58,8 @@
 	tegra124-jetson-tk1.dtb \
 	tegra124-nyan-big.dtb \
 	tegra124-venice2.dtb \
-	tegra186-p2771-0000.dtb \
+	tegra186-p2771-0000-a02.dtb \
+	tegra186-p2771-0000-b00.dtb \
 	tegra210-e2220-1170.dtb \
 	tegra210-p2371-0000.dtb \
 	tegra210-p2371-2180.dtb \
@@ -242,8 +248,10 @@
 	sun8i-a83t-sinovoip-bpi-m3.dtb
 dtb-$(CONFIG_MACH_SUN8I_H3) += \
 	sun8i-h3-orangepi-2.dtb \
+	sun8i-h3-orangepi-lite.dtb \
 	sun8i-h3-orangepi-one.dtb \
 	sun8i-h3-orangepi-pc.dtb \
+	sun8i-h3-orangepi-pc-plus.dtb \
 	sun8i-h3-orangepi-plus.dtb
 dtb-$(CONFIG_MACH_SUN50I) += \
 	sun50i-a64-pine64-plus.dtb \
@@ -262,6 +270,9 @@
 	k2e-evm.dtb \
 	k2g-evm.dtb
 
+dtb-$(CONFIG_TARGET_SAMA5D2_XPLAINED) += \
+	at91-sama5d2_xplained.dtb
+
 targets += $(dtb-y)
 
 # Add any required device tree compiler flags here
diff --git a/arch/arm/dts/am57xx-idk-common.dtsi b/arch/arm/dts/am57xx-idk-common.dtsi
index 2805b68..a5bcd25 100644
--- a/arch/arm/dts/am57xx-idk-common.dtsi
+++ b/arch/arm/dts/am57xx-idk-common.dtsi
@@ -300,3 +300,52 @@
 	ti,non-removable;
 	max-frequency = <96000000>;
 };
+
+&qspi {
+	status = "okay";
+
+	spi-max-frequency = <76800000>;
+	m25p80@0 {
+		compatible = "s25fl256s1","spi-flash";
+		spi-max-frequency = <76800000>;
+		reg = <0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		/* MTD partition table.
+		 * The ROM checks the first four physical blocks
+		 * for a valid file to boot and the flash here is
+		 * 64KiB block size.
+		 */
+		partition@0 {
+			label = "QSPI.SPL";
+			reg = <0x00000000 0x000040000>;
+		};
+		partition@1 {
+			label = "QSPI.u-boot";
+			reg = <0x00040000 0x00100000>;
+		};
+		partition@2 {
+			label = "QSPI.u-boot-spl-os";
+			reg = <0x00140000 0x00080000>;
+		};
+		partition@3 {
+			label = "QSPI.u-boot-env";
+			reg = <0x001c0000 0x00010000>;
+		};
+		partition@4 {
+			label = "QSPI.u-boot-env.backup1";
+			reg = <0x001d0000 0x0010000>;
+		};
+		partition@5 {
+			label = "QSPI.kernel";
+			reg = <0x001e0000 0x0800000>;
+		};
+		partition@6 {
+			label = "QSPI.file-system";
+			reg = <0x009e0000 0x01620000>;
+		};
+	};
+};
diff --git a/arch/arm/dts/at91-sama5d2_xplained.dts b/arch/arm/dts/at91-sama5d2_xplained.dts
new file mode 100644
index 0000000..3709437
--- /dev/null
+++ b/arch/arm/dts/at91-sama5d2_xplained.dts
@@ -0,0 +1,200 @@
+/dts-v1/;
+#include "sama5d2.dtsi"
+#include "sama5d2-pinfunc.h"
+
+/ {
+	model = "Atmel SAMA5D2 Xplained";
+	compatible = "atmel,sama5d2-xplained", "atmel,sama5d2", "atmel,sama5";
+
+	chosen {
+		stdout-path = &uart1;
+	};
+
+	ahb {
+		usb1: ohci@00400000 {
+			num-ports = <3>;
+			atmel,vbus-gpio = <&pioA 42 0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usb_default>;
+			status = "okay";
+		};
+
+		usb2: ehci@00500000 {
+			status = "okay";
+		};
+
+		sdmmc0: sdio-host@a0000000 {
+			bus-width = <8>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_sdmmc0_cmd_dat_default &pinctrl_sdmmc0_ck_cd_default>;
+			status = "okay";
+		};
+
+		sdmmc1: sdio-host@b0000000 {
+			bus-width = <4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_sdmmc1_cmd_dat_default &pinctrl_sdmmc1_ck_cd_default>;
+			status = "okay"; /* conflict with qspi0 */
+		};
+
+		apb {
+			qspi0: spi@f0020000 {
+				status = "okay";
+
+				flash@0 {
+					compatible = "atmel,sama5d2-qspi-flash";
+					reg = <0>;
+					#address-cells = <1>;
+					#size-cells = <1>;
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_qspi0_default>;
+					spi-max-frequency = <83000000>;
+
+					partition@00000000 {
+						label = "boot";
+						reg = <0x00000000 0x00c00000>;
+					};
+
+					partition@00c00000 {
+						label = "rootfs";
+						reg = <0x00c00000 0x00000000>;
+					};
+				};
+			};
+
+			spi0: spi@f8000000 {
+				cs-gpios = <&pioA 17 0>, <0>, <0>, <0>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_spi0_default>;
+				status = "okay";
+
+				spi_flash@0 {
+					compatible = "spi-flash";
+					reg = <0>;
+					spi-max-frequency = <50000000>;
+				};
+			};
+
+			macb0: ethernet@f8008000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_macb0_rmii &pinctrl_macb0_phy_irq>;
+				phy-mode = "rmii";
+				status = "okay";
+
+				ethernet-phy@1 {
+					reg = <0x1>;
+				};
+			};
+
+			uart1: serial@f8020000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart1_default>;
+				status = "okay";
+			};
+
+			i2c1: i2c@fc028000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_i2c1_default>;
+				status = "okay";
+			};
+
+			pioA: gpio@fc038000 {
+				pinctrl {
+					pinctrl_i2c1_default: i2c1_default {
+						pinmux = <PIN_PD4__TWD1>,
+							 <PIN_PD5__TWCK1>;
+						bias-disable;
+					};
+
+					pinctrl_macb0_phy_irq: macb0_phy_irq {
+						pinmux = <PIN_PC9__GPIO>;
+						bias-disable;
+					};
+
+					pinctrl_macb0_rmii: macb0_rmii {
+						pinmux = <PIN_PB14__GTXCK>,
+							 <PIN_PB15__GTXEN>,
+							 <PIN_PB16__GRXDV>,
+							 <PIN_PB17__GRXER>,
+							 <PIN_PB18__GRX0>,
+							 <PIN_PB19__GRX1>,
+							 <PIN_PB20__GTX0>,
+							 <PIN_PB21__GTX1>,
+							 <PIN_PB22__GMDC>,
+							 <PIN_PB23__GMDIO>;
+						bias-disable;
+					};
+
+					pinctrl_qspi0_default: qspi0_default {
+						pinmux = <PIN_PA22__QSPI0_SCK>,
+							 <PIN_PA23__QSPI0_CS>,
+							 <PIN_PA24__QSPI0_IO0>,
+							 <PIN_PA25__QSPI0_IO1>,
+							 <PIN_PA26__QSPI0_IO2>,
+							 <PIN_PA27__QSPI0_IO3>;
+						bias-disable;
+					};
+
+					pinctrl_sdmmc0_cmd_dat_default: sdmmc0_cmd_dat_default {
+						pinmux = <PIN_PA1__SDMMC0_CMD>,
+							 <PIN_PA2__SDMMC0_DAT0>,
+							 <PIN_PA3__SDMMC0_DAT1>,
+							 <PIN_PA4__SDMMC0_DAT2>,
+							 <PIN_PA5__SDMMC0_DAT3>,
+							 <PIN_PA6__SDMMC0_DAT4>,
+							 <PIN_PA7__SDMMC0_DAT5>,
+							 <PIN_PA8__SDMMC0_DAT6>,
+							 <PIN_PA9__SDMMC0_DAT7>;
+						bias-pull-up;
+					};
+
+					pinctrl_sdmmc0_ck_cd_default: sdmmc0_ck_cd_default {
+						pinmux = <PIN_PA0__SDMMC0_CK>,
+							 <PIN_PA10__SDMMC0_RSTN>,
+							 <PIN_PA11__SDMMC0_VDDSEL>,
+							 <PIN_PA13__SDMMC0_CD>;
+						bias-disable;
+					};
+
+					pinctrl_sdmmc1_cmd_dat_default: sdmmc1_cmd_dat_default {
+						pinmux = <PIN_PA28__SDMMC1_CMD>,
+							 <PIN_PA18__SDMMC1_DAT0>,
+							 <PIN_PA19__SDMMC1_DAT1>,
+							 <PIN_PA20__SDMMC1_DAT2>,
+							 <PIN_PA21__SDMMC1_DAT3>;
+						bias-pull-up;
+					};
+
+					pinctrl_sdmmc1_ck_cd_default: sdmmc1_ck_cd_default {
+						pinmux = <PIN_PA22__SDMMC1_CK>,
+							 <PIN_PA30__SDMMC1_CD>;
+						bias-disable;
+					};
+
+					pinctrl_spi0_default: spi0_default {
+						pinmux = <PIN_PA14__SPI0_SPCK>,
+							 <PIN_PA15__SPI0_MOSI>,
+							 <PIN_PA16__SPI0_MISO>;
+						bias-disable;
+					};
+
+					pinctrl_uart1_default: uart1_default {
+						pinmux = <PIN_PD2__URXD1>,
+							 <PIN_PD3__UTXD1>;
+						bias-disable;
+					};
+
+					pinctrl_usb_default: usb_default {
+						pinmux = <PIN_PB10__GPIO>;
+						bias-disable;
+					};
+
+					pinctrl_usba_vbus: usba_vbus {
+						pinmux = <PIN_PA31__GPIO>;
+						bias-disable;
+					};
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/dra7-evm.dts b/arch/arm/dts/dra7-evm.dts
index 08ef04e..fe755c0 100644
--- a/arch/arm/dts/dra7-evm.dts
+++ b/arch/arm/dts/dra7-evm.dts
@@ -24,6 +24,15 @@
 		reg = <0x80000000 0x60000000>; /* 1536 MB */
 	};
 
+	evm_3v3_sd: fixedregulator-sd {
+		compatible = "regulator-fixed";
+		regulator-name = "evm_3v3_sd";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		enable-active-high;
+		gpio = <&pcf_gpio_21 5 GPIO_ACTIVE_HIGH>;
+	};
+
 	mmc2_3v3: fixedregulator-mmc2 {
 		compatible = "regulator-fixed";
 		regulator-name = "mmc2_3v3";
@@ -415,6 +424,7 @@
 		interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
+		u-boot,i2c-offset-len = <0>;
 	};
 
 };
@@ -467,7 +477,8 @@
 
 &mmc1 {
 	status = "okay";
-	vmmc-supply = <&ldo1_reg>;
+	vmmc-supply = <&evm_3v3_sd>;
+	vmmc_aux-supply = <&ldo1_reg>;
 	bus-width = <4>;
 	/*
 	 * SDCD signal is not being used here - using the fact that GPIO mode
@@ -491,15 +502,13 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&qspi1_pins>;
 
-	spi-max-frequency = <48000000>;
+	spi-max-frequency = <76800000>;
 	m25p80@0 {
 		compatible = "s25fl256s1","spi-flash";
-		spi-max-frequency = <48000000>;
+		spi-max-frequency = <64000000>;
 		reg = <0>;
 		spi-tx-bus-width = <1>;
 		spi-rx-bus-width = <4>;
-		spi-cpol;
-		spi-cpha;
 		#address-cells = <1>;
 		#size-cells = <1>;
 
diff --git a/arch/arm/dts/dra72-evm.dts b/arch/arm/dts/dra72-evm.dts
index 205103e..4ca37fa 100644
--- a/arch/arm/dts/dra72-evm.dts
+++ b/arch/arm/dts/dra72-evm.dts
@@ -35,6 +35,15 @@
 		regulator-max-microvolt = <3300000>;
 	};
 
+	evm_3v3_sd: fixedregulator-sd {
+		compatible = "regulator-fixed";
+		regulator-name = "evm_3v3_sd";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		enable-active-high;
+		gpio = <&pcf_gpio_21 5 GPIO_ACTIVE_HIGH>;
+	};
+
 	extcon_usb1: extcon_usb1 {
 		compatible = "linux,extcon-usb-gpio";
 		id-gpio = <&pcf_gpio_21 1 GPIO_ACTIVE_HIGH>;
@@ -348,6 +357,7 @@
 		interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
+		u-boot,i2c-offset-len = <0>;
 	};
 };
 
@@ -369,6 +379,7 @@
 		 * VIN6_SEL_S0 is low, thus selecting McASP3 over VIN6
 		 */
 		lines-initial-states = <0x0f2b>;
+		u-boot,i2c-offset-len = <0>;
 	};
 };
 
@@ -497,7 +508,8 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc1_pins_default>;
 
-	vmmc-supply = <&ldo1_reg>;
+	vmmc_aux-supply = <&ldo1_reg>;
+	vmmc-supply = <&evm_3v3_sd>;
 	bus-width = <4>;
 	/*
 	 * SDCD signal is not being used here - using the fact that GPIO mode
@@ -576,6 +588,7 @@
 	pinctrl-names = "default", "sleep";
 	pinctrl-0 = <&cpsw_default>;
 	pinctrl-1 = <&cpsw_sleep>;
+	mode-gpios = <&pcf_gpio_21 4 GPIO_ACTIVE_HIGH>;
 };
 
 &cpsw_emac1 {
@@ -587,7 +600,6 @@
 	pinctrl-names = "default", "sleep";
 	pinctrl-0 = <&davinci_mdio_default>;
 	pinctrl-1 = <&davinci_mdio_sleep>;
-	active_slave = <1>;
 };
 
 &dcan1 {
@@ -603,15 +615,13 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&qspi1_pins>;
 
-	spi-max-frequency = <48000000>;
+	spi-max-frequency = <76800000>;
 	m25p80@0 {
 		compatible = "s25fl256s1","spi-flash";
-		spi-max-frequency = <48000000>;
+		spi-max-frequency = <64000000>;
 		reg = <0>;
 		spi-tx-bus-width = <1>;
 		spi-rx-bus-width = <4>;
-		spi-cpol;
-		spi-cpha;
 		#address-cells = <1>;
 		#size-cells = <1>;
 
diff --git a/arch/arm/dts/exynos4210-origen.dts b/arch/arm/dts/exynos4210-origen.dts
index 3f87761..26c4d7f 100644
--- a/arch/arm/dts/exynos4210-origen.dts
+++ b/arch/arm/dts/exynos4210-origen.dts
@@ -22,7 +22,7 @@
 	aliases {
 		serial0 = "/serial@13800000";
 		console = "/serial@13820000";
-		mmc2 = "sdhci@12530000";
+		mmc2 = "/sdhci@12530000";
 	};
 
 	sdhci@12510000 {
diff --git a/arch/arm/dts/exynos4210-trats.dts b/arch/arm/dts/exynos4210-trats.dts
index f3fac80..2ed38f3 100644
--- a/arch/arm/dts/exynos4210-trats.dts
+++ b/arch/arm/dts/exynos4210-trats.dts
@@ -29,8 +29,8 @@
 		i2c7 = "/i2c@138d0000";
 		serial0 = "/serial@13800000";
 		console = "/serial@13820000";
-		mmc0 = "sdhci@12510000";
-		mmc2 = "sdhci@12530000";
+		mmc0 = "/sdhci@12510000";
+		mmc2 = "/sdhci@12530000";
 	};
 
 	fimd@11c00000 {
diff --git a/arch/arm/dts/exynos4210-universal_c210.dts b/arch/arm/dts/exynos4210-universal_c210.dts
index ad3527e..8cac7dd 100644
--- a/arch/arm/dts/exynos4210-universal_c210.dts
+++ b/arch/arm/dts/exynos4210-universal_c210.dts
@@ -17,8 +17,8 @@
 	aliases {
 		serial0 = "/serial@13800000";
 		console = "/serial@13820000";
-		mmc0 = "sdhci@12510000";
-		mmc2 = "sdhci@12530000";
+		mmc0 = "/sdhci@12510000";
+		mmc2 = "/sdhci@12530000";
 	};
 
 	sdhci@12510000 {
diff --git a/arch/arm/dts/exynos4412-odroid.dts b/arch/arm/dts/exynos4412-odroid.dts
index a63e8ab..188cb93 100644
--- a/arch/arm/dts/exynos4412-odroid.dts
+++ b/arch/arm/dts/exynos4412-odroid.dts
@@ -25,8 +25,8 @@
 		i2c7 = "/i2c@138d0000";
 		serial0 = "/serial@13800000";
 		console = "/serial@13810000";
-		mmc2 = "sdhci@12530000";
-		mmc4 = "dwmmc@12550000";
+		mmc2 = "/sdhci@12530000";
+		mmc4 = "/dwmmc@12550000";
 	};
 
 	i2c@13860000 {
diff --git a/arch/arm/dts/exynos4412-trats2.dts b/arch/arm/dts/exynos4412-trats2.dts
index 2d4e522..1fbcf89 100644
--- a/arch/arm/dts/exynos4412-trats2.dts
+++ b/arch/arm/dts/exynos4412-trats2.dts
@@ -29,9 +29,9 @@
 		i2c7 = "/i2c@138d0000";
 		serial0 = "/serial@13800000";
 		console = "/serial@13820000";
-		mmc0 = "sdhci@12510000";
-		mmc2 = "sdhci@12530000";
-		mmc4 = "dwmmc@12550000";
+		mmc0 = "/sdhci@12510000";
+		mmc2 = "/sdhci@12530000";
+		mshc0 = "/dwmmc@12550000";
 	};
 
 	i2c@138d0000 {
diff --git a/arch/arm/dts/k2e-evm.dts b/arch/arm/dts/k2e-evm.dts
index 50c83c2..e2c3fb4 100644
--- a/arch/arm/dts/k2e-evm.dts
+++ b/arch/arm/dts/k2e-evm.dts
@@ -119,10 +119,11 @@
 };
 
 &spi0 {
+	status = "okay";
 	nor_flash: n25q128a11@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "Micron,n25q128a11";
+		compatible = "Micron,n25q128a11", "spi-flash";
 		spi-max-frequency = <54000000>;
 		m25p,fast-read;
 		reg = <0>;
diff --git a/arch/arm/dts/k2g-evm.dts b/arch/arm/dts/k2g-evm.dts
index 0ca36ef..61d0d55 100644
--- a/arch/arm/dts/k2g-evm.dts
+++ b/arch/arm/dts/k2g-evm.dts
@@ -31,3 +31,80 @@
 &gbe0 {
 	phy-handle = <&ethphy0>;
 };
+
+&spi1 {
+	status = "okay";
+
+	spi_nor: flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-flash";
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+		reg = <0>;
+
+		partition@0 {
+			label = "u-boot-spl";
+			reg = <0x0 0x80000>;
+			read-only;
+		};
+
+		partition@1 {
+			label = "misc";
+			reg = <0x80000 0xf80000>;
+		};
+	};
+};
+
+&qspi {
+	status = "okay";
+
+        flash0: m25p80@0 {
+                compatible = "s25fl512s","spi-flash";
+                reg = <0>;
+                spi-tx-bus-width = <1>;
+                spi-rx-bus-width = <4>;
+                spi-max-frequency = <96000000>;
+                #address-cells = <1>;
+                #size-cells = <1>;
+                tshsl-ns = <392>;
+                tsd2d-ns = <392>;
+                tchsh-ns = <100>;
+                tslch-ns = <100>;
+		block-size = <18>;
+
+
+                partition@0 {
+                        label = "QSPI.u-boot-spl-os";
+                        reg = <0x00000000 0x00100000>;
+                };
+                partition@1 {
+                        label = "QSPI.u-boot-env";
+                        reg = <0x00100000 0x00040000>;
+                };
+                partition@2 {
+                        label = "QSPI.skern";
+                        reg = <0x00140000 0x0040000>;
+                };
+                partition@3 {
+                        label = "QSPI.pmmc-firmware";
+                        reg = <0x00180000 0x0040000>;
+                };
+                partition@4 {
+                        label = "QSPI.kernel";
+                        reg = <0x001C0000 0x0800000>;
+                };
+                partition@5 {
+                        label = "QSPI.file-system";
+                        reg = <0x009C0000 0x3640000>;
+                };
+        };
+};
+
+&mmc0 {
+	status = "okay";
+};
+
+&mmc1 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/k2g.dtsi b/arch/arm/dts/k2g.dtsi
index a3ed444..add03b7 100644
--- a/arch/arm/dts/k2g.dtsi
+++ b/arch/arm/dts/k2g.dtsi
@@ -19,6 +19,11 @@
 
 	aliases {
 		serial0	= &uart0;
+		spi0 = &spi0;
+		spi1 = &spi1;
+		spi2 = &spi2;
+		spi3 = &spi3;
+		spi4 = &qspi;
 	};
 
 	memory {
@@ -80,6 +85,19 @@
 			bus_freq = <2500000>;
 		};
 
+		qspi: qspi@2940000 {
+			compatible =  "cadence,qspi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x02940000 0x1000>,
+			      <0x24000000 0x4000000>;
+			interrupts = <GIC_SPI 198 IRQ_TYPE_EDGE_RISING>;
+			num-cs = <4>;
+			fifo-depth = <256>;
+			sram-size = <256>;
+			status = "disabled";
+		};
+
 		#include "k2g-netcp.dtsi"
 
 		pmmc: pmmc@2900000 {
@@ -88,5 +106,71 @@
 			ti,lpsc_module = <1>;
 		};
 
+		spi0: spi@21805400 {
+			compatible = "ti,keystone-spi", "ti,dm6441-spi";
+			reg = <0x21805400 0x200>;
+			num-cs = <4>;
+			ti,davinci-spi-intr-line = <0>;
+			interrupts = <GIC_SPI 64 IRQ_TYPE_EDGE_RISING>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		spi1: spi@21805800 {
+			compatible = "ti,keystone-spi", "ti,dm6441-spi";
+			reg = <0x21805800 0x200>;
+			num-cs = <4>;
+			ti,davinci-spi-intr-line = <0>;
+			interrupts = <GIC_SPI 66 IRQ_TYPE_EDGE_RISING>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		spi2: spi@21805c00 {
+			compatible = "ti,keystone-spi", "ti,dm6441-spi";
+			reg = <0x21805C00 0x200>;
+			num-cs = <4>;
+			ti,davinci-spi-intr-line = <0>;
+			interrupts = <GIC_SPI 68 IRQ_TYPE_EDGE_RISING>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		spi3: spi@21806000 {
+			compatible = "ti,keystone-spi", "ti,dm6441-spi";
+			reg = <0x21806000 0x200>;
+			num-cs = <4>;
+			ti,davinci-spi-intr-line = <0>;
+			interrupts = <GIC_SPI 70 IRQ_TYPE_EDGE_RISING>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		mmc0: mmc@23000000 {
+			compatible = "ti,omap4-hsmmc";
+			reg = <0x23000000 0x400>;
+			interrupts = <GIC_SPI 96 IRQ_TYPE_EDGE_RISING>;
+			bus-width = <4>;
+			ti,needs-special-reset;
+			no-1-8-v;
+			max-frequency = <96000000>;
+			status = "disabled";
+		};
+
+		mmc1: mmc@23100000 {
+			compatible = "ti,omap4-hsmmc";
+			reg = <0x23100000 0x400>;
+			interrupts = <GIC_SPI 97 IRQ_TYPE_EDGE_RISING>;
+			bus-width = <8>;
+			ti,needs-special-reset;
+			ti,non-removable;
+			max-frequency = <96000000>;
+			status = "disabled";
+			clock-names = "fck";
+		};
 	};
 };
diff --git a/arch/arm/dts/k2hk-evm.dts b/arch/arm/dts/k2hk-evm.dts
index 660ebf5..c5cad2c 100644
--- a/arch/arm/dts/k2hk-evm.dts
+++ b/arch/arm/dts/k2hk-evm.dts
@@ -147,10 +147,11 @@
 };
 
 &spi0 {
+	status = "okay";
 	nor_flash: n25q128a11@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "Micron,n25q128a11";
+		compatible = "Micron,n25q128a11", "spi-flash";
 		spi-max-frequency = <54000000>;
 		m25p,fast-read;
 		reg = <0>;
diff --git a/arch/arm/dts/k2l-evm.dts b/arch/arm/dts/k2l-evm.dts
index 9a69a6b..da0661b 100644
--- a/arch/arm/dts/k2l-evm.dts
+++ b/arch/arm/dts/k2l-evm.dts
@@ -96,10 +96,11 @@
 };
 
 &spi0 {
+	status ="okay";
 	nor_flash: n25q128a11@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "Micron,n25q128a11";
+		compatible = "Micron,n25q128a11", "spi-flash";
 		spi-max-frequency = <54000000>;
 		m25p,fast-read;
 		reg = <0>;
diff --git a/arch/arm/dts/keystone.dtsi b/arch/arm/dts/keystone.dtsi
index f39b969..be97f3f 100644
--- a/arch/arm/dts/keystone.dtsi
+++ b/arch/arm/dts/keystone.dtsi
@@ -19,6 +19,9 @@
 
 	aliases {
 		serial0	= &uart0;
+		spi0 = &spi0;
+		spi1 = &spi1;
+		spi2 = &spi2;
 	};
 
 	chosen {
diff --git a/arch/arm/dts/ls1021a.dtsi b/arch/arm/dts/ls1021a.dtsi
index ee0e554..119b1af 100644
--- a/arch/arm/dts/ls1021a.dtsi
+++ b/arch/arm/dts/ls1021a.dtsi
@@ -368,7 +368,7 @@
 		};
 
 		usb3@3100000 {
-			compatible = "snps,dwc3";
+			compatible = "fsl,layerscape-dwc3";
 			reg = <0x3100000 0x10000>;
 			interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
 			dr_mode = "host";
diff --git a/arch/arm/dts/rk3036-sdk.dts b/arch/arm/dts/rk3036-sdk.dts
index a83badb..1c9ddf9 100644
--- a/arch/arm/dts/rk3036-sdk.dts
+++ b/arch/arm/dts/rk3036-sdk.dts
@@ -41,6 +41,4 @@
 
 &usb_otg {
 	status = "okay";
-
-	dr_mode = "host";
 };
diff --git a/arch/arm/dts/rk3288-evb.dts b/arch/arm/dts/rk3288-evb.dts
new file mode 100644
index 0000000..3e1ee58
--- /dev/null
+++ b/arch/arm/dts/rk3288-evb.dts
@@ -0,0 +1,60 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+ X11
+ */
+
+/dts-v1/;
+#include "rk3288-evb.dtsi"
+
+/ {
+	model = "Evb-RK3288";
+	compatible = "evb-rk3288,evb-rk3288", "rockchip,rk3288";
+
+	chosen {
+		stdout-path = &uart2;
+	};
+};
+
+&dmc {
+	rockchip,num-channels = <2>;
+	rockchip,pctl-timing = <0x215 0xc8 0x0 0x35 0x26 0x2 0x70 0x2000d
+		0x6 0x0 0x8 0x4 0x17 0x24 0xd 0x6
+		0x4 0x8 0x4 0x76 0x4 0x0 0x30 0x0
+		0x1 0x2 0x2 0x4 0x0 0x0 0xc0 0x4
+		0x8 0x1f4>;
+	rockchip,phy-timing = <0x48d7dd93 0x187008d8 0x121076
+		0x0 0xc3 0x6 0x2>;
+	/* Add a dummy value to cause of-platdata think this is bytes */
+	rockchip,sdram-channel = /bits/ 8 <0x2 0xa 0x3 0x2 0x2 0x0 0xe 0xe 0xff>;
+	rockchip,sdram-params = <0x20d266a4 0x5b6 2 533000000 6 9 0>;
+};
+
+&pinctrl {
+	u-boot,dm-pre-reloc;
+};
+
+&pwm1 {
+	status = "okay";
+};
+
+&uart2 {
+	u-boot,dm-pre-reloc;
+	reg-shift = <2>;
+};
+
+&sdmmc {
+	u-boot,dm-pre-reloc;
+};
+
+&emmc {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio3 {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio8 {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/rk3288-evb.dtsi b/arch/arm/dts/rk3288-evb.dtsi
new file mode 100644
index 0000000..cb7d03e
--- /dev/null
+++ b/arch/arm/dts/rk3288-evb.dtsi
@@ -0,0 +1,379 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+ X11
+ */
+
+#include "rk3288.dtsi"
+
+/ {
+	memory {
+		reg = <0 0x80000000>;
+	};
+
+	keys: gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		button@0 {
+			gpio-key,wakeup = <1>;
+			gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
+			label = "GPIO Power";
+			linux,code = <116>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pwr_key>;
+		};
+	};
+
+	vcc_sys: vsys-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_sys";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vcc_flash: flash-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_flash";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		vin-supply = <&vcc_io>;
+	};
+
+	vcc_5v: usb-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_5v";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc_sys>;
+	};
+
+	vcc_host_5v: usb-host-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&host_vbus_drv>;
+		regulator-name = "vcc_host_5v";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		vin-supply = <&vcc_5v>;
+	};
+
+	vcc_otg_5v: usb-otg-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&otg_vbus_drv>;
+		regulator-name = "vcc_otg_5v";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		vin-supply = <&vcc_5v>;
+	};
+};
+
+&cpu0 {
+	cpu0-supply = <&vdd_cpu>;
+};
+
+&emmc {
+	broken-cd;
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	disable-wp;
+	non-removable;
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_clk>, <&emmc_cmd>, <&emmc_pwr>, <&emmc_bus8>;
+	vmmc-supply = <&vcc_io>;
+	vqmmc-supply = <&vcc_flash>;
+	status = "okay";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c5>;
+	status = "okay";
+};
+
+&i2c0 {
+	clock-frequency = <400000>;
+	status = "okay";
+
+	vdd_cpu: syr827@40 {
+		compatible = "silergy,syr827";
+		fcs,suspend-voltage-selector = <1>;
+		reg = <0x40>;
+		regulator-name = "vdd_cpu";
+		regulator-min-microvolt = <850000>;
+		regulator-max-microvolt = <1350000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc_sys>;
+	};
+
+	vdd_gpu: syr828@41 {
+		compatible = "silergy,syr828";
+		fcs,suspend-voltage-selector = <1>;
+		reg = <0x41>;
+		regulator-name = "vdd_gpu";
+		regulator-min-microvolt = <850000>;
+		regulator-max-microvolt = <1350000>;
+		regulator-always-on;
+		vin-supply = <&vcc_sys>;
+	};
+
+	hym8563: hym8563@51 {
+		compatible = "haoyu,hym8563";
+		reg = <0x51>;
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		clock-output-names = "xin32k";
+		interrupt-parent = <&gpio7>;
+		interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&rtc_int>;
+	};
+
+	act8846: act8846@5a {
+		compatible = "active-semi,act8846";
+		reg = <0x5a>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwr_hold>;
+		system-power-controller;
+
+		regulators {
+			vcc_ddr: REG1 {
+				regulator-name = "vcc_ddr";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+			};
+
+			vcc_io: REG2 {
+				regulator-name = "vcc_io";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vdd_log: REG3 {
+				regulator-name = "vdd_log";
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-always-on;
+			};
+
+			vcc_20: REG4 {
+				regulator-name = "vcc_20";
+				regulator-min-microvolt = <2000000>;
+				regulator-max-microvolt = <2000000>;
+				regulator-always-on;
+			};
+
+			vccio_sd: REG5 {
+				regulator-name = "vccio_sd";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vdd10_lcd: REG6 {
+				regulator-name = "vdd10_lcd";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			vcca_codec: REG7 {
+				regulator-name = "vcca_codec";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vcc_tp: REG8 {
+				regulator-name = "vcca_33";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vccio_pmu: REG9 {
+				regulator-name = "vccio_pmu";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vdd_10: REG10 {
+				regulator-name = "vdd_10";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			vcc_18: REG11 {
+				regulator-name = "vcc_18";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			vcc18_lcd: REG12 {
+				regulator-name = "vcc18_lcd";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c1 {
+	status = "okay";
+};
+
+&i2c2 {
+	status = "okay";
+};
+
+&i2c4 {
+	status = "okay";
+};
+
+&i2c5 {
+	status = "okay";
+};
+
+&pinctrl {
+	pcfg_output_high: pcfg-output-high {
+		output-high;
+	};
+
+	pcfg_output_low: pcfg-output-low {
+		output-low;
+	};
+
+	act8846 {
+		pwr_hold: pwr-hold {
+			rockchip,pins = <0 9 RK_FUNC_GPIO &pcfg_output_high>;
+		};
+	};
+
+	hym8563 {
+		rtc_int: rtc-int {
+			rockchip,pins = <0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	keys {
+		pwr_key: pwr-key {
+			rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	sdmmc {
+		sdmmc_pwr: sdmmc-pwr {
+			rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	usb_host {
+		host_vbus_drv: host-vbus-drv {
+			rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	usb_otg {
+		otg_vbus_drv: otg-vbus-drv {
+			rockchip,pins = <0 12 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&saradc {
+	vref-supply = <&vcc_18>;
+	status = "okay";
+};
+
+&sdio0 {
+	broken-cd;
+	bus-width = <4>;
+	disable-wp;
+	non-removable;
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdio0_bus4>, <&sdio0_cmd>, <&sdio0_clk>;
+	vmmc-supply = <&vcc_18>;
+	status = "disabled";
+};
+
+&sdmmc {
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	card-detect-delay = <200>;
+	disable-wp;
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>;
+	vmmc-supply = <&vccio_sd>;
+	status = "okay";
+};
+
+&spi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_clk>, <&spi0_cs0>, <&spi0_tx>, <&spi0_rx>, <&spi0_cs1>;
+	status = "okay";
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_xfer>, <&uart0_cts>, <&uart0_rts>;
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&usb_host1 {
+	status = "okay";
+};
+
+&usb_otg {
+	status = "okay";
+};
+
+&vopb {
+	status = "okay";
+};
+
+&vopb_mmu {
+	status = "okay";
+};
+
+&vopl {
+	status = "okay";
+};
+
+&vopl_mmu {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3288-fennec.dts b/arch/arm/dts/rk3288-fennec.dts
new file mode 100644
index 0000000..36e9f3d
--- /dev/null
+++ b/arch/arm/dts/rk3288-fennec.dts
@@ -0,0 +1,60 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+ X11
+ */
+
+/dts-v1/;
+#include "rk3288-fennec.dtsi"
+
+/ {
+	model = "Rockchip RK3288 Fennec Board";
+	compatible = "rockchip,rk3288-fennec", "rockchip,rk3288";
+
+	chosen {
+		stdout-path = &uart2;
+	};
+};
+
+&dmc {
+	rockchip,num-channels = <2>;
+	rockchip,pctl-timing = <0x215 0xc8 0x0 0x35 0x26 0x2 0x70 0x2000d
+		0x6 0x0 0x8 0x4 0x17 0x24 0xd 0x6
+		0x4 0x8 0x4 0x76 0x4 0x0 0x30 0x0
+		0x1 0x2 0x2 0x4 0x0 0x0 0xc0 0x4
+		0x8 0x1f4>;
+	rockchip,phy-timing = <0x48d7dd93 0x187008d8 0x121076
+		0x0 0xc3 0x6 0x2>;
+	/* Add a dummy value to cause of-platdata think this is bytes */
+	rockchip,sdram-channel = /bits/ 8 <0x2 0xa 0x3 0x2 0x2 0x0 0xe 0xe 0xff>;
+	rockchip,sdram-params = <0x20d266a4 0x5b6 2 533000000 6 9 0>;
+};
+
+&pinctrl {
+	u-boot,dm-pre-reloc;
+};
+
+&pwm1 {
+	status = "okay";
+};
+
+&uart2 {
+	u-boot,dm-pre-reloc;
+	reg-shift = <2>;
+};
+
+&sdmmc {
+	u-boot,dm-pre-reloc;
+};
+
+&emmc {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio3 {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio8 {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/rk3288-fennec.dtsi b/arch/arm/dts/rk3288-fennec.dtsi
new file mode 100644
index 0000000..f61252c
--- /dev/null
+++ b/arch/arm/dts/rk3288-fennec.dtsi
@@ -0,0 +1,421 @@
+/*
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "rk3288.dtsi"
+
+/ {
+	memory {
+		reg = <0x0 0x80000000>;
+		device_type = "memory";
+	};
+
+	ext_gmac: external-gmac-clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <125000000>;
+		clock-output-names = "ext_gmac";
+	};
+
+	vcc_sys: vsys-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_sys";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+};
+
+&cpu0 {
+	cpu0-supply = <&vdd_cpu>;
+};
+
+&emmc {
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	disable-wp;
+	non-removable;
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_pwr &emmc_bus8>;
+	status = "okay";
+};
+
+&sdmmc {
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	card-detect-delay = <200>;
+	disable-wp;
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>;
+	status = "okay";
+	vmmc-supply = <&vcc_sd>;
+	vqmmc-supply = <&vccio_sd>;
+};
+
+&gmac {
+	assigned-clocks = <&cru SCLK_MAC>;
+	assigned-clock-parents = <&ext_gmac>;
+	clock_in_out = "input";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>, <&phy_rst>, <&phy_pmeb>, <&phy_int>;
+	phy-supply = <&vcc_lan>;
+	phy-mode = "rgmii";
+	snps,reset-active-low;
+	snps,reset-delays-us = <0 10000 1000000>;
+	snps,reset-gpio = <&gpio4 8 GPIO_ACTIVE_LOW>;
+	tx_delay = <0x30>;
+	rx_delay = <0x10>;
+	status = "okay";
+};
+
+&gpu {
+	mali-supply = <&vdd_gpu>;
+	status = "okay";
+};
+
+&hdmi {
+	status = "okay";
+};
+
+&i2c0 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	rk808: pmic@1b {
+		compatible = "rockchip,rk808";
+		reg = <0x1b>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+		#clock-cells = <1>;
+		clock-output-names = "xin32k", "rk808-clkout2";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_int &global_pwroff>;
+		rockchip,system-power-controller;
+		wakeup-source;
+
+		vcc1-supply = <&vcc_sys>;
+		vcc2-supply = <&vcc_sys>;
+		vcc3-supply = <&vcc_sys>;
+		vcc4-supply = <&vcc_sys>;
+		vcc6-supply = <&vcc_sys>;
+		vcc7-supply = <&vcc_sys>;
+		vcc8-supply = <&vcc_io>;
+		vcc9-supply = <&vcc_io>;
+		vcc10-supply = <&vcc_io>;
+		vcc11-supply = <&vcc_io>;
+		vcc12-supply = <&vcc_io>;
+		vddio-supply = <&vcc_io>;
+
+		regulators {
+			vdd_cpu: DCDC_REG1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-name = "vdd_arm";
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vdd_gpu: DCDC_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <1250000>;
+				regulator-name = "vdd_gpu";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1000000>;
+				};
+			};
+
+			vcc_ddr: DCDC_REG3 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vcc_ddr";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+				};
+			};
+
+			vcc_io: DCDC_REG4 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc_io";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3300000>;
+				};
+			};
+
+			vccio_pmu: LDO_REG1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vccio_pmu";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3300000>;
+				};
+			};
+
+			vcca_33: LDO_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcca_33";
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vdd_10: LDO_REG3 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-name = "vdd_10";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1000000>;
+				};
+			};
+
+			vcc_wl: LDO_REG4 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc_wl";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			vccio_sd: LDO_REG5 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vccio_sd";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3300000>;
+				};
+			};
+
+			vdd10_lcd: LDO_REG6 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-name = "vdd10_lcd";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1000000>;
+				};
+			};
+
+			vcc_18: LDO_REG7 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc_18";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			vcc18_lcd: LDO_REG8 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc18_lcd";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			vcc_sd: SWITCH_REG1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vcc_sd";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+				};
+			};
+
+			vcc_lan: SWITCH_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vcc_lan";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+				};
+			};
+		};
+	};
+};
+
+&pinctrl {
+	pcfg_output_high: pcfg-output-high {
+		output-high;
+	};
+
+	pcfg_output_low: pcfg-output-low {
+		output-low;
+	};
+
+	pcfg_pull_none_drv_8ma: pcfg-pull-none-drv-8ma {
+		drive-strength = <8>;
+	};
+
+	pcfg_pull_up_drv_8ma: pcfg-pull-up-drv-8ma {
+		bias-pull-up;
+		drive-strength = <8>;
+	};
+
+	gmac {
+		phy_int: phy-int {
+			rockchip,pins = <0 9 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+
+		phy_pmeb: phy-pmeb {
+			rockchip,pins = <0 8 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+
+		phy_rst: phy-rst {
+			rockchip,pins = <4 8 RK_FUNC_GPIO &pcfg_output_high>;
+		};
+	};
+
+	pmic {
+		pmic_int: pmic-int {
+			rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	sdmmc {
+		sdmmc_bus4: sdmmc-bus4 {
+			rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
+					<6 17 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
+					<6 18 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
+					<6 19 RK_FUNC_1 &pcfg_pull_up_drv_8ma>;
+		};
+
+		sdmmc_clk: sdmmc-clk {
+			rockchip,pins = <6 20 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+		};
+
+		sdmmc_cmd: sdmmc-cmd {
+			rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up_drv_8ma>;
+		};
+
+		sdmmc_pwr: sdmmc-pwr {
+			rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	usbphy {
+		host_drv: host-drv {
+			rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&usbphy {
+	pinctrl-names = "default";
+	pinctrl-0 = <&host_drv>;
+	vbus_drv-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&usb_host0_ehci {
+	status = "okay";
+};
+
+&usb_host1 {
+	status = "okay";
+};
+
+&usb_otg {
+	status = "okay";
+};
+
+&usb_hsic {
+	status = "okay";
+};
+
+&vopb {
+	status = "okay";
+};
+
+&vopb_mmu {
+	status = "okay";
+};
+
+&vopl {
+	status = "okay";
+};
+
+&vopl_mmu {
+	status = "okay";
+};
+
+&vpu {
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3288-firefly.dts b/arch/arm/dts/rk3288-firefly.dts
index aed8d3a..3176d50 100644
--- a/arch/arm/dts/rk3288-firefly.dts
+++ b/arch/arm/dts/rk3288-firefly.dts
@@ -30,7 +30,8 @@
 		0x5 0x0>;
 	rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200
 		0xa60 0x40 0x10 0x0>;
-	rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf>;
+	/* Add a dummy value to cause of-platdata think this is bytes */
+	rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf 0xff>;
 	rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
 };
 
diff --git a/arch/arm/dts/rk3288-miniarm.dts b/arch/arm/dts/rk3288-miniarm.dts
new file mode 100644
index 0000000..c741082
--- /dev/null
+++ b/arch/arm/dts/rk3288-miniarm.dts
@@ -0,0 +1,61 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+ X11
+ */
+
+/dts-v1/;
+#include "rk3288-miniarm.dtsi"
+
+/ {
+	model = "Miniarm-RK3288";
+	compatible = "rockchip,rk3288-miniarm", "rockchip,rk3288";
+
+	chosen {
+		stdout-path = &uart2;
+	};
+};
+
+&dmc {
+	rockchip,num-channels = <2>;
+	rockchip,pctl-timing = <0x29a 0xc8 0x1f8 0x42 0x4e 0x4 0xea 0xa
+		0x5 0x0 0xa 0x7 0x19 0x24 0xa 0x7
+		0x5 0xa 0x5 0x200 0x5 0x10 0x40 0x0
+		0x1 0x7 0x7 0x4 0xc 0x43 0x100 0x0
+		0x5 0x0>;
+	rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200
+		0xa60 0x40 0x10 0x0>;
+	/* Add a dummy value to cause of-platdata think this is bytes */
+	rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf 0xff>;
+	rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
+};
+
+
+&pinctrl {
+	u-boot,dm-pre-reloc;
+};
+
+&pwm1 {
+	status = "okay";
+};
+
+&uart2 {
+	u-boot,dm-pre-reloc;
+	reg-shift = <2>;
+};
+
+&sdmmc {
+	u-boot,dm-pre-reloc;
+};
+
+&emmc {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio3 {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio8 {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/rk3288-miniarm.dtsi b/arch/arm/dts/rk3288-miniarm.dtsi
new file mode 100644
index 0000000..b889875
--- /dev/null
+++ b/arch/arm/dts/rk3288-miniarm.dtsi
@@ -0,0 +1,533 @@
+/*
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "rk3288.dtsi"
+
+/ {
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x80000000>;
+	};
+
+	ext_gmac: external-gmac-clock {
+		compatible = "fixed-clock";
+		clock-frequency = <125000000>;
+		clock-output-names = "ext_gmac";
+		#clock-cells = <0>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		autorepeat;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwrbtn>;
+
+		button@0 {
+			gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
+			label = "GPIO Key Power";
+			linux,input-type = <1>;
+			gpio-key,wakeup = <1>;
+			debounce-interval = <100>;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		pwr-led {
+			gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-on";
+		};
+
+		act-led {
+			gpios=<&gpio2 3 GPIO_ACTIVE_LOW>;
+			linux,default-trigger="mmc0";
+		};
+	};
+
+	vcc_sys: vsys-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_sys";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	/*
+	 * NOTE: vcc_sd isn't hooked up on v1.0 boards where power comes from
+	 * vcc_io directly.  Those boards won't be able to power cycle SD cards
+	 * but it shouldn't hurt to toggle this pin there anyway.
+	 */
+	vcc_sd: sdmmc-regulator {
+		compatible = "regulator-fixed";
+		gpio = <&gpio7 11 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdmmc_pwr>;
+		regulator-name = "vcc_sd";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		startup-delay-us = <100000>;
+		vin-supply = <&vcc_io>;
+	};
+};
+
+&cpu0 {
+	cpu0-supply = <&vdd_cpu>;
+};
+
+&emmc {
+	broken-cd;
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	disable-wp;
+	non-removable;
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_pwr &emmc_bus8>;
+	status = "okay";
+};
+
+&sdmmc {
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	card-detect-delay = <200>;
+	disable-wp;			/* wp not hooked up */
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>;
+	status = "okay";
+	supports-sd;
+	vmmc-supply = <&vcc_sd>;
+	vqmmc-supply = <&vccio_sd>;
+};
+
+&gpu {
+	mali-supply = <&vdd_gpu>;
+	status = "okay";
+};
+
+&gmac {
+	phy-supply = <&vcc33_lan>;
+	phy-mode = "rgmii";
+	clock_in_out = "input";
+	snps,reset-gpio = <&gpio4 7 0>;
+	snps,reset-active-low;
+	snps,reset-delays-us = <0 10000 1000000>;
+	assigned-clocks = <&cru SCLK_MAC>;
+	assigned-clock-parents = <&ext_gmac>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>;
+	tx_delay = <0x30>;
+	rx_delay = <0x10>;
+	status = "ok";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c5>;
+	status = "okay";
+};
+
+&i2c0 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	rk808: pmic@1b {
+		compatible = "rockchip,rk808";
+		reg = <0x1b>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_int &global_pwroff>;
+		rockchip,system-power-controller;
+		wakeup-source;
+		#clock-cells = <1>;
+		clock-output-names = "xin32k", "rk808-clkout2";
+
+		vcc1-supply = <&vcc_sys>;
+		vcc2-supply = <&vcc_sys>;
+		vcc3-supply = <&vcc_sys>;
+		vcc4-supply = <&vcc_sys>;
+		vcc6-supply = <&vcc_sys>;
+		vcc7-supply = <&vcc_sys>;
+		vcc8-supply = <&vcc_18>;
+		vcc9-supply = <&vcc_io>;
+		vcc10-supply = <&vcc_io>;
+		vcc11-supply = <&vcc_sys>;
+		vcc12-supply = <&vcc_io>;
+		vddio-supply = <&vcc18_ldo1>;
+
+		regulators {
+			vdd_cpu: DCDC_REG1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-name = "vdd_arm";
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vdd_gpu: DCDC_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <1250000>;
+				regulator-name = "vdd_gpu";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1000000>;
+				};
+			};
+
+			vcc_ddr: DCDC_REG3 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vcc_ddr";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+				};
+			};
+
+			vcc_io: DCDC_REG4 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc_io";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3300000>;
+				};
+			};
+
+			vcc18_ldo1: LDO_REG1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc18_ldo1";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			vcc33_mipi: LDO_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc33_mipi";
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vdd_10: LDO_REG3 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-name = "vdd_10";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1000000>;
+				};
+			};
+
+			vcc18_codec: LDO_REG4 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc18_codec";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			vccio_sd: LDO_REG5 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vccio_sd";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3300000>;
+				};
+			};
+
+			vdd10_lcd: LDO_REG6 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-name = "vdd10_lcd";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1000000>;
+				};
+			};
+
+			vcc_18: LDO_REG7 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc_18";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			vcc18_lcd: LDO_REG8 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc18_lcd";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			vcc33_sd: SWITCH_REG1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vcc33_sd";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+				};
+			};
+
+			vcc33_lan: SWITCH_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vcc33_lan";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+				};
+			};
+		};
+	};
+};
+
+&i2c2 {
+	status = "okay";
+	headset: nau8825@1a {
+		compatible = "nuvoton,nau8825";
+		#sound-dai-cells = <0>;
+		reg = <0x1a>;
+		interrupt-parent = <&gpio6>;
+		interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+		nuvoton,jkdet-enable = <1>;
+		nuvoton,jkdet-pull-enable = <1>;
+		nuvoton,jkdet-pull-up = <0>;
+		nuvoton,jkdet-polarity = <1>;
+		nuvoton,vref-impedance = <2>;
+		nuvoton,micbias-voltage = <6>;
+		nuvoton,sar-threshold-num = <4>;
+		nuvoton,sar-threshold = <0xa 0x14 0x26 0x73>;
+		nuvoton,sar-hysteresis = <0>;
+		nuvoton,sar-voltage = <6>;
+		nuvoton,sar-compare-time = <0>;
+		nuvoton,sar-sampling-time = <0>;
+		nuvoton,short-key-debounce = <3>;
+		nuvoton,jack-insert-debounce = <7>;
+		nuvoton,jack-eject-debounce = <7>;
+		clock-names = "mclk";
+		clocks = <&cru SCLK_I2S0_OUT>;
+	};
+};
+
+&i2c5 {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
+
+&pwm0 {
+	status = "okay";
+};
+
+&saradc {
+	vref-supply = <&vcc18_ldo1>;
+	status ="okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&uart4 {
+	status = "okay";
+};
+
+&tsadc {
+	rockchip,hw-tshut-mode = <1>; /* tshut mode 0:CRU 1:GPIO */
+	rockchip,hw-tshut-polarity = <1>; /* tshut polarity 0:LOW 1:HIGH */
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
+
+&usb_host0_ehci {
+	status = "okay";
+};
+
+&usb_host1 {
+	status = "okay";
+};
+
+&usb_otg {
+	status= "okay";
+};
+
+&vopb {
+	status = "okay";
+};
+
+&vopb_mmu {
+	status = "okay";
+};
+
+&vopl {
+	status = "okay";
+};
+
+&vopl_mmu {
+	status = "okay";
+};
+
+&pinctrl {
+	pcfg_pull_none_drv_8ma: pcfg-pull-none-drv-8ma {
+		drive-strength = <8>;
+	};
+
+	pcfg_pull_up_drv_8ma: pcfg-pull-up-drv-8ma {
+		bias-pull-up;
+		drive-strength = <8>;
+	};
+
+	backlight {
+		bl_en: bl-en {
+			rockchip,pins = <7 2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	buttons {
+		pwrbtn: pwrbtn {
+			rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	eth_phy {
+		eth_phy_pwr: eth-phy-pwr {
+			rockchip,pins = <0 6 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	pmic {
+		pmic_int: pmic-int {
+			rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	sdmmc {
+		/*
+		 * Default drive strength isn't enough to achieve even
+		 * high-speed mode on EVB board so bump up to 8ma.
+		 */
+		sdmmc_bus4: sdmmc-bus4 {
+			rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
+					<6 17 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
+					<6 18 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
+					<6 19 RK_FUNC_1 &pcfg_pull_up_drv_8ma>;
+		};
+
+		sdmmc_clk: sdmmc-clk {
+			rockchip,pins = <6 20 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+		};
+
+		sdmmc_cmd: sdmmc-cmd {
+			rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up_drv_8ma>;
+		};
+
+		sdmmc_pwr: sdmmc-pwr {
+			rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	usb {
+		host_vbus_drv: host-vbus-drv {
+			rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		pwr_3g: pwr-3g {
+			rockchip,pins = <7 8 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
diff --git a/arch/arm/dts/rk3288-popmetal.dts b/arch/arm/dts/rk3288-popmetal.dts
new file mode 100644
index 0000000..3f61a61
--- /dev/null
+++ b/arch/arm/dts/rk3288-popmetal.dts
@@ -0,0 +1,61 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+ X11
+ */
+
+/dts-v1/;
+#include "rk3288-popmetal.dtsi"
+
+/ {
+	model = "PopMetal-RK3288";
+	compatible = "chipspark,popmetal-rk3288", "rockchip,rk3288";
+
+	chosen {
+		stdout-path = &uart2;
+	};
+};
+
+&dmc {
+	rockchip,num-channels = <2>;
+	rockchip,pctl-timing = <0x29a 0xc8 0x1f8 0x42 0x4e 0x4 0xea 0xa
+		0x5 0x0 0xa 0x7 0x19 0x24 0xa 0x7
+		0x5 0xa 0x5 0x200 0x5 0x10 0x40 0x0
+		0x1 0x7 0x7 0x4 0xc 0x43 0x100 0x0
+		0x5 0x0>;
+	rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200
+		0xa60 0x40 0x10 0x0>;
+	/* Add a dummy value to cause of-platdata think this is bytes */
+	rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf 0xff>;
+	rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
+};
+
+
+&pinctrl {
+	u-boot,dm-pre-reloc;
+};
+
+&pwm1 {
+	status = "okay";
+};
+
+&uart2 {
+	u-boot,dm-pre-reloc;
+	reg-shift = <2>;
+};
+
+&sdmmc {
+	u-boot,dm-pre-reloc;
+};
+
+&emmc {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio3 {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio8 {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/rk3288-popmetal.dtsi b/arch/arm/dts/rk3288-popmetal.dtsi
new file mode 100644
index 0000000..f3bd468
--- /dev/null
+++ b/arch/arm/dts/rk3288-popmetal.dtsi
@@ -0,0 +1,520 @@
+/*
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *  Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "rk3288.dtsi"
+
+/ {
+	memory{
+		device_type = "memory";
+		reg = <0 0x80000000>;
+	};
+
+	ext_gmac: external-gmac-clock {
+		compatible = "fixed-clock";
+		clock-frequency = <125000000>;
+		clock-output-names = "ext_gmac";
+		#clock-cells = <0>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		autorepeat;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwrbtn>;
+
+		power {
+			gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
+			label = "GPIO Key Power";
+			linux,input-type = <1>;
+			wakeup-source;
+			debounce-interval = <100>;
+		};
+	};
+
+	io_domains: io-domains {
+		compatible = "rockchip,rk3288-io-voltage-domain";
+		rockchip,grf = <&grf>;
+
+		audio-supply = <&vcca_33>;
+		bb-supply = <&vcc_io>;
+		dvp-supply = <&vcc18_dvp>;
+		flash0-supply = <&vcc_flash>;
+		flash1-supply = <&vcc_lan>;
+		gpio30-supply = <&vcc_io>;
+		gpio1830-supply = <&vcc_io>;
+		lcdc-supply = <&vcc_io>;
+		sdcard-supply = <&vccio_sd>;
+		wifi-supply = <&vccio_wl>;
+	};
+
+	ir: ir-receiver {
+		compatible = "gpio-ir-receiver";
+		gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&ir_int>;
+	};
+
+	vcc_flash: flash-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_flash";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		vin-supply = <&vcc_io>;
+	};
+
+	vcc_sd: sdmmc-regulator {
+		compatible = "regulator-fixed";
+		gpio = <&gpio7 11 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdmmc_pwr>;
+		regulator-name = "vcc_sd";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		startup-delay-us = <100000>;
+		vin-supply = <&vcc_io>;
+	};
+
+	vcc_sys: vsys-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_sys";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	/*
+	 * A PT5128 creates both dovdd_1v8 and vcc28_dvp, controlled
+	 * by the dvp_pwr pin.
+	 */
+	vcc18_dvp: vcc18-dvp-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc18-dvp";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		vin-supply = <&vcc28_dvp>;
+	};
+
+	vcc28_dvp: vcc28-dvp-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio0 17 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&dvp_pwr>;
+		regulator-name = "vcc28_dvp";
+		regulator-min-microvolt = <2800000>;
+		regulator-max-microvolt = <2800000>;
+		regulator-always-on;
+		vin-supply = <&vcc_io>;
+	};
+};
+
+&cpu0 {
+	cpu0-supply = <&vdd_cpu>;
+};
+
+&emmc {
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	disable-wp;
+	non-removable;
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_pwr &emmc_bus8>;
+	vmmc-supply = <&vcc_io>;
+	vqmmc-supply = <&vcc_flash>;
+	status = "okay";
+};
+
+&sdmmc {
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	card-detect-delay = <200>;
+	disable-wp;
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>;
+	vmmc-supply = <&vcc_sd>;
+	vqmmc-supply = <&vccio_sd>;
+	status = "okay";
+};
+
+&gmac {
+	phy-supply = <&vcc_lan>;
+	phy-mode = "rgmii";
+	clock_in_out = "input";
+	snps,reset-gpio = <&gpio4 7 0>;
+	snps,reset-active-low;
+	snps,reset-delays-us = <0 10000 1000000>;
+	assigned-clocks = <&cru SCLK_MAC>;
+	assigned-clock-parents = <&ext_gmac>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>;
+	tx_delay = <0x30>;
+	rx_delay = <0x10>;
+	status = "ok";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c5>;
+	status = "okay";
+};
+
+&i2c0 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	rk808: pmic@1b {
+		compatible = "rockchip,rk808";
+		reg = <0x1b>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_int &global_pwroff>;
+		rockchip,system-power-controller;
+		wakeup-source;
+		#clock-cells = <1>;
+		clock-output-names = "xin32k", "rk808-clkout2";
+
+		vcc1-supply = <&vcc_sys>;
+		vcc2-supply = <&vcc_sys>;
+		vcc3-supply = <&vcc_sys>;
+		vcc4-supply = <&vcc_sys>;
+		vcc6-supply = <&vcc_sys>;
+		vcc7-supply = <&vcc_sys>;
+		vcc8-supply = <&vcc_18>;
+		vcc9-supply = <&vcc_io>;
+		vcc10-supply = <&vcc_io>;
+		vcc11-supply = <&vcc_sys>;
+		vcc12-supply = <&vcc_io>;
+		vddio-supply = <&vcc_io>;
+
+		regulators {
+			vdd_cpu: DCDC_REG1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-name = "vdd_arm";
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vdd_gpu: DCDC_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <1250000>;
+				regulator-name = "vdd_gpu";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1000000>;
+				};
+			};
+
+			vcc_ddr: DCDC_REG3 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vcc_ddr";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+				};
+			};
+
+			vcc_io: DCDC_REG4 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc_io";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3300000>;
+				};
+			};
+
+			vcc_lan: LDO_REG1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc_lan";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3300000>;
+				};
+			};
+
+			vccio_sd: LDO_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vccio_sd";
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vdd_10: LDO_REG3 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-name = "vdd_10";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1000000>;
+				};
+			};
+
+			vcc18_lcd: LDO_REG4 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc18_lcd";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			ldo5: LDO_REG5 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "ldo5";
+			};
+
+			vdd10_lcd: LDO_REG6 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-name = "vdd10_lcd";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1000000>;
+				};
+			};
+
+			vcc_18: LDO_REG7 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc_18";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			vcca_33: LDO_REG8 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcca_33";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3300000>;
+				};
+			};
+
+			vccio_wl: SWITCH_REG1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vccio_wl";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+				};
+			};
+
+			vcc_lcd: SWITCH_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vcc_lcd";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+				};
+			};
+		};
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	ak8963: ak8963@0d {
+		compatible = "asahi-kasei,ak8975";
+		reg = <0x0d>;
+		interrupt-parent = <&gpio8>;
+		interrupts = <1 IRQ_TYPE_EDGE_RISING>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&comp_int>;
+	};
+
+	l3g4200d: l3g4200d@68 {
+		compatible = "st,l3g4200d-gyro";
+		st,drdy-int-pin = <2>;
+		reg = <0x6b>;
+	};
+
+	mma8452: mma8452@1d {
+		compatible = "fsl,mma8452";
+		reg = <0x1d>;
+		interrupt-parent = <&gpio8>;
+		interrupts = <0 IRQ_TYPE_EDGE_RISING>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&gsensor_int>;
+	};
+};
+
+&i2c2 {
+	status = "okay";
+};
+
+&i2c3 {
+	status = "okay";
+};
+
+&i2c4 {
+	status = "okay";
+};
+
+&i2c5 {
+	status = "okay";
+};
+
+&pinctrl {
+	ak8963 {
+		comp_int: comp-int {
+			rockchip,pins = <8 1 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	buttons {
+		pwrbtn: pwrbtn {
+			rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	dvp {
+		dvp_pwr: dvp-pwr {
+			rockchip,pins = <0 17 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	ir {
+		ir_int: ir-int {
+			rockchip,pins = <0 6 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	mma8452 {
+		gsensor_int: gsensor-int {
+			rockchip,pins = <8 0 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	pmic {
+		pmic_int: pmic-int {
+			rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	sdmmc {
+		sdmmc_pwr: sdmmc-pwr {
+			rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&tsadc {
+	rockchip,hw-tshut-mode = <0>;
+	rockchip,hw-tshut-polarity = <0>;
+	status = "okay";
+};
+
+&vopb {
+	status = "okay";
+};
+
+&vopb_mmu {
+	status = "okay";
+};
+
+&vopl {
+	status = "okay";
+};
+
+&vopl_mmu {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&uart4 {
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3288-rock2-square.dts b/arch/arm/dts/rk3288-rock2-square.dts
index 34073c9..2c30355 100644
--- a/arch/arm/dts/rk3288-rock2-square.dts
+++ b/arch/arm/dts/rk3288-rock2-square.dts
@@ -192,7 +192,7 @@
 		0x5 0x0>;
 	rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200
 		0xa60 0x40 0x10 0x0>;
-	rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf>;
+	rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf 0xff>;
 	rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
 };
 
diff --git a/arch/arm/dts/rk3288-veyron.dtsi b/arch/arm/dts/rk3288-veyron.dtsi
index 421d212..d9d5187 100644
--- a/arch/arm/dts/rk3288-veyron.dtsi
+++ b/arch/arm/dts/rk3288-veyron.dtsi
@@ -253,7 +253,7 @@
 		0x5 0x0>;
 	rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200
 		0xa60 0x40 0x10 0x0>;
-	rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf>;
+	rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf 0xff>;
 	rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
 };
 
diff --git a/arch/arm/dts/rk3288.dtsi b/arch/arm/dts/rk3288.dtsi
index 3dab0fc..bcf051a 100644
--- a/arch/arm/dts/rk3288.dtsi
+++ b/arch/arm/dts/rk3288.dtsi
@@ -454,6 +454,7 @@
 		interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&cru HCLK_OTG0>;
 		clock-names = "otg";
+		dr_mode = "otg";
 		phys = <&usbphy0>;
 		phy-names = "usb2-phy";
 		status = "disabled";
diff --git a/arch/arm/dts/rk3399-evb.dts b/arch/arm/dts/rk3399-evb.dts
new file mode 100644
index 0000000..e92a492
--- /dev/null
+++ b/arch/arm/dts/rk3399-evb.dts
@@ -0,0 +1,108 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+/dts-v1/;
+#include <dt-bindings/pwm/pwm.h>
+#include "rk3399.dtsi"
+
+/ {
+	model = "Rockchip RK3399 Evaluation Board";
+	compatible = "rockchip,rk3399-evb", "rockchip,rk3399",
+		     "google,rk3399evb-rev2";
+
+	chosen {
+		stdout-path = &uart2;
+	};
+
+	vdd_center: vdd-center {
+		compatible = "pwm-regulator";
+		pwms = <&pwm3 0 25000 0>;
+		regulator-name = "vdd_center";
+		regulator-min-microvolt = <800000>;
+		regulator-max-microvolt = <1400000>;
+		regulator-always-on;
+		regulator-boot-on;
+		status = "okay";
+	};
+
+	vcc3v3_sys: vcc3v3-sys {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc3v3_sys";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	vcc_phy: vcc-phy-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_phy";
+		regulator-always-on;
+		regulator-boot-on;
+	};
+};
+
+&emmc_phy {
+	status = "okay";
+};
+
+&pwm0 {
+	status = "okay";
+};
+
+&pwm2 {
+	status = "okay";
+};
+
+&pwm3 {
+	status = "okay";
+};
+
+&sdmmc {
+	status = "okay";
+};
+
+&sdhci {
+	bus-width = <8>;
+	mmc-hs400-1_8v;
+	mmc-hs400-enhanced-strobe;
+	non-removable;
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&usb_host0_ehci {
+	status = "okay";
+};
+
+&usb_host0_ohci {
+	status = "okay";
+};
+
+&usb_host1_ehci {
+	status = "okay";
+};
+
+&usb_host1_ohci {
+	status = "okay";
+};
+
+&pinctrl {
+	pmic {
+		pmic_int_l: pmic-int-l {
+			rockchip,pins =
+				<1 21 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+
+		pmic_dvs2: pmic-dvs2 {
+			rockchip,pins =
+				<1 18 RK_FUNC_GPIO &pcfg_pull_down>;
+		};
+	};
+};
diff --git a/arch/arm/dts/rk3399.dtsi b/arch/arm/dts/rk3399.dtsi
new file mode 100644
index 0000000..a4c6e27
--- /dev/null
+++ b/arch/arm/dts/rk3399.dtsi
@@ -0,0 +1,1028 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <dt-bindings/clock/rk3399-cru.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+
+/ {
+	compatible = "rockchip,rk3399";
+
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+	};
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&cpu_l0>;
+				};
+				core1 {
+					cpu = <&cpu_l1>;
+				};
+				core2 {
+					cpu = <&cpu_l2>;
+				};
+				core3 {
+					cpu = <&cpu_l3>;
+				};
+			};
+
+			cluster1 {
+				core0 {
+					cpu = <&cpu_b0>;
+				};
+				core1 {
+					cpu = <&cpu_b1>;
+				};
+			};
+		};
+
+		cpu_l0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+			#cooling-cells = <2>; /* min followed by max */
+			clocks = <&cru ARMCLKL>;
+		};
+
+		cpu_l1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x1>;
+			enable-method = "psci";
+			clocks = <&cru ARMCLKL>;
+		};
+
+		cpu_l2: cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x2>;
+			enable-method = "psci";
+			clocks = <&cru ARMCLKL>;
+		};
+
+		cpu_l3: cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x3>;
+			enable-method = "psci";
+			clocks = <&cru ARMCLKL>;
+		};
+
+		cpu_b0: cpu@100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x0 0x100>;
+			enable-method = "psci";
+			#cooling-cells = <2>; /* min followed by max */
+			clocks = <&cru ARMCLKB>;
+		};
+
+		cpu_b1: cpu@101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x0 0x101>;
+			enable-method = "psci";
+			clocks = <&cru ARMCLKB>;
+		};
+	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+	};
+
+	xin24m: xin24m {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xin24m";
+		#clock-cells = <0>;
+	};
+
+	amba {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		dmac_bus: dma-controller@ff6d0000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x0 0xff6d0000 0x0 0x4000>;
+			interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			clocks = <&cru ACLK_DMAC0_PERILP>;
+			clock-names = "apb_pclk";
+		};
+
+		dmac_peri: dma-controller@ff6e0000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x0 0xff6e0000 0x0 0x4000>;
+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			clocks = <&cru ACLK_DMAC1_PERILP>;
+			clock-names = "apb_pclk";
+		};
+	};
+
+	sdio0: dwmmc@fe310000 {
+		compatible = "rockchip,rk3399-dw-mshc",
+			     "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xfe310000 0x0 0x4000>;
+		interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+		clock-freq-min-max = <400000 150000000>;
+		clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>,
+			 <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+		fifo-depth = <0x100>;
+		status = "disabled";
+	};
+
+	sdmmc: dwmmc@fe320000 {
+		compatible = "rockchip,rk3399-dw-mshc",
+			     "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xfe320000 0x0 0x4000>;
+		interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+		clock-freq-min-max = <400000 150000000>;
+		clocks = <&cru SCLK_SDMMC>, <&cru HCLK_SDMMC>,
+			 <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
+		clock-names = "ciu", "biu", "ciu-drive", "ciu-sample";
+		fifo-depth = <0x100>;
+		status = "disabled";
+	};
+
+	sdhci: sdhci@fe330000 {
+		compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1";
+		reg = <0x0 0xfe330000 0x0 0x10000>;
+		interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+		assigned-clocks = <&cru SCLK_EMMC>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&cru SCLK_EMMC>, <&cru ACLK_EMMC>;
+		clock-names = "clk_xin", "clk_ahb";
+		phys = <&emmc_phy>;
+		phy-names = "phy_arasan";
+		status = "disabled";
+	};
+
+	usb_host0_ehci: usb@fe380000 {
+		compatible = "generic-ehci";
+		reg = <0x0 0xfe380000 0x0 0x20000>;
+		interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>;
+		clock-names = "hclk_host0", "hclk_host0_arb";
+		status = "disabled";
+	};
+
+	usb_host0_ohci: usb@fe3a0000 {
+		compatible = "generic-ohci";
+		reg = <0x0 0xfe3a0000 0x0 0x20000>;
+		interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>;
+		clock-names = "hclk_host0", "hclk_host0_arb";
+		status = "disabled";
+	};
+
+	usb_host1_ehci: usb@fe3c0000 {
+		compatible = "generic-ehci";
+		reg = <0x0 0xfe3c0000 0x0 0x20000>;
+		interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>;
+		clock-names = "hclk_host1", "hclk_host1_arb";
+		status = "disabled";
+	};
+
+	usb_host1_ohci: usb@fe3e0000 {
+		compatible = "generic-ohci";
+		reg = <0x0 0xfe3e0000 0x0 0x20000>;
+		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>;
+		clock-names = "hclk_host1", "hclk_host1_arb";
+		status = "disabled";
+	};
+
+	gic: interrupt-controller@fee00000 {
+		compatible = "arm,gic-v3";
+		#interrupt-cells = <3>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		interrupt-controller;
+
+		reg = <0x0 0xfee00000 0 0x10000>, /* GICD */
+		      <0x0 0xfef00000 0 0xc0000>, /* GICR */
+		      <0x0 0xfff00000 0 0x10000>, /* GICC */
+		      <0x0 0xfff10000 0 0x10000>, /* GICH */
+		      <0x0 0xfff20000 0 0x10000>; /* GICV */
+		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+		its: interrupt-controller@fee20000 {
+			compatible = "arm,gic-v3-its";
+			msi-controller;
+			reg = <0x0 0xfee20000 0x0 0x20000>;
+		};
+	};
+
+	uart0: serial@ff180000 {
+		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff180000 0x0 0x100>;
+		clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart0_xfer>;
+		status = "disabled";
+	};
+
+	uart1: serial@ff190000 {
+		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff190000 0x0 0x100>;
+		clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart1_xfer>;
+		status = "disabled";
+	};
+
+	uart2: serial@ff1a0000 {
+		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff1a0000 0x0 0x100>;
+		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+		clock-frequency = <24000000>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart2c_xfer>;
+		status = "disabled";
+	};
+
+	uart3: serial@ff1b0000 {
+		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff1b0000 0x0 0x100>;
+		clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart3_xfer>;
+		status = "disabled";
+	};
+
+	spi0: spi@ff1c0000 {
+		compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff1c0000 0x0 0x1000>;
+		clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi0_clk &spi0_tx &spi0_rx &spi0_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi1: spi@ff1d0000 {
+		compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff1d0000 0x0 0x1000>;
+		clocks = <&cru SCLK_SPI1>, <&cru PCLK_SPI1>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi1_clk &spi1_tx &spi1_rx &spi1_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi2: spi@ff1e0000 {
+		compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff1e0000 0x0 0x1000>;
+		clocks = <&cru SCLK_SPI2>, <&cru PCLK_SPI2>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi2_clk &spi2_tx &spi2_rx &spi2_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi4: spi@ff1f0000 {
+		compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff1f0000 0x0 0x1000>;
+		clocks = <&cru SCLK_SPI4>, <&cru PCLK_SPI4>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi4_clk &spi4_tx &spi4_rx &spi4_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi5: spi@ff200000 {
+		compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff200000 0x0 0x1000>;
+		clocks = <&cru SCLK_SPI5>, <&cru PCLK_SPI5>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi5_clk &spi5_tx &spi5_rx &spi5_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	pmugrf: syscon@ff320000 {
+		compatible = "rockchip,rk3399-pmugrf", "syscon", "simple-mfd";
+		reg = <0x0 0xff320000 0x0 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		pmu_io_domains: io-domains {
+			compatible = "rockchip,rk3399-pmu-io-voltage-domain";
+			status = "disabled";
+		};
+	};
+
+	spi3: spi@ff350000 {
+		compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff350000 0x0 0x1000>;
+		clocks = <&pmucru SCLK_SPI3_PMU>, <&pmucru PCLK_SPI3_PMU>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi3_clk &spi3_tx &spi3_rx &spi3_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	uart4: serial@ff370000 {
+		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff370000 0x0 0x100>;
+		clocks = <&pmucru SCLK_UART4_PMU>, <&pmucru PCLK_UART4_PMU>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart4_xfer>;
+		status = "disabled";
+	};
+
+	pwm0: pwm@ff420000 {
+		compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm";
+		reg = <0x0 0xff420000 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm0_pin>;
+		clocks = <&pmucru PCLK_RKPWM_PMU>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	pwm1: pwm@ff420010 {
+		compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm";
+		reg = <0x0 0xff420010 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm1_pin>;
+		clocks = <&pmucru PCLK_RKPWM_PMU>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	pwm2: pwm@ff420020 {
+		compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm";
+		reg = <0x0 0xff420020 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm2_pin>;
+		clocks = <&pmucru PCLK_RKPWM_PMU>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	pwm3: pwm@ff420030 {
+		compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm";
+		reg = <0x0 0xff420030 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm3a_pin>;
+		clocks = <&pmucru PCLK_RKPWM_PMU>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	pmucru: pmu-clock-controller@ff750000 {
+		compatible = "rockchip,rk3399-pmucru";
+		reg = <0x0 0xff750000 0x0 0x1000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+		assigned-clocks = <&pmucru PLL_PPLL>;
+		assigned-clock-rates = <676000000>;
+	};
+
+	cru: clock-controller@ff760000 {
+		compatible = "rockchip,rk3399-cru";
+		reg = <0x0 0xff760000 0x0 0x1000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+		assigned-clocks =
+			<&cru PLL_GPLL>, <&cru PLL_CPLL>,
+			<&cru PLL_NPLL>,
+			<&cru ACLK_PERIHP>, <&cru HCLK_PERIHP>,
+			<&cru PCLK_PERIHP>,
+			<&cru ACLK_PERILP0>, <&cru HCLK_PERILP0>,
+			<&cru PCLK_PERILP0>,
+			<&cru HCLK_PERILP1>, <&cru PCLK_PERILP1>;
+		assigned-clock-rates =
+			 <594000000>,  <800000000>,
+			<1000000000>,
+			 <150000000>,   <75000000>,
+			  <37500000>,
+			 <100000000>,  <100000000>,
+			  <50000000>,
+			 <100000000>,   <50000000>;
+	};
+
+	grf: syscon@ff770000 {
+		compatible = "rockchip,rk3399-grf", "syscon", "simple-mfd";
+		reg = <0x0 0xff770000 0x0 0x10000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		io_domains: io-domains {
+			compatible = "rockchip,rk3399-io-voltage-domain";
+			status = "disabled";
+		};
+
+		emmc_phy: phy@f780 {
+			compatible = "rockchip,rk3399-emmc-phy";
+			reg = <0xf780 0x24>;
+			#phy-cells = <0>;
+			status = "disabled";
+		};
+	};
+
+	watchdog@ff840000 {
+		compatible = "snps,dw-wdt";
+		reg = <0x0 0xff840000 0x0 0x100>;
+		clocks = <&cru PCLK_WDT>;
+		interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	spdif: spdif@ff870000 {
+		compatible = "rockchip,rk3399-spdif";
+		reg = <0x0 0xff870000 0x0 0x1000>;
+		interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+		dmas = <&dmac_bus 7>;
+		dma-names = "tx";
+		clock-names = "mclk", "hclk";
+		clocks = <&cru SCLK_SPDIF_8CH>, <&cru HCLK_SPDIF>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spdif_bus>;
+		status = "disabled";
+	};
+
+	i2s0: i2s@ff880000 {
+		compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s";
+		reg = <0x0 0xff880000 0x0 0x1000>;
+		rockchip,grf = <&grf>;
+		interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+		dmas = <&dmac_bus 0>, <&dmac_bus 1>;
+		dma-names = "tx", "rx";
+		clock-names = "i2s_clk", "i2s_hclk";
+		clocks = <&cru SCLK_I2S0_8CH>, <&cru HCLK_I2S0_8CH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s0_8ch_bus>;
+		status = "disabled";
+	};
+
+	i2s1: i2s@ff890000 {
+		compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s";
+		reg = <0x0 0xff890000 0x0 0x1000>;
+		interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+		dmas = <&dmac_bus 2>, <&dmac_bus 3>;
+		dma-names = "tx", "rx";
+		clock-names = "i2s_clk", "i2s_hclk";
+		clocks = <&cru SCLK_I2S1_8CH>, <&cru HCLK_I2S1_8CH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s1_2ch_bus>;
+		status = "disabled";
+	};
+
+	i2s2: i2s@ff8a0000 {
+		compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s";
+		reg = <0x0 0xff8a0000 0x0 0x1000>;
+		interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+		dmas = <&dmac_bus 4>, <&dmac_bus 5>;
+		dma-names = "tx", "rx";
+		clock-names = "i2s_clk", "i2s_hclk";
+		clocks = <&cru SCLK_I2S2_8CH>, <&cru HCLK_I2S2_8CH>;
+		status = "disabled";
+	};
+
+	pinctrl: pinctrl {
+		compatible = "rockchip,rk3399-pinctrl";
+		rockchip,grf = <&grf>;
+		rockchip,pmu = <&pmugrf>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gpio0: gpio0@ff720000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff720000 0x0 0x100>;
+			clocks = <&pmucru PCLK_GPIO0_PMU>;
+			interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		gpio1: gpio1@ff730000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff730000 0x0 0x100>;
+			clocks = <&pmucru PCLK_GPIO1_PMU>;
+			interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		gpio2: gpio2@ff780000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff780000 0x0 0x100>;
+			clocks = <&cru PCLK_GPIO2>;
+			interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		gpio3: gpio3@ff788000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff788000 0x0 0x100>;
+			clocks = <&cru PCLK_GPIO3>;
+			interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		gpio4: gpio4@ff790000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff790000 0x0 0x100>;
+			clocks = <&cru PCLK_GPIO4>;
+			interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		pcfg_pull_up: pcfg-pull-up {
+			bias-pull-up;
+		};
+
+		pcfg_pull_down: pcfg-pull-down {
+			bias-pull-down;
+		};
+
+		pcfg_pull_none: pcfg-pull-none {
+			bias-disable;
+		};
+
+		pcfg_pull_none_12ma: pcfg-pull-none-12ma {
+			bias-disable;
+			drive-strength = <12>;
+		};
+
+		pcfg_pull_up_8ma: pcfg-pull-up-8ma {
+			bias-pull-up;
+			drive-strength = <8>;
+		};
+
+		pcfg_pull_down_4ma: pcfg-pull-down-4ma {
+			bias-pull-down;
+			drive-strength = <4>;
+		};
+
+		pcfg_pull_up_2ma: pcfg-pull-up-2ma {
+			bias-pull-up;
+			drive-strength = <2>;
+		};
+
+		pcfg_pull_down_12ma: pcfg-pull-down-12ma {
+			bias-pull-down;
+			drive-strength = <12>;
+		};
+
+		pcfg_pull_none_13ma: pcfg-pull-none-13ma {
+			bias-disable;
+			drive-strength = <13>;
+		};
+
+		i2c0 {
+			i2c0_xfer: i2c0-xfer {
+				rockchip,pins =
+					<1 15 RK_FUNC_2 &pcfg_pull_none>,
+					<1 16 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		i2c1 {
+			i2c1_xfer: i2c1-xfer {
+				rockchip,pins =
+					<4 2 RK_FUNC_1 &pcfg_pull_none>,
+					<4 1 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c2 {
+			i2c2_xfer: i2c2-xfer {
+				rockchip,pins =
+					<2 1 RK_FUNC_2 &pcfg_pull_none_12ma>,
+					<2 0 RK_FUNC_2 &pcfg_pull_none_12ma>;
+			};
+		};
+
+		i2c3 {
+			i2c3_xfer: i2c3-xfer {
+				rockchip,pins =
+					<4 17 RK_FUNC_1 &pcfg_pull_none>,
+					<4 16 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c4 {
+			i2c4_xfer: i2c4-xfer {
+				rockchip,pins =
+					<1 12 RK_FUNC_1 &pcfg_pull_none>,
+					<1 11 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c5 {
+			i2c5_xfer: i2c5-xfer {
+				rockchip,pins =
+					<3 11 RK_FUNC_2 &pcfg_pull_none>,
+					<3 10 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		i2c6 {
+			i2c6_xfer: i2c6-xfer {
+				rockchip,pins =
+					<2 10 RK_FUNC_2 &pcfg_pull_none>,
+					<2 9 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		i2c7 {
+			i2c7_xfer: i2c7-xfer {
+				rockchip,pins =
+					<2 8 RK_FUNC_2 &pcfg_pull_none>,
+					<2 7 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		i2c8 {
+			i2c8_xfer: i2c8-xfer {
+				rockchip,pins =
+					<1 21 RK_FUNC_1 &pcfg_pull_none>,
+					<1 20 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2s0 {
+			i2s0_8ch_bus: i2s0-8ch-bus {
+				rockchip,pins =
+					<3 24 RK_FUNC_1 &pcfg_pull_none>,
+					<3 25 RK_FUNC_1 &pcfg_pull_none>,
+					<3 26 RK_FUNC_1 &pcfg_pull_none>,
+					<3 27 RK_FUNC_1 &pcfg_pull_none>,
+					<3 28 RK_FUNC_1 &pcfg_pull_none>,
+					<3 29 RK_FUNC_1 &pcfg_pull_none>,
+					<3 30 RK_FUNC_1 &pcfg_pull_none>,
+					<3 31 RK_FUNC_1 &pcfg_pull_none>,
+					<4 0 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2s1 {
+			i2s1_2ch_bus: i2s1-2ch-bus {
+				rockchip,pins =
+					<4 3 RK_FUNC_1 &pcfg_pull_none>,
+					<4 4 RK_FUNC_1 &pcfg_pull_none>,
+					<4 5 RK_FUNC_1 &pcfg_pull_none>,
+					<4 6 RK_FUNC_1 &pcfg_pull_none>,
+					<4 7 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		spdif {
+			spdif_bus: spdif-bus {
+				rockchip,pins =
+					<4 21 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		spi0 {
+			spi0_clk: spi0-clk {
+				rockchip,pins =
+					<3 6 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi0_cs0: spi0-cs0 {
+				rockchip,pins =
+					<3 7 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi0_cs1: spi0-cs1 {
+				rockchip,pins =
+					<3 8 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi0_tx: spi0-tx {
+				rockchip,pins =
+					<3 5 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi0_rx: spi0-rx {
+				rockchip,pins =
+					<3 4 RK_FUNC_2 &pcfg_pull_up>;
+			};
+		};
+
+		spi1 {
+			spi1_clk: spi1-clk {
+				rockchip,pins =
+					<1 9 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi1_cs0: spi1-cs0 {
+				rockchip,pins =
+					<1 10 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi1_rx: spi1-rx {
+				rockchip,pins =
+					<1 7 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi1_tx: spi1-tx {
+				rockchip,pins =
+					<1 8 RK_FUNC_2 &pcfg_pull_up>;
+			};
+		};
+
+		spi2 {
+			spi2_clk: spi2-clk {
+				rockchip,pins =
+					<2 11 RK_FUNC_1 &pcfg_pull_up>;
+			};
+			spi2_cs0: spi2-cs0 {
+				rockchip,pins =
+					<2 12 RK_FUNC_1 &pcfg_pull_up>;
+			};
+			spi2_rx: spi2-rx {
+				rockchip,pins =
+					<2 9 RK_FUNC_1 &pcfg_pull_up>;
+			};
+			spi2_tx: spi2-tx {
+				rockchip,pins =
+					<2 10 RK_FUNC_1 &pcfg_pull_up>;
+			};
+		};
+
+		spi3 {
+			spi3_clk: spi3-clk {
+				rockchip,pins =
+					<1 17 RK_FUNC_1 &pcfg_pull_up>;
+			};
+			spi3_cs0: spi3-cs0 {
+				rockchip,pins =
+					<1 18 RK_FUNC_1 &pcfg_pull_up>;
+			};
+			spi3_rx: spi3-rx {
+				rockchip,pins =
+					<1 15 RK_FUNC_1 &pcfg_pull_up>;
+			};
+			spi3_tx: spi3-tx {
+				rockchip,pins =
+					<1 16 RK_FUNC_1 &pcfg_pull_up>;
+			};
+		};
+
+		spi4 {
+			spi4_clk: spi4-clk {
+				rockchip,pins =
+					<3 2 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi4_cs0: spi4-cs0 {
+				rockchip,pins =
+					<3 3 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi4_rx: spi4-rx {
+				rockchip,pins =
+					<3 0 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi4_tx: spi4-tx {
+				rockchip,pins =
+					<3 1 RK_FUNC_2 &pcfg_pull_up>;
+			};
+		};
+
+		spi5 {
+			spi5_clk: spi5-clk {
+				rockchip,pins =
+					<2 22 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi5_cs0: spi5-cs0 {
+				rockchip,pins =
+					<2 23 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi5_rx: spi5-rx {
+				rockchip,pins =
+					<2 20 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi5_tx: spi5-tx {
+				rockchip,pins =
+					<2 21 RK_FUNC_2 &pcfg_pull_up>;
+			};
+		};
+
+		uart0 {
+			uart0_xfer: uart0-xfer {
+				rockchip,pins =
+					<2 16 RK_FUNC_1 &pcfg_pull_up>,
+					<2 17 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart0_cts: uart0-cts {
+				rockchip,pins =
+					<2 18 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart0_rts: uart0-rts {
+				rockchip,pins =
+					<2 19 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		uart1 {
+			uart1_xfer: uart1-xfer {
+				rockchip,pins =
+					<3 12 RK_FUNC_2 &pcfg_pull_up>,
+					<3 13 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		uart2a {
+			uart2a_xfer: uart2a-xfer {
+				rockchip,pins =
+					<4 8 RK_FUNC_2 &pcfg_pull_up>,
+					<4 9 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		uart2b {
+			uart2b_xfer: uart2b-xfer {
+				rockchip,pins =
+					<4 16 RK_FUNC_2 &pcfg_pull_up>,
+					<4 17 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		uart2c {
+			uart2c_xfer: uart2c-xfer {
+				rockchip,pins =
+					<4 19 RK_FUNC_1 &pcfg_pull_up>,
+					<4 20 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		uart3 {
+			uart3_xfer: uart3-xfer {
+				rockchip,pins =
+					<3 14 RK_FUNC_2 &pcfg_pull_up>,
+					<3 15 RK_FUNC_2 &pcfg_pull_none>;
+			};
+
+			uart3_cts: uart3-cts {
+				rockchip,pins =
+					<3 18 RK_FUNC_2 &pcfg_pull_none>;
+			};
+
+			uart3_rts: uart3-rts {
+				rockchip,pins =
+					<3 19 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		uart4 {
+			uart4_xfer: uart4-xfer {
+				rockchip,pins =
+					<1 7 RK_FUNC_1 &pcfg_pull_up>,
+					<1 8 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		uarthdcp {
+			uarthdcp_xfer: uarthdcp-xfer {
+				rockchip,pins =
+					<4 21 RK_FUNC_2 &pcfg_pull_up>,
+					<4 22 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		pwm0 {
+			pwm0_pin: pwm0-pin {
+				rockchip,pins =
+					<4 18 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			vop0_pwm_pin: vop0-pwm-pin {
+				rockchip,pins =
+					<4 18 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		pwm1 {
+			pwm1_pin: pwm1-pin {
+				rockchip,pins =
+					<4 22 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			vop1_pwm_pin: vop1-pwm-pin {
+				rockchip,pins =
+					<4 18 RK_FUNC_3 &pcfg_pull_none>;
+			};
+		};
+
+		pwm2 {
+			pwm2_pin: pwm2-pin {
+				rockchip,pins =
+					<1 19 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm3a {
+			pwm3a_pin: pwm3a-pin {
+				rockchip,pins =
+					<0 6 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm3b {
+			pwm3b_pin: pwm3b-pin {
+				rockchip,pins =
+					<1 14 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/sama5d2-pinfunc.h b/arch/arm/dts/sama5d2-pinfunc.h
new file mode 100644
index 0000000..b0c912f
--- /dev/null
+++ b/arch/arm/dts/sama5d2-pinfunc.h
@@ -0,0 +1,880 @@
+#define PINMUX_PIN(no, func, ioset) \
+(((no) & 0xffff) | (((func) & 0xf) << 16) | (((ioset) & 0xff) << 20))
+
+#define PIN_PA0				0
+#define PIN_PA0__GPIO			PINMUX_PIN(PIN_PA0, 0, 0)
+#define PIN_PA0__SDMMC0_CK		PINMUX_PIN(PIN_PA0, 1, 1)
+#define PIN_PA0__QSPI0_SCK		PINMUX_PIN(PIN_PA0, 2, 1)
+#define PIN_PA0__D0			PINMUX_PIN(PIN_PA0, 6, 2)
+#define PIN_PA1				1
+#define PIN_PA1__GPIO			PINMUX_PIN(PIN_PA1, 0, 0)
+#define PIN_PA1__SDMMC0_CMD		PINMUX_PIN(PIN_PA1, 1, 1)
+#define PIN_PA1__QSPI0_CS		PINMUX_PIN(PIN_PA1, 2, 1)
+#define PIN_PA1__D1			PINMUX_PIN(PIN_PA1, 6, 2)
+#define PIN_PA2				2
+#define PIN_PA2__GPIO			PINMUX_PIN(PIN_PA2, 0, 0)
+#define PIN_PA2__SDMMC0_DAT0		PINMUX_PIN(PIN_PA2, 1, 1)
+#define PIN_PA2__QSPI0_IO0		PINMUX_PIN(PIN_PA2, 2, 1)
+#define PIN_PA2__D2			PINMUX_PIN(PIN_PA2, 6, 2)
+#define PIN_PA3				3
+#define PIN_PA3__GPIO			PINMUX_PIN(PIN_PA3, 0, 0)
+#define PIN_PA3__SDMMC0_DAT1		PINMUX_PIN(PIN_PA3, 1, 1)
+#define PIN_PA3__QSPI0_IO1		PINMUX_PIN(PIN_PA3, 2, 1)
+#define PIN_PA3__D3			PINMUX_PIN(PIN_PA3, 6, 2)
+#define PIN_PA4				4
+#define PIN_PA4__GPIO			PINMUX_PIN(PIN_PA4, 0, 0)
+#define PIN_PA4__SDMMC0_DAT2		PINMUX_PIN(PIN_PA4, 1, 1)
+#define PIN_PA4__QSPI0_IO2		PINMUX_PIN(PIN_PA4, 2, 1)
+#define PIN_PA4__D4			PINMUX_PIN(PIN_PA4, 6, 2)
+#define PIN_PA5				5
+#define PIN_PA5__GPIO			PINMUX_PIN(PIN_PA5, 0, 0)
+#define PIN_PA5__SDMMC0_DAT3		PINMUX_PIN(PIN_PA5, 1, 1)
+#define PIN_PA5__QSPI0_IO3		PINMUX_PIN(PIN_PA5, 2, 1)
+#define PIN_PA5__D5			PINMUX_PIN(PIN_PA5, 6, 2)
+#define PIN_PA6				6
+#define PIN_PA6__GPIO			PINMUX_PIN(PIN_PA6, 0, 0)
+#define PIN_PA6__SDMMC0_DAT4		PINMUX_PIN(PIN_PA6, 1, 1)
+#define PIN_PA6__QSPI1_SCK		PINMUX_PIN(PIN_PA6, 2, 1)
+#define PIN_PA6__TIOA5			PINMUX_PIN(PIN_PA6, 4, 1)
+#define PIN_PA6__FLEXCOM2_IO0		PINMUX_PIN(PIN_PA6, 5, 1)
+#define PIN_PA6__D6			PINMUX_PIN(PIN_PA6, 6, 2)
+#define PIN_PA7				7
+#define PIN_PA7__GPIO			PINMUX_PIN(PIN_PA7, 0, 0)
+#define PIN_PA7__SDMMC0_DAT5		PINMUX_PIN(PIN_PA7, 1, 1)
+#define PIN_PA7__QSPI1_IO0		PINMUX_PIN(PIN_PA7, 2, 1)
+#define PIN_PA7__TIOB5			PINMUX_PIN(PIN_PA7, 4, 1)
+#define PIN_PA7__FLEXCOM2_IO1		PINMUX_PIN(PIN_PA7, 5, 1)
+#define PIN_PA7__D7			PINMUX_PIN(PIN_PA7, 6, 2)
+#define PIN_PA8				8
+#define PIN_PA8__GPIO			PINMUX_PIN(PIN_PA8, 0, 0)
+#define PIN_PA8__SDMMC0_DAT6		PINMUX_PIN(PIN_PA8, 1, 1)
+#define PIN_PA8__QSPI1_IO1		PINMUX_PIN(PIN_PA8, 2, 1)
+#define PIN_PA8__TCLK5			PINMUX_PIN(PIN_PA8, 4, 1)
+#define PIN_PA8__FLEXCOM2_IO2		PINMUX_PIN(PIN_PA8, 5, 1)
+#define PIN_PA8__NWE_NANDWE		PINMUX_PIN(PIN_PA8, 6, 2)
+#define PIN_PA9				9
+#define PIN_PA9__GPIO			PINMUX_PIN(PIN_PA9, 0, 0)
+#define PIN_PA9__SDMMC0_DAT7		PINMUX_PIN(PIN_PA9, 1, 1)
+#define PIN_PA9__QSPI1_IO2		PINMUX_PIN(PIN_PA9, 2, 1)
+#define PIN_PA9__TIOA4			PINMUX_PIN(PIN_PA9, 4, 1)
+#define PIN_PA9__FLEXCOM2_IO3		PINMUX_PIN(PIN_PA9, 5, 1)
+#define PIN_PA9__NCS3			PINMUX_PIN(PIN_PA9, 6, 2)
+#define PIN_PA10			10
+#define PIN_PA10__GPIO			PINMUX_PIN(PIN_PA10, 0, 0)
+#define PIN_PA10__SDMMC0_RSTN		PINMUX_PIN(PIN_PA10, 1, 1)
+#define PIN_PA10__QSPI1_IO3		PINMUX_PIN(PIN_PA10, 2, 1)
+#define PIN_PA10__TIOB4			PINMUX_PIN(PIN_PA10, 4, 1)
+#define PIN_PA10__FLEXCOM2_IO4		PINMUX_PIN(PIN_PA10, 5, 1)
+#define PIN_PA10__A21_NANDALE		PINMUX_PIN(PIN_PA10, 6, 2)
+#define PIN_PA11			11
+#define PIN_PA11__GPIO			PINMUX_PIN(PIN_PA11, 0, 0)
+#define PIN_PA11__SDMMC0_VDDSEL		PINMUX_PIN(PIN_PA11, 1, 1)
+#define PIN_PA11__QSPI1_CS		PINMUX_PIN(PIN_PA11, 2, 1)
+#define PIN_PA11__TCLK4			PINMUX_PIN(PIN_PA11, 4, 1)
+#define PIN_PA11__A22_NANDCLE		PINMUX_PIN(PIN_PA11, 6, 2)
+#define PIN_PA12			12
+#define PIN_PA12__GPIO			PINMUX_PIN(PIN_PA12, 0, 0)
+#define PIN_PA12__SDMMC0_WP		PINMUX_PIN(PIN_PA12, 1, 1)
+#define PIN_PA12__IRQ			PINMUX_PIN(PIN_PA12, 2, 1)
+#define PIN_PA12__NRD_NANDOE		PINMUX_PIN(PIN_PA12, 6, 2)
+#define PIN_PA13			13
+#define PIN_PA13__GPIO			PINMUX_PIN(PIN_PA13, 0, 0)
+#define PIN_PA13__SDMMC0_CD		PINMUX_PIN(PIN_PA13, 1, 1)
+#define PIN_PA13__FLEXCOM3_IO1		PINMUX_PIN(PIN_PA13, 5, 1)
+#define PIN_PA13__D8			PINMUX_PIN(PIN_PA13, 6, 2)
+#define PIN_PA14			14
+#define PIN_PA14__GPIO			PINMUX_PIN(PIN_PA14, 0, 0)
+#define PIN_PA14__SPI0_SPCK		PINMUX_PIN(PIN_PA14, 1, 1)
+#define PIN_PA14__TK1			PINMUX_PIN(PIN_PA14, 2, 1)
+#define PIN_PA14__QSPI0_SCK		PINMUX_PIN(PIN_PA14, 3, 2)
+#define PIN_PA14__I2SC1_MCK		PINMUX_PIN(PIN_PA14, 4, 2)
+#define PIN_PA14__FLEXCOM3_IO2		PINMUX_PIN(PIN_PA14, 5, 1)
+#define PIN_PA14__D9			PINMUX_PIN(PIN_PA14, 6, 2)
+#define PIN_PA15			15
+#define PIN_PA15__GPIO			PINMUX_PIN(PIN_PA15, 0, 0)
+#define PIN_PA15__SPI0_MOSI		PINMUX_PIN(PIN_PA15, 1, 1)
+#define PIN_PA15__TF1			PINMUX_PIN(PIN_PA15, 2, 1)
+#define PIN_PA15__QSPI0_CS		PINMUX_PIN(PIN_PA15, 3, 2)
+#define PIN_PA15__I2SC1_CK		PINMUX_PIN(PIN_PA15, 4, 2)
+#define PIN_PA15__FLEXCOM3_IO0		PINMUX_PIN(PIN_PA15, 5, 1)
+#define PIN_PA15__D10			PINMUX_PIN(PIN_PA15, 6, 2)
+#define PIN_PA16			16
+#define PIN_PA16__GPIO			PINMUX_PIN(PIN_PA16, 0, 0)
+#define PIN_PA16__SPI0_MISO		PINMUX_PIN(PIN_PA16, 1, 1)
+#define PIN_PA16__TD1			PINMUX_PIN(PIN_PA16, 2, 1)
+#define PIN_PA16__QSPI0_IO0		PINMUX_PIN(PIN_PA16, 3, 2)
+#define PIN_PA16__I2SC1_WS		PINMUX_PIN(PIN_PA16, 4, 2)
+#define PIN_PA16__FLEXCOM3_IO3		PINMUX_PIN(PIN_PA16, 5, 1)
+#define PIN_PA16__D11			PINMUX_PIN(PIN_PA16, 6, 2)
+#define PIN_PA17			17
+#define PIN_PA17__GPIO			PINMUX_PIN(PIN_PA17, 0, 0)
+#define PIN_PA17__SPI0_NPCS0		PINMUX_PIN(PIN_PA17, 1, 1)
+#define PIN_PA17__RD1			PINMUX_PIN(PIN_PA17, 2, 1)
+#define PIN_PA17__QSPI0_IO1		PINMUX_PIN(PIN_PA17, 3, 2)
+#define PIN_PA17__I2SC1_DI0		PINMUX_PIN(PIN_PA17, 4, 2)
+#define PIN_PA17__FLEXCOM3_IO4		PINMUX_PIN(PIN_PA17, 5, 1)
+#define PIN_PA17__D12			PINMUX_PIN(PIN_PA17, 6, 2)
+#define PIN_PA18			18
+#define PIN_PA18__GPIO			PINMUX_PIN(PIN_PA18, 0, 0)
+#define PIN_PA18__SPI0_NPCS1		PINMUX_PIN(PIN_PA18, 1, 1)
+#define PIN_PA18__RK1			PINMUX_PIN(PIN_PA18, 2, 1)
+#define PIN_PA18__QSPI0_IO2		PINMUX_PIN(PIN_PA18, 3, 2)
+#define PIN_PA18__I2SC1_DO0		PINMUX_PIN(PIN_PA18, 4, 2)
+#define PIN_PA18__SDMMC1_DAT0		PINMUX_PIN(PIN_PA18, 5, 1)
+#define PIN_PA18__D13			PINMUX_PIN(PIN_PA18, 6, 2)
+#define PIN_PA19			19
+#define PIN_PA19__GPIO			PINMUX_PIN(PIN_PA19, 0, 0)
+#define PIN_PA19__SPI0_NPCS2		PINMUX_PIN(PIN_PA19, 1, 1)
+#define PIN_PA19__RF1			PINMUX_PIN(PIN_PA19, 2, 1)
+#define PIN_PA19__QSPI0_IO3		PINMUX_PIN(PIN_PA19, 3, 2)
+#define PIN_PA19__TIOA0			PINMUX_PIN(PIN_PA19, 4, 1)
+#define PIN_PA19__SDMMC1_DAT1		PINMUX_PIN(PIN_PA19, 5, 1)
+#define PIN_PA19__D14			PINMUX_PIN(PIN_PA19, 6, 2)
+#define PIN_PA20			20
+#define PIN_PA20__GPIO			PINMUX_PIN(PIN_PA20, 0, 0)
+#define PIN_PA20__SPI0_NPCS3		PINMUX_PIN(PIN_PA20, 1, 1)
+#define PIN_PA20__TIOB0			PINMUX_PIN(PIN_PA20, 4, 1)
+#define PIN_PA20__SDMMC1_DAT2		PINMUX_PIN(PIN_PA20, 5, 1)
+#define PIN_PA20__D15			PINMUX_PIN(PIN_PA20, 6, 2)
+#define PIN_PA21			21
+#define PIN_PA21__GPIO			PINMUX_PIN(PIN_PA21, 0, 0)
+#define PIN_PA21__IRQ			PINMUX_PIN(PIN_PA21, 1, 2)
+#define PIN_PA21__PCK2			PINMUX_PIN(PIN_PA21, 2, 3)
+#define PIN_PA21__TCLK0			PINMUX_PIN(PIN_PA21, 4, 1)
+#define PIN_PA21__SDMMC1_DAT3		PINMUX_PIN(PIN_PA21, 5, 1)
+#define PIN_PA21__NANDRDY		PINMUX_PIN(PIN_PA21, 6, 2)
+#define PIN_PA22			22
+#define PIN_PA22__GPIO			PINMUX_PIN(PIN_PA22, 0, 0)
+#define PIN_PA22__FLEXCOM1_IO2		PINMUX_PIN(PIN_PA22, 1, 1)
+#define PIN_PA22__D0			PINMUX_PIN(PIN_PA22, 2, 1)
+#define PIN_PA22__TCK			PINMUX_PIN(PIN_PA22, 3, 4)
+#define PIN_PA22__SPI1_SPCK		PINMUX_PIN(PIN_PA22, 4, 2)
+#define PIN_PA22__SDMMC1_CK		PINMUX_PIN(PIN_PA22, 5, 1)
+#define PIN_PA22__QSPI0_SCK		PINMUX_PIN(PIN_PA22, 6, 3)
+#define PIN_PA23			23
+#define PIN_PA23__GPIO			PINMUX_PIN(PIN_PA23, 0, 0)
+#define PIN_PA23__FLEXCOM1_IO1		PINMUX_PIN(PIN_PA23, 1, 1)
+#define PIN_PA23__D1			PINMUX_PIN(PIN_PA23, 2, 1)
+#define PIN_PA23__TDI			PINMUX_PIN(PIN_PA23, 3, 4)
+#define PIN_PA23__SPI1_MOSI		PINMUX_PIN(PIN_PA23, 4, 2)
+#define PIN_PA23__QSPI0_CS		PINMUX_PIN(PIN_PA23, 6, 3)
+#define PIN_PA24			24
+#define PIN_PA24__GPIO			PINMUX_PIN(PIN_PA24, 0, 0)
+#define PIN_PA24__FLEXCOM1_IO0		PINMUX_PIN(PIN_PA24, 1, 1)
+#define PIN_PA24__D2			PINMUX_PIN(PIN_PA24, 2, 1)
+#define PIN_PA24__TDO			PINMUX_PIN(PIN_PA24, 3, 4)
+#define PIN_PA24__SPI1_MISO		PINMUX_PIN(PIN_PA24, 4, 2)
+#define PIN_PA24__QSPI0_IO0		PINMUX_PIN(PIN_PA24, 6, 3)
+#define PIN_PA25			25
+#define PIN_PA25__GPIO			PINMUX_PIN(PIN_PA25, 0, 0)
+#define PIN_PA25__FLEXCOM1_IO3		PINMUX_PIN(PIN_PA25, 1, 1)
+#define PIN_PA25__D3			PINMUX_PIN(PIN_PA25, 2, 1)
+#define PIN_PA25__TMS			PINMUX_PIN(PIN_PA25, 3, 4)
+#define PIN_PA25__SPI1_NPCS0		PINMUX_PIN(PIN_PA25, 4, 2)
+#define PIN_PA25__QSPI0_IO1		PINMUX_PIN(PIN_PA25, 6, 3)
+#define PIN_PA26			26
+#define PIN_PA26__GPIO			PINMUX_PIN(PIN_PA26, 0, 0)
+#define PIN_PA26__FLEXCOM1_IO4		PINMUX_PIN(PIN_PA26, 1, 1)
+#define PIN_PA26__D4			PINMUX_PIN(PIN_PA26, 2, 1)
+#define PIN_PA26__NTRST			PINMUX_PIN(PIN_PA26, 3, 4)
+#define PIN_PA26__SPI1_NPCS1		PINMUX_PIN(PIN_PA26, 4, 2)
+#define PIN_PA26__QSPI0_IO2		PINMUX_PIN(PIN_PA26, 6, 3)
+#define PIN_PA27			27
+#define PIN_PA27__GPIO			PINMUX_PIN(PIN_PA27, 0, 0)
+#define PIN_PA27__TIOA1			PINMUX_PIN(PIN_PA27, 1, 2)
+#define PIN_PA27__D5			PINMUX_PIN(PIN_PA27, 2, 1)
+#define PIN_PA27__SPI0_NPCS2		PINMUX_PIN(PIN_PA27, 3, 2)
+#define PIN_PA27__SPI1_NPCS2		PINMUX_PIN(PIN_PA27, 4, 2)
+#define PIN_PA27__SDMMC1_RSTN		PINMUX_PIN(PIN_PA27, 5, 1)
+#define PIN_PA27__QSPI0_IO3		PINMUX_PIN(PIN_PA27, 6, 3)
+#define PIN_PA28			28
+#define PIN_PA28__GPIO			PINMUX_PIN(PIN_PA28, 0, 0)
+#define PIN_PA28__TIOB1			PINMUX_PIN(PIN_PA28, 1, 2)
+#define PIN_PA28__D6			PINMUX_PIN(PIN_PA28, 2, 1)
+#define PIN_PA28__SPI0_NPCS3		PINMUX_PIN(PIN_PA28, 3, 2)
+#define PIN_PA28__SPI1_NPCS3		PINMUX_PIN(PIN_PA28, 4, 2)
+#define PIN_PA28__SDMMC1_CMD		PINMUX_PIN(PIN_PA28, 5, 1)
+#define PIN_PA28__CLASSD_L0		PINMUX_PIN(PIN_PA28, 6, 1)
+#define PIN_PA29			29
+#define PIN_PA29__GPIO			PINMUX_PIN(PIN_PA29, 0, 0)
+#define PIN_PA29__TCLK1			PINMUX_PIN(PIN_PA29, 1, 2)
+#define PIN_PA29__D7			PINMUX_PIN(PIN_PA29, 2, 1)
+#define PIN_PA29__SPI0_NPCS1		PINMUX_PIN(PIN_PA29, 3, 2)
+#define PIN_PA29__SDMMC1_WP		PINMUX_PIN(PIN_PA29, 5, 1)
+#define PIN_PA29__CLASSD_L1		PINMUX_PIN(PIN_PA29, 6, 1)
+#define PIN_PA30			30
+#define PIN_PA30__GPIO			PINMUX_PIN(PIN_PA30, 0, 0)
+#define PIN_PA30__NWE_NANDWE		PINMUX_PIN(PIN_PA30, 2, 1)
+#define PIN_PA30__SPI0_NPCS0		PINMUX_PIN(PIN_PA30, 3, 2)
+#define PIN_PA30__PWMH0			PINMUX_PIN(PIN_PA30, 4, 1)
+#define PIN_PA30__SDMMC1_CD		PINMUX_PIN(PIN_PA30, 5, 1)
+#define PIN_PA30__CLASSD_L2		PINMUX_PIN(PIN_PA30, 6, 1)
+#define PIN_PA31			31
+#define PIN_PA31__GPIO			PINMUX_PIN(PIN_PA31, 0, 0)
+#define PIN_PA31__NCS3			PINMUX_PIN(PIN_PA31, 2, 1)
+#define PIN_PA31__SPI0_MISO		PINMUX_PIN(PIN_PA31, 3, 2)
+#define PIN_PA31__PWML0			PINMUX_PIN(PIN_PA31, 4, 1)
+#define PIN_PA31__CLASSD_L3		PINMUX_PIN(PIN_PA31, 6, 1)
+#define PIN_PB0				32
+#define PIN_PB0__GPIO			PINMUX_PIN(PIN_PB0, 0, 0)
+#define PIN_PB0__A21_NANDALE		PINMUX_PIN(PIN_PB0, 2, 1)
+#define PIN_PB0__SPI0_MOSI		PINMUX_PIN(PIN_PB0, 3, 2)
+#define PIN_PB0__PWMH1			PINMUX_PIN(PIN_PB0, 4, 1)
+#define PIN_PB1				33
+#define PIN_PB1__GPIO			PINMUX_PIN(PIN_PB1, 0, 0)
+#define PIN_PB1__A22_NANDCLE		PINMUX_PIN(PIN_PB1, 2, 1)
+#define PIN_PB1__SPI0_SPCK		PINMUX_PIN(PIN_PB1, 3, 2)
+#define PIN_PB1__PWML1			PINMUX_PIN(PIN_PB1, 4, 1)
+#define PIN_PB1__CLASSD_R0		PINMUX_PIN(PIN_PB1, 6, 1)
+#define PIN_PB2				34
+#define PIN_PB2__GPIO			PINMUX_PIN(PIN_PB2, 0, 0)
+#define PIN_PB2__NRD_NANDOE		PINMUX_PIN(PIN_PB2, 2, 1)
+#define PIN_PB2__PWMFI0			PINMUX_PIN(PIN_PB2, 4, 1)
+#define PIN_PB2__CLASSD_R1		PINMUX_PIN(PIN_PB2, 6, 1)
+#define PIN_PB3				35
+#define PIN_PB3__GPIO			PINMUX_PIN(PIN_PB3, 0, 0)
+#define PIN_PB3__URXD4			PINMUX_PIN(PIN_PB3, 1, 1)
+#define PIN_PB3__D8			PINMUX_PIN(PIN_PB3, 2, 1)
+#define PIN_PB3__IRQ			PINMUX_PIN(PIN_PB3, 3, 3)
+#define PIN_PB3__PWMEXTRG0		PINMUX_PIN(PIN_PB3, 4, 1)
+#define PIN_PB3__CLASSD_R2		PINMUX_PIN(PIN_PB3, 6, 1)
+#define PIN_PB4				36
+#define PIN_PB4__GPIO			PINMUX_PIN(PIN_PB4, 0, 0)
+#define PIN_PB4__UTXD4			PINMUX_PIN(PIN_PB4, 1, 1)
+#define PIN_PB4__D9			PINMUX_PIN(PIN_PB4, 2, 1)
+#define PIN_PB4__FIQ			PINMUX_PIN(PIN_PB4, 3, 4)
+#define PIN_PB4__CLASSD_R3		PINMUX_PIN(PIN_PB4, 6, 1)
+#define PIN_PB5				37
+#define PIN_PB5__GPIO			PINMUX_PIN(PIN_PB5, 0, 0)
+#define PIN_PB5__TCLK2			PINMUX_PIN(PIN_PB5, 1, 1)
+#define PIN_PB5__D10			PINMUX_PIN(PIN_PB5, 2, 1)
+#define PIN_PB5__PWMH2			PINMUX_PIN(PIN_PB5, 3, 1)
+#define PIN_PB5__QSPI1_SCK		PINMUX_PIN(PIN_PB5, 4, 2)
+#define PIN_PB5__GTSUCOMP		PINMUX_PIN(PIN_PB5, 6, 3)
+#define PIN_PB6				38
+#define PIN_PB6__GPIO			PINMUX_PIN(PIN_PB6, 0, 0)
+#define PIN_PB6__TIOA2			PINMUX_PIN(PIN_PB6, 1, 1)
+#define PIN_PB6__D11			PINMUX_PIN(PIN_PB6, 2, 1)
+#define PIN_PB6__PWML2			PINMUX_PIN(PIN_PB6, 3, 1)
+#define PIN_PB6__QSPI1_CS		PINMUX_PIN(PIN_PB6, 4, 2)
+#define PIN_PB6__GTXER			PINMUX_PIN(PIN_PB6, 6, 3)
+#define PIN_PB7				39
+#define PIN_PB7__GPIO			PINMUX_PIN(PIN_PB7, 0, 0)
+#define PIN_PB7__TIOB2			PINMUX_PIN(PIN_PB7, 1, 1)
+#define PIN_PB7__D12			PINMUX_PIN(PIN_PB7, 2, 1)
+#define PIN_PB7__PWMH3			PINMUX_PIN(PIN_PB7, 3, 1)
+#define PIN_PB7__QSPI1_IO0		PINMUX_PIN(PIN_PB7, 4, 2)
+#define PIN_PB7__GRXCK			PINMUX_PIN(PIN_PB7, 6, 3)
+#define PIN_PB8				40
+#define PIN_PB8__GPIO			PINMUX_PIN(PIN_PB8, 0, 0)
+#define PIN_PB8__TCLK3			PINMUX_PIN(PIN_PB8, 1, 1)
+#define PIN_PB8__D13			PINMUX_PIN(PIN_PB8, 2, 1)
+#define PIN_PB8__PWML3			PINMUX_PIN(PIN_PB8, 3, 1)
+#define PIN_PB8__QSPI1_IO1		PINMUX_PIN(PIN_PB8, 4, 2)
+#define PIN_PB8__GCRS			PINMUX_PIN(PIN_PB8, 6, 3)
+#define PIN_PB9				41
+#define PIN_PB9__GPIO			PINMUX_PIN(PIN_PB9, 0, 0)
+#define PIN_PB9__TIOA3			PINMUX_PIN(PIN_PB9, 1, 1)
+#define PIN_PB9__D14			PINMUX_PIN(PIN_PB9, 2, 1)
+#define PIN_PB9__PWMFI1			PINMUX_PIN(PIN_PB9, 3, 1)
+#define PIN_PB9__QSPI1_IO2		PINMUX_PIN(PIN_PB9, 4, 2)
+#define PIN_PB9__GCOL			PINMUX_PIN(PIN_PB9, 6, 3)
+#define PIN_PB10			42
+#define PIN_PB10__GPIO			PINMUX_PIN(PIN_PB10, 0, 0)
+#define PIN_PB10__TIOB3			PINMUX_PIN(PIN_PB10, 1, 1)
+#define PIN_PB10__D15			PINMUX_PIN(PIN_PB10, 2, 1)
+#define PIN_PB10__PWMEXTRG1		PINMUX_PIN(PIN_PB10, 3, 1)
+#define PIN_PB10__QSPI1_IO3		PINMUX_PIN(PIN_PB10, 4, 2)
+#define PIN_PB10__GRX2			PINMUX_PIN(PIN_PB10, 6, 3)
+#define PIN_PB11			43
+#define PIN_PB11__GPIO			PINMUX_PIN(PIN_PB11, 0, 0)
+#define PIN_PB11__LCDDAT0		PINMUX_PIN(PIN_PB11, 1, 1)
+#define PIN_PB11__A0_NBS0		PINMUX_PIN(PIN_PB11, 2, 1)
+#define PIN_PB11__URXD3			PINMUX_PIN(PIN_PB11, 3, 3)
+#define PIN_PB11__PDMIC_DAT		PINMUX_PIN(PIN_PB11, 4, 2)
+#define PIN_PB11__GRX3			PINMUX_PIN(PIN_PB11, 6, 3)
+#define PIN_PB12			44
+#define PIN_PB12__GPIO			PINMUX_PIN(PIN_PB12, 0, 0)
+#define PIN_PB12__LCDDAT1		PINMUX_PIN(PIN_PB12, 1, 1)
+#define PIN_PB12__A1			PINMUX_PIN(PIN_PB12, 2, 1)
+#define PIN_PB12__UTXD3			PINMUX_PIN(PIN_PB12, 3, 3)
+#define PIN_PB12__PDMIC_CLK		PINMUX_PIN(PIN_PB12, 4, 2)
+#define PIN_PB12__GTX2			PINMUX_PIN(PIN_PB12, 6, 3)
+#define PIN_PB13			45
+#define PIN_PB13__GPIO			PINMUX_PIN(PIN_PB13, 0, 0)
+#define PIN_PB13__LCDDAT2		PINMUX_PIN(PIN_PB13, 1, 1)
+#define PIN_PB13__A2			PINMUX_PIN(PIN_PB13, 2, 1)
+#define PIN_PB13__PCK1			PINMUX_PIN(PIN_PB13, 3, 3)
+#define PIN_PB13__GTX3			PINMUX_PIN(PIN_PB13, 6, 3)
+#define PIN_PB14			46
+#define PIN_PB14__GPIO			PINMUX_PIN(PIN_PB14, 0, 0)
+#define PIN_PB14__LCDDAT3		PINMUX_PIN(PIN_PB14, 1, 1)
+#define PIN_PB14__A3			PINMUX_PIN(PIN_PB14, 2, 1)
+#define PIN_PB14__TK1			PINMUX_PIN(PIN_PB14, 3, 2)
+#define PIN_PB14__I2SC1_MCK		PINMUX_PIN(PIN_PB14, 4, 1)
+#define PIN_PB14__QSPI1_SCK		PINMUX_PIN(PIN_PB14, 5, 3)
+#define PIN_PB14__GTXCK			PINMUX_PIN(PIN_PB14, 6, 3)
+#define PIN_PB15			47
+#define PIN_PB15__GPIO			PINMUX_PIN(PIN_PB15, 0, 0)
+#define PIN_PB15__LCDDAT4		PINMUX_PIN(PIN_PB15, 1, 1)
+#define PIN_PB15__A4			PINMUX_PIN(PIN_PB15, 2, 1)
+#define PIN_PB15__TF1			PINMUX_PIN(PIN_PB15, 3, 2)
+#define PIN_PB15__I2SC1_CK		PINMUX_PIN(PIN_PB15, 4, 1)
+#define PIN_PB15__QSPI1_CS		PINMUX_PIN(PIN_PB15, 5, 3)
+#define PIN_PB15__GTXEN			PINMUX_PIN(PIN_PB15, 6, 3)
+#define PIN_PB16			48
+#define PIN_PB16__GPIO			PINMUX_PIN(PIN_PB16, 0, 0)
+#define PIN_PB16__LCDDAT5		PINMUX_PIN(PIN_PB16, 1, 1)
+#define PIN_PB16__A5			PINMUX_PIN(PIN_PB16, 2, 1)
+#define PIN_PB16__TD1			PINMUX_PIN(PIN_PB16, 3, 2)
+#define PIN_PB16__I2SC1_WS		PINMUX_PIN(PIN_PB16, 4, 1)
+#define PIN_PB16__QSPI1_IO0		PINMUX_PIN(PIN_PB16, 5, 3)
+#define PIN_PB16__GRXDV			PINMUX_PIN(PIN_PB16, 6, 3)
+#define PIN_PB17			49
+#define PIN_PB17__GPIO			PINMUX_PIN(PIN_PB17, 0, 0)
+#define PIN_PB17__LCDDAT6		PINMUX_PIN(PIN_PB17, 1, 1)
+#define PIN_PB17__A6			PINMUX_PIN(PIN_PB17, 2, 1)
+#define PIN_PB17__RD1			PINMUX_PIN(PIN_PB17, 3, 2)
+#define PIN_PB17__I2SC1_DI0		PINMUX_PIN(PIN_PB17, 4, 1)
+#define PIN_PB17__QSPI1_IO1		PINMUX_PIN(PIN_PB17, 5, 3)
+#define PIN_PB17__GRXER			PINMUX_PIN(PIN_PB17, 6, 3)
+#define PIN_PB18			50
+#define PIN_PB18__GPIO			PINMUX_PIN(PIN_PB18, 0, 0)
+#define PIN_PB18__LCDDAT7		PINMUX_PIN(PIN_PB18, 1, 1)
+#define PIN_PB18__A7			PINMUX_PIN(PIN_PB18, 2, 1)
+#define PIN_PB18__RK1			PINMUX_PIN(PIN_PB18, 3, 2)
+#define PIN_PB18__I2SC1_DO0		PINMUX_PIN(PIN_PB18, 4, 1)
+#define PIN_PB18__QSPI1_IO2		PINMUX_PIN(PIN_PB18, 5, 3)
+#define PIN_PB18__GRX0			PINMUX_PIN(PIN_PB18, 6, 3)
+#define PIN_PB19			51
+#define PIN_PB19__GPIO			PINMUX_PIN(PIN_PB19, 0, 0)
+#define PIN_PB19__LCDDAT8		PINMUX_PIN(PIN_PB19, 1, 1)
+#define PIN_PB19__A8			PINMUX_PIN(PIN_PB19, 2, 1)
+#define PIN_PB19__RF1			PINMUX_PIN(PIN_PB19, 3, 2)
+#define PIN_PB19__TIOA3			PINMUX_PIN(PIN_PB19, 4, 2)
+#define PIN_PB19__QSPI1_IO3		PINMUX_PIN(PIN_PB19, 5, 3)
+#define PIN_PB19__GRX1			PINMUX_PIN(PIN_PB19, 6, 3)
+#define PIN_PB20			52
+#define PIN_PB20__GPIO			PINMUX_PIN(PIN_PB20, 0, 0)
+#define PIN_PB20__LCDDAT9		PINMUX_PIN(PIN_PB20, 1, 1)
+#define PIN_PB20__A9			PINMUX_PIN(PIN_PB20, 2, 1)
+#define PIN_PB20__TK0			PINMUX_PIN(PIN_PB20, 3, 1)
+#define PIN_PB20__TIOB3			PINMUX_PIN(PIN_PB20, 4, 2)
+#define PIN_PB20__PCK1			PINMUX_PIN(PIN_PB20, 5, 4)
+#define PIN_PB20__GTX0			PINMUX_PIN(PIN_PB20, 6, 3)
+#define PIN_PB21			53
+#define PIN_PB21__GPIO			PINMUX_PIN(PIN_PB21, 0, 0)
+#define PIN_PB21__LCDDAT10		PINMUX_PIN(PIN_PB21, 1, 1)
+#define PIN_PB21__A10			PINMUX_PIN(PIN_PB21, 2, 1)
+#define PIN_PB21__TF0			PINMUX_PIN(PIN_PB21, 3, 1)
+#define PIN_PB21__TCLK3			PINMUX_PIN(PIN_PB21, 4, 2)
+#define PIN_PB21__FLEXCOM3_IO2		PINMUX_PIN(PIN_PB21, 5, 3)
+#define PIN_PB21__GTX1			PINMUX_PIN(PIN_PB21, 6, 3)
+#define PIN_PB22			54
+#define PIN_PB22__GPIO			PINMUX_PIN(PIN_PB22, 0, 0)
+#define PIN_PB22__LCDDAT11		PINMUX_PIN(PIN_PB22, 1, 1)
+#define PIN_PB22__A11			PINMUX_PIN(PIN_PB22, 2, 1)
+#define PIN_PB22__TDO			PINMUX_PIN(PIN_PB22, 3, 1)
+#define PIN_PB22__TIOA2			PINMUX_PIN(PIN_PB22, 4, 2)
+#define PIN_PB22__FLEXCOM3_IO1		PINMUX_PIN(PIN_PB22, 5, 3)
+#define PIN_PB22__GMDC			PINMUX_PIN(PIN_PB22, 6, 3)
+#define PIN_PB23			55
+#define PIN_PB23__GPIO			PINMUX_PIN(PIN_PB23, 0, 0)
+#define PIN_PB23__LCDDAT12		PINMUX_PIN(PIN_PB23, 1, 1)
+#define PIN_PB23__A12			PINMUX_PIN(PIN_PB23, 2, 1)
+#define PIN_PB23__RD0			PINMUX_PIN(PIN_PB23, 3, 1)
+#define PIN_PB23__TIOB2			PINMUX_PIN(PIN_PB23, 4, 2)
+#define PIN_PB23__FLEXCOM3_IO0		PINMUX_PIN(PIN_PB23, 5, 3)
+#define PIN_PB23__GMDIO			PINMUX_PIN(PIN_PB23, 6, 3)
+#define PIN_PB24			56
+#define PIN_PB24__GPIO			PINMUX_PIN(PIN_PB24, 0, 0)
+#define PIN_PB24__LCDDAT13		PINMUX_PIN(PIN_PB24, 1, 1)
+#define PIN_PB24__A13			PINMUX_PIN(PIN_PB24, 2, 1)
+#define PIN_PB24__RK0			PINMUX_PIN(PIN_PB24, 3, 1)
+#define PIN_PB24__TCLK2			PINMUX_PIN(PIN_PB24, 4, 2)
+#define PIN_PB24__FLEXCOM3_IO3		PINMUX_PIN(PIN_PB24, 5, 3)
+#define PIN_PB24__ISC_D10		PINMUX_PIN(PIN_PB24, 6, 3)
+#define PIN_PB25			57
+#define PIN_PB25__GPIO			PINMUX_PIN(PIN_PB25, 0, 0)
+#define PIN_PB25__LCDDAT14		PINMUX_PIN(PIN_PB25, 1, 1)
+#define PIN_PB25__A14			PINMUX_PIN(PIN_PB25, 2, 1)
+#define PIN_PB25__RF0			PINMUX_PIN(PIN_PB25, 3, 1)
+#define PIN_PB25__FLEXCOM3_IO4		PINMUX_PIN(PIN_PB25, 5, 3)
+#define PIN_PB25__ISC_D11		PINMUX_PIN(PIN_PB25, 6, 3)
+#define PIN_PB26			58
+#define PIN_PB26__GPIO			PINMUX_PIN(PIN_PB26, 0, 0)
+#define PIN_PB26__LCDDAT15		PINMUX_PIN(PIN_PB26, 1, 1)
+#define PIN_PB26__A15			PINMUX_PIN(PIN_PB26, 2, 1)
+#define PIN_PB26__URXD0			PINMUX_PIN(PIN_PB26, 3, 1)
+#define PIN_PB26__PDMIC_DAT		PINMUX_PIN(PIN_PB26, 4, 1)
+#define PIN_PB26__ISC_D0		PINMUX_PIN(PIN_PB26, 6, 3)
+#define PIN_PB27			59
+#define PIN_PB27__GPIO			PINMUX_PIN(PIN_PB27, 0, 0)
+#define PIN_PB27__LCDDAT16		PINMUX_PIN(PIN_PB27, 1, 1)
+#define PIN_PB27__A16			PINMUX_PIN(PIN_PB27, 2, 1)
+#define PIN_PB27__UTXD0			PINMUX_PIN(PIN_PB27, 3, 1)
+#define PIN_PB27__PDMIC_CLK		PINMUX_PIN(PIN_PB27, 4, 1)
+#define PIN_PB27__ISC_D1		PINMUX_PIN(PIN_PB27, 6, 3)
+#define PIN_PB28			60
+#define PIN_PB28__GPIO			PINMUX_PIN(PIN_PB28, 0, 0)
+#define PIN_PB28__LCDDAT17		PINMUX_PIN(PIN_PB28, 1, 1)
+#define PIN_PB28__A17			PINMUX_PIN(PIN_PB28, 2, 1)
+#define PIN_PB28__FLEXCOM0_IO0		PINMUX_PIN(PIN_PB28, 3, 1)
+#define PIN_PB28__TIOA5			PINMUX_PIN(PIN_PB28, 4, 2)
+#define PIN_PB28__ISC_D2		PINMUX_PIN(PIN_PB28, 6, 3)
+#define PIN_PB29			61
+#define PIN_PB29__GPIO			PINMUX_PIN(PIN_PB29, 0, 0)
+#define PIN_PB29__LCDDAT18		PINMUX_PIN(PIN_PB29, 1, 1)
+#define PIN_PB29__A18			PINMUX_PIN(PIN_PB29, 2, 1)
+#define PIN_PB29__FLEXCOM0_IO1		PINMUX_PIN(PIN_PB29, 3, 1)
+#define PIN_PB29__TIOB5			PINMUX_PIN(PIN_PB29, 4, 2)
+#define PIN_PB29__ISC_D3		PINMUX_PIN(PIN_PB29, 7, 3)
+#define PIN_PB30			62
+#define PIN_PB30__GPIO			PINMUX_PIN(PIN_PB30, 0, 0)
+#define PIN_PB30__LCDDAT19		PINMUX_PIN(PIN_PB30, 1, 1)
+#define PIN_PB30__A19			PINMUX_PIN(PIN_PB30, 2, 1)
+#define PIN_PB30__FLEXCOM0_IO2		PINMUX_PIN(PIN_PB30, 3, 1)
+#define PIN_PB30__TCLK5			PINMUX_PIN(PIN_PB30, 4, 2)
+#define PIN_PB30__ISC_D4		PINMUX_PIN(PIN_PB30, 6, 3)
+#define PIN_PB31			63
+#define PIN_PB31__GPIO			PINMUX_PIN(PIN_PB31, 0, 0)
+#define PIN_PB31__LCDDAT20		PINMUX_PIN(PIN_PB31, 1, 1)
+#define PIN_PB31__A20			PINMUX_PIN(PIN_PB31, 2, 1)
+#define PIN_PB31__FLEXCOM0_IO3		PINMUX_PIN(PIN_PB31, 3, 1)
+#define PIN_PB31__TWD0			PINMUX_PIN(PIN_PB31, 4, 1)
+#define PIN_PB31__ISC_D5		PINMUX_PIN(PIN_PB31, 6, 3)
+#define PIN_PC0				64
+#define PIN_PC0__GPIO			PINMUX_PIN(PIN_PC0, 0, 0)
+#define PIN_PC0__LCDDAT21		PINMUX_PIN(PIN_PC0, 1, 1)
+#define PIN_PC0__A23			PINMUX_PIN(PIN_PC0, 2, 1)
+#define PIN_PC0__FLEXCOM0_IO4		PINMUX_PIN(PIN_PC0, 3, 1)
+#define PIN_PC0__TWCK0			PINMUX_PIN(PIN_PC0, 4, 1)
+#define PIN_PC0__ISC_D6			PINMUX_PIN(PIN_PC0, 6, 3)
+#define PIN_PC1				65
+#define PIN_PC1__GPIO			PINMUX_PIN(PIN_PC1, 0, 0)
+#define PIN_PC1__LCDDAT22		PINMUX_PIN(PIN_PC1, 1, 1)
+#define PIN_PC1__A24			PINMUX_PIN(PIN_PC1, 2, 1)
+#define PIN_PC1__CANTX0			PINMUX_PIN(PIN_PC1, 3, 1)
+#define PIN_PC1__SPI1_SPCK		PINMUX_PIN(PIN_PC1, 4, 1)
+#define PIN_PC1__I2SC0_CK		PINMUX_PIN(PIN_PC1, 5, 1)
+#define PIN_PC1__ISC_D7			PINMUX_PIN(PIN_PC1, 6, 3)
+#define PIN_PC2				66
+#define PIN_PC2__GPIO			PINMUX_PIN(PIN_PC2, 0, 0)
+#define PIN_PC2__LCDDAT23		PINMUX_PIN(PIN_PC2, 1, 1)
+#define PIN_PC2__A25			PINMUX_PIN(PIN_PC2, 2, 1)
+#define PIN_PC2__CANRX0			PINMUX_PIN(PIN_PC2, 3, 1)
+#define PIN_PC2__SPI1_MOSI		PINMUX_PIN(PIN_PC2, 4, 1)
+#define PIN_PC2__I2SC0_MCK		PINMUX_PIN(PIN_PC2, 5, 1)
+#define PIN_PC2__ISC_D8			PINMUX_PIN(PIN_PC2, 6, 3)
+#define PIN_PC3				67
+#define PIN_PC3__GPIO			PINMUX_PIN(PIN_PC3, 0, 0)
+#define PIN_PC3__LCDPWM			PINMUX_PIN(PIN_PC3, 1, 1)
+#define PIN_PC3__NWAIT			PINMUX_PIN(PIN_PC3, 2, 1)
+#define PIN_PC3__TIOA1			PINMUX_PIN(PIN_PC3, 3, 1)
+#define PIN_PC3__SPI1_MISO		PINMUX_PIN(PIN_PC3, 4, 1)
+#define PIN_PC3__I2SC0_WS		PINMUX_PIN(PIN_PC3, 5, 1)
+#define PIN_PC3__ISC_D9			PINMUX_PIN(PIN_PC3, 6, 3)
+#define PIN_PC4				68
+#define PIN_PC4__GPIO			PINMUX_PIN(PIN_PC4, 0, 0)
+#define PIN_PC4__LCDDISP		PINMUX_PIN(PIN_PC4, 1, 1)
+#define PIN_PC4__NWR1_NBS1		PINMUX_PIN(PIN_PC4, 2, 1)
+#define PIN_PC4__TIOB1			PINMUX_PIN(PIN_PC4, 3, 1)
+#define PIN_PC4__SPI1_NPCS0		PINMUX_PIN(PIN_PC4, 4, 1)
+#define PIN_PC4__I2SC0_DI0		PINMUX_PIN(PIN_PC4, 5, 1)
+#define PIN_PC4__ISC_PCK		PINMUX_PIN(PIN_PC4, 6, 3)
+#define PIN_PC5				69
+#define PIN_PC5__GPIO			PINMUX_PIN(PIN_PC5, 0, 0)
+#define PIN_PC5__LCDVSYNC		PINMUX_PIN(PIN_PC5, 1, 1)
+#define PIN_PC5__NCS0			PINMUX_PIN(PIN_PC5, 2, 1)
+#define PIN_PC5__TCLK1			PINMUX_PIN(PIN_PC5, 3, 1)
+#define PIN_PC5__SPI1_NPCS1		PINMUX_PIN(PIN_PC5, 4, 1)
+#define PIN_PC5__I2SC0_DO0		PINMUX_PIN(PIN_PC5, 5, 1)
+#define PIN_PC5__ISC_VSYNC		PINMUX_PIN(PIN_PC5, 6, 3)
+#define PIN_PC6				70
+#define PIN_PC6__GPIO			PINMUX_PIN(PIN_PC6, 0, 0)
+#define PIN_PC6__LCDHSYNC		PINMUX_PIN(PIN_PC6, 1, 1)
+#define PIN_PC6__NCS1			PINMUX_PIN(PIN_PC6, 2, 1)
+#define PIN_PC6__TWD1			PINMUX_PIN(PIN_PC6, 3, 1)
+#define PIN_PC6__SPI1_NPCS2		PINMUX_PIN(PIN_PC6, 4, 1)
+#define PIN_PC6__ISC_HSYNC		PINMUX_PIN(PIN_PC6, 6, 3)
+#define PIN_PC7				71
+#define PIN_PC7__GPIO			PINMUX_PIN(PIN_PC7, 0, 0)
+#define PIN_PC7__LCDPCK			PINMUX_PIN(PIN_PC7, 1, 1)
+#define PIN_PC7__NCS2			PINMUX_PIN(PIN_PC7, 2, 1)
+#define PIN_PC7__TWCK1			PINMUX_PIN(PIN_PC7, 3, 1)
+#define PIN_PC7__SPI1_NPCS3		PINMUX_PIN(PIN_PC7, 4, 1)
+#define PIN_PC7__URXD1			PINMUX_PIN(PIN_PC7, 5, 2)
+#define PIN_PC7__ISC_MCK		PINMUX_PIN(PIN_PC7, 6, 3)
+#define PIN_PC8				72
+#define PIN_PC8__GPIO			PINMUX_PIN(PIN_PC8, 0, 0)
+#define PIN_PC8__LCDDEN			PINMUX_PIN(PIN_PC8, 1, 1)
+#define PIN_PC8__NANDRDY		PINMUX_PIN(PIN_PC8, 2, 1)
+#define PIN_PC8__FIQ			PINMUX_PIN(PIN_PC8, 3, 1)
+#define PIN_PC8__PCK0			PINMUX_PIN(PIN_PC8, 4, 3)
+#define PIN_PC8__UTXD1			PINMUX_PIN(PIN_PC8, 5, 2)
+#define PIN_PC8__ISC_FIELD		PINMUX_PIN(PIN_PC8, 6, 3)
+#define PIN_PC9				73
+#define PIN_PC9__GPIO			PINMUX_PIN(PIN_PC9, 0, 0)
+#define PIN_PC9__FIQ			PINMUX_PIN(PIN_PC9, 1, 3)
+#define PIN_PC9__GTSUCOMP		PINMUX_PIN(PIN_PC9, 2, 1)
+#define PIN_PC9__ISC_D0			PINMUX_PIN(PIN_PC9, 2, 1)
+#define PIN_PC9__TIOA4			PINMUX_PIN(PIN_PC9, 4, 2)
+#define PIN_PC10			74
+#define PIN_PC10__GPIO			PINMUX_PIN(PIN_PC10, 0, 0)
+#define PIN_PC10__LCDDAT2		PINMUX_PIN(PIN_PC10, 1, 2)
+#define PIN_PC10__GTXCK			PINMUX_PIN(PIN_PC10, 2, 1)
+#define PIN_PC10__ISC_D1		PINMUX_PIN(PIN_PC10, 3, 1)
+#define PIN_PC10__TIOB4			PINMUX_PIN(PIN_PC10, 4, 2)
+#define PIN_PC10__CANTX0		PINMUX_PIN(PIN_PC10, 5, 2)
+#define PIN_PC11			75
+#define PIN_PC11__GPIO			PINMUX_PIN(PIN_PC11, 0, 0)
+#define PIN_PC11__LCDDAT3		PINMUX_PIN(PIN_PC11, 1, 2)
+#define PIN_PC11__GTXEN			PINMUX_PIN(PIN_PC11, 2, 1)
+#define PIN_PC11__ISC_D2		PINMUX_PIN(PIN_PC11, 3, 1)
+#define PIN_PC11__TCLK4			PINMUX_PIN(PIN_PC11, 4, 2)
+#define PIN_PC11__CANRX0		PINMUX_PIN(PIN_PC11, 5, 2)
+#define PIN_PC11__A0_NBS0		PINMUX_PIN(PIN_PC11, 6, 2)
+#define PIN_PC12			76
+#define PIN_PC12__GPIO			PINMUX_PIN(PIN_PC12, 0, 0)
+#define PIN_PC12__LCDDAT4		PINMUX_PIN(PIN_PC12, 1, 2)
+#define PIN_PC12__GRXDV			PINMUX_PIN(PIN_PC12, 2, 1)
+#define PIN_PC12__ISC_D3		PINMUX_PIN(PIN_PC12, 3, 1)
+#define PIN_PC12__URXD3			PINMUX_PIN(PIN_PC12, 4, 1)
+#define PIN_PC12__TK0			PINMUX_PIN(PIN_PC12, 5, 2)
+#define PIN_PC12__A1			PINMUX_PIN(PIN_PC12, 6, 2)
+#define PIN_PC13			77
+#define PIN_PC13__GPIO			PINMUX_PIN(PIN_PC13, 0, 0)
+#define PIN_PC13__LCDDAT5		PINMUX_PIN(PIN_PC13, 1, 2)
+#define PIN_PC13__GRXER			PINMUX_PIN(PIN_PC13, 2, 1)
+#define PIN_PC13__ISC_D4		PINMUX_PIN(PIN_PC13, 3, 1)
+#define PIN_PC13__UTXD3			PINMUX_PIN(PIN_PC13, 4, 1)
+#define PIN_PC13__TF0			PINMUX_PIN(PIN_PC13, 5, 2)
+#define PIN_PC13__A2			PINMUX_PIN(PIN_PC13, 6, 2)
+#define PIN_PC14			78
+#define PIN_PC14__GPIO			PINMUX_PIN(PIN_PC14, 0, 0)
+#define PIN_PC14__LCDDAT6		PINMUX_PIN(PIN_PC14, 1, 2)
+#define PIN_PC14__GRX0			PINMUX_PIN(PIN_PC14, 2, 1)
+#define PIN_PC14__ISC_D5		PINMUX_PIN(PIN_PC14, 3, 1)
+#define PIN_PC14__TDO			PINMUX_PIN(PIN_PC14, 5, 2)
+#define PIN_PC14__A3			PINMUX_PIN(PIN_PC14, 6, 2)
+#define PIN_PC15			79
+#define PIN_PC15__GPIO			PINMUX_PIN(PIN_PC15, 0, 0)
+#define PIN_PC15__LCDDAT7		PINMUX_PIN(PIN_PC15, 1, 2)
+#define PIN_PC15__GRX1			PINMUX_PIN(PIN_PC15, 2, 1)
+#define PIN_PC15__ISC_D6		PINMUX_PIN(PIN_PC15, 3, 1)
+#define PIN_PC15__RD0			PINMUX_PIN(PIN_PC15, 5, 2)
+#define PIN_PC15__A4			PINMUX_PIN(PIN_PC15, 6, 2)
+#define PIN_PC16			80
+#define PIN_PC16__GPIO			PINMUX_PIN(PIN_PC16, 0, 0)
+#define PIN_PC16__LCDDAT10		PINMUX_PIN(PIN_PC16, 1, 2)
+#define PIN_PC16__GTX0			PINMUX_PIN(PIN_PC16, 2, 1)
+#define PIN_PC16__ISC_D7		PINMUX_PIN(PIN_PC16, 3, 1)
+#define PIN_PC16__RK0			PINMUX_PIN(PIN_PC16, 5, 2)
+#define PIN_PC16__A5			PINMUX_PIN(PIN_PC16, 6, 2)
+#define PIN_PC17			81
+#define PIN_PC17__GPIO			PINMUX_PIN(PIN_PC17, 0, 0)
+#define PIN_PC17__LCDDAT11		PINMUX_PIN(PIN_PC17, 1, 2)
+#define PIN_PC17__GTX1			PINMUX_PIN(PIN_PC17, 2, 1)
+#define PIN_PC17__ISC_D8		PINMUX_PIN(PIN_PC17, 3, 1)
+#define PIN_PC17__RF0			PINMUX_PIN(PIN_PC17, 5, 2)
+#define PIN_PC17__A6			PINMUX_PIN(PIN_PC17, 6, 2)
+#define PIN_PC18			82
+#define PIN_PC18__GPIO			PINMUX_PIN(PIN_PC18, 0, 0)
+#define PIN_PC18__LCDDAT12		PINMUX_PIN(PIN_PC18, 1, 2)
+#define PIN_PC18__GMDC			PINMUX_PIN(PIN_PC18, 2, 1)
+#define PIN_PC18__ISC_D9		PINMUX_PIN(PIN_PC18, 3, 1)
+#define PIN_PC18__FLEXCOM3_IO2		PINMUX_PIN(PIN_PC18, 5, 2)
+#define PIN_PC18__A7			PINMUX_PIN(PIN_PC18, 6, 2)
+#define PIN_PC19			83
+#define PIN_PC19__GPIO			PINMUX_PIN(PIN_PC19, 0, 0)
+#define PIN_PC19__LCDDAT13		PINMUX_PIN(PIN_PC19, 1, 2)
+#define PIN_PC19__GMDIO			PINMUX_PIN(PIN_PC19, 2, 1)
+#define PIN_PC19__ISC_D10		PINMUX_PIN(PIN_PC19, 3, 1)
+#define PIN_PC19__FLEXCOM3_IO1		PINMUX_PIN(PIN_PC19, 5, 2)
+#define PIN_PC19__A8			PINMUX_PIN(PIN_PC19, 6, 2)
+#define PIN_PC20			84
+#define PIN_PC20__GPIO			PINMUX_PIN(PIN_PC20, 0, 0)
+#define PIN_PC20__LCDDAT14		PINMUX_PIN(PIN_PC20, 1, 2)
+#define PIN_PC20__GRXCK			PINMUX_PIN(PIN_PC20, 2, 1)
+#define PIN_PC20__ISC_D11		PINMUX_PIN(PIN_PC20, 3, 1)
+#define PIN_PC20__FLEXCOM3_IO0		PINMUX_PIN(PIN_PC20, 5, 2)
+#define PIN_PC20__A9			PINMUX_PIN(PIN_PC20, 6, 2)
+#define PIN_PC21			85
+#define PIN_PC21__GPIO			PINMUX_PIN(PIN_PC21, 0, 0)
+#define PIN_PC21__LCDDAT15		PINMUX_PIN(PIN_PC21, 1, 2)
+#define PIN_PC21__GTXER			PINMUX_PIN(PIN_PC21, 2, 1)
+#define PIN_PC21__ISC_PCK		PINMUX_PIN(PIN_PC21, 3, 1)
+#define PIN_PC21__FLEXCOM3_IO3		PINMUX_PIN(PIN_PC21, 5, 2)
+#define PIN_PC21__A10			PINMUX_PIN(PIN_PC21, 6, 2)
+#define PIN_PC22			86
+#define PIN_PC22__GPIO			PINMUX_PIN(PIN_PC22, 0, 0)
+#define PIN_PC22__LCDDAT18		PINMUX_PIN(PIN_PC22, 1, 2)
+#define PIN_PC22__GCRS			PINMUX_PIN(PIN_PC22, 2, 1)
+#define PIN_PC22__ISC_VSYNC		PINMUX_PIN(PIN_PC22, 3, 1)
+#define PIN_PC22__FLEXCOM3_IO4		PINMUX_PIN(PIN_PC22, 5, 2)
+#define PIN_PC22__A11			PINMUX_PIN(PIN_PC22, 6, 2)
+#define PIN_PC23			87
+#define PIN_PC23__GPIO			PINMUX_PIN(PIN_PC23, 0, 0)
+#define PIN_PC23__LCDDAT19		PINMUX_PIN(PIN_PC23, 1, 2)
+#define PIN_PC23__GCOL			PINMUX_PIN(PIN_PC23, 2, 1)
+#define PIN_PC23__ISC_HSYNC		PINMUX_PIN(PIN_PC23, 3, 1)
+#define PIN_PC23__A12			PINMUX_PIN(PIN_PC23, 6, 2)
+#define PIN_PC24			88
+#define PIN_PC24__GPIO			PINMUX_PIN(PIN_PC24, 0, 0)
+#define PIN_PC24__LCDDAT20		PINMUX_PIN(PIN_PC24, 1, 2)
+#define PIN_PC24__GRX2			PINMUX_PIN(PIN_PC24, 2, 1)
+#define PIN_PC24__ISC_MCK		PINMUX_PIN(PIN_PC24, 3, 1)
+#define PIN_PC24__A13			PINMUX_PIN(PIN_PC24, 6, 2)
+#define PIN_PC25			89
+#define PIN_PC25__GPIO			PINMUX_PIN(PIN_PC25, 0, 0)
+#define PIN_PC25__LCDDAT21		PINMUX_PIN(PIN_PC25, 1, 2)
+#define PIN_PC25__GRX3			PINMUX_PIN(PIN_PC25, 2, 1)
+#define PIN_PC25__ISC_FIELD		PINMUX_PIN(PIN_PC25, 3, 1)
+#define PIN_PC25__A14			PINMUX_PIN(PIN_PC25, 6, 2)
+#define PIN_PC26			90
+#define PIN_PC26__GPIO			PINMUX_PIN(PIN_PC26, 0, 0)
+#define PIN_PC26__LCDDAT22		PINMUX_PIN(PIN_PC26, 1, 2)
+#define PIN_PC26__GTX2			PINMUX_PIN(PIN_PC26, 2, 1)
+#define PIN_PC26__CANTX1		PINMUX_PIN(PIN_PC26, 4, 1)
+#define PIN_PC26__A15			PINMUX_PIN(PIN_PC26, 6, 2)
+#define PIN_PC27			91
+#define PIN_PC27__GPIO			PINMUX_PIN(PIN_PC27, 0, 0)
+#define PIN_PC27__LCDDAT23		PINMUX_PIN(PIN_PC27, 1, 2)
+#define PIN_PC27__GTX3			PINMUX_PIN(PIN_PC27, 2, 1)
+#define PIN_PC27__PCK1			PINMUX_PIN(PIN_PC27, 3, 2)
+#define PIN_PC27__CANRX1		PINMUX_PIN(PIN_PC27, 4, 1)
+#define PIN_PC27__TWD0			PINMUX_PIN(PIN_PC27, 5, 2)
+#define PIN_PC27__A16			PINMUX_PIN(PIN_PC27, 6, 2)
+#define PIN_PC28			92
+#define PIN_PC28__GPIO			PINMUX_PIN(PIN_PC28, 0, 0)
+#define PIN_PC28__LCDPWM		PINMUX_PIN(PIN_PC28, 1, 2)
+#define PIN_PC28__FLEXCOM4_IO0		PINMUX_PIN(PIN_PC28, 2, 1)
+#define PIN_PC28__PCK2			PINMUX_PIN(PIN_PC28, 3, 2)
+#define PIN_PC28__TWCK0			PINMUX_PIN(PIN_PC28, 5, 2)
+#define PIN_PC28__A17			PINMUX_PIN(PIN_PC28, 6, 2)
+#define PIN_PC29			93
+#define PIN_PC29__GPIO			PINMUX_PIN(PIN_PC29, 0, 0)
+#define PIN_PC29__LCDDISP		PINMUX_PIN(PIN_PC29, 1, 2)
+#define PIN_PC29__FLEXCOM4_IO1		PINMUX_PIN(PIN_PC29, 2, 1)
+#define PIN_PC29__A18			PINMUX_PIN(PIN_PC29, 6, 2)
+#define PIN_PC30			94
+#define PIN_PC30__GPIO			PINMUX_PIN(PIN_PC30, 0, 0)
+#define PIN_PC30__LCDVSYNC		PINMUX_PIN(PIN_PC30, 1, 2)
+#define PIN_PC30__FLEXCOM4_IO2		PINMUX_PIN(PIN_PC30, 2, 1)
+#define PIN_PC30__A19			PINMUX_PIN(PIN_PC30, 6, 2)
+#define PIN_PC31			95
+#define PIN_PC31__GPIO			PINMUX_PIN(PIN_PC31, 0, 0)
+#define PIN_PC31__LCDHSYNC		PINMUX_PIN(PIN_PC31, 1, 2)
+#define PIN_PC31__FLEXCOM4_IO3		PINMUX_PIN(PIN_PC31, 2, 1)
+#define PIN_PC31__URXD3			PINMUX_PIN(PIN_PC31, 3, 2)
+#define PIN_PC31__A20			PINMUX_PIN(PIN_PC31, 6, 2)
+#define PIN_PD0				96
+#define PIN_PD0__GPIO			PINMUX_PIN(PIN_PD0, 0, 0)
+#define PIN_PD0__LCDPCK			PINMUX_PIN(PIN_PD0, 1, 2)
+#define PIN_PD0__FLEXCOM4_IO4		PINMUX_PIN(PIN_PD0, 2, 1)
+#define PIN_PD0__UTXD3			PINMUX_PIN(PIN_PD0, 3, 2)
+#define PIN_PD0__GTSUCOMP		PINMUX_PIN(PIN_PD0, 4, 2)
+#define PIN_PD0__A23			PINMUX_PIN(PIN_PD0, 6, 2)
+#define PIN_PD1				97
+#define PIN_PD1__GPIO			PINMUX_PIN(PIN_PD1, 0, 0)
+#define PIN_PD1__LCDDEN			PINMUX_PIN(PIN_PD1, 1, 2)
+#define PIN_PD1__GRXCK			PINMUX_PIN(PIN_PD1, 4, 2)
+#define PIN_PD1__A24			PINMUX_PIN(PIN_PD1, 6, 2)
+#define PIN_PD2				98
+#define PIN_PD2__GPIO			PINMUX_PIN(PIN_PD2, 0, 0)
+#define PIN_PD2__URXD1			PINMUX_PIN(PIN_PD2, 1, 1)
+#define PIN_PD2__GTXER			PINMUX_PIN(PIN_PD2, 4, 2)
+#define PIN_PD2__ISC_MCK		PINMUX_PIN(PIN_PD2, 5, 2)
+#define PIN_PD2__A25			PINMUX_PIN(PIN_PD2, 6, 2)
+#define PIN_PD3				99
+#define PIN_PD3__GPIO			PINMUX_PIN(PIN_PD3, 0, 0)
+#define PIN_PD3__UTXD1			PINMUX_PIN(PIN_PD3, 1, 1)
+#define PIN_PD3__FIQ			PINMUX_PIN(PIN_PD3, 2, 2)
+#define PIN_PD3__GCRS			PINMUX_PIN(PIN_PD3, 4, 2)
+#define PIN_PD3__ISC_D11		PINMUX_PIN(PIN_PD3, 5, 2)
+#define PIN_PD3__NWAIT			PINMUX_PIN(PIN_PD3, 6, 2)
+#define PIN_PD4				100
+#define PIN_PD4__GPIO			PINMUX_PIN(PIN_PD4, 0, 0)
+#define PIN_PD4__TWD1			PINMUX_PIN(PIN_PD4, 1, 2)
+#define PIN_PD4__URXD2			PINMUX_PIN(PIN_PD4, 2, 1)
+#define PIN_PD4__GCOL			PINMUX_PIN(PIN_PD4, 4, 2)
+#define PIN_PD4__ISC_D10		PINMUX_PIN(PIN_PD4, 5, 2)
+#define PIN_PD4__NCS0			PINMUX_PIN(PIN_PD4, 6, 2)
+#define PIN_PD5				101
+#define PIN_PD5__GPIO			PINMUX_PIN(PIN_PD5, 0, 0)
+#define PIN_PD5__TWCK1			PINMUX_PIN(PIN_PD5, 1, 2)
+#define PIN_PD5__UTXD2			PINMUX_PIN(PIN_PD5, 2, 1)
+#define PIN_PD5__GRX2			PINMUX_PIN(PIN_PD5, 4, 2)
+#define PIN_PD5__ISC_D9			PINMUX_PIN(PIN_PD5, 5, 2)
+#define PIN_PD5__NCS1			PINMUX_PIN(PIN_PD5, 6, 2)
+#define PIN_PD6				102
+#define PIN_PD6__GPIO			PINMUX_PIN(PIN_PD6, 0, 0)
+#define PIN_PD6__TCK			PINMUX_PIN(PIN_PD6, 1, 2)
+#define PIN_PD6__PCK1			PINMUX_PIN(PIN_PD6, 2, 1)
+#define PIN_PD6__GRX3			PINMUX_PIN(PIN_PD6, 4, 2)
+#define PIN_PD6__ISC_D8			PINMUX_PIN(PIN_PD6, 5, 2)
+#define PIN_PD6__NCS2			PINMUX_PIN(PIN_PD6, 6, 2)
+#define PIN_PD7				103
+#define PIN_PD7__GPIO			PINMUX_PIN(PIN_PD7, 0, 0)
+#define PIN_PD7__TDI			PINMUX_PIN(PIN_PD7, 1, 2)
+#define PIN_PD7__UTMI_RXVAL		PINMUX_PIN(PIN_PD7, 3, 1)
+#define PIN_PD7__GTX2			PINMUX_PIN(PIN_PD7, 4, 2)
+#define PIN_PD7__ISC_D0			PINMUX_PIN(PIN_PD7, 5, 2)
+#define PIN_PD7__NWR1_NBS1		PINMUX_PIN(PIN_PD7, 6, 2)
+#define PIN_PD8				104
+#define PIN_PD8__GPIO			PINMUX_PIN(PIN_PD8, 0, 0)
+#define PIN_PD8__TDO			PINMUX_PIN(PIN_PD8, 1, 2)
+#define PIN_PD8__UTMI_RXERR		PINMUX_PIN(PIN_PD8, 3, 1)
+#define PIN_PD8__GTX3			PINMUX_PIN(PIN_PD8, 4, 2)
+#define PIN_PD8__ISC_D1			PINMUX_PIN(PIN_PD8, 5, 2)
+#define PIN_PD8__NANDRDY		PINMUX_PIN(PIN_PD8, 6, 2)
+#define PIN_PD9				105
+#define PIN_PD9__GPIO			PINMUX_PIN(PIN_PD9, 0, 0)
+#define PIN_PD9__TMS			PINMUX_PIN(PIN_PD9, 1, 2)
+#define PIN_PD9__UTMI_RXACT		PINMUX_PIN(PIN_PD9, 3, 1)
+#define PIN_PD9__GTXCK			PINMUX_PIN(PIN_PD9, 4, 2)
+#define PIN_PD9__ISC_D2			PINMUX_PIN(PIN_PD9, 5, 2)
+#define PIN_PD10			106
+#define PIN_PD10__GPIO			PINMUX_PIN(PIN_PD10, 0, 0)
+#define PIN_PD10__NTRST			PINMUX_PIN(PIN_PD10, 1, 2)
+#define PIN_PD10__UTMI_HDIS		PINMUX_PIN(PIN_PD10, 3, 1)
+#define PIN_PD10__GTXEN			PINMUX_PIN(PIN_PD10, 4, 2)
+#define PIN_PD10__ISC_D3		PINMUX_PIN(PIN_PD10, 5, 2)
+#define PIN_PD11			107
+#define PIN_PD11__GPIO			PINMUX_PIN(PIN_PD11, 0, 0)
+#define PIN_PD11__TIOA1			PINMUX_PIN(PIN_PD11, 1, 3)
+#define PIN_PD11__PCK2			PINMUX_PIN(PIN_PD11, 2, 2)
+#define PIN_PD11__UTMI_LS0		PINMUX_PIN(PIN_PD11, 3, 1)
+#define PIN_PD11__GRXDV			PINMUX_PIN(PIN_PD11, 4, 2)
+#define PIN_PD11__ISC_D4		PINMUX_PIN(PIN_PD11, 5, 2)
+#define PIN_PD11__ISC_MCK		PINMUX_PIN(PIN_PD11, 7, 4)
+#define PIN_PD12			108
+#define PIN_PD12__GPIO			PINMUX_PIN(PIN_PD12, 0, 0)
+#define PIN_PD12__TIOB1			PINMUX_PIN(PIN_PD12, 1, 3)
+#define PIN_PD12__FLEXCOM4_IO0		PINMUX_PIN(PIN_PD12, 2, 2)
+#define PIN_PD12__UTMI_LS1		PINMUX_PIN(PIN_PD12, 3, 1)
+#define PIN_PD12__GRXER			PINMUX_PIN(PIN_PD12, 4, 2)
+#define PIN_PD12__ISC_D5		PINMUX_PIN(PIN_PD12, 5, 2)
+#define PIN_PD12__ISC_D4		PINMUX_PIN(PIN_PD12, 6, 4)
+#define PIN_PD13			109
+#define PIN_PD13__GPIO			PINMUX_PIN(PIN_PD13, 0, 0)
+#define PIN_PD13__TCLK1			PINMUX_PIN(PIN_PD13, 1, 3)
+#define PIN_PD13__FLEXCOM4_IO1		PINMUX_PIN(PIN_PD13, 2, 2)
+#define PIN_PD13__UTMI_CDRPCSEL0	PINMUX_PIN(PIN_PD13, 3, 1)
+#define PIN_PD13__GRX0			PINMUX_PIN(PIN_PD13, 4, 2)
+#define PIN_PD13__ISC_D6		PINMUX_PIN(PIN_PD13, 5, 2)
+#define PIN_PD13__ISC_D5		PINMUX_PIN(PIN_PD13, 6, 4)
+#define PIN_PD14			110
+#define PIN_PD14__GPIO			PINMUX_PIN(PIN_PD14, 0, 0)
+#define PIN_PD14__TCK			PINMUX_PIN(PIN_PD14, 1, 1)
+#define PIN_PD14__FLEXCOM4_IO2		PINMUX_PIN(PIN_PD14, 2, 2)
+#define PIN_PD14__UTMI_CDRPCSEL1	PINMUX_PIN(PIN_PD14, 3, 1)
+#define PIN_PD14__GRX1			PINMUX_PIN(PIN_PD14, 4, 2)
+#define PIN_PD14__ISC_D7		PINMUX_PIN(PIN_PD14, 5, 2)
+#define PIN_PD14__ISC_D6		PINMUX_PIN(PIN_PD14, 6, 4)
+#define PIN_PD15			111
+#define PIN_PD15__GPIO			PINMUX_PIN(PIN_PD15, 0, 0)
+#define PIN_PD15__TDI			PINMUX_PIN(PIN_PD15, 1, 1)
+#define PIN_PD15__FLEXCOM4_IO3		PINMUX_PIN(PIN_PD15, 2, 2)
+#define PIN_PD15__UTMI_CDRCPDIVEN	PINMUX_PIN(PIN_PD15, 3, 1)
+#define PIN_PD15__GTX0			PINMUX_PIN(PIN_PD15, 4, 2)
+#define PIN_PD15__ISC_PCK		PINMUX_PIN(PIN_PD15, 5, 2)
+#define PIN_PD15__ISC_D7		PINMUX_PIN(PIN_PD15, 6, 4)
+#define PIN_PD16			112
+#define PIN_PD16__GPIO			PINMUX_PIN(PIN_PD16, 0, 0)
+#define PIN_PD16__TDO			PINMUX_PIN(PIN_PD16, 1, 1)
+#define PIN_PD16__FLEXCOM4_IO4		PINMUX_PIN(PIN_PD16, 2, 2)
+#define PIN_PD16__UTMI_CDRBISTEN	PINMUX_PIN(PIN_PD16, 3, 1)
+#define PIN_PD16__GTX1			PINMUX_PIN(PIN_PD16, 4, 2)
+#define PIN_PD16__ISC_VSYNC		PINMUX_PIN(PIN_PD16, 5, 2)
+#define PIN_PD16__ISC_D8		PINMUX_PIN(PIN_PD16, 6, 4)
+#define PIN_PD17			113
+#define PIN_PD17__GPIO			PINMUX_PIN(PIN_PD17, 0, 0)
+#define PIN_PD17__TMS			PINMUX_PIN(PIN_PD17, 1, 1)
+#define PIN_PD17__UTMI_CDRCPSELDIV	PINMUX_PIN(PIN_PD17, 3, 1)
+#define PIN_PD17__GMDC			PINMUX_PIN(PIN_PD17, 4, 2)
+#define PIN_PD17__ISC_HSYNC		PINMUX_PIN(PIN_PD17, 5, 2)
+#define PIN_PD17__ISC_D9		PINMUX_PIN(PIN_PD17, 6, 4)
+#define PIN_PD18			114
+#define PIN_PD18__GPIO			PINMUX_PIN(PIN_PD18, 0, 0)
+#define PIN_PD18__NTRST			PINMUX_PIN(PIN_PD18, 1, 1)
+#define PIN_PD18__GMDIO			PINMUX_PIN(PIN_PD18, 4, 2)
+#define PIN_PD18__ISC_FIELD		PINMUX_PIN(PIN_PD18, 5, 2)
+#define PIN_PD18__ISC_D10		PINMUX_PIN(PIN_PD18, 6, 4)
+#define PIN_PD19			115
+#define PIN_PD19__GPIO			PINMUX_PIN(PIN_PD19, 0, 0)
+#define PIN_PD19__PCK0			PINMUX_PIN(PIN_PD19, 1, 1)
+#define PIN_PD19__TWD1			PINMUX_PIN(PIN_PD19, 2, 3)
+#define PIN_PD19__URXD2			PINMUX_PIN(PIN_PD19, 3, 3)
+#define PIN_PD19__I2SC0_CK		PINMUX_PIN(PIN_PD19, 5, 2)
+#define PIN_PD19__ISC_D11		PINMUX_PIN(PIN_PD19, 6, 4)
+#define PIN_PD20			116
+#define PIN_PD20__GPIO			PINMUX_PIN(PIN_PD20, 0, 0)
+#define PIN_PD20__TIOA2			PINMUX_PIN(PIN_PD20, 1, 3)
+#define PIN_PD20__TWCK1			PINMUX_PIN(PIN_PD20, 2, 3)
+#define PIN_PD20__UTXD2			PINMUX_PIN(PIN_PD20, 3, 3)
+#define PIN_PD20__I2SC0_MCK		PINMUX_PIN(PIN_PD20, 5, 2)
+#define PIN_PD20__ISC_PCK		PINMUX_PIN(PIN_PD20, 6, 4)
+#define PIN_PD21			117
+#define PIN_PD21__GPIO			PINMUX_PIN(PIN_PD21, 0, 0)
+#define PIN_PD21__TIOB2			PINMUX_PIN(PIN_PD21, 1, 3)
+#define PIN_PD21__TWD0			PINMUX_PIN(PIN_PD21, 2, 4)
+#define PIN_PD21__FLEXCOM4_IO0		PINMUX_PIN(PIN_PD21, 3, 3)
+#define PIN_PD21__I2SC0_WS		PINMUX_PIN(PIN_PD21, 5, 2)
+#define PIN_PD21__ISC_VSYNC		PINMUX_PIN(PIN_PD21, 6, 4)
+#define PIN_PD22			118
+#define PIN_PD22__GPIO			PINMUX_PIN(PIN_PD22, 0, 0)
+#define PIN_PD22__TCLK2			PINMUX_PIN(PIN_PD22, 1, 3)
+#define PIN_PD22__TWCK0			PINMUX_PIN(PIN_PD22, 2, 4)
+#define PIN_PD22__FLEXCOM4_IO1		PINMUX_PIN(PIN_PD22, 3, 3)
+#define PIN_PD22__I2SC0_DI0		PINMUX_PIN(PIN_PD22, 5, 2)
+#define PIN_PD22__ISC_HSYNC		PINMUX_PIN(PIN_PD22, 6, 4)
+#define PIN_PD23			119
+#define PIN_PD23__GPIO			PINMUX_PIN(PIN_PD23, 0, 0)
+#define PIN_PD23__URXD2			PINMUX_PIN(PIN_PD23, 1, 2)
+#define PIN_PD23__FLEXCOM4_IO2		PINMUX_PIN(PIN_PD23, 3, 3)
+#define PIN_PD23__I2SC0_DO0		PINMUX_PIN(PIN_PD23, 5, 2)
+#define PIN_PD23__ISC_FIELD		PINMUX_PIN(PIN_PD23, 6, 4)
+#define PIN_PD24			120
+#define PIN_PD24__GPIO			PINMUX_PIN(PIN_PD24, 0, 0)
+#define PIN_PD24__UTXD2			PINMUX_PIN(PIN_PD23, 1, 2)
+#define PIN_PD24__FLEXCOM4_IO3		PINMUX_PIN(PIN_PD23, 3, 3)
+#define PIN_PD25			121
+#define PIN_PD25__GPIO			PINMUX_PIN(PIN_PD25, 0, 0)
+#define PIN_PD25__SPI1_SPCK		PINMUX_PIN(PIN_PD25, 1, 3)
+#define PIN_PD25__FLEXCOM4_IO4		PINMUX_PIN(PIN_PD25, 3, 3)
+#define PIN_PD26			122
+#define PIN_PD26__GPIO			PINMUX_PIN(PIN_PD26, 0, 0)
+#define PIN_PD26__SPI1_MOSI		PINMUX_PIN(PIN_PD26, 1, 3)
+#define PIN_PD26__FLEXCOM2_IO0		PINMUX_PIN(PIN_PD26, 3, 2)
+#define PIN_PD27			123
+#define PIN_PD27__GPIO			PINMUX_PIN(PIN_PD27, 0, 0)
+#define PIN_PD27__SPI1_MISO		PINMUX_PIN(PIN_PD27, 1, 3)
+#define PIN_PD27__TCK			PINMUX_PIN(PIN_PD27, 2, 3)
+#define PIN_PD27__FLEXCOM2_IO1		PINMUX_PIN(PIN_PD27, 3, 2)
+#define PIN_PD28			124
+#define PIN_PD28__GPIO			PINMUX_PIN(PIN_PD28, 0, 0)
+#define PIN_PD28__SPI1_NPCS0		PINMUX_PIN(PIN_PD28, 1, 3)
+#define PIN_PD28__TCI			PINMUX_PIN(PIN_PD28, 2, 3)
+#define PIN_PD28__FLEXCOM2_IO2		PINMUX_PIN(PIN_PD28, 3, 2)
+#define PIN_PD29			125
+#define PIN_PD29__GPIO			PINMUX_PIN(PIN_PD29, 0, 0)
+#define PIN_PD29__SPI1_NPCS1		PINMUX_PIN(PIN_PD29, 1, 3)
+#define PIN_PD29__TDO			PINMUX_PIN(PIN_PD29, 2, 3)
+#define PIN_PD29__FLEXCOM2_IO3		PINMUX_PIN(PIN_PD29, 3, 2)
+#define PIN_PD29__TIOA3			PINMUX_PIN(PIN_PD29, 4, 3)
+#define PIN_PD29__TWD0			PINMUX_PIN(PIN_PD29, 5, 3)
+#define PIN_PD30			126
+#define PIN_PD30__GPIO			PINMUX_PIN(PIN_PD30, 0, 0)
+#define PIN_PD30__SPI1_NPCS2		PINMUX_PIN(PIN_PD30, 1, 3)
+#define PIN_PD30__TMS			PINMUX_PIN(PIN_PD30, 2, 3)
+#define PIN_PD30__FLEXCOM2_IO4		PINMUX_PIN(PIN_PD30, 3, 2)
+#define PIN_PD30__TIOB3			PINMUX_PIN(PIN_PD30, 4, 3)
+#define PIN_PD30__TWCK0			PINMUX_PIN(PIN_PD30, 5, 3)
+#define PIN_PD31			127
+#define PIN_PD31__GPIO			PINMUX_PIN(PIN_PD31, 0, 0)
+#define PIN_PD31__ADTRG			PINMUX_PIN(PIN_PD31, 1, 1)
+#define PIN_PD31__NTRST			PINMUX_PIN(PIN_PD31, 2, 3)
+#define PIN_PD31__IRQ			PINMUX_PIN(PIN_PD31, 3, 4)
+#define PIN_PD31__TCLK3			PINMUX_PIN(PIN_PD31, 4, 3)
+#define PIN_PD31__PCK0			PINMUX_PIN(PIN_PD31, 5, 2)
diff --git a/arch/arm/dts/sama5d2.dtsi b/arch/arm/dts/sama5d2.dtsi
new file mode 100644
index 0000000..19feb66
--- /dev/null
+++ b/arch/arm/dts/sama5d2.dtsi
@@ -0,0 +1,671 @@
+#include "skeleton.dtsi"
+
+/ {
+	model = "Atmel SAMA5D2 family SoC";
+	compatible = "atmel,sama5d2";
+
+	aliases {
+		spi0 = &spi0;
+		spi1 = &qspi0;
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+	};
+
+	clocks {
+		slow_xtal: slow_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+
+		main_xtal: main_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+	};
+
+	ahb {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		usb1: ohci@00400000 {
+			compatible = "atmel,at91rm9200-ohci", "usb-ohci";
+			reg = <0x00400000 0x100000>;
+			clocks = <&uhphs_clk>, <&uhphs_clk>, <&uhpck>;
+			clock-names = "ohci_clk", "hclk", "uhpck";
+			status = "disabled";
+		};
+
+		usb2: ehci@00500000 {
+			compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
+			reg = <0x00500000 0x100000>;
+			clocks = <&utmi>, <&uhphs_clk>;
+			clock-names = "usb_clk", "ehci_clk";
+			status = "disabled";
+		};
+
+		sdmmc0: sdio-host@a0000000 {
+			compatible = "atmel,sama5d2-sdhci";
+			reg = <0xa0000000 0x300>;
+			clocks = <&sdmmc0_hclk>, <&sdmmc0_gclk>, <&main>;
+			clock-names = "hclock", "multclk", "baseclk";
+			status = "disabled";
+		};
+
+		sdmmc1: sdio-host@b0000000 {
+			compatible = "atmel,sama5d2-sdhci";
+			reg = <0xb0000000 0x300>;
+			clocks = <&sdmmc1_hclk>, <&sdmmc1_gclk>, <&main>;
+			clock-names = "hclock", "multclk", "baseclk";
+			status = "disabled";
+		};
+
+		apb {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			pmc: pmc@f0014000 {
+				compatible = "atmel,sama5d2-pmc", "syscon";
+				reg = <0xf0014000 0x160>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				#interrupt-cells = <1>;
+
+				main: mainck {
+					compatible = "atmel,at91sam9x5-clk-main";
+					#clock-cells = <0>;
+				};
+
+				plla: pllack {
+					compatible = "atmel,sama5d3-clk-pll";
+					#clock-cells = <0>;
+					clocks = <&main>;
+					reg = <0>;
+					atmel,clk-input-range = <12000000 12000000>;
+					#atmel,pll-clk-output-range-cells = <4>;
+					atmel,pll-clk-output-ranges = <600000000 1200000000 0 0>;
+				};
+
+				plladiv: plladivck {
+					compatible = "atmel,at91sam9x5-clk-plldiv";
+					#clock-cells = <0>;
+					clocks = <&plla>;
+				};
+
+				audio_pll_frac: audiopll_fracck {
+					compatible = "atmel,sama5d2-clk-audio-pll-frac";
+					#clock-cells = <0>;
+					clocks = <&main>;
+				};
+
+				audio_pll_pad: audiopll_padck {
+					compatible = "atmel,sama5d2-clk-audio-pll-pad";
+					#clock-cells = <0>;
+					clocks = <&audio_pll_frac>;
+				};
+
+				audio_pll_pmc: audiopll_pmcck {
+					compatible = "atmel,sama5d2-clk-audio-pll-pmc";
+					#clock-cells = <0>;
+					clocks = <&audio_pll_frac>;
+				};
+
+				utmi: utmick {
+					compatible = "atmel,at91sam9x5-clk-utmi";
+					#clock-cells = <0>;
+					clocks = <&main>;
+				};
+
+				mck: masterck {
+					compatible = "atmel,at91sam9x5-clk-master";
+					#clock-cells = <0>;
+					clocks = <&main>, <&plladiv>, <&utmi>;
+					atmel,clk-output-range = <124000000 166000000>;
+					atmel,clk-divisors = <1 2 4 3>;
+				};
+
+				h32ck: h32mxck {
+					#clock-cells = <0>;
+					compatible = "atmel,sama5d4-clk-h32mx";
+					clocks = <&mck>;
+				};
+
+				usb: usbck {
+					compatible = "atmel,at91sam9x5-clk-usb";
+					#clock-cells = <0>;
+					clocks = <&plladiv>, <&utmi>;
+				};
+
+				prog: progck {
+					compatible = "atmel,at91sam9x5-clk-programmable";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					interrupt-parent = <&pmc>;
+					clocks = <&main>, <&plladiv>, <&utmi>, <&mck>;
+
+					prog0: prog0 {
+						#clock-cells = <0>;
+						reg = <0>;
+					};
+
+					prog1: prog1 {
+						#clock-cells = <0>;
+						reg = <1>;
+					};
+
+					prog2: prog2 {
+						#clock-cells = <0>;
+						reg = <2>;
+					};
+				};
+
+				systemck {
+					compatible = "atmel,at91rm9200-clk-system";
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					ddrck: ddrck {
+						#clock-cells = <0>;
+						reg = <2>;
+						clocks = <&mck>;
+					};
+
+					lcdck: lcdck {
+						#clock-cells = <0>;
+						reg = <3>;
+						clocks = <&mck>;
+					};
+
+					uhpck: uhpck {
+						#clock-cells = <0>;
+						reg = <6>;
+						clocks = <&usb>;
+					};
+
+					udpck: udpck {
+						#clock-cells = <0>;
+						reg = <7>;
+						clocks = <&usb>;
+					};
+
+					pck0: pck0 {
+						#clock-cells = <0>;
+						reg = <8>;
+						clocks = <&prog0>;
+					};
+
+					pck1: pck1 {
+						#clock-cells = <0>;
+						reg = <9>;
+						clocks = <&prog1>;
+					};
+
+					pck2: pck2 {
+						#clock-cells = <0>;
+						reg = <10>;
+						clocks = <&prog2>;
+					};
+
+					iscck: iscck {
+						#clock-cells = <0>;
+						reg = <18>;
+						clocks = <&mck>;
+					};
+				};
+
+				periph32ck {
+					compatible = "atmel,at91sam9x5-clk-peripheral";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					clocks = <&h32ck>;
+
+					macb0_clk: macb0_clk {
+						#clock-cells = <0>;
+						reg = <5>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					tdes_clk: tdes_clk {
+						#clock-cells = <0>;
+						reg = <11>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					matrix1_clk: matrix1_clk {
+						#clock-cells = <0>;
+						reg = <14>;
+					};
+
+					hsmc_clk: hsmc_clk {
+						#clock-cells = <0>;
+						reg = <17>;
+					};
+
+					pioA_clk: pioA_clk {
+						#clock-cells = <0>;
+						reg = <18>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					flx0_clk: flx0_clk {
+						#clock-cells = <0>;
+						reg = <19>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					flx1_clk: flx1_clk {
+						#clock-cells = <0>;
+						reg = <20>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					flx2_clk: flx2_clk {
+						#clock-cells = <0>;
+						reg = <21>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					flx3_clk: flx3_clk {
+						#clock-cells = <0>;
+						reg = <22>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					flx4_clk: flx4_clk {
+						#clock-cells = <0>;
+						reg = <23>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					uart0_clk: uart0_clk {
+						#clock-cells = <0>;
+						reg = <24>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					uart1_clk: uart1_clk {
+						#clock-cells = <0>;
+						reg = <25>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					uart2_clk: uart2_clk {
+						#clock-cells = <0>;
+						reg = <26>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					uart3_clk: uart3_clk {
+						#clock-cells = <0>;
+						reg = <27>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					uart4_clk: uart4_clk {
+						#clock-cells = <0>;
+						reg = <28>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					twi0_clk: twi0_clk {
+						reg = <29>;
+						#clock-cells = <0>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					twi1_clk: twi1_clk {
+						#clock-cells = <0>;
+						reg = <30>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					spi0_clk: spi0_clk {
+						#clock-cells = <0>;
+						reg = <33>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					spi1_clk: spi1_clk {
+						#clock-cells = <0>;
+						reg = <34>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					tcb0_clk: tcb0_clk {
+						#clock-cells = <0>;
+						reg = <35>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					tcb1_clk: tcb1_clk {
+						#clock-cells = <0>;
+						reg = <36>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					pwm_clk: pwm_clk {
+						#clock-cells = <0>;
+						reg = <38>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					adc_clk: adc_clk {
+						#clock-cells = <0>;
+						reg = <40>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					uhphs_clk: uhphs_clk {
+						#clock-cells = <0>;
+						reg = <41>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					udphs_clk: udphs_clk {
+						#clock-cells = <0>;
+						reg = <42>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					ssc0_clk: ssc0_clk {
+						#clock-cells = <0>;
+						reg = <43>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					ssc1_clk: ssc1_clk {
+						#clock-cells = <0>;
+						reg = <44>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					trng_clk: trng_clk {
+						#clock-cells = <0>;
+						reg = <47>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					pdmic_clk: pdmic_clk {
+						#clock-cells = <0>;
+						reg = <48>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					i2s0_clk: i2s0_clk {
+						#clock-cells = <0>;
+						reg = <54>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					i2s1_clk: i2s1_clk {
+						#clock-cells = <0>;
+						reg = <55>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					can0_clk: can0_clk {
+						#clock-cells = <0>;
+						reg = <56>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					can1_clk: can1_clk {
+						#clock-cells = <0>;
+						reg = <57>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					classd_clk: classd_clk {
+						#clock-cells = <0>;
+						reg = <59>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+				};
+
+				periph64ck {
+					compatible = "atmel,at91sam9x5-clk-peripheral";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					clocks = <&mck>;
+
+					dma0_clk: dma0_clk {
+						#clock-cells = <0>;
+						reg = <6>;
+					};
+
+					dma1_clk: dma1_clk {
+						#clock-cells = <0>;
+						reg = <7>;
+					};
+
+					aes_clk: aes_clk {
+						#clock-cells = <0>;
+						reg = <9>;
+					};
+
+					aesb_clk: aesb_clk {
+						#clock-cells = <0>;
+						reg = <10>;
+					};
+
+					sha_clk: sha_clk {
+						#clock-cells = <0>;
+						reg = <12>;
+					};
+
+					mpddr_clk: mpddr_clk {
+						#clock-cells = <0>;
+						reg = <13>;
+					};
+
+					matrix0_clk: matrix0_clk {
+						#clock-cells = <0>;
+						reg = <15>;
+					};
+
+					sdmmc0_hclk: sdmmc0_hclk {
+						#clock-cells = <0>;
+						reg = <31>;
+					};
+
+					sdmmc1_hclk: sdmmc1_hclk {
+						#clock-cells = <0>;
+						reg = <32>;
+					};
+
+					lcdc_clk: lcdc_clk {
+						#clock-cells = <0>;
+						reg = <45>;
+					};
+
+					isc_clk: isc_clk {
+						#clock-cells = <0>;
+						reg = <46>;
+					};
+
+					qspi0_clk: qspi0_clk {
+						#clock-cells = <0>;
+						reg = <52>;
+					};
+
+					qspi1_clk: qspi1_clk {
+						#clock-cells = <0>;
+						reg = <53>;
+					};
+				};
+
+				gck {
+					compatible = "atmel,sama5d2-clk-generated";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					interrupt-parent = <&pmc>;
+					clocks = <&main>, <&plla>, <&utmi>, <&mck>;
+
+					sdmmc0_gclk: sdmmc0_gclk {
+						#clock-cells = <0>;
+						reg = <31>;
+					};
+
+					sdmmc1_gclk: sdmmc1_gclk {
+						#clock-cells = <0>;
+						reg = <32>;
+					};
+
+					tcb0_gclk: tcb0_gclk {
+						#clock-cells = <0>;
+						reg = <35>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					tcb1_gclk: tcb1_gclk {
+						#clock-cells = <0>;
+						reg = <36>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					pwm_gclk: pwm_gclk {
+						#clock-cells = <0>;
+						reg = <38>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
+					pdmic_gclk: pdmic_gclk {
+						#clock-cells = <0>;
+						reg = <48>;
+					};
+
+					i2s0_gclk: i2s0_gclk {
+						#clock-cells = <0>;
+						reg = <54>;
+					};
+
+					i2s1_gclk: i2s1_gclk {
+						#clock-cells = <0>;
+						reg = <55>;
+					};
+
+					can0_gclk: can0_gclk {
+						#clock-cells = <0>;
+						reg = <56>;
+						atmel,clk-output-range = <0 80000000>;
+					};
+
+					can1_gclk: can1_gclk {
+						#clock-cells = <0>;
+						reg = <57>;
+						atmel,clk-output-range = <0 80000000>;
+					};
+
+					classd_gclk: classd_gclk {
+						#clock-cells = <0>;
+						reg = <59>;
+						atmel,clk-output-range = <0 100000000>;
+					};
+				};
+			};
+
+			qspi0: spi@f0020000 {
+				compatible = "atmel,sama5d2-qspi";
+				reg = <0xf0020000 0x100>, <0xd0000000 0x08000000>;
+				reg-names = "qspi_base", "qspi_mmap";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&qspi0_clk>;
+				status = "disabled";
+			};
+
+			spi0: spi@f8000000 {
+				compatible = "atmel,at91rm9200-spi";
+				reg = <0xf8000000 0x100>;
+				clocks = <&spi0_clk>;
+				clock-names = "spi_clk";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			macb0: ethernet@f8008000 {
+				compatible = "cdns,macb";
+				reg = <0xf8008000 0x1000>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&macb0_clk>, <&macb0_clk>;
+				clock-names = "hclk", "pclk";
+				status = "disabled";
+			};
+
+			uart1: serial@f8020000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xf8020000 0x100>;
+				status = "disabled";
+			};
+
+			i2c0: i2c@f8028000 {
+				compatible = "atmel,sama5d2-i2c";
+				reg = <0xf8028000 0x100>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&twi0_clk>;
+				status = "disabled";
+			};
+
+			sckc@f8048050 {
+				compatible = "atmel,at91sam9x5-sckc";
+				reg = <0xf8048050 0x4>;
+
+				slow_rc_osc: slow_rc_osc {
+					compatible = "atmel,at91sam9x5-clk-slow-rc-osc";
+					#clock-cells = <0>;
+					clock-frequency = <32768>;
+					clock-accuracy = <250000000>;
+					atmel,startup-time-usec = <75>;
+				};
+
+				slow_osc: slow_osc {
+					compatible = "atmel,at91sam9x5-clk-slow-osc";
+					#clock-cells = <0>;
+					clocks = <&slow_xtal>;
+					atmel,startup-time-usec = <1200000>;
+				};
+
+				clk32k: slowck {
+					compatible = "atmel,at91sam9x5-clk-slow";
+					#clock-cells = <0>;
+					clocks = <&slow_rc_osc &slow_osc>;
+				};
+			};
+
+			spi1: spi@fc000000 {
+				compatible = "atmel,at91rm9200-spi";
+				reg = <0xfc000000 0x100>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@fc028000 {
+				compatible = "atmel,sama5d2-i2c";
+				reg = <0xfc028000 0x100>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&twi1_clk>;
+				status = "disabled";
+			};
+
+			pioA: gpio@fc038000 {
+				compatible = "atmel,sama5d2-gpio";
+				reg = <0xfc038000 0x600>;
+				clocks = <&pioA_clk>;
+				gpio-controller;
+				#gpio-cells = <2>;
+
+				pinctrl {
+					compatible = "atmel,sama5d2-pinctrl";
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/sun50i-a64-pine64-plus.dts b/arch/arm/dts/sun50i-a64-pine64-plus.dts
index 549dc15..389c609 100644
--- a/arch/arm/dts/sun50i-a64-pine64-plus.dts
+++ b/arch/arm/dts/sun50i-a64-pine64-plus.dts
@@ -57,3 +57,16 @@
 		reg = <0x40000000 0x40000000>;
 	};
 };
+
+&emac {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>;
+	phy-mode = "rgmii";
+	phy = <&phy1>;
+	status = "okay";
+
+	phy1: ethernet-phy@1 {
+	reg = <1>;
+	};
+};
+
diff --git a/arch/arm/dts/sun50i-a64.dtsi b/arch/arm/dts/sun50i-a64.dtsi
index 1bd436f..7d0dc76 100644
--- a/arch/arm/dts/sun50i-a64.dtsi
+++ b/arch/arm/dts/sun50i-a64.dtsi
@@ -506,6 +506,25 @@
 				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
 				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 			};
+
+			rmii_pins: rmii_pins {
+				allwinner,pins = "PD10", "PD11", "PD13", "PD14",
+						 "PD17", "PD18", "PD19", "PD20",
+						 "PD22", "PD23";
+				allwinner,function = "emac";
+				allwinner,drive = <SUN4I_PINCTRL_40_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
+
+			rgmii_pins: rgmii_pins {
+				allwinner,pins = "PD8", "PD9", "PD10", "PD11",
+						 "PD12", "PD13", "PD15",
+						 "PD16", "PD17", "PD18", "PD19",
+						 "PD20", "PD21", "PD22", "PD23";
+				allwinner,function = "emac";
+				allwinner,drive = <SUN4I_PINCTRL_40_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
 		};
 
 		ahb_rst: reset@1c202c0 {
@@ -620,5 +639,19 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 		};
+
+		emac: ethernet@01c30000 {
+			compatible = "allwinner,sun50i-a64-emac";
+			reg = <0x01c30000 0x2000>, <0x01c00030 0x4>;
+			reg-names = "emac", "syscon";
+			interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+			resets = <&ahb_rst 17>;
+			reset-names = "ahb";
+			clocks = <&bus_gates 17>;
+			clock-names = "ahb";
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
 	};
 };
diff --git a/arch/arm/dts/sun5i-a10s.dtsi b/arch/arm/dts/sun5i-a10s.dtsi
index bddd0de..a5f8855 100644
--- a/arch/arm/dts/sun5i-a10s.dtsi
+++ b/arch/arm/dts/sun5i-a10s.dtsi
@@ -241,6 +241,20 @@
 		allwinner,drive = <SUN4I_PINCTRL_30_MA>;
 		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 	};
+
+	nand_cs2_pins_a: nand_cs@2 {
+		allwinner,pins = "PC17";
+		allwinner,function = "nand0";
+		allwinner,drive = <0>;
+		allwinner,pull = <0>;
+	};
+
+	nand_cs3_pins_a: nand_cs@3 {
+		allwinner,pins = "PC18";
+		allwinner,function = "nand0";
+		allwinner,drive = <0>;
+		allwinner,pull = <0>;
+	};
 };
 
 &sram_a {
diff --git a/arch/arm/dts/sun5i-a13-olinuxino.dts b/arch/arm/dts/sun5i-a13-olinuxino.dts
index b3c234c..30e069a 100644
--- a/arch/arm/dts/sun5i-a13-olinuxino.dts
+++ b/arch/arm/dts/sun5i-a13-olinuxino.dts
@@ -155,6 +155,21 @@
 	status = "okay";
 };
 
+&nfc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&nand_pins_a &nand_cs0_pins_a &nand_rb0_pins_a>;
+	status = "okay";
+
+	nand@0 {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		reg = <0>;
+		allwinner,rb = <0>;
+		nand-ecc-mode = "hw";
+		allwinner,randomize;
+	};
+};
+
 &ohci0 {
 	status = "okay";
 };
diff --git a/arch/arm/dts/sun5i-r8-chip.dts b/arch/arm/dts/sun5i-r8-chip.dts
index 6ad19e2..b1b62d5 100644
--- a/arch/arm/dts/sun5i-r8-chip.dts
+++ b/arch/arm/dts/sun5i-r8-chip.dts
@@ -142,6 +142,21 @@
 	status = "okay";
 };
 
+&nfc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&nand_pins_a &nand_cs0_pins_a &nand_rb0_pins_a>;
+	status = "okay";
+
+	nand@0 {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		reg = <0>;
+		allwinner,rb = <0>;
+		nand-ecc-mode = "hw";
+		nand-on-flash-bbt;
+	};
+};
+
 &ohci0 {
 	status = "okay";
 };
diff --git a/arch/arm/dts/sun5i.dtsi b/arch/arm/dts/sun5i.dtsi
index 59a9426..87e5353 100644
--- a/arch/arm/dts/sun5i.dtsi
+++ b/arch/arm/dts/sun5i.dtsi
@@ -356,6 +356,17 @@
 			#dma-cells = <2>;
 		};
 
+		nfc: nand@01c03000 {
+			compatible = "allwinner,sun4i-a10-nand";
+			reg = <0x01c03000 0x1000>;
+			interrupts = <37>;
+			clocks = <&ahb_gates 13>, <&nand_clk>;
+			clock-names = "ahb", "mod";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		spi0: spi@01c05000 {
 			compatible = "allwinner,sun4i-a10-spi";
 			reg = <0x01c05000 0x1000>;
@@ -548,6 +559,44 @@
 				allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
 			};
 
+			nand_pins_a: nand_base0@0 {
+				allwinner,pins = "PC0", "PC1", "PC2",
+						"PC5", "PC8", "PC9", "PC10",
+						"PC11", "PC12", "PC13", "PC14",
+						"PC15";
+				allwinner,function = "nand0";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+
+			nand_cs0_pins_a: nand_cs@0 {
+				allwinner,pins = "PC4";
+				allwinner,function = "nand0";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+
+			nand_cs1_pins_a: nand_cs@1 {
+				allwinner,pins = "PC3";
+				allwinner,function = "nand0";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+
+			nand_rb0_pins_a: nand_rb@0 {
+				allwinner,pins = "PC6";
+				allwinner,function = "nand0";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+
+			nand_rb1_pins_a: nand_rb@1 {
+				allwinner,pins = "PC7";
+				allwinner,function = "nand0";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+
 			uart3_pins_a: uart3@0 {
 				allwinner,pins = "PG9", "PG10";
 				allwinner,function = "uart3";
diff --git a/arch/arm/dts/sun8i-h3-orangepi-2.dts b/arch/arm/dts/sun8i-h3-orangepi-2.dts
index f93f5d1..d3f8f55 100644
--- a/arch/arm/dts/sun8i-h3-orangepi-2.dts
+++ b/arch/arm/dts/sun8i-h3-orangepi-2.dts
@@ -184,3 +184,16 @@
 	usb1_vbus-supply = <&reg_usb1_vbus>;
 	status = "okay";
 };
+
+&emac {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>;
+	phy-mode = "rgmii";
+	phy = <&phy1>;
+	status = "okay";
+
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+	};
+};
+
diff --git a/arch/arm/dts/sun8i-h3-orangepi-lite.dts b/arch/arm/dts/sun8i-h3-orangepi-lite.dts
new file mode 100644
index 0000000..ac71749
--- /dev/null
+++ b/arch/arm/dts/sun8i-h3-orangepi-lite.dts
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2016 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "sun8i-h3.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+
+/ {
+	model = "Xunlong Orange Pi Lite";
+	compatible = "xunlong,orangepi-lite", "allwinner,sun8i-h3";
+
+	aliases {
+		/* The H3 emac is not used so the wifi is ethernet0 */
+		ethernet1 = &rtl8189ftv;
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&leds_opc>, <&leds_r_opc>;
+
+		pwr_led {
+			label = "orangepi:green:pwr";
+			gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>;
+			default-state = "on";
+		};
+
+		status_led {
+			label = "orangepi:red:status";
+			gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	r_gpio_keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&sw_r_opc>;
+
+		sw4 {
+			label = "sw4";
+			linux,code = <BTN_0>;
+			gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&ehci2 {
+	status = "okay";
+};
+
+&ir {
+	pinctrl-names = "default";
+	pinctrl-0 = <&ir_pins_a>;
+	status = "okay";
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
+	cd-inverted;
+	status = "okay";
+};
+
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins_a>;
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	non-removable;
+	status = "okay";
+
+	/*
+	 * Explicitly define the sdio device, so that we can add an ethernet
+	 * alias for it (which e.g. makes u-boot set a mac-address).
+	 */
+	rtl8189ftv: sdio_wifi@1 {
+		reg = <1>;
+	};
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&ohci2 {
+	status = "okay";
+};
+
+&pio {
+	leds_opc: led_pins@0 {
+		allwinner,pins = "PA15";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+};
+
+&r_pio {
+	leds_r_opc: led_pins@0 {
+		allwinner,pins = "PL10";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	sw_r_opc: key_pins@0 {
+		allwinner,pins = "PL3";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins_a>;
+	status = "okay";
+};
+
+&usbphy {
+	/* USB VBUS is always on */
+	status = "okay";
+};
diff --git a/arch/arm/dts/sun8i-h3-orangepi-one.dts b/arch/arm/dts/sun8i-h3-orangepi-one.dts
index 0adf932..8df5c74 100644
--- a/arch/arm/dts/sun8i-h3-orangepi-one.dts
+++ b/arch/arm/dts/sun8i-h3-orangepi-one.dts
@@ -94,6 +94,17 @@
 	status = "okay";
 };
 
+&emac {
+	phy = <&phy1>;
+	phy-mode = "mii";
+	allwinner,use-internal-phy;
+	allwinner,leds-active-low;
+	status = "okay";
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+	};
+};
+
 &mmc0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
diff --git a/arch/arm/dts/sun8i-h3-orangepi-pc-plus.dts b/arch/arm/dts/sun8i-h3-orangepi-pc-plus.dts
new file mode 100644
index 0000000..9a8cdd4
--- /dev/null
+++ b/arch/arm/dts/sun8i-h3-orangepi-pc-plus.dts
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* The Orange Pi PC Plus is an extended version of the regular PC */
+#include "sun8i-h3-orangepi-pc.dts"
+
+/ {
+	model = "Xunlong Orange Pi PC / PC Plus";
+
+	aliases {
+		/* ethernet0 is the H3 emac, defined in sun8i-h3.dtsi */
+		ethernet1 = &rtl8189ftv;
+	};
+};
+
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins_a>;
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	non-removable;
+	status = "okay";
+
+	/*
+	 * Explicitly define the sdio device, so that we can add an ethernet
+	 * alias for it (which e.g. makes u-boot set a mac-address).
+	 */
+	rtl8189ftv: sdio_wifi@1 {
+		reg = <1>;
+	};
+};
+
+&mmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_8bit_pins>;
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <8>;
+	non-removable;
+	cap-mmc-hw-reset;
+	status = "okay";
+};
+
+&mmc2_8bit_pins {
+	/* Increase drive strength for DDR modes */
+	allwinner,drive = <SUN4I_PINCTRL_40_MA>;
+	/* eMMC is missing pull-ups */
+	allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+};
diff --git a/arch/arm/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/dts/sun8i-h3-orangepi-pc.dts
index 30ccca0..0a74a91 100644
--- a/arch/arm/dts/sun8i-h3-orangepi-pc.dts
+++ b/arch/arm/dts/sun8i-h3-orangepi-pc.dts
@@ -173,3 +173,15 @@
 	/* USB VBUS is always on */
 	status = "okay";
 };
+
+&emac {
+	phy = <&phy1>;
+	phy-mode = "mii";
+	allwinner,use-internal-phy;
+	allwinner,leds-active-low;
+	status = "okay";
+
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+	};
+};
diff --git a/arch/arm/dts/sun8i-h3-orangepi-plus.dts b/arch/arm/dts/sun8i-h3-orangepi-plus.dts
index 900ec4f..28f74f6 100644
--- a/arch/arm/dts/sun8i-h3-orangepi-plus.dts
+++ b/arch/arm/dts/sun8i-h3-orangepi-plus.dts
@@ -40,26 +40,13 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/dts-v1/;
-#include "sun8i-h3.dtsi"
-#include "sunxi-common-regulators.dtsi"
-
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
+/* The Orange Pi Plus is an extended version of the Orange Pi 2 */
+#include "sun8i-h3-orangepi-2.dts"
 
 / {
-	model = "Xunlong Orange Pi Plus";
+	model = "Xunlong Orange Pi Plus / Plus 2 / Plus 2E";
 	compatible = "xunlong,orangepi-plus", "allwinner,sun8i-h3";
 
-	aliases {
-		serial0 = &uart0;
-	};
-
-	chosen {
-		stdout-path = "serial0:115200n8";
-	};
-
 	reg_usb3_vbus: usb3-vbus {
 		compatible = "regulator-fixed";
 		pinctrl-names = "default";
@@ -71,75 +58,42 @@
 		enable-active-high;
 		gpio = <&pio 6 11 GPIO_ACTIVE_HIGH>;
 	};
-
-	leds {
-		compatible = "gpio-leds";
-		pinctrl-names = "default";
-		pinctrl-0 = <&leds_opc>;
-
-		status_led {
-			label = "status:red:user";
-			gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>;
-		};
-	};
-
-	r_leds {
-		compatible = "gpio-leds";
-		pinctrl-names = "default";
-		pinctrl-0 = <&leds_r_opc>;
-
-		tx {
-			label = "pwr:green:user";
-			gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>;
-			default-state = "on";
-		};
-	};
-
-	r_gpio_keys {
-		compatible = "gpio-keys";
-		input-name = "sw4";
+};
 
-		pinctrl-names = "default";
-		pinctrl-0 = <&sw_r_opc>;
+&ehci2 {
+	status = "okay";
+};
 
-		sw4@0 {
-			label = "sw4";
-			linux,code = <BTN_0>;
-			gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>;
-		};
-	};
+&ehci3 {
+	status = "okay";
 };
 
-&pio {
-	leds_opc: led_pins@0 {
-		allwinner,pins = "PA15";
-		allwinner,function = "gpio_out";
-		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-	};
+&mmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_8bit_pins>;
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <8>;
+	non-removable;
+	cap-mmc-hw-reset;
+	status = "okay";
 };
 
-&r_pio {
-	leds_r_opc: led_pins@0 {
-		allwinner,pins = "PL10";
-		allwinner,function = "gpio_out";
-		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-	};
+&mmc2_8bit_pins {
+	/* Increase drive strength for DDR modes */
+	allwinner,drive = <SUN4I_PINCTRL_40_MA>;
+	/* eMMC is missing pull-ups */
+	allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+};
 
-	sw_r_opc: key_pins@0 {
-		allwinner,pins = "PL03";
-		allwinner,function = "gpio_in";
-		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-	};
+&ohci1 {
+	status = "okay";
 };
 
-&ehci1 {
+&ohci2 {
 	status = "okay";
 };
 
-&ehci3 {
+&ohci3 {
 	status = "okay";
 };
 
@@ -152,33 +106,6 @@
 	};
 };
 
-&mmc0 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
-	vmmc-supply = <&reg_vcc3v3>;
-	bus-width = <4>;
-	cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
-	cd-inverted;
-	status = "okay";
-};
-
-&reg_usb1_vbus {
-	gpio = <&pio 6 13 GPIO_ACTIVE_HIGH>;
-	status = "okay";
-};
-
-&uart0 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&uart0_pins_a>;
-	status = "okay";
-};
-
-&usb1_vbus_pin_a {
-	allwinner,pins = "PG13";
-};
-
 &usbphy {
-	usb1_vbus-supply = <&reg_usb1_vbus>;
 	usb3_vbus-supply = <&reg_usb3_vbus>;
-	status = "okay";
 };
diff --git a/arch/arm/dts/sun8i-h3.dtsi b/arch/arm/dts/sun8i-h3.dtsi
index c2f63c5..84e52b9 100644
--- a/arch/arm/dts/sun8i-h3.dtsi
+++ b/arch/arm/dts/sun8i-h3.dtsi
@@ -48,6 +48,10 @@
 / {
 	interrupt-parent = <&gic>;
 
+	aliases {
+		ethernet0 = <&emac>;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -501,6 +505,17 @@
 			interrupt-controller;
 			#interrupt-cells = <3>;
 
+			rgmii_pins: rgmii_pins {
+				allwinner,pins = "PD0", "PD1", "PD2", "PD3",
+						 "PD4", "PD5", "PD7",
+						 "PD8", "PD9", "PD10",
+						 "PD12", "PD13", "PD15",
+						 "PD16", "PD17";
+				allwinner,function = "emac";
+				allwinner,drive = <SUN4I_PINCTRL_40_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
+
 			uart0_pins_a: uart0@0 {
 				allwinner,pins = "PA4", "PA5";
 				allwinner,function = "uart0";
@@ -530,6 +545,16 @@
 				allwinner,drive = <SUN4I_PINCTRL_30_MA>;
 				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 			};
+
+			mmc2_8bit_pins: mmc2_8bit {
+				allwinner,pins = "PC5", "PC6", "PC8",
+						 "PC9", "PC10", "PC11",
+						 "PC12", "PC13", "PC14",
+						 "PC15", "PC16";
+				allwinner,function = "mmc2";
+				allwinner,drive = <SUN4I_PINCTRL_30_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
 		};
 
 		ahb_rst: reset@01c202c0 {
@@ -616,6 +641,20 @@
 			status = "disabled";
 		};
 
+		emac: ethernet@01c30000 {
+			compatible = "allwinner,sun8i-h3-emac";
+			reg = <0x01c30000 0x2000>, <0x01c00030 0x4>;
+			reg-names = "emac", "syscon";
+			interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+			resets = <&ahb_rst 17>, <&ahb_rst 66>;
+			reset-names = "ahb", "ephy";
+			clocks = <&bus_gates 17>, <&bus_gates 128>;
+			clock-names = "ahb", "ephy";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		gic: interrupt-controller@01c81000 {
 			compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
 			reg = <0x01c81000 0x1000>,
diff --git a/arch/arm/dts/tegra186-p2771-0000-a02.dts b/arch/arm/dts/tegra186-p2771-0000-a02.dts
new file mode 100644
index 0000000..36a3c21
--- /dev/null
+++ b/arch/arm/dts/tegra186-p2771-0000-a02.dts
@@ -0,0 +1,32 @@
+/dts-v1/;
+
+#include "tegra186-p2771-0000.dtsi"
+
+/ {
+	model = "NVIDIA P2771-0000 A02";
+	compatible = "nvidia,p2771-0000-a02", "nvidia,p2771-0000", "nvidia,tegra186";
+
+	sdhci@3400000 {
+		cd-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 6) GPIO_ACTIVE_LOW>;
+		power-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 5) GPIO_ACTIVE_HIGH>;
+	};
+
+	pcie-controller@10003000 {
+		status = "okay";
+
+		pci@1,0 {
+			status = "okay";
+			nvidia,num-lanes = <2>;
+		};
+
+		pci@2,0 {
+			status = "disabled";
+			nvidia,num-lanes = <1>;
+		};
+
+		pci@3,0 {
+			status = "okay";
+			nvidia,num-lanes = <1>;
+		};
+	};
+};
diff --git a/arch/arm/dts/tegra186-p2771-0000-b00.dts b/arch/arm/dts/tegra186-p2771-0000-b00.dts
new file mode 100644
index 0000000..0f1d0e8
--- /dev/null
+++ b/arch/arm/dts/tegra186-p2771-0000-b00.dts
@@ -0,0 +1,32 @@
+/dts-v1/;
+
+#include "tegra186-p2771-0000.dtsi"
+
+/ {
+	model = "NVIDIA P2771-0000 B00";
+	compatible = "nvidia,p2771-0000-b00", "nvidia,p2771-0000", "nvidia,tegra186";
+
+	sdhci@3400000 {
+		cd-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 5) GPIO_ACTIVE_LOW>;
+		power-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 6) GPIO_ACTIVE_HIGH>;
+	};
+
+	pcie-controller@10003000 {
+		status = "okay";
+
+		pci@1,0 {
+			status = "okay";
+			nvidia,num-lanes = <4>;
+		};
+
+		pci@2,0 {
+			status = "disabled";
+			nvidia,num-lanes = <0>;
+		};
+
+		pci@3,0 {
+			status = "disabled";
+			nvidia,num-lanes = <1>;
+		};
+	};
+};
diff --git a/arch/arm/dts/tegra186-p2771-0000.dts b/arch/arm/dts/tegra186-p2771-0000.dts
deleted file mode 100644
index 5f29ee4..0000000
--- a/arch/arm/dts/tegra186-p2771-0000.dts
+++ /dev/null
@@ -1,25 +0,0 @@
-/dts-v1/;
-
-#include "tegra186.dtsi"
-
-/ {
-	model = "NVIDIA P2771-0000";
-	compatible = "nvidia,p2771-0000", "nvidia,tegra186";
-
-	chosen {
-		stdout-path = &uarta;
-	};
-
-	aliases {
-		sdhci0 = "/sdhci@3460000";
-	};
-
-	memory {
-		reg = <0x0 0x80000000 0x0 0x60000000>;
-	};
-
-	sdhci@3460000 {
-		status = "okay";
-		bus-width = <8>;
-	};
-};
diff --git a/arch/arm/dts/tegra186-p2771-0000.dtsi b/arch/arm/dts/tegra186-p2771-0000.dtsi
new file mode 100644
index 0000000..d867674
--- /dev/null
+++ b/arch/arm/dts/tegra186-p2771-0000.dtsi
@@ -0,0 +1,72 @@
+#include "tegra186.dtsi"
+
+/ {
+	model = "NVIDIA P2771-0000";
+	compatible = "nvidia,p2771-0000", "nvidia,tegra186";
+
+	chosen {
+		stdout-path = &uarta;
+	};
+
+	aliases {
+		sdhci0 = "/sdhci@3460000";
+		sdhci1 = "/sdhci@3400000";
+		i2c0 = "/bpmp/i2c";
+		i2c1 = "/i2c@3160000";
+		i2c2 = "/i2c@c240000";
+		i2c3 = "/i2c@3180000";
+		i2c4 = "/i2c@3190000";
+		i2c5 = "/i2c@31c0000";
+		i2c6 = "/i2c@c250000";
+		i2c7 = "/i2c@31e0000";
+	};
+
+	memory {
+		reg = <0x0 0x80000000 0x0 0x60000000>;
+	};
+
+	i2c@3160000 {
+		status = "okay";
+	};
+
+	i2c@3180000 {
+		status = "okay";
+	};
+
+	i2c@3190000 {
+		status = "okay";
+	};
+
+	i2c@31c0000 {
+		status = "okay";
+	};
+
+	sdhci@3400000 {
+		status = "okay";
+		wp-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 4) GPIO_ACTIVE_HIGH>;
+		bus-width = <4>;
+	};
+
+	sdhci@3460000 {
+		status = "okay";
+		bus-width = <8>;
+	};
+
+	i2c@c240000 {
+		status = "okay";
+	};
+
+	i2c@c250000 {
+		status = "okay";
+	};
+
+	i2c@31e0000 {
+		status = "okay";
+	};
+
+	bpmp {
+		i2c {
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/dts/tegra186.dtsi b/arch/arm/dts/tegra186.dtsi
index fce34fa6..d9e7f03 100644
--- a/arch/arm/dts/tegra186.dtsi
+++ b/arch/arm/dts/tegra186.dtsi
@@ -1,14 +1,18 @@
 #include "skeleton.dtsi"
-#include <dt-bindings/gpio/tegra-gpio.h>
+#include <dt-bindings/clock/tegra186-clock.h>
+#include <dt-bindings/gpio/tegra186-gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/mailbox/tegra-hsp.h>
+#include <dt-bindings/mailbox/tegra186-hsp.h>
+#include <dt-bindings/power/tegra186-powergate.h>
+#include <dt-bindings/reset/tegra186-reset.h>
 
 / {
 	compatible = "nvidia,tegra186";
+	interrupt-parent = <&gic>;
 	#address-cells = <2>;
 	#size-cells = <2>;
 
-	gpio@2200000 {
+	gpio_main: gpio@2200000 {
 		compatible = "nvidia,tegra186-gpio";
 		reg-names = "security", "gpio";
 		reg =
@@ -34,26 +38,154 @@
 		status = "disabled";
 	};
 
+	gen1_i2c: i2c@3160000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x3160000 0x0 0x100>;
+		interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp TEGRA186_CLK_I2C1>;
+		clock-names = "i2c";
+		resets = <&bpmp TEGRA186_RESET_I2C1>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	cam_i2c: i2c@3180000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x3180000 0x0 0x100>;
+		interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp TEGRA186_CLK_I2C3>;
+		clock-names = "i2c";
+		resets = <&bpmp TEGRA186_RESET_I2C3>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	dp_aux_ch1_i2c: i2c@3190000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x3190000 0x0 0x100>;
+		interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp TEGRA186_CLK_I2C4>;
+		clock-names = "i2c";
+		resets = <&bpmp TEGRA186_RESET_I2C4>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	dp_aux_ch0_i2c: i2c@31b0000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x31b0000 0x0 0x100>;
+		interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp TEGRA186_CLK_I2C6>;
+		clock-names = "i2c";
+		resets = <&bpmp TEGRA186_RESET_I2C6>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	gen7_i2c: i2c@31c0000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x31c0000 0x0 0x100>;
+		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp TEGRA186_CLK_I2C7>;
+		clock-names = "i2c";
+		resets = <&bpmp TEGRA186_RESET_I2C7>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	gen9_i2c: i2c@31e0000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x31e0000 0x0 0x100>;
+		interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp TEGRA186_CLK_I2C9>;
+		clock-names = "i2c";
+		resets = <&bpmp TEGRA186_RESET_I2C9>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	sdhci@3400000 {
+		compatible = "nvidia,tegra186-sdhci";
+		reg = <0x0 0x03400000 0x0 0x200>;
+		resets = <&bpmp TEGRA186_RESET_SDMMC1>;
+		reset-names = "sdmmc";
+		clocks = <&bpmp TEGRA186_CLK_SDMMC1>;
+		clock-names = "sdmmc";
+		interrupts = <GIC_SPI 62 0x04>;
+		status = "disabled";
+	};
+
 	sdhci@3460000 {
 		compatible = "nvidia,tegra186-sdhci";
 		reg = <0x0 0x03460000 0x0 0x200>;
+		resets = <&bpmp TEGRA186_RESET_SDMMC4>;
+		reset-names = "sdmmc";
+		clocks = <&bpmp TEGRA186_CLK_SDMMC4>;
+		clock-names = "sdmmc";
 		interrupts = <GIC_SPI 31 0x04>;
 		status = "disabled";
 	};
 
+	gic: interrupt-controller@3881000 {
+		compatible = "arm,gic-400";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0x0 0x3881000 0x0 0x1000>,
+		      <0x0 0x3882000 0x0 0x2000>,
+		      <0x0 0x3884000 0x0 0x2000>,
+		      <0x0 0x3886000 0x0 0x2000>;
+		interrupts = <GIC_PPI 9
+			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+		interrupt-parent = <&gic>;
+	};
+
 	hsp: hsp@3c00000 {
 		compatible = "nvidia,tegra186-hsp";
 		reg = <0x0 0x03c00000 0x0 0xa0000>;
 		interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
-		nvidia,num-SM = <0x8>;
-		nvidia,num-AS = <0x2>;
-		nvidia,num-SS = <0x2>;
-		nvidia,num-DB = <0x7>;
-		nvidia,num-SI = <0x8>;
-		#mbox-cells = <1>;
+		interrupt-names = "doorbell";
+		#mbox-cells = <2>;
+	};
+
+	gen2_i2c: i2c@c240000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0xc240000 0x0 0x100>;
+		interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp TEGRA186_CLK_I2C2>;
+		clock-names = "i2c";
+		resets = <&bpmp TEGRA186_RESET_I2C2>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	gen8_i2c: i2c@c250000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0xc250000 0x0 0x100>;
+		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp TEGRA186_CLK_I2C8>;
+		clock-names = "i2c";
+		resets = <&bpmp TEGRA186_RESET_I2C8>;
+		reset-names = "i2c";
+		status = "disabled";
 	};
 
-	gpio@c2f0000 {
+	gpio_aon: gpio@c2f0000 {
 		compatible = "nvidia,tegra186-gpio-aon";
 		reg-names = "security", "gpio";
 		reg =
@@ -66,4 +198,124 @@
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
+
+	pcie-controller@10003000 {
+		compatible = "nvidia,tegra186-pcie";
+		device_type = "pci";
+		reg = <0x0 0x10003000 0x0 0x00000800   /* PADS registers */
+		       0x0 0x10003800 0x0 0x00000800   /* AFI registers */
+		       0x0 0x40000000 0x0 0x10000000>; /* configuration space */
+		reg-names = "pads", "afi", "cs";
+		interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>, /* controller interrupt */
+			     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>, /* MSI interrupt */
+			     <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; /* Wake interrupt */
+		interrupt-names = "intr", "msi", "wake";
+
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0>;
+		interrupt-map = <0 0 0 0 &gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+
+		bus-range = <0x00 0xff>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+
+		ranges = <0x82000000 0 0x10000000 0x0 0x10000000 0 0x00001000   /* port 0 configuration space */
+			  0x82000000 0 0x10001000 0x0 0x10001000 0 0x00001000   /* port 1 configuration space */
+			  0x82000000 0 0x10004000 0x0 0x10004000 0 0x00001000   /* port 2 configuration space */
+			  0x81000000 0 0x0        0x0 0x50000000 0 0x00010000   /* downstream I/O (64 KiB) */
+			  0x82000000 0 0x50100000 0x0 0x50100000 0 0x07f00000   /* non-prefetchable memory (127 MiB) */
+			  0xc2000000 0 0x58000000 0x0 0x58000000 0 0x28000000>; /* prefetchable memory (640 MiB) */
+
+		clocks = <&bpmp TEGRA186_CLK_PCIE>,
+			 <&bpmp TEGRA186_CLK_AFI>;
+		clock-names = "pex", "afi";
+		resets = <&bpmp TEGRA186_RESET_PCIE>,
+			 <&bpmp TEGRA186_RESET_AFI>,
+			 <&bpmp TEGRA186_RESET_PCIEXCLK>;
+		reset-names = "pex", "afi", "pcie_x";
+		power-domains = <&bpmp TEGRA186_POWER_DOMAIN_PCX>;
+		status = "disabled";
+
+		pci@1,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82000800 0 0x10000000 0 0x1000>;
+			reg = <0x000800 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <2>;
+		};
+
+		pci@2,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82001000 0 0x10001000 0 0x1000>;
+			reg = <0x001000 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <1>;
+		};
+
+		pci@3,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82001800 0 0x10004000 0 0x1000>;
+			reg = <0x001800 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <1>;
+		};
+	};
+
+	sysram@30000000 {
+		compatible = "nvidia,tegra186-sysram", "mmio-sram";
+		reg = <0x0 0x30000000 0x0 0x50000>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0 0x0 0x0 0x30000000 0x0 0x50000>;
+
+		sysram_cpu_bpmp_tx: shmem@4e000 {
+			compatible = "nvidia,tegra186-bpmp-shmem";
+			reg = <0x0 0x4e000 0x0 0x1000>;
+		};
+
+		sysram_cpu_bpmp_rx: shmem@4f000 {
+			compatible = "nvidia,tegra186-bpmp-shmem";
+			reg = <0x0 0x4f000 0x0 0x1000>;
+		};
+	};
+
+	bpmp: bpmp {
+		compatible = "nvidia,tegra186-bpmp";
+		mboxes = <&hsp HSP_MBOX_TYPE_DB HSP_DB_MASTER_BPMP>;
+		/*
+		 * In theory, these references, and the configuration in the
+		 * node these reference point at, are board-specific, since
+		 * they depend on the BCT's memory carve-out setup, the
+		 * firmware that's actually loaded onto the BPMP, etc. However,
+		 * in practice, all boards are likely to use identical values.
+		 */
+		shmem = <&sysram_cpu_bpmp_tx &sysram_cpu_bpmp_rx>;
+		#clock-cells = <1>;
+		#power-domain-cells = <1>;
+		#reset-cells = <1>;
+
+		bpmp_i2c: i2c {
+			compatible = "nvidia,tegra186-bpmp-i2c";
+			nvidia,bpmp = <&bpmp>;
+			nvidia,bpmp-bus-id = <5>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+	};
 };
diff --git a/arch/arm/dts/uniphier-proxstream2-gentil.dts b/arch/arm/dts/uniphier-proxstream2-gentil.dts
index 61f6164..1175703 100644
--- a/arch/arm/dts/uniphier-proxstream2-gentil.dts
+++ b/arch/arm/dts/uniphier-proxstream2-gentil.dts
@@ -19,13 +19,13 @@
 	};
 
 	chosen {
-		stdout-path = "serial2:115200n8";
+		stdout-path = "serial0:115200n8";
 	};
 
 	aliases {
-		serial0 = &serial0;
-		serial1 = &serial1;
-		serial2 = &serial2;
+		serial0 = &serial2;
+		serial1 = &serial0;
+		serial2 = &serial1;
 		i2c0 = &i2c0;
 		i2c2 = &i2c2;
 		i2c4 = &i2c4;
diff --git a/arch/arm/dts/uniphier-proxstream2-vodka.dts b/arch/arm/dts/uniphier-proxstream2-vodka.dts
index 3d5b300..928a092 100644
--- a/arch/arm/dts/uniphier-proxstream2-vodka.dts
+++ b/arch/arm/dts/uniphier-proxstream2-vodka.dts
@@ -19,13 +19,13 @@
 	};
 
 	chosen {
-		stdout-path = "serial2:115200n8";
+		stdout-path = "serial0:115200n8";
 	};
 
 	aliases {
-		serial0 = &serial0;
-		serial1 = &serial1;
-		serial2 = &serial2;
+		serial0 = &serial2;
+		serial1 = &serial0;
+		serial2 = &serial1;
 		i2c0 = &i2c0;
 		i2c4 = &i2c4;
 		i2c5 = &i2c5;
diff --git a/arch/arm/dts/zynqmp-clk.dtsi b/arch/arm/dts/zynqmp-clk.dtsi
index 3418909..0918c68 100644
--- a/arch/arm/dts/zynqmp-clk.dtsi
+++ b/arch/arm/dts/zynqmp-clk.dtsi
@@ -13,6 +13,7 @@
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <100000000>;
+		u-boot,dm-pre-reloc;
 	};
 
 	clk125: clk125 {
diff --git a/arch/arm/dts/zynqmp-ep108-clk.dtsi b/arch/arm/dts/zynqmp-ep108-clk.dtsi
index 48bb426..b3ce0de 100644
--- a/arch/arm/dts/zynqmp-ep108-clk.dtsi
+++ b/arch/arm/dts/zynqmp-ep108-clk.dtsi
@@ -13,6 +13,7 @@
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <25000000>;
+		u-boot,dm-pre-reloc;
 	};
 
 	i2c_clk: i2c_clk {
diff --git a/arch/arm/imx-common/ddrmc-vf610.c b/arch/arm/imx-common/ddrmc-vf610.c
index daf3c7e..9bc56f6 100644
--- a/arch/arm/imx-common/ddrmc-vf610.c
+++ b/arch/arm/imx-common/ddrmc-vf610.c
@@ -212,7 +212,7 @@
 			cr_setting++;
 		}
 
-	/* perform default PHY settings (may be overriden by custom settings */
+	/* perform default PHY settings (may be overridden by custom settings */
 	phy_setting = default_phy_settings;
 	while (phy_setting->phy_rnum >= 0) {
 		writel(phy_setting->setting,
diff --git a/arch/arm/include/asm/arch-am33xx/sys_proto.h b/arch/arm/include/asm/arch-am33xx/sys_proto.h
index 8f573d2..ed1a46c 100644
--- a/arch/arm/include/asm/arch-am33xx/sys_proto.h
+++ b/arch/arm/include/asm/arch-am33xx/sys_proto.h
@@ -25,9 +25,8 @@
 
 void sdelay(unsigned long);
 
-struct gpmc_cs;
 void gpmc_init(void);
-void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base,
+void enable_gpmc_cs_config(const u32 *gpmc_config, const struct gpmc_cs *cs, u32 base,
 			u32 size);
 void omap_nand_switch_ecc(uint32_t, uint32_t);
 
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/config.h b/arch/arm/include/asm/arch-fsl-layerscape/config.h
index 44fe0c0..b0ad4b4 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/config.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/config.h
@@ -149,43 +149,43 @@
 #define CONFIG_ARM_ERRATA_833471
 
 #define CONFIG_SYS_FSL_MAX_NUM_OF_SEC		1
-#elif defined(CONFIG_LS1043A)
-#define CONFIG_MAX_CPUS				4
+#elif defined(CONFIG_FSL_LSCH2)
 #define CONFIG_SYS_CACHELINE_SIZE		64
-#define CONFIG_SYS_FMAN_V3
-#define CONFIG_SYS_NUM_FMAN			1
-#define CONFIG_SYS_NUM_FM1_DTSEC		7
-#define CONFIG_SYS_NUM_FM1_10GEC		1
-#define CONFIG_SYS_FSL_IFC_BANK_COUNT		4
 #define CONFIG_NUM_DDR_CONTROLLERS		1
-#define CONFIG_SYS_CCSRBAR_DEFAULT		0x01000000
 #define CONFIG_SYS_FSL_SEC_COMPAT		5
 #define CONFIG_SYS_FSL_OCRAM_BASE		0x10000000 /* initial RAM */
-#define CONFIG_SYS_FSL_OCRAM_SIZE		0x200000 /* 2 MiB */
-#define CONFIG_SYS_FSL_DDR_BE
-#define CONFIG_SYS_DDR_BLOCK1_SIZE		((phys_size_t)2 << 30)
-#define CONFIG_MAX_MEM_MAPPED			CONFIG_SYS_DDR_BLOCK1_SIZE
+#define CONFIG_SYS_FSL_OCRAM_SIZE		0x00200000 /* 2M */
+#define CONFIG_SYS_CCSRBAR_DEFAULT		0x01000000
 
-#define CONFIG_SYS_FSL_CCSR_GUR_BE
 #define CONFIG_SYS_FSL_CCSR_SCFG_BE
-#define CONFIG_SYS_FSL_IFC_BE
 #define CONFIG_SYS_FSL_ESDHC_BE
 #define CONFIG_SYS_FSL_WDOG_BE
 #define CONFIG_SYS_FSL_DSPI_BE
 #define CONFIG_SYS_FSL_QSPI_BE
+#define CONFIG_SYS_FSL_CCSR_GUR_BE
 #define CONFIG_SYS_FSL_PEX_LUT_BE
+#define CONFIG_SYS_FSL_SEC_BE
+
+#define CONFIG_SYS_FSL_SRDS_1
+/* SoC related */
+#ifdef CONFIG_LS1043A
+#define CONFIG_MAX_CPUS				4
+#define CONFIG_SYS_FMAN_V3
+#define CONFIG_SYS_NUM_FMAN			1
+#define CONFIG_SYS_NUM_FM1_DTSEC		7
+#define CONFIG_SYS_NUM_FM1_10GEC		1
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT		4
+#define CONFIG_SYS_FSL_DDR_BE
+#define CONFIG_SYS_DDR_BLOCK1_SIZE		((phys_size_t)2 << 30)
+#define CONFIG_MAX_MEM_MAPPED			CONFIG_SYS_DDR_BLOCK1_SIZE
 
 #define QE_MURAM_SIZE		0x6000UL
 #define MAX_QE_RISC		1
 #define QE_NUM_OF_SNUM		28
 
-#define SRDS_MAX_LANES		4
-#define CONFIG_SYS_FSL_SRDS_1
-#define CONFIG_SYS_FSL_PCIE_COMPAT		"fsl,qoriq-pcie-v2.4"
-
+#define CONFIG_SYS_FSL_IFC_BE
 #define CONFIG_SYS_FSL_SFP_VER_3_2
 #define CONFIG_SYS_FSL_SEC_MON_BE
-#define CONFIG_SYS_FSL_SEC_BE
 #define CONFIG_SYS_FSL_SFP_BE
 #define CONFIG_SYS_FSL_SRK_LE
 #define CONFIG_KEY_REVOCATION
@@ -205,32 +205,40 @@
 #define CONFIG_SYS_FSL_MAX_NUM_OF_SEC		1
 #elif defined(CONFIG_LS1012A)
 #define CONFIG_MAX_CPUS                         1
-#define CONFIG_SYS_CACHELINE_SIZE		64
-#define CONFIG_NUM_DDR_CONTROLLERS		1
-#define CONFIG_SYS_CCSRBAR_DEFAULT		0x01000000
-#define CONFIG_SYS_FSL_SEC_COMPAT		5
 #undef	CONFIG_SYS_FSL_DDRC_ARM_GEN3
 
-#define CONFIG_SYS_FSL_OCRAM_BASE		0x10000000 /* initial RAM */
-#define CONFIG_SYS_FSL_OCRAM_SIZE		0x200000 /* 2 MiB */
-
 #define GICD_BASE		0x01401000
 #define GICC_BASE		0x01402000
+#elif defined(CONFIG_LS1046A)
+#define CONFIG_MAX_CPUS				4
+#define CONFIG_SYS_FMAN_V3
+#define CONFIG_SYS_NUM_FMAN			1
+#define CONFIG_SYS_NUM_FM1_DTSEC		8
+#define CONFIG_SYS_NUM_FM1_10GEC		2
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT		4
+#define CONFIG_SYS_FSL_DDR_BE
+#define CONFIG_SYS_DDR_BLOCK1_SIZE  ((phys_size_t)2 << 30)
+#define CONFIG_MAX_MEM_MAPPED           CONFIG_SYS_DDR_BLOCK1_SIZE
 
-#define CONFIG_SYS_FSL_CCSR_GUR_BE
-#define CONFIG_SYS_FSL_CCSR_SCFG_BE
-#define CONFIG_SYS_FSL_ESDHC_BE
-#define CONFIG_SYS_FSL_WDOG_BE
-#define CONFIG_SYS_FSL_DSPI_BE
-#define CONFIG_SYS_FSL_QSPI_BE
-#define CONFIG_SYS_FSL_PEX_LUT_BE
+#define CONFIG_SYS_FSL_SRDS_2
+#define CONFIG_SYS_FSL_IFC_BE
+#define CONFIG_SYS_FSL_SFP_VER_3_2
+#define CONFIG_SYS_FSL_SNVS_LE
+#define CONFIG_SYS_FSL_SFP_BE
+#define CONFIG_SYS_FSL_SRK_LE
+#define CONFIG_KEY_REVOCATION
 
-#define SRDS_MAX_LANES		4
-#define CONFIG_SYS_FSL_SRDS_1
-#define CONFIG_SYS_FSL_PCIE_COMPAT		"fsl,qoriq-pcie-v2.4"
-#define CONFIG_SYS_FSL_SEC_BE
+/* SMMU Defintions */
+#define SMMU_BASE		0x09000000
+
+/* Generic Interrupt Controller Definitions */
+#define GICD_BASE		0x01410000
+#define GICC_BASE		0x01420000
+
+#define CONFIG_SYS_FSL_MAX_NUM_OF_SEC		1
 #else
 #error SoC not defined
 #endif
+#endif
 
 #endif /* _ASM_ARMV8_FSL_LAYERSCAPE_CONFIG_H_ */
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/cpu.h b/arch/arm/include/asm/arch-fsl-layerscape/cpu.h
index 197b0eb..e2d96a1 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/cpu.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/cpu.h
@@ -13,35 +13,14 @@
 	CPU_TYPE_ENTRY(LS2045A, LS2045A, 4),
 	CPU_TYPE_ENTRY(LS1043A, LS1043A, 4),
 	CPU_TYPE_ENTRY(LS1023A, LS1023A, 2),
+	CPU_TYPE_ENTRY(LS1046A, LS1046A, 4),
+	CPU_TYPE_ENTRY(LS1026A, LS1026A, 2),
 	CPU_TYPE_ENTRY(LS2040A, LS2040A, 4),
 	CPU_TYPE_ENTRY(LS1012A, LS1012A, 1),
 };
 
 #ifndef CONFIG_SYS_DCACHE_OFF
 
-#define SECTION_SHIFT_L0		39UL
-#define SECTION_SHIFT_L1		30UL
-#define SECTION_SHIFT_L2		21UL
-#define BLOCK_SIZE_L0			0x8000000000
-#define BLOCK_SIZE_L1			0x40000000
-#define BLOCK_SIZE_L2			0x200000
-#define NUM_OF_ENTRY			512
-#define TCR_EL2_PS_40BIT		(2 << 16)
-
-#define LAYERSCAPE_VA_BITS		(40)
-#define LAYERSCAPE_TCR		(TCR_TG0_4K		| \
-				TCR_EL2_PS_40BIT	| \
-				TCR_SHARED_NON		| \
-				TCR_ORGN_NC		| \
-				TCR_IRGN_NC		| \
-				TCR_T0SZ(LAYERSCAPE_VA_BITS))
-#define LAYERSCAPE_TCR_FINAL	(TCR_TG0_4K		| \
-				TCR_EL2_PS_40BIT	| \
-				TCR_SHARED_OUTER	| \
-				TCR_ORGN_WBWA		| \
-				TCR_IRGN_WBWA		| \
-				TCR_T0SZ(LAYERSCAPE_VA_BITS))
-
 #ifdef CONFIG_FSL_LSCH3
 #define CONFIG_SYS_FSL_CCSR_BASE	0x00000000
 #define CONFIG_SYS_FSL_CCSR_SIZE	0x10000000
@@ -101,174 +80,261 @@
 #define CONFIG_SYS_FSL_DRAM_SIZE3	0x7800000000	/* 480GB */
 #endif
 
-struct sys_mmu_table {
-	u64 virt_addr;
-	u64 phys_addr;
-	u64 size;
-	u64 memory_type;
-	u64 attribute;
-};
-
-struct table_info {
-	u64 *ptr;
-	u64 table_base;
-	u64 entry_size;
-};
-
-static const struct sys_mmu_table early_mmu_table[] = {
+#define EARLY_PGTABLE_SIZE 0x5000
+static struct mm_region early_map[] = {
 #ifdef CONFIG_FSL_LSCH3
 	{ CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE,
-	  CONFIG_SYS_FSL_CCSR_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_FSL_CCSR_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_BASE,
-	  CONFIG_SYS_FSL_OCRAM_SIZE, MT_NORMAL, PTE_BLOCK_NON_SHARE },
+	  CONFIG_SYS_FSL_OCRAM_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE
+	},
 	{ CONFIG_SYS_FSL_QSPI_BASE1, CONFIG_SYS_FSL_QSPI_BASE1,
-	  CONFIG_SYS_FSL_QSPI_SIZE1,  MT_NORMAL, PTE_BLOCK_NON_SHARE},
+	  CONFIG_SYS_FSL_QSPI_SIZE1,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE},
 	/* For IFC Region #1, only the first 4MB is cache-enabled */
 	{ CONFIG_SYS_FSL_IFC_BASE1, CONFIG_SYS_FSL_IFC_BASE1,
-	  CONFIG_SYS_FSL_IFC_SIZE1_1, MT_NORMAL, PTE_BLOCK_NON_SHARE },
+	  CONFIG_SYS_FSL_IFC_SIZE1_1,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE
+	},
 	{ CONFIG_SYS_FSL_IFC_BASE1 + CONFIG_SYS_FSL_IFC_SIZE1_1,
 	  CONFIG_SYS_FSL_IFC_BASE1 + CONFIG_SYS_FSL_IFC_SIZE1_1,
 	  CONFIG_SYS_FSL_IFC_SIZE1 - CONFIG_SYS_FSL_IFC_SIZE1_1,
-	  MT_DEVICE_NGNRNE, PTE_BLOCK_NON_SHARE },
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
+	},
 	{ CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FSL_IFC_BASE1,
-	  CONFIG_SYS_FSL_IFC_SIZE1, MT_DEVICE_NGNRNE, PTE_BLOCK_NON_SHARE },
+	  CONFIG_SYS_FSL_IFC_SIZE1,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
+	},
 	{ CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1,
-	  CONFIG_SYS_FSL_DRAM_SIZE1, MT_NORMAL,
-	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS },
+	  CONFIG_SYS_FSL_DRAM_SIZE1,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
 	/* Map IFC region #2 up to CONFIG_SYS_FLASH_BASE for NAND boot */
 	{ CONFIG_SYS_FSL_IFC_BASE2, CONFIG_SYS_FSL_IFC_BASE2,
 	  CONFIG_SYS_FLASH_BASE - CONFIG_SYS_FSL_IFC_BASE2,
-	  MT_DEVICE_NGNRNE, PTE_BLOCK_NON_SHARE },
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
+	},
 	{ CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE,
-	  CONFIG_SYS_FSL_DCSR_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_FSL_DCSR_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2,
-	  CONFIG_SYS_FSL_DRAM_SIZE2, MT_NORMAL,
-	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS },
+	  CONFIG_SYS_FSL_DRAM_SIZE2,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
 #elif defined(CONFIG_FSL_LSCH2)
 	{ CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE,
-	  CONFIG_SYS_FSL_CCSR_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_FSL_CCSR_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_BASE,
-	  CONFIG_SYS_FSL_OCRAM_SIZE, MT_NORMAL, PTE_BLOCK_NON_SHARE },
+	  CONFIG_SYS_FSL_OCRAM_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE
+	},
 	{ CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE,
-	  CONFIG_SYS_FSL_DCSR_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_FSL_DCSR_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_FSL_QSPI_BASE, CONFIG_SYS_FSL_QSPI_BASE,
-	  CONFIG_SYS_FSL_QSPI_SIZE, MT_DEVICE_NGNRNE, PTE_BLOCK_NON_SHARE },
+	  CONFIG_SYS_FSL_QSPI_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
+	},
 	{ CONFIG_SYS_FSL_IFC_BASE, CONFIG_SYS_FSL_IFC_BASE,
-	  CONFIG_SYS_FSL_IFC_SIZE, MT_DEVICE_NGNRNE, PTE_BLOCK_NON_SHARE },
+	  CONFIG_SYS_FSL_IFC_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
+	},
 	{ CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1,
-	  CONFIG_SYS_FSL_DRAM_SIZE1, MT_NORMAL,
-	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS },
+	  CONFIG_SYS_FSL_DRAM_SIZE1,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
 	{ CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2,
-	  CONFIG_SYS_FSL_DRAM_SIZE2, MT_NORMAL,
-	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS },
+	  CONFIG_SYS_FSL_DRAM_SIZE2,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
 #endif
+	{},	/* list terminator */
 };
 
-static const struct sys_mmu_table final_mmu_table[] = {
+static struct mm_region final_map[] = {
 #ifdef CONFIG_FSL_LSCH3
 	{ CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE,
-	  CONFIG_SYS_FSL_CCSR_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_FSL_CCSR_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_BASE,
-	  CONFIG_SYS_FSL_OCRAM_SIZE, MT_NORMAL, PTE_BLOCK_NON_SHARE },
+	  CONFIG_SYS_FSL_OCRAM_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE
+	},
 	{ CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1,
-	  CONFIG_SYS_FSL_DRAM_SIZE1, MT_NORMAL,
-	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS },
+	  CONFIG_SYS_FSL_DRAM_SIZE1,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
 	{ CONFIG_SYS_FSL_QSPI_BASE1, CONFIG_SYS_FSL_QSPI_BASE1,
-	  CONFIG_SYS_FSL_QSPI_SIZE1,  MT_NORMAL, PTE_BLOCK_NON_SHARE},
+	  CONFIG_SYS_FSL_QSPI_SIZE1,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE
+	},
 	{ CONFIG_SYS_FSL_QSPI_BASE2, CONFIG_SYS_FSL_QSPI_BASE2,
-	  CONFIG_SYS_FSL_QSPI_SIZE2, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_FSL_QSPI_SIZE2,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_FSL_IFC_BASE2, CONFIG_SYS_FSL_IFC_BASE2,
-	  CONFIG_SYS_FSL_IFC_SIZE2, MT_DEVICE_NGNRNE, PTE_BLOCK_NON_SHARE },
+	  CONFIG_SYS_FSL_IFC_SIZE2,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
+	},
 	{ CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE,
-	  CONFIG_SYS_FSL_DCSR_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_FSL_DCSR_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_FSL_MC_BASE, CONFIG_SYS_FSL_MC_BASE,
-	  CONFIG_SYS_FSL_MC_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_FSL_MC_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_FSL_NI_BASE, CONFIG_SYS_FSL_NI_BASE,
-	  CONFIG_SYS_FSL_NI_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_FSL_NI_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	/* For QBMAN portal, only the first 64MB is cache-enabled */
 	{ CONFIG_SYS_FSL_QBMAN_BASE, CONFIG_SYS_FSL_QBMAN_BASE,
-	  CONFIG_SYS_FSL_QBMAN_SIZE_1, MT_NORMAL,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN | PTE_BLOCK_NS },
+	  CONFIG_SYS_FSL_QBMAN_SIZE_1,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN | PTE_BLOCK_NS
+	},
 	{ CONFIG_SYS_FSL_QBMAN_BASE + CONFIG_SYS_FSL_QBMAN_SIZE_1,
 	  CONFIG_SYS_FSL_QBMAN_BASE + CONFIG_SYS_FSL_QBMAN_SIZE_1,
 	  CONFIG_SYS_FSL_QBMAN_SIZE - CONFIG_SYS_FSL_QBMAN_SIZE_1,
-	  MT_DEVICE_NGNRNE, PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_PCIE1_PHYS_ADDR, CONFIG_SYS_PCIE1_PHYS_ADDR,
-	  CONFIG_SYS_PCIE1_PHYS_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_PCIE1_PHYS_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_PCIE2_PHYS_ADDR, CONFIG_SYS_PCIE2_PHYS_ADDR,
-	  CONFIG_SYS_PCIE2_PHYS_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_PCIE2_PHYS_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_PCIE3_PHYS_ADDR, CONFIG_SYS_PCIE3_PHYS_ADDR,
-	  CONFIG_SYS_PCIE3_PHYS_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_PCIE3_PHYS_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 #ifdef CONFIG_LS2080A
 	{ CONFIG_SYS_PCIE4_PHYS_ADDR, CONFIG_SYS_PCIE4_PHYS_ADDR,
-	  CONFIG_SYS_PCIE4_PHYS_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_PCIE4_PHYS_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 #endif
 	{ CONFIG_SYS_FSL_WRIOP1_BASE, CONFIG_SYS_FSL_WRIOP1_BASE,
-	  CONFIG_SYS_FSL_WRIOP1_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_FSL_WRIOP1_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_FSL_AIOP1_BASE, CONFIG_SYS_FSL_AIOP1_BASE,
-	  CONFIG_SYS_FSL_AIOP1_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_FSL_AIOP1_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_FSL_PEBUF_BASE, CONFIG_SYS_FSL_PEBUF_BASE,
-	  CONFIG_SYS_FSL_PEBUF_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_FSL_PEBUF_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2,
-	  CONFIG_SYS_FSL_DRAM_SIZE2, MT_NORMAL,
-	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS },
+	  CONFIG_SYS_FSL_DRAM_SIZE2,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
 #elif defined(CONFIG_FSL_LSCH2)
 	{ CONFIG_SYS_FSL_BOOTROM_BASE, CONFIG_SYS_FSL_BOOTROM_BASE,
-	  CONFIG_SYS_FSL_BOOTROM_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_FSL_BOOTROM_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE,
-	  CONFIG_SYS_FSL_CCSR_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_FSL_CCSR_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_BASE,
-	  CONFIG_SYS_FSL_OCRAM_SIZE, MT_NORMAL, PTE_BLOCK_NON_SHARE },
+	  CONFIG_SYS_FSL_OCRAM_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE
+	},
 	{ CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE,
-	  CONFIG_SYS_FSL_DCSR_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_FSL_DCSR_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_FSL_QSPI_BASE, CONFIG_SYS_FSL_QSPI_BASE,
-	  CONFIG_SYS_FSL_QSPI_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_FSL_QSPI_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_FSL_IFC_BASE, CONFIG_SYS_FSL_IFC_BASE,
-	  CONFIG_SYS_FSL_IFC_SIZE, MT_DEVICE_NGNRNE, PTE_BLOCK_NON_SHARE },
+	  CONFIG_SYS_FSL_IFC_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
+	},
 	{ CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1,
-	  CONFIG_SYS_FSL_DRAM_SIZE1, MT_NORMAL,
-	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS },
+	  CONFIG_SYS_FSL_DRAM_SIZE1,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
 	{ CONFIG_SYS_FSL_QBMAN_BASE, CONFIG_SYS_FSL_QBMAN_BASE,
-	  CONFIG_SYS_FSL_QBMAN_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_FSL_QBMAN_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2,
-	  CONFIG_SYS_FSL_DRAM_SIZE2, MT_NORMAL,
-	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS },
+	  CONFIG_SYS_FSL_DRAM_SIZE2,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
 	{ CONFIG_SYS_PCIE1_PHYS_ADDR, CONFIG_SYS_PCIE1_PHYS_ADDR,
-	  CONFIG_SYS_PCIE1_PHYS_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_PCIE1_PHYS_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_PCIE2_PHYS_ADDR, CONFIG_SYS_PCIE2_PHYS_ADDR,
-	  CONFIG_SYS_PCIE2_PHYS_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_PCIE2_PHYS_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_PCIE3_PHYS_ADDR, CONFIG_SYS_PCIE3_PHYS_ADDR,
-	  CONFIG_SYS_PCIE3_PHYS_SIZE, MT_DEVICE_NGNRNE,
-	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN },
+	  CONFIG_SYS_PCIE3_PHYS_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
 	{ CONFIG_SYS_FSL_DRAM_BASE3, CONFIG_SYS_FSL_DRAM_BASE3,
-	  CONFIG_SYS_FSL_DRAM_SIZE3, MT_NORMAL,
-	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS },
+	  CONFIG_SYS_FSL_DRAM_SIZE3,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
 #endif
-};
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+	{},	/* space holder for secure mem */
 #endif
+	{},
+};
+#endif	/* !CONFIG_SYS_DCACHE_OFF */
 
 int fsl_qoriq_core_to_cluster(unsigned int core);
 u32 cpu_mask(void);
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h b/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
index 487cba8..e1b3f44 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
@@ -140,6 +140,7 @@
 
 enum srds {
 	FSL_SRDS_1  = 0,
+	FSL_SRDS_2  = 1,
 };
 
 #endif
@@ -150,7 +151,7 @@
 enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane);
 int is_serdes_prtcl_valid(int serdes, u32 prtcl);
 
-#ifdef	CONFIG_LS1043A
+#ifdef CONFIG_FSL_LSCH2
 const char *serdes_clock_to_string(u32 clock);
 int get_serdes_protocol(void);
 #endif
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h
index 8b8a7c1..95a4293 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h
@@ -31,9 +31,9 @@
 #define CONFIG_SYS_NS16550_COM2			(CONFIG_SYS_IMMR + 0x011c0600)
 #define CONFIG_SYS_NS16550_COM3			(CONFIG_SYS_IMMR + 0x011d0500)
 #define CONFIG_SYS_NS16550_COM4			(CONFIG_SYS_IMMR + 0x011d0600)
-#define CONFIG_SYS_LS1043A_XHCI_USB1_ADDR	(CONFIG_SYS_IMMR + 0x01f00000)
-#define CONFIG_SYS_LS1043A_XHCI_USB2_ADDR	(CONFIG_SYS_IMMR + 0x02000000)
-#define CONFIG_SYS_LS1043A_XHCI_USB3_ADDR	(CONFIG_SYS_IMMR + 0x02100000)
+#define CONFIG_SYS_XHCI_USB1_ADDR		(CONFIG_SYS_IMMR + 0x01f00000)
+#define CONFIG_SYS_XHCI_USB2_ADDR		(CONFIG_SYS_IMMR + 0x02000000)
+#define CONFIG_SYS_XHCI_USB3_ADDR		(CONFIG_SYS_IMMR + 0x02100000)
 #define CONFIG_SYS_PCIE1_ADDR			(CONFIG_SYS_IMMR + 0x2400000)
 #define CONFIG_SYS_PCIE2_ADDR			(CONFIG_SYS_IMMR + 0x2500000)
 #define CONFIG_SYS_PCIE3_ADDR			(CONFIG_SYS_IMMR + 0x2600000)
@@ -94,6 +94,7 @@
 #define TY_ITYP_VER_A7          0x1
 #define TY_ITYP_VER_A53         0x2
 #define TY_ITYP_VER_A57         0x3
+#define TY_ITYP_VER_A72		0x4
 
 #define TP_CLUSTER_EOC		0xc0000000      /* end of clusters */
 #define TP_CLUSTER_INIT_MASK    0x0000003f      /* initiator mask */
@@ -227,6 +228,8 @@
 #define FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_MASK	0x3f
 #define FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK	0xffff0000
 #define FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT	16
+#define FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK	0x0000ffff
+#define FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT	0
 #define RCW_SB_EN_REG_INDEX	7
 #define RCW_SB_EN_MASK		0x00200000
 
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h
index 3ad46eb..93e26c1 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h
@@ -52,8 +52,8 @@
 #define I2C3_BASE_ADDR				(CONFIG_SYS_IMMR + 0x01020000)
 #define I2C4_BASE_ADDR				(CONFIG_SYS_IMMR + 0x01030000)
 
-#define CONFIG_SYS_LS2080A_XHCI_USB1_ADDR	(CONFIG_SYS_IMMR + 0x02100000)
-#define CONFIG_SYS_LS2080A_XHCI_USB2_ADDR	(CONFIG_SYS_IMMR + 0x02110000)
+#define CONFIG_SYS_XHCI_USB1_ADDR		(CONFIG_SYS_IMMR + 0x02100000)
+#define CONFIG_SYS_XHCI_USB2_ADDR		(CONFIG_SYS_IMMR + 0x02110000)
 
 /* TZ Address Space Controller Definitions */
 #define TZASC1_BASE			0x01100000	/* as per CCSR map. */
@@ -156,6 +156,7 @@
 #define TY_ITYP_VER_A7		0x1
 #define TY_ITYP_VER_A53		0x2
 #define TY_ITYP_VER_A57		0x3
+#define TY_ITYP_VER_A72		0x4
 
 #define TP_CLUSTER_EOC		0x80000000	/* end of clusters */
 #define TP_CLUSTER_INIT_MASK	0x0000003f	/* initiator mask */
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/ppa.h b/arch/arm/include/asm/arch-fsl-layerscape/ppa.h
new file mode 100644
index 0000000..1f1442b
--- /dev/null
+++ b/arch/arm/include/asm/arch-fsl-layerscape/ppa.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2016 NXP Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __FSL_PPA_H_
+#define __FSL_PPA_H_
+
+#define SEC_FIRMWARE_FIT_IMAGE		"firmware"
+#define SEC_FIRMEWARE_FIT_CNF_NAME	"config@1"
+#define SEC_FIRMWARE_TARGET_EL		2
+
+int ppa_init(void);
+
+#endif
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/soc.h b/arch/arm/include/asm/arch-fsl-layerscape/soc.h
index 39e8c7a..8d4a7ad 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/soc.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/soc.h
@@ -44,6 +44,8 @@
 #define SVR_LS1012A		0x870400
 #define SVR_LS1043A		0x879200
 #define SVR_LS1023A		0x879208
+#define SVR_LS1046A		0x870700
+#define SVR_LS1026A		0x870708
 #define SVR_LS2045A		0x870120
 #define SVR_LS2080A		0x870110
 #define SVR_LS2085A		0x870100
diff --git a/arch/arm/include/asm/arch-ls102xa/config.h b/arch/arm/include/asm/arch-ls102xa/config.h
index 04abec4..d408fe4 100644
--- a/arch/arm/include/asm/arch-ls102xa/config.h
+++ b/arch/arm/include/asm/arch-ls102xa/config.h
@@ -10,7 +10,7 @@
 #define CONFIG_SYS_CACHELINE_SIZE		64
 
 #define OCRAM_BASE_ADDR				0x10000000
-#define OCRAM_SIZE				0x00020000
+#define OCRAM_SIZE				0x00010000
 #define OCRAM_BASE_S_ADDR			0x10010000
 #define OCRAM_S_SIZE				0x00010000
 
@@ -32,16 +32,15 @@
 #define CONFIG_SYS_FSL_SERDES_ADDR		(CONFIG_SYS_IMMR + 0x00ea0000)
 #define CONFIG_SYS_FSL_GUTS_ADDR		(CONFIG_SYS_IMMR + 0x00ee0000)
 #define CONFIG_SYS_FSL_LS1_CLK_ADDR		(CONFIG_SYS_IMMR + 0x00ee1000)
+#define CONFIG_SYS_FSL_RCPM_ADDR		(CONFIG_SYS_IMMR + 0x00ee2000)
 #define CONFIG_SYS_NS16550_COM1			(CONFIG_SYS_IMMR + 0x011c0500)
 #define CONFIG_SYS_NS16550_COM2			(CONFIG_SYS_IMMR + 0x011d0500)
 #define CONFIG_SYS_DCU_ADDR			(CONFIG_SYS_IMMR + 0x01ce0000)
-#define CONFIG_SYS_LS102XA_XHCI_USB1_ADDR	(CONFIG_SYS_IMMR + 0x02100000)
-#define CONFIG_SYS_LS102XA_USB1_ADDR \
-	(CONFIG_SYS_IMMR + CONFIG_SYS_LS102XA_USB1_OFFSET)
+#define CONFIG_SYS_XHCI_USB1_ADDR		(CONFIG_SYS_IMMR + 0x02100000)
+#define CONFIG_SYS_EHCI_USB1_ADDR		(CONFIG_SYS_IMMR + 0x07600000)
 
 #define CONFIG_SYS_FSL_SEC_OFFSET		0x00700000
 #define CONFIG_SYS_FSL_JR0_OFFSET		0x00710000
-#define CONFIG_SYS_LS102XA_USB1_OFFSET		0x07600000
 #define CONFIG_SYS_TSEC1_OFFSET			0x01d10000
 #define CONFIG_SYS_TSEC2_OFFSET			0x01d50000
 #define CONFIG_SYS_TSEC3_OFFSET			0x01d90000
diff --git a/arch/arm/include/asm/arch-omap3/sys_proto.h b/arch/arm/include/asm/arch-omap3/sys_proto.h
index 24563c0..5979340 100644
--- a/arch/arm/include/asm/arch-omap3/sys_proto.h
+++ b/arch/arm/include/asm/arch-omap3/sys_proto.h
@@ -40,11 +40,12 @@
 void do_sdrc_init(u32, u32);
 
 void get_board_mem_timings(struct board_sdrc_timings *timings);
-void identify_nand_chip(int *mfr, int *id);
+int identify_nand_chip(int *mfr, int *id);
 void emif4_init(void);
 void gpmc_init(void);
-void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base,
-			u32 size);
+void enable_gpmc_cs_config(const u32 *gpmc_config, const struct gpmc_cs *cs,
+				u32 base, u32 size);
+void set_gpmc_cs0(int flash_type);
 
 void watchdog_init(void);
 void set_muxconf_regs(void);
diff --git a/arch/arm/include/asm/arch-omap4/i2c.h b/arch/arm/include/asm/arch-omap4/i2c.h
index adc8eb2..463e979 100644
--- a/arch/arm/include/asm/arch-omap4/i2c.h
+++ b/arch/arm/include/asm/arch-omap4/i2c.h
@@ -14,9 +14,9 @@
 	unsigned short revnb_lo;	/* 0x00 */
 	unsigned short res1;
 	unsigned short revnb_hi;	/* 0x04 */
-	unsigned short res2[13];
-	unsigned short sysc;		/* 0x20 */
-	unsigned short res3;
+	unsigned short res2[5];
+	unsigned short sysc;		/* 0x10 */
+	unsigned short res3[9];
 	unsigned short irqstatus_raw;	/* 0x24 */
 	unsigned short res4;
 	unsigned short stat;		/* 0x28 */
diff --git a/arch/arm/include/asm/arch-omap5/i2c.h b/arch/arm/include/asm/arch-omap5/i2c.h
index d875cfe..2b55edf 100644
--- a/arch/arm/include/asm/arch-omap5/i2c.h
+++ b/arch/arm/include/asm/arch-omap5/i2c.h
@@ -14,9 +14,9 @@
 	unsigned short revnb_lo;	/* 0x00 */
 	unsigned short res1;
 	unsigned short revnb_hi;	/* 0x04 */
-	unsigned short res2[13];
-	unsigned short sysc;		/* 0x20 */
-	unsigned short res3;
+	unsigned short res2[5];
+	unsigned short sysc;		/* 0x10 */
+	unsigned short res3[9];
 	unsigned short irqstatus_raw;	/* 0x24 */
 	unsigned short res4;
 	unsigned short stat;		/* 0x28 */
diff --git a/arch/arm/include/asm/arch-rockchip/clock.h b/arch/arm/include/asm/arch-rockchip/clock.h
index 317e512..21edbc2 100644
--- a/arch/arm/include/asm/arch-rockchip/clock.h
+++ b/arch/arm/include/asm/arch-rockchip/clock.h
@@ -65,6 +65,8 @@
 struct rk3288_cru;
 struct rk3288_grf;
 
-void rkclk_configure_cpu(struct rk3288_cru *cru, struct rk3288_grf *grf);
+void rk3288_clk_configure_cpu(struct rk3288_cru *cru, struct rk3288_grf *grf);
+
+int rockchip_get_clk(struct udevice **devp);
 
 #endif
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3399.h b/arch/arm/include/asm/arch-rockchip/cru_rk3399.h
new file mode 100644
index 0000000..c919f47
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3399.h
@@ -0,0 +1,93 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __ASM_ARCH_CRU_RK3399_H_
+#define __ASM_ARCH_CRU_RK3399_H_
+
+#include <common.h>
+
+struct rk3399_pmucru {
+	u32 ppll_con[6];
+	u32 reserved[0x1a];
+	u32 pmucru_clksel[6];
+	u32 pmucru_clkfrac_con[2];
+	u32 reserved2[0x18];
+	u32 pmucru_clkgate_con[3];
+	u32 reserved3;
+	u32 pmucru_softrst_con[2];
+	u32 reserved4[2];
+	u32 pmucru_rstnhold_con[2];
+	u32 reserved5[2];
+	u32 pmucru_gatedis_con[2];
+};
+check_member(rk3399_pmucru, pmucru_gatedis_con[1], 0x134);
+
+struct rk3399_cru {
+	u32 apll_l_con[6];
+	u32 reserved[2];
+	u32 apll_b_con[6];
+	u32 reserved1[2];
+	u32 dpll_con[6];
+	u32 reserved2[2];
+	u32 cpll_con[6];
+	u32 reserved3[2];
+	u32 gpll_con[6];
+	u32 reserved4[2];
+	u32 npll_con[6];
+	u32 reserved5[2];
+	u32 vpll_con[6];
+	u32 reserved6[0x0a];
+	u32 clksel_con[108];
+	u32 reserved7[0x14];
+	u32 clkgate_con[35];
+	u32 reserved8[0x1d];
+	u32 softrst_con[21];
+	u32 reserved9[0x2b];
+	u32 glb_srst_fst_value;
+	u32 glb_srst_snd_value;
+	u32 glb_cnt_th;
+	u32 misc_con;
+	u32 glb_rst_con;
+	u32 glb_rst_st;
+	u32 reserved10[0x1a];
+	u32 sdmmc_con[2];
+	u32 sdio0_con[2];
+	u32 sdio1_con[2];
+};
+check_member(rk3399_cru, sdio1_con[1], 0x594);
+#define MHz		1000000
+#define KHz		1000
+#define OSC_HZ		(24*MHz)
+#define APLL_HZ		(600*MHz)
+#define GPLL_HZ		(594*MHz)
+#define CPLL_HZ		(384*MHz)
+#define PPLL_HZ		(594*MHz)
+
+#define PMU_PCLK_HZ	(99*MHz)
+
+#define ACLKM_CORE_HZ	(300*MHz)
+#define ATCLK_CORE_HZ	(300*MHz)
+#define PCLK_DBG_HZ	(100*MHz)
+
+#define PERIHP_ACLK_HZ	(148500*KHz)
+#define PERIHP_HCLK_HZ	(148500*KHz)
+#define PERIHP_PCLK_HZ	(37125*KHz)
+
+#define PERILP0_ACLK_HZ	(99000*KHz)
+#define PERILP0_HCLK_HZ	(99000*KHz)
+#define PERILP0_PCLK_HZ	(49500*KHz)
+
+#define PERILP1_HCLK_HZ	(99000*KHz)
+#define PERILP1_PCLK_HZ	(49500*KHz)
+
+#define PWM_CLOCK_HZ    PMU_PCLK_HZ
+
+enum apll_l_frequencies {
+	APLL_L_1600_MHZ,
+	APLL_L_600_MHZ,
+};
+
+#endif	/* __ASM_ARCH_CRU_RK3399_H_ */
diff --git a/arch/arm/include/asm/arch-rockchip/sdram.h b/arch/arm/include/asm/arch-rockchip/sdram.h
index d3de42d..e08e28f 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram.h
@@ -24,6 +24,12 @@
 	u8 row_3_4;
 	u8 cs0_row;
 	u8 cs1_row;
+	/*
+	 * For of-platdata, which would otherwise convert this into two
+	 * byte-swapped integers. With a size of 9 bytes, this struct will
+	 * appear in of-platdata as a byte array.
+	 */
+	u8 dummy;
 };
 
 struct rk3288_sdram_pctl_timing {
@@ -81,12 +87,4 @@
 	u32 odt;
 };
 
-struct rk3288_sdram_params {
-	struct rk3288_sdram_channel ch[2];
-	struct rk3288_sdram_pctl_timing pctl_timing;
-	struct rk3288_sdram_phy_timing phy_timing;
-	struct rk3288_base_params base;
-	int num_channels;
-};
-
 #endif
diff --git a/arch/arm/include/asm/arch-stm32f7/fmc.h b/arch/arm/include/asm/arch-stm32f7/fmc.h
new file mode 100644
index 0000000..7dd5077
--- /dev/null
+++ b/arch/arm/include/asm/arch-stm32f7/fmc.h
@@ -0,0 +1,75 @@
+/*
+ * (C) Copyright 2013
+ * Pavel Boldin, Emcraft Systems, paboldin@emcraft.com
+ *
+ * (C) Copyright 2015
+ * Kamil Lulko, <kamil.lulko@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _MACH_FMC_H_
+#define _MACH_FMC_H_
+
+struct stm32_fmc_regs {
+	u32 sdcr1;	/* Control register 1 */
+	u32 sdcr2;	/* Control register 2 */
+	u32 sdtr1;	/* Timing register 1 */
+	u32 sdtr2;	/* Timing register 2 */
+	u32 sdcmr;	/* Mode register */
+	u32 sdrtr;	/* Refresh timing register */
+	u32 sdsr;	/* Status register */
+};
+
+/*
+ * FMC registers base
+ */
+#define STM32_SDRAM_FMC_BASE	0xA0000140
+#define STM32_SDRAM_FMC		((struct stm32_fmc_regs *)STM32_SDRAM_FMC_BASE)
+
+/* Control register SDCR */
+#define FMC_SDCR_RPIPE_SHIFT	13	/* RPIPE bit shift */
+#define FMC_SDCR_RBURST_SHIFT	12	/* RBURST bit shift */
+#define FMC_SDCR_SDCLK_SHIFT	10	/* SDRAM clock divisor shift */
+#define FMC_SDCR_WP_SHIFT	9	/* Write protection shift */
+#define FMC_SDCR_CAS_SHIFT	7	/* CAS latency shift */
+#define FMC_SDCR_NB_SHIFT	6	/* Number of banks shift */
+#define FMC_SDCR_MWID_SHIFT	4	/* Memory width shift */
+#define FMC_SDCR_NR_SHIFT	2	/* Number of row address bits shift */
+#define FMC_SDCR_NC_SHIFT	0	/* Number of col address bits shift */
+
+/* Timings register SDTR */
+#define FMC_SDTR_TMRD_SHIFT	0	/* Load mode register to active */
+#define FMC_SDTR_TXSR_SHIFT	4	/* Exit self-refresh time */
+#define FMC_SDTR_TRAS_SHIFT	8	/* Self-refresh time */
+#define FMC_SDTR_TRC_SHIFT	12	/* Row cycle delay */
+#define FMC_SDTR_TWR_SHIFT	16	/* Recovery delay */
+#define FMC_SDTR_TRP_SHIFT	20	/* Row precharge delay */
+#define FMC_SDTR_TRCD_SHIFT	24	/* Row-to-column delay */
+
+
+#define FMC_SDCMR_NRFS_SHIFT	5
+
+#define FMC_SDCMR_MODE_NORMAL		0
+#define FMC_SDCMR_MODE_START_CLOCK	1
+#define FMC_SDCMR_MODE_PRECHARGE	2
+#define FMC_SDCMR_MODE_AUTOREFRESH	3
+#define FMC_SDCMR_MODE_WRITE_MODE	4
+#define FMC_SDCMR_MODE_SELFREFRESH	5
+#define FMC_SDCMR_MODE_POWERDOWN	6
+
+#define FMC_SDCMR_BANK_1		(1 << 4)
+#define FMC_SDCMR_BANK_2		(1 << 3)
+
+#define FMC_SDCMR_MODE_REGISTER_SHIFT	9
+
+#define FMC_SDSR_BUSY			(1 << 5)
+
+#define FMC_BUSY_WAIT()		do { \
+		__asm__ __volatile__ ("dsb" : : : "memory"); \
+		while (STM32_SDRAM_FMC->sdsr & FMC_SDSR_BUSY) \
+			; \
+	} while (0)
+
+
+#endif /* _MACH_FMC_H_ */
diff --git a/arch/arm/include/asm/arch-stm32f7/stm32.h b/arch/arm/include/asm/arch-stm32f7/stm32.h
index 68bdab0..de55ae5 100644
--- a/arch/arm/include/asm/arch-stm32f7/stm32.h
+++ b/arch/arm/include/asm/arch-stm32f7/stm32.h
@@ -64,6 +64,52 @@
 };
 #define STM32_BUS_MASK          0xFFFF0000
 
+struct stm32_rcc_regs {
+	u32 cr;		/* RCC clock control */
+	u32 pllcfgr;	/* RCC PLL configuration */
+	u32 cfgr;	/* RCC clock configuration */
+	u32 cir;	/* RCC clock interrupt */
+	u32 ahb1rstr;	/* RCC AHB1 peripheral reset */
+	u32 ahb2rstr;	/* RCC AHB2 peripheral reset */
+	u32 ahb3rstr;	/* RCC AHB3 peripheral reset */
+	u32 rsv0;
+	u32 apb1rstr;	/* RCC APB1 peripheral reset */
+	u32 apb2rstr;	/* RCC APB2 peripheral reset */
+	u32 rsv1[2];
+	u32 ahb1enr;	/* RCC AHB1 peripheral clock enable */
+	u32 ahb2enr;	/* RCC AHB2 peripheral clock enable */
+	u32 ahb3enr;	/* RCC AHB3 peripheral clock enable */
+	u32 rsv2;
+	u32 apb1enr;	/* RCC APB1 peripheral clock enable */
+	u32 apb2enr;	/* RCC APB2 peripheral clock enable */
+	u32 rsv3[2];
+	u32 ahb1lpenr;	/* RCC AHB1 periph clk enable in low pwr mode */
+	u32 ahb2lpenr;	/* RCC AHB2 periph clk enable in low pwr mode */
+	u32 ahb3lpenr;	/* RCC AHB3 periph clk enable in low pwr mode */
+	u32 rsv4;
+	u32 apb1lpenr;	/* RCC APB1 periph clk enable in low pwr mode */
+	u32 apb2lpenr;	/* RCC APB2 periph clk enable in low pwr mode */
+	u32 rsv5[2];
+	u32 bdcr;	/* RCC Backup domain control */
+	u32 csr;	/* RCC clock control & status */
+	u32 rsv6[2];
+	u32 sscgr;	/* RCC spread spectrum clock generation */
+	u32 plli2scfgr;	/* RCC PLLI2S configuration */
+	u32 pllsaicfgr;
+	u32 dckcfgr;
+};
+#define STM32_RCC		((struct stm32_rcc_regs *)RCC_BASE)
+
+struct stm32_pwr_regs {
+	u32 cr1;   /* power control register 1 */
+	u32 csr1;  /* power control/status register 2 */
+	u32 cr2;   /* power control register 2 */
+	u32 csr2;  /* power control/status register 2 */
+};
+#define STM32_PWR		((struct stm32_pwr_regs *)PWR_BASE)
+
 int configure_clocks(void);
+unsigned long clock_get(enum clock clck);
+void stm32_flash_latency_cfg(int latency);
 
 #endif /* _ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
index 0088bb9..d1c5ad0 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
@@ -269,6 +269,11 @@
 #define CCM_MBUS_CTRL_CLK_SRC_PLL5 0x2
 #define CCM_MBUS_CTRL_GATE (0x1 << 31)
 
+#define CCM_NAND_CTRL_M(x)		((x) - 1)
+#define CCM_NAND_CTRL_N(x)		((x) << 16)
+#define CCM_NAND_CTRL_OSCM24		(0x0 << 24)
+#define CCM_NAND_CTRL_PLL6		(0x1 << 24)
+#define CCM_NAND_CTRL_PLL5		(0x2 << 24)
 #define CCM_NAND_CTRL_ENABLE		(0x1 << 31)
 
 #define CCM_MMC_CTRL_M(x)		((x) - 1)
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
index c2e72f5..d4dff1e 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -40,7 +40,8 @@
 	u32 ahb_gate1;		/* 0x64 ahb module clock gating 1 */
 	u32 apb1_gate;		/* 0x68 apb1 module clock gating */
 	u32 apb2_gate;		/* 0x6c apb2 module clock gating */
-	u32 reserved9[4];
+	u32 bus_gate4;          /* 0x70 gate 4 module clock gating */
+	u8 res3[0xc];
 	u32 nand0_clk_cfg;	/* 0x80 nand0 clock control */
 	u32 nand1_clk_cfg;	/* 0x84 nand1 clock control */
 	u32 sd0_clk_cfg;	/* 0x88 sd0 clock control */
@@ -387,6 +388,7 @@
 #define AHB_RESET_OFFSET_LCD0		4
 
 /* ahb_reset2 offsets */
+#define AHB_RESET_OFFSET_EPHY		2
 #define AHB_RESET_OFFSET_LVDS		0
 
 /* apb2 reset */
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
index c5e9d88..cd009d7 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
@@ -87,7 +87,8 @@
 #define SUNXI_KEYPAD_BASE		0x01c23000
 #define SUNXI_TZPC_BASE			0x01c23400
 
-#if defined(CONFIG_MACH_SUN8I_A83T) || defined(CONFIG_MACH_SUN8I_H3)
+#if defined(CONFIG_MACH_SUN8I_A83T) || defined(CONFIG_MACH_SUN8I_H3) || \
+defined(CONFIG_MACH_SUN50I)
 /* SID address space starts at 0x01c1400, but e-fuse is at offset 0x200 */
 #define SUNXI_SID_BASE			0x01c14200
 #else
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
index 1ace548..bff7d14 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -141,6 +141,7 @@
 /* GPIO pin function config */
 #define SUNXI_GPIO_INPUT	0
 #define SUNXI_GPIO_OUTPUT	1
+#define SUNXI_GPIO_DISABLE	7
 
 #define SUNXI_GPA_EMAC		2
 #define SUN6I_GPA_GMAC		2
@@ -162,8 +163,10 @@
 #define SUN50I_GPB_UART0	4
 
 #define SUNXI_GPC_NAND		2
+#define SUNXI_GPC_SPI0		3
 #define SUNXI_GPC_SDC2		3
 #define SUN6I_GPC_SDC3		4
+#define SUN50I_GPC_SPI0		4
 
 #define SUN8I_GPD_SDC1		3
 #define SUNXI_GPD_LCD0		2
diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h
index 3da360b..cb52e64 100644
--- a/arch/arm/include/asm/arch-sunxi/mmc.h
+++ b/arch/arm/include/asm/arch-sunxi/mmc.h
@@ -127,5 +127,4 @@
 #define SUNXI_MMC_COMMON_RESET			(1 << 18)
 
 struct mmc *sunxi_mmc_init(int sdc_no);
-int sunxi_mmc_has_egon_boot_signature(struct mmc *mmc);
 #endif /* _SUNXI_MMC_H */
diff --git a/arch/arm/include/asm/arch-sunxi/spl.h b/arch/arm/include/asm/arch-sunxi/spl.h
index ec73379..5d7ab55 100644
--- a/arch/arm/include/asm/arch-sunxi/spl.h
+++ b/arch/arm/include/asm/arch-sunxi/spl.h
@@ -51,7 +51,14 @@
 		uint8_t spl_signature[4];
 	};
 	uint32_t fel_script_address;
-	uint32_t reserved1[3];
+	/*
+	 * If the fel_uEnv_length member below is set to a non-zero value,
+	 * it specifies the size (byte count) of data at fel_script_address.
+	 * At the same time this indicates that the data is in uEnv.txt
+	 * compatible format, ready to be imported via "env import -t".
+	 */
+	uint32_t fel_uEnv_length;
+	uint32_t reserved1[2];
 	uint32_t boot_media;		/* written here by the boot ROM */
 	uint32_t reserved2[5];		/* padding, align to 64 bytes */
 };
diff --git a/arch/arm/include/asm/arch-tegra/board.h b/arch/arm/include/asm/arch-tegra/board.h
index 783bb3c..a3db7ed 100644
--- a/arch/arm/include/asm/arch-tegra/board.h
+++ b/arch/arm/include/asm/arch-tegra/board.h
@@ -20,7 +20,7 @@
 /*
  * Hooks to allow boards to set up the pinmux for a specific function.
  * Has to be implemented in the board files as we don't yet support pinmux
- * setup from FTD. If a board file does not implement one of those functions
+ * setup from FDT. If a board file does not implement one of those functions
  * an empty stub function will be called.
  */
 
diff --git a/arch/arm/include/asm/arch-tegra/bpmp_abi.h b/arch/arm/include/asm/arch-tegra/bpmp_abi.h
new file mode 100644
index 0000000..7b6ad89
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra/bpmp_abi.h
@@ -0,0 +1,1591 @@
+/*
+ * Copyright (c) 2014-2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _ABI_BPMP_ABI_H_
+#define _ABI_BPMP_ABI_H_
+
+#ifdef LK
+#include <stdint.h>
+#endif
+
+#ifndef __ABI_PACKED
+#define __ABI_PACKED __attribute__((packed))
+#endif
+
+#ifdef NO_GCC_EXTENSIONS
+#define EMPTY char empty;
+#define EMPTY_ARRAY 1
+#else
+#define EMPTY
+#define EMPTY_ARRAY 0
+#endif
+
+#ifndef __UNION_ANON
+#define __UNION_ANON
+#endif
+/**
+ * @file
+ */
+
+
+/**
+ * @defgroup MRQ MRQ Messages
+ * @brief Messages sent to/from BPMP via IPC
+ * @{
+ *   @defgroup MRQ_Format Message Format
+ *   @defgroup MRQ_Codes Message Request (MRQ) Codes
+ *   @defgroup MRQ_Payloads Message Payloads
+ *   @defgroup Error_Codes Error Codes
+ * @}
+ */
+
+/**
+ * @addtogroup MRQ_Format Message Format
+ * @{
+ * The CPU requests the BPMP to perform a particular service by
+ * sending it an IVC frame containing a single MRQ message. An MRQ
+ * message consists of a @ref mrq_request followed by a payload whose
+ * format depends on mrq_request::mrq.
+ *
+ * The BPMP processes the data and replies with an IVC frame (on the
+ * same IVC channel) containing and MRQ response. An MRQ response
+ * consists of a @ref mrq_response followed by a payload whose format
+ * depends on the associated mrq_request::mrq.
+ *
+ * A well-defined subset of the MRQ messages that the CPU sends to the
+ * BPMP can lead to BPMP eventually sending an MRQ message to the
+ * CPU. For example, when the CPU uses an #MRQ_THERMAL message to set
+ * a thermal trip point, the BPMP may eventually send a single
+ * #MRQ_THERMAL message of its own to the CPU indicating that the trip
+ * point has been crossed.
+ * @}
+ */
+
+/**
+ * @ingroup MRQ_Format
+ * @brief header for an MRQ message
+ *
+ * Provides the MRQ number for the MRQ message: #mrq. The remainder of
+ * the MRQ message is a payload (immediately following the
+ * mrq_request) whose format depends on mrq.
+ *
+ * @todo document the flags
+ */
+struct mrq_request {
+	/** @brief MRQ number of the request */
+	uint32_t mrq;
+	/** @brief flags for the request */
+	uint32_t flags;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Format
+ * @brief header for an MRQ response
+ *
+ *  Provides an error code for the associated MRQ message. The
+ *  remainder of the MRQ response is a payload (immediately following
+ *  the mrq_response) whose format depends on the associated
+ *  mrq_request::mrq
+ *
+ * @todo document the flags
+ */
+struct mrq_response {
+	/** @brief error code for the MRQ request itself */
+	int32_t err;
+	/** @brief flags for the response */
+	uint32_t flags;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Format
+ * Minimum needed size for an IPC message buffer
+ */
+#define MSG_MIN_SZ	128
+/**
+ * @ingroup MRQ_Format
+ *  Minimum size guaranteed for data in an IPC message buffer
+ */
+#define MSG_DATA_MIN_SZ	120
+
+/**
+ * @ingroup MRQ_Codes
+ * @name Legal MRQ codes
+ * These are the legal values for mrq_request::mrq
+ * @{
+ */
+
+#define MRQ_PING		0
+#define MRQ_QUERY_TAG		1
+#define MRQ_MODULE_LOAD		4
+#define MRQ_MODULE_UNLOAD	5
+#define MRQ_TRACE_MODIFY	7
+#define MRQ_WRITE_TRACE		8
+#define MRQ_THREADED_PING	9
+#define MRQ_MODULE_MAIL		11
+#define MRQ_DEBUGFS		19
+#define MRQ_RESET		20
+#define MRQ_I2C			21
+#define MRQ_CLK			22
+#define MRQ_QUERY_ABI		23
+#define MRQ_PG_READ_STATE	25
+#define MRQ_PG_UPDATE_STATE	26
+#define MRQ_THERMAL		27
+#define MRQ_CPU_VHINT		28
+#define MRQ_ABI_RATCHET		29
+#define MRQ_EMC_DVFS_LATENCY	31
+#define MRQ_TRACE_ITER		64
+
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @brief Maximum MRQ code to be sent by CPU software to
+ * BPMP. Subject to change in future
+ */
+#define MAX_CPU_MRQ_ID		64
+
+/**
+ * @addtogroup MRQ_Payloads Message Payloads
+ * @{
+ *   @defgroup Ping
+ *   @defgroup Query_Tag Query Tag
+ *   @defgroup Module Loadable Modules
+ *   @defgroup Trace
+ *   @defgroup Debugfs
+ *   @defgroup Reset
+ *   @defgroup I2C
+ *   @defgroup Clocks
+ *   @defgroup ABI_info ABI Info
+ *   @defgroup MC_Flush MC Flush
+ *   @defgroup Powergating
+ *   @defgroup Thermal
+ *   @defgroup Vhint CPU Voltage hint
+ *   @defgroup MRQ_Deprecated Deprecated MRQ messages
+ *   @defgroup EMC
+ * @}
+ */
+
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_PING
+ * @brief A simple ping
+ *
+ * * Platforms: All
+ * * Initiators: Any
+ * * Targets: Any
+ * * Request Payload: @ref mrq_ping_request
+ * * Response Payload: @ref mrq_ping_response
+ *
+ * @ingroup MRQ_Codes
+ * @def MRQ_THREADED_PING
+ * @brief A deeper ping
+ *
+ * * Platforms: All
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_ping_request
+ * * Response Payload: @ref mrq_ping_response
+ *
+ * Behavior is equivalent to a simple #MRQ_PING except that BPMP
+ * responds from a thread context (providing a slightly more robust
+ * sign of life).
+ *
+ */
+
+/**
+ * @ingroup Ping
+ * @brief request with #MRQ_PING
+ *
+ * Used by the sender of an #MRQ_PING message to request a pong from
+ * recipient. The response from the recipient is computed based on
+ * #challenge.
+ */
+struct mrq_ping_request {
+/** @brief arbitrarily chosen value */
+	uint32_t challenge;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Ping
+ * @brief response to #MRQ_PING
+ *
+ * Sent in response to an #MRQ_PING message. #reply should be the
+ * mrq_ping_request challenge left shifted by 1 with the carry-bit
+ * dropped.
+ *
+ */
+struct mrq_ping_response {
+	/** @brief response to the MRQ_PING challege */
+	uint32_t reply;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_QUERY_TAG
+ * @brief Query BPMP firmware's tag (i.e. version information)
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_query_tag_request
+ * * Response Payload: N/A
+ *
+ */
+
+/**
+ * @ingroup Query_Tag
+ * @brief request with #MRQ_QUERY_TAG
+ *
+ * Used by #MRQ_QUERY_TAG call to ask BPMP to fill in the memory
+ * pointed by #addr with BPMP firmware header.
+ *
+ * The sender is reponsible for ensuring that #addr is mapped in to
+ * the recipient's address map.
+ */
+struct mrq_query_tag_request {
+  /** @brief base address to store the firmware header */
+	uint32_t addr;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_MODULE_LOAD
+ * @brief dynamically load a BPMP code module
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_module_load_request
+ * * Response Payload: @ref mrq_module_load_response
+ *
+ * @note This MRQ is disabled on production systems
+ *
+ */
+
+/**
+ * @ingroup Module
+ * @brief request with #MRQ_MODULE_LOAD
+ *
+ * Used by #MRQ_MODULE_LOAD calls to ask the recipient to dynamically
+ * load the code located at #phys_addr and having size #size
+ * bytes. #phys_addr is treated as a void pointer.
+ *
+ * The recipient copies the code from #phys_addr to locally allocated
+ * memory prior to responding to this message.
+ *
+ * @todo document the module header format
+ *
+ * The sender is responsible for ensuring that the code is mapped in
+ * the recipient's address map.
+ *
+ */
+struct mrq_module_load_request {
+	/** @brief base address of the code to load. Treated as (void *) */
+	uint32_t phys_addr; /* (void *) */
+	/** @brief size in bytes of code to load */
+	uint32_t size;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Module
+ * @brief response to #MRQ_MODULE_LOAD
+ *
+ * @todo document mrq_response::err
+ */
+struct mrq_module_load_response {
+	/** @brief handle to the loaded module */
+	uint32_t base;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_MODULE_UNLOAD
+ * @brief unload a previously loaded code module
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_module_unload_request
+ * * Response Payload: N/A
+ *
+ * @note This MRQ is disabled on production systems
+ */
+
+/**
+ * @ingroup Module
+ * @brief request with #MRQ_MODULE_UNLOAD
+ *
+ * Used by #MRQ_MODULE_UNLOAD calls to request that a previously loaded
+ * module be unloaded.
+ */
+struct mrq_module_unload_request {
+	/** @brief handle of the module to unload */
+	uint32_t base;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_TRACE_MODIFY
+ * @brief modify the set of enabled trace events
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_trace_modify_request
+ * * Response Payload: @ref mrq_trace_modify_response
+ *
+ * @note This MRQ is disabled on production systems
+ */
+
+/**
+ * @ingroup Trace
+ * @brief request with #MRQ_TRACE_MODIFY
+ *
+ * Used by %MRQ_TRACE_MODIFY calls to enable or disable specify trace
+ * events.  #set takes precedence for any bit set in both #set and
+ * #clr.
+ */
+struct mrq_trace_modify_request {
+	/** @brief bit mask of trace events to disable */
+	uint32_t clr;
+	/** @brief bit mask of trace events to enable */
+	uint32_t set;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Trace
+ * @brief response to #MRQ_TRACE_MODIFY
+ *
+ * Sent in repsonse to an #MRQ_TRACE_MODIFY message. #mask reflects the
+ * state of which events are enabled after the recipient acted on the
+ * message.
+ *
+ */
+struct mrq_trace_modify_response {
+	/** @brief bit mask of trace event enable states */
+	uint32_t mask;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_WRITE_TRACE
+ * @brief Write trace data to a buffer
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_write_trace_request
+ * * Response Payload: @ref mrq_write_trace_response
+ *
+ * mrq_response::err depends on the @ref mrq_write_trace_request field
+ * values. err is -#BPMP_EINVAL if size is zero or area is NULL or
+ * area is in an illegal range. A positive value for err indicates the
+ * number of bytes written to area.
+ *
+ * @note This MRQ is disabled on production systems
+ */
+
+/**
+ * @ingroup Trace
+ * @brief request with #MRQ_WRITE_TRACE
+ *
+ * Used by MRQ_WRITE_TRACE calls to ask the recipient to copy trace
+ * data from the recipient's local buffer to the output buffer. #area
+ * is treated as a byte-aligned pointer in the recipient's address
+ * space.
+ *
+ * The sender is responsible for ensuring that the output
+ * buffer is mapped in the recipient's address map. The recipient is
+ * responsible for protecting its own code and data from accidental
+ * overwrites.
+ */
+struct mrq_write_trace_request {
+	/** @brief base address of output buffer */
+	uint32_t area;
+	/** @brief size in bytes of the output buffer */
+	uint32_t size;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Trace
+ * @brief response to #MRQ_WRITE_TRACE
+ *
+ * Once this response is sent, the respondent will not access the
+ * output buffer further.
+ */
+struct mrq_write_trace_response {
+	/**
+	 * @brief flag whether more data remains in local buffer
+	 *
+	 * Value is 1 if the entire local trace buffer has been
+	 * drained to the outputbuffer. Value is 0 otherwise.
+	 */
+	uint32_t eof;
+} __ABI_PACKED;
+
+/** @private */
+struct mrq_threaded_ping_request {
+	uint32_t challenge;
+} __ABI_PACKED;
+
+/** @private */
+struct mrq_threaded_ping_response {
+	uint32_t reply;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_MODULE_MAIL
+ * @brief send a message to a loadable module
+ *
+ * * Platforms: All
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_module_mail_request
+ * * Response Payload: @ref mrq_module_mail_response
+ *
+ * @note This MRQ is disabled on production systems
+ */
+
+/**
+ * @ingroup Module
+ * @brief request with #MRQ_MODULE_MAIL
+ */
+struct mrq_module_mail_request {
+	/** @brief handle to the previously loaded module */
+	uint32_t base;
+	/** @brief module-specific mail payload
+	 *
+	 * The length of data[ ] is unknown to the BPMP core firmware
+	 * but it is limited to the size of an IPC message.
+	 */
+	uint8_t data[EMPTY_ARRAY];
+} __ABI_PACKED;
+
+/**
+ * @ingroup Module
+ * @brief response to #MRQ_MODULE_MAIL
+ */
+struct mrq_module_mail_response {
+	/** @brief module-specific mail payload
+	 *
+	 * The length of data[ ] is unknown to the BPMP core firmware
+	 * but it is limited to the size of an IPC message.
+	 */
+	uint8_t data[EMPTY_ARRAY];
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_DEBUGFS
+ * @brief Interact with BPMP's debugfs file nodes
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_debugfs_request
+ * * Response Payload: @ref mrq_debugfs_response
+ */
+
+/**
+ * @addtogroup Debugfs
+ * @{
+ *
+ * The BPMP firmware implements a pseudo-filesystem called
+ * debugfs. Any driver within the firmware may register with debugfs
+ * to expose an arbitrary set of "files" in the filesystem. When
+ * software on the CPU writes to a debugfs file, debugfs passes the
+ * written data to a callback provided by the driver. When software on
+ * the CPU reads a debugfs file, debugfs queries the driver for the
+ * data to return to the CPU. The intention of the debugfs filesystem
+ * is to provide information useful for debugging the system at
+ * runtime.
+ *
+ * @note The files exposed via debugfs are not part of the
+ * BPMP firmware's ABI. debugfs files may be added or removed in any
+ * given version of the firmware. Typically the semantics of a debugfs
+ * file are consistent from version to version but even that is not
+ * guaranteed.
+ *
+ * @}
+ */
+/** @ingroup Debugfs */
+enum mrq_debugfs_commands {
+	CMD_DEBUGFS_READ = 1,
+	CMD_DEBUGFS_WRITE = 2,
+	CMD_DEBUGFS_DUMPDIR = 3,
+	CMD_DEBUGFS_MAX
+};
+
+/**
+ * @ingroup Debugfs
+ * @brief parameters for CMD_DEBUGFS_READ/WRITE command
+ */
+struct cmd_debugfs_fileop_request {
+	/** @brief physical address pointing at filename */
+	uint32_t fnameaddr;
+	/** @brief length in bytes of filename buffer */
+	uint32_t fnamelen;
+	/** @brief physical address pointing to data buffer */
+	uint32_t dataaddr;
+	/** @brief length in bytes of data buffer */
+	uint32_t datalen;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Debugfs
+ * @brief parameters for CMD_DEBUGFS_READ/WRITE command
+ */
+struct cmd_debugfs_dumpdir_request {
+	/** @brief physical address pointing to data buffer */
+	uint32_t dataaddr;
+	/** @brief length in bytes of data buffer */
+	uint32_t datalen;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Debugfs
+ * @brief response data for CMD_DEBUGFS_READ/WRITE command
+ */
+struct cmd_debugfs_fileop_response {
+	/** @brief always 0 */
+	uint32_t reserved;
+	/** @brief number of bytes read from or written to data buffer */
+	uint32_t nbytes;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Debugfs
+ * @brief response data for CMD_DEBUGFS_DUMPDIR command
+ */
+struct cmd_debugfs_dumpdir_response {
+	/** @brief always 0 */
+	uint32_t reserved;
+	/** @brief number of bytes read from or written to data buffer */
+	uint32_t nbytes;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Debugfs
+ * @brief request with #MRQ_DEBUGFS.
+ *
+ * The sender of an MRQ_DEBUGFS message uses #cmd to specify a debugfs
+ * command to execute. Legal commands are the values of @ref
+ * mrq_debugfs_commands. Each command requires a specific additional
+ * payload of data.
+ *
+ * |command            |payload|
+ * |-------------------|-------|
+ * |CMD_DEBUGFS_READ   |fop    |
+ * |CMD_DEBUGFS_WRITE  |fop    |
+ * |CMD_DEBUGFS_DUMPDIR|dumpdir|
+ */
+struct mrq_debugfs_request {
+	uint32_t cmd;
+	union {
+		struct cmd_debugfs_fileop_request fop;
+		struct cmd_debugfs_dumpdir_request dumpdir;
+	} __UNION_ANON;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Debugfs
+ */
+struct mrq_debugfs_response {
+	/** @brief always 0 */
+	int32_t reserved;
+	union {
+		/** @brief response data for CMD_DEBUGFS_READ OR
+		 * CMD_DEBUGFS_WRITE command
+		 */
+		struct cmd_debugfs_fileop_response fop;
+		/** @brief response data for CMD_DEBUGFS_DUMPDIR command */
+		struct cmd_debugfs_dumpdir_response dumpdir;
+	} __UNION_ANON;
+} __ABI_PACKED;
+
+/**
+ * @addtogroup Debugfs
+ * @{
+ */
+#define DEBUGFS_S_ISDIR	(1 << 9)
+#define DEBUGFS_S_IRUSR	(1 << 8)
+#define DEBUGFS_S_IWUSR	(1 << 7)
+/** @} */
+
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_RESET
+ * @brief reset an IP block
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_reset_request
+ * * Response Payload: N/A
+ */
+
+/**
+ * @ingroup Reset
+ */
+enum mrq_reset_commands {
+	CMD_RESET_ASSERT = 1,
+	CMD_RESET_DEASSERT = 2,
+	CMD_RESET_MODULE = 3,
+	CMD_RESET_MAX, /* not part of ABI and subject to change */
+};
+
+/**
+ * @ingroup Reset
+ * @brief request with MRQ_RESET
+ *
+ * Used by the sender of an #MRQ_RESET message to request BPMP to
+ * assert or or deassert a given reset line.
+ */
+struct mrq_reset_request {
+	/** @brief reset action to perform (@enum mrq_reset_commands) */
+	uint32_t cmd;
+	/** @brief id of the reset to affected */
+	uint32_t reset_id;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_I2C
+ * @brief issue an i2c transaction
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_i2c_request
+ * * Response Payload: @ref mrq_i2c_response
+ */
+
+/**
+ * @addtogroup I2C
+ * @{
+ */
+#define TEGRA_I2C_IPC_MAX_IN_BUF_SIZE	(MSG_DATA_MIN_SZ - 12)
+#define TEGRA_I2C_IPC_MAX_OUT_BUF_SIZE	(MSG_DATA_MIN_SZ - 4)
+/** @} */
+
+/**
+ * @ingroup I2C
+ * @name Serial I2C flags
+ * Use these flags with serial_i2c_request::flags
+ * @{
+ */
+#define SERIALI2C_TEN           0x0010
+#define SERIALI2C_RD            0x0001
+#define SERIALI2C_STOP          0x8000
+#define SERIALI2C_NOSTART       0x4000
+#define SERIALI2C_REV_DIR_ADDR  0x2000
+#define SERIALI2C_IGNORE_NAK    0x1000
+#define SERIALI2C_NO_RD_ACK     0x0800
+#define SERIALI2C_RECV_LEN      0x0400
+/** @} */
+/** @ingroup I2C */
+enum {
+	CMD_I2C_XFER = 1
+};
+
+/**
+ * @ingroup I2C
+ * @brief serializable i2c request
+ *
+ * Instances of this structure are packed (little-endian) into
+ * cmd_i2c_xfer_request::data_buf. Each instance represents a single
+ * transaction (or a portion of a transaction with repeated starts) on
+ * an i2c bus.
+ *
+ * Because these structures are packed, some instances are likely to
+ * be misaligned. Additionally because #data is variable length, it is
+ * not possible to iterate through a serialized list of these
+ * structures without inspecting #len in each instance.  It may be
+ * easier to serialize or deserialize cmd_i2c_xfer_request::data_buf
+ * manually rather than using this structure definition.
+*/
+struct serial_i2c_request {
+	/** @brief I2C slave address */
+	uint16_t addr;
+	/** @brief bitmask of SERIALI2C_ flags */
+	uint16_t flags;
+	/** @brief length of I2C transaction in bytes */
+	uint16_t len;
+	/** @brief for write transactions only, #len bytes of data */
+	uint8_t data[];
+} __ABI_PACKED;
+
+/**
+ * @ingroup I2C
+ * @brief trigger one or more i2c transactions
+ */
+struct cmd_i2c_xfer_request {
+	/** @brief valid bus number from mach-t186/i2c-t186.h*/
+	uint32_t bus_id;
+
+	/** @brief count of valid bytes in #data_buf*/
+	uint32_t data_size;
+
+	/** @brief serialized packed instances of @ref serial_i2c_request*/
+	uint8_t data_buf[TEGRA_I2C_IPC_MAX_IN_BUF_SIZE];
+} __ABI_PACKED;
+
+/**
+ * @ingroup I2C
+ * @brief container for data read from the i2c bus
+ *
+ * Processing an cmd_i2c_xfer_request::data_buf causes BPMP to execute
+ * zero or more I2C reads. The data read from the bus is serialized
+ * into #data_buf.
+ */
+struct cmd_i2c_xfer_response {
+	/** @brief count of valid bytes in #data_buf*/
+	uint32_t data_size;
+	/** @brief i2c read data */
+	uint8_t data_buf[TEGRA_I2C_IPC_MAX_OUT_BUF_SIZE];
+} __ABI_PACKED;
+
+/**
+ * @ingroup I2C
+ * @brief request with #MRQ_I2C
+ */
+struct mrq_i2c_request {
+	/** @brief always CMD_I2C_XFER (i.e. 1) */
+	uint32_t cmd;
+	/** @brief parameters of the transfer request */
+	struct cmd_i2c_xfer_request xfer;
+} __ABI_PACKED;
+
+/**
+ * @ingroup I2C
+ * @brief response to #MRQ_I2C
+ */
+struct mrq_i2c_response {
+	struct cmd_i2c_xfer_response xfer;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_CLK
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_clk_request
+ * * Response Payload: @ref mrq_clk_response
+ * @addtogroup Clocks
+ * @{
+ */
+
+/**
+ * @name MRQ_CLK sub-commands
+ * @{
+ */
+enum {
+	CMD_CLK_GET_RATE = 1,
+	CMD_CLK_SET_RATE = 2,
+	CMD_CLK_ROUND_RATE = 3,
+	CMD_CLK_GET_PARENT = 4,
+	CMD_CLK_SET_PARENT = 5,
+	CMD_CLK_IS_ENABLED = 6,
+	CMD_CLK_ENABLE = 7,
+	CMD_CLK_DISABLE = 8,
+	CMD_CLK_GET_ALL_INFO = 14,
+	CMD_CLK_GET_MAX_CLK_ID = 15,
+	CMD_CLK_MAX,
+};
+/** @} */
+
+#define MRQ_CLK_NAME_MAXLEN	40
+#define MRQ_CLK_MAX_PARENTS	16
+
+/** @private */
+struct cmd_clk_get_rate_request {
+	EMPTY
+} __ABI_PACKED;
+
+struct cmd_clk_get_rate_response {
+	int64_t rate;
+} __ABI_PACKED;
+
+struct cmd_clk_set_rate_request {
+	int32_t unused;
+	int64_t rate;
+} __ABI_PACKED;
+
+struct cmd_clk_set_rate_response {
+	int64_t rate;
+} __ABI_PACKED;
+
+struct cmd_clk_round_rate_request {
+	int32_t unused;
+	int64_t rate;
+} __ABI_PACKED;
+
+struct cmd_clk_round_rate_response {
+	int64_t rate;
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_get_parent_request {
+	EMPTY
+} __ABI_PACKED;
+
+struct cmd_clk_get_parent_response {
+	uint32_t parent_id;
+} __ABI_PACKED;
+
+struct cmd_clk_set_parent_request {
+	uint32_t parent_id;
+} __ABI_PACKED;
+
+struct cmd_clk_set_parent_response {
+	uint32_t parent_id;
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_is_enabled_request {
+	EMPTY
+} __ABI_PACKED;
+
+struct cmd_clk_is_enabled_response {
+	int32_t state;
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_enable_request {
+	EMPTY
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_enable_response {
+	EMPTY
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_disable_request {
+	EMPTY
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_disable_response {
+	EMPTY
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_get_all_info_request {
+	EMPTY
+} __ABI_PACKED;
+
+struct cmd_clk_get_all_info_response {
+	uint32_t flags;
+	uint32_t parent;
+	uint32_t parents[MRQ_CLK_MAX_PARENTS];
+	uint8_t num_parents;
+	uint8_t name[MRQ_CLK_NAME_MAXLEN];
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_get_max_clk_id_request {
+	EMPTY
+} __ABI_PACKED;
+
+struct cmd_clk_get_max_clk_id_response {
+	uint32_t max_id;
+} __ABI_PACKED;
+/** @} */
+
+/**
+ * @ingroup Clocks
+ * @brief request with #MRQ_CLK
+ *
+ * Used by the sender of an #MRQ_CLK message to control clocks. The
+ * clk_request is split into several sub-commands. Some sub-commands
+ * require no additional data. Others have a sub-command specific
+ * payload
+ *
+ * |sub-command                 |payload                |
+ * |----------------------------|-----------------------|
+ * |CMD_CLK_GET_RATE            |-                      |
+ * |CMD_CLK_SET_RATE            |clk_set_rate           |
+ * |CMD_CLK_ROUND_RATE          |clk_round_rate         |
+ * |CMD_CLK_GET_PARENT          |-                      |
+ * |CMD_CLK_SET_PARENT          |clk_set_parent         |
+ * |CMD_CLK_IS_ENABLED          |-                      |
+ * |CMD_CLK_ENABLE              |-                      |
+ * |CMD_CLK_DISABLE             |-                      |
+ * |CMD_CLK_GET_ALL_INFO        |-                      |
+ * |CMD_CLK_GET_MAX_CLK_ID      |-                      |
+ *
+ */
+
+struct mrq_clk_request {
+	/** @brief sub-command and clock id concatenated to 32-bit word.
+	 * - bits[31..24] is the sub-cmd.
+	 * - bits[23..0] is the clock id
+	 */
+	uint32_t cmd_and_id;
+
+	union {
+		/** @private */
+		struct cmd_clk_get_rate_request clk_get_rate;
+		struct cmd_clk_set_rate_request clk_set_rate;
+		struct cmd_clk_round_rate_request clk_round_rate;
+		/** @private */
+		struct cmd_clk_get_parent_request clk_get_parent;
+		struct cmd_clk_set_parent_request clk_set_parent;
+		/** @private */
+		struct cmd_clk_enable_request clk_enable;
+		/** @private */
+		struct cmd_clk_disable_request clk_disable;
+		/** @private */
+		struct cmd_clk_is_enabled_request clk_is_enabled;
+		/** @private */
+		struct cmd_clk_get_all_info_request clk_get_all_info;
+		/** @private */
+		struct cmd_clk_get_max_clk_id_request clk_get_max_clk_id;
+	} __UNION_ANON;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Clocks
+ * @brief response to MRQ_CLK
+ *
+ * Each sub-command supported by @ref mrq_clk_request may return
+ * sub-command-specific data. Some do and some do not as indicated in
+ * the following table
+ *
+ * |sub-command                 |payload                 |
+ * |----------------------------|------------------------|
+ * |CMD_CLK_GET_RATE            |clk_get_rate            |
+ * |CMD_CLK_SET_RATE            |clk_set_rate            |
+ * |CMD_CLK_ROUND_RATE          |clk_round_rate          |
+ * |CMD_CLK_GET_PARENT          |clk_get_parent          |
+ * |CMD_CLK_SET_PARENT          |clk_set_parent          |
+ * |CMD_CLK_IS_ENABLED          |clk_is_enabled          |
+ * |CMD_CLK_ENABLE              |-                       |
+ * |CMD_CLK_DISABLE             |-                       |
+ * |CMD_CLK_GET_ALL_INFO        |clk_get_all_info        |
+ * |CMD_CLK_GET_MAX_CLK_ID      |clk_get_max_id          |
+ *
+ */
+
+struct mrq_clk_response {
+	union {
+		struct cmd_clk_get_rate_response clk_get_rate;
+		struct cmd_clk_set_rate_response clk_set_rate;
+		struct cmd_clk_round_rate_response clk_round_rate;
+		struct cmd_clk_get_parent_response clk_get_parent;
+		struct cmd_clk_set_parent_response clk_set_parent;
+		/** @private */
+		struct cmd_clk_enable_response clk_enable;
+		/** @private */
+		struct cmd_clk_disable_response clk_disable;
+		struct cmd_clk_is_enabled_response clk_is_enabled;
+		struct cmd_clk_get_all_info_response clk_get_all_info;
+		struct cmd_clk_get_max_clk_id_response clk_get_max_clk_id;
+	} __UNION_ANON;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_QUERY_ABI
+ * @brief check if an MRQ is implemented
+ *
+ * * Platforms: All
+ * * Initiators: Any
+ * * Targets: Any
+ * * Request Payload: @ref mrq_query_abi_request
+ * * Response Payload: @ref mrq_query_abi_response
+ */
+
+/**
+ * @ingroup ABI_info
+ * @brief request with MRQ_QUERY_ABI
+ *
+ * Used by #MRQ_QUERY_ABI call to check if MRQ code #mrq is supported
+ * by the recipient.
+ */
+struct mrq_query_abi_request {
+	/** @brief MRQ code to query */
+	uint32_t mrq;
+} __ABI_PACKED;
+
+/**
+ * @ingroup ABI_info
+ * @brief response to MRQ_QUERY_ABI
+ */
+struct mrq_query_abi_response {
+	/** @brief 0 if queried MRQ is supported. Else, -#BPMP_ENODEV */
+	int32_t status;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_PG_READ_STATE
+ * @brief read the power-gating state of a partition
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_pg_read_state_request
+ * * Response Payload: @ref mrq_pg_read_state_response
+ * @addtogroup Powergating
+ * @{
+ */
+
+/**
+ * @brief request with #MRQ_PG_READ_STATE
+ *
+ * Used by MRQ_PG_READ_STATE call to read the current state of a
+ * partition.
+ */
+struct mrq_pg_read_state_request {
+	/** @brief ID of partition */
+	uint32_t partition_id;
+} __ABI_PACKED;
+
+/**
+ * @brief response to MRQ_PG_READ_STATE
+ * @todo define possible errors.
+ */
+struct mrq_pg_read_state_response {
+	/** @brief read as don't care */
+	uint32_t sram_state;
+	/** @brief state of power partition
+	 * * 0 : off
+	 * * 1 : on
+	 */
+	uint32_t logic_state;
+} __ABI_PACKED;
+
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_PG_UPDATE_STATE
+ * @brief modify the power-gating state of a partition
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_pg_update_state_request
+ * * Response Payload: N/A
+ * @addtogroup Powergating
+ * @{
+ */
+
+/**
+ * @brief request with mrq_pg_update_state_request
+ *
+ * Used by #MRQ_PG_UPDATE_STATE call to request BPMP to change the
+ * state of a power partition #partition_id.
+ */
+struct mrq_pg_update_state_request {
+	/** @brief ID of partition */
+	uint32_t partition_id;
+	/** @brief secondary control of power partition
+	 *  @details Ignored by many versions of the BPMP
+	 *  firmware. For maximum compatibility, set the value
+	 *  according to @logic_state
+	 * *  0x1: power ON partition (@ref logic_state == 0x3)
+	 * *  0x3: power OFF partition (@ref logic_state == 0x1)
+	 */
+	uint32_t sram_state;
+	/** @brief controls state of power partition, legal values are
+	 * *  0x1 : power OFF partition
+	 * *  0x3 : power ON partition
+	 */
+	uint32_t logic_state;
+	/** @brief change state of clocks of the power partition, legal values
+	 * *  0x0 : do not change clock state
+	 * *  0x1 : disable partition clocks (only applicable when
+	 *          @ref logic_state == 0x1)
+	 * *  0x3 : enable partition clocks (only applicable when
+	 *          @ref logic_state == 0x3)
+	 */
+	uint32_t clock_state;
+} __ABI_PACKED;
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_THERMAL
+ * @brief interact with BPMP thermal framework
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: Any
+ * * Request Payload: TODO
+ * * Response Payload: TODO
+ *
+ * @addtogroup Thermal
+ *
+ * The BPMP firmware includes a thermal framework. Drivers within the
+ * bpmp firmware register with the framework to provide thermal
+ * zones. Each thermal zone corresponds to an entity whose temperature
+ * can be measured. The framework also has a notion of trip points. A
+ * trip point consists of a thermal zone id, a temperature, and a
+ * callback routine. The framework invokes the callback when the zone
+ * hits the indicated temperature. The BPMP firmware uses this thermal
+ * framework interally to implement various temperature-dependent
+ * functions.
+ *
+ * Software on the CPU can use #MRQ_THERMAL (with payload @ref
+ * mrq_thermal_host_to_bpmp_request) to interact with the BPMP thermal
+ * framework. The CPU must It can query the number of supported zones,
+ * query zone temperatures, and set trip points.
+ *
+ * When a trip point set by the CPU gets crossed, BPMP firmware issues
+ * an IPC to the CPU having mrq_request::mrq = #MRQ_THERMAL and a
+ * payload of @ref mrq_thermal_bpmp_to_host_request.
+ * @{
+ */
+enum mrq_thermal_host_to_bpmp_cmd {
+	/**
+	 * @brief Check whether the BPMP driver supports the specified
+	 * request type.
+	 *
+	 * Host needs to supply request parameters.
+	 *
+	 * mrq_response::err is 0 if the specified request is
+	 * supported and -#BPMP_ENODEV otherwise.
+	 */
+	CMD_THERMAL_QUERY_ABI = 0,
+
+	/**
+	 * @brief Get the current temperature of the specified zone.
+	 *
+	 * Host needs to supply request parameters.
+	 *
+	 * mrq_response::err is
+	 * *  0: Temperature query succeeded.
+	 * *  -#BPMP_EINVAL: Invalid request parameters.
+	 * *  -#BPMP_ENOENT: No driver registered for thermal zone..
+	 * *  -#BPMP_EFAULT: Problem reading temperature measurement.
+	 */
+	CMD_THERMAL_GET_TEMP = 1,
+
+	/**
+	 * @brief Enable or disable and set the lower and upper
+	 *   thermal limits for a thermal trip point. Each zone has
+	 *   one trip point.
+	 *
+	 * Host needs to supply request parameters. Once the
+	 * temperature hits a trip point, the BPMP will send a message
+	 * to the CPU having MRQ=MRQ_THERMAL and
+	 * type=CMD_THERMAL_HOST_TRIP_REACHED
+	 *
+	 * mrq_response::err is
+	 * *  0: Trip successfully set.
+	 * *  -#BPMP_EINVAL: Invalid request parameters.
+	 * *  -#BPMP_ENOENT: No driver registered for thermal zone.
+	 * *  -#BPMP_EFAULT: Problem setting trip point.
+	 */
+	CMD_THERMAL_SET_TRIP = 2,
+
+	/**
+	 * @brief Get the number of supported thermal zones.
+	 *
+	 * No request parameters required.
+	 *
+	 * mrq_response::err is always 0, indicating success.
+	 */
+	CMD_THERMAL_GET_NUM_ZONES = 3,
+
+	/** @brief: number of supported host-to-bpmp commands. May
+	 * increase in future
+	 */
+	CMD_THERMAL_HOST_TO_BPMP_NUM
+};
+
+enum mrq_thermal_bpmp_to_host_cmd {
+	/**
+	 * @brief Indication that the temperature for a zone has
+	 *   exceeded the range indicated in the thermal trip point
+	 *   for the zone.
+	 *
+	 * BPMP needs to supply request parameters. Host only needs to
+	 * acknowledge.
+	 */
+	CMD_THERMAL_HOST_TRIP_REACHED = 100,
+
+	/** @brief: number of supported bpmp-to-host commands. May
+	 * increase in future
+	 */
+	CMD_THERMAL_BPMP_TO_HOST_NUM
+};
+
+/*
+ * Host->BPMP request data for request type CMD_THERMAL_QUERY_ABI
+ *
+ * zone: Request type for which to check existence.
+ */
+struct cmd_thermal_query_abi_request {
+	uint32_t type;
+} __ABI_PACKED;
+
+/*
+ * Host->BPMP request data for request type CMD_THERMAL_GET_TEMP
+ *
+ * zone: Number of thermal zone.
+ */
+struct cmd_thermal_get_temp_request {
+	uint32_t zone;
+} __ABI_PACKED;
+
+/*
+ * BPMP->Host reply data for request CMD_THERMAL_GET_TEMP
+ *
+ * error: 0 if request succeeded.
+ *	-BPMP_EINVAL if request parameters were invalid.
+ *      -BPMP_ENOENT if no driver was registered for the specified thermal zone.
+ *      -BPMP_EFAULT for other thermal zone driver errors.
+ * temp: Current temperature in millicelsius.
+ */
+struct cmd_thermal_get_temp_response {
+	int32_t temp;
+} __ABI_PACKED;
+
+/*
+ * Host->BPMP request data for request type CMD_THERMAL_SET_TRIP
+ *
+ * zone: Number of thermal zone.
+ * low: Temperature of lower trip point in millicelsius
+ * high: Temperature of upper trip point in millicelsius
+ * enabled: 1 to enable trip point, 0 to disable trip point
+ */
+struct cmd_thermal_set_trip_request {
+	uint32_t zone;
+	int32_t low;
+	int32_t high;
+	uint32_t enabled;
+} __ABI_PACKED;
+
+/*
+ * BPMP->Host request data for request type CMD_THERMAL_HOST_TRIP_REACHED
+ *
+ * zone: Number of thermal zone where trip point was reached.
+ */
+struct cmd_thermal_host_trip_reached_request {
+	uint32_t zone;
+} __ABI_PACKED;
+
+/*
+ * BPMP->Host reply data for request type CMD_THERMAL_GET_NUM_ZONES
+ *
+ * num: Number of supported thermal zones. The thermal zones are indexed
+ *      starting from zero.
+ */
+struct cmd_thermal_get_num_zones_response {
+	uint32_t num;
+} __ABI_PACKED;
+
+/*
+ * Host->BPMP request data.
+ *
+ * Reply type is union mrq_thermal_bpmp_to_host_response.
+ *
+ * type: Type of request. Values listed in enum mrq_thermal_type.
+ * data: Request type specific parameters.
+ */
+struct mrq_thermal_host_to_bpmp_request {
+	uint32_t type;
+	union {
+		struct cmd_thermal_query_abi_request query_abi;
+		struct cmd_thermal_get_temp_request get_temp;
+		struct cmd_thermal_set_trip_request set_trip;
+	} __UNION_ANON;
+} __ABI_PACKED;
+
+/*
+ * BPMP->Host request data.
+ *
+ * type: Type of request. Values listed in enum mrq_thermal_type.
+ * data: Request type specific parameters.
+ */
+struct mrq_thermal_bpmp_to_host_request {
+	uint32_t type;
+	union {
+		struct cmd_thermal_host_trip_reached_request host_trip_reached;
+	} __UNION_ANON;
+} __ABI_PACKED;
+
+/*
+ * Data in reply to a Host->BPMP request.
+ */
+union mrq_thermal_bpmp_to_host_response {
+	struct cmd_thermal_get_temp_response get_temp;
+	struct cmd_thermal_get_num_zones_response get_num_zones;
+} __ABI_PACKED;
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_CPU_VHINT
+ * @brief Query CPU voltage hint data
+ *
+ * * Platforms: T186
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_cpu_vhint_request
+ * * Response Payload: N/A
+ *
+ * @addtogroup Vhint CPU Voltage hint
+ * @{
+ */
+
+/**
+ * @brief request with #MRQ_CPU_VHINT
+ *
+ * Used by #MRQ_CPU_VHINT call by CCPLEX to retrieve voltage hint data
+ * from BPMP to memory space pointed by #addr. CCPLEX is responsible
+ * to allocate sizeof(cpu_vhint_data) sized block of memory and
+ * appropriately map it for BPMP before sending the request.
+ */
+struct mrq_cpu_vhint_request {
+	/** @brief IOVA address for the #cpu_vhint_data */
+	uint32_t addr; /* struct cpu_vhint_data * */
+	/** @brief ID of the cluster whose data is requested */
+	uint32_t cluster_id; /* enum cluster_id */
+} __ABI_PACKED;
+
+/**
+ * @brief description of the CPU v/f relation
+ *
+ * Used by #MRQ_CPU_VHINT call to carry data pointed by #addr of
+ * struct mrq_cpu_vhint_request
+ */
+struct cpu_vhint_data {
+	uint32_t ref_clk_hz; /**< reference frequency in Hz */
+	uint16_t pdiv; /**< post divider value */
+	uint16_t mdiv; /**< input divider value */
+	uint16_t ndiv_max; /**< fMAX expressed with max NDIV value */
+	/** table of ndiv values as a function of vINDEX (voltage index) */
+	uint16_t ndiv[80];
+	/** minimum allowed NDIV value */
+	uint16_t ndiv_min;
+	/** minimum allowed voltage hint value (as in vINDEX) */
+	uint16_t vfloor;
+	/** maximum allowed voltage hint value (as in vINDEX) */
+	uint16_t vceil;
+	/** post-multiplier for vindex value */
+	uint16_t vindex_mult;
+	/** post-divider for vindex value */
+	uint16_t vindex_div;
+	/** reserved for future use */
+	uint16_t reserved[328];
+} __ABI_PACKED;
+
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_ABI_RATCHET
+ * @brief ABI ratchet value query
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_abi_ratchet_request
+ * * Response Payload: @ref mrq_abi_ratchet_response
+ * @addtogroup ABI_info
+ * @{
+ */
+
+/**
+ * @brief an ABI compatibility mechanism
+ *
+ * BPMP_ABI_RATCHET_VALUE may increase for various reasons in a future
+ * revision of this header file.
+ * 1. That future revision deprecates some MRQ
+ * 2. That future revision introduces a breaking change to an existing
+ *    MRQ or
+ * 3. A bug is discovered in an existing implementation of the BPMP-FW
+ *    (or possibly one of its clients) which warrants deprecating that
+ *    implementation.
+ */
+#define BPMP_ABI_RATCHET_VALUE 3
+
+/**
+ * @brief request with #MRQ_ABI_RATCHET.
+ *
+ * #ratchet should be #BPMP_ABI_RATCHET_VALUE from the ABI header
+ * against which the requester was compiled.
+ *
+ * If ratchet is less than BPMP's #BPMP_ABI_RATCHET_VALUE, BPMP may
+ * reply with mrq_response::err = -#BPMP_ERANGE to indicate that
+ * BPMP-FW cannot interoperate correctly with the requester. Requester
+ * should cease further communication with BPMP.
+ *
+ * Otherwise, err shall be 0.
+ */
+struct mrq_abi_ratchet_request {
+	/** @brief requester's ratchet value */
+	uint16_t ratchet;
+};
+
+/**
+ * @brief response to #MRQ_ABI_RATCHET
+ *
+ * #ratchet shall be #BPMP_ABI_RATCHET_VALUE from the ABI header
+ * against which BPMP firwmare was compiled.
+ *
+ * If #ratchet is less than the requester's #BPMP_ABI_RATCHET_VALUE,
+ * the requster must either interoperate with BPMP according to an ABI
+ * header version with BPMP_ABI_RATCHET_VALUE = ratchet or cease
+ * communication with BPMP.
+ *
+ * If mrq_response::err is 0 and ratchet is greater than or equal to the
+ * requester's BPMP_ABI_RATCHET_VALUE, the requester should continue
+ * normal operation.
+ */
+struct mrq_abi_ratchet_response {
+	/** @brief BPMP's ratchet value */
+	uint16_t ratchet;
+};
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_EMC_DVFS_LATENCY
+ * @brief query frequency dependent EMC DVFS latency
+ *
+ * * Platforms: T186
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: N/A
+ * * Response Payload: @ref mrq_emc_dvfs_latency_response
+ * @addtogroup EMC
+ * @{
+ */
+
+/**
+ * @brief used by @ref mrq_emc_dvfs_latency_response
+ */
+struct emc_dvfs_latency {
+	/** @brief EMC frequency in kHz */
+	uint32_t freq;
+	/** @brief EMC DVFS latency in nanoseconds */
+	uint32_t latency;
+} __ABI_PACKED;
+
+#define EMC_DVFS_LATENCY_MAX_SIZE	14
+/**
+ * @brief response to #MRQ_EMC_DVFS_LATENCY
+ */
+struct mrq_emc_dvfs_latency_response {
+	/** @brief the number valid entries in #pairs */
+	uint32_t num_pairs;
+	/** @brief EMC <frequency, latency> information */
+	struct emc_dvfs_latency pairs[EMC_DVFS_LATENCY_MAX_SIZE];
+} __ABI_PACKED;
+
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_TRACE_ITER
+ * @brief manage the trace iterator
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: N/A
+ * * Response Payload: @ref mrq_trace_iter_request
+ * @addtogroup Trace
+ * @{
+ */
+enum {
+	/** @brief (re)start the tracing now. Ignore older events */
+	TRACE_ITER_INIT = 0,
+	/** @brief clobber all events in the trace buffer */
+	TRACE_ITER_CLEAN = 1
+};
+
+/**
+ * @brief request with #MRQ_TRACE_ITER
+ */
+struct mrq_trace_iter_request {
+	/** @brief TRACE_ITER_INIT or TRACE_ITER_CLEAN */
+	uint32_t cmd;
+} __ABI_PACKED;
+
+/** @} */
+
+/*
+ *  4. Enumerations
+ */
+
+/*
+ *   4.1 CPU enumerations
+ *
+ * See <mach-t186/system-t186.h>
+ *
+ *   4.2 CPU Cluster enumerations
+ *
+ * See <mach-t186/system-t186.h>
+ *
+ *   4.3 System low power state enumerations
+ *
+ * See <mach-t186/system-t186.h>
+ */
+
+/*
+ *   4.4 Clock enumerations
+ *
+ * For clock enumerations, see <mach-t186/clk-t186.h>
+ */
+
+/*
+ *   4.5 Reset enumerations
+ *
+ * For reset enumerations, see <mach-t186/reset-t186.h>
+ */
+
+/*
+ *   4.6 Thermal sensor enumerations
+ *
+ * For thermal sensor enumerations, see <mach-t186/thermal-t186.h>
+ */
+
+/**
+ * @defgroup Error_Codes
+ * Negative values for mrq_response::err generally indicate some
+ * error. The ABI defines the following error codes. Negating these
+ * defines is an exercise left to the user.
+ * @{
+ */
+/** @brief No such file or directory */
+#define BPMP_ENOENT	2
+/** @brief No MRQ handler */
+#define BPMP_ENOHANDLER	3
+/** @brief I/O error */
+#define BPMP_EIO	5
+/** @brief Bad sub-MRQ command */
+#define BPMP_EBADCMD	6
+/** @brief Not enough memory */
+#define BPMP_ENOMEM	12
+/** @brief Permission denied */
+#define BPMP_EACCES	13
+/** @brief Bad address */
+#define BPMP_EFAULT	14
+/** @brief No such device */
+#define BPMP_ENODEV	19
+/** @brief Argument is a directory */
+#define BPMP_EISDIR	21
+/** @brief Invalid argument */
+#define BPMP_EINVAL	22
+/** @brief Timeout during operation */
+#define BPMP_ETIMEDOUT  23
+/** @brief Out of range */
+#define BPMP_ERANGE	34
+/** @} */
+/** @} */
+#endif
diff --git a/arch/arm/include/asm/arch-tegra/clock.h b/arch/arm/include/asm/arch-tegra/clock.h
index e56031d..7daf8bc 100644
--- a/arch/arm/include/asm/arch-tegra/clock.h
+++ b/arch/arm/include/asm/arch-tegra/clock.h
@@ -324,7 +324,7 @@
  * @param p post divider(DIVP)
  * @param cpcon base PLL charge pump(CPCON)
  * @return 0 if ok, -1 on error (the requested PLL is incorrect and cannot
- *              be overriden), 1 if PLL is already correct
+ *              be overridden), 1 if PLL is already correct
  */
 int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon);
 
diff --git a/arch/arm/include/asm/arch-tegra/ivc.h b/arch/arm/include/asm/arch-tegra/ivc.h
new file mode 100644
index 0000000..7f2287a
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra/ivc.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _ASM_ARCH_TEGRA_IVC_H
+#define _ASM_ARCH_TEGRA_IVC_H
+
+#include <common.h>
+
+/*
+ * Tegra IVC is a communication protocol that transfers fixed-size frames
+ * bi-directionally and in-order between the local CPU and some remote entity.
+ * Communication is via a statically sized and allocated buffer in shared
+ * memory and a notification mechanism.
+ *
+ * This API handles all aspects of the shared memory buffer's metadata, and
+ * leaves all aspects of the frame content to the calling code; frames
+ * typically contain some higher-level protocol. The notification mechanism is
+ * also handled externally to this API, since it can vary from instance to
+ * instance.
+ *
+ * The client model is to first find some free (for TX) or filled (for RX)
+ * frame, process that frame's memory buffer (fill or read it), and then
+ * inform the protocol that the frame has been filled/read, i.e. advance the
+ * write/read pointer. If the channel is full, there may be no available frames
+ * to fill/read. In this case, client code may either poll for an available
+ * frame, or wait for the remote entity to send a notification to the local
+ * CPU.
+ */
+
+/**
+ * struct tegra_ivc - In-memory shared memory layout.
+ *
+ * This is described in detail in ivc.c.
+ */
+struct tegra_ivc_channel_header;
+
+/**
+ * struct tegra_ivc - Software state of an IVC channel.
+ *
+ * This state is internal to the IVC code and should not be accessed directly
+ * by clients. It is public solely so clients can allocate storage for the
+ * structure.
+ */
+struct tegra_ivc {
+	/**
+	 * rx_channel - Pointer to the shared memory region used to receive
+	 * messages from the remote entity.
+	 */
+	struct tegra_ivc_channel_header *rx_channel;
+	/**
+	 * tx_channel - Pointer to the shared memory region used to send
+	 * messages to the remote entity.
+	 */
+	struct tegra_ivc_channel_header *tx_channel;
+	/**
+	 * r_pos - The position in list of frames in rx_channel that we are
+	 * reading from.
+	 */
+	uint32_t r_pos;
+	/**
+	 * w_pos - The position in list of frames in tx_channel that we are
+	 * writing to.
+	 */
+	uint32_t w_pos;
+	/**
+	 * nframes - The number of frames allocated (in each direction) in
+	 * shared memory.
+	 */
+	uint32_t nframes;
+	/**
+	 * frame_size - The size of each frame in shared memory.
+	 */
+	uint32_t frame_size;
+	/**
+	 * notify - Function to call to notify the remote processor of a
+	 * change in channel state.
+	 */
+	void (*notify)(struct tegra_ivc *);
+};
+
+/**
+ * tegra_ivc_read_get_next_frame - Locate the next frame to receive.
+ *
+ * Locate the next frame to be received/processed, return the address of the
+ * frame, and do not remove it from the queue. Repeated calls to this function
+ * will return the same address until tegra_ivc_read_advance() is called.
+ *
+ * @ivc		The IVC channel.
+ * @frame	Pointer to be filled with the address of the frame to receive.
+ *
+ * @return 0 if a frame is available, else a negative error code.
+ */
+int tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc, void **frame);
+
+/**
+ * tegra_ivc_read_advance - Advance the read queue.
+ *
+ * Inform the protocol and remote entity that the frame returned by
+ * tegra_ivc_read_get_next_frame() has been processed. The remote end may then
+ * re-use it to transmit further data. Subsequent to this function returning,
+ * tegra_ivc_read_get_next_frame() will return a different frame.
+ *
+ * @ivc		The IVC channel.
+ *
+ * @return 0 if OK, else a negative error code.
+ */
+int tegra_ivc_read_advance(struct tegra_ivc *ivc);
+
+/**
+ * tegra_ivc_write_get_next_frame - Locate the next frame to fill for transmit.
+ *
+ * Locate the next frame to be filled for transmit, return the address of the
+ * frame, and do not add it to the queue. Repeated calls to this function
+ * will return the same address until tegra_ivc_read_advance() is called.
+ *
+ * @ivc		The IVC channel.
+ * @frame	Pointer to be filled with the address of the frame to fill.
+ *
+ * @return 0 if a frame is available, else a negative error code.
+ */
+int tegra_ivc_write_get_next_frame(struct tegra_ivc *ivc, void **frame);
+
+/**
+ * tegra_ivc_write_advance - Advance the write queue.
+ *
+ * Inform the protocol and remote entity that the frame returned by
+ * tegra_ivc_write_get_next_frame() has been filled and should be transmitted.
+ * The remote end may then read data from it. Subsequent to this function
+ * returning, tegra_ivc_write_get_next_frame() will return a different frame.
+ *
+ * @ivc		The IVC channel.
+ *
+ * @return 0 if OK, else a negative error code.
+ */
+int tegra_ivc_write_advance(struct tegra_ivc *ivc);
+
+/**
+ * tegra_ivc_channel_notified - handle internal messages
+ *
+ * This function must be called following every notification.
+ *
+ * @ivc		The IVC channel.
+ *
+ * @return 0 if the channel is ready for communication, or -EAGAIN if a
+ * channel reset is in progress.
+ */
+int tegra_ivc_channel_notified(struct tegra_ivc *ivc);
+
+/**
+ * tegra_ivc_channel_reset - initiates a reset of the shared memory state
+ *
+ * This function must be called after a channel is initialized but before it
+ * is used for communication. The channel will be ready for use when a
+ * subsequent call to notify the remote of the channel reset indicates the
+ * reset operation is complete.
+ *
+ * @ivc		The IVC channel.
+ */
+void tegra_ivc_channel_reset(struct tegra_ivc *ivc);
+
+/**
+ * tegra_ivc_init - Initialize a channel's software state.
+ *
+ * @ivc		The IVC channel.
+ * @rx_base	Address of the the RX shared memory buffer.
+ * @tx_base	Address of the the TX shared memory buffer.
+ * @nframes	Number of frames in each shared memory buffer.
+ * @frame_size	Size of each frame.
+ *
+ * @return 0 if OK, else a negative error code.
+ */
+int tegra_ivc_init(struct tegra_ivc *ivc, ulong rx_base, ulong tx_base,
+		   uint32_t nframes, uint32_t frame_size,
+		   void (*notify)(struct tegra_ivc *));
+
+#endif
diff --git a/arch/arm/include/asm/arch-tegra/tegra_mmc.h b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
index 75e56c4..07ef4c0 100644
--- a/arch/arm/include/asm/arch-tegra/tegra_mmc.h
+++ b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
@@ -9,6 +9,9 @@
 #ifndef __TEGRA_MMC_H_
 #define __TEGRA_MMC_H_
 
+#include <common.h>
+#include <clk.h>
+#include <reset.h>
 #include <fdtdec.h>
 #include <asm/gpio.h>
 
@@ -134,7 +137,10 @@
 	int id;			/* device id/number, 0-3 */
 	int enabled;		/* 1 to enable, 0 to disable */
 	int width;		/* Bus Width, 1, 4 or 8 */
-#ifndef CONFIG_TEGRA186
+#ifdef CONFIG_TEGRA186
+	struct reset_ctl reset_ctl;
+	struct clk clk;
+#else
 	enum periph_id mmc_id;	/* Peripheral ID: PERIPH_ID_... */
 #endif
 	struct gpio_desc cd_gpio;	/* Change Detect GPIO */
diff --git a/arch/arm/include/asm/arch-tegra124/display.h b/arch/arm/include/asm/arch-tegra124/display.h
index ca6644a..c522faa 100644
--- a/arch/arm/include/asm/arch-tegra124/display.h
+++ b/arch/arm/include/asm/arch-tegra124/display.h
@@ -11,7 +11,7 @@
 /**
  * Register a new display based on device tree configuration.
  *
- * The frame buffer can be positioned by U-Boot or overriden by the fdt.
+ * The frame buffer can be positioned by U-Boot or overridden by the fdt.
  * You should pass in the U-Boot address here, and check the contents of
  * struct fdt_disp_config to see what was actually chosen.
  *
diff --git a/arch/arm/include/asm/arch-zynqmp/clk.h b/arch/arm/include/asm/arch-zynqmp/clk.h
index b18333d..bfd53b5 100644
--- a/arch/arm/include/asm/arch-zynqmp/clk.h
+++ b/arch/arm/include/asm/arch-zynqmp/clk.h
@@ -8,7 +8,6 @@
 #ifndef _ASM_ARCH_CLK_H_
 #define _ASM_ARCH_CLK_H_
 
-unsigned long get_uart_clk(int dev_id);
 unsigned long zynqmp_get_system_timer_freq(void);
 
 #endif /* _ASM_ARCH_CLK_H_ */
diff --git a/arch/arm/include/asm/armv7.h b/arch/arm/include/asm/armv7.h
index 423fc70..a20702e 100644
--- a/arch/arm/include/asm/armv7.h
+++ b/arch/arm/include/asm/armv7.h
@@ -126,6 +126,8 @@
 
 extern char __secure_start[];
 extern char __secure_end[];
+extern char __secure_stack_start[];
+extern char __secure_stack_end[];
 
 #endif /* CONFIG_ARMV7_NONSEC */
 
diff --git a/arch/arm/include/asm/armv7m.h b/arch/arm/include/asm/armv7m.h
index 200444d..54d8a2b 100644
--- a/arch/arm/include/asm/armv7m.h
+++ b/arch/arm/include/asm/armv7m.h
@@ -51,10 +51,21 @@
 #define V7M_MPU_CTRL_ENABLE		(1 << 0)
 #define V7M_MPU_CTRL_HFNMIENA		(1 << 1)
 
+#define V7M_MPU_CTRL_ENABLE		(1 << 0)
+#define V7M_MPU_CTRL_DISABLE		(0 << 0)
+#define V7M_MPU_CTRL_HFNMIENA		(1 << 1)
+
 #define V7M_MPU_RASR_EN			(1 << 0)
 #define V7M_MPU_RASR_SIZE_BITS		1
 #define V7M_MPU_RASR_SIZE_4GB		(31 << V7M_MPU_RASR_SIZE_BITS)
+#define V7M_MPU_RASR_SIZE_8MB		(24 << V7M_MPU_RASR_SIZE_BITS)
+#define V7M_MPU_RASR_TEX_SHIFT	19
+#define V7M_MPU_RASR_S_SHIFT		18
+#define V7M_MPU_RASR_C_SHIFT		17
+#define V7M_MPU_RASR_B_SHIFT		16
 #define V7M_MPU_RASR_AP_RW_RW		(3 << 24)
+#define V7M_MPU_RASR_XN_ENABLE	(0 << 28)
+#define V7M_MPU_RASR_XN_DISABLE (1 << 28)
 
 #endif /* !defined(__ASSEMBLY__) */
 #endif /* ARMV7M_H */
diff --git a/arch/arm/include/asm/armv8/mmu.h b/arch/arm/include/asm/armv8/mmu.h
index 0d08ed3..aa0f3c4 100644
--- a/arch/arm/include/asm/armv8/mmu.h
+++ b/arch/arm/include/asm/armv8/mmu.h
@@ -135,12 +135,15 @@
 }
 
 struct mm_region {
-	u64 base;
+	u64 virt;
+	u64 phys;
 	u64 size;
 	u64 attrs;
 };
 
 extern struct mm_region *mem_map;
+void setup_pgtables(void);
+u64 get_tcr(int el, u64 *pips, u64 *pva_bits);
 #endif
 
 #endif /* _ASM_ARMV8_MMU_H_ */
diff --git a/arch/arm/include/asm/armv8/sec_firmware.h b/arch/arm/include/asm/armv8/sec_firmware.h
new file mode 100644
index 0000000..eb68185
--- /dev/null
+++ b/arch/arm/include/asm/armv8/sec_firmware.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2016 NXP Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __SEC_FIRMWARE_H_
+#define __SEC_FIRMWARE_H_
+
+#ifdef CONFIG_FSL_LS_PPA
+#include <asm/arch/ppa.h>
+#endif
+
+int sec_firmware_init(const void *, u32 *, u32 *);
+int _sec_firmware_entry(const void *, u32 *, u32 *);
+bool sec_firmware_is_valid(const void *);
+#ifdef CONFIG_ARMV8_PSCI
+unsigned int sec_firmware_support_psci_version(void);
+unsigned int _sec_firmware_support_psci_version(void);
+#endif
+
+#endif /* __SEC_FIRMWARE_H_ */
diff --git a/arch/arm/include/asm/barriers.h b/arch/arm/include/asm/barriers.h
index 37870f9..04784b7 100644
--- a/arch/arm/include/asm/barriers.h
+++ b/arch/arm/include/asm/barriers.h
@@ -30,15 +30,22 @@
 
 #endif /* !CONFIG_ARM64 */
 
-#if defined(__ARM_ARCH_7A__) || defined(CONFIG_ARM64)
+#if __LINUX_ARM_ARCH__ >= 7
 #define ISB	asm volatile ("isb sy" : : : "memory")
 #define DSB	asm volatile ("dsb sy" : : : "memory")
 #define DMB	asm volatile ("dmb sy" : : : "memory")
-#else
+#elif __LINUX_ARM_ARCH__ == 6
 #define ISB	CP15ISB
 #define DSB	CP15DSB
 #define DMB	CP15DMB
+#else
+#define ISB	asm volatile ("" : : : "memory")
+#define DSB	CP15DSB
+#define DMB	asm volatile ("" : : : "memory")
 #endif
 
+#define isb()	ISB
+#define dsb()	DSB
+#define dmb()	DMB
 #endif	/* __ASSEMBLY__ */
 #endif	/* __BARRIERS_H__ */
diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h
index 1f63127..16e65c3 100644
--- a/arch/arm/include/asm/cache.h
+++ b/arch/arm/include/asm/cache.h
@@ -29,6 +29,8 @@
 }
 #endif
 
+int check_cache_range(unsigned long start, unsigned long stop);
+
 void l2_cache_enable(void);
 void l2_cache_disable(void);
 void set_section_dcache(int section, enum dcache_option option);
diff --git a/arch/arm/include/asm/config.h b/arch/arm/include/asm/config.h
index 435fc45..1ad221a 100644
--- a/arch/arm/include/asm/config.h
+++ b/arch/arm/include/asm/config.h
@@ -11,7 +11,6 @@
 #define CONFIG_SYS_BOOT_RAMDISK_HIGH
 
 #ifdef CONFIG_ARM64
-#define CONFIG_PHYS_64BIT
 #define CONFIG_STATIC_RELA
 #endif
 
diff --git a/arch/arm/include/asm/fsl_secure_boot.h b/arch/arm/include/asm/fsl_secure_boot.h
index 53cd755..b35c271 100644
--- a/arch/arm/include/asm/fsl_secure_boot.h
+++ b/arch/arm/include/asm/fsl_secure_boot.h
@@ -17,8 +17,6 @@
 
 #ifdef CONFIG_CHAIN_OF_TRUST
 #define CONFIG_CMD_ESBC_VALIDATE
-#define CONFIG_CMD_BLOB
-#define CONFIG_CMD_HASH
 #define CONFIG_FSL_SEC_MON
 #define CONFIG_SHA_HW_ACCEL
 #define CONFIG_SHA_PROG_HW_ACCEL
@@ -28,6 +26,28 @@
 #define CONFIG_FSL_CAAM
 #endif
 
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SPL_BOARD_INIT
+#define CONFIG_SPL_DM			1
+#define CONFIG_SPL_CRYPTO_SUPPORT
+#define CONFIG_SPL_HASH_SUPPORT
+#define CONFIG_SPL_RSA
+#define CONFIG_SPL_DRIVERS_MISC_SUPPORT
+/*
+ * Define the key hash for U-Boot here if public/private key pair used to
+ * sign U-boot are different from the SRK hash put in the fuse
+ * Example of defining KEY_HASH is
+ * #define CONFIG_SPL_UBOOT_KEY_HASH \
+ *      "41066b564c6ffcef40ccbc1e0a5d0d519604000c785d97bbefd25e4d288d1c8b"
+ * else leave it defined as NULL
+ */
+
+#define CONFIG_SPL_UBOOT_KEY_HASH	NULL
+#endif /* ifdef CONFIG_SPL_BUILD */
+
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_CMD_BLOB
+#define CONFIG_CMD_HASH
 #define CONFIG_KEY_REVOCATION
 #ifndef CONFIG_SYS_RAMBOOT
 /* The key used for verification of next level images
@@ -58,39 +78,55 @@
 	"setenv hwconfig \'fsl_ddr:ctlr_intlv=null,bank_intlv=null\';"
 #else
 #define CONFIG_EXTRA_ENV \
-	"setenv fdt_high 0xcfffffff;"	\
-	"setenv initrd_high 0xcfffffff;"	\
+	"setenv fdt_high 0xffffffff;"	\
+	"setenv initrd_high 0xffffffff;"	\
 	"setenv hwconfig \'fsl_ddr:ctlr_intlv=null,bank_intlv=null\';"
 #endif
 
 /* Copying Bootscript and Header to DDR from NOR for LS2 and for rest, from
  * Non-XIP Memory (Nand/SD)*/
-#if defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_LS2080A)
+#if defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_LS2080A) || \
+	defined(CONFIG_SD_BOOT)
 #define CONFIG_BOOTSCRIPT_COPY_RAM
 #endif
-/* The address needs to be modified according to NOR and DDR memory map */
+/* The address needs to be modified according to NOR, NAND, SD and
+ * DDR memory map
+ */
 #ifdef CONFIG_LS2080A
-#define CONFIG_BS_HDR_ADDR_FLASH	0x583920000
-#define CONFIG_BS_ADDR_FLASH		0x583900000
+#define CONFIG_BS_HDR_ADDR_DEVICE	0x583920000
+#define CONFIG_BS_ADDR_DEVICE		0x583900000
 #define CONFIG_BS_HDR_ADDR_RAM		0xa3920000
 #define CONFIG_BS_ADDR_RAM		0xa3900000
+#define CONFIG_BS_HDR_SIZE		0x00002000
+#define CONFIG_BS_SIZE			0x00001000
+#else
+#ifdef CONFIG_SD_BOOT
+/* For SD boot address and size are assigned in terms of sector
+ * offset and no. of sectors respectively.
+ */
+#define CONFIG_BS_HDR_ADDR_DEVICE	0x00000800
+#define CONFIG_BS_ADDR_DEVICE		0x00000840
+#define CONFIG_BS_HDR_SIZE		0x00000010
+#define CONFIG_BS_SIZE			0x00000008
 #else
-#define CONFIG_BS_HDR_ADDR_FLASH	0x600a0000
-#define CONFIG_BS_ADDR_FLASH		0x60060000
-#define CONFIG_BS_HDR_ADDR_RAM		0xa0060000
-#define CONFIG_BS_ADDR_RAM		0xa0060000
+#define CONFIG_BS_HDR_ADDR_DEVICE	0x600a0000
+#define CONFIG_BS_ADDR_DEVICE		0x60060000
+#define CONFIG_BS_HDR_SIZE		0x00002000
+#define CONFIG_BS_SIZE			0x00001000
+#endif /* #ifdef CONFIG_SD_BOOT */
+#define CONFIG_BS_HDR_ADDR_RAM		0x81000000
+#define CONFIG_BS_ADDR_RAM		0x81020000
 #endif
 
 #ifdef CONFIG_BOOTSCRIPT_COPY_RAM
 #define CONFIG_BOOTSCRIPT_HDR_ADDR	CONFIG_BS_HDR_ADDR_RAM
-#define CONFIG_BS_HDR_SIZE		0x00002000
 #define CONFIG_BOOTSCRIPT_ADDR		CONFIG_BS_ADDR_RAM
-#define CONFIG_BS_SIZE			0x00001000
 #else
-#define CONFIG_BOOTSCRIPT_HDR_ADDR	CONFIG_BS_HDR_ADDR_FLASH
-/* BS_HDR_SIZE, BOOTSCRIPT_ADDR and BS_SIZE are not required */
+#define CONFIG_BOOTSCRIPT_HDR_ADDR	CONFIG_BS_HDR_ADDR_DEVICE
+/* BOOTSCRIPT_ADDR is not required */
 #endif
 
 #include <config_fsl_chain_trust.h>
+#endif /* #ifndef CONFIG_SPL_BUILD */
 #endif /* #ifdef CONFIG_CHAIN_OF_TRUST */
 #endif
diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index 77d2653..1055017 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -44,6 +44,21 @@
 	unsigned long tlb_emerg;
 #endif
 #endif
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+#define MEM_RESERVE_SECURE_SECURED	0x1
+#define MEM_RESERVE_SECURE_MAINTAINED	0x2
+#define MEM_RESERVE_SECURE_ADDR_MASK	(~0x3)
+	/*
+	 * Secure memory addr
+	 * This variable needs maintenance if the RAM base is not zero,
+	 * or if RAM splits into non-consecutive banks. It also has a
+	 * flag indicating the secure memory is marked as secure by MMU.
+	 * Flags used: 0x1 secured
+	 *             0x2 maintained
+	 */
+	phys_addr_t secure_ram;
+	unsigned long tlb_allocated;
+#endif
 
 #ifdef CONFIG_OMAP_COMMON
 	u32 omap_boot_device;
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 9d185a6..5834f5b 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -25,6 +25,7 @@
 #include <linux/types.h>
 #include <asm/byteorder.h>
 #include <asm/memory.h>
+#include <asm/barriers.h>
 #if 0	/* XXX###XXX */
 #include <asm/arch/hardware.h>
 #endif	/* XXX###XXX */
@@ -136,8 +137,7 @@
  * TODO: The kernel offers some more advanced versions of barriers, it might
  * have some advantages to use them instead of the simple one here.
  */
-#define mb()		asm volatile("dsb sy" : : : "memory")
-#define dmb()		__asm__ __volatile__ ("" : : : "memory")
+#define mb()		dsb()
 #define __iormb()	dmb()
 #define __iowmb()	dmb()
 
@@ -292,40 +292,6 @@
 #define readsb(a, d, s)		__raw_readsb((unsigned long)a, d, s)
 
 /*
- * ioremap and friends.
- *
- * ioremap takes a PCI memory address, as specified in
- * linux/Documentation/IO-mapping.txt.  If you want a
- * physical address, use __ioremap instead.
- */
-extern void * __ioremap(unsigned long offset, size_t size, unsigned long flags);
-extern void __iounmap(void *addr);
-
-/*
- * Generic ioremap support.
- *
- * Define:
- *  iomem_valid_addr(off,size)
- *  iomem_to_phys(off)
- */
-#ifdef iomem_valid_addr
-#define __arch_ioremap(off,sz,nocache)					\
- ({									\
-	unsigned long _off = (off), _size = (sz);			\
-	void *_ret = (void *)0;						\
-	if (iomem_valid_addr(_off, _size))				\
-		_ret = __ioremap(iomem_to_phys(_off),_size,nocache);	\
-	_ret;								\
- })
-
-#define __arch_iounmap __iounmap
-#endif
-
-#define ioremap(off,sz)			__arch_ioremap((off),(sz),0)
-#define ioremap_nocache(off,sz)		__arch_ioremap((off),(sz),1)
-#define iounmap(_addr)			__arch_iounmap(_addr)
-
-/*
  * DMA-consistent mapping functions.  These allocate/free a region of
  * uncached, unwrite-buffered mapped memory space for use with DMA
  * devices.  This is the "generic" version.  The PCI specific version
diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h
index 07f3848..605c549 100644
--- a/arch/arm/include/asm/omap_common.h
+++ b/arch/arm/include/asm/omap_common.h
@@ -627,6 +627,12 @@
 
 void omap_smc1(u32 service, u32 val);
 
+/*
+ * Low-level helper function used when performing secure ROM calls on high-
+ * security (HS) device variants by doing a specially-formed smc entry.
+ */
+u32 omap_smc_sec(u32 service, u32 proc_id, u32 flag, u32 *params);
+
 void enable_edma3_clocks(void);
 void disable_edma3_clocks(void);
 
diff --git a/arch/arm/include/asm/omap_sec_common.h b/arch/arm/include/asm/omap_sec_common.h
new file mode 100644
index 0000000..842f2af
--- /dev/null
+++ b/arch/arm/include/asm/omap_sec_common.h
@@ -0,0 +1,30 @@
+/*
+ * (C) Copyright 2016
+ * Texas Instruments, <www.ti.com>
+ *
+ * Andreas Dannenberg <dannenberg@ti.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#ifndef	_OMAP_SEC_COMMON_H_
+#define	_OMAP_SEC_COMMON_H_
+
+#include <common.h>
+
+/*
+ * Invoke secure ROM API on high-security (HS) device variants. It formats
+ * the variable argument list into the format expected by the ROM code before
+ * triggering the actual low-level smc entry.
+ */
+u32 secure_rom_call(u32 service, u32 proc_id, u32 flag, ...);
+
+/*
+ * Invoke a secure ROM API on high-secure (HS) device variants that can be used
+ * to verify a secure blob by authenticating and optionally decrypting it. The
+ * exact operation performed depends on how the certificate that was embedded
+ * into the blob during the signing/encryption step when the secure blob was
+ * first created.
+ */
+int secure_boot_verify_image(void **p_image, size_t *p_size);
+
+#endif /* _OMAP_SEC_COMMON_H_ */
diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h
index bc5edda..5b8ce4d 100644
--- a/arch/arm/include/asm/psci.h
+++ b/arch/arm/include/asm/psci.h
@@ -18,6 +18,9 @@
 #ifndef __ARM_PSCI_H__
 #define __ARM_PSCI_H__
 
+#define ARM_PSCI_VER_1_0		(0x00010000)
+#define ARM_PSCI_VER_0_2		(0x00000002)
+
 /* PSCI 0.1 interface */
 #define ARM_PSCI_FN_BASE		0x95c1ba5e
 #define ARM_PSCI_FN(n)			(ARM_PSCI_FN_BASE + (n))
@@ -31,6 +34,12 @@
 #define ARM_PSCI_RET_NI			(-1)
 #define ARM_PSCI_RET_INVAL		(-2)
 #define ARM_PSCI_RET_DENIED		(-3)
+#define ARM_PSCI_RET_ALREADY_ON		(-4)
+#define ARM_PSCI_RET_ON_PENDING		(-5)
+#define ARM_PSCI_RET_INTERNAL_FAILURE	(-6)
+#define ARM_PSCI_RET_NOT_PRESENT	(-7)
+#define ARM_PSCI_RET_DISABLED		(-8)
+#define ARM_PSCI_RET_INVALID_ADDRESS	(-9)
 
 /* PSCI 0.2 interface */
 #define ARM_PSCI_0_2_FN_BASE			0x84000000
@@ -47,16 +56,39 @@
 #define ARM_PSCI_0_2_FN_SYSTEM_OFF		ARM_PSCI_0_2_FN(8)
 #define ARM_PSCI_0_2_FN_SYSTEM_RESET		ARM_PSCI_0_2_FN(9)
 
+/* PSCI 1.0 interface */
+#define ARM_PSCI_1_0_FN_PSCI_FEATURES		ARM_PSCI_0_2_FN(10)
+#define ARM_PSCI_1_0_FN_CPU_FREEZE		ARM_PSCI_0_2_FN(11)
+#define ARM_PSCI_1_0_FN_CPU_DEFAULT_SUSPEND	ARM_PSCI_0_2_FN(12)
+#define ARM_PSCI_1_0_FN_NODE_HW_STATE		ARM_PSCI_0_2_FN(13)
+#define ARM_PSCI_1_0_FN_SYSTEM_SUSPEND		ARM_PSCI_0_2_FN(14)
+#define ARM_PSCI_1_0_FN_SET_SUSPEND_MODE	ARM_PSCI_0_2_FN(15)
+#define ARM_PSCI_1_0_FN_STAT_RESIDENCY		ARM_PSCI_0_2_FN(16)
+#define ARM_PSCI_1_0_FN_STAT_COUNT		ARM_PSCI_0_2_FN(17)
+
+/* 1KB stack per core */
+#define ARM_PSCI_STACK_SHIFT	10
+#define ARM_PSCI_STACK_SIZE	(1 << ARM_PSCI_STACK_SHIFT)
+
+/* PSCI affinity level state returned by AFFINITY_INFO */
+#define PSCI_AFFINITY_LEVEL_ON		0
+#define PSCI_AFFINITY_LEVEL_OFF		1
+#define PSCI_AFFINITY_LEVEL_ON_PENDING	2
+
 #ifndef __ASSEMBLY__
 #include <asm/types.h>
 
+/* These 2 helper functions assume cpu < CONFIG_ARMV7_PSCI_NR_CPUS */
+u32 psci_get_target_pc(int cpu);
+void psci_save_target_pc(int cpu, u32 pc);
+
 void psci_cpu_entry(void);
 u32 psci_get_cpu_id(void);
-u32 psci_get_cpu_stack_top(int cpu);
 void psci_cpu_off_common(void);
 
 int psci_update_dt(void *fdt);
 void psci_board_init(void);
+int fdt_psci(void *fdt);
 #endif /* ! __ASSEMBLY__ */
 
 #endif /* __ARM_PSCI_H__ */
diff --git a/arch/arm/include/asm/secure.h b/arch/arm/include/asm/secure.h
index effdb18..5a403bc 100644
--- a/arch/arm/include/asm/secure.h
+++ b/arch/arm/include/asm/secure.h
@@ -3,6 +3,9 @@
 
 #include <config.h>
 
+#define __secure __attribute__ ((section ("._secure.text")))
+#define __secure_data __attribute__ ((section ("._secure.data")))
+
 #ifdef CONFIG_ARMV7_SECURE_BASE
 /*
  * Warning, horror ahead.
diff --git a/arch/arm/include/asm/setjmp.h b/arch/arm/include/asm/setjmp.h
index ae738b2..f7b97ef 100644
--- a/arch/arm/include/asm/setjmp.h
+++ b/arch/arm/include/asm/setjmp.h
@@ -43,6 +43,7 @@
 #else
 	asm volatile(
 #ifdef CONFIG_SYS_THUMB_BUILD
+		".align 2\n"
 		"adr r0, jmp_target\n"
 		"add r0, r0, $1\n"
 #else
@@ -52,7 +53,8 @@
 		"mov r2, sp\n"
 		"stm r1!, {r0, r2, r4, r5, r6, r7}\n"
 		"b 2f\n"
-		"jmp_target: "
+		".align 2\n"
+		"jmp_target: \n"
 		"mov %0, #1\n"
 		"2:\n"
 		: "+l" (r)
diff --git a/arch/arm/include/asm/spin_table.h b/arch/arm/include/asm/spin_table.h
new file mode 100644
index 0000000..8b57539
--- /dev/null
+++ b/arch/arm/include/asm/spin_table.h
@@ -0,0 +1,14 @@
+/*
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __ASM_SPIN_TABLE_H__
+#define __ASM_SPIN_TABLE_H__
+
+extern u64 spin_table_cpu_release_addr;
+extern char spin_table_reserve_begin;
+extern char spin_table_reserve_end;
+
+int spin_table_update_dt(void *fdt);
+
+#endif /* __ASM_SPIN_TABLE_H__ */
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 2bdc0be..7b7b867 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -3,6 +3,7 @@
 
 #include <common.h>
 #include <linux/compiler.h>
+#include <asm/barriers.h>
 
 #ifdef CONFIG_ARM64
 
@@ -34,11 +35,6 @@
 	DCACHE_WRITEALLOC = 4 << 2,
 };
 
-#define isb()				\
-	({asm volatile(			\
-	"isb" : : : "memory");		\
-	})
-
 #define wfi()				\
 	({asm volatile(			\
 	"wfi" : : : "memory");		\
@@ -227,8 +223,6 @@
  */
 void save_boot_params_ret(void);
 
-#define isb() __asm__ __volatile__ ("" : : : "memory")
-
 #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
 
 #ifdef __ARM_ARCH_7A__
diff --git a/arch/arm/include/asm/types.h b/arch/arm/include/asm/types.h
index d108915..9af7353 100644
--- a/arch/arm/include/asm/types.h
+++ b/arch/arm/include/asm/types.h
@@ -71,5 +71,4 @@
 
 #endif /* __KERNEL__ */
 
-typedef unsigned long resource_size_t;
 #endif
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 0e05e87..caa62c6 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -26,12 +26,15 @@
 
 obj-$(CONFIG_CPU_V7M) += cmd_boot.o
 obj-$(CONFIG_OF_LIBFDT) += bootm-fdt.o
+obj-$(CONFIG_CMD_BOOTI) += bootm.o
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
+obj-$(CONFIG_CMD_BOOTZ) += bootm.o zimage.o
 obj-$(CONFIG_SYS_L2_PL310) += cache-pl310.o
 obj-$(CONFIG_USE_ARCH_MEMSET) += memset.o
 obj-$(CONFIG_USE_ARCH_MEMCPY) += memcpy.o
 else
 obj-$(CONFIG_SPL_FRAMEWORK) += spl.o
+obj-$(CONFIG_SPL_FRAMEWORK) += zimage.o
 endif
 obj-$(CONFIG_SEMIHOSTING) += semihosting.o
 
@@ -55,6 +58,8 @@
 obj-y	+= cache-cp15.o
 endif
 
+obj-y	+= psci-dt.o
+
 obj-$(CONFIG_DEBUG_LL)	+= debug.o
 
 # For EABI conformant tool chains, provide eabi_compat()
@@ -63,11 +68,6 @@
 endif
 
 asflags-y += -DCONFIG_ARM_ASM_UNIFIED
-ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TEGRA),yy)
-asflags-y += -D__LINUX_ARM_ARCH__=4
-else
-asflags-y += -D__LINUX_ARM_ARCH__=$(CONFIG_SYS_ARM_ARCH)
-endif
 
 # some files can only build in ARM or THUMB2, not THUMB1
 
diff --git a/arch/arm/lib/bootm-fdt.c b/arch/arm/lib/bootm-fdt.c
index 76b75d8..a517550 100644
--- a/arch/arm/lib/bootm-fdt.c
+++ b/arch/arm/lib/bootm-fdt.c
@@ -21,9 +21,11 @@
 #include <asm/armv7.h>
 #endif
 #include <asm/psci.h>
+#include <asm/spin_table.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#ifdef CONFIG_ARCH_FIXUP_FDT
 int arch_fixup_fdt(void *blob)
 {
 	bd_t *bd = gd->bd;
@@ -45,7 +47,13 @@
 	if (ret)
 		return ret;
 
-#ifdef CONFIG_ARMV7_NONSEC
+#ifdef CONFIG_ARMV8_SPIN_TABLE
+	ret = spin_table_update_dt(blob);
+	if (ret)
+		return ret;
+#endif
+
+#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV8_PSCI)
 	ret = psci_update_dt(blob);
 	if (ret)
 		return ret;
@@ -53,3 +61,4 @@
 
 	return 0;
 }
+#endif
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 0838d89..53c3141 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -248,15 +248,20 @@
 	}
 }
 
-#ifdef CONFIG_ARMV7_NONSEC
-bool armv7_boot_nonsec(void)
+__weak bool armv7_boot_nonsec_default(void)
 {
-	char *s = getenv("bootm_boot_mode");
 #ifdef CONFIG_ARMV7_BOOT_SEC_DEFAULT
-	bool nonsec = false;
+	return false;
 #else
-	bool nonsec = true;
+	return true;
 #endif
+}
+
+#ifdef CONFIG_ARMV7_NONSEC
+bool armv7_boot_nonsec(void)
+{
+	char *s = getenv("bootm_boot_mode");
+	bool nonsec = armv7_boot_nonsec_default();
 
 	if (s && !strcmp(s, "sec"))
 		nonsec = false;
@@ -358,38 +363,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_CMD_BOOTZ
-
-struct zimage_header {
-	uint32_t	code[9];
-	uint32_t	zi_magic;
-	uint32_t	zi_start;
-	uint32_t	zi_end;
-};
-
-#define	LINUX_ARM_ZIMAGE_MAGIC	0x016f2818
-
-int bootz_setup(ulong image, ulong *start, ulong *end)
-{
-	struct zimage_header *zi;
-
-	zi = (struct zimage_header *)map_sysmem(image, 0);
-	if (zi->zi_magic != LINUX_ARM_ZIMAGE_MAGIC) {
-		puts("Bad Linux ARM zImage magic!\n");
-		return 1;
-	}
-
-	*start = zi->zi_start;
-	*end = zi->zi_end;
-
-	printf("Kernel image @ %#08lx [ %#08lx - %#08lx ]\n", image, *start,
-	      *end);
-
-	return 0;
-}
-
-#endif	/* CONFIG_CMD_BOOTZ */
-
 #if defined(CONFIG_BOOTM_VXWORKS)
 void boot_prep_vxworks(bootm_headers_t *images)
 {
@@ -399,8 +372,10 @@
 	if (images->ft_addr) {
 		off = fdt_path_offset(images->ft_addr, "/memory");
 		if (off < 0) {
+#ifdef CONFIG_ARCH_FIXUP_FDT
 			if (arch_fixup_fdt(images->ft_addr))
 				puts("## WARNING: fixup memory failed!\n");
+#endif
 		}
 	}
 #endif
diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c
index 3bd8710..d330b09 100644
--- a/arch/arm/lib/cache.c
+++ b/arch/arm/lib/cache.c
@@ -10,6 +10,10 @@
 #include <common.h>
 #include <malloc.h>
 
+#ifndef CONFIG_SYS_CACHELINE_SIZE
+#define CONFIG_SYS_CACHELINE_SIZE 32
+#endif
+
 /*
  * Flush range from all levels of d-cache/unified-cache.
  * Affects the range [start, start + size - 1].
@@ -46,6 +50,24 @@
 	/* An empty stub, real implementation should be in platform code */
 }
 
+int check_cache_range(unsigned long start, unsigned long stop)
+{
+	int ok = 1;
+
+	if (start & (CONFIG_SYS_CACHELINE_SIZE - 1))
+		ok = 0;
+
+	if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1))
+		ok = 0;
+
+	if (!ok) {
+		warn_non_spl("CACHE: Misaligned operation at range [%08lx, %08lx]\n",
+			     start, stop);
+	}
+
+	return ok;
+}
+
 #ifdef CONFIG_SYS_NONCACHED_MEMORY
 /*
  * Reserve one MMU section worth of address space below the malloc() area that
diff --git a/arch/arm/lib/crt0_64.S b/arch/arm/lib/crt0_64.S
index cad22c7..91b19e0 100644
--- a/arch/arm/lib/crt0_64.S
+++ b/arch/arm/lib/crt0_64.S
@@ -108,6 +108,7 @@
  * Set up final (full) environment
  */
 	bl	c_runtime_cpu_setup		/* still call old routine */
+#endif /* !CONFIG_SPL_BUILD */
 
 /* TODO: For SPL, call spl_relocate_stack_gd() to alloc stack relocation */
 
@@ -130,6 +131,4 @@
 
 	/* NOTREACHED - board_init_r() does not return */
 
-#endif /* !CONFIG_SPL_BUILD */
-
 ENDPROC(_main)
diff --git a/arch/arm/lib/psci-dt.c b/arch/arm/lib/psci-dt.c
new file mode 100644
index 0000000..baf6d70
--- /dev/null
+++ b/arch/arm/lib/psci-dt.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2016 NXP Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+#include <linux/sizes.h>
+#include <linux/kernel.h>
+#include <asm/psci.h>
+#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
+#include <asm/armv8/sec_firmware.h>
+#endif
+
+int fdt_psci(void *fdt)
+{
+#if defined(CONFIG_ARMV8_PSCI) || defined(CONFIG_ARMV7_PSCI)
+	int nodeoff;
+	unsigned int psci_ver = 0;
+	int tmp;
+
+	nodeoff = fdt_path_offset(fdt, "/cpus");
+	if (nodeoff < 0) {
+		printf("couldn't find /cpus\n");
+		return nodeoff;
+	}
+
+	/* add 'enable-method = "psci"' to each cpu node */
+	for (tmp = fdt_first_subnode(fdt, nodeoff);
+	     tmp >= 0;
+	     tmp = fdt_next_subnode(fdt, tmp)) {
+		const struct fdt_property *prop;
+		int len;
+
+		prop = fdt_get_property(fdt, tmp, "device_type", &len);
+		if (!prop)
+			continue;
+		if (len < 4)
+			continue;
+		if (strcmp(prop->data, "cpu"))
+			continue;
+
+		/*
+		 * Not checking rv here, our approach is to skip over errors in
+		 * individual cpu nodes, hopefully some of the nodes are
+		 * processed correctly and those will boot
+		 */
+		fdt_setprop_string(fdt, tmp, "enable-method", "psci");
+	}
+
+	nodeoff = fdt_path_offset(fdt, "/psci");
+	if (nodeoff >= 0)
+		goto init_psci_node;
+
+	nodeoff = fdt_path_offset(fdt, "/");
+	if (nodeoff < 0)
+		return nodeoff;
+
+	nodeoff = fdt_add_subnode(fdt, nodeoff, "psci");
+	if (nodeoff < 0)
+		return nodeoff;
+
+init_psci_node:
+#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
+	psci_ver = sec_firmware_support_psci_version();
+#elif defined(CONFIG_ARMV7_PSCI_1_0)
+	psci_ver = ARM_PSCI_VER_1_0;
+#endif
+	switch (psci_ver) {
+	case ARM_PSCI_VER_1_0:
+		tmp = fdt_setprop_string(fdt, nodeoff,
+				"compatible", "arm,psci-1.0");
+		if (tmp)
+			return tmp;
+	case ARM_PSCI_VER_0_2:
+		tmp = fdt_appendprop_string(fdt, nodeoff,
+				"compatible", "arm,psci-0.2");
+		if (tmp)
+			return tmp;
+	default:
+	/*
+	 * The Secure firmware framework isn't able to support PSCI version 0.1.
+	 */
+#ifndef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
+		tmp = fdt_appendprop_string(fdt, nodeoff,
+				"compatible", "arm,psci");
+		if (tmp)
+			return tmp;
+		tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_suspend",
+				ARM_PSCI_FN_CPU_SUSPEND);
+		if (tmp)
+			return tmp;
+		tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_off",
+				ARM_PSCI_FN_CPU_OFF);
+		if (tmp)
+			return tmp;
+		tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_on",
+				ARM_PSCI_FN_CPU_ON);
+		if (tmp)
+			return tmp;
+		tmp = fdt_setprop_u32(fdt, nodeoff, "migrate",
+				ARM_PSCI_FN_MIGRATE);
+		if (tmp)
+			return tmp;
+#endif
+		break;
+	}
+
+	tmp = fdt_setprop_string(fdt, nodeoff, "method", "smc");
+	if (tmp)
+		return tmp;
+
+#endif
+	return 0;
+}
diff --git a/arch/arm/lib/sections.c b/arch/arm/lib/sections.c
index 6a94522..952e8ae 100644
--- a/arch/arm/lib/sections.c
+++ b/arch/arm/lib/sections.c
@@ -27,6 +27,8 @@
 char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end")));
 char __secure_start[0] __attribute__((section(".__secure_start")));
 char __secure_end[0] __attribute__((section(".__secure_end")));
+char __secure_stack_start[0] __attribute__((section(".__secure_stack_start")));
+char __secure_stack_end[0] __attribute__((section(".__secure_stack_end")));
 char __efi_runtime_start[0] __attribute__((section(".__efi_runtime_start")));
 char __efi_runtime_stop[0] __attribute__((section(".__efi_runtime_stop")));
 char __efi_runtime_rel_start[0] __attribute__((section(".__efi_runtime_rel_start")));
diff --git a/arch/arm/lib/spl.c b/arch/arm/lib/spl.c
index e428868..3587ad6 100644
--- a/arch/arm/lib/spl.c
+++ b/arch/arm/lib/spl.c
@@ -25,22 +25,20 @@
 #endif
 
 /*
- * In the context of SPL, board_init_f must ensure that any clocks/etc for
- * DDR are enabled, ensure that the stack pointer is valid, clear the BSS
- * and call board_init_r.  We provide this version by default but mark it
- * as __weak to allow for platforms to do this in their own way if needed.
+ * In the context of SPL, board_init_f() prepares the hardware for execution
+ * from system RAM (DRAM, DDR...). As system RAM may not be available yet,
+ * board_init_f() must use the current GD to store any data which must be
+ * passed on to later stages. These data include the relocation destination,
+ * the future stack, and the future GD location. BSS is cleared after this
+ * function (and therefore must be accessible).
+ *
+ * We provide this version by default but mark it as __weak to allow for
+ * platforms to do this in their own way if needed. Please see the top
+ * level U-Boot README "Board Initialization Flow" section for info on what
+ * to put in this function.
  */
 void __weak board_init_f(ulong dummy)
 {
-	/* Clear the BSS. */
-	memset(__bss_start, 0, __bss_end - __bss_start);
-
-#ifndef CONFIG_SPL_DM
-	/* TODO: Remove settings of the global data pointer here */
-	gd = &gdata;
-#endif
-
-	board_init_r(NULL, 0);
 }
 
 /*
@@ -60,7 +58,7 @@
 	typedef void (*image_entry_arg_t)(int, int, void *)
 		__attribute__ ((noreturn));
 	image_entry_arg_t image_entry =
-		(image_entry_arg_t) spl_image.entry_point;
+		(image_entry_arg_t)(uintptr_t) spl_image.entry_point;
 	cleanup_before_linux();
 	image_entry(0, machid, arg);
 }
diff --git a/arch/arm/lib/zimage.c b/arch/arm/lib/zimage.c
new file mode 100644
index 0000000..1e811a8
--- /dev/null
+++ b/arch/arm/lib/zimage.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016
+ * Ladislav Michl <ladis@linux-mips.org>
+ *
+ * bootz code:
+ * Copyright (C) 2012 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+
+#define	LINUX_ARM_ZIMAGE_MAGIC	0x016f2818
+
+struct arm_z_header {
+	uint32_t	code[9];
+	uint32_t	zi_magic;
+	uint32_t	zi_start;
+	uint32_t	zi_end;
+} __attribute__ ((__packed__));
+
+int bootz_setup(ulong image, ulong *start, ulong *end)
+{
+	struct arm_z_header *zi = (struct arm_z_header *)image;
+
+	if (zi->zi_magic != LINUX_ARM_ZIMAGE_MAGIC) {
+#ifndef CONFIG_SPL_FRAMEWORK
+		puts("Bad Linux ARM zImage magic!\n");
+#endif
+		return 1;
+	}
+
+	*start = zi->zi_start;
+	*end = zi->zi_end;
+#ifndef CONFIG_SPL_FRAMEWORK
+	printf("Kernel image @ %#08lx [ %#08lx - %#08lx ]\n",
+	       image, *start, *end);
+#endif
+
+	return 0;
+}
diff --git a/arch/arm/mach-at91/include/mach/at91_pmc.h b/arch/arm/mach-at91/include/mach/at91_pmc.h
index 680ceb0..2875ff2 100644
--- a/arch/arm/mach-at91/include/mach/at91_pmc.h
+++ b/arch/arm/mach-at91/include/mach/at91_pmc.h
@@ -149,6 +149,9 @@
 
 #define AT91_PMC_PCR_PID_MASK		(0x3f)
 #define AT91_PMC_PCR_GCKCSS		(0x7 << 8)
+#define AT91_PMC_PCR_GCKCSS_MASK	0x07
+#define AT91_PMC_PCR_GCKCSS_OFFSET	8
+#define AT91_PMC_PCR_GCKCSS_(x)		((x & 0x07) << 8)
 #define		AT91_PMC_PCR_GCKCSS_SLOW_CLK	(0x0 << 8)
 #define		AT91_PMC_PCR_GCKCSS_MAIN_CLK	(0x1 << 8)
 #define		AT91_PMC_PCR_GCKCSS_PLLA_CLK	(0x2 << 8)
@@ -158,8 +161,9 @@
 #define AT91_PMC_PCR_CMD_WRITE		(0x1 << 12)
 #define AT91_PMC_PCR_DIV		(0x3 << 16)
 #define AT91_PMC_PCR_GCKDIV		(0xff << 20)
-#define		AT91_PMC_PCR_GCKDIV_(x)		(((x) & 0xff) << 20)
-#define		AT91_PMC_PCR_GCKDIV_OFFSET	20
+#define AT91_PMC_PCR_GCKDIV_MASK	0xff
+#define AT91_PMC_PCR_GCKDIV_OFFSET	20
+#define AT91_PMC_PCR_GCKDIV_(x)		((x & 0xff) << 20)
 #define AT91_PMC_PCR_EN			(0x1 << 28)
 #define AT91_PMC_PCR_GCKEN		(0x1 << 29)
 
@@ -243,8 +247,9 @@
 #define		AT91_PMC_PCK1RDY	(1 <<  9)		/* Programmable Clock 1 */
 #define		AT91_PMC_PCK2RDY	(1 << 10)		/* Programmable Clock 2 */
 #define		AT91_PMC_PCK3RDY	(1 << 11)		/* Programmable Clock 3 */
+#define		AT91_PMC_MOSCSELS	BIT(16)			/* Main Oscillator Selection Status */
+#define		AT91_PMC_MOSCRCS	BIT(17)			/* 12 MHz RC Oscillator Status */
 #define		AT91_PMC_GCKRDY		(1 << 24)
-
 #define		AT91_PMC_PROTKEY	0x504d4301	/* Activation Code */
 
 /* PLL Charge Pump Current Register (PMC_PLLICPR) */
diff --git a/arch/arm/mach-at91/include/mach/atmel_pio4.h b/arch/arm/mach-at91/include/mach/atmel_pio4.h
index 8bb4b12..6760bec 100644
--- a/arch/arm/mach-at91/include/mach/atmel_pio4.h
+++ b/arch/arm/mach-at91/include/mach/atmel_pio4.h
@@ -29,6 +29,41 @@
 
 #endif
 
+/*
+ * PIO Configuration Register Fields
+ */
+#define ATMEL_PIO_CFGR_FUNC_MASK	GENMASK(2, 0)
+#define ATMEL_PIO_CFGR_FUNC_GPIO	(0x0 << 0)
+#define ATMEL_PIO_CFGR_FUNC_PERIPH_A	(0x1 << 0)
+#define ATMEL_PIO_CFGR_FUNC_PERIPH_B	(0x2 << 0)
+#define ATMEL_PIO_CFGR_FUNC_PERIPH_C	(0x3 << 0)
+#define ATMEL_PIO_CFGR_FUNC_PERIPH_D	(0x4 << 0)
+#define ATMEL_PIO_CFGR_FUNC_PERIPH_E	(0x5 << 0)
+#define ATMEL_PIO_CFGR_FUNC_PERIPH_F	(0x6 << 0)
+#define ATMEL_PIO_CFGR_FUNC_PERIPH_G	(0x7 << 0)
+#define ATMEL_PIO_DIR_MASK		BIT(8)
+#define ATMEL_PIO_PUEN_MASK		BIT(9)
+#define ATMEL_PIO_PDEN_MASK		BIT(10)
+#define ATMEL_PIO_IFEN_MASK		BIT(12)
+#define ATMEL_PIO_IFSCEN_MASK		BIT(13)
+#define ATMEL_PIO_OPD_MASK		BIT(14)
+#define ATMEL_PIO_SCHMITT_MASK		BIT(15)
+#define ATMEL_PIO_CFGR_EVTSEL_MASK	GENMASK(26, 24)
+#define ATMEL_PIO_CFGR_EVTSEL_FALLING	(0 << 24)
+#define ATMEL_PIO_CFGR_EVTSEL_RISING	(1 << 24)
+#define ATMEL_PIO_CFGR_EVTSEL_BOTH	(2 << 24)
+#define ATMEL_PIO_CFGR_EVTSEL_LOW	(3 << 24)
+#define ATMEL_PIO_CFGR_EVTSEL_HIGH	(4 << 24)
+
+#define ATMEL_PIO_NPINS_PER_BANK	32
+#define ATMEL_PIO_BANK(pin_id)		(pin_id / ATMEL_PIO_NPINS_PER_BANK)
+#define ATMEL_PIO_LINE(pin_id)		(pin_id % ATMEL_PIO_NPINS_PER_BANK)
+#define ATMEL_PIO_BANK_OFFSET		0x40
+
+#define ATMEL_GET_PIN_NO(pinfunc)	((pinfunc) & 0xff)
+#define ATMEL_GET_PIN_FUNC(pinfunc)	((pinfunc >> 16) & 0xf)
+#define ATMEL_GET_PIN_IOSET(pinfunc)	((pinfunc >> 20) & 0xf)
+
 #define AT91_PIO_PORTA		0x0
 #define AT91_PIO_PORTB		0x1
 #define AT91_PIO_PORTC		0x2
diff --git a/arch/arm/mach-exynos/include/mach/dwmmc.h b/arch/arm/mach-exynos/include/mach/dwmmc.h
index bd997ad..ab8361f 100644
--- a/arch/arm/mach-exynos/include/mach/dwmmc.h
+++ b/arch/arm/mach-exynos/include/mach/dwmmc.h
@@ -28,4 +28,3 @@
 #define DWMCI_DIVRATIO_MASK		0x7
 
 int exynos_dwmmc_init(const void *blob);
-int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel);
diff --git a/arch/arm/mach-exynos/include/mach/system.h b/arch/arm/mach-exynos/include/mach/system.h
index 3ffb296..2c94a6b 100644
--- a/arch/arm/mach-exynos/include/mach/system.h
+++ b/arch/arm/mach-exynos/include/mach/system.h
@@ -38,16 +38,6 @@
 #define USB20_PHY_CFG_HOST_LINK_EN	(1 << 0)
 
 /*
- * Data Synchronization Barrier acts as a special kind of memory barrier.
- * No instruction in program order after this instruction executes until
- * this instruction completes. This instruction completes when:
- * - All explicit memory accesses before this instruction complete.
- * - All Cache, Branch predictor and TLB maintenance operations before
- *   this instruction complete.
- */
-#define dsb() __asm__ __volatile__ ("dsb\n\t" : : );
-
-/*
  * This instruction causes an event to be signaled to all cores
  * within a multiprocessor system. If SEV is implemented,
  * WFE must also be implemented.
diff --git a/arch/arm/mach-exynos/mmu-arm64.c b/arch/arm/mach-exynos/mmu-arm64.c
index ba6d99d..2381422 100644
--- a/arch/arm/mach-exynos/mmu-arm64.c
+++ b/arch/arm/mach-exynos/mmu-arm64.c
@@ -13,21 +13,20 @@
 #ifdef CONFIG_EXYNOS7420
 static struct mm_region exynos7420_mem_map[] = {
 	{
-		.base	= 0x10000000UL,
+		.virt	= 0x10000000UL,
+		.phys	= 0x10000000UL,
 		.size	= 0x10000000UL,
 		.attrs	= PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 				PTE_BLOCK_NON_SHARE |
 				PTE_BLOCK_PXN | PTE_BLOCK_UXN,
 	}, {
-		.base	= 0x40000000UL,
+		.virt	= 0x40000000UL,
+		.phys	= 0x40000000UL,
 		.size	= 0x80000000UL,
 		.attrs	= PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 				PTE_BLOCK_INNER_SHARE,
 	}, {
 		/* List terminator */
-		.base	= 0,
-		.size	= 0,
-		.attrs	= 0,
 	},
 };
 
diff --git a/arch/arm/mach-keystone/init.c b/arch/arm/mach-keystone/init.c
index 3b6d5ef..6e5a1e1 100644
--- a/arch/arm/mach-keystone/init.c
+++ b/arch/arm/mach-keystone/init.c
@@ -101,9 +101,7 @@
 	msmc_share_all_segments(KS2_MSMC_SEGMENT_C6X_0);
 	msmc_share_all_segments(K2HKLE_MSMC_SEGMENT_ARM);
 	msmc_share_all_segments(K2HKLE_MSMC_SEGMENT_NETCP);
-#ifdef KS2_MSMC_SEGMENT_QM_PDSP
 	msmc_share_all_segments(K2HKLE_MSMC_SEGMENT_QM_PDSP);
-#endif
 	msmc_share_all_segments(K2HKLE_MSMC_SEGMENT_PCIE0);
 	msmc_share_all_segments(KS2_MSMC_SEGMENT_DEBUG);
 }
diff --git a/arch/arm/mach-meson/board.c b/arch/arm/mach-meson/board.c
index 64fa3c1..1dd53e2 100644
--- a/arch/arm/mach-meson/board.c
+++ b/arch/arm/mach-meson/board.c
@@ -48,12 +48,14 @@
 
 static struct mm_region gxbb_mem_map[] = {
 	{
-		.base = 0x0UL,
+		.virt = 0x0UL,
+		.phys = 0x0UL,
 		.size = 0x80000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_INNER_SHARE
 	}, {
-		.base = 0x80000000UL,
+		.virt = 0x80000000UL,
+		.phys = 0x80000000UL,
 		.size = 0x80000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE |
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 2a8afac..1aac3c8 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -1,7 +1,21 @@
 if ARCH_ROCKCHIP
 
+config ROCKCHIP_RK3036
+	bool "Support Rockchip RK3036"
+	select CPU_V7
+	select SUPPORT_SPL
+	select SPL
+	help
+	  The Rockchip RK3036 is a ARM-based SoC with a dual-core Cortex-A7
+	  including NEON and GPU, Mali-400 graphics, several DDR3 options
+	  and video codec support. Peripherals include Gigabit Ethernet,
+	  USB2 host and OTG, SDIO, I2S, UART, SPI, I2C and PWMs.
+
 config ROCKCHIP_RK3288
 	bool "Support Rockchip RK3288"
+	select CPU_V7
+	select SUPPORT_SPL
+	select SPL
 	help
 	  The Rockchip RK3288 is a ARM-based SoC with a quad-core Cortex-A17
 	  including NEON and GPU, 1MB L2 cache, Mali-T7 graphics, two
@@ -9,41 +23,26 @@
 	  and video codec support. Peripherals include Gigabit Ethernet,
 	  USB2 host and OTG, SDIO, I2S, UART,s, SPI, I2C and PWMs.
 
-config ROCKCHIP_RK3036
-	bool "Support Rockchip RK3036"
+config ROCKCHIP_RK3399
+	bool "Support Rockchip RK3399"
+	select ARM64
 	help
-	  The Rockchip RK3036 is a ARM-based SoC with a dual-core Cortex-A7
-	  including NEON and GPU, Mali-400 graphics, several DDR3 options
+	  The Rockchip RK3399 is a ARM-based SoC with a dual-core Cortex-A72
+	  and quad-core Cortex-A53.
+	  including NEON and GPU, 1MB L2 cache, Mali-T7 graphics, two
+	  video interfaces supporting HDMI and eDP, several DDR3 options
 	  and video codec support. Peripherals include Gigabit Ethernet,
-	  USB2 host and OTG, SDIO, I2S, UART, SPI, I2C and PWMs.
-
-config SYS_MALLOC_F
-	default y
-
-config SPL_SYS_MALLOC_SIMPLE
-	default y
+	  USB2 host and OTG, SDIO, I2S, UARTs, SPI, I2C and PWMs.
 
-config SPL_DM
-	default y
-
-config DM_SERIAL
-	default y
-
-config DM_SPI
-	default y
-
-config DM_SPI_FLASH
-	default y
-
-config DM_I2C
-	default y
-
-config DM_GPIO
-	default y
-
-config BLK
-	default y
+config ROCKCHIP_SPL_BACK_TO_BROM
+	bool "SPL returns to bootrom"
+	default y if ROCKCHIP_RK3036
+	help
+	  Rockchip SoCs have ability to load SPL & U-Boot binary. If enabled,
+          SPL will return to the boot rom, which will then load the U-Boot
+          binary to keep going on.
 
-source "arch/arm/mach-rockchip/rk3288/Kconfig"
 source "arch/arm/mach-rockchip/rk3036/Kconfig"
+source "arch/arm/mach-rockchip/rk3288/Kconfig"
+source "arch/arm/mach-rockchip/rk3399/Kconfig"
 endif
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 55567cb..157d42f 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -5,11 +5,15 @@
 #
 
 ifdef CONFIG_SPL_BUILD
-obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-spl.o
 obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board-spl.o
+obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-spl.o
+obj-$(CONFIG_ROCKCHIP_SPL_BACK_TO_BROM) += save_boot_param.o
 else
 obj-$(CONFIG_ROCKCHIP_RK3288) += board.o
 endif
+ifndef CONFIG_ARM64
 obj-y += rk_timer.o
-obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288/
+endif
 obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036/
+obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288/
+obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399/
diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c
index 816540e..bec756d 100644
--- a/arch/arm/mach-rockchip/board.c
+++ b/arch/arm/mach-rockchip/board.c
@@ -10,12 +10,45 @@
 #include <ram.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
+#include <asm/arch/periph.h>
+#include <asm/gpio.h>
+#include <dm/pinctrl.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
 int board_init(void)
 {
+#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+	struct udevice *pinctrl;
+	int ret;
+
+    /*
+     * We need to implement sdcard iomux here for the further
+     * initlization, otherwise, it'll hit sdcard command sending
+     * timeout exception.
+     */
+	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
+	if (ret) {
+		debug("%s: Cannot find pinctrl device\n", __func__);
+		goto err;
+	}
+	ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD);
+	if (ret) {
+		debug("%s: Failed to set up SD card\n", __func__);
+		goto err;
+	}
+
+	return 0;
+err:
+	printf("board_init: Error %d\n", ret);
+
+	/* No way to report error here */
+	hang();
+
+	return -1;
+#else
 	return 0;
+#endif
 }
 
 int dram_init(void)
@@ -52,6 +85,78 @@
 {
 }
 
+#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
+#include <usb.h>
+#include <usb/dwc2_udc.h>
+
+static struct dwc2_plat_otg_data rk3288_otg_data = {
+	.rx_fifo_sz	= 512,
+	.np_tx_fifo_sz	= 16,
+	.tx_fifo_sz	= 128,
+};
+
+int board_usb_init(int index, enum usb_init_type init)
+{
+	int node, phy_node;
+	const char *mode;
+	bool matched = false;
+	const void *blob = gd->fdt_blob;
+	u32 grf_phy_offset;
+
+	/* find the usb_otg node */
+	node = fdt_node_offset_by_compatible(blob, -1,
+					"rockchip,rk3288-usb");
+
+	while (node > 0) {
+		mode = fdt_getprop(blob, node, "dr_mode", NULL);
+		if (mode && strcmp(mode, "otg") == 0) {
+			matched = true;
+			break;
+		}
+
+		node = fdt_node_offset_by_compatible(blob, node,
+					"rockchip,rk3288-usb");
+	}
+	if (!matched) {
+		debug("Not found usb_otg device\n");
+		return -ENODEV;
+	}
+	rk3288_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg");
+
+	node = fdtdec_lookup_phandle(blob, node, "phys");
+	if (node <= 0) {
+		debug("Not found usb phy device\n");
+		return -ENODEV;
+	}
+
+	phy_node = fdt_parent_offset(blob, node);
+	if (phy_node <= 0) {
+		debug("Not found usb phy device\n");
+		return -ENODEV;
+	}
+
+	rk3288_otg_data.phy_of_node = phy_node;
+	grf_phy_offset = fdtdec_get_addr(blob, node, "reg");
+
+	/* find the grf node */
+	node = fdt_node_offset_by_compatible(blob, -1,
+					"rockchip,rk3288-grf");
+	if (node <= 0) {
+		debug("Not found grf device\n");
+		return -ENODEV;
+	}
+	rk3288_otg_data.regs_phy = grf_phy_offset +
+				fdtdec_get_addr(blob, node, "reg");
+
+	return dwc2_udc_probe(&rk3288_otg_data);
+}
+
+int board_usb_cleanup(int index, enum usb_init_type init)
+{
+	return 0;
+}
+#endif
+
 static int do_clock(cmd_tbl_t *cmdtp, int flag, int argc,
 		       char * const argv[])
 {
@@ -73,7 +178,7 @@
 	int ret, i;
 	struct udevice *dev;
 
-	ret = uclass_get_device(UCLASS_CLK, 0, &dev);
+	ret = rockchip_get_clk(&dev);
 	if (ret) {
 		printf("clk-uclass not found\n");
 		return 0;
diff --git a/arch/arm/mach-rockchip/rk3036/Kconfig b/arch/arm/mach-rockchip/rk3036/Kconfig
index cc03808..0804714 100644
--- a/arch/arm/mach-rockchip/rk3036/Kconfig
+++ b/arch/arm/mach-rockchip/rk3036/Kconfig
@@ -12,10 +12,7 @@
 config SYS_MALLOC_F_LEN
 	default 0x400
 
-config ROCKCHIP_COMMON
-	bool "Support rk common fuction"
-
-source "board/evb_rk3036/evb_rk3036/Kconfig"
-source "board/kylin/kylin_rk3036/Kconfig"
+source "board/rockchip/evb_rk3036/Kconfig"
+source "board/rockchip/kylin_rk3036/Kconfig"
 
 endif
diff --git a/arch/arm/mach-rockchip/rk3036/Makefile b/arch/arm/mach-rockchip/rk3036/Makefile
index 97d299d..916a7a4 100644
--- a/arch/arm/mach-rockchip/rk3036/Makefile
+++ b/arch/arm/mach-rockchip/rk3036/Makefile
@@ -5,9 +5,7 @@
 #
 
 ifndef CONFIG_SPL_BUILD
-obj-y += reset_rk3036.o
 obj-y += syscon_rk3036.o
 endif
 
 obj-y += sdram_rk3036.o
-obj-y += save_boot_param.o
diff --git a/arch/arm/mach-rockchip/rk3288-board-spl.c b/arch/arm/mach-rockchip/rk3288-board-spl.c
index 15f1266..e0d92a6 100644
--- a/arch/arm/mach-rockchip/rk3288-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3288-board-spl.c
@@ -29,6 +29,7 @@
 
 u32 spl_boot_device(void)
 {
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	const void *blob = gd->fdt_blob;
 	struct udevice *dev;
 	const char *bootdev;
@@ -63,6 +64,7 @@
 	}
 
 fallback:
+#endif
 	return BOOT_DEVICE_MMC1;
 }
 
@@ -114,7 +116,8 @@
 #ifdef CONFIG_SPL_MMC_SUPPORT
 static int configure_emmc(struct udevice *pinctrl)
 {
-#if !defined(CONFIG_TARGET_ROCK2) && !defined(CONFIG_TARGET_FIREFLY_RK3288)
+#if defined(CONFIG_TARGET_CHROMEBOOK_JERRY)
+
 	struct gpio_desc desc;
 	int ret;
 
@@ -145,11 +148,10 @@
 		return ret;
 	}
 #endif
-
 	return 0;
 }
 #endif
-
+extern void back_to_bootrom(void);
 void board_init_f(ulong dummy)
 {
 	struct udevice *pinctrl;
@@ -187,7 +189,7 @@
 	rockchip_timer_init();
 	configure_l2ctlr();
 
-	ret = uclass_get_device(UCLASS_CLK, 0, &dev);
+	ret = rockchip_get_clk(&dev);
 	if (ret) {
 		debug("CLK init failed: %d\n", ret);
 		return;
@@ -204,6 +206,9 @@
 		debug("DRAM init failed: %d\n", ret);
 		return;
 	}
+#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+	back_to_bootrom();
+#endif
 }
 
 static int setup_led(void)
@@ -246,6 +251,7 @@
 		debug("%s: Cannot find pinctrl device\n", __func__);
 		goto err;
 	}
+
 #ifdef CONFIG_SPL_MMC_SUPPORT
 	ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD);
 	if (ret) {
diff --git a/arch/arm/mach-rockchip/rk3288/Kconfig b/arch/arm/mach-rockchip/rk3288/Kconfig
index 7215624..b4113e0 100644
--- a/arch/arm/mach-rockchip/rk3288/Kconfig
+++ b/arch/arm/mach-rockchip/rk3288/Kconfig
@@ -8,6 +8,39 @@
 	  also includes on-board eMMC and 1GB of SDRAM. Expansion connectors
 	  provide access to display pins, I2C, SPI, UART and GPIOs.
 
+config TARGET_EVB_RK3288
+	bool "Evb-RK3288"
+	help
+	  EVB-RK3288 is a RK3288-based development board with 2 USB ports,
+	  HDMI, VGA, micro-SD card, audio, WiFi  and Gigabit Ethernet, It
+	  also includes on-board eMMC and 2GB of SDRAM. Expansion connectors
+	  provide access to display pins, I2C, SPI, UART and GPIOs.
+
+config TARGET_FENNEC_RK3288
+	bool "Fennec-RK3288"
+	help
+	  Fennec is a RK3288-based development board with 2 USB ports,
+	  HDMI, micro-SD card, audio, WiFi and Gigabit Ethernet. It also
+	  includes on-board eMMC and 2GB of SDRAM. Expansion connectors
+	  provide access to display pins, I2C, SPI, UART and GPIOs.
+
+config TARGET_POPMETAL_RK3288
+	bool "PopMetal-RK3288"
+	help
+	  PopMetal is a RK3288-based development board with 3 USB host ports,
+	  1 micro USB OTG port, HDMI, VGA, micro-SD card, audio, WiFi, Gigabit
+	  Ethernet and lots of sensors. It also includes on-board 8 GeMMC and
+	  2GB DDR3. Expansion connectors provide access to I2C, SPI, UART,
+	  GPIOs and display interface.
+
+config TARGET_MINIARM_RK3288
+	bool "miniarm-RK3288"
+	help
+	  Miniarm is a RK3288-based development board with 2 USB ports, HDMI,
+	  micro-SD card, audio, Gigabit Ethernet. It also includes on-board
+	  8GB eMMC and 2GB of SDRAM. Expansion connectors provide access to
+	  I2C, SPI, UART, GPIOs.
+
 config TARGET_CHROMEBOOK_JERRY
 	bool "Google/Rockchip Veyron-Jerry Chromebook"
 	help
@@ -39,10 +72,18 @@
 config SYS_MALLOC_F_LEN
 	default 0x0800
 
-source "board/google/chromebook_jerry/Kconfig"
+source "board/chipspark/popmetal_rk3288/Kconfig"
 
 source "board/firefly/firefly-rk3288/Kconfig"
 
+source "board/google/chromebook_jerry/Kconfig"
+
 source "board/radxa/rock2/Kconfig"
 
+source "board/rockchip/evb_rk3288/Kconfig"
+
+source "board/rockchip/fennec_rk3288/Kconfig"
+
+source "board/rockchip/miniarm_rk3288/Kconfig"
+
 endif
diff --git a/arch/arm/mach-rockchip/rk3288/Makefile b/arch/arm/mach-rockchip/rk3288/Makefile
index 6f62375..5ec3f0d 100644
--- a/arch/arm/mach-rockchip/rk3288/Makefile
+++ b/arch/arm/mach-rockchip/rk3288/Makefile
@@ -4,6 +4,6 @@
 # SPDX-License-Identifier:      GPL-2.0+
 #
 
-obj-y += reset_rk3288.o
+obj-y += clk_rk3288.o
 obj-y += sdram_rk3288.o
 obj-y += syscon_rk3288.o
diff --git a/arch/arm/mach-rockchip/rk3288/clk_rk3288.c b/arch/arm/mach-rockchip/rk3288/clk_rk3288.c
new file mode 100644
index 0000000..2099e34
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3288/clk_rk3288.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <syscon.h>
+#include <asm/arch/clock.h>
+
+int rockchip_get_clk(struct udevice **devp)
+{
+	return uclass_get_device_by_driver(UCLASS_CLK,
+			DM_GET_DRIVER(rockchip_rk3288_cru), devp);
+}
diff --git a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
index 55ac73e..cf9ef2e 100644
--- a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
+++ b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
@@ -10,6 +10,7 @@
 #include <common.h>
 #include <clk.h>
 #include <dm.h>
+#include <dt-structs.h>
 #include <errno.h>
 #include <ram.h>
 #include <regmap.h>
@@ -41,8 +42,21 @@
 	struct rk3288_grf *grf;
 	struct rk3288_sgrf *sgrf;
 	struct rk3288_pmu *pmu;
+	bool is_veyron;
 };
 
+struct rk3288_sdram_params {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_rockchip_rk3288_dmc of_plat;
+#endif
+	struct rk3288_sdram_channel ch[2];
+	struct rk3288_sdram_pctl_timing pctl_timing;
+	struct rk3288_sdram_phy_timing phy_timing;
+	struct rk3288_base_params base;
+	int num_channels;
+	struct regmap *map;
+};
+
 #ifdef CONFIG_SPL_BUILD
 static void copy_to_reg(u32 *dest, const u32 *src, u32 n)
 {
@@ -561,14 +575,14 @@
 			&sdram_params->ch[chan];
 
 		sys_reg |= info->row_3_4 << SYS_REG_ROW_3_4_SHIFT(chan);
-		sys_reg |= chan << SYS_REG_CHINFO_SHIFT(chan);
+		sys_reg |= 1 << SYS_REG_CHINFO_SHIFT(chan);
 		sys_reg |= (info->rank - 1) << SYS_REG_RANK_SHIFT(chan);
 		sys_reg |= (info->col - 9) << SYS_REG_COL_SHIFT(chan);
-		sys_reg |= info->bk == 3 ? 1 << SYS_REG_BK_SHIFT(chan) : 0;
+		sys_reg |= info->bk == 3 ? 0 : 1 << SYS_REG_BK_SHIFT(chan);
 		sys_reg |= (info->cs0_row - 13) << SYS_REG_CS0_ROW_SHIFT(chan);
 		sys_reg |= (info->cs1_row - 13) << SYS_REG_CS1_ROW_SHIFT(chan);
-		sys_reg |= info->bw << SYS_REG_BW_SHIFT(chan);
-		sys_reg |= info->dbw << SYS_REG_DBW_SHIFT(chan);
+		sys_reg |= (2 >> info->bw) << SYS_REG_BW_SHIFT(chan);
+		sys_reg |= (2 >> info->dbw) << SYS_REG_DBW_SHIFT(chan);
 
 		dram_cfg_rbc(&dram->chan[chan], chan, sdram_params);
 	}
@@ -703,7 +717,7 @@
 
 	return 0;
 }
-#endif
+#endif /* CONFIG_SPL_BUILD */
 
 size_t sdram_size_mb(struct rk3288_pmu *pmu)
 {
@@ -720,13 +734,13 @@
 		rank = 1 + (sys_reg >> SYS_REG_RANK_SHIFT(ch) &
 			SYS_REG_RANK_MASK);
 		col = 9 + (sys_reg >> SYS_REG_COL_SHIFT(ch) & SYS_REG_COL_MASK);
-		bk = sys_reg & (1 << SYS_REG_BK_SHIFT(ch)) ? 3 : 0;
+		bk = 3 - ((sys_reg >> SYS_REG_BK_SHIFT(ch)) & SYS_REG_BK_MASK);
 		cs0_row = 13 + (sys_reg >> SYS_REG_CS0_ROW_SHIFT(ch) &
 				SYS_REG_CS0_ROW_MASK);
 		cs1_row = 13 + (sys_reg >> SYS_REG_CS1_ROW_SHIFT(ch) &
 				SYS_REG_CS1_ROW_MASK);
-		bw = (sys_reg >> SYS_REG_BW_SHIFT(ch)) &
-			SYS_REG_BW_MASK;
+		bw = (2 >> ((sys_reg >> SYS_REG_BW_SHIFT(ch)) &
+			SYS_REG_BW_MASK));
 		row_3_4 = sys_reg >> SYS_REG_ROW_3_4_SHIFT(ch) &
 			SYS_REG_ROW_3_4_MASK;
 
@@ -770,7 +784,7 @@
 		return ret;
 	udelay(100);/* Must wait for voltage to stabilize, 2mV/us */
 
-	rkclk_configure_cpu(priv->cru, priv->grf);
+	rk3288_clk_configure_cpu(priv->cru, priv->grf);
 
 	return 0;
 }
@@ -779,18 +793,36 @@
 static int setup_sdram(struct udevice *dev)
 {
 	struct dram_info *priv = dev_get_priv(dev);
-	struct rk3288_sdram_params params;
+	struct rk3288_sdram_params *params = dev_get_platdata(dev);
+
+# ifdef CONFIG_ROCKCHIP_FAST_SPL
+	if (priv->is_veyron) {
+		int ret;
+
+		ret = veyron_init(priv);
+		if (ret)
+			return ret;
+	}
+# endif
+
+	return sdram_init(priv, params);
+}
+
+static int rk3288_dmc_ofdata_to_platdata(struct udevice *dev)
+{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct rk3288_sdram_params *params = dev_get_platdata(dev);
 	const void *blob = gd->fdt_blob;
 	int node = dev->of_offset;
 	int i, ret;
 
-	params.num_channels = fdtdec_get_int(blob, node,
-					     "rockchip,num-channels", 1);
-	for (i = 0; i < params.num_channels; i++) {
+	params->num_channels = fdtdec_get_int(blob, node,
+					      "rockchip,num-channels", 1);
+	for (i = 0; i < params->num_channels; i++) {
 		ret = fdtdec_get_byte_array(blob, node,
 					    "rockchip,sdram-channel",
-					    (u8 *)&params.ch[i],
-					    sizeof(params.ch[i]));
+					    (u8 *)&params->ch[i],
+					    sizeof(params->ch[i]));
 		if (ret) {
 			debug("%s: Cannot read rockchip,sdram-channel\n",
 			      __func__);
@@ -798,46 +830,82 @@
 		}
 	}
 	ret = fdtdec_get_int_array(blob, node, "rockchip,pctl-timing",
-				   (u32 *)&params.pctl_timing,
-				   sizeof(params.pctl_timing) / sizeof(u32));
+				   (u32 *)&params->pctl_timing,
+				   sizeof(params->pctl_timing) / sizeof(u32));
 	if (ret) {
 		debug("%s: Cannot read rockchip,pctl-timing\n", __func__);
 		return -EINVAL;
 	}
 	ret = fdtdec_get_int_array(blob, node, "rockchip,phy-timing",
-				   (u32 *)&params.phy_timing,
-				   sizeof(params.phy_timing) / sizeof(u32));
+				   (u32 *)&params->phy_timing,
+				   sizeof(params->phy_timing) / sizeof(u32));
 	if (ret) {
 		debug("%s: Cannot read rockchip,phy-timing\n", __func__);
 		return -EINVAL;
 	}
 	ret = fdtdec_get_int_array(blob, node, "rockchip,sdram-params",
-				   (u32 *)&params.base,
-				   sizeof(params.base) / sizeof(u32));
+				   (u32 *)&params->base,
+				   sizeof(params->base) / sizeof(u32));
 	if (ret) {
 		debug("%s: Cannot read rockchip,sdram-params\n", __func__);
 		return -EINVAL;
 	}
+#ifdef CONFIG_ROCKCHIP_FAST_SPL
+	struct dram_info *priv = dev_get_priv(dev);
 
-# ifdef CONFIG_ROCKCHIP_FAST_SPL
-	if (!fdt_node_check_compatible(blob, 0, "google,veyron")) {
-		ret = veyron_init(priv);
-		if (ret)
-			return ret;
+	priv->is_veyron = !fdt_node_check_compatible(blob, 0, "google,veyron");
+#endif
+	ret = regmap_init_mem(dev, &params->map);
+	if (ret)
+		return ret;
+#endif
+
+	return 0;
+}
+#endif /* CONFIG_SPL_BUILD */
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+static int conv_of_platdata(struct udevice *dev)
+{
+	struct rk3288_sdram_params *plat = dev_get_platdata(dev);
+	struct dtd_rockchip_rk3288_dmc *of_plat = &plat->of_plat;
+	int i, ret;
+
+	for (i = 0; i < 2; i++) {
+		memcpy(&plat->ch[i], of_plat->rockchip_sdram_channel,
+		       sizeof(plat->ch[i]));
 	}
-# endif
+	memcpy(&plat->pctl_timing, of_plat->rockchip_pctl_timing,
+	       sizeof(plat->pctl_timing));
+	memcpy(&plat->phy_timing, of_plat->rockchip_phy_timing,
+	       sizeof(plat->phy_timing));
+	memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
+	plat->num_channels = of_plat->rockchip_num_channels;
+	ret = regmap_init_mem_platdata(dev, of_plat->reg,
+				       ARRAY_SIZE(of_plat->reg) / 2,
+				       &plat->map);
+	if (ret)
+		return ret;
 
-	return sdram_init(priv, &params);
+	return 0;
 }
 #endif
 
 static int rk3288_dmc_probe(struct udevice *dev)
 {
+#ifdef CONFIG_SPL_BUILD
+	struct rk3288_sdram_params *plat = dev_get_platdata(dev);
+#endif
 	struct dram_info *priv = dev_get_priv(dev);
 	struct regmap *map;
 	int ret;
 	struct udevice *dev_clk;
 
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	ret = conv_of_platdata(dev);
+	if (ret)
+		return ret;
+#endif
 	map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_NOC);
 	if (IS_ERR(map))
 		return PTR_ERR(map);
@@ -849,15 +917,13 @@
 	priv->sgrf = syscon_get_first_range(ROCKCHIP_SYSCON_SGRF);
 	priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
 
-	ret = regmap_init_mem(dev, &map);
-	if (ret)
-		return ret;
-	priv->chan[0].pctl = regmap_get_range(map, 0);
-	priv->chan[0].publ = regmap_get_range(map, 1);
-	priv->chan[1].pctl = regmap_get_range(map, 2);
-	priv->chan[1].publ = regmap_get_range(map, 3);
-
-	ret = uclass_get_device(UCLASS_CLK, 0, &dev_clk);
+#ifdef CONFIG_SPL_BUILD
+	priv->chan[0].pctl = regmap_get_range(plat->map, 0);
+	priv->chan[0].publ = regmap_get_range(plat->map, 1);
+	priv->chan[1].pctl = regmap_get_range(plat->map, 2);
+	priv->chan[1].publ = regmap_get_range(plat->map, 3);
+#endif
+	ret = rockchip_get_clk(&dev_clk);
 	if (ret)
 		return ret;
 	priv->ddr_clk.id = CLK_DDR;
@@ -898,10 +964,16 @@
 };
 
 U_BOOT_DRIVER(dmc_rk3288) = {
-	.name = "rk3288_dmc",
+	.name = "rockchip_rk3288_dmc",
 	.id = UCLASS_RAM,
 	.of_match = rk3288_dmc_ids,
 	.ops = &rk3288_dmc_ops,
+#ifdef CONFIG_SPL_BUILD
+	.ofdata_to_platdata = rk3288_dmc_ofdata_to_platdata,
+#endif
 	.probe = rk3288_dmc_probe,
 	.priv_auto_alloc_size = sizeof(struct dram_info),
+#ifdef CONFIG_SPL_BUILD
+	.platdata_auto_alloc_size = sizeof(struct rk3288_sdram_params),
+#endif
 };
diff --git a/arch/arm/mach-rockchip/rk3288/syscon_rk3288.c b/arch/arm/mach-rockchip/rk3288/syscon_rk3288.c
index c9f7c4e..be4b2b0 100644
--- a/arch/arm/mach-rockchip/rk3288/syscon_rk3288.c
+++ b/arch/arm/mach-rockchip/rk3288/syscon_rk3288.c
@@ -23,3 +23,41 @@
 	.id = UCLASS_SYSCON,
 	.of_match = rk3288_syscon_ids,
 };
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+static int rk3288_syscon_bind_of_platdata(struct udevice *dev)
+{
+	dev->driver_data = dev->driver->of_match->data;
+	debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(rockchip_rk3288_noc) = {
+	.name = "rockchip_rk3288_noc",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3288_syscon_ids,
+	.bind = rk3288_syscon_bind_of_platdata,
+};
+
+U_BOOT_DRIVER(rockchip_rk3288_grf) = {
+	.name = "rockchip_rk3288_grf",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3288_syscon_ids + 1,
+	.bind = rk3288_syscon_bind_of_platdata,
+};
+
+U_BOOT_DRIVER(rockchip_rk3288_sgrf) = {
+	.name = "rockchip_rk3288_sgrf",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3288_syscon_ids + 2,
+	.bind = rk3288_syscon_bind_of_platdata,
+};
+
+U_BOOT_DRIVER(rockchip_rk3288_pmu) = {
+	.name = "rockchip_rk3288_pmu",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3288_syscon_ids + 3,
+	.bind = rk3288_syscon_bind_of_platdata,
+};
+#endif
diff --git a/arch/arm/mach-rockchip/rk3399/Kconfig b/arch/arm/mach-rockchip/rk3399/Kconfig
new file mode 100644
index 0000000..83bd04a
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3399/Kconfig
@@ -0,0 +1,23 @@
+if ROCKCHIP_RK3399
+
+choice
+	prompt "RK3399 board select"
+
+config TARGET_EVB_RK3399
+	bool "RK3399 evaluation board"
+	help
+	  RK3399evb is a evaluation board for Rockchp rk3399,
+	  with full function and phisical connectors support like type-C ports,
+	  usb2.0 host ports, LVDS, JTAG, MAC, SDcard, HDMI, USB-2-serial...
+
+endchoice
+
+config SYS_SOC
+	default "rockchip"
+
+config SYS_MALLOC_F_LEN
+	default 0x0800
+
+source "board/rockchip/evb_rk3399/Kconfig"
+
+endif
diff --git a/arch/arm/mach-rockchip/rk3399/Makefile b/arch/arm/mach-rockchip/rk3399/Makefile
new file mode 100644
index 0000000..607f9c9
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3399/Makefile
@@ -0,0 +1,8 @@
+#
+# (C) Copyright 2016 Rockchip Electronics Co., Ltd
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y += rk3399.o
+obj-y += syscon_rk3399.o
diff --git a/arch/arm/mach-rockchip/rk3399/rk3399.c b/arch/arm/mach-rockchip/rk3399/rk3399.c
new file mode 100644
index 0000000..b9d7629
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3399/rk3399.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/armv8/mmu.h>
+
+static struct mm_region rk3399_mem_map[] = {
+	{
+		.virt = 0x0UL,
+		.phys = 0x0UL,
+		.size = 0x80000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	}, {
+		.virt = 0xf0000000UL,
+		.phys = 0xf0000000UL,
+		.size = 0x10000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* List terminator */
+		0,
+	}
+};
+
+struct mm_region *mem_map = rk3399_mem_map;
diff --git a/arch/arm/mach-rockchip/rk3399/syscon_rk3399.c b/arch/arm/mach-rockchip/rk3399/syscon_rk3399.c
new file mode 100644
index 0000000..2d81c55
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3399/syscon_rk3399.c
@@ -0,0 +1,20 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <syscon.h>
+#include <asm/arch/clock.h>
+
+static const struct udevice_id rk3399_syscon_ids[] = {
+	{ .compatible = "rockchip,rk3399-grf", .data = ROCKCHIP_SYSCON_GRF },
+};
+
+U_BOOT_DRIVER(syscon_rk3399) = {
+	.name = "rk3399_syscon",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3399_syscon_ids,
+};
diff --git a/arch/arm/mach-rockchip/rk3036/save_boot_param.S b/arch/arm/mach-rockchip/save_boot_param.S
similarity index 89%
rename from arch/arm/mach-rockchip/rk3036/save_boot_param.S
rename to arch/arm/mach-rockchip/save_boot_param.S
index 778ec83..85b407b 100644
--- a/arch/arm/mach-rockchip/rk3036/save_boot_param.S
+++ b/arch/arm/mach-rockchip/save_boot_param.S
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2015 Google, Inc
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
  *
  * SPDX-License-Identifier:     GPL-2.0+
  */
diff --git a/arch/arm/mach-snapdragon/Makefile b/arch/arm/mach-snapdragon/Makefile
index 4735844..d82a04d 100644
--- a/arch/arm/mach-snapdragon/Makefile
+++ b/arch/arm/mach-snapdragon/Makefile
@@ -6,4 +6,3 @@
 
 obj-y += clock-apq8016.o
 obj-y += sysmap-apq8016.o
-obj-y += reset.o
diff --git a/arch/arm/mach-snapdragon/sysmap-apq8016.c b/arch/arm/mach-snapdragon/sysmap-apq8016.c
index ef0db2a..580b9c7 100644
--- a/arch/arm/mach-snapdragon/sysmap-apq8016.c
+++ b/arch/arm/mach-snapdragon/sysmap-apq8016.c
@@ -11,13 +11,15 @@
 
 static struct mm_region apq8016_mem_map[] = {
 	{
-		.base = 0x0UL, /* Peripheral block */
+		.virt = 0x0UL, /* Peripheral block */
+		.phys = 0x0UL, /* Peripheral block */
 		.size = 0x8000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE |
 			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
 	}, {
-		.base = 0x80000000UL, /* DDR */
+		.virt = 0x80000000UL, /* DDR */
+		.phys = 0x80000000UL, /* DDR */
 		.size = 0x80000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_INNER_SHARE
diff --git a/arch/arm/mach-stm32/stm32f7/Makefile b/arch/arm/mach-stm32/stm32f7/Makefile
index 40f1ad3..643d4d9 100644
--- a/arch/arm/mach-stm32/stm32f7/Makefile
+++ b/arch/arm/mach-stm32/stm32f7/Makefile
@@ -5,4 +5,4 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-y += timer.o clock.o
+obj-y += timer.o clock.o soc.o
diff --git a/arch/arm/mach-stm32/stm32f7/clock.c b/arch/arm/mach-stm32/stm32f7/clock.c
index 17a715b..78d22d4 100644
--- a/arch/arm/mach-stm32/stm32f7/clock.c
+++ b/arch/arm/mach-stm32/stm32f7/clock.c
@@ -11,6 +11,234 @@
 #include <asm/arch/stm32.h>
 #include <asm/arch/stm32_periph.h>
 
+#define RCC_CR_HSION		(1 << 0)
+#define RCC_CR_HSEON		(1 << 16)
+#define RCC_CR_HSERDY		(1 << 17)
+#define RCC_CR_HSEBYP		(1 << 18)
+#define RCC_CR_CSSON		(1 << 19)
+#define RCC_CR_PLLON		(1 << 24)
+#define RCC_CR_PLLRDY		(1 << 25)
+
+#define RCC_PLLCFGR_PLLM_MASK	0x3F
+#define RCC_PLLCFGR_PLLN_MASK	0x7FC0
+#define RCC_PLLCFGR_PLLP_MASK	0x30000
+#define RCC_PLLCFGR_PLLQ_MASK	0xF000000
+#define RCC_PLLCFGR_PLLSRC	(1 << 22)
+#define RCC_PLLCFGR_PLLM_SHIFT	0
+#define RCC_PLLCFGR_PLLN_SHIFT	6
+#define RCC_PLLCFGR_PLLP_SHIFT	16
+#define RCC_PLLCFGR_PLLQ_SHIFT	24
+
+#define RCC_CFGR_AHB_PSC_MASK	0xF0
+#define RCC_CFGR_APB1_PSC_MASK	0x1C00
+#define RCC_CFGR_APB2_PSC_MASK	0xE000
+#define RCC_CFGR_SW0		(1 << 0)
+#define RCC_CFGR_SW1		(1 << 1)
+#define RCC_CFGR_SW_MASK	0x3
+#define RCC_CFGR_SW_HSI		0
+#define RCC_CFGR_SW_HSE		RCC_CFGR_SW0
+#define RCC_CFGR_SW_PLL		RCC_CFGR_SW1
+#define RCC_CFGR_SWS0		(1 << 2)
+#define RCC_CFGR_SWS1		(1 << 3)
+#define RCC_CFGR_SWS_MASK	0xC
+#define RCC_CFGR_SWS_HSI	0
+#define RCC_CFGR_SWS_HSE	RCC_CFGR_SWS0
+#define RCC_CFGR_SWS_PLL	RCC_CFGR_SWS1
+#define RCC_CFGR_HPRE_SHIFT	4
+#define RCC_CFGR_PPRE1_SHIFT	10
+#define RCC_CFGR_PPRE2_SHIFT	13
+
+#define RCC_APB1ENR_PWREN	(1 << 28)
+
+/*
+ * RCC USART specific definitions
+ */
+#define RCC_ENR_USART1EN		(1 << 4)
+#define RCC_ENR_USART2EN		(1 << 17)
+#define RCC_ENR_USART3EN		(1 << 18)
+#define RCC_ENR_USART6EN		(1 <<  5)
+
+/*
+ * Offsets of some PWR registers
+ */
+#define PWR_CR1_ODEN		(1 << 16)
+#define PWR_CR1_ODSWEN		(1 << 17)
+#define PWR_CSR1_ODRDY		(1 << 16)
+#define PWR_CSR1_ODSWRDY	(1 << 17)
+
+
+/*
+ * RCC GPIO specific definitions
+ */
+#define RCC_ENR_GPIO_A_EN	(1 << 0)
+#define RCC_ENR_GPIO_B_EN	(1 << 1)
+#define RCC_ENR_GPIO_C_EN	(1 << 2)
+#define RCC_ENR_GPIO_D_EN	(1 << 3)
+#define RCC_ENR_GPIO_E_EN	(1 << 4)
+#define RCC_ENR_GPIO_F_EN	(1 << 5)
+#define RCC_ENR_GPIO_G_EN	(1 << 6)
+#define RCC_ENR_GPIO_H_EN	(1 << 7)
+#define RCC_ENR_GPIO_I_EN	(1 << 8)
+#define RCC_ENR_GPIO_J_EN	(1 << 9)
+#define RCC_ENR_GPIO_K_EN	(1 << 10)
+
+struct pll_psc {
+	u8	pll_m;
+	u16	pll_n;
+	u8	pll_p;
+	u8	pll_q;
+	u8	ahb_psc;
+	u8	apb1_psc;
+	u8	apb2_psc;
+};
+
+#define AHB_PSC_1		0
+#define AHB_PSC_2		0x8
+#define AHB_PSC_4		0x9
+#define AHB_PSC_8		0xA
+#define AHB_PSC_16		0xB
+#define AHB_PSC_64		0xC
+#define AHB_PSC_128		0xD
+#define AHB_PSC_256		0xE
+#define AHB_PSC_512		0xF
+
+#define APB_PSC_1		0
+#define APB_PSC_2		0x4
+#define APB_PSC_4		0x5
+#define APB_PSC_8		0x6
+#define APB_PSC_16		0x7
+
+#if !defined(CONFIG_STM32_HSE_HZ)
+#error "CONFIG_STM32_HSE_HZ not defined!"
+#else
+#if (CONFIG_STM32_HSE_HZ == 25000000)
+#if (CONFIG_SYS_CLK_FREQ == 200000000)
+/* 200 MHz */
+struct pll_psc sys_pll_psc = {
+	.pll_m = 25,
+	.pll_n = 400,
+	.pll_p = 2,
+	.pll_q = 8,
+	.ahb_psc = AHB_PSC_1,
+	.apb1_psc = APB_PSC_4,
+	.apb2_psc = APB_PSC_2
+};
+#endif
+#else
+#error "No PLL/Prescaler configuration for given CONFIG_STM32_HSE_HZ exists"
+#endif
+#endif
+
+int configure_clocks(void)
+{
+	/* Reset RCC configuration */
+	setbits_le32(&STM32_RCC->cr, RCC_CR_HSION);
+	writel(0, &STM32_RCC->cfgr); /* Reset CFGR */
+	clrbits_le32(&STM32_RCC->cr, (RCC_CR_HSEON | RCC_CR_CSSON
+		| RCC_CR_PLLON));
+	writel(0x24003010, &STM32_RCC->pllcfgr); /* Reset value from RM */
+	clrbits_le32(&STM32_RCC->cr, RCC_CR_HSEBYP);
+	writel(0, &STM32_RCC->cir); /* Disable all interrupts */
+
+	/* Configure for HSE+PLL operation */
+	setbits_le32(&STM32_RCC->cr, RCC_CR_HSEON);
+	while (!(readl(&STM32_RCC->cr) & RCC_CR_HSERDY))
+		;
+
+	setbits_le32(&STM32_RCC->cfgr, ((
+		sys_pll_psc.ahb_psc << RCC_CFGR_HPRE_SHIFT)
+		| (sys_pll_psc.apb1_psc << RCC_CFGR_PPRE1_SHIFT)
+		| (sys_pll_psc.apb2_psc << RCC_CFGR_PPRE2_SHIFT)));
+
+	/* Configure the main PLL */
+	uint32_t pllcfgr = 0;
+	pllcfgr = RCC_PLLCFGR_PLLSRC; /* pll source HSE */
+	pllcfgr |= sys_pll_psc.pll_m << RCC_PLLCFGR_PLLM_SHIFT;
+	pllcfgr |= sys_pll_psc.pll_n << RCC_PLLCFGR_PLLN_SHIFT;
+	pllcfgr |= ((sys_pll_psc.pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT;
+	pllcfgr |= sys_pll_psc.pll_q << RCC_PLLCFGR_PLLQ_SHIFT;
+	writel(pllcfgr, &STM32_RCC->pllcfgr);
+
+	/* Enable the main PLL */
+	setbits_le32(&STM32_RCC->cr, RCC_CR_PLLON);
+	while (!(readl(&STM32_RCC->cr) & RCC_CR_PLLRDY))
+		;
+
+	/* Enable high performance mode, System frequency up to 200 MHz */
+	setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_PWREN);
+	setbits_le32(&STM32_PWR->cr1, PWR_CR1_ODEN);
+	/* Infinite wait! */
+	while (!(readl(&STM32_PWR->csr1) & PWR_CSR1_ODRDY))
+		;
+	/* Enable the Over-drive switch */
+	setbits_le32(&STM32_PWR->cr1, PWR_CR1_ODSWEN);
+	/* Infinite wait! */
+	while (!(readl(&STM32_PWR->csr1) & PWR_CSR1_ODSWRDY))
+		;
+
+	stm32_flash_latency_cfg(5);
+	clrbits_le32(&STM32_RCC->cfgr, (RCC_CFGR_SW0 | RCC_CFGR_SW1));
+	setbits_le32(&STM32_RCC->cfgr, RCC_CFGR_SW_PLL);
+
+	while ((readl(&STM32_RCC->cfgr) & RCC_CFGR_SWS_MASK) !=
+			RCC_CFGR_SWS_PLL)
+		;
+
+	return 0;
+}
+
+unsigned long clock_get(enum clock clck)
+{
+	u32 sysclk = 0;
+	u32 shift = 0;
+	/* Prescaler table lookups for clock computation */
+	u8 ahb_psc_table[16] = {
+		0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9
+	};
+	u8 apb_psc_table[8] = {
+		0, 0, 0, 0, 1, 2, 3, 4
+	};
+
+	if ((readl(&STM32_RCC->cfgr) & RCC_CFGR_SWS_MASK) ==
+			RCC_CFGR_SWS_PLL) {
+		u16 pllm, plln, pllp;
+		pllm = (readl(&STM32_RCC->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
+		plln = ((readl(&STM32_RCC->pllcfgr) & RCC_PLLCFGR_PLLN_MASK)
+			>> RCC_PLLCFGR_PLLN_SHIFT);
+		pllp = ((((readl(&STM32_RCC->pllcfgr) & RCC_PLLCFGR_PLLP_MASK)
+			>> RCC_PLLCFGR_PLLP_SHIFT) + 1) << 1);
+		sysclk = ((CONFIG_STM32_HSE_HZ / pllm) * plln) / pllp;
+	}
+
+	switch (clck) {
+	case CLOCK_CORE:
+		return sysclk;
+		break;
+	case CLOCK_AHB:
+		shift = ahb_psc_table[(
+			(readl(&STM32_RCC->cfgr) & RCC_CFGR_AHB_PSC_MASK)
+			>> RCC_CFGR_HPRE_SHIFT)];
+		return sysclk >>= shift;
+		break;
+	case CLOCK_APB1:
+		shift = apb_psc_table[(
+			(readl(&STM32_RCC->cfgr) & RCC_CFGR_APB1_PSC_MASK)
+			>> RCC_CFGR_PPRE1_SHIFT)];
+		return sysclk >>= shift;
+		break;
+	case CLOCK_APB2:
+		shift = apb_psc_table[(
+			(readl(&STM32_RCC->cfgr) & RCC_CFGR_APB2_PSC_MASK)
+			>> RCC_CFGR_PPRE2_SHIFT)];
+		return sysclk >>= shift;
+		break;
+	default:
+		return 0;
+		break;
+	}
+}
+
+
 void clock_setup(int peripheral)
 {
 	switch (peripheral) {
diff --git a/arch/arm/mach-stm32/stm32f7/soc.c b/arch/arm/mach-stm32/stm32f7/soc.c
new file mode 100644
index 0000000..8baee99
--- /dev/null
+++ b/arch/arm/mach-stm32/stm32f7/soc.c
@@ -0,0 +1,76 @@
+/*
+ * (C) Copyright 2015
+ * Kamil Lulko, <kamil.lulko@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/armv7m.h>
+#include <asm/arch/stm32.h>
+
+u32 get_cpu_rev(void)
+{
+	return 0;
+}
+
+int arch_cpu_init(void)
+{
+	configure_clocks();
+
+	/*
+		* Configure the memory protection unit (MPU)
+		* 0x00000000 - 0xffffffff: Strong-order, Shareable
+		* 0xC0000000 - 0xC0800000: Normal, Outer and inner Non-cacheable
+	 */
+
+	 /* Disable MPU */
+	 writel(0, &V7M_MPU->ctrl);
+
+	 writel(
+		 0x00000000 /* address */
+		 | 1 << 4	/* VALID */
+		 | 0 << 0	/* REGION */
+		 , &V7M_MPU->rbar
+	 );
+
+	 /* Strong-order, Shareable */
+	 /* TEX=000, S=1, C=0, B=0*/
+	 writel(
+		 (V7M_MPU_RASR_XN_ENABLE
+			 | V7M_MPU_RASR_AP_RW_RW
+			 | 0x01 << V7M_MPU_RASR_S_SHIFT
+			 | 0x00 << V7M_MPU_RASR_TEX_SHIFT
+			 | V7M_MPU_RASR_SIZE_4GB
+			 | V7M_MPU_RASR_EN)
+		 , &V7M_MPU->rasr
+	 );
+
+	 writel(
+		 0xC0000000 /* address */
+		 | 1 << 4	/* VALID */
+		 | 1 << 0	/* REGION */
+		 , &V7M_MPU->rbar
+	 );
+
+	 /* Normal, Outer and inner Non-cacheable */
+	 /* TEX=001, S=0, C=0, B=0*/
+	 writel(
+		 (V7M_MPU_RASR_XN_ENABLE
+			 | V7M_MPU_RASR_AP_RW_RW
+			 | 0x01 << V7M_MPU_RASR_TEX_SHIFT
+			 | V7M_MPU_RASR_SIZE_8MB
+			 | V7M_MPU_RASR_EN)
+			 , &V7M_MPU->rasr
+	 );
+
+	 /* Enable MPU */
+	 writel(V7M_MPU_CTRL_ENABLE | V7M_MPU_CTRL_HFNMIENA, &V7M_MPU->ctrl);
+
+	return 0;
+}
+
+void s_init(void)
+{
+}
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index 66e028e..6d9518d 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -46,13 +46,15 @@
 static struct mm_region sunxi_mem_map[] = {
 	{
 		/* SRAM, MMIO regions */
-		.base = 0x0UL,
+		.virt = 0x0UL,
+		.phys = 0x0UL,
 		.size = 0x40000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE
 	}, {
 		/* RAM */
-		.base = 0x40000000UL,
+		.virt = 0x40000000UL,
+		.phys = 0x40000000UL,
 		.size = 0x80000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_INNER_SHARE
@@ -203,7 +205,8 @@
  */
 u32 spl_boot_device(void)
 {
-	__maybe_unused struct mmc *mmc0, *mmc1;
+	int boot_source;
+
 	/*
 	 * When booting from the SD card or NAND memory, the "eGON.BT0"
 	 * signature is expected to be found in memory at the address 0x0004
@@ -223,27 +226,19 @@
 	if (!is_boot0_magic(SPL_ADDR + 4)) /* eGON.BT0 */
 		return BOOT_DEVICE_BOARD;
 
-	/* The BROM will try to boot from mmc0 first, so try that first. */
-#ifdef CONFIG_MMC
-	mmc_initialize(gd->bd);
-	mmc0 = find_mmc_device(0);
-	if (sunxi_mmc_has_egon_boot_signature(mmc0))
+	boot_source = readb(SPL_ADDR + 0x28);
+	switch (boot_source) {
+	case SUNXI_BOOTED_FROM_MMC0:
 		return BOOT_DEVICE_MMC1;
-#endif
-
-	/* Fallback to booting NAND if enabled. */
-	if (IS_ENABLED(CONFIG_SPL_NAND_SUPPORT))
+	case SUNXI_BOOTED_FROM_NAND:
 		return BOOT_DEVICE_NAND;
-
-#ifdef CONFIG_MMC
-	if (CONFIG_MMC_SUNXI_SLOT_EXTRA == 2) {
-		mmc1 = find_mmc_device(1);
-		if (sunxi_mmc_has_egon_boot_signature(mmc1))
-			return BOOT_DEVICE_MMC2;
+	case SUNXI_BOOTED_FROM_MMC2:
+		return BOOT_DEVICE_MMC2;
+	case SUNXI_BOOTED_FROM_SPI:
+		return BOOT_DEVICE_SPI;
 	}
-#endif
 
-	panic("Could not determine boot source\n");
+	panic("Unknown boot source %d\n", boot_source);
 	return -1;		/* Never reached */
 }
 
diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c
index 20b430f..95143d1 100644
--- a/arch/arm/mach-sunxi/dram_helpers.c
+++ b/arch/arm/mach-sunxi/dram_helpers.c
@@ -32,7 +32,7 @@
 	/* Try to write different values to RAM at two addresses */
 	writel(0, CONFIG_SYS_SDRAM_BASE);
 	writel(0xaa55aa55, (ulong)CONFIG_SYS_SDRAM_BASE + offset);
-	DSB;
+	dsb();
 	/* Check if the same value is actually observed when reading back */
 	return readl(CONFIG_SYS_SDRAM_BASE) ==
 	       readl((ulong)CONFIG_SYS_SDRAM_BASE + offset);
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index f4affa5..1eaf406 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -1,5 +1,13 @@
 if TEGRA
 
+config TEGRA_IVC
+	bool "Tegra IVC protocol"
+	help
+	  IVC (Inter-VM Communication) protocol is a Tegra-specific IPC
+	  (Inter Processor Communication) framework. Within the context of
+	  U-Boot, it is typically used for communication between the main CPU
+	  and various auxiliary processors.
+
 config TEGRA_COMMON
 	bool "Tegra common options"
 	select DM
@@ -56,10 +64,17 @@
 
 config TEGRA186
 	bool "Tegra186 family"
+	select CLK
 	select DM_MAILBOX
+	select DM_RESET
+	select MISC
+	select TEGRA186_BPMP
+	select TEGRA186_CLOCK
 	select TEGRA186_GPIO
+	select TEGRA186_RESET
 	select TEGRA_ARMV8_COMMON
 	select TEGRA_HSP
+	select TEGRA_IVC
 
 endchoice
 
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 12ee1cd..b978fec 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -15,23 +15,25 @@
 obj-$(CONFIG_CMD_ENTERRCM) += cmd_enterrcm.o
 endif
 
-obj-$(CONFIG_ARM64) += arm64-mmu.o
 obj-y += ap.o
 obj-y += board.o board2.o
 obj-y += cache.o
 obj-y += clock.o
-obj-y += lowlevel_init.o
 obj-y += pinmux-common.o
 obj-y += powergate.o
 obj-y += xusb-padctl-dummy.o
-obj-$(CONFIG_DISPLAY_CPUINFO) += sys_info.o
-obj-$(CONFIG_TEGRA_GPU) += gpu.o
-obj-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o
+endif
 
+obj-$(CONFIG_ARM64) += arm64-mmu.o
+obj-y += dt-setup.o
+obj-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o
+obj-$(CONFIG_TEGRA_GPU) += gpu.o
+obj-$(CONFIG_TEGRA_IVC) += ivc.o
+obj-y += lowlevel_init.o
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_ARMV7_PSCI) += psci.o
 endif
-endif
+obj-$(CONFIG_DISPLAY_CPUINFO) += sys_info.o
 
 obj-$(CONFIG_TEGRA20) += tegra20/
 obj-$(CONFIG_TEGRA30) += tegra30/
diff --git a/arch/arm/mach-tegra/arm64-mmu.c b/arch/arm/mach-tegra/arm64-mmu.c
index 501c4f0..7b1d258 100644
--- a/arch/arm/mach-tegra/arm64-mmu.c
+++ b/arch/arm/mach-tegra/arm64-mmu.c
@@ -14,13 +14,15 @@
 
 static struct mm_region tegra_mem_map[] = {
 	{
-		.base = 0x0UL,
+		.virt = 0x0UL,
+		.phys = 0x0UL,
 		.size = 0x80000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE |
 			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
 	}, {
-		.base = 0x80000000UL,
+		.virt = 0x80000000UL,
+		.phys = 0x80000000UL,
 		.size = 0xff80000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_INNER_SHARE
diff --git a/arch/arm/mach-tegra/board186.c b/arch/arm/mach-tegra/board186.c
index f4b6152..1b9799f 100644
--- a/arch/arm/mach-tegra/board186.c
+++ b/arch/arm/mach-tegra/board186.c
@@ -11,20 +11,19 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-int dram_init(void)
+int board_early_init_f(void)
 {
-	gd->ram_size = (1.5 * 1024 * 1024 * 1024);
 	return 0;
 }
 
-int board_early_init_f(void)
+__weak int tegra_board_init(void)
 {
 	return 0;
 }
 
 int board_init(void)
 {
-	return 0;
+	return tegra_board_init();
 }
 
 int board_late_init(void)
@@ -32,12 +31,6 @@
 	return 0;
 }
 
-void dram_init_banksize(void)
-{
-	gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
-	gd->bd->bi_dram[0].size = gd->ram_size;
-}
-
 void pad_init_mmc(struct mmc_host *host)
 {
 }
@@ -48,8 +41,3 @@
 
 	return 0;
 }
-
-int ft_system_setup(void *blob, bd_t *bd)
-{
-	return 0;
-}
diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c
index 141d6e1..9158ace 100644
--- a/arch/arm/mach-tegra/board2.c
+++ b/arch/arm/mach-tegra/board2.c
@@ -397,29 +397,3 @@
 {
 	return CONFIG_SYS_SDRAM_BASE + usable_ram_size_below_4g();
 }
-
-/*
- * This function is called right before the kernel is booted. "blob" is the
- * device tree that will be passed to the kernel.
- */
-int ft_system_setup(void *blob, bd_t *bd)
-{
-	const char *gpu_compats[] = {
-#if defined(CONFIG_TEGRA124)
-		"nvidia,gk20a",
-#endif
-#if defined(CONFIG_TEGRA210)
-		"nvidia,gm20b",
-#endif
-	};
-	int i, ret;
-
-	/* Enable GPU node if GPU setup has been performed */
-	for (i = 0; i < ARRAY_SIZE(gpu_compats); i++) {
-		ret = tegra_gpu_enable_node(blob, gpu_compats[i]);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index c50d56d..36eabc8 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -510,7 +510,7 @@
  * @param p post divider(DIVP)
  * @param cpcon base PLL charge pump(CPCON)
  * @return 0 if ok, -1 on error (the requested PLL is incorrect and cannot
- *		be overriden), 1 if PLL is already correct
+ *		be overridden), 1 if PLL is already correct
  */
 int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon)
 {
diff --git a/arch/arm/mach-tegra/cpu.h b/arch/arm/mach-tegra/cpu.h
index 3f38969..1154f8b 100644
--- a/arch/arm/mach-tegra/cpu.h
+++ b/arch/arm/mach-tegra/cpu.h
@@ -16,7 +16,7 @@
 #elif defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA114) || \
 	defined(CONFIG_TEGRA124) || defined(CONFIG_TEGRA210)
 #define NVBL_PLLP_KHZ	408000
-#define CSITE_KHZ	204000
+#define CSITE_KHZ	136000
 #else
 #error "Unknown Tegra chip!"
 #endif
diff --git a/arch/arm/mach-tegra/dt-setup.c b/arch/arm/mach-tegra/dt-setup.c
new file mode 100644
index 0000000..f44d9cb
--- /dev/null
+++ b/arch/arm/mach-tegra/dt-setup.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010-2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch-tegra/gpu.h>
+
+/*
+ * This function is called right before the kernel is booted. "blob" is the
+ * device tree that will be passed to the kernel.
+ */
+int ft_system_setup(void *blob, bd_t *bd)
+{
+	const char *gpu_compats[] = {
+#if defined(CONFIG_TEGRA124)
+		"nvidia,gk20a",
+#endif
+#if defined(CONFIG_TEGRA210)
+		"nvidia,gm20b",
+#endif
+	};
+	int i, ret;
+
+	/* Enable GPU node if GPU setup has been performed */
+	for (i = 0; i < ARRAY_SIZE(gpu_compats); i++) {
+		ret = tegra_gpu_enable_node(blob, gpu_compats[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/mach-tegra/ivc.c b/arch/arm/mach-tegra/ivc.c
new file mode 100644
index 0000000..cf6626f
--- /dev/null
+++ b/arch/arm/mach-tegra/ivc.c
@@ -0,0 +1,553 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch-tegra/ivc.h>
+
+#define TEGRA_IVC_ALIGN 64
+
+/*
+ * IVC channel reset protocol.
+ *
+ * Each end uses its tx_channel.state to indicate its synchronization state.
+ */
+enum ivc_state {
+	/*
+	 * This value is zero for backwards compatibility with services that
+	 * assume channels to be initially zeroed. Such channels are in an
+	 * initially valid state, but cannot be asynchronously reset, and must
+	 * maintain a valid state at all times.
+	 *
+	 * The transmitting end can enter the established state from the sync or
+	 * ack state when it observes the receiving endpoint in the ack or
+	 * established state, indicating that has cleared the counters in our
+	 * rx_channel.
+	 */
+	ivc_state_established = 0,
+
+	/*
+	 * If an endpoint is observed in the sync state, the remote endpoint is
+	 * allowed to clear the counters it owns asynchronously with respect to
+	 * the current endpoint. Therefore, the current endpoint is no longer
+	 * allowed to communicate.
+	 */
+	ivc_state_sync,
+
+	/*
+	 * When the transmitting end observes the receiving end in the sync
+	 * state, it can clear the w_count and r_count and transition to the ack
+	 * state. If the remote endpoint observes us in the ack state, it can
+	 * return to the established state once it has cleared its counters.
+	 */
+	ivc_state_ack
+};
+
+/*
+ * This structure is divided into two-cache aligned parts, the first is only
+ * written through the tx_channel pointer, while the second is only written
+ * through the rx_channel pointer. This delineates ownership of the cache lines,
+ * which is critical to performance and necessary in non-cache coherent
+ * implementations.
+ */
+struct tegra_ivc_channel_header {
+	union {
+		/* fields owned by the transmitting end */
+		struct {
+			uint32_t w_count;
+			uint32_t state;
+		};
+		uint8_t w_align[TEGRA_IVC_ALIGN];
+	};
+	union {
+		/* fields owned by the receiving end */
+		uint32_t r_count;
+		uint8_t r_align[TEGRA_IVC_ALIGN];
+	};
+};
+
+static inline void tegra_ivc_invalidate_counter(struct tegra_ivc *ivc,
+					struct tegra_ivc_channel_header *h,
+					ulong offset)
+{
+	ulong base = ((ulong)h) + offset;
+	invalidate_dcache_range(base, base + TEGRA_IVC_ALIGN);
+}
+
+static inline void tegra_ivc_flush_counter(struct tegra_ivc *ivc,
+					   struct tegra_ivc_channel_header *h,
+					   ulong offset)
+{
+	ulong base = ((ulong)h) + offset;
+	flush_dcache_range(base, base + TEGRA_IVC_ALIGN);
+}
+
+static inline ulong tegra_ivc_frame_addr(struct tegra_ivc *ivc,
+					 struct tegra_ivc_channel_header *h,
+					 uint32_t frame)
+{
+	BUG_ON(frame >= ivc->nframes);
+
+	return ((ulong)h) + sizeof(struct tegra_ivc_channel_header) +
+	       (ivc->frame_size * frame);
+}
+
+static inline void *tegra_ivc_frame_pointer(struct tegra_ivc *ivc,
+					    struct tegra_ivc_channel_header *ch,
+					    uint32_t frame)
+{
+	return (void *)tegra_ivc_frame_addr(ivc, ch, frame);
+}
+
+static inline void tegra_ivc_invalidate_frame(struct tegra_ivc *ivc,
+					struct tegra_ivc_channel_header *h,
+					unsigned frame)
+{
+	ulong base = tegra_ivc_frame_addr(ivc, h, frame);
+	invalidate_dcache_range(base, base + ivc->frame_size);
+}
+
+static inline void tegra_ivc_flush_frame(struct tegra_ivc *ivc,
+					 struct tegra_ivc_channel_header *h,
+					 unsigned frame)
+{
+	ulong base = tegra_ivc_frame_addr(ivc, h, frame);
+	flush_dcache_range(base, base + ivc->frame_size);
+}
+
+static inline int tegra_ivc_channel_empty(struct tegra_ivc *ivc,
+					  struct tegra_ivc_channel_header *ch)
+{
+	/*
+	 * This function performs multiple checks on the same values with
+	 * security implications, so create snapshots with ACCESS_ONCE() to
+	 * ensure that these checks use the same values.
+	 */
+	uint32_t w_count = ACCESS_ONCE(ch->w_count);
+	uint32_t r_count = ACCESS_ONCE(ch->r_count);
+
+	/*
+	 * Perform an over-full check to prevent denial of service attacks where
+	 * a server could be easily fooled into believing that there's an
+	 * extremely large number of frames ready, since receivers are not
+	 * expected to check for full or over-full conditions.
+	 *
+	 * Although the channel isn't empty, this is an invalid case caused by
+	 * a potentially malicious peer, so returning empty is safer, because it
+	 * gives the impression that the channel has gone silent.
+	 */
+	if (w_count - r_count > ivc->nframes)
+		return 1;
+
+	return w_count == r_count;
+}
+
+static inline int tegra_ivc_channel_full(struct tegra_ivc *ivc,
+					 struct tegra_ivc_channel_header *ch)
+{
+	/*
+	 * Invalid cases where the counters indicate that the queue is over
+	 * capacity also appear full.
+	 */
+	return (ACCESS_ONCE(ch->w_count) - ACCESS_ONCE(ch->r_count)) >=
+	       ivc->nframes;
+}
+
+static inline void tegra_ivc_advance_rx(struct tegra_ivc *ivc)
+{
+	ACCESS_ONCE(ivc->rx_channel->r_count) =
+			ACCESS_ONCE(ivc->rx_channel->r_count) + 1;
+
+	if (ivc->r_pos == ivc->nframes - 1)
+		ivc->r_pos = 0;
+	else
+		ivc->r_pos++;
+}
+
+static inline void tegra_ivc_advance_tx(struct tegra_ivc *ivc)
+{
+	ACCESS_ONCE(ivc->tx_channel->w_count) =
+			ACCESS_ONCE(ivc->tx_channel->w_count) + 1;
+
+	if (ivc->w_pos == ivc->nframes - 1)
+		ivc->w_pos = 0;
+	else
+		ivc->w_pos++;
+}
+
+static inline int tegra_ivc_check_read(struct tegra_ivc *ivc)
+{
+	ulong offset;
+
+	/*
+	 * tx_channel->state is set locally, so it is not synchronized with
+	 * state from the remote peer. The remote peer cannot reset its
+	 * transmit counters until we've acknowledged its synchronization
+	 * request, so no additional synchronization is required because an
+	 * asynchronous transition of rx_channel->state to ivc_state_ack is not
+	 * allowed.
+	 */
+	if (ivc->tx_channel->state != ivc_state_established)
+		return -ECONNRESET;
+
+	/*
+	 * Avoid unnecessary invalidations when performing repeated accesses to
+	 * an IVC channel by checking the old queue pointers first.
+	 * Synchronization is only necessary when these pointers indicate empty
+	 * or full.
+	 */
+	if (!tegra_ivc_channel_empty(ivc, ivc->rx_channel))
+		return 0;
+
+	offset = offsetof(struct tegra_ivc_channel_header, w_count);
+	tegra_ivc_invalidate_counter(ivc, ivc->rx_channel, offset);
+	return tegra_ivc_channel_empty(ivc, ivc->rx_channel) ? -ENOMEM : 0;
+}
+
+static inline int tegra_ivc_check_write(struct tegra_ivc *ivc)
+{
+	ulong offset;
+
+	if (ivc->tx_channel->state != ivc_state_established)
+		return -ECONNRESET;
+
+	if (!tegra_ivc_channel_full(ivc, ivc->tx_channel))
+		return 0;
+
+	offset = offsetof(struct tegra_ivc_channel_header, r_count);
+	tegra_ivc_invalidate_counter(ivc, ivc->tx_channel, offset);
+	return tegra_ivc_channel_full(ivc, ivc->tx_channel) ? -ENOMEM : 0;
+}
+
+static inline uint32_t tegra_ivc_channel_avail_count(struct tegra_ivc *ivc,
+	struct tegra_ivc_channel_header *ch)
+{
+	/*
+	 * This function isn't expected to be used in scenarios where an
+	 * over-full situation can lead to denial of service attacks. See the
+	 * comment in tegra_ivc_channel_empty() for an explanation about
+	 * special over-full considerations.
+	 */
+	return ACCESS_ONCE(ch->w_count) - ACCESS_ONCE(ch->r_count);
+}
+
+int tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc, void **frame)
+{
+	int result = tegra_ivc_check_read(ivc);
+	if (result < 0)
+		return result;
+
+	/*
+	 * Order observation of w_pos potentially indicating new data before
+	 * data read.
+	 */
+	mb();
+
+	tegra_ivc_invalidate_frame(ivc, ivc->rx_channel, ivc->r_pos);
+	*frame = tegra_ivc_frame_pointer(ivc, ivc->rx_channel, ivc->r_pos);
+
+	return 0;
+}
+
+int tegra_ivc_read_advance(struct tegra_ivc *ivc)
+{
+	ulong offset;
+	int result;
+
+	/*
+	 * No read barriers or synchronization here: the caller is expected to
+	 * have already observed the channel non-empty. This check is just to
+	 * catch programming errors.
+	 */
+	result = tegra_ivc_check_read(ivc);
+	if (result)
+		return result;
+
+	tegra_ivc_advance_rx(ivc);
+	offset = offsetof(struct tegra_ivc_channel_header, r_count);
+	tegra_ivc_flush_counter(ivc, ivc->rx_channel, offset);
+
+	/*
+	 * Ensure our write to r_pos occurs before our read from w_pos.
+	 */
+	mb();
+
+	offset = offsetof(struct tegra_ivc_channel_header, w_count);
+	tegra_ivc_invalidate_counter(ivc, ivc->rx_channel, offset);
+
+	if (tegra_ivc_channel_avail_count(ivc, ivc->rx_channel) ==
+	    ivc->nframes - 1)
+		ivc->notify(ivc);
+
+	return 0;
+}
+
+int tegra_ivc_write_get_next_frame(struct tegra_ivc *ivc, void **frame)
+{
+	int result = tegra_ivc_check_write(ivc);
+	if (result)
+		return result;
+
+	*frame = tegra_ivc_frame_pointer(ivc, ivc->tx_channel, ivc->w_pos);
+
+	return 0;
+}
+
+int tegra_ivc_write_advance(struct tegra_ivc *ivc)
+{
+	ulong offset;
+	int result;
+
+	result = tegra_ivc_check_write(ivc);
+	if (result)
+		return result;
+
+	tegra_ivc_flush_frame(ivc, ivc->tx_channel, ivc->w_pos);
+
+	/*
+	 * Order any possible stores to the frame before update of w_pos.
+	 */
+	mb();
+
+	tegra_ivc_advance_tx(ivc);
+	offset = offsetof(struct tegra_ivc_channel_header, w_count);
+	tegra_ivc_flush_counter(ivc, ivc->tx_channel, offset);
+
+	/*
+	 * Ensure our write to w_pos occurs before our read from r_pos.
+	 */
+	mb();
+
+	offset = offsetof(struct tegra_ivc_channel_header, r_count);
+	tegra_ivc_invalidate_counter(ivc, ivc->tx_channel, offset);
+
+	if (tegra_ivc_channel_avail_count(ivc, ivc->tx_channel) == 1)
+		ivc->notify(ivc);
+
+	return 0;
+}
+
+/*
+ * ===============================================================
+ *  IVC State Transition Table - see tegra_ivc_channel_notified()
+ * ===============================================================
+ *
+ *	local	remote	action
+ *	-----	------	-----------------------------------
+ *	SYNC	EST	<none>
+ *	SYNC	ACK	reset counters; move to EST; notify
+ *	SYNC	SYNC	reset counters; move to ACK; notify
+ *	ACK	EST	move to EST; notify
+ *	ACK	ACK	move to EST; notify
+ *	ACK	SYNC	reset counters; move to ACK; notify
+ *	EST	EST	<none>
+ *	EST	ACK	<none>
+ *	EST	SYNC	reset counters; move to ACK; notify
+ *
+ * ===============================================================
+ */
+int tegra_ivc_channel_notified(struct tegra_ivc *ivc)
+{
+	ulong offset;
+	enum ivc_state peer_state;
+
+	/* Copy the receiver's state out of shared memory. */
+	offset = offsetof(struct tegra_ivc_channel_header, w_count);
+	tegra_ivc_invalidate_counter(ivc, ivc->rx_channel, offset);
+	peer_state = ACCESS_ONCE(ivc->rx_channel->state);
+
+	if (peer_state == ivc_state_sync) {
+		/*
+		 * Order observation of ivc_state_sync before stores clearing
+		 * tx_channel.
+		 */
+		mb();
+
+		/*
+		 * Reset tx_channel counters. The remote end is in the SYNC
+		 * state and won't make progress until we change our state,
+		 * so the counters are not in use at this time.
+		 */
+		ivc->tx_channel->w_count = 0;
+		ivc->rx_channel->r_count = 0;
+
+		ivc->w_pos = 0;
+		ivc->r_pos = 0;
+
+		/*
+		 * Ensure that counters appear cleared before new state can be
+		 * observed.
+		 */
+		mb();
+
+		/*
+		 * Move to ACK state. We have just cleared our counters, so it
+		 * is now safe for the remote end to start using these values.
+		 */
+		ivc->tx_channel->state = ivc_state_ack;
+		offset = offsetof(struct tegra_ivc_channel_header, w_count);
+		tegra_ivc_flush_counter(ivc, ivc->tx_channel, offset);
+
+		/*
+		 * Notify remote end to observe state transition.
+		 */
+		ivc->notify(ivc);
+	} else if (ivc->tx_channel->state == ivc_state_sync &&
+			peer_state == ivc_state_ack) {
+		/*
+		 * Order observation of ivc_state_sync before stores clearing
+		 * tx_channel.
+		 */
+		mb();
+
+		/*
+		 * Reset tx_channel counters. The remote end is in the ACK
+		 * state and won't make progress until we change our state,
+		 * so the counters are not in use at this time.
+		 */
+		ivc->tx_channel->w_count = 0;
+		ivc->rx_channel->r_count = 0;
+
+		ivc->w_pos = 0;
+		ivc->r_pos = 0;
+
+		/*
+		 * Ensure that counters appear cleared before new state can be
+		 * observed.
+		 */
+		mb();
+
+		/*
+		 * Move to ESTABLISHED state. We know that the remote end has
+		 * already cleared its counters, so it is safe to start
+		 * writing/reading on this channel.
+		 */
+		ivc->tx_channel->state = ivc_state_established;
+		offset = offsetof(struct tegra_ivc_channel_header, w_count);
+		tegra_ivc_flush_counter(ivc, ivc->tx_channel, offset);
+
+		/*
+		 * Notify remote end to observe state transition.
+		 */
+		ivc->notify(ivc);
+	} else if (ivc->tx_channel->state == ivc_state_ack) {
+		/*
+		 * At this point, we have observed the peer to be in either
+		 * the ACK or ESTABLISHED state. Next, order observation of
+		 * peer state before storing to tx_channel.
+		 */
+		mb();
+
+		/*
+		 * Move to ESTABLISHED state. We know that we have previously
+		 * cleared our counters, and we know that the remote end has
+		 * cleared its counters, so it is safe to start writing/reading
+		 * on this channel.
+		 */
+		ivc->tx_channel->state = ivc_state_established;
+		offset = offsetof(struct tegra_ivc_channel_header, w_count);
+		tegra_ivc_flush_counter(ivc, ivc->tx_channel, offset);
+
+		/*
+		 * Notify remote end to observe state transition.
+		 */
+		ivc->notify(ivc);
+	} else {
+		/*
+		 * There is no need to handle any further action. Either the
+		 * channel is already fully established, or we are waiting for
+		 * the remote end to catch up with our current state. Refer
+		 * to the diagram in "IVC State Transition Table" above.
+		 */
+	}
+
+	if (ivc->tx_channel->state != ivc_state_established)
+		return -EAGAIN;
+
+	return 0;
+}
+
+void tegra_ivc_channel_reset(struct tegra_ivc *ivc)
+{
+	ulong offset;
+
+	ivc->tx_channel->state = ivc_state_sync;
+	offset = offsetof(struct tegra_ivc_channel_header, w_count);
+	tegra_ivc_flush_counter(ivc, ivc->tx_channel, offset);
+	ivc->notify(ivc);
+}
+
+static int check_ivc_params(ulong qbase1, ulong qbase2, uint32_t nframes,
+			    uint32_t frame_size)
+{
+	int ret = 0;
+
+	BUG_ON(offsetof(struct tegra_ivc_channel_header, w_count) &
+	       (TEGRA_IVC_ALIGN - 1));
+	BUG_ON(offsetof(struct tegra_ivc_channel_header, r_count) &
+	       (TEGRA_IVC_ALIGN - 1));
+	BUG_ON(sizeof(struct tegra_ivc_channel_header) &
+	       (TEGRA_IVC_ALIGN - 1));
+
+	if ((uint64_t)nframes * (uint64_t)frame_size >= 0x100000000) {
+		error("tegra_ivc: nframes * frame_size overflows\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * The headers must at least be aligned enough for counters
+	 * to be accessed atomically.
+	 */
+	if ((qbase1 & (TEGRA_IVC_ALIGN - 1)) ||
+	    (qbase2 & (TEGRA_IVC_ALIGN - 1))) {
+		error("tegra_ivc: channel start not aligned\n");
+		return -EINVAL;
+	}
+
+	if (frame_size & (TEGRA_IVC_ALIGN - 1)) {
+		error("tegra_ivc: frame size not adequately aligned\n");
+		return -EINVAL;
+	}
+
+	if (qbase1 < qbase2) {
+		if (qbase1 + frame_size * nframes > qbase2)
+			ret = -EINVAL;
+	} else {
+		if (qbase2 + frame_size * nframes > qbase1)
+			ret = -EINVAL;
+	}
+
+	if (ret) {
+		error("tegra_ivc: queue regions overlap\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+int tegra_ivc_init(struct tegra_ivc *ivc, ulong rx_base, ulong tx_base,
+		   uint32_t nframes, uint32_t frame_size,
+		   void (*notify)(struct tegra_ivc *))
+{
+	int ret;
+
+	if (!ivc)
+		return -EINVAL;
+
+	ret = check_ivc_params(rx_base, tx_base, nframes, frame_size);
+	if (ret)
+		return ret;
+
+	ivc->rx_channel = (struct tegra_ivc_channel_header *)rx_base;
+	ivc->tx_channel = (struct tegra_ivc_channel_header *)tx_base;
+	ivc->w_pos = 0;
+	ivc->r_pos = 0;
+	ivc->nframes = nframes;
+	ivc->frame_size = frame_size;
+	ivc->notify = notify;
+
+	return 0;
+}
diff --git a/arch/arm/mach-tegra/psci.S b/arch/arm/mach-tegra/psci.S
index b836da1..645d08f 100644
--- a/arch/arm/mach-tegra/psci.S
+++ b/arch/arm/mach-tegra/psci.S
@@ -61,9 +61,6 @@
 	ldrne	r7, [r5]
 	mcrne	p15, 0, r7, c14, c0, 0	@ write CNTFRQ to CPU1..3
 
-	bl	psci_get_cpu_stack_top	@ stack top => r0
-	mov	sp, r0
-
 	bx	r6
 ENDPROC(psci_arch_init)
 
@@ -88,12 +85,13 @@
 ENDPROC(psci_cpu_off)
 
 ENTRY(psci_cpu_on)
-	push	{lr}
+	push	{r4, r5, r6, lr}
 
+	mov	r4, r1
 	mov	r0, r1
-	bl	psci_get_cpu_stack_top	@ get stack top of target CPU
-	str	r2, [r0]		@ store target PC at stack top
-	dsb
+	mov	r1, r2
+	bl	psci_save_target_pc	@ store target PC
+	mov	r1, r4
 
 	ldr	r6, =TEGRA_RESET_EXCEPTION_VECTOR
 	ldr	r5, =psci_cpu_entry
@@ -106,9 +104,7 @@
 	str	r5, [r6, r2]
 
 	mov	r0, #ARM_PSCI_RET_SUCCESS	@ Return PSCI_RET_SUCCESS
-	pop	{pc}
+	pop	{r4, r5, r6, pc}
 ENDPROC(psci_cpu_on)
 
-	.globl psci_text_end
-psci_text_end:
 	.popsection
diff --git a/arch/arm/mach-tegra/tegra186/Makefile b/arch/arm/mach-tegra/tegra186/Makefile
index ce4610d..033d600 100644
--- a/arch/arm/mach-tegra/tegra186/Makefile
+++ b/arch/arm/mach-tegra/tegra186/Makefile
@@ -2,7 +2,6 @@
 #
 # SPDX-License-Identifier: GPL-2.0
 
-obj-y += ../arm64-mmu.o
 obj-y += ../board186.o
-obj-y += ../lowlevel_init.o
-obj-$(CONFIG_DISPLAY_CPUINFO) += ../sys_info.o
+obj-y += nvtboot_ll.o
+obj-y += nvtboot_mem.o
diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_ll.S b/arch/arm/mach-tegra/tegra186/nvtboot_ll.S
new file mode 100644
index 0000000..1eab890
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra186/nvtboot_ll.S
@@ -0,0 +1,20 @@
+/*
+ * Save nvtboot-related boot-time CPU state
+ *
+ * (C) Copyright 2015-2016 NVIDIA Corporation <www.nvidia.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+
+.globl	nvtboot_boot_x0
+nvtboot_boot_x0:
+	.dword 0
+
+ENTRY(save_boot_params)
+	adr	x8, nvtboot_boot_x0
+	str	x0, [x8]
+	b	save_boot_params_ret
+ENDPROC(save_boot_params)
diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_mem.c b/arch/arm/mach-tegra/tegra186/nvtboot_mem.c
new file mode 100644
index 0000000..37dd8d4
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra186/nvtboot_mem.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdt_support.h>
+#include <fdtdec.h>
+#include <asm/arch/tegra.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern unsigned long nvtboot_boot_x0;
+
+/*
+ * A parsed version of /memory/reg from the DTB that is passed to U-Boot in x0.
+ *
+ * We only support up to two banks since that's all the binary  bootloader
+ * ever sets. We assume bank 0 is RAM below 4G and bank 1 is RAM  above 4G.
+ * This is all a fairly safe assumption, since the L4T kernel makes  the same
+ * assumptions, so the bootloader is unlikely to change.
+ *
+ * This is written to before relocation, and hence cannot be in .bss, since
+ * .bss overlaps the DTB that's appended to the U-Boot binary. The initializer
+ * forces this into .data and avoids this issue. This also has the nice side-
+ * effect of the content being valid after relocation.
+ */
+static struct {
+	u64 start;
+	u64 size;
+} ram_banks[2] = {{1}};
+
+int dram_init(void)
+{
+	unsigned int na, ns;
+	const void *nvtboot_blob = (void *)nvtboot_boot_x0;
+	int node, len, i;
+	const u32 *prop;
+
+	memset(ram_banks, 0, sizeof(ram_banks));
+
+	na = fdtdec_get_uint(nvtboot_blob, 0, "#address-cells", 2);
+	ns = fdtdec_get_uint(nvtboot_blob, 0, "#size-cells", 2);
+
+	node = fdt_path_offset(nvtboot_blob, "/memory");
+	if (node < 0) {
+		error("Can't find /memory node in nvtboot DTB");
+		hang();
+	}
+	prop = fdt_getprop(nvtboot_blob, node, "reg", &len);
+	if (!prop) {
+		error("Can't find /memory/reg property in nvtboot DTB");
+		hang();
+	}
+
+	len /= (na + ns);
+	if (len > ARRAY_SIZE(ram_banks))
+		len = ARRAY_SIZE(ram_banks);
+
+	gd->ram_size = 0;
+	for (i = 0; i < len; i++) {
+		ram_banks[i].start = of_read_number(prop, na);
+		prop += na;
+		ram_banks[i].size = of_read_number(prop, ns);
+		prop += ns;
+		gd->ram_size += ram_banks[i].size;
+	}
+
+	return 0;
+}
+
+extern unsigned long nvtboot_boot_x0;
+
+void dram_init_banksize(void)
+{
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		gd->bd->bi_dram[i].start = ram_banks[i].start;
+		gd->bd->bi_dram[i].size = ram_banks[i].size;
+	}
+}
+
+ulong board_get_usable_ram_top(ulong total_size)
+{
+	return ram_banks[0].start + ram_banks[0].size;
+}
diff --git a/arch/arm/mach-tegra/tegra20/Makefile b/arch/arm/mach-tegra/tegra20/Makefile
index 17c1990..72d82a5 100644
--- a/arch/arm/mach-tegra/tegra20/Makefile
+++ b/arch/arm/mach-tegra/tegra20/Makefile
@@ -10,7 +10,8 @@
 
 # The AVP is ARMv4T architecture so we must use special compiler
 # flags for any startup files it might use.
-CFLAGS_warmboot_avp.o += -march=armv4t
+CFLAGS_warmboot_avp.o = -march=armv4t -U__LINUX_ARM_ARCH__ \
+	-D__LINUX_ARM_ARCH__=4
 
 obj-y	+= clock.o funcmux.o pinmux.o
 obj-$(CONFIG_TEGRA_LP0) += warmboot.o crypto.o warmboot_avp.o
diff --git a/arch/arm/mach-uniphier/Kconfig b/arch/arm/mach-uniphier/Kconfig
index e256eeb..a8a0b90 100644
--- a/arch/arm/mach-uniphier/Kconfig
+++ b/arch/arm/mach-uniphier/Kconfig
@@ -6,12 +6,15 @@
 config ARCH_UNIPHIER_32BIT
 	bool
 	select CPU_V7
+	select CPU_V7_HAS_NONSEC
+	select ARMV7_NONSEC
 
 config ARCH_UNIPHIER_64BIT
 	bool
 	select ARM64
 	select SPL_SEPARATE_BSS
 	select ARMV8_MULTIENTRY
+	select ARMV8_SPIN_TABLE
 
 choice
         prompt "UniPhier SoC select"
@@ -69,6 +72,13 @@
 	depends on ARCH_UNIPHIER_PRO5_PXS2_LD6B
 	default y
 
+config CACHE_UNIPHIER
+	bool "Enable the UniPhier L2 cache controller"
+	depends on ARCH_UNIPHIER_32BIT
+	default y
+	help
+	  This option allows to use the UniPhier System Cache as L2 cache.
+
 config MICRO_SUPPORT_CARD
 	bool "Use Micro Support Card"
 	help
diff --git a/arch/arm/mach-uniphier/arm32/Makefile b/arch/arm/mach-uniphier/arm32/Makefile
index 376c06b..6f05d72 100644
--- a/arch/arm/mach-uniphier/arm32/Makefile
+++ b/arch/arm/mach-uniphier/arm32/Makefile
@@ -7,7 +7,8 @@
 obj-$(CONFIG_DEBUG_LL) += debug_ll.o
 else
 obj-y += late_lowlevel_init.o
-obj-y += cache_uniphier.o
+obj-y += cache-uniphier.o
+obj-$(CONFIG_ARMV7_PSCI) += psci.o psci_smp.o
 endif
 
 obj-y += timer.o
diff --git a/arch/arm/mach-uniphier/arm32/arm-mpcore.h b/arch/arm/mach-uniphier/arm32/arm-mpcore.h
index cf7cd46..1a85664 100644
--- a/arch/arm/mach-uniphier/arm32/arm-mpcore.h
+++ b/arch/arm/mach-uniphier/arm32/arm-mpcore.h
@@ -12,6 +12,9 @@
 
 /* SCU Control Register */
 #define SCU_CTRL		0x00
+#define SCU_ENABLE		(1 << 0)
+#define SCU_STANDBY_ENABLE	(1 << 5)
+
 /* SCU Configuration Register */
 #define SCU_CONF		0x04
 /* SCU CPU Power Status Register */
diff --git a/arch/arm/mach-uniphier/arm32/cache-uniphier.c b/arch/arm/mach-uniphier/arm32/cache-uniphier.c
new file mode 100644
index 0000000..658969b
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm32/cache-uniphier.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2012-2014 Panasonic Corporation
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <asm/armv7.h>
+#include <asm/processor.h>
+
+#include "cache-uniphier.h"
+
+/* control registers */
+#define UNIPHIER_SSCC		0x500c0000	/* Control Register */
+#define    UNIPHIER_SSCC_BST			(0x1 << 20)	/* UCWG burst read */
+#define    UNIPHIER_SSCC_ACT			(0x1 << 19)	/* Inst-Data separate */
+#define    UNIPHIER_SSCC_WTG			(0x1 << 18)	/* WT gathering on */
+#define    UNIPHIER_SSCC_PRD			(0x1 << 17)	/* enable pre-fetch */
+#define    UNIPHIER_SSCC_ON			(0x1 <<  0)	/* enable cache */
+#define UNIPHIER_SSCLPDAWCR	0x500c0030	/* Unified/Data Active Way Control */
+#define UNIPHIER_SSCLPIAWCR	0x500c0034	/* Instruction Active Way Control */
+
+/* revision registers */
+#define UNIPHIER_SSCID		0x503c0100	/* ID Register */
+
+/* operation registers */
+#define UNIPHIER_SSCOPE		0x506c0244	/* Cache Operation Primitive Entry */
+#define    UNIPHIER_SSCOPE_CM_INV		0x0	/* invalidate */
+#define    UNIPHIER_SSCOPE_CM_CLEAN		0x1	/* clean */
+#define    UNIPHIER_SSCOPE_CM_FLUSH		0x2	/* flush */
+#define    UNIPHIER_SSCOPE_CM_SYNC		0x8	/* sync (drain bufs) */
+#define    UNIPHIER_SSCOPE_CM_FLUSH_PREFETCH	0x9	/* flush p-fetch buf */
+#define UNIPHIER_SSCOQM		0x506c0248
+#define    UNIPHIER_SSCOQM_TID_MASK		(0x3 << 21)
+#define    UNIPHIER_SSCOQM_TID_LRU_DATA		(0x0 << 21)
+#define    UNIPHIER_SSCOQM_TID_LRU_INST		(0x1 << 21)
+#define    UNIPHIER_SSCOQM_TID_WAY		(0x2 << 21)
+#define    UNIPHIER_SSCOQM_S_MASK		(0x3 << 17)
+#define    UNIPHIER_SSCOQM_S_RANGE		(0x0 << 17)
+#define    UNIPHIER_SSCOQM_S_ALL		(0x1 << 17)
+#define    UNIPHIER_SSCOQM_S_WAY		(0x2 << 17)
+#define    UNIPHIER_SSCOQM_CE			(0x1 << 15)	/* notify completion */
+#define    UNIPHIER_SSCOQM_CW			(0x1 << 14)
+#define    UNIPHIER_SSCOQM_CM_MASK		(0x7)
+#define    UNIPHIER_SSCOQM_CM_INV		0x0	/* invalidate */
+#define    UNIPHIER_SSCOQM_CM_CLEAN		0x1	/* clean */
+#define    UNIPHIER_SSCOQM_CM_FLUSH		0x2	/* flush */
+#define    UNIPHIER_SSCOQM_CM_PREFETCH		0x3	/* prefetch to cache */
+#define    UNIPHIER_SSCOQM_CM_PREFETCH_BUF	0x4	/* prefetch to pf-buf */
+#define    UNIPHIER_SSCOQM_CM_TOUCH		0x5	/* touch */
+#define    UNIPHIER_SSCOQM_CM_TOUCH_ZERO	0x6	/* touch to zero */
+#define    UNIPHIER_SSCOQM_CM_TOUCH_DIRTY	0x7	/* touch with dirty */
+#define UNIPHIER_SSCOQAD	0x506c024c	/* Cache Operation Queue Address */
+#define UNIPHIER_SSCOQSZ	0x506c0250	/* Cache Operation Queue Size */
+#define UNIPHIER_SSCOQMASK	0x506c0254	/* Cache Operation Queue Address Mask */
+#define UNIPHIER_SSCOQWN	0x506c0258	/* Cache Operation Queue Way Number */
+#define UNIPHIER_SSCOPPQSEF	0x506c025c	/* Cache Operation Queue Set Complete */
+#define    UNIPHIER_SSCOPPQSEF_FE		(0x1 << 1)
+#define    UNIPHIER_SSCOPPQSEF_OE		(0x1 << 0)
+#define UNIPHIER_SSCOLPQS	0x506c0260	/* Cache Operation Queue Status */
+#define    UNIPHIER_SSCOLPQS_EF			(0x1 << 2)
+#define    UNIPHIER_SSCOLPQS_EST		(0x1 << 1)
+#define    UNIPHIER_SSCOLPQS_QST		(0x1 << 0)
+
+#define UNIPHIER_SSC_LINE_SIZE		128
+#define UNIPHIER_SSC_RANGE_OP_MAX_SIZE	(0x00400000 - (UNIPHIER_SSC_LINE_SIZE))
+
+#define UNIPHIER_SSCOQAD_IS_NEEDED(op) \
+		((op & UNIPHIER_SSCOQM_S_MASK) == UNIPHIER_SSCOQM_S_RANGE)
+#define UNIPHIER_SSCOQWM_IS_NEEDED(op) \
+		(((op & UNIPHIER_SSCOQM_S_MASK) == UNIPHIER_SSCOQM_S_WAY) || \
+		 ((op & UNIPHIER_SSCOQM_TID_MASK) == UNIPHIER_SSCOQM_TID_WAY))
+
+/* uniphier_cache_sync - perform a sync point for a particular cache level */
+static void uniphier_cache_sync(void)
+{
+	/* drain internal buffers */
+	writel(UNIPHIER_SSCOPE_CM_SYNC, UNIPHIER_SSCOPE);
+	/* need a read back to confirm */
+	readl(UNIPHIER_SSCOPE);
+}
+
+/**
+ * uniphier_cache_maint_common - run a queue operation
+ *
+ * @start: start address of range operation (don't care for "all" operation)
+ * @size: data size of range operation (don't care for "all" operation)
+ * @ways: target ways (don't care for operations other than pre-fetch, touch
+ * @operation: flags to specify the desired cache operation
+ */
+static void uniphier_cache_maint_common(u32 start, u32 size, u32 ways,
+					u32 operation)
+{
+	/* clear the complete notification flag */
+	writel(UNIPHIER_SSCOLPQS_EF, UNIPHIER_SSCOLPQS);
+
+	do {
+		/* set cache operation */
+		writel(UNIPHIER_SSCOQM_CE | operation, UNIPHIER_SSCOQM);
+
+		/* set address range if needed */
+		if (likely(UNIPHIER_SSCOQAD_IS_NEEDED(operation))) {
+			writel(start, UNIPHIER_SSCOQAD);
+			writel(size, UNIPHIER_SSCOQSZ);
+		}
+
+		/* set target ways if needed */
+		if (unlikely(UNIPHIER_SSCOQWM_IS_NEEDED(operation)))
+			writel(ways, UNIPHIER_SSCOQWN);
+	} while (unlikely(readl(UNIPHIER_SSCOPPQSEF) &
+			  (UNIPHIER_SSCOPPQSEF_FE | UNIPHIER_SSCOPPQSEF_OE)));
+
+	/* wait until the operation is completed */
+	while (likely(readl(UNIPHIER_SSCOLPQS) != UNIPHIER_SSCOLPQS_EF))
+		cpu_relax();
+}
+
+static void uniphier_cache_maint_all(u32 operation)
+{
+	uniphier_cache_maint_common(0, 0, 0, UNIPHIER_SSCOQM_S_ALL | operation);
+
+	uniphier_cache_sync();
+}
+
+static void uniphier_cache_maint_range(u32 start, u32 end, u32 ways,
+				       u32 operation)
+{
+	u32 size;
+
+	/*
+	 * If the start address is not aligned,
+	 * perform a cache operation for the first cache-line
+	 */
+	start = start & ~(UNIPHIER_SSC_LINE_SIZE - 1);
+
+	size = end - start;
+
+	if (unlikely(size >= (u32)(-UNIPHIER_SSC_LINE_SIZE))) {
+		/* this means cache operation for all range */
+		uniphier_cache_maint_all(operation);
+		return;
+	}
+
+	/*
+	 * If the end address is not aligned,
+	 * perform a cache operation for the last cache-line
+	 */
+	size = ALIGN(size, UNIPHIER_SSC_LINE_SIZE);
+
+	while (size) {
+		u32 chunk_size = min_t(u32, size, UNIPHIER_SSC_RANGE_OP_MAX_SIZE);
+
+		uniphier_cache_maint_common(start, chunk_size, ways,
+					    UNIPHIER_SSCOQM_S_RANGE | operation);
+
+		start += chunk_size;
+		size -= chunk_size;
+	}
+
+	uniphier_cache_sync();
+}
+
+void uniphier_cache_prefetch_range(u32 start, u32 end, u32 ways)
+{
+	uniphier_cache_maint_range(start, end, ways,
+				   UNIPHIER_SSCOQM_TID_WAY |
+				   UNIPHIER_SSCOQM_CM_PREFETCH);
+}
+
+void uniphier_cache_touch_range(u32 start, u32 end, u32 ways)
+{
+	uniphier_cache_maint_range(start, end, ways,
+				   UNIPHIER_SSCOQM_TID_WAY |
+				   UNIPHIER_SSCOQM_CM_TOUCH);
+}
+
+void uniphier_cache_touch_zero_range(u32 start, u32 end, u32 ways)
+{
+	uniphier_cache_maint_range(start, end, ways,
+				   UNIPHIER_SSCOQM_TID_WAY |
+				   UNIPHIER_SSCOQM_CM_TOUCH_ZERO);
+}
+
+void uniphier_cache_inv_way(u32 ways)
+{
+	uniphier_cache_maint_common(0, 0, ways,
+				    UNIPHIER_SSCOQM_S_WAY |
+				    UNIPHIER_SSCOQM_CM_INV);
+}
+
+void uniphier_cache_set_active_ways(int cpu, u32 active_ways)
+{
+	void __iomem *base = (void __iomem *)UNIPHIER_SSCC + 0xc00;
+
+	switch (readl(UNIPHIER_SSCID)) { /* revision */
+	case 0x11:	/* sLD3 */
+		base = (void __iomem *)UNIPHIER_SSCC + 0x870;
+		break;
+	case 0x12:	/* LD4 */
+	case 0x16:	/* sld8 */
+		base = (void __iomem *)UNIPHIER_SSCC + 0x840;
+		break;
+	default:
+		base = (void __iomem *)UNIPHIER_SSCC + 0xc00;
+		break;
+	}
+
+	writel(active_ways, base + 4 * cpu);
+}
+
+static void uniphier_cache_endisable(int enable)
+{
+	u32 tmp;
+
+	tmp = readl(UNIPHIER_SSCC);
+	if (enable)
+		tmp |= UNIPHIER_SSCC_ON;
+	else
+		tmp &= ~UNIPHIER_SSCC_ON;
+	writel(tmp, UNIPHIER_SSCC);
+}
+
+void uniphier_cache_enable(void)
+{
+	uniphier_cache_endisable(1);
+}
+
+void uniphier_cache_disable(void)
+{
+	uniphier_cache_endisable(0);
+}
+
+#ifdef CONFIG_CACHE_UNIPHIER
+void v7_outer_cache_flush_all(void)
+{
+	uniphier_cache_maint_all(UNIPHIER_SSCOQM_CM_FLUSH);
+}
+
+void v7_outer_cache_inval_all(void)
+{
+	uniphier_cache_maint_all(UNIPHIER_SSCOQM_CM_INV);
+}
+
+void v7_outer_cache_flush_range(u32 start, u32 end)
+{
+	uniphier_cache_maint_range(start, end, 0, UNIPHIER_SSCOQM_CM_FLUSH);
+}
+
+void v7_outer_cache_inval_range(u32 start, u32 end)
+{
+	if (start & (UNIPHIER_SSC_LINE_SIZE - 1)) {
+		start &= ~(UNIPHIER_SSC_LINE_SIZE - 1);
+		uniphier_cache_maint_range(start, UNIPHIER_SSC_LINE_SIZE, 0,
+					   UNIPHIER_SSCOQM_CM_FLUSH);
+		start += UNIPHIER_SSC_LINE_SIZE;
+	}
+
+	if (start >= end) {
+		uniphier_cache_sync();
+		return;
+	}
+
+	if (end & (UNIPHIER_SSC_LINE_SIZE - 1)) {
+		end &= ~(UNIPHIER_SSC_LINE_SIZE - 1);
+		uniphier_cache_maint_range(end, UNIPHIER_SSC_LINE_SIZE, 0,
+					   UNIPHIER_SSCOQM_CM_FLUSH);
+	}
+
+	if (start >= end) {
+		uniphier_cache_sync();
+		return;
+	}
+
+	uniphier_cache_maint_range(start, end, 0, UNIPHIER_SSCOQM_CM_INV);
+}
+
+void v7_outer_cache_enable(void)
+{
+	uniphier_cache_set_active_ways(0, U32_MAX);	/* activate all ways */
+	uniphier_cache_enable();
+}
+
+void v7_outer_cache_disable(void)
+{
+	uniphier_cache_disable();
+}
+#endif
+
+void enable_caches(void)
+{
+	dcache_enable();
+}
diff --git a/arch/arm/mach-uniphier/arm32/cache-uniphier.h b/arch/arm/mach-uniphier/arm32/cache-uniphier.h
new file mode 100644
index 0000000..493d66c
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm32/cache-uniphier.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CACHE_UNIPHIER_H
+#define __CACHE_UNIPHIER_H
+
+#include <linux/types.h>
+
+void uniphier_cache_prefetch_range(u32 start, u32 end, u32 ways);
+void uniphier_cache_touch_range(u32 start, u32 end, u32 ways);
+void uniphier_cache_touch_zero_range(u32 start, u32 end, u32 ways);
+void uniphier_cache_inv_way(u32 ways);
+void uniphier_cache_set_active_ways(int cpu, u32 active_ways);
+void uniphier_cache_enable(void);
+void uniphier_cache_disable(void);
+
+#endif /* __CACHE_UNIPHIER_H */
diff --git a/arch/arm/mach-uniphier/arm32/cache_uniphier.c b/arch/arm/mach-uniphier/arm32/cache_uniphier.c
deleted file mode 100644
index 4398114..0000000
--- a/arch/arm/mach-uniphier/arm32/cache_uniphier.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <linux/io.h>
-#include <asm/armv7.h>
-
-#include "ssc-regs.h"
-
-#ifdef CONFIG_UNIPHIER_L2CACHE_ON
-static void uniphier_cache_sync(void)
-{
-	writel(SSCOPE_CM_SYNC, SSCOPE); /* drain internal buffers */
-	readl(SSCOPE); /* need a read back to confirm */
-}
-
-static void uniphier_cache_maint_all(u32 operation)
-{
-	/* try until the command is successfully set */
-	do {
-		writel(SSCOQM_S_ALL | SSCOQM_CE | operation, SSCOQM);
-	} while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE));
-
-	/* wait until the operation is completed */
-	while (readl(SSCOLPQS) != SSCOLPQS_EF)
-		;
-
-	/* clear the complete notification flag */
-	writel(SSCOLPQS_EF, SSCOLPQS);
-
-	uniphier_cache_sync();
-}
-
-void v7_outer_cache_flush_all(void)
-{
-	uniphier_cache_maint_all(SSCOQM_CM_WB_INV);
-}
-
-void v7_outer_cache_inval_all(void)
-{
-	uniphier_cache_maint_all(SSCOQM_CM_INV);
-}
-
-static void __uniphier_cache_maint_range(u32 start, u32 size, u32 operation)
-{
-	/* try until the command is successfully set */
-	do {
-		writel(SSCOQM_S_ADDRESS | SSCOQM_CE | operation, SSCOQM);
-		writel(start, SSCOQAD);
-		writel(size, SSCOQSZ);
-
-	} while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE));
-
-	/* wait until the operation is completed */
-	while (readl(SSCOLPQS) != SSCOLPQS_EF)
-		;
-
-	/* clear the complete notification flag */
-	writel(SSCOLPQS_EF, SSCOLPQS);
-}
-
-static void uniphier_cache_maint_range(u32 start, u32 end, u32 operation)
-{
-	u32 size;
-
-	/*
-	 * If start address is not aligned to cache-line,
-	 * do cache operation for the first cache-line
-	 */
-	start = start & ~(SSC_LINE_SIZE - 1);
-
-	size = end - start;
-
-	if (unlikely(size >= (u32)(-SSC_LINE_SIZE))) {
-		/* this means cache operation for all range */
-		uniphier_cache_maint_all(operation);
-		return;
-	}
-
-	/*
-	 * If end address is not aligned to cache-line,
-	 * do cache operation for the last cache-line
-	 */
-	size = ALIGN(size, SSC_LINE_SIZE);
-
-	while (size) {
-		u32 chunk_size = size > SSC_RANGE_OP_MAX_SIZE ?
-						SSC_RANGE_OP_MAX_SIZE : size;
-		__uniphier_cache_maint_range(start, chunk_size, operation);
-
-		start += chunk_size;
-		size -= chunk_size;
-	}
-
-	uniphier_cache_sync();
-}
-
-void v7_outer_cache_flush_range(u32 start, u32 end)
-{
-	uniphier_cache_maint_range(start, end, SSCOQM_CM_WB_INV);
-}
-
-void v7_outer_cache_inval_range(u32 start, u32 end)
-{
-	if (start & (SSC_LINE_SIZE - 1)) {
-		start &= ~(SSC_LINE_SIZE - 1);
-		__uniphier_cache_maint_range(start, SSC_LINE_SIZE,
-					     SSCOQM_CM_WB_INV);
-		start += SSC_LINE_SIZE;
-	}
-
-	if (start >= end) {
-		uniphier_cache_sync();
-		return;
-	}
-
-	if (end & (SSC_LINE_SIZE - 1)) {
-		end &= ~(SSC_LINE_SIZE - 1);
-		__uniphier_cache_maint_range(end, SSC_LINE_SIZE,
-					     SSCOQM_CM_WB_INV);
-	}
-
-	if (start >= end) {
-		uniphier_cache_sync();
-		return;
-	}
-
-	uniphier_cache_maint_range(start, end, SSCOQM_CM_INV);
-}
-
-void v7_outer_cache_enable(void)
-{
-	u32 tmp;
-
-	writel(U32_MAX, SSCLPDAWCR);	/* activate all ways */
-	tmp = readl(SSCC);
-	tmp |= SSCC_ON;
-	writel(tmp, SSCC);
-}
-#endif
-
-void v7_outer_cache_disable(void)
-{
-	u32 tmp;
-	tmp = readl(SSCC);
-	tmp &= ~SSCC_ON;
-	writel(tmp, SSCC);
-}
-
-void enable_caches(void)
-{
-	dcache_enable();
-}
diff --git a/arch/arm/mach-uniphier/arm32/late_lowlevel_init.S b/arch/arm/mach-uniphier/arm32/late_lowlevel_init.S
index cce91df..6f40362 100644
--- a/arch/arm/mach-uniphier/arm32/late_lowlevel_init.S
+++ b/arch/arm/mach-uniphier/arm32/late_lowlevel_init.S
@@ -5,14 +5,10 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#include <config.h>
 #include <linux/linkage.h>
 
-#include "ssc-regs.h"
-
 ENTRY(lowlevel_init)
-	ldr	r1, = SSCC
-	ldr	r0, [r1]
-	bic	r0, r0, #SSCC_ON	@ L2 disable
-	str	r0, [r1]
-	mov	pc, lr
+	ldr	sp, = CONFIG_SYS_INIT_SP_ADDR
+	b	uniphier_cache_disable
 ENDPROC(lowlevel_init)
diff --git a/arch/arm/mach-uniphier/arm32/lowlevel_init.S b/arch/arm/mach-uniphier/arm32/lowlevel_init.S
index cc34116..af5ed1c 100644
--- a/arch/arm/mach-uniphier/arm32/lowlevel_init.S
+++ b/arch/arm/mach-uniphier/arm32/lowlevel_init.S
@@ -1,5 +1,7 @@
 /*
- * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2012-2015 Panasonic Corporation
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -9,8 +11,6 @@
 #include <linux/sizes.h>
 #include <asm/system.h>
 
-#include "ssc-regs.h"
-
 ENTRY(lowlevel_init)
 	mov	r8, lr			@ persevere link reg across call
 
@@ -25,10 +25,6 @@
 	orr	r0, r0, #(CR_C | CR_M)	@ enable MMU and Dcache
 	mcr	p15, 0, r0, c1, c0, 0
 
-#ifdef CONFIG_DEBUG_LL
-	bl	debug_ll_init
-#endif
-
 	bl	setup_init_ram		@ RAM area for stack and page table
 
 	/*
@@ -47,6 +43,10 @@
 
 	bl	enable_mmu
 
+#ifdef CONFIG_DEBUG_LL
+	bl	debug_ll_init
+#endif
+
 	mov	lr, r8			@ restore link
 	mov	pc, lr			@ back to my caller
 ENDPROC(lowlevel_init)
@@ -86,39 +86,42 @@
  */
 #define BOOT_RAM_SIZE	(SZ_32K)
 #define BOOT_RAM_BASE	((CONFIG_SPL_STACK) - (BOOT_RAM_SIZE))
-#define BOOT_WAY_BITS	(0x00000100)   /* way 8 */
+#define BOOT_RAM_WAYS	(0x00000100)	@ way 8
+
+#define SSCO_BASE		0x506c0000
+#define SSCOPE			0x244
+#define SSCOQM			0x248
+#define SSCOQAD			0x24c
+#define SSCOQSZ			0x250
+#define SSCOQWN			0x258
+#define SSCOPPQSEF		0x25c
+#define SSCOLPQS		0x260
 
 ENTRY(setup_init_ram)
-	/*
-	 * Touch to zero for the boot way
-	 */
-0:
-	/*
-	 * set SSCOQM, SSCOQAD, SSCOQSZ, SSCOQWN in this order
-	 */
-	ldr	r0, = 0x00408006	@ touch to zero with address range
-	ldr	r1, = SSCOQM
-	str	r0, [r1]
+	ldr	r1, = SSCO_BASE
+	mrc	p15, 0, r0, c2, c0, 0	@ TTBR0
+	ldr	r0, [r0, #0x400]	@ entry for virtual address 0x100*****
+	bfc	r0, #0, #20
+	cmp	r0, #0x50000000		@ is sLD3 page table?
+	biceq	r1, r1, #0xc0000000	@ sLD3 ROM maps 0x5******* to 0x1*******
+
+	/* Touch to zero for the boot way */
+0:	ldr	r0, = 0x00408006	@ touch to zero with address range
+	str	r0, [r1, #SSCOQM]
 	ldr	r0, = BOOT_RAM_BASE
-	ldr	r1, = SSCOQAD
-	str	r0, [r1]
+	str	r0, [r1, #SSCOQAD]
 	ldr	r0, = BOOT_RAM_SIZE
-	ldr	r1, = SSCOQSZ
-	str	r0, [r1]
-	ldr	r0, = BOOT_WAY_BITS
-	ldr	r1, = SSCOQWN
-	str	r0, [r1]
-	ldr	r1, = SSCOPPQSEF
-	ldr	r0, [r1]
+	str	r0, [r1, #SSCOQSZ]
+	ldr	r0, = BOOT_RAM_WAYS
+	str	r0, [r1, #SSCOQWN]
+	ldr	r0, [r1, #SSCOPPQSEF]
 	cmp	r0, #0			@ check if the command is successfully set
 	bne	0b			@ try again if an error occurs
 
-	ldr	r1, = SSCOLPQS
-1:
-	ldr	r0, [r1]
+1:	ldr	r0, [r1, #SSCOLPQS]
 	cmp	r0, #0x4
 	bne	1b			@ wait until the operation is completed
-	str	r0, [r1]		@ clear the complete notification flag
+	str	r0, [r1, #SSCOLPQS]	@ clear the complete notification flag
 
 	mov	pc, lr
 ENDPROC(setup_init_ram)
diff --git a/arch/arm/mach-uniphier/arm32/psci.c b/arch/arm/mach-uniphier/arm32/psci.c
new file mode 100644
index 0000000..633a3e0
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm32/psci.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/psci.h>
+#include <linux/sizes.h>
+#include <asm/processor.h>
+#include <asm/psci.h>
+#include <asm/secure.h>
+
+#include "../debug.h"
+#include "../soc-info.h"
+#include "arm-mpcore.h"
+#include "cache-uniphier.h"
+
+#define UNIPHIER_SMPCTRL_ROM_RSV2	0x59801208
+
+void uniphier_smp_trampoline(void);
+void uniphier_smp_trampoline_end(void);
+u32 uniphier_smp_booted[CONFIG_ARMV7_PSCI_NR_CPUS];
+
+static int uniphier_get_nr_cpus(void)
+{
+	switch (uniphier_get_soc_type()) {
+	case SOC_UNIPHIER_SLD3:
+	case SOC_UNIPHIER_PRO4:
+	case SOC_UNIPHIER_PRO5:
+		return 2;
+	case SOC_UNIPHIER_PXS2:
+	case SOC_UNIPHIER_LD6B:
+		return 4;
+	default:
+		return 1;
+	}
+}
+
+static void uniphier_smp_kick_all_cpus(void)
+{
+	const u32 target_ways = BIT(0);
+	size_t trmp_size;
+	u32 trmp_src = (unsigned long)uniphier_smp_trampoline;
+	u32 trmp_src_end = (unsigned long)uniphier_smp_trampoline_end;
+	u32 trmp_dest, trmp_dest_end;
+	int nr_cpus, i;
+	int timeout = 1000;
+
+	nr_cpus = uniphier_get_nr_cpus();
+	if (nr_cpus == 1)
+		return;
+
+	for (i = 0; i < nr_cpus; i++)	/* lock ways for all CPUs */
+		uniphier_cache_set_active_ways(i, 0);
+	uniphier_cache_inv_way(target_ways);
+	uniphier_cache_enable();
+
+	/* copy trampoline code */
+	uniphier_cache_prefetch_range(trmp_src, trmp_src_end, target_ways);
+
+	trmp_size = trmp_src_end - trmp_src;
+
+	trmp_dest = trmp_src & (SZ_64K - 1);
+	trmp_dest += SZ_1M - SZ_64K * 2;
+
+	trmp_dest_end = trmp_dest + trmp_size;
+
+	uniphier_cache_touch_range(trmp_dest, trmp_dest_end, target_ways);
+
+	writel(trmp_dest, UNIPHIER_SMPCTRL_ROM_RSV2);
+
+	asm("dsb	ishst\n" /* Ensure the write to ROM_RSV2 is visible */
+	    "sev"); /* Bring up all secondary CPUs from Boot ROM into U-Boot */
+
+	while (--timeout) {
+		int all_booted = 1;
+
+		for (i = 1; i < nr_cpus; i++)
+			if (!uniphier_smp_booted[i])
+				all_booted = 0;
+		if (all_booted)
+			break;
+		udelay(1);
+
+		/* barrier here because uniphier_smp_booted[] may be updated */
+		cpu_relax();
+	}
+
+	if (!timeout)
+		printf("warning: some of secondary CPUs may not boot\n");
+
+	uniphier_cache_disable();
+}
+
+void psci_board_init(void)
+{
+	unsigned long scu_base;
+	u32 scu_ctrl, tmp;
+
+	asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (scu_base));
+
+	scu_ctrl = readl(scu_base + 0x30);
+	if (!(scu_ctrl & 1))
+		writel(scu_ctrl | 0x1, scu_base + 0x30);
+
+	scu_ctrl = readl(scu_base + SCU_CTRL);
+	scu_ctrl |= SCU_ENABLE | SCU_STANDBY_ENABLE;
+	writel(scu_ctrl, scu_base + SCU_CTRL);
+
+	tmp = readl(scu_base + SCU_SNSAC);
+	tmp |= 0xfff;
+	writel(tmp, scu_base + SCU_SNSAC);
+
+	uniphier_smp_kick_all_cpus();
+}
+
+void psci_arch_init(void)
+{
+	u32 actlr;
+
+	asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (actlr));
+	actlr |= 0x41;		/* set SMP and FW bits */
+	asm("mcr p15, 0, %0, c1, c0, 1" : : "r" (actlr));
+}
+
+u32 uniphier_psci_holding_pen_release __secure_data = 0xffffffff;
+
+int __secure psci_cpu_on(u32 function_id, u32 cpuid, u32 entry_point)
+{
+	u32 cpu = cpuid & 0xff;
+
+	debug_puts("[U-Boot PSCI]  psci_cpu_on: cpuid=");
+	debug_puth(cpuid);
+	debug_puts(", entry_point=");
+	debug_puth(entry_point);
+	debug_puts("\n");
+
+	psci_save_target_pc(cpu, entry_point);
+
+	/* We assume D-cache is off, so do not call flush_dcache() here */
+	uniphier_psci_holding_pen_release = cpu;
+
+	/* Send an event to wake up the secondary CPU. */
+	asm("dsb	ishst\n"
+	    "sev");
+
+	return PSCI_RET_SUCCESS;
+}
diff --git a/arch/arm/mach-uniphier/arm32/psci_smp.S b/arch/arm/mach-uniphier/arm32/psci_smp.S
new file mode 100644
index 0000000..aa2fa5f
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm32/psci_smp.S
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <linux/linkage.h>
+#include <asm/system.h>
+
+	.section ._secure.text, "ax"
+
+ENTRY(uniphier_smp_trampoline)
+	ldr	r0, 0f
+	mrc	p15, 0, r1, c1, c0, 0	@ SCTLR (System Control Register)
+	orr	r1, r1, #CR_I		@ Enable ICache
+	bic	r1, r1, #(CR_C | CR_M)	@ Disable MMU and Dcache
+	mcr	p15, 0, r1, c1, c0, 0
+
+	bx	r0
+0:	.word	uniphier_secondary_startup
+	.globl	uniphier_smp_trampoline_end
+uniphier_smp_trampoline_end:
+ENDPROC(uniphier_smp_trampoline)
+
+LENTRY(uniphier_secondary_startup)
+	mrc	p15, 0, r1, c0, c0, 5	@ MPIDR (Multiprocessor Affinity Reg)
+	and	r1, r1, #0xff
+
+	ldr	r2, =uniphier_smp_booted
+	mov	r0, #1
+	str	r0, [r2, r1, lsl #2]
+
+	ldr	r2, =uniphier_psci_holding_pen_release
+pen:	ldr	r0, [r2]
+	cmp	r0, r1
+	beq	psci_cpu_entry
+	wfe
+	b	pen
+ENDPROC(uniphier_secondary_startup)
diff --git a/arch/arm/mach-uniphier/arm32/ssc-regs.h b/arch/arm/mach-uniphier/arm32/ssc-regs.h
deleted file mode 100644
index 02fca3b..0000000
--- a/arch/arm/mach-uniphier/arm32/ssc-regs.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * UniPhier System Cache (L2 Cache) registers
- *
- * Copyright (C) 2011-2014 Panasonic Corporation
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef ARCH_SSC_REGS_H
-#define ARCH_SSC_REGS_H
-
-#define SSCC			0x500c0000
-#define SSCC_BST		(0x1 << 20)
-#define SSCC_ACT		(0x1 << 19)
-#define SSCC_WTG		(0x1 << 18)
-#define SSCC_PRD		(0x1 << 17)
-#define SSCC_WBWA		(0x1 << 16)
-#define SSCC_EX			(0x1 << 13)
-#define SSCC_ON			(0x1 <<  0)
-
-#define SSCLPDAWCR		0x500c0030
-
-#define SSCOPE			0x506c0244
-#define SSCOPE_CM_SYNC		0x00000008
-
-#define SSCOQM			0x506c0248
-#define SSCOQM_TID_MASK		(0x3 << 21)
-#define SSCOQM_TID_BY_WAY	(0x2 << 21)
-#define SSCOQM_TID_BY_INST_WAY	(0x1 << 21)
-#define SSCOQM_TID_BY_DATA_WAY	(0x0 << 21)
-#define SSCOQM_S_MASK		(0x3 << 17)
-#define SSCOQM_S_WAY		(0x2 << 17)
-#define SSCOQM_S_ALL		(0x1 << 17)
-#define SSCOQM_S_ADDRESS	(0x0 << 17)
-#define SSCOQM_CE		(0x1 << 15)
-#define SSCOQM_CW		(0x1 << 14)
-#define SSCOQM_CM_MASK		(0x7)
-#define SSCOQM_CM_DIRT_TOUCH	(0x7)
-#define SSCOQM_CM_ZERO_TOUCH	(0x6)
-#define SSCOQM_CM_NORM_TOUCH	(0x5)
-#define SSCOQM_CM_PREF_FETCH	(0x4)
-#define SSCOQM_CM_SSC_FETCH	(0x3)
-#define SSCOQM_CM_WB_INV	(0x2)
-#define SSCOQM_CM_WB		(0x1)
-#define SSCOQM_CM_INV		(0x0)
-
-#define SSCOQAD			0x506c024c
-#define SSCOQSZ			0x506c0250
-#define SSCOQWN			0x506c0258
-
-#define SSCOPPQSEF		0x506c025c
-#define SSCOPPQSEF_FE		(0x1 << 1)
-#define SSCOPPQSEF_OE		(0x1 << 0)
-
-#define SSCOLPQS		0x506c0260
-#define SSCOLPQS_EF		(0x1 << 2)
-#define SSCOLPQS_EST		(0x1 << 1)
-#define SSCOLPQS_QST		(0x1 << 0)
-
-#define SSCOQCE0		0x506c0270
-
-#define SSC_LINE_SIZE		128
-#define SSC_RANGE_OP_MAX_SIZE	(0x00400000 - (SSC_LINE_SIZE))
-
-#endif  /* ARCH_SSC_REGS_H */
diff --git a/arch/arm/mach-uniphier/arm64/arm-cci500.c b/arch/arm/mach-uniphier/arm64/arm-cci500.c
index 607f96a..f18595d 100644
--- a/arch/arm/mach-uniphier/arm64/arm-cci500.c
+++ b/arch/arm/mach-uniphier/arm64/arm-cci500.c
@@ -1,13 +1,12 @@
 /*
  * Initialization of ARM Corelink CCI-500 Cache Coherency Interconnect
  *
- * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <common.h>
-#include <mapmem.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
 #include <linux/sizes.h>
@@ -28,13 +27,13 @@
 		void __iomem *base;
 		u32 tmp;
 
-		base = map_sysmem(slave_base, SZ_4K);
+		base = ioremap(slave_base, SZ_4K);
 
 		tmp = readl(base);
 		tmp |= CCI500_SNOOP_CTRL_EN_DVM | CCI500_SNOOP_CTRL_EN_SNOOP;
 		writel(tmp, base);
 
-		unmap_sysmem(base);
+		iounmap(base);
 
 		slave_base += CCI500_SLAVE_OFFSET;
 	}
diff --git a/arch/arm/mach-uniphier/arm64/mem_map.c b/arch/arm/mach-uniphier/arm64/mem_map.c
index 74ef919..67bc4f1 100644
--- a/arch/arm/mach-uniphier/arm64/mem_map.c
+++ b/arch/arm/mach-uniphier/arm64/mem_map.c
@@ -10,14 +10,16 @@
 
 static struct mm_region uniphier_mem_map[] = {
 	{
-		.base = 0x00000000,
+		.virt = 0x00000000,
+		.phys = 0x00000000,
 		.size = 0x80000000,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE |
 			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
 	},
 	{
-		.base = 0x80000000,
+		.virt = 0x80000000,
+		.phys = 0x80000000,
 		.size = 0xc0000000,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_INNER_SHARE
diff --git a/arch/arm/mach-uniphier/arm64/smp_kick_cpus.c b/arch/arm/mach-uniphier/arm64/smp_kick_cpus.c
index 5971ad2..4f08963 100644
--- a/arch/arm/mach-uniphier/arm64/smp_kick_cpus.c
+++ b/arch/arm/mach-uniphier/arm64/smp_kick_cpus.c
@@ -1,11 +1,10 @@
 /*
- * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <common.h>
-#include <mapmem.h>
 #include <linux/io.h>
 #include <linux/sizes.h>
 
@@ -18,11 +17,11 @@
 {
 	void __iomem *rom_boot_rsv0;
 
-	rom_boot_rsv0 = map_sysmem(UNIPHIER_SMPCTRL_ROM_RSV0, SZ_8);
+	rom_boot_rsv0 = ioremap(UNIPHIER_SMPCTRL_ROM_RSV0, SZ_8);
 
 	writeq((u64)uniphier_secondary_startup, rom_boot_rsv0);
 
-	unmap_sysmem(rom_boot_rsv0);
+	iounmap(rom_boot_rsv0);
 
 	uniphier_smp_setup();
 
diff --git a/arch/arm/mach-uniphier/arm64/timer.c b/arch/arm/mach-uniphier/arm64/timer.c
index 4beab9d..c10903a 100644
--- a/arch/arm/mach-uniphier/arm64/timer.c
+++ b/arch/arm/mach-uniphier/arm64/timer.c
@@ -1,11 +1,10 @@
 /*
- * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <common.h>
-#include <mapmem.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
 #include <linux/sizes.h>
@@ -21,7 +20,7 @@
 	void __iomem *base;
 	u32 tmp;
 
-	base = map_sysmem(CNT_CONTROL_BASE, SZ_4K);
+	base = ioremap(CNT_CONTROL_BASE, SZ_4K);
 
 	/*
 	 * Note:
@@ -32,7 +31,7 @@
 	tmp |= CNTCR_EN;
 	writel(tmp, base + CNTCR);
 
-	unmap_sysmem(base);
+	iounmap(base);
 
 	return 0;
 }
diff --git a/arch/arm/mach-uniphier/boards.c b/arch/arm/mach-uniphier/boards.c
index ed308f3..20093d8 100644
--- a/arch/arm/mach-uniphier/boards.c
+++ b/arch/arm/mach-uniphier/boards.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -38,7 +39,6 @@
 static const struct uniphier_board_data uniphier_ld4_data = {
 	.dram_freq = 1600,
 	.dram_nr_ch = 2,
-	.dram_ddr3plus = true,
 	.dram_ch[0] = {
 		.base = 0x80000000,
 		.size = 0x10000000,
@@ -49,6 +49,7 @@
 		.size = 0x10000000,
 		.width = 16,
 	},
+	.flags = UNIPHIER_BD_DDR3PLUS,
 };
 #endif
 
@@ -90,7 +91,6 @@
 static const struct uniphier_board_data uniphier_sld8_data = {
 	.dram_freq = 1333,
 	.dram_nr_ch = 2,
-	.dram_ddr3plus = true,
 	.dram_ch[0] = {
 		.base = 0x80000000,
 		.size = 0x10000000,
@@ -101,6 +101,7 @@
 		.size = 0x10000000,
 		.width = 16,
 	},
+	.flags = UNIPHIER_BD_DDR3PLUS,
 };
 #endif
 
@@ -202,6 +203,22 @@
 		.width = 32,
 	},
 };
+
+static const struct uniphier_board_data uniphier_ld21_data = {
+	.dram_freq = 1866,
+	.dram_nr_ch = 2,
+	.dram_ch[0] = {
+		.base = 0x80000000,
+		.size = 0x40000000,
+		.width = 32,
+	},
+	.dram_ch[1] = {
+		.base = 0xc0000000,
+		.size = 0x40000000,
+		.width = 32,
+	},
+	.flags = UNIPHIER_BD_PACKAGE_LD21,
+};
 #endif
 
 struct uniphier_board_id {
@@ -237,6 +254,7 @@
 	{ "socionext,ph1-ld11", &uniphier_ld11_data, },
 #endif
 #if defined(CONFIG_ARCH_UNIPHIER_LD20)
+	{ "socionext,ph1-ld21", &uniphier_ld21_data, },
 	{ "socionext,ph1-ld20", &uniphier_ld20_data, },
 #endif
 };
diff --git a/arch/arm/mach-uniphier/clk/clk-pxs2.c b/arch/arm/mach-uniphier/clk/clk-pxs2.c
index 76bf856..0d92405 100644
--- a/arch/arm/mach-uniphier/clk/clk-pxs2.c
+++ b/arch/arm/mach-uniphier/clk/clk-pxs2.c
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#include <linux/bitops.h>
 #include <linux/io.h>
 
 #include "../init.h"
@@ -32,12 +33,16 @@
 	tmp |= SC_RSTCTRL2_NRST_USB3B1;
 	writel(tmp, SC_RSTCTRL2);
 	readl(SC_RSTCTRL2); /* dummy read */
+
+	tmp = readl(SC_RSTCTRL6);
+	tmp |= 0x37;
+	writel(tmp, SC_RSTCTRL6);
 #endif
 
 	/* provide clocks */
 	tmp = readl(SC_CLKCTRL);
 #ifdef CONFIG_USB_XHCI_UNIPHIER
-	tmp |= SC_CLKCTRL_CEN_USB31 | SC_CLKCTRL_CEN_USB30 |
+	tmp |= BIT(20) | BIT(19) | SC_CLKCTRL_CEN_USB31 | SC_CLKCTRL_CEN_USB30 |
 		SC_CLKCTRL_CEN_GIO;
 #endif
 #ifdef CONFIG_UNIPHIER_ETH
diff --git a/arch/arm/mach-uniphier/debug.h b/arch/arm/mach-uniphier/debug.h
new file mode 100644
index 0000000..bc16f77
--- /dev/null
+++ b/arch/arm/mach-uniphier/debug.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DEBUG_H__
+#define __DEBUG_H__
+
+#include <linux/io.h>
+#include <linux/serial_reg.h>
+
+#define DEBUG_UART_BASE		0x54006800
+#define UART_SHIFT 2
+
+#define UNIPHIER_UART_TX		0
+#define UNIPHIER_UART_LSR		(5 * 4)
+
+/* All functions are inline so that they can be called from .secure section. */
+
+#ifdef DEBUG
+static inline void debug_putc(int c)
+{
+	void __iomem *base = (void __iomem *)DEBUG_UART_BASE;
+
+	while (!(readl(base + UNIPHIER_UART_LSR) & UART_LSR_THRE))
+		;
+
+	writel(c, base + UNIPHIER_UART_TX);
+}
+
+static inline void debug_puts(const char *s)
+{
+	while (*s) {
+		if (*s == '\n')
+			debug_putc('\r');
+
+		debug_putc(*s++);
+	}
+}
+
+static inline void debug_puth(unsigned long val)
+{
+	int i;
+	unsigned char c;
+
+	for (i = 8; i--; ) {
+		c = ((val >> (i * 4)) & 0xf);
+		c += (c >= 10) ? 'a' - 10 : '0';
+		debug_putc(c);
+	}
+}
+#else
+static inline void debug_putc(int c)
+{
+}
+
+static inline void debug_puts(const char *s)
+{
+}
+
+static inline void debug_puth(unsigned long val)
+{
+}
+#endif
+
+#endif /* __DEBUG_H__ */
diff --git a/arch/arm/mach-uniphier/dram/cmd_ddrphy.c b/arch/arm/mach-uniphier/dram/cmd_ddrphy.c
index 7a9f76c..0a5a73d 100644
--- a/arch/arm/mach-uniphier/dram/cmd_ddrphy.c
+++ b/arch/arm/mach-uniphier/dram/cmd_ddrphy.c
@@ -1,11 +1,12 @@
 /*
- * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2014      Panasonic Corporation
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #include <common.h>
-#include <mapmem.h>
 #include <linux/io.h>
 #include <linux/sizes.h>
 
@@ -51,7 +52,7 @@
 	int p, dx;
 
 	for (p = 0; *base; base++, p++) {
-		phy = map_sysmem(*base, SZ_4K);
+		phy = ioremap(*base, SZ_4K);
 
 		for (dx = 0; dx < NR_DATX8_PER_DDRPHY; dx++) {
 			printf("PHY%dDX%d:", p, dx);
@@ -59,7 +60,7 @@
 			printf("\n");
 		}
 
-		unmap_sysmem(phy);
+		iounmap(phy);
 	}
 }
 
@@ -172,7 +173,7 @@
 	printf("\n--- DDR PHY registers ---\n");
 
 	for (p = 0; *base; base++, p++) {
-		phy = map_sysmem(*base, SZ_4K);
+		phy = ioremap(*base, SZ_4K);
 
 		printf("== PHY%d (base: %p) ==\n", p, phy);
 		printf(" No: Name      : Address  : Data\n");
@@ -206,7 +207,7 @@
 		REG_DUMP(dx[1].gcr);
 		REG_DUMP(dx[1].gtr);
 
-		unmap_sysmem(phy);
+		iounmap(phy);
 	}
 }
 
diff --git a/arch/arm/mach-uniphier/dram/umc-ld4.c b/arch/arm/mach-uniphier/dram/umc-ld4.c
index fc75864..1ea6193 100644
--- a/arch/arm/mach-uniphier/dram/umc-ld4.c
+++ b/arch/arm/mach-uniphier/dram/umc-ld4.c
@@ -1,5 +1,7 @@
 /*
- * Copyright (C) 2011-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2011-2014 Panasonic Corporation
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -175,7 +177,7 @@
 	for (ch = 0; ch < DRAM_CH_NR; ch++) {
 		ret = umc_ch_init(dc_base, ca_base, bd->dram_freq,
 				  bd->dram_ch[ch].size,
-				  bd->dram_ddr3plus, ch);
+				  !!(bd->flags & UNIPHIER_BD_DDR3PLUS), ch);
 		if (ret) {
 			pr_err("failed to initialize UMC ch%d\n", ch);
 			return ret;
diff --git a/arch/arm/mach-uniphier/dram/umc-pro4.c b/arch/arm/mach-uniphier/dram/umc-pro4.c
index 853f561..f6c2d7f 100644
--- a/arch/arm/mach-uniphier/dram/umc-pro4.c
+++ b/arch/arm/mach-uniphier/dram/umc-pro4.c
@@ -1,5 +1,7 @@
 /*
- * Copyright (C) 2011-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2011-2014 Panasonic Corporation
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -170,7 +172,7 @@
 		ret = umc_ch_init(dc_base, ca_base, bd->dram_freq,
 				  bd->dram_ch[ch].size,
 				  bd->dram_ch[ch].width,
-				  bd->dram_ddr3plus);
+				  !!(bd->flags & UNIPHIER_BD_DDR3PLUS));
 		if (ret) {
 			pr_err("failed to initialize UMC ch%d\n", ch);
 			return ret;
diff --git a/arch/arm/mach-uniphier/dram/umc-sld8.c b/arch/arm/mach-uniphier/dram/umc-sld8.c
index e831766..61b1dc1 100644
--- a/arch/arm/mach-uniphier/dram/umc-sld8.c
+++ b/arch/arm/mach-uniphier/dram/umc-sld8.c
@@ -1,5 +1,7 @@
 /*
- * Copyright (C) 2011-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2011-2014 Panasonic Corporation
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -178,7 +180,7 @@
 	for (ch = 0; ch < DRAM_CH_NR; ch++) {
 		ret = umc_ch_init(dc_base, ca_base, bd->dram_freq,
 				  bd->dram_ch[ch].size,
-				  bd->dram_ddr3plus, ch);
+				  !!(bd->flags & UNIPHIER_BD_DDR3PLUS), ch);
 		if (ret) {
 			pr_err("failed to initialize UMC ch%d\n", ch);
 			return ret;
diff --git a/arch/arm/mach-uniphier/init.h b/arch/arm/mach-uniphier/init.h
index cba0bc9..db80074 100644
--- a/arch/arm/mach-uniphier/init.h
+++ b/arch/arm/mach-uniphier/init.h
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -20,8 +21,11 @@
 struct uniphier_board_data {
 	unsigned int dram_freq;
 	unsigned int dram_nr_ch;
-	bool dram_ddr3plus;
 	struct uniphier_dram_ch dram_ch[UNIPHIER_MAX_NR_DRAM_CH];
+	unsigned int flags;
+#define UNIPHIER_BD_DDR3PLUS		BIT(2)
+#define UNIPHIER_BD_PACKAGE_LD21	1
+#define UNIPHIER_BD_PACKAGE_TYPE(f)	((f) & 0x3)
 };
 
 const struct uniphier_board_data *uniphier_get_board_param(void);
diff --git a/arch/arm/mach-uniphier/sbc/sbc-regs.h b/arch/arm/mach-uniphier/sbc/sbc-regs.h
index a5dca74..673fb75 100644
--- a/arch/arm/mach-uniphier/sbc/sbc-regs.h
+++ b/arch/arm/mach-uniphier/sbc/sbc-regs.h
@@ -1,7 +1,8 @@
 /*
  * UniPhier SBC (System Bus Controller) registers
  *
- * Copyright (C) 2011-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2011-2014 Panasonic Corporation
+ * Copyright (C) 2015-2016 Socionext Inc.
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -75,7 +76,6 @@
 #define	SBCTRL74		(SBCTRL_BASE + 0x170)
 
 #define PC0CTRL				0x598000c0
-#define ROM_BOOT_ROMRSV2		0x59801208
 
 #ifndef __ASSEMBLY__
 #include <linux/io.h>
diff --git a/arch/arm/mach-uniphier/sc-regs.h b/arch/arm/mach-uniphier/sc-regs.h
index a095589..ad58e10 100644
--- a/arch/arm/mach-uniphier/sc-regs.h
+++ b/arch/arm/mach-uniphier/sc-regs.h
@@ -1,7 +1,9 @@
 /*
  * UniPhier SC (System Control) block registers
  *
- * Copyright (C) 2011-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2011-2015 Panasonic Corporation
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -68,6 +70,10 @@
 #define SC_RSTCTRL4_NRST_UMC31		(0x1 <<  5)	/* UMC ch1 */
 #define SC_RSTCTRL4_NRST_UMC30		(0x1 <<  4)	/* UMC ch0 */
 
+#define SC_RSTCTRL5			(SC_BASE_ADDR | 0x2010)
+
+#define SC_RSTCTRL6			(SC_BASE_ADDR | 0x2014)
+
 #define SC_CLKCTRL			(SC_BASE_ADDR | 0x2104)
 #define SC_CLKCTRL_CEN_USB31		(0x1 << 17)	/* USB3 #1 */
 #define SC_CLKCTRL_CEN_USB30		(0x1 << 16)	/* USB3 #0 */
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
index db3c579..a982320 100644
--- a/arch/arm/mach-zynq/Kconfig
+++ b/arch/arm/mach-zynq/Kconfig
@@ -17,4 +17,7 @@
 	  Based on this option include/configs/<CONFIG_SYS_CONFIG_NAME>.h header
 	  will be used for board configuration.
 
+config SYS_MALLOC_F_LEN
+	default 0x600
+
 endif
diff --git a/arch/m68k/cpu/mcf5227x/start.S b/arch/m68k/cpu/mcf5227x/start.S
index 13c036f..b5d51bd 100644
--- a/arch/m68k/cpu/mcf5227x/start.S
+++ b/arch/m68k/cpu/mcf5227x/start.S
@@ -28,52 +28,37 @@
 	rte;
 
 #if defined(CONFIG_CF_SBF)
-#define ASM_DRAMINIT	(asm_dram_init - CONFIG_SYS_TEXT_BASE + CONFIG_SYS_INIT_RAM_ADDR)
-#define ASM_SBF_IMG_HDR	(asm_sbf_img_hdr - CONFIG_SYS_TEXT_BASE + CONFIG_SYS_INIT_RAM_ADDR)
+#define ASM_DRAMINIT	(asm_dram_init - CONFIG_SYS_TEXT_BASE + \
+	CONFIG_SYS_INIT_RAM_ADDR)
+#define ASM_SBF_IMG_HDR	(asm_sbf_img_hdr - CONFIG_SYS_TEXT_BASE + \
+	CONFIG_SYS_INIT_RAM_ADDR)
 #endif
 
 .text
+
 /*
- *	Vector table. This is used for initial platform startup.
- *	These vectors are to catch any un-intended traps.
+ * Vector table. This is used for initial platform startup.
+ * These vectors are to catch any un-intended traps.
  */
 _vectors:
-
 #if defined(CONFIG_CF_SBF)
-INITSP:		.long	0		/* Initial SP	*/
-INITPC:		.long	ASM_DRAMINIT	/* Initial PC 	*/
+INITSP:	.long	0			/* Initial SP	*/
+INITPC:	.long	ASM_DRAMINIT		/* Initial PC 	*/
 #else
-INITSP:		.long	0	/* Initial SP	*/
-INITPC:		.long	_START	/* Initial PC 		*/
+INITSP:	.long	0			/* Initial SP	*/
+INITPC:	.long	_START			/* Initial PC 	*/
 #endif
 
-vector02:	.long	_FAULT	/* Access Error		*/
-vector03:	.long	_FAULT	/* Address Error	*/
-vector04:	.long	_FAULT	/* Illegal Instruction	*/
-vector05:	.long	_FAULT	/* Reserved		*/
-vector06:	.long	_FAULT	/* Reserved		*/
-vector07:	.long	_FAULT	/* Reserved		*/
-vector08:	.long	_FAULT	/* Privilege Violation	*/
-vector09:	.long	_FAULT	/* Trace		*/
-vector0A:	.long	_FAULT	/* Unimplemented A-Line	*/
-vector0B:	.long	_FAULT	/* Unimplemented F-Line	*/
-vector0C:	.long	_FAULT	/* Debug Interrupt	*/
-vector0D:	.long	_FAULT	/* Reserved		*/
-vector0E:	.long	_FAULT	/* Format Error		*/
-vector0F:	.long	_FAULT	/* Unitialized Int.	*/
+vector02_0F:
+.long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
+.long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 
 /* Reserved */
 vector10_17:
 .long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 
-vector18:	.long	_FAULT	/* Spurious Interrupt	*/
-vector19:	.long	_FAULT	/* Autovector Level 1	*/
-vector1A:	.long	_FAULT	/* Autovector Level 2	*/
-vector1B:	.long	_FAULT	/* Autovector Level 3	*/
-vector1C:	.long	_FAULT	/* Autovector Level 4	*/
-vector1D:	.long	_FAULT	/* Autovector Level 5	*/
-vector1E:	.long	_FAULT	/* Autovector Level 6	*/
-vector1F:	.long	_FAULT	/* Autovector Level 7	*/
+vector18_1F:
+.long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 
 #if !defined(CONFIG_CF_SBF)
 /* TRAP #0 - #15 */
@@ -120,15 +105,16 @@
 #if defined(CONFIG_CF_SBF)
 	/* Image header: chksum 4 bytes, len 4 bytes, img dest 4 bytes */
 asm_sbf_img_hdr:
-	.long	0x00000000	/* checksum, not yet implemented */
-	.long	0x00020000	/* image length */
+	.long	0x00000000		/* checksum, not yet implemented */
+	.long	0x00020000		/* image length */
 	.long	CONFIG_SYS_TEXT_BASE	/* image to be relocated at */
 
 asm_dram_init:
 	move.l	#(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_CTRL), %d0
-	movec	%d0, %RAMBAR1	/* init Rambar */
+	movec	%d0, %RAMBAR1		/* init Rambar */
+
 	move.l	#(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
-	clr.l %sp@-
+	clr.l	%sp@-
 
 	/* Must disable global address */
 	move.l	#0xFC008000, %a1
@@ -142,7 +128,6 @@
 	 * Dram Initialization
 	 * a1, a2, and d0
 	 */
-	/* mscr sdram */
 	move.l	#0xFC0A4074, %a1
 	move.b	#(CONFIG_SYS_SDRAM_DRV_STRENGTH), (%a1)
 	nop
@@ -336,15 +321,15 @@
 
 	move.b	(%a3), %d1
 	rts
-#endif			/* CONFIG_CF_SBF */
+#endif /* CONFIG_CF_SBF */
 
-	.text
+.text
 	. = 0x400
-	.globl	_start
+.globl _start
 _start:
 	nop
 	nop
-	move.w #0x2700,%sr		/* Mask off Interrupt */
+	move.w	#0x2700,%sr		/* Mask off Interrupt */
 
 	/* Set vector base register at the beginning of the Flash */
 #if defined(CONFIG_CF_SBF)
@@ -366,17 +351,17 @@
 	movec	%d0, %ACR1
 
 	/* initialize general use internal ram */
-	move.l #0, %d0
-	move.l #(ICACHE_STATUS), %a1	/* icache */
-	move.l #(DCACHE_STATUS), %a2	/* icache */
-	move.l %d0, (%a1)
-	move.l %d0, (%a2)
+	move.l	#0, %d0
+	move.l	#(ICACHE_STATUS), %a1	/* icache */
+	move.l	#(DCACHE_STATUS), %a2	/* icache */
+	move.l	%d0, (%a1)
+	move.l	%d0, (%a2)
 
 	/* put relocation table address to a5 */
-	move.l #__got_start, %a5
+	move.l	#__got_start, %a5
 
 	/* setup stack initially on top of internal static ram  */
-	move.l  #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
+	move.l	#(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
 
 	/*
 	 * if configured, malloc_f arena will be reserved first,
@@ -386,20 +371,23 @@
 	bsr	board_init_f_alloc_reserve
 
 	/* update stack and frame-pointers */
-	move.l  %d0, %sp
-	move.l  %sp, %fp
+	move.l	%d0, %sp
+	move.l	%sp, %fp
 
 	/* initialize reserved area */
-	move.l  %d0, -(%sp)
-	bsr     board_init_f_init_reserve
+	move.l	%d0, -(%sp)
+	bsr	board_init_f_init_reserve
 
-	bsr cpu_init_f			/* run low-level CPU init code (from flash) */
-	clr.l   %sp@-
-	bsr board_init_f		/* run low-level board init code (from flash) */
+	/* run low-level CPU init code (from flash) */
+	bsr	cpu_init_f
+	clr.l	%sp@-
+
+	/* run low-level board init code (from flash) */
+	bsr	board_init_f
 
 	/* board_init_f() does not return */
 
-/*------------------------------------------------------------------------------*/
+/******************************************************************************/
 
 /*
  * void relocate_code (addr_sp, gd, addr_moni)
@@ -412,23 +400,23 @@
  * r5 = length in bytes
  * r6 = cachelinesize
  */
-	.globl	relocate_code
+.globl relocate_code
 relocate_code:
-	link.w %a6,#0
-	move.l 8(%a6), %sp		/* set new stack pointer */
+	link.w	%a6,#0
+	move.l	8(%a6), %sp		/* set new stack pointer */
 
-	move.l 12(%a6), %d0		/* Save copy of Global Data pointer */
-	move.l 16(%a6), %a0		/* Save copy of Destination Address */
+	move.l	12(%a6), %d0		/* Save copy of Global Data pointer */
+	move.l	16(%a6), %a0		/* Save copy of Destination Address */
 
-	move.l #CONFIG_SYS_MONITOR_BASE, %a1
-	move.l #__init_end, %a2
-	move.l %a0, %a3
+	move.l	#CONFIG_SYS_MONITOR_BASE, %a1
+	move.l	#__init_end, %a2
+	move.l	%a0, %a3
 
 	/* copy the code to RAM */
 1:
-	move.l (%a1)+, (%a3)+
-	cmp.l  %a1,%a2
-	bgt.s	 1b
+	move.l	(%a1)+, (%a3)+
+	cmp.l	%a1,%a2
+	bgt.s	1b
 
 /*
  * We are done. Do not return, instead branch to second part of board
@@ -458,7 +446,7 @@
 	 */
 	move.l	%a0, %a1
 	add.l	#(__got_start - CONFIG_SYS_MONITOR_BASE),%a1
-	move.l	%a1,%a5			/* * fix got pointer register a5 */
+	move.l	%a1,%a5			/* fix got pointer register a5 */
 
 	move.l	%a0, %a2
 	add.l	#(__got_end - CONFIG_SYS_MONITOR_BASE),%a2
@@ -472,39 +460,40 @@
 	bne	7b
 
 	/* calculate relative jump to board_init_r in ram */
-	move.l %a0, %a1
-	add.l #(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1
+	move.l	%a0, %a1
+	add.l	#(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1
 
 	/* set parameters for board_init_r */
-	move.l %a0,-(%sp)		/* dest_addr */
-	move.l %d0,-(%sp)		/* gd */
+	move.l	%a0,-(%sp)		/* dest_addr */
+	move.l	%d0,-(%sp)		/* gd */
 	jsr	(%a1)
 
-/*------------------------------------------------------------------------------*/
+/******************************************************************************/
+
 /* exception code */
-	.globl _fault
+.globl _fault
 _fault:
-	bra _fault
-	.globl	_exc_handler
+	bra	_fault
 
+.globl _exc_handler
 _exc_handler:
 	SAVE_ALL
 	movel	%sp,%sp@-
-	bsr exc_handler
+	bsr	exc_handler
 	addql	#4,%sp
 	RESTORE_ALL
 
-	.globl	_int_handler
+.globl _int_handler
 _int_handler:
 	SAVE_ALL
 	movel	%sp,%sp@-
-	bsr int_handler
+	bsr	int_handler
 	addql	#4,%sp
 	RESTORE_ALL
 
-/*------------------------------------------------------------------------------*/
+/******************************************************************************/
 
-	.globl	version_string
+.globl version_string
 version_string:
-	.ascii U_BOOT_VERSION_STRING, "\0"
-	.align 4
+.ascii U_BOOT_VERSION_STRING, "\0"
+.align 4
diff --git a/arch/m68k/cpu/mcf523x/start.S b/arch/m68k/cpu/mcf523x/start.S
index 3aa4dd6..c4f6082 100644
--- a/arch/m68k/cpu/mcf523x/start.S
+++ b/arch/m68k/cpu/mcf523x/start.S
@@ -28,41 +28,25 @@
 	rte;
 
 .text
+
 /*
- *	Vector table. This is used for initial platform startup.
- *	These vectors are to catch any un-intended traps.
+ * Vector table. This is used for initial platform startup.
+ * These vectors are to catch any un-intended traps.
  */
 _vectors:
+INITSP:	.long	0x00000000		/* Initial SP	*/
+INITPC:	.long	_START			/* Initial PC	*/
 
-INITSP:		.long	0x00000000	/* Initial SP	*/
-INITPC:		.long	_START	/* Initial PC		*/
-vector02:	.long	_FAULT	/* Access Error		*/
-vector03:	.long	_FAULT	/* Address Error	*/
-vector04:	.long	_FAULT	/* Illegal Instruction	*/
-vector05:	.long	_FAULT	/* Reserved		*/
-vector06:	.long	_FAULT	/* Reserved		*/
-vector07:	.long	_FAULT	/* Reserved		*/
-vector08:	.long	_FAULT	/* Privilege Violation	*/
-vector09:	.long	_FAULT	/* Trace		*/
-vector0A:	.long	_FAULT	/* Unimplemented A-Line	*/
-vector0B:	.long	_FAULT	/* Unimplemented F-Line	*/
-vector0C:	.long	_FAULT	/* Debug Interrupt	*/
-vector0D:	.long	_FAULT	/* Reserved		*/
-vector0E:	.long	_FAULT	/* Format Error		*/
-vector0F:	.long	_FAULT	/* Unitialized Int.	*/
+vector02_0F:
+.long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
+.long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 
 /* Reserved */
 vector10_17:
 .long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 
-vector18:	.long	_FAULT	/* Spurious Interrupt	*/
-vector19:	.long	_FAULT	/* Autovector Level 1	*/
-vector1A:	.long	_FAULT	/* Autovector Level 2	*/
-vector1B:	.long	_FAULT	/* Autovector Level 3	*/
-vector1C:	.long	_FAULT	/* Autovector Level 4	*/
-vector1D:	.long	_FAULT	/* Autovector Level 5	*/
-vector1E:	.long	_FAULT	/* Autovector Level 6	*/
-vector1F:	.long	_FAULT	/* Autovector Level 7	*/
+vector18_1F:
+.long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 
 /* TRAP #0 - #15 */
 vector20_2F:
@@ -104,13 +88,13 @@
 .long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 .long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 
-	.text
+.text
 
-	.globl	_start
+.globl _start
 _start:
 	nop
 	nop
-	move.w #0x2700,%sr	/* Mask off Interrupt */
+	move.w	#0x2700,%sr		/* Mask off Interrupt */
 
 	/* Set vector base register at the beginning of the Flash */
 	move.l	#CONFIG_SYS_FLASH_BASE, %d0
@@ -120,22 +104,22 @@
 	movec	%d0, %RAMBAR1
 
 	/* invalidate and disable cache */
-	move.l	#CF_CACR_CINV, %d0		/* Invalidate cache cmd */
-	movec	%d0, %CACR			/* Invalidate cache */
+	move.l	#CF_CACR_CINV, %d0	/* Invalidate cache cmd */
+	movec	%d0, %CACR		/* Invalidate cache */
 	nop
 	move.l	#0, %d0
 	movec	%d0, %ACR0
 	movec	%d0, %ACR1
 
 	/* initialize general use internal ram */
-	move.l #0, %d0
-	move.l #(ICACHE_STATUS), %a1	/* icache */
-	move.l #(DCACHE_STATUS), %a2	/* icache */
-	move.l %d0, (%a1)
-	move.l %d0, (%a2)
+	move.l	#0, %d0
+	move.l	#(ICACHE_STATUS), %a1	/* icache */
+	move.l	#(DCACHE_STATUS), %a2	/* icache */
+	move.l	%d0, (%a1)
+	move.l	%d0, (%a2)
 
 	/* put relocation table address to a5 */
-	move.l #__got_start, %a5
+	move.l	#__got_start, %a5
 
 	/* setup stack initially on top of internal static ram  */
 	move.l  #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
@@ -149,25 +133,26 @@
 	jsr	(%a1)
 
 	/* update stack and frame-pointers */
-	move.l  %d0, %sp
-	move.l  %sp, %fp
+	move.l	%d0, %sp
+	move.l	%sp, %fp
 
 	/* initialize reserved area */
-	move.l  %d0, -(%sp)
+	move.l	%d0, -(%sp)
 	move.l	#board_init_f_init_reserve, %a1
 	jsr	(%a1)
 
 	/* run low-level CPU init code (from flash) */
-	move.l #cpu_init_f, %a1
-	jsr (%a1)
+	move.l	#cpu_init_f, %a1
+	jsr	(%a1)
+
 	/* run low-level board init code (from flash) */
-	clr.l   %sp@-
-	move.l #board_init_f, %a1
-	jsr (%a1)
+	clr.l	%sp@-
+	move.l	#board_init_f, %a1
+	jsr	(%a1)
 
 	/* board_init_f() does not return */
 
-/*------------------------------------------------------------------------------*/
+/******************************************************************************/
 
 /*
  * void relocate_code (addr_sp, gd, addr_moni)
@@ -180,23 +165,23 @@
  * r5 = length in bytes
  * r6 = cachelinesize
  */
-	.globl	relocate_code
+.globl relocate_code
 relocate_code:
-	link.w %a6,#0
-	move.l 8(%a6), %sp		/* set new stack pointer */
+	link.w	%a6,#0
+	move.l	8(%a6), %sp		/* set new stack pointer */
 
-	move.l 12(%a6), %d0		/* Save copy of Global Data pointer */
-	move.l 16(%a6), %a0		/* Save copy of Destination Address */
+	move.l	12(%a6), %d0		/* Save copy of Global Data pointer */
+	move.l	16(%a6), %a0		/* Save copy of Destination Address */
 
-	move.l #CONFIG_SYS_MONITOR_BASE, %a1
-	move.l #__init_end, %a2
-	move.l %a0, %a3
+	move.l	#CONFIG_SYS_MONITOR_BASE, %a1
+	move.l	#__init_end, %a2
+	move.l	%a0, %a3
 
 	/* copy the code to RAM */
 1:
-	move.l (%a1)+, (%a3)+
-	cmp.l  %a1,%a2
-	bgt.s	 1b
+	move.l	(%a1)+, (%a3)+
+	cmp.l	%a1,%a2
+	bgt.s	1b
 
 /*
  * We are done. Do not return, instead branch to second part of board
@@ -240,39 +225,40 @@
 	bne	7b
 
 	/* calculate relative jump to board_init_r in ram */
-	move.l %a0, %a1
-	add.l #(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1
+	move.l	%a0, %a1
+	add.l	#(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1
 
 	/* set parameters for board_init_r */
-	move.l %a0,-(%sp)		/* dest_addr */
-	move.l %d0,-(%sp)		/* gd */
+	move.l	%a0,-(%sp)		/* dest_addr */
+	move.l	%d0,-(%sp)		/* gd */
 	jsr	(%a1)
 
-/*------------------------------------------------------------------------------*/
+/******************************************************************************/
+
 /* exception code */
-	.globl _fault
+.globl _fault
 _fault:
-	bra _fault
-	.globl	_exc_handler
+	bra	_fault
 
+.globl _exc_handler
 _exc_handler:
 	SAVE_ALL
 	movel	%sp,%sp@-
-	bsr exc_handler
+	bsr	exc_handler
 	addql	#4,%sp
 	RESTORE_ALL
 
-	.globl	_int_handler
+.globl _int_handler
 _int_handler:
 	SAVE_ALL
 	movel	%sp,%sp@-
-	bsr int_handler
+	bsr	int_handler
 	addql	#4,%sp
 	RESTORE_ALL
 
-/*------------------------------------------------------------------------------*/
+/******************************************************************************/
 
-	.globl	version_string
+.globl version_string
 version_string:
-	.ascii U_BOOT_VERSION_STRING, "\0"
-	.align 4
+.ascii U_BOOT_VERSION_STRING, "\0"
+.align 4
diff --git a/arch/m68k/cpu/mcf52x2/start.S b/arch/m68k/cpu/mcf52x2/start.S
index a048884..9837c41 100644
--- a/arch/m68k/cpu/mcf52x2/start.S
+++ b/arch/m68k/cpu/mcf52x2/start.S
@@ -34,12 +34,12 @@
 #if !defined(CONFIG_MONITOR_IS_IN_RAM)
 
 .text
+
 /*
- *	Vector table. This is used for initial platform startup.
- *	These vectors are to catch any un-intended traps.
+ * Vector table. This is used for initial platform startup.
+ * These vectors are to catch any un-intended traps.
  */
 _vectors:
-
 .long	0x00000000		/* Flash offset is 0 until we setup CS0 */
 #if defined(CONFIG_M5282) && (CONFIG_SYS_TEXT_BASE == CONFIG_SYS_INT_FLASH_BASE)
 .long	_start - CONFIG_SYS_TEXT_BASE
@@ -85,24 +85,24 @@
 
 #endif
 
-	.text
-
+.text
 
 #if defined(CONFIG_SYS_INT_FLASH_BASE) && \
     (defined(CONFIG_M5282) || defined(CONFIG_M5281))
-	#if (CONFIG_SYS_TEXT_BASE == CONFIG_SYS_INT_FLASH_BASE)
-		.long	0x55AA55AA,0xAA55AA55 /* CFM Backdoorkey */
-		.long	0xFFFFFFFF /* all sectors protected */
-		.long	0x00000000 /* supervisor/User restriction */
-		.long	0x00000000 /* programm/data space restriction */
-		.long	0x00000000 /* Flash security */
-	#endif
+#if (CONFIG_SYS_TEXT_BASE == CONFIG_SYS_INT_FLASH_BASE)
+.long	0x55AA55AA,0xAA55AA55		/* CFM Backdoorkey */
+.long	0xFFFFFFFF			/* all sectors protected */
+.long	0x00000000			/* supervisor/User restriction */
+.long	0x00000000			/* programm/data space restriction */
+.long	0x00000000			/* Flash security */
+#endif
 #endif
-	.globl	_start
+
+.globl _start
 _start:
 	nop
 	nop
-	move.w #0x2700,%sr
+	move.w	#0x2700,%sr
 
 #if defined(CONFIG_M5208)
 	/* Initialize RAMBAR: locate SRAM and validate it */
@@ -111,22 +111,24 @@
 #endif
 
 #if defined(CONFIG_M5272) || defined(CONFIG_M5249) || defined(CONFIG_M5253)
-	move.l	#(CONFIG_SYS_MBAR + 1), %d0		/* set MBAR address + valid flag */
+	/* set MBAR address + valid flag */
+	move.l	#(CONFIG_SYS_MBAR + 1), %d0
 	move.c	%d0, %MBAR
 
 	/*** The 5249 has MBAR2 as well ***/
 #ifdef CONFIG_SYS_MBAR2
-	move.l	#(CONFIG_SYS_MBAR2 + 1), %d0	        /* Get MBAR2 address */
-	movec	%d0, #0xc0e		        /* Set MBAR2 */
+	/* Get MBAR2 address */
+	move.l	#(CONFIG_SYS_MBAR2 + 1), %d0
+	 /* Set MBAR2 */
+	movec	%d0, #0xc0e
 #endif
-
 	move.l	#(CONFIG_SYS_INIT_RAM_ADDR + 1), %d0
 	movec	%d0, %RAMBAR0
 #endif /* CONFIG_M5272 || CONFIG_M5249 || CONFIG_M5253 */
 
 #if defined(CONFIG_M5282) || defined(CONFIG_M5271)
-	/* Initialize IPSBAR */
-	move.l	#(CONFIG_SYS_MBAR + 1), %d0		/* set IPSBAR address + valid flag */
+	/* set MBAR address + valid flag */
+	move.l	#(CONFIG_SYS_MBAR + 1), %d0
 	move.l	%d0, 0x40000000
 
 	/* Initialize RAMBAR1: locate SRAM and validate it */
@@ -135,22 +137,24 @@
 
 #if defined(CONFIG_M5282)
 #if (CONFIG_SYS_TEXT_BASE == CONFIG_SYS_INT_FLASH_BASE)
-	/* Setup code in SRAM to initialize FLASHBAR, if start from internal Flash */
-
-	move.l #(_flashbar_setup-CONFIG_SYS_INT_FLASH_BASE), %a0
-	move.l #(_flashbar_setup_end-CONFIG_SYS_INT_FLASH_BASE), %a1
-	move.l #(CONFIG_SYS_INIT_RAM_ADDR), %a2
+	/*
+	 * Setup code in SRAM to initialize FLASHBAR,
+	 * if start from internal Flash
+	 */
+	move.l	#(_flashbar_setup-CONFIG_SYS_INT_FLASH_BASE), %a0
+	move.l	#(_flashbar_setup_end-CONFIG_SYS_INT_FLASH_BASE), %a1
+	move.l	#(CONFIG_SYS_INIT_RAM_ADDR), %a2
 _copy_flash:
-	move.l (%a0)+, (%a2)+
-	cmp.l %a0, %a1
-	bgt.s _copy_flash
-	jmp CONFIG_SYS_INIT_RAM_ADDR
+	move.l	(%a0)+, (%a2)+
+	cmp.l	%a0, %a1
+	bgt.s	_copy_flash
+	jmp	CONFIG_SYS_INIT_RAM_ADDR
 
 _flashbar_setup:
 	/* Initialize FLASHBAR: locate internal Flash and validate it */
 	move.l	#(CONFIG_SYS_INT_FLASH_BASE + CONFIG_SYS_INT_FLASH_ENABLE), %d0
 	movec	%d0, %FLASHBAR
-	jmp _after_flashbar_copy.L	/* Force jump to absolute address */
+	jmp	_after_flashbar_copy.L	/* Force jump to absolute address */
 _flashbar_setup_end:
 	nop
 _after_flashbar_copy:
@@ -162,7 +166,8 @@
 
 #endif
 #endif
-	/* if we come from a pre-loader we have no exception table and
+	/*
+	 * if we come from a pre-loader we have no exception table and
 	 * therefore no VBR to set
 	 */
 #if !defined(CONFIG_MONITOR_IS_IN_RAM)
@@ -175,8 +180,8 @@
 #endif
 
 #ifdef CONFIG_M5275
-	/* Initialize IPSBAR */
-	move.l	#(CONFIG_SYS_MBAR + 1), %d0		/* set IPSBAR address + valid flag */
+	/* set MBAR address + valid flag */
+	move.l	#(CONFIG_SYS_MBAR + 1), %d0
 	move.l	%d0, 0x40000000
 /*	movec	%d0, %MBAR */
 
@@ -186,17 +191,17 @@
 #endif
 
 	/* initialize general use internal ram */
-	move.l #0, %d0
-	move.l #(ICACHE_STATUS), %a1	/* icache */
-	move.l #(DCACHE_STATUS), %a2	/* icache */
-	move.l %d0, (%a1)
-	move.l %d0, (%a2)
+	move.l	#0, %d0
+	move.l	#(ICACHE_STATUS), %a1	/* icache */
+	move.l	#(DCACHE_STATUS), %a2	/* icache */
+	move.l	%d0, (%a1)
+	move.l	%d0, (%a2)
 
 	/* put relocation table address to a5 */
-	move.l #__got_start, %a5
+	move.l	#__got_start, %a5
 
 	/* setup stack initially on top of internal static ram  */
-	move.l  #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
+	move.l	#(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
 
 	/*
 	 * if configured, malloc_f arena will be reserved first,
@@ -204,28 +209,29 @@
 	 */
 	move.l	%sp, -(%sp)
 	move.l	#board_init_f_alloc_reserve, %a1
-	jsr (%a1)
+	jsr	(%a1)
 
 	/* update stack and frame-pointers */
-	move.l  %d0, %sp
-	move.l  %sp, %fp
+	move.l	%d0, %sp
+	move.l	%sp, %fp
 
 	/* initialize reserved area */
-	move.l  %d0, -(%sp)
+	move.l	%d0, -(%sp)
 	move.l	#board_init_f_init_reserve, %a1
-	jsr (%a1)
+	jsr	(%a1)
 
 	/* run low-level CPU init code (from flash) */
-	move.l #cpu_init_f, %a1
-	jsr (%a1)
+	move.l	#cpu_init_f, %a1
+	jsr	(%a1)
+
 	/* run low-level board init code (from flash) */
-	clr.l   %sp@-
-	move.l #board_init_f, %a1
-	jsr (%a1)
+	clr.l	%sp@-
+	move.l	#board_init_f, %a1
+	jsr	(%a1)
 
 	/* board_init_f() does not return */
 
-/*------------------------------------------------------------------------------*/
+/******************************************************************************/
 
 /*
  * void relocate_code (addr_sp, gd, addr_moni)
@@ -238,22 +244,22 @@
  * r5 = length in bytes
  * r6 = cachelinesize
  */
-	.globl	relocate_code
+.globl relocate_code
 relocate_code:
-	link.w %a6,#0
-	move.l 8(%a6), %sp		/* set new stack pointer */
+	link.w	%a6,#0
+	move.l	8(%a6), %sp		/* set new stack pointer */
 
-	move.l 12(%a6), %d0		/* Save copy of Global Data pointer */
-	move.l 16(%a6), %a0		/* Save copy of Destination Address */
+	move.l	12(%a6), %d0		/* Save copy of Global Data pointer */
+	move.l	16(%a6), %a0		/* Save copy of Destination Address */
 
-	move.l #CONFIG_SYS_MONITOR_BASE, %a1
-	move.l #__init_end, %a2
-	move.l %a0, %a3
+	move.l	#CONFIG_SYS_MONITOR_BASE, %a1
+	move.l	#__init_end, %a2
+	move.l	%a0, %a3
 	/* copy the code to RAM */
 1:
-	move.l (%a1)+, (%a3)+
-	cmp.l  %a1,%a2
-	bgt.s	 1b
+	move.l	(%a1)+, (%a3)+
+	cmp.l	%a1,%a2
+	bgt.s	1b
 
 /*
  * We are done. Do not return, instead branch to second part of board
@@ -283,7 +289,7 @@
 	 */
 	move.l	%a0, %a1
 	add.l	#(__got_start - CONFIG_SYS_MONITOR_BASE),%a1
-	move.l	%a1,%a5		/* * fix got pointer register a5 */
+	move.l	%a1,%a5			/* fix got pointer register a5 */
 
 	move.l	%a0, %a2
 	add.l	#(__got_end - CONFIG_SYS_MONITOR_BASE),%a2
@@ -297,43 +303,44 @@
 	bne	7b
 
 	/* calculate relative jump to board_init_r in ram */
-	move.l %a0, %a1
-	add.l #(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1
+	move.l	%a0, %a1
+	add.l	#(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1
 
 	/* set parameters for board_init_r */
-	move.l %a0,-(%sp)		/* dest_addr */
-	move.l %d0,-(%sp)		/* gd */
+	move.l	%a0,-(%sp)		/* dest_addr */
+	move.l	%d0,-(%sp)		/* gd */
 #if defined(DEBUG) && (CONFIG_SYS_TEXT_BASE != CONFIG_SYS_INT_FLASH_BASE) && \
     defined(CONFIG_SYS_HALT_BEFOR_RAM_JUMP)
 	halt
 #endif
 	jsr	(%a1)
 
-/*------------------------------------------------------------------------------*/
+/******************************************************************************/
+
 /* exception code */
-	.globl _fault
+.globl _fault
 _fault:
-	bra _fault
+	bra	_fault
 
-	.globl	_exc_handler
+.globl _exc_handler
 _exc_handler:
 	SAVE_ALL
 	movel	%sp,%sp@-
-	bsr exc_handler
+	bsr	exc_handler
 	addql	#4,%sp
 	RESTORE_ALL
 
-	.globl	_int_handler
+.globl _int_handler
 _int_handler:
 	SAVE_ALL
 	movel	%sp,%sp@-
-	bsr int_handler
+	bsr	int_handler
 	addql	#4,%sp
 	RESTORE_ALL
 
-/*------------------------------------------------------------------------------*/
+/******************************************************************************/
 
-	.globl	version_string
+.globl version_string
 version_string:
-	.ascii U_BOOT_VERSION_STRING, "\0"
-	.align 4
+.ascii U_BOOT_VERSION_STRING, "\0"
+.align 4
diff --git a/arch/m68k/cpu/mcf530x/start.S b/arch/m68k/cpu/mcf530x/start.S
index ca8bb32..da41c9a 100644
--- a/arch/m68k/cpu/mcf530x/start.S
+++ b/arch/m68k/cpu/mcf530x/start.S
@@ -36,12 +36,12 @@
 #if !defined(CONFIG_MONITOR_IS_IN_RAM)
 
 .text
+
 /*
- *	Vector table. This is used for initial platform startup.
- *	These vectors are to catch any un-intended traps.
+ * Vector table. This is used for initial platform startup.
+ * These vectors are to catch any un-intended traps.
  */
 _vectors:
-
 /* Flash offset is 0 until we setup CS0 */
 .long	0x00000000
 #if defined(CONFIG_M5307) && \
@@ -89,12 +89,13 @@
 
 #endif
 
-	.text
-	.globl	_start
+.text
+
+.globl _start
 _start:
 	nop
 	nop
-	move.w  #0x2700,%sr
+	move.w	#0x2700,%sr
 
 	/* set MBAR address + valid flag */
 	move.l	#(CONFIG_SYS_MBAR + 1), %d0
@@ -104,11 +105,11 @@
 	move.c	%d0, %RAMBAR
 
 	/* DS 4.8.2 (Cache Organization) invalidate and disable cache */
-        move.l  #CF_CACR_CINVA, %d0
-        movec   %d0, %CACR
-        move.l  #0, %d0
-        movec   %d0, %ACR0
-        movec   %d0, %ACR1
+        move.l	#CF_CACR_CINVA, %d0
+        movec	%d0, %CACR
+        move.l	#0, %d0
+        movec	%d0, %ACR0
+        movec	%d0, %ACR1
 
 	/*
 	 * if we come from a pre-loader we have no exception table and
@@ -127,10 +128,10 @@
 	move.l	%d0, (%a2)
 
 	/* put relocation table address to a5 */
-	move.l #__got_start, %a5
+	move.l	#__got_start, %a5
 
 	/* setup stack initially on top of internal static ram  */
-	move.l  #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
+	move.l	#(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
 
 	/*
 	 * if configured, malloc_f arena will be reserved first,
@@ -140,23 +141,23 @@
 	bsr	board_init_f_alloc_reserve
 
 	/* update stack and frame-pointers */
-	move.l  %d0, %sp
-	move.l  %sp, %fp
+	move.l	%d0, %sp
+	move.l	%sp, %fp
 
 	/* initialize reserved area */
-	move.l  %d0, -(%sp)
-	bsr     board_init_f_init_reserve
+	move.l	%d0, -(%sp)
+	bsr	board_init_f_init_reserve
 
 	/* run low-level CPU init code (from flash) */
-	bsr cpu_init_f
+	bsr	cpu_init_f
 
 	/* run low-level board init code (from flash) */
-	clr.l   %sp@-
-	bsr board_init_f
+	clr.l	%sp@-
+	bsr	board_init_f
 
 	/* board_init_f() does not return */
 
-/*--------------------------------------------------------------------------*/
+/******************************************************************************/
 
 /*
  * void relocate_code (addr_sp, gd, addr_moni)
@@ -165,7 +166,7 @@
  * after relocating the monitor code.
  *
  */
-	.globl	relocate_code
+.globl relocate_code
 relocate_code:
 	link.w	%a6,#0
 	move.l	8(%a6), %sp	/* set new stack pointer */
@@ -209,7 +210,8 @@
 	 */
 	move.l	%a0, %a1
 	add.l	#(__got_start - CONFIG_SYS_MONITOR_BASE), %a1
-	/* * fix got pointer register a5 */
+
+	/* fix got pointer register a5 */
 	move.l	%a1,%a5
 
 	move.l	%a0, %a2
@@ -236,33 +238,34 @@
 #endif
 	jsr	(%a1)
 
-/*--------------------------------------------------------------------------*/
+/******************************************************************************/
+
 /* exception code */
-	.globl _fault
+.globl _fault
 _fault:
 	bra	_fault
 
-	.globl	_exc_handler
+.globl _exc_handler
 _exc_handler:
 	SAVE_ALL
 	movel	%sp,%sp@-
-	bsr 	exc_handler
+	bsr	exc_handler
 	addql	#4,%sp
 	RESTORE_ALL
 
-	.globl	_int_handler
+.globl _int_handler
 _int_handler:
 	SAVE_ALL
 	movel	%sp,%sp@-
-	bsr 	int_handler
+	bsr	int_handler
 	addql	#4,%sp
 	RESTORE_ALL
 
-/*--------------------------------------------------------------------------*/
+/******************************************************************************/
 
-	.globl	version_string
+.globl version_string
 version_string:
-	.ascii	U_BOOT_VERSION
-	.ascii	" (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
-	.ascii	CONFIG_IDENT_STRING, "\0"
-	.align	4
+.ascii	U_BOOT_VERSION
+.ascii	" (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
+.ascii	CONFIG_IDENT_STRING, "\0"
+.align	4
diff --git a/arch/m68k/cpu/mcf532x/start.S b/arch/m68k/cpu/mcf532x/start.S
index f25bc54..302fca5 100644
--- a/arch/m68k/cpu/mcf532x/start.S
+++ b/arch/m68k/cpu/mcf532x/start.S
@@ -31,42 +31,27 @@
 	rte;
 
 #if !defined(CONFIG_MONITOR_IS_IN_RAM)
+
 .text
+
 /*
- *	Vector table. This is used for initial platform startup.
- *	These vectors are to catch any un-intended traps.
+ * Vector table. This is used for initial platform startup.
+ * These vectors are to catch any un-intended traps.
  */
 _vectors:
+INITSP:	.long	0x00000000		/* Initial SP	*/
+INITPC:	.long	_START			/* Initial PC		*/
 
-INITSP:		.long	0x00000000	/* Initial SP	*/
-INITPC:		.long	_START	/* Initial PC		*/
-vector02:	.long	_FAULT	/* Access Error		*/
-vector03:	.long	_FAULT	/* Address Error	*/
-vector04:	.long	_FAULT	/* Illegal Instruction	*/
-vector05:	.long	_FAULT	/* Reserved		*/
-vector06:	.long	_FAULT	/* Reserved		*/
-vector07:	.long	_FAULT	/* Reserved		*/
-vector08:	.long	_FAULT	/* Privilege Violation	*/
-vector09:	.long	_FAULT	/* Trace		*/
-vector0A:	.long	_FAULT	/* Unimplemented A-Line	*/
-vector0B:	.long	_FAULT	/* Unimplemented F-Line	*/
-vector0C:	.long	_FAULT	/* Debug Interrupt	*/
-vector0D:	.long	_FAULT	/* Reserved		*/
-vector0E:	.long	_FAULT	/* Format Error		*/
-vector0F:	.long	_FAULT	/* Unitialized Int.	*/
+vector02_0F:
+.long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
+.long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 
 /* Reserved */
 vector10_17:
 .long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 
-vector18:	.long	_FAULT	/* Spurious Interrupt	*/
-vector19:	.long	_FAULT	/* Autovector Level 1	*/
-vector1A:	.long	_FAULT	/* Autovector Level 2	*/
-vector1B:	.long	_FAULT	/* Autovector Level 3	*/
-vector1C:	.long	_FAULT	/* Autovector Level 4	*/
-vector1D:	.long	_FAULT	/* Autovector Level 5	*/
-vector1E:	.long	_FAULT	/* Autovector Level 6	*/
-vector1F:	.long	_FAULT	/* Autovector Level 7	*/
+vector18_1F:
+.long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 
 /* TRAP #0 - #15 */
 vector20_2F:
@@ -109,13 +94,13 @@
 .long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 #endif /* !defined(CONFIG_MONITOR_IS_IN_RAM) */
 
-	.text
+.text
 
-	.globl	_start
+.globl _start
 _start:
 	nop
 	nop
-	move.w #0x2700,%sr	/* Mask off Interrupt */
+	move.w	#0x2700,%sr	/* Mask off Interrupt */
 
 #if !defined(CONFIG_MONITOR_IS_IN_RAM)
 	/* Set vector base register at the beginning of the Flash */
@@ -142,14 +127,14 @@
 #endif
 
 	/* initialize general use internal ram */
-	move.l #0, %d0
-	move.l #(ICACHE_STATUS), %a1	/* icache */
-	move.l #(DCACHE_STATUS), %a2	/* icache */
-	move.l %d0, (%a1)
-	move.l %d0, (%a2)
+	move.l	#0, %d0
+	move.l	#(ICACHE_STATUS), %a1	/* icache */
+	move.l	#(DCACHE_STATUS), %a2	/* icache */
+	move.l	%d0, (%a1)
+	move.l	%d0, (%a2)
 
 	/* put relocation table address to a5 */
-	move.l #__got_start, %a5
+	move.l	#__got_start, %a5
 
 	/* setup stack initially on top of internal static ram  */
 	move.l  #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
@@ -167,13 +152,14 @@
 	move.l  %sp, %fp
 
 	/* initialize reserved area */
-	move.l  %d0, -(%sp)
+	move.l	%d0, -(%sp)
 	move.l	#board_init_f_init_reserve, %a1
 	jsr	(%a1)
 
 	/* run low-level CPU init code (from flash) */
-	move.l #cpu_init_f, %a1
-	jsr (%a1)
+	move.l	#cpu_init_f, %a1
+	jsr	(%a1)
+
 	/* run low-level board init code (from flash) */
 	clr.l   %sp@-
 	move.l #board_init_f, %a1
@@ -181,7 +167,7 @@
 
 	/* board_init_f() does not return */
 
-/*------------------------------------------------------------------------------*/
+/******************************************************************************/
 
 /*
  * void relocate_code (addr_sp, gd, addr_moni)
@@ -194,23 +180,23 @@
  * r5 = length in bytes
  * r6 = cachelinesize
  */
-	.globl	relocate_code
+.globl relocate_code
 relocate_code:
-	link.w %a6,#0
-	move.l 8(%a6), %sp		/* set new stack pointer */
+	link.w	%a6,#0
+	move.l	8(%a6), %sp		/* set new stack pointer */
 
-	move.l 12(%a6), %d0		/* Save copy of Global Data pointer */
-	move.l 16(%a6), %a0		/* Save copy of Destination Address */
+	move.l	12(%a6), %d0		/* Save copy of Global Data pointer */
+	move.l	16(%a6), %a0		/* Save copy of Destination Address */
 
-	move.l #CONFIG_SYS_MONITOR_BASE, %a1
-	move.l #__init_end, %a2
-	move.l %a0, %a3
+	move.l	#CONFIG_SYS_MONITOR_BASE, %a1
+	move.l	#__init_end, %a2
+	move.l	%a0, %a3
 
 	/* copy the code to RAM */
 1:
-	move.l (%a1)+, (%a3)+
-	cmp.l  %a1,%a2
-	bgt.s	 1b
+	move.l	(%a1)+, (%a3)+
+	cmp.l	%a1,%a2
+	bgt.s	1b
 
 /*
  * We are done. Do not return, instead branch to second part of board
@@ -240,7 +226,7 @@
 	 */
 	move.l	%a0, %a1
 	add.l	#(__got_start - CONFIG_SYS_MONITOR_BASE),%a1
-	move.l	%a1,%a5		/* * fix got pointer register a5 */
+	move.l	%a1,%a5			/* fix got pointer register a5 */
 
 	move.l	%a0, %a2
 	add.l	#(__got_end - CONFIG_SYS_MONITOR_BASE),%a2
@@ -254,38 +240,40 @@
 	bne	7b
 
 	/* calculate relative jump to board_init_r in ram */
-	move.l %a0, %a1
-	add.l #(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1
+	move.l	%a0, %a1
+	add.l	#(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1
 
 	/* set parameters for board_init_r */
-	move.l %a0,-(%sp)		/* dest_addr */
-	move.l %d0,-(%sp)		/* gd */
+	move.l	%a0,-(%sp)		/* dest_addr */
+	move.l	%d0,-(%sp)		/* gd */
 	jsr	(%a1)
 
-/*------------------------------------------------------------------------------*/
+/******************************************************************************/
+
 /* exception code */
-	.globl _fault
+.globl _fault
 _fault:
 	bra _fault
-	.globl	_exc_handler
 
+.globl _exc_handler
 _exc_handler:
 	SAVE_ALL
 	movel	%sp,%sp@-
-	bsr exc_handler
+	bsr	exc_handler
 	addql	#4,%sp
 	RESTORE_ALL
 
-	.globl	_int_handler
+.globl _int_handler
 _int_handler:
 	SAVE_ALL
 	movel	%sp,%sp@-
-	bsr int_handler
+	bsr	int_handler
 	addql	#4,%sp
 	RESTORE_ALL
 
-/*------------------------------------------------------------------------------*/
-	.globl	version_string
+/******************************************************************************/
+
+.globl version_string
 version_string:
-	.ascii U_BOOT_VERSION_STRING, "\0"
-	.align 4
+.ascii U_BOOT_VERSION_STRING, "\0"
+.align 4
diff --git a/arch/m68k/cpu/mcf5445x/start.S b/arch/m68k/cpu/mcf5445x/start.S
index ba38678..bc48ca0 100644
--- a/arch/m68k/cpu/mcf5445x/start.S
+++ b/arch/m68k/cpu/mcf5445x/start.S
@@ -33,62 +33,47 @@
 	rte;
 
 #if defined(CONFIG_SERIAL_BOOT)
-#define ASM_DRAMINIT	(asm_dram_init - CONFIG_SYS_TEXT_BASE + CONFIG_SYS_INIT_RAM_ADDR)
+#define ASM_DRAMINIT	(asm_dram_init - CONFIG_SYS_TEXT_BASE + \
+	CONFIG_SYS_INIT_RAM_ADDR)
 #define ASM_DRAMINIT_N	(asm_dram_init - CONFIG_SYS_TEXT_BASE)
-#define ASM_SBF_IMG_HDR	(asm_sbf_img_hdr - CONFIG_SYS_TEXT_BASE + CONFIG_SYS_INIT_RAM_ADDR)
+#define ASM_SBF_IMG_HDR	(asm_sbf_img_hdr - CONFIG_SYS_TEXT_BASE + \
+	CONFIG_SYS_INIT_RAM_ADDR)
 #endif
 
 .text
 
 /*
- *	Vector table. This is used for initial platform startup.
- *	These vectors are to catch any un-intended traps.
+ * Vector table. This is used for initial platform startup.
+ * These vectors are to catch any un-intended traps.
  */
 _vectors:
 #if defined(CONFIG_SERIAL_BOOT)
 
-INITSP:	.long	0		/* Initial SP	*/
+INITSP:	.long	0			/* Initial SP	*/
 #ifdef CONFIG_CF_SBF
-INITPC:	.long	ASM_DRAMINIT	/* Initial PC 	*/
+INITPC:	.long	ASM_DRAMINIT		/* Initial PC 	*/
 #endif
 #ifdef CONFIG_SYS_NAND_BOOT
-INITPC:	.long	ASM_DRAMINIT_N	/* Initial PC 	*/
+INITPC:	.long	ASM_DRAMINIT_N		/* Initial PC 	*/
 #endif
 
 #else
 
-INITSP:		.long	0	/* Initial SP	*/
-INITPC:		.long	_START	/* Initial PC 		*/
+INITSP:	.long	0			/* Initial SP	*/
+INITPC:	.long	_START			/* Initial PC 	*/
 
 #endif
 
-vector02:	.long	_FAULT	/* Access Error		*/
-vector03:	.long	_FAULT	/* Address Error	*/
-vector04:	.long	_FAULT	/* Illegal Instruction	*/
-vector05:	.long	_FAULT	/* Reserved		*/
-vector06:	.long	_FAULT	/* Reserved		*/
-vector07:	.long	_FAULT	/* Reserved		*/
-vector08:	.long	_FAULT	/* Privilege Violation	*/
-vector09:	.long	_FAULT	/* Trace		*/
-vector0A:	.long	_FAULT	/* Unimplemented A-Line	*/
-vector0B:	.long	_FAULT	/* Unimplemented F-Line	*/
-vector0C:	.long	_FAULT	/* Debug Interrupt	*/
-vector0D:	.long	_FAULT	/* Reserved		*/
-vector0E:	.long	_FAULT	/* Format Error		*/
-vector0F:	.long	_FAULT	/* Unitialized Int.	*/
+vector02_0F:
+.long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
+.long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 
 /* Reserved */
 vector10_17:
 .long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 
-vector18:	.long	_FAULT	/* Spurious Interrupt	*/
-vector19:	.long	_FAULT	/* Autovector Level 1	*/
-vector1A:	.long	_FAULT	/* Autovector Level 2	*/
-vector1B:	.long	_FAULT	/* Autovector Level 3	*/
-vector1C:	.long	_FAULT	/* Autovector Level 4	*/
-vector1D:	.long	_FAULT	/* Autovector Level 5	*/
-vector1E:	.long	_FAULT	/* Autovector Level 6	*/
-vector1F:	.long	_FAULT	/* Autovector Level 7	*/
+vector18_1F:
+.long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 
 #if !defined(CONFIG_SERIAL_BOOT)
 
@@ -136,12 +121,12 @@
 #if defined(CONFIG_SERIAL_BOOT)
 	/* Image header: chksum 4 bytes, len 4 bytes, img dest 4 bytes */
 asm_sbf_img_hdr:
-	.long	0x00000000	/* checksum, not yet implemented */
-	.long	0x00040000	/* image length */
+	.long	0x00000000		/* checksum, not yet implemented */
+	.long	0x00040000		/* image length */
 	.long	CONFIG_SYS_TEXT_BASE	/* image to be relocated at */
 
 asm_dram_init:
-	move.w #0x2700,%sr		/* Mask off Interrupt */
+	move.w	#0x2700,%sr		/* Mask off Interrupt */
 
 #ifdef CONFIG_SYS_NAND_BOOT
 	/* for assembly stack */
@@ -149,7 +134,7 @@
 	movec	%d0, %RAMBAR1
 
 	move.l	#(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
-	clr.l %sp@-
+	clr.l	%sp@-
 #endif
 
 #ifdef CONFIG_CF_SBF
@@ -160,11 +145,11 @@
 	movec	%d0, %RAMBAR1
 
 	/* initialize general use internal ram */
-	move.l #0, %d0
-	move.l #(ICACHE_STATUS), %a1	/* icache */
-	move.l #(DCACHE_STATUS), %a2	/* dcache */
-	move.l %d0, (%a1)
-	move.l %d0, (%a2)
+	move.l	#0, %d0
+	move.l	#(ICACHE_STATUS), %a1	/* icache */
+	move.l	#(DCACHE_STATUS), %a2	/* dcache */
+	move.l	%d0, (%a1)
+	move.l	%d0, (%a2)
 
 	/* invalidate and disable cache */
 	move.l	#(CONFIG_SYS_ICACHE_INV + CONFIG_SYS_DCACHE_INV), %d0
@@ -176,7 +161,7 @@
 	movec	%d0, %ACR3
 
 	move.l	#(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp
-	clr.l %sp@-
+	clr.l	%sp@-
 
 	/* Must disable global address */
 	move.l	#0xFC008000, %a1
@@ -185,7 +170,7 @@
 	move.l	#(CONFIG_SYS_CS0_CTRL), (%a1)
 	move.l	#0xFC008004, %a1
 	move.l	#(CONFIG_SYS_CS0_MASK), (%a1)
-#endif			/* CONFIG_CF_SBF */
+#endif /* CONFIG_CF_SBF */
 
 #ifdef CONFIG_MCF5441x
 	/* TC: enable all peripherals,
@@ -193,9 +178,9 @@
 	move.l	#0xFC04002D, %a1
 
 #if defined(CONFIG_CF_SBF)
-	move.b	#23, (%a1)	/* dspi */
+	move.b	#23, (%a1)		/* dspi */
 #endif
-	move.b	#46, (%a1)	/* DDR */
+	move.b	#46, (%a1)		/* DDR */
 
 	/* slew settings */
 	move.l	#0xEC094060, %a1
@@ -365,7 +350,7 @@
 
 	move.l	#2000, %d1
 	jsr	asm_delay
-#endif		/* CONFIG_MCF5445x */
+#endif /* CONFIG_MCF5445x */
 
 #ifdef CONFIG_CF_SBF
 	/*
@@ -484,7 +469,7 @@
 
 	move.b	(%a3), %d1
 	rts
-#endif			/* CONFIG_CF_SBF */
+#endif /* CONFIG_CF_SBF */
 
 #ifdef CONFIG_SYS_NAND_BOOT
 	/* copy 4 boot pages to dram as soon as possible */
@@ -509,13 +494,13 @@
 	move.l	%d1, (%a1)
 
 	/* initialize general use internal ram */
-	move.l #0, %d0
-	move.l #(CACR_STATUS), %a1	/* CACR */
-	move.l #(ICACHE_STATUS), %a2	/* icache */
-	move.l #(DCACHE_STATUS), %a3	/* dcache */
-	move.l %d0, (%a1)
-	move.l %d0, (%a2)
-	move.l %d0, (%a3)
+	move.l	#0, %d0
+	move.l	#(CACR_STATUS), %a1	/* CACR */
+	move.l	#(ICACHE_STATUS), %a2	/* icache */
+	move.l	#(DCACHE_STATUS), %a3	/* dcache */
+	move.l	%d0, (%a1)
+	move.l	%d0, (%a2)
+	move.l	%d0, (%a3)
 
 	/* invalidate and disable cache */
 	move.l	#0x01004100, %d0	/* Invalidate cache cmd */
@@ -571,7 +556,7 @@
 	move.l	#4, %d2			/* start at 4 */
 	move.l  #0xFC0FFF04, %a0	/* cmd2 */
 	move.l  #0xFC0FFF0C, %a1	/* rar */
-	move.l	#(CONFIG_SYS_TEXT_BASE + 0xF80), %a2	/* dst */
+	move.l	#(CONFIG_SYS_TEXT_BASE + 0xF80), %a2
 
 asm_nand_read:
 	move.l	#0x11000000, %d0	/* rar */
@@ -621,14 +606,14 @@
 	rts
 #endif			/* CONFIG_CF_SBF || CONFIG_NAND_U_BOOT */
 
-	.text
+.text
 	. = 0x400
-	.globl	_start
+.globl _start
 _start:
 #if !defined(CONFIG_SERIAL_BOOT)
 	nop
 	nop
-	move.w #0x2700,%sr		/* Mask off Interrupt */
+	move.w	#0x2700,%sr		/* Mask off Interrupt */
 
 	/* Set vector base register at the beginning of the Flash */
 	move.l	#CONFIG_SYS_FLASH_BASE, %d0
@@ -638,11 +623,11 @@
 	movec	%d0, %RAMBAR1
 
 	/* initialize general use internal ram */
-	move.l #0, %d0
-	move.l #(ICACHE_STATUS), %a1	/* icache */
-	move.l #(DCACHE_STATUS), %a2	/* dcache */
-	move.l %d0, (%a1)
-	move.l %d0, (%a2)
+	move.l	#0, %d0
+	move.l	#(ICACHE_STATUS), %a1	/* icache */
+	move.l	#(DCACHE_STATUS), %a2	/* dcache */
+	move.l	%d0, (%a1)
+	move.l	%d0, (%a2)
 
 	/* invalidate and disable cache */
 	move.l	#(CONFIG_SYS_ICACHE_INV + CONFIG_SYS_DCACHE_INV), %d0
@@ -658,10 +643,10 @@
 #endif
 
 	/* put relocation table address to a5 */
-	move.l #__got_start, %a5
+	move.l	#__got_start, %a5
 
 	/* setup stack initially on top of internal static ram  */
-	move.l  #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
+	move.l	#(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
 
 	/*
 	 * if configured, malloc_f arena will be reserved first,
@@ -672,25 +657,26 @@
 	jsr	(%a1)
 
 	/* update stack and frame-pointers */
-	move.l  %d0, %sp
-	move.l  %sp, %fp
+	move.l	%d0, %sp
+	move.l	%sp, %fp
 
 	/* initialize reserved area */
-	move.l  %d0, -(%sp)
+	move.l	%d0, -(%sp)
 	move.l	#board_init_f_init_reserve, %a1
 	jsr	(%a1)
 
 	/* run low-level CPU init code (from flash) */
-	move.l #cpu_init_f, %a1
-	jsr (%a1)
+	move.l	#cpu_init_f, %a1
+	jsr	(%a1)
+
 	/* run low-level board init code (from flash) */
 	clr.l   %sp@-
-	move.l #board_init_f, %a1
-	jsr (%a1)
+	move.l	#board_init_f, %a1
+	jsr	(%a1)
 
 	/* board_init_f() does not return */
 
-/*------------------------------------------------------------------------------*/
+/******************************************************************************/
 
 /*
  * void relocate_code (addr_sp, gd, addr_moni)
@@ -703,23 +689,23 @@
  * r5 = length in bytes
  * r6 = cachelinesize
  */
-	.globl	relocate_code
+.globl relocate_code
 relocate_code:
-	link.w %a6,#0
-	move.l 8(%a6), %sp		/* set new stack pointer */
+	link.w	%a6,#0
+	move.l	8(%a6), %sp		/* set new stack pointer */
 
-	move.l 12(%a6), %d0		/* Save copy of Global Data pointer */
-	move.l 16(%a6), %a0		/* Save copy of Destination Address */
+	move.l	12(%a6), %d0		/* Save copy of Global Data pointer */
+	move.l	16(%a6), %a0		/* Save copy of Destination Address */
 
-	move.l #CONFIG_SYS_MONITOR_BASE, %a1
-	move.l #__init_end, %a2
-	move.l %a0, %a3
+	move.l	#CONFIG_SYS_MONITOR_BASE, %a1
+	move.l	#__init_end, %a2
+	move.l	%a0, %a3
 
 	/* copy the code to RAM */
 1:
-	move.l (%a1)+, (%a3)+
-	cmp.l  %a1,%a2
-	bgt.s	 1b
+	move.l	(%a1)+, (%a3)+
+	cmp.l	%a1,%a2
+	bgt.s	1b
 
 /*
  * We are done. Do not return, instead branch to second part of board
@@ -749,7 +735,7 @@
 	 */
 	move.l	%a0, %a1
 	add.l	#(__got_start - CONFIG_SYS_MONITOR_BASE),%a1
-	move.l	%a1,%a5			/* * fix got pointer register a5 */
+	move.l	%a1,%a5			/* fix got pointer register a5 */
 
 	move.l	%a0, %a2
 	add.l	#(__got_end - CONFIG_SYS_MONITOR_BASE),%a2
@@ -763,39 +749,40 @@
 	bne	7b
 
 	/* calculate relative jump to board_init_r in ram */
-	move.l %a0, %a1
-	add.l #(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1
+	move.l	%a0, %a1
+	add.l	#(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1
 
 	/* set parameters for board_init_r */
-	move.l %a0,-(%sp)		/* dest_addr */
-	move.l %d0,-(%sp)		/* gd */
+	move.l	%a0,-(%sp)		/* dest_addr */
+	move.l	%d0,-(%sp)		/* gd */
 	jsr	(%a1)
 
-/*------------------------------------------------------------------------------*/
+/******************************************************************************/
+
 /* exception code */
-	.globl _fault
+.globl _fault
 _fault:
-	bra _fault
-	.globl	_exc_handler
+	bra	_fault
 
+.globl _exc_handler
 _exc_handler:
 	SAVE_ALL
 	movel	%sp,%sp@-
-	bsr exc_handler
+	bsr	exc_handler
 	addql	#4,%sp
 	RESTORE_ALL
 
-	.globl	_int_handler
+.globl _int_handler
 _int_handler:
 	SAVE_ALL
 	movel	%sp,%sp@-
-	bsr int_handler
+	bsr	int_handler
 	addql	#4,%sp
 	RESTORE_ALL
 
-/*------------------------------------------------------------------------------*/
+/******************************************************************************/
 
-	.globl	version_string
+.globl version_string
 version_string:
-	.ascii U_BOOT_VERSION_STRING, "\0"
-	.align 4
+.ascii U_BOOT_VERSION_STRING, "\0"
+.align 4
diff --git a/arch/m68k/cpu/mcf547x_8x/start.S b/arch/m68k/cpu/mcf547x_8x/start.S
index 9a87a0d..fecf253 100644
--- a/arch/m68k/cpu/mcf547x_8x/start.S
+++ b/arch/m68k/cpu/mcf547x_8x/start.S
@@ -28,41 +28,25 @@
 	rte;
 
 .text
+
 /*
- *	Vector table. This is used for initial platform startup.
- *	These vectors are to catch any un-intended traps.
+ * Vector table. This is used for initial platform startup.
+ * These vectors are to catch any un-intended traps.
  */
 _vectors:
+INITSP:	.long	0x00000000		/* Initial SP	*/
+INITPC:	.long	_START			/* Initial PC	*/
 
-INITSP:		.long	0x00000000	/* Initial SP	*/
-INITPC:		.long	_START	/* Initial PC		*/
-vector02:	.long	_FAULT	/* Access Error		*/
-vector03:	.long	_FAULT	/* Address Error	*/
-vector04:	.long	_FAULT	/* Illegal Instruction	*/
-vector05:	.long	_FAULT	/* Reserved		*/
-vector06:	.long	_FAULT	/* Reserved		*/
-vector07:	.long	_FAULT	/* Reserved		*/
-vector08:	.long	_FAULT	/* Privilege Violation	*/
-vector09:	.long	_FAULT	/* Trace		*/
-vector0A:	.long	_FAULT	/* Unimplemented A-Line	*/
-vector0B:	.long	_FAULT	/* Unimplemented F-Line	*/
-vector0C:	.long	_FAULT	/* Debug Interrupt	*/
-vector0D:	.long	_FAULT	/* Reserved		*/
-vector0E:	.long	_FAULT	/* Format Error		*/
-vector0F:	.long	_FAULT	/* Unitialized Int.	*/
+vector02_0F:
+.long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
+.long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 
 /* Reserved */
 vector10_17:
 .long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 
-vector18:	.long	_FAULT	/* Spurious Interrupt	*/
-vector19:	.long	_FAULT	/* Autovector Level 1	*/
-vector1A:	.long	_FAULT	/* Autovector Level 2	*/
-vector1B:	.long	_FAULT	/* Autovector Level 3	*/
-vector1C:	.long	_FAULT	/* Autovector Level 4	*/
-vector1D:	.long	_FAULT	/* Autovector Level 5	*/
-vector1E:	.long	_FAULT	/* Autovector Level 6	*/
-vector1F:	.long	_FAULT	/* Autovector Level 7	*/
+vector18_1F:
+.long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 
 /* TRAP #0 - #15 */
 vector20_2F:
@@ -104,13 +88,13 @@
 .long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 .long	_FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
 
-	.text
+.text
 
-	.globl	_start
+.globl _start
 _start:
 	nop
 	nop
-	move.w #0x2700,%sr		/* Mask off Interrupt */
+	move.w	#0x2700,%sr		/* Mask off Interrupt */
 
 	/* Set vector base register at the beginning of the Flash */
 	move.l	#CONFIG_SYS_FLASH_BASE, %d0
@@ -122,7 +106,7 @@
 	move.l	#(CONFIG_SYS_INIT_RAM1_ADDR + CONFIG_SYS_INIT_RAM1_CTRL), %d0
 	movec	%d0, %RAMBAR1
 
-	move.l	#CONFIG_SYS_MBAR, %d0		/* set MBAR address */
+	move.l	#CONFIG_SYS_MBAR, %d0	/* set MBAR address */
 	move.c	%d0, %MBAR
 
 	/* invalidate and disable cache */
@@ -135,17 +119,17 @@
 	movec	%d0, %ACR3
 
 	/* initialize general use internal ram */
-	move.l #0, %d0
-	move.l #(ICACHE_STATUS), %a1	/* icache */
-	move.l #(DCACHE_STATUS), %a2	/* icache */
-	move.l %d0, (%a1)
-	move.l %d0, (%a2)
+	move.l	#0, %d0
+	move.l	#(ICACHE_STATUS), %a1	/* icache */
+	move.l	#(DCACHE_STATUS), %a2	/* icache */
+	move.l	%d0, (%a1)
+	move.l	%d0, (%a2)
 
 	/* put relocation table address to a5 */
-	move.l #__got_start, %a5
+	move.l	#__got_start, %a5
 
 	/* setup stack initially on top of internal static ram  */
-	move.l  #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
+	move.l	#(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp
 
 	/*
 	 * if configured, malloc_f arena will be reserved first,
@@ -159,16 +143,19 @@
 	move.l  %sp, %fp
 
 	/* initialize reserved area */
-	move.l  %d0, -(%sp)
-	bsr     board_init_f_init_reserve
+	move.l	%d0, -(%sp)
+	bsr	board_init_f_init_reserve
 
-	jbsr cpu_init_f			/* run low-level CPU init code (from flash) */
-	clr.l   %sp@-
-	jbsr board_init_f		/* run low-level board init code (from flash) */
+	/* run low-level CPU init code (from flash) */
+	jbsr	cpu_init_f
+
+	/* run low-level board init code (from flash) */
+	clr.l	%sp@-
+	jbsr	board_init_f
 
 	/* board_init_f() does not return */
 
-/*------------------------------------------------------------------------------*/
+/******************************************************************************/
 
 /*
  * void relocate_code (addr_sp, gd, addr_moni)
@@ -181,23 +168,23 @@
  * r5 = length in bytes
  * r6 = cachelinesize
  */
-	.globl	relocate_code
+.globl relocate_code
 relocate_code:
-	link.w %a6,#0
-	move.l 8(%a6), %sp		/* set new stack pointer */
+	link.w	%a6,#0
+	move.l	8(%a6), %sp		/* set new stack pointer */
 
-	move.l 12(%a6), %d0		/* Save copy of Global Data pointer */
-	move.l 16(%a6), %a0		/* Save copy of Destination Address */
+	move.l	12(%a6), %d0		/* Save copy of Global Data pointer */
+	move.l	16(%a6), %a0		/* Save copy of Destination Address */
 
-	move.l #CONFIG_SYS_MONITOR_BASE, %a1
-	move.l #__init_end, %a2
-	move.l %a0, %a3
+	move.l	#CONFIG_SYS_MONITOR_BASE, %a1
+	move.l	#__init_end, %a2
+	move.l	%a0, %a3
 
 	/* copy the code to RAM */
 1:
-	move.l (%a1)+, (%a3)+
-	cmp.l  %a1,%a2
-	bgt.s	 1b
+	move.l	(%a1)+, (%a3)+
+	cmp.l	%a1,%a2
+	bgt.s	1b
 
 /*
  * We are done. Do not return, instead branch to second part of board
@@ -227,7 +214,7 @@
 	 */
 	move.l	%a0, %a1
 	add.l	#(__got_start - CONFIG_SYS_MONITOR_BASE),%a1
-	move.l	%a1,%a5		/* * fix got pointer register a5 */
+	move.l	%a1,%a5			/* fix got pointer register a5 */
 
 	move.l	%a0, %a2
 	add.l	#(__got_end - CONFIG_SYS_MONITOR_BASE),%a2
@@ -241,39 +228,40 @@
 	bne	7b
 
 	/* calculate relative jump to board_init_r in ram */
-	move.l %a0, %a1
-	add.l #(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1
+	move.l	%a0, %a1
+	add.l	#(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1
 
 	/* set parameters for board_init_r */
-	move.l %a0,-(%sp)		/* dest_addr */
-	move.l %d0,-(%sp)		/* gd */
+	move.l	%a0,-(%sp)		/* dest_addr */
+	move.l	%d0,-(%sp)		/* gd */
 	jsr	(%a1)
 
-/*------------------------------------------------------------------------------*/
+/******************************************************************************/
+
 /* exception code */
-	.globl _fault
+.globl _fault
 _fault:
-	bra _fault
-	.globl	_exc_handler
+	bra	_fault
 
+.globl _exc_handler
 _exc_handler:
 	SAVE_ALL
 	movel	%sp,%sp@-
-	bsr exc_handler
+	bsr	exc_handler
 	addql	#4,%sp
 	RESTORE_ALL
 
-	.globl	_int_handler
+.globl _int_handler
 _int_handler:
 	SAVE_ALL
 	movel	%sp,%sp@-
-	bsr int_handler
+	bsr	int_handler
 	addql	#4,%sp
 	RESTORE_ALL
 
-/*------------------------------------------------------------------------------*/
+/******************************************************************************/
 
-	.globl	version_string
+.globl version_string
 version_string:
-	.ascii U_BOOT_VERSION_STRING, "\0"
-	.align 4
+.ascii U_BOOT_VERSION_STRING, "\0"
+.align 4
diff --git a/arch/m68k/include/asm/fec.h b/arch/m68k/include/asm/fec.h
index 6856aac..2799293 100644
--- a/arch/m68k/include/asm/fec.h
+++ b/arch/m68k/include/asm/fec.h
@@ -15,6 +15,8 @@
 #ifndef	fec_h
 #define	fec_h
 
+#include <phy.h>
+
 /* Buffer descriptors used FEC.
 */
 typedef struct cpm_buf_desc {
@@ -341,10 +343,9 @@
 void __mii_init(void);
 uint mii_send(uint mii_cmd);
 int mii_discover_phy(struct eth_device *dev);
-int mcffec_miiphy_read(const char *devname, unsigned char addr,
-		       unsigned char reg, unsigned short *value);
-int mcffec_miiphy_write(const char *devname, unsigned char addr,
-			unsigned char reg, unsigned short value);
+int mcffec_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg);
+int mcffec_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+			u16 value);
 #endif
 
 #endif				/* fec_h */
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index aa0475a..0c6a4ab 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -253,6 +253,7 @@
 #endif
 }
 
+#ifdef CONFIG_ARCH_FIXUP_FDT
 int arch_fixup_fdt(void *blob)
 {
 #if CONFIG_IS_ENABLED(MIPS_BOOT_FDT) && CONFIG_IS_ENABLED(OF_LIBFDT)
@@ -264,6 +265,7 @@
 	return 0;
 #endif
 }
+#endif
 
 static int boot_setup_fdt(bootm_headers_t *images)
 {
diff --git a/arch/mips/mach-au1x00/au1x00_eth.c b/arch/mips/mach-au1x00/au1x00_eth.c
index 9216860..67f4953 100644
--- a/arch/mips/mach-au1x00/au1x00_eth.c
+++ b/arch/mips/mach-au1x00/au1x00_eth.c
@@ -73,9 +73,9 @@
 #define MAX_WAIT 1000
 
 #if defined(CONFIG_CMD_MII)
-int  au1x00_miiphy_read(const char *devname, unsigned char addr,
-		unsigned char reg, unsigned short * value)
+int au1x00_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
+	unsigned short value = 0;
 	volatile u32 *mii_control_reg = (volatile u32*)(ETH0_BASE+MAC_MII_CNTRL);
 	volatile u32 *mii_data_reg = (volatile u32*)(ETH0_BASE+MAC_MII_DATA);
 	u32 mii_control;
@@ -102,12 +102,12 @@
 			return -1;
 		}
 	}
-	*value = *mii_data_reg;
-	return 0;
+	value = *mii_data_reg;
+	return value;
 }
 
-int  au1x00_miiphy_write(const char *devname, unsigned char addr,
-		unsigned char reg, unsigned short value)
+int au1x00_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+			u16 value)
 {
 	volatile u32 *mii_control_reg = (volatile u32*)(ETH0_BASE+MAC_MII_CNTRL);
 	volatile u32 *mii_data_reg = (volatile u32*)(ETH0_BASE+MAC_MII_DATA);
@@ -290,8 +290,17 @@
 	eth_register(dev);
 
 #if defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name,
-		au1x00_miiphy_read, au1x00_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = au1x00_miiphy_read;
+	mdiodev->write = au1x00_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 
 	return 1;
diff --git a/arch/nds32/include/asm/io.h b/arch/nds32/include/asm/io.h
index 04708e9..b2c4d0e 100644
--- a/arch/nds32/include/asm/io.h
+++ b/arch/nds32/include/asm/io.h
@@ -344,40 +344,6 @@
 #define insl_p(port, to, len)		insl(port, to, len)
 
 /*
- * ioremap and friends.
- *
- * ioremap takes a PCI memory address, as specified in
- * linux/Documentation/IO-mapping.txt.  If you want a
- * physical address, use __ioremap instead.
- */
-extern void *__ioremap(unsigned long offset, size_t size, unsigned long flags);
-extern void __iounmap(void *addr);
-
-/*
- * Generic ioremap support.
- *
- * Define:
- *  iomem_valid_addr(off,size)
- *  iomem_to_phys(off)
- */
-#ifdef iomem_valid_addr
-#define __arch_ioremap(off, sz, nocache)				\
-({									\
-	unsigned long _off = (off), _size = (sz);			\
-	void *_ret = (void *)0;						\
-	if (iomem_valid_addr(_off, _size))				\
-		_ret = __ioremap(iomem_to_phys(_off), _size, 0);	\
-	_ret;								\
-})
-
-#define __arch_iounmap __iounmap
-#endif
-
-#define ioremap(off, sz)		__arch_ioremap((off), (sz), 0)
-#define ioremap_nocache(off, sz)	__arch_ioremap((off), (sz), 1)
-#define iounmap(_addr)			__arch_iounmap(_addr)
-
-/*
  * DMA-consistent mapping functions.  These allocate/free a region of
  * uncached, unwrite-buffered mapped memory space for use with DMA
  * devices.  This is the "generic" version.  The PCI specific version
diff --git a/arch/powerpc/cpu/mpc8260/ether_fcc.c b/arch/powerpc/cpu/mpc8260/ether_fcc.c
index a11ad1e..072eb76 100644
--- a/arch/powerpc/cpu/mpc8260/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc8260/ether_fcc.c
@@ -379,8 +379,17 @@
 
 #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
 		&& defined(CONFIG_BITBANGMII)
-		miiphy_register(dev->name,
-				bb_miiphy_read,	bb_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+		mdiodev->read = bb_miiphy_read;
+		mdiodev->write = bb_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 #endif
 	}
 
diff --git a/arch/powerpc/cpu/mpc85xx/Kconfig b/arch/powerpc/cpu/mpc85xx/Kconfig
index 0b89157..9bcbda0 100644
--- a/arch/powerpc/cpu/mpc85xx/Kconfig
+++ b/arch/powerpc/cpu/mpc85xx/Kconfig
@@ -17,6 +17,7 @@
 config TARGET_B4860QDS
 	bool "Support B4860QDS"
 	select SUPPORT_SPL
+	select PHYS_64BIT
 
 config TARGET_BSC9131RDB
 	bool "Support BSC9131RDB"
@@ -30,18 +31,23 @@
 	bool "Support C29XPCIE"
 	select SUPPORT_SPL
 	select SUPPORT_TPL
+	select PHYS_64BIT
 
 config TARGET_P3041DS
 	bool "Support P3041DS"
+	select PHYS_64BIT
 
 config TARGET_P4080DS
 	bool "Support P4080DS"
+	select PHYS_64BIT
 
 config TARGET_P5020DS
 	bool "Support P5020DS"
+	select PHYS_64BIT
 
 config TARGET_P5040DS
 	bool "Support P5040DS"
+	select PHYS_64BIT
 
 config TARGET_MPC8536DS
 	bool "Support MPC8536DS"
@@ -96,46 +102,57 @@
 
 config TARGET_P2041RDB
 	bool "Support P2041RDB"
+	select PHYS_64BIT
 
 config TARGET_QEMU_PPCE500
 	bool "Support qemu-ppce500"
+	select PHYS_64BIT
 
 config TARGET_T102XQDS
 	bool "Support T102xQDS"
 	select SUPPORT_SPL
+	select PHYS_64BIT
 
 config TARGET_T102XRDB
 	bool "Support T102xRDB"
 	select SUPPORT_SPL
+	select PHYS_64BIT
 
 config TARGET_T1040QDS
 	bool "Support T1040QDS"
+	select PHYS_64BIT
 
 config TARGET_T104XRDB
 	bool "Support T104xRDB"
 	select SUPPORT_SPL
+	select PHYS_64BIT
 
 config TARGET_T208XQDS
 	bool "Support T208xQDS"
 	select SUPPORT_SPL
+	select PHYS_64BIT
 
 config TARGET_T208XRDB
 	bool "Support T208xRDB"
 	select SUPPORT_SPL
+	select PHYS_64BIT
 
 config TARGET_T4240QDS
 	bool "Support T4240QDS"
 	select SUPPORT_SPL
+	select PHYS_64BIT
 
 config TARGET_T4240RDB
 	bool "Support T4240RDB"
 	select SUPPORT_SPL
+	select PHYS_64BIT
 
 config TARGET_CONTROLCENTERD
 	bool "Support controlcenterd"
 
 config TARGET_KMP204X
 	bool "Support kmp204x"
+	select PHYS_64BIT
 
 config TARGET_XPEDITE520X
 	bool "Support xpedite520x"
@@ -151,6 +168,7 @@
 
 config TARGET_CYRUS
 	bool "Support Varisys Cyrus"
+	select PHYS_64BIT
 
 endchoice
 
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c b/arch/powerpc/cpu/mpc85xx/cpu_init.c
index 61f5639..ace4279 100644
--- a/arch/powerpc/cpu/mpc85xx/cpu_init.c
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c
@@ -439,7 +439,7 @@
 #ifdef CONFIG_SYS_DCSRBAR_PHYS
 	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
 #endif
-#if defined(CONFIG_SECURE_BOOT)
+#if defined(CONFIG_SECURE_BOOT) && !defined(CONFIG_SYS_RAMBOOT)
 	struct law_entry law;
 #endif
 #ifdef CONFIG_MPC8548
@@ -459,7 +459,7 @@
 	disable_tlb(14);
 	disable_tlb(15);
 
-#if defined(CONFIG_SECURE_BOOT)
+#if defined(CONFIG_SECURE_BOOT) && !defined(CONFIG_SYS_RAMBOOT)
 	/* Disable the LAW created for NOR flash by the PBI commands */
 	law = find_law(CONFIG_SYS_PBI_FLASH_BASE);
 	if (law.index != -1)
diff --git a/arch/powerpc/cpu/mpc85xx/ether_fcc.c b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
index 51f1bee..7708f05 100644
--- a/arch/powerpc/cpu/mpc85xx/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
@@ -441,8 +441,17 @@
 
 #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
 		&& defined(CONFIG_BITBANGMII)
-		miiphy_register(dev->name,
-				bb_miiphy_read,	bb_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+		mdiodev->read = bb_miiphy_read;
+		mdiodev->write = bb_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 #endif
 	}
 
diff --git a/arch/powerpc/cpu/mpc85xx/mp.c b/arch/powerpc/cpu/mpc85xx/mp.c
index 88c8e65..0addf84 100644
--- a/arch/powerpc/cpu/mpc85xx/mp.c
+++ b/arch/powerpc/cpu/mpc85xx/mp.c
@@ -30,7 +30,7 @@
  */
 int hold_cores_in_reset(int verbose)
 {
-	/* Default to no, overriden by 'y', 'yes', 'Y', 'Yes', or '1' */
+	/* Default to no, overridden by 'y', 'yes', 'Y', 'Yes', or '1' */
 	if (getenv_yesno("mp_holdoff") == 1) {
 		if (verbose) {
 			puts("Secondary cores are being held in reset.\n");
diff --git a/arch/powerpc/cpu/mpc85xx/start.S b/arch/powerpc/cpu/mpc85xx/start.S
index 4c51225..c3e1234 100644
--- a/arch/powerpc/cpu/mpc85xx/start.S
+++ b/arch/powerpc/cpu/mpc85xx/start.S
@@ -1069,17 +1069,23 @@
 #elif !defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SECURE_BOOT)
 	/* create a temp mapping in AS = 1 for Flash mapping
 	 * created by PBL for ISBC code
-	*/
+	 */
 	create_tlb1_entry 15, \
 		1, BOOKE_PAGESZ_1M, \
 		CONFIG_SYS_MONITOR_BASE & 0xfff00000, MAS2_I|MAS2_G, \
 		CONFIG_SYS_PBI_FLASH_WINDOW & 0xfff00000, MAS3_SX|MAS3_SW|MAS3_SR, \
 		0, r6
 
-#elif defined(CONFIG_RAMBOOT_PBL) && defined(CONFIG_SECURE_BOOT)
+/*
+ * For Targets without CONFIG_SPL like P3, P5
+ * and for targets with CONFIG_SPL like T1, T2, T4, only for
+ * u-boot-spl i.e. CONFIG_SPL_BUILD
+ */
+#elif defined(CONFIG_RAMBOOT_PBL) && defined(CONFIG_SECURE_BOOT) && \
+	(!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD))
 	/* create a temp mapping in AS = 1 for mapping CONFIG_SYS_MONITOR_BASE
 	 * to L3 Address configured by PBL for ISBC code
-	*/
+	 */
 	create_tlb1_entry 15, \
 		1, BOOKE_PAGESZ_1M, \
 		CONFIG_SYS_MONITOR_BASE & 0xfff00000, MAS2_I|MAS2_G, \
diff --git a/arch/powerpc/cpu/mpc86xx/config.mk b/arch/powerpc/cpu/mpc86xx/config.mk
index 69a0b96..aefb0f1 100644
--- a/arch/powerpc/cpu/mpc86xx/config.mk
+++ b/arch/powerpc/cpu/mpc86xx/config.mk
@@ -5,4 +5,4 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-PLATFORM_CPPFLAGS += -mstring -maltivec -mabi=altivec -msoft-float
+PLATFORM_CPPFLAGS += -mcpu=7400 -mstring -maltivec -mabi=altivec -msoft-float
diff --git a/arch/powerpc/cpu/mpc8xx/fec.c b/arch/powerpc/cpu/mpc8xx/fec.c
index f1ae358..0940906 100644
--- a/arch/powerpc/cpu/mpc8xx/fec.c
+++ b/arch/powerpc/cpu/mpc8xx/fec.c
@@ -6,10 +6,12 @@
  */
 
 #include <common.h>
-#include <malloc.h>
+#include <command.h>
 #include <commproc.h>
+#include <malloc.h>
 #include <net.h>
-#include <command.h>
+
+#include <phy.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -47,10 +49,9 @@
 static int mii_discover_phy(struct eth_device *dev);
 #endif
 
-int fec8xx_miiphy_read(const char *devname, unsigned char addr,
-		unsigned char  reg, unsigned short *value);
-int fec8xx_miiphy_write(const char *devname, unsigned char  addr,
-		unsigned char  reg, unsigned short value);
+int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg);
+int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+			u16 value);
 
 static struct ether_fcc_info_s
 {
@@ -170,8 +171,17 @@
 		eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-		miiphy_register(dev->name,
-			fec8xx_miiphy_read, fec8xx_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+		mdiodev->read = fec8xx_miiphy_read;
+		mdiodev->write = fec8xx_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 #endif
 	}
 	return 1;
@@ -894,9 +904,9 @@
  *	  Otherwise they hang in mii_send() !!! Sorry!
  *****************************************************************************/
 
-int fec8xx_miiphy_read(const char *devname, unsigned char addr,
-		unsigned char  reg, unsigned short *value)
+int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
+	unsigned short value = 0;
 	short rdreg;    /* register working value */
 
 #ifdef MII_DEBUG
@@ -904,15 +914,15 @@
 #endif
 	rdreg = mii_send(mk_mii_read(addr, reg));
 
-	*value = rdreg;
+	value = rdreg;
 #ifdef MII_DEBUG
-	printf ("0x%04x\n", *value);
+	printf ("0x%04x\n", value);
 #endif
-	return 0;
+	return value;
 }
 
-int fec8xx_miiphy_write(const char *devname, unsigned char  addr,
-		unsigned char  reg, unsigned short value)
+int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+			u16 value)
 {
 #ifdef MII_DEBUG
 	printf ("miiphy_write(0x%x) @ 0x%x = ", reg, addr);
diff --git a/arch/powerpc/cpu/mpc8xxx/fsl_pamu.c b/arch/powerpc/cpu/mpc8xxx/fsl_pamu.c
index 9421f1e..ede8e66 100644
--- a/arch/powerpc/cpu/mpc8xxx/fsl_pamu.c
+++ b/arch/powerpc/cpu/mpc8xxx/fsl_pamu.c
@@ -239,15 +239,23 @@
 	spaact_size = sizeof(struct paace) * NUM_SPAACT_ENTRIES;
 
 	/* Allocate space for Primary PAACT Table */
+#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_PPAACT_ADDR))
+	ppaact = (void *)CONFIG_SPL_PPAACT_ADDR;
+#else
 	ppaact = memalign(PAMU_TABLE_ALIGNMENT, ppaact_size);
 	if (!ppaact)
 		return -1;
+#endif
 	memset(ppaact, 0, ppaact_size);
 
 	/* Allocate space for Secondary PAACT Table */
+#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_SPAACT_ADDR))
+	sec = (void *)CONFIG_SPL_SPAACT_ADDR;
+#else
 	sec = memalign(PAMU_TABLE_ALIGNMENT, spaact_size);
 	if (!sec)
 		return -1;
+#endif
 	memset(sec, 0, spaact_size);
 
 	ppaact_phys = virt_to_phys((void *)ppaact);
diff --git a/arch/powerpc/cpu/mpc8xxx/pamu_table.c b/arch/powerpc/cpu/mpc8xxx/pamu_table.c
index 26c5ea4..a8e6f51 100644
--- a/arch/powerpc/cpu/mpc8xxx/pamu_table.c
+++ b/arch/powerpc/cpu/mpc8xxx/pamu_table.c
@@ -28,6 +28,14 @@
 
 	i++;
 #endif
+#if (defined(CONFIG_SPL_BUILD) && (CONFIG_SYS_INIT_L3_VADDR))
+	tbl->start_addr[i] =
+		(uint64_t)virt_to_phys((void *)CONFIG_SYS_INIT_L3_VADDR);
+	tbl->size[i] = 256 * 1024; /* 256K CPC flash */
+	tbl->end_addr[i] = tbl->start_addr[i] +  tbl->size[i] - 1;
+
+	i++;
+#endif
 	debug("PAMU address\t\t\tsize\n");
 	for (j = 0; j < i ; j++)
 		debug("%llx \t\t\t%llx\n",  tbl->start_addr[j],  tbl->size[j]);
diff --git a/arch/powerpc/cpu/ppc4xx/Kconfig b/arch/powerpc/cpu/ppc4xx/Kconfig
index 36af1b9..92a330d 100644
--- a/arch/powerpc/cpu/ppc4xx/Kconfig
+++ b/arch/powerpc/cpu/ppc4xx/Kconfig
@@ -30,6 +30,7 @@
 
 config TARGET_KATMAI
 	bool "Support katmai"
+	select PHYS_64BIT
 
 config TARGET_KILAUEA
 	bool "Support kilauea"
diff --git a/arch/powerpc/cpu/ppc4xx/miiphy.c b/arch/powerpc/cpu/ppc4xx/miiphy.c
index 10147de..f0fc098 100644
--- a/arch/powerpc/cpu/ppc4xx/miiphy.c
+++ b/arch/powerpc/cpu/ppc4xx/miiphy.c
@@ -318,8 +318,7 @@
 	return 0;
 }
 
-int emac4xx_miiphy_read (const char *devname, unsigned char addr, unsigned char reg,
-			 unsigned short *value)
+int emac4xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
 	unsigned long sta_reg;
 	unsigned long emac_reg;
@@ -330,17 +329,15 @@
 		return -1;
 
 	sta_reg = in_be32((void *)EMAC0_STACR + emac_reg);
-	*value = sta_reg >> 16;
-
-	return 0;
+	return sta_reg >> 16;
 }
 
 /***********************************************************/
 /* write a phy reg and return the value with a rc	    */
 /***********************************************************/
 
-int emac4xx_miiphy_write (const char *devname, unsigned char addr, unsigned char reg,
-			  unsigned short value)
+int emac4xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+			 u16 value)
 {
 	return emac_miiphy_command(addr, reg, EMAC_STACR_WRITE, value);
 }
diff --git a/arch/powerpc/cpu/ppc4xx/start.S b/arch/powerpc/cpu/ppc4xx/start.S
index b432b18..7633abc 100644
--- a/arch/powerpc/cpu/ppc4xx/start.S
+++ b/arch/powerpc/cpu/ppc4xx/start.S
@@ -144,7 +144,7 @@
 #endif
 
 /*
- * Unless otherwise overriden, enable two 128MB cachable instruction regions
+ * Unless otherwise overridden, enable two 128MB cachable instruction regions
  * at CONFIG_SYS_SDRAM_BASE and another 128MB cacheable instruction region covering
  * NOR flash at CONFIG_SYS_FLASH_BASE. Disable all cacheable data regions.
  */
@@ -743,8 +743,16 @@
 	/*----------------------------------------------------------------*/
 	/* Setup the stack in internal SRAM */
 	/*----------------------------------------------------------------*/
-	lis	r1,CONFIG_SYS_INIT_RAM_ADDR@h
-	ori	r1,r1,CONFIG_SYS_INIT_SP_OFFSET@l
+	lis	r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE)@h
+	ori	r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE)@l
+	/*
+	 * Reserve space for globals and store address for initialization
+	 * with board_init_f_init_reserve() in r14
+	 */
+	mr	r3, r1
+	bl	board_init_f_alloc_reserve
+	mr	r1, r3
+	mr	r14, r3
 	li	r0,0
 	stwu	r0,-4(r1)
 	stwu	r0,-4(r1)		/* Terminate call chain */
@@ -760,13 +768,9 @@
 #endif
 
 	bl	cpu_init_f	/* run low-level CPU init code	   (from Flash) */
-	mr	r3, r1
-	bl	board_init_f_alloc_reserve
-	mr	r1, r3
+	/* address for globals was stored in r14 */
+	mr	r3, r14
 	bl	board_init_f_init_reserve
-	li	r0,0
-	stwu	r0, -4(r1)
-	stwu	r0, -4(r1)
 	li	r3, 0
 	bl	board_init_f
 	/* NOTREACHED - board_init_f() does not return */
@@ -831,8 +835,16 @@
 	 * for their primordial stack, setup stack here directly after the
 	 * SDRAM is initialized in ext_bus_cntlr_init.
 	 */
+	lis	r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE)@h
+	ori	r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE)@l
+	/*
+	 * Reserve space for globals and store address for initialization
+	 * with board_init_f_init_reserve() in r14
+	 */
-	lis	r1, CONFIG_SYS_INIT_RAM_ADDR@h
-	ori	r1,r1,CONFIG_SYS_INIT_SP_OFFSET /* set up the stack in SDRAM */
+	mr	r3, r1
+	bl	board_init_f_alloc_reserve
+	mr	r1, r3
+	mr	r14, r3
 
 	li	r0, 0			/* Make room for stack frame header and */
 	stwu	r0, -4(r1)		/* clear final stack frame so that	*/
@@ -972,8 +984,16 @@
 	 * Load the initial stack pointer and data area and convert the size,
 	 * in bytes, to the number of words to initialize to a known value.
 	 */
-	lis	r1, CONFIG_SYS_INIT_RAM_ADDR@h
-	ori	r1, r1, CONFIG_SYS_INIT_SP_OFFSET@l
+	lis	r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE)@h
+	ori	r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE)@l
+	/*
+	 * Reserve space for globals and store address for initialization
+	 * with board_init_f_init_reserve() in r14
+	 */
+	mr	r3, r1
+	bl	board_init_f_alloc_reserve
+	mr	r1, r3
+	mr	r14, r3
 
 	lis	r4, (CONFIG_SYS_INIT_RAM_SIZE >> 2)@h
 	ori	r4, r4, (CONFIG_SYS_INIT_RAM_SIZE >> 2)@l
@@ -993,6 +1013,7 @@
 	 * Make room for stack frame header and clear final stack frame so
 	 * that stack backtraces terminate cleanly.
 	 */
+	li	r0, 0
 	stwu	r0, -4(r1)
 	stwu	r0, -4(r1)
 
@@ -1011,10 +1032,16 @@
 	/*
 	 * Stack in OCM.
 	 */
-
-	/* Set up Stack at top of OCM */
-	lis	r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)@h
-	ori	r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)@l
+	lis	r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE)@h
+	ori	r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE)@l
+	/*
+	 * Reserve space for globals and store address for initialization
+	 * with board_init_f_init_reserve() in r14
+	 */
+	mr	r3, r1
+	bl	board_init_f_alloc_reserve
+	mr	r1, r3
+	mr	r14, r3
 
 	/* Set up a zeroized stack frame so that backtrace works right */
 	li	r0, 0
@@ -1035,12 +1062,9 @@
 	GET_GOT			/* initialize GOT access			*/
 
 	bl	cpu_init_f	/* run low-level CPU init code	   (from Flash) */
-	mr	r3, r1
-	bl	board_init_f_alloc_reserve
-	mr	r1, r3
+	/* address for globals was stored in r14 */
+	mr	r3, r14
 	bl	board_init_f_init_reserve
-	stwu	r0, -4(r1)
-	stwu	r0, -4(r1)
 	li	r3, 0
 	bl	board_init_f	/* run first part of init code (from Flash)	*/
 	/* NOTREACHED - board_init_f() does not return */
diff --git a/arch/powerpc/include/asm/arch-mpc85xx/gpio.h b/arch/powerpc/include/asm/arch-mpc85xx/gpio.h
index 41b6677..76faa22 100644
--- a/arch/powerpc/include/asm/arch-mpc85xx/gpio.h
+++ b/arch/powerpc/include/asm/arch-mpc85xx/gpio.h
@@ -18,4 +18,10 @@
 #include <asm/mpc85xx_gpio.h>
 #endif
 
+struct mpc85xx_gpio_plat {
+	ulong addr;
+	unsigned long size;
+	uint ngpios;
+};
+
 #endif
diff --git a/arch/powerpc/include/asm/fsl_secure_boot.h b/arch/powerpc/include/asm/fsl_secure_boot.h
index 826f9c9..2e937f0 100644
--- a/arch/powerpc/include/asm/fsl_secure_boot.h
+++ b/arch/powerpc/include/asm/fsl_secure_boot.h
@@ -35,7 +35,9 @@
 	defined(CONFIG_T104xD4RDB) || \
 	defined(CONFIG_PPC_T1023) || \
 	defined(CONFIG_PPC_T1024)
+#ifndef CONFIG_SYS_RAMBOOT
 #define CONFIG_SYS_CPC_REINIT_F
+#endif
 #define CONFIG_KEY_REVOCATION
 #undef CONFIG_SYS_INIT_L3_ADDR
 #define CONFIG_SYS_INIT_L3_ADDR			0xbff00000
@@ -43,7 +45,13 @@
 
 #if defined(CONFIG_RAMBOOT_PBL)
 #undef CONFIG_SYS_INIT_L3_ADDR
-#define CONFIG_SYS_INIT_L3_ADDR			0xbff00000
+#ifdef CONFIG_SYS_INIT_L3_VADDR
+#define CONFIG_SYS_INIT_L3_ADDR	\
+			(CONFIG_SYS_INIT_L3_VADDR & ~0xFFF00000) | \
+					0xbff00000
+#else
+#define CONFIG_SYS_INIT_L3_ADDR		0xbff00000
+#endif
 #endif
 
 #if defined(CONFIG_C29XPCIE)
@@ -72,6 +80,32 @@
 
 #ifdef CONFIG_CHAIN_OF_TRUST
 
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SPL_DM			1
+#define CONFIG_SPL_CRYPTO_SUPPORT
+#define CONFIG_SPL_HASH_SUPPORT
+#define CONFIG_SPL_RSA
+#define CONFIG_SPL_DRIVERS_MISC_SUPPORT
+/*
+ * PPAACT and SPAACT table for PAMU must be placed on DDR after DDR init
+ * due to space crunch on CPC and thus malloc will not work.
+ */
+#define CONFIG_SPL_PPAACT_ADDR		0x2e000000
+#define CONFIG_SPL_SPAACT_ADDR		0x2f000000
+#define CONFIG_SPL_JR0_LIODN_S		454
+#define CONFIG_SPL_JR0_LIODN_NS		458
+/*
+ * Define the key hash for U-Boot here if public/private key pair used to
+ * sign U-boot are different from the SRK hash put in the fuse
+ * Example of defining KEY_HASH is
+ * #define CONFIG_SPL_UBOOT_KEY_HASH \
+ *      "41066b564c6ffcef40ccbc1e0a5d0d519604000c785d97bbefd25e4d288d1c8b"
+ * else leave it defined as NULL
+ */
+
+#define CONFIG_SPL_UBOOT_KEY_HASH	NULL
+#endif /* ifdef CONFIG_SPL_BUILD */
+
 #define CONFIG_CMD_ESBC_VALIDATE
 #define CONFIG_CMD_BLOB
 #define CONFIG_FSL_SEC_MON
@@ -82,7 +116,9 @@
 #define CONFIG_FSL_CAAM
 #endif
 
-/* fsl_setenv_chain_of_trust() must be called from
+#ifndef CONFIG_SPL_BUILD
+/*
+ * fsl_setenv_chain_of_trust() must be called from
  * board_late_init()
  */
 #ifndef CONFIG_BOARD_LATE_INIT
@@ -92,10 +128,10 @@
 /* If Boot Script is not on NOR and is required to be copied on RAM */
 #ifdef CONFIG_BOOTSCRIPT_COPY_RAM
 #define CONFIG_BS_HDR_ADDR_RAM		0x00010000
-#define CONFIG_BS_HDR_ADDR_FLASH	0x00800000
+#define CONFIG_BS_HDR_ADDR_DEVICE	0x00800000
 #define CONFIG_BS_HDR_SIZE		0x00002000
 #define CONFIG_BS_ADDR_RAM		0x00012000
-#define CONFIG_BS_ADDR_FLASH		0x00802000
+#define CONFIG_BS_ADDR_DEVICE		0x00802000
 #define CONFIG_BS_SIZE			0x00001000
 
 #define CONFIG_BOOTSCRIPT_HDR_ADDR	CONFIG_BS_HDR_ADDR_RAM
@@ -119,5 +155,6 @@
 #endif /* #ifdef CONFIG_BOOTSCRIPT_COPY_RAM */
 
 #include <config_fsl_chain_trust.h>
+#endif /* #ifndef CONFIG_SPL_BUILD */
 #endif /* #ifdef CONFIG_CHAIN_OF_TRUST */
 #endif
diff --git a/arch/powerpc/include/asm/immap_85xx.h b/arch/powerpc/include/asm/immap_85xx.h
index c045a24..7a878be 100644
--- a/arch/powerpc/include/asm/immap_85xx.h
+++ b/arch/powerpc/include/asm/immap_85xx.h
@@ -1579,7 +1579,7 @@
 #define CPC_HDBCR0_CDQ_SPEC_DIS	0x08000000
 #define CPC_HDBCR0_TAG_ECC_SCRUB_DIS	0x01000000
 #define CPC_HDBCR0_DATA_ECC_SCRUB_DIS	0x00400000
-#define CPC_HDBCR0_SPLRU_LEVEL_EN	0x003c0000
+#define CPC_HDBCR0_SPLRU_LEVEL_EN	0x001e0000
 #endif /* CONFIG_SYS_FSL_CPC */
 
 /* Global Utilities Block */
diff --git a/arch/powerpc/include/asm/status_led.h b/arch/powerpc/include/asm/status_led.h
index 4416190..260a831 100644
--- a/arch/powerpc/include/asm/status_led.h
+++ b/arch/powerpc/include/asm/status_led.h
@@ -7,7 +7,7 @@
 #ifndef __ASM_STATUS_LED_H__
 #define __ASM_STATUS_LED_H__
 
-/* if not overriden */
+/* if not overridden */
 #ifndef CONFIG_BOARD_SPECIFIC_LED
 # if defined(CONFIG_8xx)
 #  include <mpc8xx.h>
diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index a8a90cb..d4c1ee0 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -10,8 +10,13 @@
 config SYS_CPU
 	default "sandbox"
 
+config SANDBOX_SPL
+	bool "Enable SPL for sandbox"
+	select SUPPORT_SPL
+
 config SYS_CONFIG_NAME
-	default "sandbox"
+	default "sandbox_spl" if SANDBOX_SPL
+	default "sandbox" if !SANDBOX_SPL
 
 config PCI
 	bool "PCI support"
diff --git a/arch/sandbox/config.mk b/arch/sandbox/config.mk
index 16fd6d50..6d62abb 100644
--- a/arch/sandbox/config.mk
+++ b/arch/sandbox/config.mk
@@ -20,4 +20,9 @@
 	-Wl,--start-group $(u-boot-main) -Wl,--end-group \
 	$(PLATFORM_LIBS) -Wl,-Map -Wl,u-boot.map
 
+cmd_u-boot-spl = (cd $(obj) && $(CC) -o $(SPL_BIN) -Wl,-T u-boot-spl.lds \
+	-Wl,--start-group $(patsubst $(obj)/%,%,$(u-boot-spl-main)) \
+	$(patsubst $(obj)/%,%,$(u-boot-spl-platdata)) -Wl,--end-group \
+	$(PLATFORM_LIBS) -Wl,-Map -Wl,u-boot-spl.map -Wl,--gc-sections)
+
 CONFIG_ARCH_DEVICE_TREE := sandbox
diff --git a/arch/sandbox/cpu/Makefile b/arch/sandbox/cpu/Makefile
index 1b42fee..db43633 100644
--- a/arch/sandbox/cpu/Makefile
+++ b/arch/sandbox/cpu/Makefile
@@ -8,6 +8,7 @@
 #
 
 obj-y	:= cpu.o os.o start.o state.o
+obj-$(CONFIG_SPL_BUILD)	+= spl.o
 obj-$(CONFIG_ETH_SANDBOX_RAW)	+= eth-raw-os.o
 obj-$(CONFIG_SANDBOX_SDL)	+= sdl.o
 
diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c
index 196f3e1..2def722 100644
--- a/arch/sandbox/cpu/cpu.c
+++ b/arch/sandbox/cpu/cpu.c
@@ -4,10 +4,12 @@
  */
 #define DEBUG
 #include <common.h>
-#include <dm/root.h>
+#include <errno.h>
+#include <libfdt.h>
 #include <os.h>
 #include <asm/io.h>
 #include <asm/state.h>
+#include <dm/root.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -55,7 +57,7 @@
 
 void *map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
 {
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && !defined(CONFIG_SPL_BUILD)
 	unsigned long plen = len;
 	void *ptr;
 
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 8a4d719..2d63dd8 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -541,6 +541,57 @@
 	return unlink(fname);
 }
 
+int os_find_u_boot(char *fname, int maxlen)
+{
+	struct sandbox_state *state = state_get_current();
+	const char *progname = state->argv[0];
+	int len = strlen(progname);
+	char *p;
+	int fd;
+
+	if (len >= maxlen || len < 4)
+		return -ENOSPC;
+
+	/* Look for 'u-boot' in the same directory as 'u-boot-spl' */
+	strcpy(fname, progname);
+	if (!strcmp(fname + len - 4, "-spl")) {
+		fname[len - 4] = '\0';
+		fd = os_open(fname, O_RDONLY);
+		if (fd >= 0) {
+			close(fd);
+			return 0;
+		}
+	}
+
+	/* Look for 'u-boot' in the parent directory of spl/ */
+	p = strstr(fname, "/spl/");
+	if (p) {
+		strcpy(p, p + 4);
+		fd = os_open(fname, O_RDONLY);
+		if (fd >= 0) {
+			close(fd);
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
+int os_spl_to_uboot(const char *fname)
+{
+	struct sandbox_state *state = state_get_current();
+	char *argv[state->argc + 1];
+	int ret;
+
+	memcpy(argv, state->argv, sizeof(char *) * (state->argc + 1));
+	argv[0] = (char *)fname;
+	ret = execv(fname, argv);
+	if (ret)
+		return ret;
+
+	return unlink(fname);
+}
+
 void os_localtime(struct rtc_time *rt)
 {
 	time_t t = time(NULL);
diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c
new file mode 100644
index 0000000..e8349c0
--- /dev/null
+++ b/arch/sandbox/cpu/spl.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <os.h>
+#include <spl.h>
+#include <asm/spl.h>
+#include <asm/state.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void board_init_f(ulong flag)
+{
+	struct sandbox_state *state = state_get_current();
+
+	gd->arch.ram_buf = state->ram_buf;
+	gd->ram_size = state->ram_size;
+}
+
+u32 spl_boot_device(void)
+{
+	return BOOT_DEVICE_BOARD;
+}
+
+void spl_board_announce_boot_device(void)
+{
+	char fname[256];
+	int ret;
+
+	ret = os_find_u_boot(fname, sizeof(fname));
+	if (ret) {
+		printf("(%s not found, error %d)\n", fname, ret);
+		return;
+	}
+	printf("%s\n", fname);
+}
+
+int spl_board_load_image(void)
+{
+	char fname[256];
+	int ret;
+
+	ret = os_find_u_boot(fname, sizeof(fname));
+	if (ret)
+		return ret;
+
+	/* Hopefully this will not return */
+	return os_spl_to_uboot(fname);
+}
+
+void spl_board_init(void)
+{
+	struct udevice *dev;
+
+	preloader_console_init();
+
+	/*
+	* Scan all the devices so that we can output their platform data. See
+	* sandbox_spl_probe().
+	*/
+	for (uclass_first_device(UCLASS_MISC, &dev);
+	dev;
+	uclass_next_device(&dev))
+		;
+}
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 969618e..6e4ec01 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -73,6 +73,7 @@
 }
 SANDBOX_CMDLINE_OPT_SHORT(help, 'h', 0, "Display help");
 
+#ifndef CONFIG_SPL_BUILD
 int sandbox_main_loop_init(void)
 {
 	struct sandbox_state *state = state_get_current();
@@ -97,6 +98,7 @@
 
 	return 0;
 }
+#endif
 
 static int sandbox_cmdline_cb_boot(struct sandbox_state *state,
 				      const char *arg)
diff --git a/arch/sandbox/cpu/u-boot-spl.lds b/arch/sandbox/cpu/u-boot-spl.lds
new file mode 100644
index 0000000..7e92b4a
--- /dev/null
+++ b/arch/sandbox/cpu/u-boot-spl.lds
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2011-2012 The Chromium OS Authors.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+SECTIONS
+{
+
+	. = ALIGN(4);
+	.u_boot_list : {
+		KEEP(*(SORT(.u_boot_list*)));
+	}
+
+	__u_boot_sandbox_option_start = .;
+	_u_boot_sandbox_getopt : { *(.u_boot_sandbox_getopt) }
+	__u_boot_sandbox_option_end = .;
+
+	__bss_start = .;
+}
+
+INSERT BEFORE .data;
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 2ae4014..e6d336f 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -172,6 +172,37 @@
 		};
 	};
 
+	spl-test {
+		u-boot,dm-pre-reloc;
+		compatible = "sandbox,spl-test";
+		boolval;
+		intval = <1>;
+		intarray = <2 3 4>;
+		byteval = [05];
+		bytearray = [06];
+		longbytearray = [09 0a 0b 0c 0d 0e 0f 10 11];
+		stringval = "message";
+		stringarray = "multi-word", "message";
+	};
+
+	spl-test2 {
+		u-boot,dm-pre-reloc;
+		compatible = "sandbox,spl-test";
+		intval = <3>;
+		intarray = <5>;
+		byteval = [08];
+		bytearray = [01 23 34];
+		longbytearray = [09 0a 0b 0c];
+		stringval = "message2";
+		stringarray = "another", "multi-word", "message";
+	};
+
+	spl-test3 {
+		u-boot,dm-pre-reloc;
+		compatible = "sandbox,spl-test";
+		stringarray = "one";
+	};
+
 	square {
 		compatible = "demo-shape";
 		colour = "blue";
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 9e46f9e..fff175d 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -262,6 +262,16 @@
 		};
 	};
 
+	pwrdom: power-domain {
+		compatible = "sandbox,power-domain";
+		#power-domain-cells = <1>;
+	};
+
+	power-domain-test {
+		compatible = "sandbox,power-domain-test";
+		power-domains = <&pwrdom 2>;
+	};
+
 	ram {
 		compatible = "sandbox,ram";
 	};
diff --git a/arch/sandbox/include/asm/power-domain.h b/arch/sandbox/include/asm/power-domain.h
new file mode 100644
index 0000000..cad3885
--- /dev/null
+++ b/arch/sandbox/include/asm/power-domain.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef __SANDBOX_POWER_DOMAIN_H
+#define __SANDBOX_POWER_DOMAIN_H
+
+#include <common.h>
+
+struct udevice;
+
+int sandbox_power_domain_query(struct udevice *dev, unsigned long id);
+
+int sandbox_power_domain_test_get(struct udevice *dev);
+int sandbox_power_domain_test_on(struct udevice *dev);
+int sandbox_power_domain_test_off(struct udevice *dev);
+int sandbox_power_domain_test_free(struct udevice *dev);
+
+#endif
diff --git a/arch/sandbox/include/asm/spl.h b/arch/sandbox/include/asm/spl.h
new file mode 100644
index 0000000..59f2401
--- /dev/null
+++ b/arch/sandbox/include/asm/spl.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __asm_spl_h
+#define __asm_spl_h
+
+#define CONFIG_SPL_BOARD_LOAD_IMAGE
+
+/**
+ * Board-specific load method for boards that have a special way of loading
+ * U-Boot, which does not fit with the existing SPL code.
+ *
+ * @return 0 on success, negative errno value on failure.
+ */
+int spl_board_load_image(void);
+
+enum {
+	BOOT_DEVICE_BOARD,
+};
+
+#endif
diff --git a/arch/sandbox/lib/Makefile b/arch/sandbox/lib/Makefile
index 96761e2..2e7802f 100644
--- a/arch/sandbox/lib/Makefile
+++ b/arch/sandbox/lib/Makefile
@@ -8,5 +8,8 @@
 #
 
 obj-y	+= interrupts.o
+ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_PCI)	+= pci_io.o
+endif
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
+obj-$(CONFIG_CMD_BOOTZ) += bootm.o
diff --git a/arch/sandbox/lib/bootm.c b/arch/sandbox/lib/bootm.c
index d49c927..0c9a797 100644
--- a/arch/sandbox/lib/bootm.c
+++ b/arch/sandbox/lib/bootm.c
@@ -56,7 +56,7 @@
 		bootstage_mark(BOOTSTAGE_ID_RUN_OS);
 		printf("## Transferring control to Linux (at address %08lx)...\n",
 		       images->ep);
-		reset_cpu(0);
+		printf("sandbox: continuing, as we cannot run Linux\n");
 	}
 
 	return 0;
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 0a00db3..5dc27be 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -128,39 +128,6 @@
 #define in_8(port)			inb(port)
 #define in_le16(port)		inw(port)
 #define in_le32(port)		inl(port)
-/*
- * ioremap and friends.
- *
- * ioremap takes a PCI memory address, as specified in
- * linux/Documentation/IO-mapping.txt.  If you want a
- * physical address, use __ioremap instead.
- */
-extern void *__ioremap(unsigned long offset, size_t size, unsigned long flags);
-extern void __iounmap(void *addr);
-
-/*
- * Generic ioremap support.
- *
- * Define:
- *  iomem_valid_addr(off,size)
- *  iomem_to_phys(off)
- */
-#ifdef iomem_valid_addr
-#define __arch_ioremap(off, sz, nocache)				\
-({								\
-	unsigned long _off = (off), _size = (sz);		\
-	void *_ret = (void *)0;					\
-	if (iomem_valid_addr(_off, _size))			\
-		_ret = __ioremap(iomem_to_phys(_off), _size, 0);	\
-	_ret;							\
-})
-
-#define __arch_iounmap __iounmap
-#endif
-
-#define ioremap(off, sz)			__arch_ioremap((off), (sz), 0)
-#define ioremap_nocache(off, sz)		__arch_ioremap((off), (sz), 1)
-#define iounmap(_addr)			__arch_iounmap(_addr)
 
 /*
  * DMA-consistent mapping functions.  These allocate/free a region of
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 29d2307..5193ee7 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -8,12 +8,18 @@
 	prompt "Mainboard vendor"
 	default VENDOR_EMULATION
 
+config VENDOR_ADVANTECH
+	bool "advantech"
+
 config VENDOR_CONGATEC
 	bool "congatec"
 
 config VENDOR_COREBOOT
 	bool "coreboot"
 
+config VENDOR_DFI
+	bool "dfi"
+
 config VENDOR_EFI
 	bool "efi"
 
@@ -29,8 +35,10 @@
 endchoice
 
 # board-specific options below
+source "board/advantech/Kconfig"
 source "board/congatec/Kconfig"
 source "board/coreboot/Kconfig"
+source "board/dfi/Kconfig"
 source "board/efi/Kconfig"
 source "board/emulation/Kconfig"
 source "board/google/Kconfig"
diff --git a/arch/x86/cpu/baytrail/Kconfig b/arch/x86/cpu/baytrail/Kconfig
index 407feb2..1c8ac37 100644
--- a/arch/x86/cpu/baytrail/Kconfig
+++ b/arch/x86/cpu/baytrail/Kconfig
@@ -7,3 +7,14 @@
 config INTEL_BAYTRAIL
 	bool
 	select HAVE_FSP if !EFI
+
+if INTEL_BAYTRAIL
+config INTERNAL_UART
+	bool "Enable the SoC integrated legacy UART"
+	help
+	  There is a legacy UART integrated into the Bay Trail SoC.
+	  A maximum baud rate of 115200 bps is supported. For this
+	  reason, it is recommended that the UART port be used for
+	  debug purposes only, eg: U-Boot console.
+
+endif
diff --git a/arch/x86/cpu/baytrail/acpi.c b/arch/x86/cpu/baytrail/acpi.c
index 5ee4868..fa92d88 100644
--- a/arch/x86/cpu/baytrail/acpi.c
+++ b/arch/x86/cpu/baytrail/acpi.c
@@ -5,10 +5,14 @@
  */
 
 #include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <dm/uclass-internal.h>
 #include <asm/acpi_table.h>
 #include <asm/ioapic.h>
 #include <asm/mpspec.h>
 #include <asm/tables.h>
+#include <asm/arch/global_nvs.h>
 #include <asm/arch/iomap.h>
 
 void acpi_create_fadt(struct acpi_fadt *fadt, struct acpi_facs *facs,
@@ -161,3 +165,25 @@
 
 	return current;
 }
+
+void acpi_create_gnvs(struct acpi_global_nvs *gnvs)
+{
+	struct udevice *dev;
+	int ret;
+
+	/* at least we have one processor */
+	gnvs->pcnt = 1;
+	/* override the processor count with actual number */
+	ret = uclass_find_first_device(UCLASS_CPU, &dev);
+	if (ret == 0 && dev != NULL) {
+		ret = cpu_get_count(dev);
+		if (ret > 0)
+			gnvs->pcnt = ret;
+	}
+
+	/* determine whether internal uart is on */
+	if (IS_ENABLED(CONFIG_INTERNAL_UART))
+		gnvs->iuart_en = 1;
+	else
+		gnvs->iuart_en = 0;
+}
diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c
index b1faf8c..2837709 100644
--- a/arch/x86/cpu/baytrail/cpu.c
+++ b/arch/x86/cpu/baytrail/cpu.c
@@ -9,12 +9,60 @@
 #include <common.h>
 #include <cpu.h>
 #include <dm.h>
+#include <pci.h>
 #include <asm/cpu.h>
 #include <asm/cpu_x86.h>
+#include <asm/io.h>
 #include <asm/lapic.h>
 #include <asm/msr.h>
 #include <asm/turbo.h>
 
+#define BYT_PRV_CLK			0x800
+#define BYT_PRV_CLK_EN			(1 << 0)
+#define BYT_PRV_CLK_M_VAL_SHIFT		1
+#define BYT_PRV_CLK_N_VAL_SHIFT		16
+#define BYT_PRV_CLK_UPDATE		(1 << 31)
+
+static void hsuart_clock_set(void *base)
+{
+	u32 m, n, reg;
+
+	/*
+	 * Configure the BayTrail UART clock for the internal HS UARTs
+	 * (PCI devices) to 58982400 Hz
+	 */
+	m = 0x2400;
+	n = 0x3d09;
+	reg = (m << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT);
+	writel(reg, base + BYT_PRV_CLK);
+	reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
+	writel(reg, base + BYT_PRV_CLK);
+}
+
+/*
+ * Configure the internal clock of both SIO HS-UARTs, if they are enabled
+ * via FSP
+ */
+int arch_cpu_init_dm(void)
+{
+	struct udevice *dev;
+	void *base;
+	int ret;
+	int i;
+
+	/* Loop over the 2 HS-UARTs */
+	for (i = 0; i < 2; i++) {
+		ret = dm_pci_bus_find_bdf(PCI_BDF(0, 0x1e, 3 + i), &dev);
+		if (!ret) {
+			base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
+					      PCI_REGION_MEM);
+			hsuart_clock_set(base);
+		}
+	}
+
+	return 0;
+}
+
 static void set_max_freq(void)
 {
 	msr_t perf_ctl;
diff --git a/arch/x86/cpu/ivybridge/lpc.c b/arch/x86/cpu/ivybridge/lpc.c
index ff1faa5..4e0be2a 100644
--- a/arch/x86/cpu/ivybridge/lpc.c
+++ b/arch/x86/cpu/ivybridge/lpc.c
@@ -424,8 +424,6 @@
 static int lpc_init_extra(struct udevice *dev)
 {
 	struct udevice *pch = dev->parent;
-	const void *blob = gd->fdt_blob;
-	int node;
 
 	debug("pch: lpc_init\n");
 	dm_pci_write_bar32(pch, 0, 0);
@@ -434,10 +432,6 @@
 	dm_pci_write_bar32(pch, 3, 0x800);
 	dm_pci_write_bar32(pch, 4, 0x900);
 
-	node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_PCH);
-	if (node < 0)
-		return -ENOENT;
-
 	/* Set the value for PCI command register. */
 	dm_pci_write_config16(pch, PCI_COMMAND, 0x000f);
 
diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c
index 9d9f63d..e0b06b5 100644
--- a/arch/x86/cpu/ivybridge/sdram.c
+++ b/arch/x86/cpu/ivybridge/sdram.c
@@ -458,6 +458,11 @@
 	struct udevice *dev, *me_dev;
 	int ret;
 
+	/* We need the pinctrl set up early */
+	ret = syscon_get_by_driver_data(X86_SYSCON_PINCONF, &dev);
+	if (ret)
+		return ret;
+
 	ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev);
 	if (ret)
 		return ret;
diff --git a/arch/x86/cpu/quark/acpi.c b/arch/x86/cpu/quark/acpi.c
index 8f69829..3968f7a 100644
--- a/arch/x86/cpu/quark/acpi.c
+++ b/arch/x86/cpu/quark/acpi.c
@@ -9,6 +9,7 @@
 #include <asm/ioapic.h>
 #include <asm/mpspec.h>
 #include <asm/tables.h>
+#include <asm/arch/global_nvs.h>
 #include <asm/arch/iomap.h>
 
 void acpi_create_fadt(struct acpi_fadt *fadt, struct acpi_facs *facs,
@@ -161,3 +162,9 @@
 
 	return current;
 }
+
+void acpi_create_gnvs(struct acpi_global_nvs *gnvs)
+{
+	/* quark is a uni-processor */
+	gnvs->pcnt = 1;
+}
diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile
index 23156bb..3f534ad 100644
--- a/arch/x86/dts/Makefile
+++ b/arch/x86/dts/Makefile
@@ -9,12 +9,15 @@
 	conga-qeval20-qa3-e3845.dtb \
 	cougarcanyon2.dtb \
 	crownbay.dtb \
+	dfi-bt700-q7x-151.dtb \
 	efi.dtb \
 	galileo.dtb \
 	minnowmax.dtb \
 	qemu-x86_i440fx.dtb \
 	qemu-x86_q35.dtb \
-	broadwell_som-6896.dtb
+	theadorable-x86-dfi-bt700.dtb \
+	broadwell_som-6896.dtb \
+	baytrail_som-db5800-som-6867.dtb
 
 targets += $(dtb-y)
 
diff --git a/arch/x86/dts/baytrail_som-db5800-som-6867.dts b/arch/x86/dts/baytrail_som-db5800-som-6867.dts
new file mode 100644
index 0000000..e1d81a7
--- /dev/null
+++ b/arch/x86/dts/baytrail_som-db5800-som-6867.dts
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ * Copyright (C) 2016, George McCollister <george.mccollister@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/x86-gpio.h>
+#include <dt-bindings/interrupt-router/intel-irq.h>
+
+/include/ "skeleton.dtsi"
+/include/ "serial.dtsi"
+/include/ "rtc.dtsi"
+/include/ "tsc_timer.dtsi"
+
+/ {
+	model = "Advantech SOM-DB5800-SOM-6867";
+	compatible = "advantech,som-db5800-som-6867", "intel,baytrail";
+
+	aliases {
+		serial0 = &serial;
+		spi0 = &spi;
+	};
+
+	config {
+		silent_console = <0>;
+	};
+
+	pch_pinctrl {
+		compatible = "intel,x86-pinctrl";
+		reg = <0 0>;
+
+		/* HDA_RSTB */
+		soc_gpio_s0_8@0 {
+			pad-offset = <0x220>;
+			mode-func = <2>;
+		};
+
+		/* HDA_SYNC */
+		soc_gpio_s0_9@0 {
+			pad-offset = <0x250>;
+			mode-func = <2>;
+			pull-assign = <1>;
+		};
+
+		/* HDA_CLK */
+		soc_gpio_s0_10@0 {
+			pad-offset = <0x240>;
+			mode-func = <2>;
+		};
+
+		/* HDA_SDO */
+		soc_gpio_s0_11@0 {
+			pad-offset = <0x260>;
+			mode-func = <2>;
+			pull-assign = <1>;
+		};
+
+		/* HDA_SDI0 */
+		soc_gpio_s0_12@0 {
+			pad-offset = <0x270>;
+			mode-func = <2>;
+		};
+
+		/* SERIRQ */
+		soc_gpio_s0_50@0 {
+			pad-offset = <0x560>;
+			mode-func = <1>;
+		};
+	};
+
+	chosen {
+		stdout-path = "/serial";
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "intel,baytrail-cpu";
+			reg = <0>;
+			intel,apic-id = <0>;
+		};
+
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "intel,baytrail-cpu";
+			reg = <1>;
+			intel,apic-id = <2>;
+		};
+
+		cpu@2 {
+			device_type = "cpu";
+			compatible = "intel,baytrail-cpu";
+			reg = <2>;
+			intel,apic-id = <4>;
+		};
+
+		cpu@3 {
+			device_type = "cpu";
+			compatible = "intel,baytrail-cpu";
+			reg = <3>;
+			intel,apic-id = <6>;
+		};
+
+	};
+
+	pci {
+		compatible = "intel,pci-baytrail", "pci-x86";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		u-boot,dm-pre-reloc;
+		ranges = <0x02000000 0x0 0x80000000 0x80000000 0 0x40000000
+			  0x42000000 0x0 0xc0000000 0xc0000000 0 0x20000000
+			  0x01000000 0x0 0x2000 0x2000 0 0xe000>;
+
+		pch@1f,0 {
+			reg = <0x0000f800 0 0 0 0>;
+			compatible = "pci8086,0f1c", "intel,pch9";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			irq-router {
+				compatible = "intel,irq-router";
+				intel,pirq-config = "ibase";
+				intel,ibase-offset = <0x50>;
+				intel,actl-addr = <0>;
+				intel,pirq-link = <8 8>;
+				intel,pirq-mask = <0xdee0>;
+				intel,pirq-routing = <
+					/* BayTrail PCI devices */
+					PCI_BDF(0, 2, 0) INTA PIRQA
+					PCI_BDF(0, 3, 0) INTA PIRQA
+					PCI_BDF(0, 16, 0) INTA PIRQA
+					PCI_BDF(0, 17, 0) INTA PIRQA
+					PCI_BDF(0, 18, 0) INTA PIRQA
+					PCI_BDF(0, 19, 0) INTA PIRQA
+					PCI_BDF(0, 20, 0) INTA PIRQA
+					PCI_BDF(0, 21, 0) INTA PIRQA
+					PCI_BDF(0, 22, 0) INTA PIRQA
+					PCI_BDF(0, 23, 0) INTA PIRQA
+					PCI_BDF(0, 24, 0) INTA PIRQA
+					PCI_BDF(0, 24, 1) INTC PIRQC
+					PCI_BDF(0, 24, 2) INTD PIRQD
+					PCI_BDF(0, 24, 3) INTB PIRQB
+					PCI_BDF(0, 24, 4) INTA PIRQA
+					PCI_BDF(0, 24, 5) INTC PIRQC
+					PCI_BDF(0, 24, 6) INTD PIRQD
+					PCI_BDF(0, 24, 7) INTB PIRQB
+					PCI_BDF(0, 26, 0) INTA PIRQA
+					PCI_BDF(0, 27, 0) INTA PIRQA
+					PCI_BDF(0, 28, 0) INTA PIRQA
+					PCI_BDF(0, 28, 1) INTB PIRQB
+					PCI_BDF(0, 28, 2) INTC PIRQC
+					PCI_BDF(0, 28, 3) INTD PIRQD
+					PCI_BDF(0, 29, 0) INTA PIRQA
+					PCI_BDF(0, 30, 0) INTA PIRQA
+					PCI_BDF(0, 30, 1) INTD PIRQD
+					PCI_BDF(0, 30, 2) INTB PIRQB
+					PCI_BDF(0, 30, 3) INTC PIRQC
+					PCI_BDF(0, 30, 4) INTD PIRQD
+					PCI_BDF(0, 30, 5) INTB PIRQB
+					PCI_BDF(0, 31, 3) INTB PIRQB
+
+					/*
+					 * PCIe root ports downstream
+					 * interrupts
+					 */
+					PCI_BDF(1, 0, 0) INTA PIRQA
+					PCI_BDF(1, 0, 0) INTB PIRQB
+					PCI_BDF(1, 0, 0) INTC PIRQC
+					PCI_BDF(1, 0, 0) INTD PIRQD
+					PCI_BDF(2, 0, 0) INTA PIRQB
+					PCI_BDF(2, 0, 0) INTB PIRQC
+					PCI_BDF(2, 0, 0) INTC PIRQD
+					PCI_BDF(2, 0, 0) INTD PIRQA
+					PCI_BDF(3, 0, 0) INTA PIRQC
+					PCI_BDF(3, 0, 0) INTB PIRQD
+					PCI_BDF(3, 0, 0) INTC PIRQA
+					PCI_BDF(3, 0, 0) INTD PIRQB
+					PCI_BDF(4, 0, 0) INTA PIRQD
+					PCI_BDF(4, 0, 0) INTB PIRQA
+					PCI_BDF(4, 0, 0) INTC PIRQB
+					PCI_BDF(4, 0, 0) INTD PIRQC
+				>;
+			};
+
+			spi: spi {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "intel,ich9-spi";
+				spi-flash@0 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					reg = <0>;
+					compatible = "macronix,mx25l6405d",
+						"spi-flash";
+					memory-map = <0xff800000 0x00800000>;
+					rw-mrc-cache {
+						label = "rw-mrc-cache";
+						reg = <0x006f0000 0x00010000>;
+					};
+				};
+			};
+
+			gpioa {
+				compatible = "intel,ich6-gpio";
+				u-boot,dm-pre-reloc;
+				reg = <0 0x20>;
+				bank-name = "A";
+			};
+
+			gpiob {
+				compatible = "intel,ich6-gpio";
+				u-boot,dm-pre-reloc;
+				reg = <0x20 0x20>;
+				bank-name = "B";
+			};
+
+			gpioc {
+				compatible = "intel,ich6-gpio";
+				u-boot,dm-pre-reloc;
+				reg = <0x40 0x20>;
+				bank-name = "C";
+			};
+
+			gpiod {
+				compatible = "intel,ich6-gpio";
+				u-boot,dm-pre-reloc;
+				reg = <0x60 0x20>;
+				bank-name = "D";
+			};
+
+			gpioe {
+				compatible = "intel,ich6-gpio";
+				u-boot,dm-pre-reloc;
+				reg = <0x80 0x20>;
+				bank-name = "E";
+			};
+
+			gpiof {
+				compatible = "intel,ich6-gpio";
+				u-boot,dm-pre-reloc;
+				reg = <0xA0 0x20>;
+				bank-name = "F";
+			};
+		};
+	};
+
+	fsp {
+		compatible = "intel,baytrail-fsp";
+		fsp,mrc-init-tseg-size = <0>;
+		fsp,mrc-init-mmio-size = <0x800>;
+		fsp,mrc-init-spd-addr1 = <0xa0>;
+		fsp,mrc-init-spd-addr2 = <0xa2>;
+		fsp,enable-spi;
+		fsp,enable-sata;
+		fsp,sata-mode = <1>;
+		fsp,enable-azalia;
+		fsp,lpss-sio-enable-pci-mode;
+		fsp,enable-dma0;
+		fsp,enable-dma1;
+		fsp,enable-i2c0;
+		fsp,enable-i2c1;
+		fsp,enable-i2c2;
+		fsp,enable-i2c3;
+		fsp,enable-i2c4;
+		fsp,enable-i2c5;
+		fsp,enable-i2c6;
+		fsp,enable-pwm0;
+		fsp,enable-pwm1;
+		fsp,igd-dvmt50-pre-alloc = <2>;
+		fsp,aperture-size = <2>;
+		fsp,gtt-size = <2>;
+		fsp,scc-enable-pci-mode;
+		fsp,os-selection = <4>;
+		fsp,enable-igd;
+		fsp,serial-debug-port-address = <0x3f8>;
+		fsp,serial-debug-port-type = <1>;
+	};
+
+	microcode {
+		update@0 {
+#include "microcode/m0130673325.dtsi"
+		};
+		update@1 {
+#include "microcode/m0130679907.dtsi"
+		};
+	};
+
+};
diff --git a/arch/x86/dts/conga-qeval20-qa3-e3845.dts b/arch/x86/dts/conga-qeval20-qa3-e3845.dts
index fba089d..f0efe90 100644
--- a/arch/x86/dts/conga-qeval20-qa3-e3845.dts
+++ b/arch/x86/dts/conga-qeval20-qa3-e3845.dts
@@ -46,6 +46,17 @@
 			pad-offset = <0x3a0>;
 			mode-func = <1>;
 		};
+
+		/* Add SMBus PAD configuration */
+		smbus_clk@0 {
+			pad-offset = <0x580>;
+			mode-func = <1>;
+		};
+
+		smbus_data@0 {
+			pad-offset = <0x5a0>;
+			mode-func = <1>;
+		};
 	};
 
 	chosen {
@@ -244,13 +255,6 @@
 		fsp,lpss-sio-enable-pci-mode;
 		fsp,enable-dma0;
 		fsp,enable-dma1;
-		fsp,enable-i2c0;
-		fsp,enable-i2c1;
-		fsp,enable-i2c2;
-		fsp,enable-i2c3;
-		fsp,enable-i2c4;
-		fsp,enable-i2c5;
-		fsp,enable-i2c6;
 		fsp,enable-pwm0;
 		fsp,enable-pwm1;
 		fsp,igd-dvmt50-pre-alloc = <2>;
diff --git a/arch/x86/dts/dfi-bt700-q7x-151.dts b/arch/x86/dts/dfi-bt700-q7x-151.dts
new file mode 100644
index 0000000..31d9679
--- /dev/null
+++ b/arch/x86/dts/dfi-bt700-q7x-151.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+
+#include "dfi-bt700.dtsi"
+
+#include "serial.dtsi"
+
+/ {
+	model = "DFI-BT700";
+	compatible = "dfi,bt700", "intel,baytrail";
+
+	aliases {
+		serial0 = &serial;
+		spi0 = &spi;
+	};
+};
diff --git a/arch/x86/dts/dfi-bt700.dtsi b/arch/x86/dts/dfi-bt700.dtsi
new file mode 100644
index 0000000..75ee6ad
--- /dev/null
+++ b/arch/x86/dts/dfi-bt700.dtsi
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <dt-bindings/gpio/x86-gpio.h>
+#include <dt-bindings/interrupt-router/intel-irq.h>
+
+#include "skeleton.dtsi"
+#include "rtc.dtsi"
+#include "tsc_timer.dtsi"
+
+/ {
+	config {
+		silent_console = <0>;
+	};
+
+	pch_pinctrl {
+		compatible = "intel,x86-pinctrl";
+		reg = <0 0>;
+
+		/* Add UART1 PAD configuration (SIO HS-UART) */
+		uart1_txd@0 {
+			pad-offset = <0x10>;
+			mode-func = <1>;
+		};
+
+		uart1_rxd@0 {
+			pad-offset = <0x20>;
+			mode-func = <1>;
+		};
+
+		/*
+		 * As of today, the latest version FSP (gold4) for BayTrail
+		 * misses the PAD configuration of the SD controller's Card
+		 * Detect signal. The default PAD value for the CD pin sets
+		 * the pin to work in GPIO mode, which causes card detect
+		 * status cannot be reflected by the Present State register
+		 * in the SD controller (bit 16 & bit 18 are always zero).
+		 *
+		 * Configure this pin to function 1 (SD controller).
+		 */
+		sdmmc3_cd@0 {
+			pad-offset = <0x3a0>;
+			mode-func = <1>;
+		};
+	};
+
+	chosen {
+		stdout-path = "/serial";
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "intel,baytrail-cpu";
+			reg = <0>;
+			intel,apic-id = <0>;
+		};
+
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "intel,baytrail-cpu";
+			reg = <1>;
+			intel,apic-id = <2>;
+		};
+
+		cpu@2 {
+			device_type = "cpu";
+			compatible = "intel,baytrail-cpu";
+			reg = <2>;
+			intel,apic-id = <4>;
+		};
+
+		cpu@3 {
+			device_type = "cpu";
+			compatible = "intel,baytrail-cpu";
+			reg = <3>;
+			intel,apic-id = <6>;
+		};
+	};
+
+	pci {
+		compatible = "intel,pci-baytrail", "pci-x86";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		u-boot,dm-pre-reloc;
+		ranges = <0x02000000 0x0 0x80000000 0x80000000 0 0x40000000
+			  0x42000000 0x0 0xc0000000 0xc0000000 0 0x20000000
+			  0x01000000 0x0 0x2000 0x2000 0 0xe000>;
+
+		pciuart0: uart@1e,3 {
+			compatible = "pci8086,0f0a.00",
+					"pci8086,0f0a",
+					"pciclass,070002",
+					"pciclass,0700",
+					"ns16550";
+			u-boot,dm-pre-reloc;
+			reg = <0x0200f310 0x0 0x0 0x0 0x0>;
+			reg-shift = <2>;
+			clock-frequency = <58982400>;
+			current-speed = <115200>;
+		};
+
+		pch@1f,0 {
+			reg = <0x0000f800 0 0 0 0>;
+			compatible = "pci8086,0f1c", "intel,pch9";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			irq-router {
+				compatible = "intel,irq-router";
+				intel,pirq-config = "ibase";
+				intel,ibase-offset = <0x50>;
+				intel,actl-addr = <0>;
+				intel,pirq-link = <8 8>;
+				intel,pirq-mask = <0xdee0>;
+				intel,pirq-routing = <
+					/* BayTrail PCI devices */
+					PCI_BDF(0, 2, 0) INTA PIRQA
+					PCI_BDF(0, 3, 0) INTA PIRQA
+					PCI_BDF(0, 16, 0) INTA PIRQA
+					PCI_BDF(0, 17, 0) INTA PIRQA
+					PCI_BDF(0, 18, 0) INTA PIRQA
+					PCI_BDF(0, 19, 0) INTA PIRQA
+					PCI_BDF(0, 20, 0) INTA PIRQA
+					PCI_BDF(0, 21, 0) INTA PIRQA
+					PCI_BDF(0, 22, 0) INTA PIRQA
+					PCI_BDF(0, 23, 0) INTA PIRQA
+					PCI_BDF(0, 24, 0) INTA PIRQA
+					PCI_BDF(0, 24, 1) INTC PIRQC
+					PCI_BDF(0, 24, 2) INTD PIRQD
+					PCI_BDF(0, 24, 3) INTB PIRQB
+					PCI_BDF(0, 24, 4) INTA PIRQA
+					PCI_BDF(0, 24, 5) INTC PIRQC
+					PCI_BDF(0, 24, 6) INTD PIRQD
+					PCI_BDF(0, 24, 7) INTB PIRQB
+					PCI_BDF(0, 26, 0) INTA PIRQA
+					PCI_BDF(0, 27, 0) INTA PIRQA
+					PCI_BDF(0, 28, 0) INTA PIRQA
+					PCI_BDF(0, 28, 1) INTB PIRQB
+					PCI_BDF(0, 28, 2) INTC PIRQC
+					PCI_BDF(0, 28, 3) INTD PIRQD
+					PCI_BDF(0, 29, 0) INTA PIRQA
+					PCI_BDF(0, 30, 0) INTA PIRQA
+					PCI_BDF(0, 30, 1) INTD PIRQD
+					PCI_BDF(0, 30, 2) INTB PIRQB
+					PCI_BDF(0, 30, 3) INTC PIRQC
+					PCI_BDF(0, 30, 4) INTD PIRQD
+					PCI_BDF(0, 30, 5) INTB PIRQB
+					PCI_BDF(0, 31, 3) INTB PIRQB
+
+					/*
+					 * PCIe root ports downstream
+					 * interrupts
+					 */
+					PCI_BDF(1, 0, 0) INTA PIRQA
+					PCI_BDF(1, 0, 0) INTB PIRQB
+					PCI_BDF(1, 0, 0) INTC PIRQC
+					PCI_BDF(1, 0, 0) INTD PIRQD
+					PCI_BDF(2, 0, 0) INTA PIRQB
+					PCI_BDF(2, 0, 0) INTB PIRQC
+					PCI_BDF(2, 0, 0) INTC PIRQD
+					PCI_BDF(2, 0, 0) INTD PIRQA
+					PCI_BDF(3, 0, 0) INTA PIRQC
+					PCI_BDF(3, 0, 0) INTB PIRQD
+					PCI_BDF(3, 0, 0) INTC PIRQA
+					PCI_BDF(3, 0, 0) INTD PIRQB
+					PCI_BDF(4, 0, 0) INTA PIRQD
+					PCI_BDF(4, 0, 0) INTB PIRQA
+					PCI_BDF(4, 0, 0) INTC PIRQB
+					PCI_BDF(4, 0, 0) INTD PIRQC
+				>;
+			};
+
+			spi: spi {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "intel,ich9-spi";
+				spi-flash@0 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					reg = <0>;
+					compatible = "stmicro,n25q064a",
+						"spi-flash";
+					memory-map = <0xff800000 0x00800000>;
+					rw-mrc-cache {
+						label = "rw-mrc-cache";
+						reg = <0x006f0000 0x00010000>;
+					};
+				};
+			};
+
+			gpioa {
+				compatible = "intel,ich6-gpio";
+				u-boot,dm-pre-reloc;
+				reg = <0 0x20>;
+				bank-name = "A";
+			};
+
+			gpiob {
+				compatible = "intel,ich6-gpio";
+				u-boot,dm-pre-reloc;
+				reg = <0x20 0x20>;
+				bank-name = "B";
+			};
+
+			gpioc {
+				compatible = "intel,ich6-gpio";
+				u-boot,dm-pre-reloc;
+				reg = <0x40 0x20>;
+				bank-name = "C";
+			};
+
+			gpiod {
+				compatible = "intel,ich6-gpio";
+				u-boot,dm-pre-reloc;
+				reg = <0x60 0x20>;
+				bank-name = "D";
+			};
+
+			gpioe {
+				compatible = "intel,ich6-gpio";
+				u-boot,dm-pre-reloc;
+				reg = <0x80 0x20>;
+				bank-name = "E";
+			};
+
+			gpiof {
+				compatible = "intel,ich6-gpio";
+				u-boot,dm-pre-reloc;
+				reg = <0xA0 0x20>;
+				bank-name = "F";
+			};
+		};
+	};
+
+	fsp {
+		compatible = "intel,baytrail-fsp";
+		fsp,mrc-init-tseg-size = <0>;
+		fsp,mrc-init-mmio-size = <0x800>;
+		fsp,mrc-init-spd-addr1 = <0xa0>;
+		fsp,mrc-init-spd-addr2 = <0xa2>;
+		fsp,emmc-boot-mode = <1>;
+		fsp,enable-sdio;
+		fsp,enable-sdcard;
+		fsp,enable-hsuart0;
+		fsp,enable-hsuart1;
+		fsp,enable-spi;
+		fsp,enable-sata;
+		fsp,sata-mode = <1>;
+		fsp,enable-lpe;
+		fsp,lpss-sio-enable-pci-mode;
+		fsp,enable-dma0;
+		fsp,enable-dma1;
+		fsp,enable-i2c0;
+		fsp,enable-i2c1;
+		fsp,enable-i2c2;
+		fsp,enable-i2c3;
+		fsp,enable-i2c4;
+		fsp,enable-i2c5;
+		fsp,enable-i2c6;
+		fsp,enable-pwm0;
+		fsp,enable-pwm1;
+		fsp,igd-dvmt50-pre-alloc = <2>;
+		fsp,aperture-size = <2>;
+		fsp,gtt-size = <2>;
+		fsp,scc-enable-pci-mode;
+		fsp,os-selection = <4>;
+		fsp,emmc45-ddr50-enabled;
+		fsp,emmc45-retune-timer-value = <8>;
+		fsp,enable-igd;
+		fsp,enable-memory-down;
+		fsp,memory-down-params {
+			compatible = "intel,baytrail-fsp-mdp";
+			fsp,dram-speed = <2>;		/* 2=1333MHz */
+			fsp,dram-type = <1>;		/* 1=DDR3L */
+			fsp,dimm-0-enable;
+			fsp,dimm-width = <1>;		/* 1=x16, 2=x32 */
+			fsp,dimm-density = <3>;		/* 3=8Gbit */
+			fsp,dimm-bus-width = <3>;	/* 3=64bits */
+			fsp,dimm-sides = <0>;		/* 0=1 ranks -> 0x2b */
+
+			/* These following values might need a re-visit */
+			fsp,dimm-tcl = <8>;
+			fsp,dimm-trpt-rcd = <8>;
+			fsp,dimm-twr = <8>;
+			fsp,dimm-twtr = <4>;
+			fsp,dimm-trrd = <6>;
+			fsp,dimm-trtp = <4>;
+			fsp,dimm-tfaw = <22>;
+		};
+	};
+
+	microcode {
+		update@0 {
+#include "microcode/m0130673325.dtsi"
+		};
+		update@1 {
+#include "microcode/m0130679907.dtsi"
+		};
+	};
+};
diff --git a/arch/x86/dts/theadorable-x86-dfi-bt700.dts b/arch/x86/dts/theadorable-x86-dfi-bt700.dts
new file mode 100644
index 0000000..75f9ffa
--- /dev/null
+++ b/arch/x86/dts/theadorable-x86-dfi-bt700.dts
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+
+#include "dfi-bt700.dtsi"
+
+/ {
+	model = "theadorable-x86-DFI-BT700";
+	compatible = "anonymous,theadorable-x86-dfi-bt700", "dfi,bt700",
+			"intel,baytrail";
+
+	aliases {
+		serial0 = &pciuart0;
+		spi0 = &spi;
+	};
+};
diff --git a/arch/x86/include/asm/acpi/global_nvs.h b/arch/x86/include/asm/acpi/global_nvs.h
new file mode 100644
index 0000000..7f2ffd4
--- /dev/null
+++ b/arch/x86/include/asm/acpi/global_nvs.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _ACPI_GNVS_H_
+#define _ACPI_GNVS_H_
+
+/*
+ * This file provides two ACPI global NVS macros: ACPI_GNVS_ADDR and
+ * ACPI_GNVS_SIZE. They are to be used in platform's global_nvs.asl file
+ * to declare the GNVS OperationRegion, as well as write_acpi_tables()
+ * for the GNVS address runtime fix up.
+ */
+#define ACPI_GNVS_ADDR	0xdeadbeef
+#define ACPI_GNVS_SIZE	0x100
+
+#endif /* _ACPI_GNVS_H_ */
diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h
index 56aa282..caff4d8 100644
--- a/arch/x86/include/asm/acpi_table.h
+++ b/arch/x86/include/asm/acpi_table.h
@@ -299,6 +299,9 @@
 /* PM1_CNT bit defines */
 #define PM1_CNT_SCI_EN		(1 << 0)
 
+/* ACPI global NVS structure */
+struct acpi_global_nvs;
+
 /* These can be used by the target port */
 
 void acpi_fill_header(struct acpi_table_header *header, char *signature);
@@ -312,4 +315,5 @@
 int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
 			       u8 cpu, u16 flags, u8 lint);
 u32 acpi_fill_madt(u32 current);
+void acpi_create_gnvs(struct acpi_global_nvs *gnvs);
 u32 write_acpi_tables(u32 start);
diff --git a/arch/x86/include/asm/arch-baytrail/acpi/global_nvs.asl b/arch/x86/include/asm/arch-baytrail/acpi/global_nvs.asl
new file mode 100644
index 0000000..a28d4df
--- /dev/null
+++ b/arch/x86/include/asm/arch-baytrail/acpi/global_nvs.asl
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2016 Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/acpi/global_nvs.h>
+
+OperationRegion(GNVS, SystemMemory, ACPI_GNVS_ADDR, ACPI_GNVS_SIZE)
+Field(GNVS, ByteAcc, NoLock, Preserve)
+{
+	Offset (0x00),
+	PCNT, 8,	/* processor count */
+	IURE, 8,	/* internal UART enabled */
+}
diff --git a/arch/x86/include/asm/arch-baytrail/acpi/lpc.asl b/arch/x86/include/asm/arch-baytrail/acpi/lpc.asl
index 22f0d68..fe34d32 100644
--- a/arch/x86/include/asm/arch-baytrail/acpi/lpc.asl
+++ b/arch/x86/include/asm/arch-baytrail/acpi/lpc.asl
@@ -119,17 +119,14 @@
 
 		Method(_STA, 0, Serialized)
 		{
-			/*
-			 * TODO:
-			 *
-			 * Need to hide the internal UART depending on whether
-			 * internal UART is enabled or not so that external
-			 * SuperIO UART can be exposed to system.
-			 */
-			Store(1, UI3E)
-			Store(1, UI4E)
-			Store(1, C1EN)
-			Return (STA_VISIBLE)
+			If (LEqual(IURE, 1)) {
+				Store(1, UI3E)
+				Store(1, UI4E)
+				Store(1, C1EN)
+				Return (STA_VISIBLE)
+			} Else {
+				Return (STA_MISSING)
+			}
 
 		}
 
diff --git a/arch/x86/include/asm/arch-baytrail/acpi/platform.asl b/arch/x86/include/asm/arch-baytrail/acpi/platform.asl
index 6bc82ec..a80d2c0 100644
--- a/arch/x86/include/asm/arch-baytrail/acpi/platform.asl
+++ b/arch/x86/include/asm/arch-baytrail/acpi/platform.asl
@@ -22,6 +22,9 @@
 	Return (Package() {0, 0})
 }
 
+/* ACPI global NVS */
+#include "global_nvs.asl"
+
 /* TODO: add CPU ASL support */
 
 Scope (\_SB)
diff --git a/arch/x86/include/asm/arch-baytrail/global_nvs.h b/arch/x86/include/asm/arch-baytrail/global_nvs.h
new file mode 100644
index 0000000..56e3626
--- /dev/null
+++ b/arch/x86/include/asm/arch-baytrail/global_nvs.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _GLOBAL_NVS_H_
+#define _GLOBAL_NVS_H_
+
+struct __packed acpi_global_nvs {
+	u8	pcnt;		/* processor count */
+	u8	iuart_en;	/* internal UART enabled */
+
+	/*
+	 * Add padding so sizeof(struct acpi_global_nvs) == 0x100.
+	 * This must match the size defined in the global_nvs.asl.
+	 */
+	u8	rsvd[254];
+};
+
+#endif /* _GLOBAL_NVS_H_ */
diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h
index 4725250..9c51f63 100644
--- a/arch/x86/include/asm/arch-ivybridge/pch.h
+++ b/arch/x86/include/asm/arch-ivybridge/pch.h
@@ -134,32 +134,6 @@
 #define SATA_IOBP_SP0G3IR	0xea000151
 #define SATA_IOBP_SP1G3IR	0xea000051
 
-/* PCI Configuration Space (D31:F3): SMBus */
-#define PCH_SMBUS_DEV		PCI_BDF(0, 0x1f, 3)
-#define SMB_BASE		0x20
-#define HOSTC			0x40
-#define SMB_RCV_SLVA		0x09
-
-/* HOSTC bits */
-#define I2C_EN			(1 << 2)
-#define SMB_SMI_EN		(1 << 1)
-#define HST_EN			(1 << 0)
-
-/* SMBus I/O bits. */
-#define SMBHSTSTAT		0x0
-#define SMBHSTCTL		0x2
-#define SMBHSTCMD		0x3
-#define SMBXMITADD		0x4
-#define SMBHSTDAT0		0x5
-#define SMBHSTDAT1		0x6
-#define SMBBLKDAT		0x7
-#define SMBTRNSADD		0x9
-#define SMBSLVDATA		0xa
-#define SMLINK_PIN_CTL		0xe
-#define SMBUS_PIN_CTL		0xf
-
-#define SMBUS_TIMEOUT		(10 * 1000 * 100)
-
 #define VCH		0x0000	/* 32bit */
 #define VCAP1		0x0004	/* 32bit */
 #define VCAP2		0x0008	/* 32bit */
diff --git a/arch/x86/include/asm/arch-quark/acpi/global_nvs.asl b/arch/x86/include/asm/arch-quark/acpi/global_nvs.asl
new file mode 100644
index 0000000..6f0435e
--- /dev/null
+++ b/arch/x86/include/asm/arch-quark/acpi/global_nvs.asl
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2016 Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/acpi/global_nvs.h>
+
+OperationRegion(GNVS, SystemMemory, ACPI_GNVS_ADDR, ACPI_GNVS_SIZE)
+Field(GNVS, ByteAcc, NoLock, Preserve)
+{
+	Offset (0x00),
+	PCNT, 8,	/* processor count */
+}
diff --git a/arch/x86/include/asm/arch-quark/acpi/platform.asl b/arch/x86/include/asm/arch-quark/acpi/platform.asl
index bd72842..1ecf153 100644
--- a/arch/x86/include/asm/arch-quark/acpi/platform.asl
+++ b/arch/x86/include/asm/arch-quark/acpi/platform.asl
@@ -22,6 +22,9 @@
 	Return (Package() {0, 0})
 }
 
+/* ACPI global NVS */
+#include "global_nvs.asl"
+
 /* TODO: add CPU ASL support */
 
 Scope (\_SB)
diff --git a/arch/x86/include/asm/arch-quark/global_nvs.h b/arch/x86/include/asm/arch-quark/global_nvs.h
new file mode 100644
index 0000000..0231da0
--- /dev/null
+++ b/arch/x86/include/asm/arch-quark/global_nvs.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _GLOBAL_NVS_H_
+#define _GLOBAL_NVS_H_
+
+struct __packed acpi_global_nvs {
+	u8	pcnt;		/* processor count */
+
+	/*
+	 * Add padding so sizeof(struct acpi_global_nvs) == 0x100.
+	 * This must match the size defined in the global_nvs.asl.
+	 */
+	u8	rsvd[255];
+};
+
+#endif /* _GLOBAL_NVS_H_ */
diff --git a/arch/x86/include/asm/cache.h b/arch/x86/include/asm/cache.h
index 508b63f..4ff63c3 100644
--- a/arch/x86/include/asm/cache.h
+++ b/arch/x86/include/asm/cache.h
@@ -11,12 +11,12 @@
  * If CONFIG_SYS_CACHELINE_SIZE is defined use it for DMA alignment.  Otherwise
  * use 64-bytes, a safe default for x86.
  */
-#ifdef CONFIG_SYS_CACHELINE_SIZE
-#define ARCH_DMA_MINALIGN	CONFIG_SYS_CACHELINE_SIZE
-#else
-#define ARCH_DMA_MINALIGN	64
+#ifndef CONFIG_SYS_CACHELINE_SIZE
+#define CONFIG_SYS_CACHELINE_SIZE	64
 #endif
 
+#define ARCH_DMA_MINALIGN		CONFIG_SYS_CACHELINE_SIZE
+
 static inline void wbinvd(void)
 {
 	asm volatile ("wbinvd" : : : "memory");
diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c
index bb71286..7001e8b 100644
--- a/arch/x86/lib/acpi_table.c
+++ b/arch/x86/lib/acpi_table.c
@@ -11,10 +11,12 @@
 #include <cpu.h>
 #include <dm.h>
 #include <dm/uclass-internal.h>
+#include <asm/acpi/global_nvs.h>
 #include <asm/acpi_table.h>
 #include <asm/io.h>
 #include <asm/lapic.h>
 #include <asm/tables.h>
+#include <asm/arch/global_nvs.h>
 
 /*
  * IASL compiles the dsdt entries and writes the hex values
@@ -336,6 +338,7 @@
 	struct acpi_fadt *fadt;
 	struct acpi_mcfg *mcfg;
 	struct acpi_madt *madt;
+	int i;
 
 	current = start;
 
@@ -383,6 +386,25 @@
 	current += dsdt->length - sizeof(struct acpi_table_header);
 	current = ALIGN(current, 16);
 
+	/* Pack GNVS into the ACPI table area */
+	for (i = 0; i < dsdt->length; i++) {
+		u32 *gnvs = (u32 *)((u32)dsdt + i);
+		if (*gnvs == ACPI_GNVS_ADDR) {
+			debug("Fix up global NVS in DSDT to 0x%08x\n", current);
+			*gnvs = current;
+			break;
+		}
+	}
+
+	/* Update DSDT checksum since we patched the GNVS address */
+	dsdt->checksum = 0;
+	dsdt->checksum = table_compute_checksum((void *)dsdt, dsdt->length);
+
+	/* Fill in platform-specific global NVS variables */
+	acpi_create_gnvs((struct acpi_global_nvs *)current);
+	current += sizeof(struct acpi_global_nvs);
+	current = ALIGN(current, 16);
+
 	debug("ACPI:    * FADT\n");
 	fadt = (struct acpi_fadt *)current;
 	current += sizeof(struct acpi_fadt);
diff --git a/arch/x86/lib/fsp/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c
index b05dced..a480361 100644
--- a/arch/x86/lib/fsp/fsp_support.c
+++ b/arch/x86/lib/fsp/fsp_support.c
@@ -110,7 +110,7 @@
 	struct upd_region *fsp_upd;
 #endif
 
-#ifdef CONFIG_DEBUG_UART
+#ifdef CONFIG_INTERNAL_UART
 	setup_internal_uart(1);
 #endif
 
diff --git a/arch/x86/lib/lpc-uclass.c b/arch/x86/lib/lpc-uclass.c
index c6e8f73..eb033e6 100644
--- a/arch/x86/lib/lpc-uclass.c
+++ b/arch/x86/lib/lpc-uclass.c
@@ -7,24 +7,11 @@
 
 #include <common.h>
 #include <dm.h>
-#include <dm/root.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static int lpc_uclass_post_bind(struct udevice *bus)
-{
-	/*
-	 * Scan the device tree for devices
-	 *
-	 * Before relocation, only bind devices marked for pre-relocation
-	 * use.
-	 */
-	return dm_scan_fdt_node(bus, gd->fdt_blob, bus->of_offset,
-				gd->flags & GD_FLG_RELOC ? false : true);
-}
-
 UCLASS_DRIVER(lpc) = {
 	.id		= UCLASS_LPC,
 	.name		= "lpc",
-	.post_bind	= lpc_uclass_post_bind,
+	.post_bind	= dm_scan_fdt_dev,
 };
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
new file mode 100644
index 0000000..2ba7132
--- /dev/null
+++ b/arch/xtensa/Kconfig
@@ -0,0 +1,21 @@
+menu "Xtensa architecture"
+	depends on XTENSA
+
+config SYS_ARCH
+	string
+	default "xtensa"
+
+config SYS_CPU
+	string "Xtensa Core Variant"
+
+choice
+	prompt "Target select"
+
+config TARGET_XTFPGA
+	bool "Support XTFPGA"
+
+endchoice
+
+source "board/cadence/xtfpga/Kconfig"
+
+endmenu
diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile
new file mode 100644
index 0000000..130d76f
--- /dev/null
+++ b/arch/xtensa/Makefile
@@ -0,0 +1,8 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+head-y := arch/xtensa/cpu/start.o
+
+libs-y += arch/xtensa/cpu/
+libs-y += arch/xtensa/lib/
diff --git a/arch/xtensa/config.mk b/arch/xtensa/config.mk
new file mode 100644
index 0000000..7dd8d8a
--- /dev/null
+++ b/arch/xtensa/config.mk
@@ -0,0 +1,12 @@
+#
+# (C) Copyright 2007 - 2013 Tensilica, Inc.
+# (C) Copyright 2014 - 2016 Cadence Design Systems Inc.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+CROSS_COMPILE ?= xtensa-linux-
+PLATFORM_CPPFLAGS += -D__XTENSA__ -mlongcalls -mforce-no-pic \
+		     -ffunction-sections -fdata-sections
+
+LDFLAGS_FINAL += --gc-sections
diff --git a/arch/xtensa/cpu/Makefile b/arch/xtensa/cpu/Makefile
new file mode 100644
index 0000000..e83f620
--- /dev/null
+++ b/arch/xtensa/cpu/Makefile
@@ -0,0 +1,9 @@
+#
+# (C) Copyright 2007 - 2013 Tensilica, Inc.
+# (C) Copyright 2014 - 2016 Cadence Design Systems Inc.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y = cpu.o exceptions.o
+extra-y = start.o
diff --git a/arch/xtensa/cpu/cpu.c b/arch/xtensa/cpu/cpu.c
new file mode 100644
index 0000000..6787a61
--- /dev/null
+++ b/arch/xtensa/cpu/cpu.c
@@ -0,0 +1,49 @@
+/*
+ * (C) Copyright 2008 - 2013 Tensilica Inc.
+ * (C) Copyright 2014 - 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/*
+ * CPU specific code
+ */
+
+#include <common.h>
+#include <command.h>
+#include <linux/stringify.h>
+#include <asm/global_data.h>
+#include <asm/cache.h>
+#include <asm/string.h>
+#include <asm/misc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+gd_t *gd __attribute__((section(".data")));
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+/*
+ * Print information about the CPU.
+ */
+
+int print_cpuinfo(void)
+{
+	char buf[120], mhz[8];
+	uint32_t id0, id1;
+
+	asm volatile ("rsr %0, 176\n"
+		      "rsr %1, 208\n"
+		      : "=r"(id0), "=r"(id1));
+
+	sprintf(buf, "CPU:   Xtensa %s (id: %08x:%08x) at %s MHz\n",
+		XCHAL_CORE_ID, id0, id1, strmhz(mhz, gd->cpu_clk));
+	puts(buf);
+	return 0;
+}
+#endif
+
+int arch_cpu_init(void)
+{
+	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
+	return 0;
+}
diff --git a/arch/xtensa/cpu/exceptions.c b/arch/xtensa/cpu/exceptions.c
new file mode 100644
index 0000000..16639a0
--- /dev/null
+++ b/arch/xtensa/cpu/exceptions.c
@@ -0,0 +1,44 @@
+/*
+ * (C) Copyright 2008 - 2013 Tensilica Inc.
+ * (C) Copyright 2014 - 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/*
+ * Exception handling.
+ *  We currently don't handle any exception and force a reset.
+ *  (Note that alloca is a special case and handled in start.S)
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/string.h>
+#include <asm/regs.h>
+
+typedef void (*handler_t)(struct pt_regs *);
+
+void unhandled_exception(struct pt_regs *regs)
+{
+	printf("Unhandled Exception: EXCCAUSE = %ld, EXCVADDR = %lx, pc = %lx\n",
+	       regs->exccause, regs->excvaddr, regs->pc);
+	panic("*** PANIC\n");
+}
+
+handler_t exc_table[EXCCAUSE_LAST] = {
+	[0 ... EXCCAUSE_LAST-1]			= unhandled_exception,
+};
+
+int interrupt_init(void)
+{
+	return 0;
+}
+
+void enable_interrupts(void)
+{
+}
+
+int disable_interrupts(void)
+{
+	return 0;
+}
diff --git a/arch/xtensa/cpu/start.S b/arch/xtensa/cpu/start.S
new file mode 100644
index 0000000..8e4bc99
--- /dev/null
+++ b/arch/xtensa/cpu/start.S
@@ -0,0 +1,677 @@
+/*
+ * (C) Copyright 2008 - 2013 Tensilica Inc.
+ * (C) Copyright 2014 - 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <asm/asmmacro.h>
+#include <asm/cacheasm.h>
+#include <asm/regs.h>
+#include <asm/arch/tie.h>
+#include <asm-offsets.h>
+
+/*
+ * Offsets into the the pt_regs struture.
+ * Make sure these always match with the structure defined in ptrace.h!
+ */
+
+#define PT_PC		0
+#define PT_PS		4
+#define PT_DEPC		8
+#define PT_EXCCAUSE	12
+#define PT_EXCVADDR	16
+#define PT_DEBUGCAUSE	20
+#define PT_WMASK	24
+#define PT_LBEG		28
+#define PT_LEND		32
+#define PT_LCOUNT	36
+#define PT_SAR		40
+#define PT_WINDOWBASE	44
+#define PT_WINDOWSTART	48
+#define PT_SYSCALL	52
+#define PT_ICOUNTLEVEL	56
+#define PT_RESERVED	60
+#define PT_AREG		64
+#define PT_SIZE		(64 + 64)
+
+/*
+ * Cache attributes are different for full MMU and region protection.
+ */
+
+#if XCHAL_HAVE_PTP_MMU
+#define CA_WRITEBACK	(0x7)
+#else
+#define CA_WRITEBACK	(0x4)
+#endif
+
+/*
+ * Reset vector.
+ * Only a trampoline to jump to _start
+ * (Note that we have to mark the section writable as the section contains
+ *  a relocatable literal)
+ */
+
+	.section .ResetVector.text, "awx"
+	.global _ResetVector
+_ResetVector:
+
+	j	1f
+	.align 4
+2:	.long	_start
+1:	l32r	a2, 2b
+	jx	a2
+
+
+/*
+ * Processor initialization. We still run in rom space.
+ *
+ * NOTE: Running in ROM
+ *  For Xtensa, we currently don't allow to run some code from ROM but
+ *  unpack the data immediately to memory. This requires, for example,
+ *  that DDR has been set up before running U-Boot. (See also comments
+ *  inline for ways to change it)
+ */
+
+	.section .reset.text, "ax"
+	.global _start
+	.align 4
+_start:
+	/* Keep a0 = 0 for various initializations */
+
+	movi	a0, 0
+
+	/*
+	 * For full MMU cores, put page table at unmapped virtual address.
+	 * This ensures that accesses outside the static maps result
+	 * in miss exceptions rather than random behaviour.
+	 */
+
+#if XCHAL_HAVE_PTP_MMU
+	wsr	a0, PTEVADDR
+#endif
+
+	/* Disable dbreak debug exceptions */
+
+#if XCHAL_HAVE_DEBUG && XCHAL_NUM_DBREAK > 0
+	.set	_index, 0
+	.rept	XCHAL_NUM_DBREAK
+	wsr	a0, DBREAKC + _index
+	.set	_index, _index + 1
+	.endr
+#endif
+
+	/* Reset windowbase and windowstart */
+
+#if XCHAL_HAVE_WINDOWED
+	movi	a3, 1
+	wsr	a3, windowstart
+	wsr	a0, windowbase
+	rsync
+	movi	a0, 0			/* windowbase might have changed */
+#endif
+
+	/*
+	 * Vecbase in bitstream may differ from header files
+	 * set or check it.
+	 */
+
+#if XCHAL_HAVE_VECBASE
+	movi	a3, XCHAL_VECBASE_RESET_VADDR	/* VECBASE reset value */
+	wsr	a3, VECBASE
+#endif
+
+#if XCHAL_HAVE_LOOPS
+	/* Disable loops */
+
+	wsr	a0, LCOUNT
+#endif
+
+	/* Set PS.WOE = 0, PS.EXCM = 0 (for loop), PS.INTLEVEL = EXCM level */
+
+#if XCHAL_HAVE_XEA1
+	movi	a2, 1
+#else
+	movi	a2, XCHAL_EXCM_LEVEL
+#endif
+	wsr	a2, PS
+	rsync
+
+	/* Unlock and invalidate caches */
+
+	___unlock_dcache_all a2, a3
+	___invalidate_dcache_all a2, a3
+	___unlock_icache_all a2, a3
+	___invalidate_icache_all a2, a3
+
+	isync
+
+	/* Unpack data sections */
+
+	movi	a2, __reloc_table_start
+	movi	a3, __reloc_table_end
+
+1:	beq	a2, a3, 3f	# no more entries?
+	l32i	a4, a2, 0	# start destination (in RAM)
+	l32i	a5, a2, 4	# end destination (in RAM)
+	l32i	a6, a2, 8	# start source (in ROM)
+	addi	a2, a2, 12	# next entry
+	beq	a4, a5, 1b	# skip, empty entry
+	beq	a4, a6, 1b	# skip, source and destination are the same
+
+	/* If there's memory protection option with 512MB TLB regions and
+	 * cache attributes in TLB entries and caching is not inhibited,
+	 * enable data/instruction cache for relocated image.
+	 */
+#if XCHAL_HAVE_SPANNING_WAY && \
+	(!defined(CONFIG_SYS_DCACHE_OFF) || \
+	 !defined(CONFIG_SYS_ICACHE_OFF))
+	srli	a7, a4, 29
+	slli	a7, a7, 29
+	addi	a7, a7, XCHAL_SPANNING_WAY
+#ifndef CONFIG_SYS_DCACHE_OFF
+	rdtlb1	a8, a7
+	srli	a8, a8, 4
+	slli	a8, a8, 4
+	addi	a8, a8, CA_WRITEBACK
+	wdtlb	a8, a7
+#endif
+#ifndef CONFIG_SYS_ICACHE_OFF
+	ritlb1	a8, a7
+	srli	a8, a8, 4
+	slli	a8, a8, 4
+	addi	a8, a8, CA_WRITEBACK
+	witlb	a8, a7
+#endif
+	isync
+#endif
+
+2:	l32i	a7, a6, 0
+	addi	a6, a6, 4
+	s32i	a7, a4, 0
+	addi	a4, a4, 4
+	bltu	a4, a5, 2b
+	j	1b
+
+3:	/* All code and initalized data segments have been copied */
+
+	/* Setup PS, PS.WOE = 1, PS.EXCM = 0, PS.INTLEVEL = EXCM level. */
+
+#if __XTENSA_CALL0_ABI__
+	movi	a2, XCHAL_EXCM_LEVEL
+#else
+	movi	a2, (1<<PS_WOE_BIT) | XCHAL_EXCM_LEVEL
+#endif
+	wsr	a2, PS
+	rsync
+
+	/* Writeback */
+
+	___flush_dcache_all a2, a3
+
+#ifdef __XTENSA_WINDOWED_ABI__
+	/*
+	 * In windowed ABI caller and call target need to be within the same
+	 * gigabyte. Put the rest of the code into the text segment and jump
+	 * there.
+	 */
+
+	movi	a4, .Lboard_init_code
+	jx	a4
+
+	.text
+	.align	4
+.Lboard_init_code:
+#endif
+
+	movi	a0, 0
+	movi	sp, (CONFIG_SYS_TEXT_ADDR - 16) & 0xfffffff0
+
+#ifdef CONFIG_DEBUG_UART
+	movi	a4, debug_uart_init
+#ifdef __XTENSA_CALL0_ABI__
+	callx0	a4
+#else
+	callx4	a4
+#endif
+#endif
+
+	movi	a4, board_init_f_alloc_reserve
+
+#ifdef __XTENSA_CALL0_ABI__
+	mov	a2, sp
+	callx0	a4
+	mov	sp, a2
+#else
+	mov	a6, sp
+	callx4	a4
+	movsp	sp, a6
+#endif
+
+	movi	a4, board_init_f_init_reserve
+
+#ifdef __XTENSA_CALL0_ABI__
+	callx0	a4
+#else
+	callx4	a4
+#endif
+
+        /*
+	 * Call board initialization routine (never returns).
+	 */
+
+	movi	a4, board_init_f
+
+#ifdef __XTENSA_CALL0_ABI__
+	movi	a2, 0
+	callx0	a4
+#else
+	movi	a6, 0
+	callx4	a4
+#endif
+	/* Never Returns */
+	ill
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * a2 = addr_sp
+ * a3 = gd
+ * a4 = destination address
+ */
+	.text
+	.globl relocate_code
+	.align 4
+relocate_code:
+	abi_entry
+
+#ifdef __XTENSA_CALL0_ABI__
+	mov	a1, a2
+	mov	a2, a3
+	mov	a3, a4
+	movi	a0, board_init_r
+	callx0	a0
+#else
+	/* We can't movsp here, because the chain of stack frames may cross
+	 * the now reserved memory. We need to toss all window frames except
+	 * the current, create new pristine stack frame and start from scratch.
+	 */
+	rsr	a0, windowbase
+	ssl	a0
+	movi	a0, 1
+	sll	a0, a0
+	wsr	a0, windowstart
+	rsync
+
+	movi	a0, 0
+
+	/* Reserve 16-byte save area */
+	addi	sp, a2, -16
+	mov	a6, a3
+	mov	a7, a4
+	movi	a4, board_init_r
+	callx4	a4
+#endif
+	ill
+
+#if XCHAL_HAVE_EXCEPTIONS
+
+/*
+ * Exception vectors.
+ *
+ *  Various notes:
+ *   - We currently don't use the user exception vector (PS.UM is always 0),
+ *     but do define such a vector, just in case. They both jump to the
+ *     same exception handler, though.
+ *   - We currently only save the bare minimum number of registers:
+ *     a0...a15, sar, loop-registers, exception register (epc1, excvaddr,
+ *     exccause, depc)
+ *   - WINDOWSTART is only saved to identify if registers have been spilled
+ *     to the wrong stack (exception stack) while executing the exception
+ *     handler.
+ */
+
+	.section .KernelExceptionVector.text, "ax"
+	.global _KernelExceptionVector
+_KernelExceptionVector:
+
+	wsr	a2, EXCSAVE1
+	movi	a2, ExceptionHandler
+	jx	a2
+
+	.section .UserExceptionVector.text, "ax"
+	.global _UserExceptionVector
+_UserExceptionVector:
+
+	wsr	a2, EXCSAVE1
+	movi	a2, ExceptionHandler
+	jx	a2
+
+#if !XCHAL_HAVE_XEA1
+	.section .DoubleExceptionVector.text, "ax"
+	.global _DoubleExceptionVector
+_DoubleExceptionVector:
+
+#ifdef __XTENSA_CALL0_ABI__
+	wsr	a0, EXCSAVE1
+	movi    a0, hang                # report and ask user to reset board
+	callx0	a0
+#else
+	wsr	a4, EXCSAVE1
+	movi    a4, hang                # report and ask user to reset board
+	callx4	a4
+#endif
+#endif
+	/* Does not return here */
+
+
+	.text
+	.align 4
+ExceptionHandler:
+
+	rsr	a2, EXCCAUSE		# find handler
+
+#if XCHAL_HAVE_WINDOWED
+	/* Special case for alloca handler */
+
+	bnei	a2, 5, 1f		# jump if not alloca exception
+
+	addi	a1, a1, -16 - 4		# create a small stack frame
+	s32i	a3, a1, 0		# and save a3 (a2 still in excsave1)
+	movi	a2, fast_alloca_exception
+	jx	a2			# jump to fast_alloca_exception
+#endif
+	/* All other exceptions go here: */
+
+	/* Create ptrace stack and save a0...a3 */
+
+1:	addi	a2, a1, - PT_SIZE - 16
+	s32i	a0, a2, PT_AREG + 0 * 4
+	s32i	a1, a2, PT_AREG + 1 * 4
+	s32i	a3, a2, PT_AREG + 3 * 4
+	rsr	a3, EXCSAVE1
+	s32i	a3, a2, PT_AREG + 2 * 4
+	mov	a1, a2
+
+	/* Save remaining AR registers */
+
+	s32i	a4, a1, PT_AREG + 4 * 4
+	s32i	a5, a1, PT_AREG + 5 * 4
+	s32i	a6, a1, PT_AREG + 6 * 4
+	s32i	a7, a1, PT_AREG + 7 * 4
+	s32i	a8, a1, PT_AREG + 8 * 4
+	s32i	a9, a1, PT_AREG + 9 * 4
+	s32i	a10, a1, PT_AREG + 10 * 4
+	s32i	a11, a1, PT_AREG + 11 * 4
+	s32i	a12, a1, PT_AREG + 12 * 4
+	s32i	a13, a1, PT_AREG + 13 * 4
+	s32i	a14, a1, PT_AREG + 14 * 4
+	s32i	a15, a1, PT_AREG + 15 * 4
+
+	/* Save SRs */
+
+#if XCHAL_HAVE_WINDOWED
+	rsr	a2, WINDOWSTART
+	s32i	a2, a1, PT_WINDOWSTART
+#endif
+
+	rsr	a2, SAR
+	rsr	a3, EPC1
+	rsr	a4, EXCVADDR
+	s32i	a2, a1, PT_SAR
+	s32i	a3, a1, PT_PC
+	s32i	a4, a1, PT_EXCVADDR
+
+#if XCHAL_HAVE_LOOPS
+	movi	a2, 0
+	rsr	a3, LBEG
+	xsr	a2, LCOUNT
+	s32i	a3, a1, PT_LBEG
+	rsr	a3, LEND
+	s32i	a2, a1, PT_LCOUNT
+	s32i	a3, a1, PT_LEND
+#endif
+
+	/* Set up C environment and call registered handler */
+	/* Setup stack, PS.WOE = 1, PS.EXCM = 0, PS.INTLEVEL = EXCM level. */
+
+	rsr	a2, EXCCAUSE
+#if XCHAL_HAVE_XEA1
+	movi	a3, (1<<PS_WOE_BIT) | 1
+#elif __XTENSA_CALL0_ABI__
+	movi	a3, XCHAL_EXCM_LEVEL
+#else
+	movi	a3, (1<<PS_WOE_BIT) | XCHAL_EXCM_LEVEL
+#endif
+	xsr	a3, PS
+	rsync
+	s32i	a2, a1, PT_EXCCAUSE
+	s32i	a3, a1, PT_PS
+
+	movi	a0, exc_table
+	addx4	a0, a2, a0
+	l32i	a0, a0, 0
+#ifdef __XTENSA_CALL0_ABI__
+	mov	a2, a1			# Provide stack frame as only argument
+	callx0	a0
+	l32i	a3, a1, PT_PS
+#else
+	mov	a6, a1			# Provide stack frame as only argument
+	callx4	a0
+#endif
+
+	/* Restore PS and go to exception mode (PS.EXCM=1) */
+
+	wsr	a3, PS
+
+	/* Restore SR registers */
+
+#if XCHAL_HAVE_LOOPS
+	l32i	a2, a1, PT_LBEG
+	l32i	a3, a1, PT_LEND
+	l32i	a4, a1, PT_LCOUNT
+	wsr	a2, LBEG
+	wsr	a3, LEND
+	wsr	a4, LCOUNT
+#endif
+
+	l32i	a2, a1, PT_SAR
+	l32i	a3, a1, PT_PC
+	wsr	a2, SAR
+	wsr	a3, EPC1
+
+#if XCHAL_HAVE_WINDOWED
+	/* Do we need to simulate a MOVSP? */
+
+	l32i	a2, a1, PT_WINDOWSTART
+	addi	a3, a2, -1
+	and	a2, a2, a3
+	beqz	a2, 1f			# Skip if regs were spilled before exc.
+
+	rsr	a2, WINDOWSTART
+	addi	a3, a2, -1
+	and	a2, a2, a3
+	bnez	a2, 1f			# Skip if registers aren't spilled now
+
+	addi	a2, a1, -16
+	l32i	a4, a2, 0
+	l32i	a5, a2, 4
+	s32i	a4, a1, PT_SIZE + 0
+	s32i	a5, a1, PT_SIZE + 4
+	l32i	a4, a2, 8
+	l32i	a5, a2, 12
+	s32i	a4, a1, PT_SIZE + 8
+	s32i	a5, a1, PT_SIZE + 12
+#endif
+
+	/* Restore address register */
+
+1:	l32i	a15, a1, PT_AREG + 15 * 4
+	l32i	a14, a1, PT_AREG + 14 * 4
+	l32i	a13, a1, PT_AREG + 13 * 4
+	l32i	a12, a1, PT_AREG + 12 * 4
+	l32i	a11, a1, PT_AREG + 11 * 4
+	l32i	a10, a1, PT_AREG + 10 * 4
+	l32i	a9, a1, PT_AREG + 9 * 4
+	l32i	a8, a1, PT_AREG + 8 * 4
+	l32i	a7, a1, PT_AREG + 7 * 4
+	l32i	a6, a1, PT_AREG + 6 * 4
+	l32i	a5, a1, PT_AREG + 5 * 4
+	l32i	a4, a1, PT_AREG + 4 * 4
+	l32i	a3, a1, PT_AREG + 3 * 4
+	l32i	a2, a1, PT_AREG + 2 * 4
+	l32i	a0, a1, PT_AREG + 0 * 4
+
+	l32i	a1, a1, PT_AREG + 1 * 4 # Remove ptrace stack frame
+
+	rfe
+
+#endif /* XCHAL_HAVE_EXCEPTIONS */
+
+#if XCHAL_HAVE_WINDOWED
+
+/*
+ * Window overflow and underflow handlers.
+ * The handlers must be 64 bytes apart, first starting with the underflow
+ * handlers underflow-4 to underflow-12, then the overflow handlers
+ * overflow-4 to overflow-12.
+ *
+ * Note: We rerun the underflow handlers if we hit an exception, so
+ *	 we try to access any page that would cause a page fault early.
+ */
+
+	.section .WindowVectors.text, "ax"
+
+/* 4-Register Window Overflow Vector (Handler) */
+
+	.align 64
+.global _WindowOverflow4
+_WindowOverflow4:
+	s32e	a0, a5, -16
+	s32e	a1, a5, -12
+	s32e	a2, a5,  -8
+	s32e	a3, a5,  -4
+	rfwo
+
+
+/* 4-Register Window Underflow Vector (Handler) */
+
+	.align 64
+.global _WindowUnderflow4
+_WindowUnderflow4:
+	l32e	a0, a5, -16
+	l32e	a1, a5, -12
+	l32e	a2, a5,  -8
+	l32e	a3, a5,  -4
+	rfwu
+
+/*
+ * a0:	a0
+ * a1:	new stack pointer = a1 - 16 - 4
+ * a2:	available, saved in excsave1
+ * a3:	available, saved on stack *a1
+ */
+
+/* 15*/	.byte	0xff
+
+fast_alloca_exception:	/* must be at _WindowUnderflow4 + 16 */
+
+/* 16*/	rsr	a2, PS
+/* 19*/	rsr	a3, WINDOWBASE
+/* 22*/	extui	a2, a2, PS_OWB_SHIFT, PS_OWB_SHIFT
+/* 25*/	xor	a2, a2, a3
+/* 28*/	rsr	a3, PS
+/* 31*/	slli	a2, a2, PS_OWB_SHIFT
+/* 34*/	xor	a2, a3, a2
+/* 37*/	wsr	a2, PS
+
+/* 40*/	_l32i	a3, a1, 0
+/* 43*/	addi	a1, a1, 16 + 4
+/* 46*/	rsr	a2, EXCSAVE1
+
+/* 49*/	rotw	-1
+/* 52*/	_bbci.l	a4, 31, _WindowUnderflow4	/* 0x: call4 */
+/* 55*/	rotw	-1
+/* 58*/	_bbci.l	a8, 30, _WindowUnderflow8	/* 10: call8 */
+/* 61*/ _j	__WindowUnderflow12		/* 11: call12 */
+/* 64*/
+
+/* 8-Register Window Overflow Vector (Handler) */
+
+	.align 64
+.global _WindowOverflow8
+_WindowOverflow8:
+	s32e	a0, a9, -16
+	l32e	a0, a1, -12
+	s32e	a2, a9,  -8
+	s32e	a1, a9, -12
+	s32e	a3, a9,  -4
+	s32e	a4, a0, -32
+	s32e	a5, a0, -28
+	s32e	a6, a0, -24
+	s32e	a7, a0, -20
+	rfwo
+
+/* 8-Register Window Underflow Vector (Handler) */
+
+	.align 64
+.global _WindowUnderflow8
+_WindowUnderflow8:
+	l32e	a1, a9, -12
+	l32e	a0, a9, -16
+	l32e	a7, a1, -12
+	l32e	a2, a9,  -8
+	l32e	a4, a7, -32
+	l32e	a3, a9,  -4
+	l32e	a5, a7, -28
+	l32e	a6, a7, -24
+	l32e	a7, a7, -20
+	rfwu
+
+/* 12-Register Window Overflow Vector (Handler) */
+
+	.align 64
+.global _WindowOverflow12
+_WindowOverflow12:
+	s32e	a0,  a13, -16
+	l32e	a0,  a1,  -12
+	s32e	a1,  a13, -12
+	s32e	a2,  a13,  -8
+	s32e	a3,  a13,  -4
+	s32e	a4,  a0,  -48
+	s32e	a5,  a0,  -44
+	s32e	a6,  a0,  -40
+	s32e	a7,  a0,  -36
+	s32e	a8,  a0,  -32
+	s32e	a9,  a0,  -28
+	s32e	a10, a0,  -24
+	s32e	a11, a0,  -20
+	rfwo
+
+/* 12-Register Window Underflow Vector (Handler) */
+
+	.org _WindowOverflow12 + 64 - 3
+__WindowUnderflow12:
+	rotw	-1
+.global _WindowUnderflow12
+_WindowUnderflow12:
+	l32e	a1,  a13, -12
+	l32e	a0,  a13, -16
+	l32e	a11, a1,  -12
+	l32e	a2,  a13,  -8
+	l32e	a4,  a11, -48
+	l32e	a8,  a11, -32
+	l32e	a3,  a13,  -4
+	l32e	a5,  a11, -44
+	l32e	a6,  a11, -40
+	l32e	a7,  a11, -36
+	l32e	a9,  a11, -28
+	l32e	a10, a11, -24
+	l32e	a11, a11, -20
+	rfwu
+
+#endif /* XCHAL_HAVE_WINDOWED */
diff --git a/arch/xtensa/cpu/u-boot.lds b/arch/xtensa/cpu/u-boot.lds
new file mode 100644
index 0000000..853ae5a
--- /dev/null
+++ b/arch/xtensa/cpu/u-boot.lds
@@ -0,0 +1,116 @@
+/*
+ * (C) Copyright 2008 - 2013 Tensilica, Inc.
+ * (C) Copyright 2014 - 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <asm/ldscript.h>
+#include <asm/arch/core.h>
+#include <asm/addrspace.h>
+#include <asm-offsets.h>
+
+OUTPUT_ARCH(xtensa)
+ENTRY(_start)
+
+/*
+ * U-Boot resets from SYSROM and unpacks itself from a ROM store to RAM.
+ * The reset vector is usually near the base of SYSROM and has room
+ * above it for the ROM store into which the rest of U-Boot is packed.
+ * The ROM store also needs to be above any other vectors that are in ROM.
+ * If a core has its vectors near the top of ROM, this must be edited.
+ *
+ * Note that to run C code out of ROM, the processor would have to support
+ * 'relocatable' exception vectors and provide a scratch memory for the
+ * initial stack. Not all Xtensa processor configurations support that, so
+ * we can simplify the boot process and unpack U-Boot to RAM immediately.
+ * This, however, requires that memory have been initialized throug some
+ * other means (serial ROM, for example) or are initialized early (requiring
+ * an assembler function. See start.S for more details)
+ */
+
+SECTIONS
+{
+  . = + SIZEOF_HEADERS;
+  SECTION_ResetVector(XCHAL_RESET_VECTOR_VADDR, LMA_EQ_VMA)
+
+  .reloc_table ALIGN(4) : FOLLOWING(.ResetVector.text)
+  {
+    __reloc_table_start = ABSOLUTE(.);
+#if XCHAL_HAVE_WINDOWED
+    RELOCATE2(WindowVectors,text);
+#endif
+    RELOCATE2(KernelExceptionVector,literal);
+    RELOCATE2(KernelExceptionVector,text);
+    RELOCATE2(UserExceptionVector,literal);
+    RELOCATE2(UserExceptionVector,text);
+    RELOCATE2(DoubleExceptionVector,literal);
+    RELOCATE2(DoubleExceptionVector,text);
+    RELOCATE1(text);
+    RELOCATE1(rodata);
+    RELOCATE1(data);
+    RELOCATE1(u_boot_list);
+    __reloc_table_end = ABSOLUTE(.);
+  }
+
+#if XCHAL_HAVE_WINDOWED
+  SECTION_VECTOR(WindowVectors,text,XCHAL_WINDOW_VECTORS_VADDR,
+		 FOLLOWING(.reloc_table))
+  SECTION_VECTOR(KernelExceptionVector,literal,XCHAL_KERNEL_VECTOR_VADDR-8,
+		 FOLLOWING(.WindowVectors.text))
+#else
+  SECTION_VECTOR(KernelExceptionVector,literal,XCHAL_KERNEL_VECTOR_VADDR-8,
+		 FOLLOWING(.reloc_table))
+#endif
+  SECTION_VECTOR(KernelExceptionVector,text,XCHAL_KERNEL_VECTOR_VADDR,
+		 FOLLOWING(.KernelExceptionVector.literal))
+  SECTION_VECTOR(UserExceptionVector,literal,XCHAL_USER_VECTOR_VADDR-8,
+		 FOLLOWING(.KernelExceptionVector.text))
+  SECTION_VECTOR(UserExceptionVector,text,XCHAL_USER_VECTOR_VADDR,
+		 FOLLOWING(.UserExceptionVector.literal))
+  SECTION_VECTOR(DoubleExceptionVector,literal,XCHAL_DOUBLEEXC_VECTOR_VADDR-8,
+		 FOLLOWING(.UserExceptionVector.text))
+  SECTION_VECTOR(DoubleExceptionVector,text,XCHAL_DOUBLEEXC_VECTOR_VADDR,
+		 FOLLOWING(.DoubleExceptionVector.literal))
+
+  __monitor_start = CONFIG_SYS_TEXT_ADDR;
+
+  SECTION_text(CONFIG_SYS_TEXT_ADDR, FOLLOWING(.DoubleExceptionVector.text))
+  SECTION_rodata(ALIGN(16), FOLLOWING(.text))
+  SECTION_u_boot_list(ALIGN(16), FOLLOWING(.rodata))
+  SECTION_data(ALIGN(16), FOLLOWING(.u_boot_list))
+
+  __reloc_end = .;
+  __init_end = .;
+
+  SECTION_bss(__init_end (OVERLAY),)
+
+  __monitor_end = .;
+
+  /*
+   * On many Xtensa boards a region of RAM may be mapped to the ROM address
+   * space to facilitate on-chip-debug, and U-Boot must fit with that region.
+   * The config variables CONFIG_SYS_MONITOR_* define the region.
+   * If U-Boot extends beyond this region it will appear discontiguous in the
+   * address space and is in danger of overwriting itself during unpacking
+   * ("relocation").
+   * This causes U-Boot to crash in a way that is difficult to debug. On some
+   * boards (such as xtav60) the region is small enough that U-Boot will not
+   * fit if compiled entirely with -O0 (a common scenario). To avoid a lengthy
+   * debugging session when this happens, ensure a link-time error occurs.
+   *
+   */
+
+   ASSERT(__monitor_end - __monitor_start <= CONFIG_SYS_MONITOR_LEN,
+          "U-Boot ROM image is too large. Check optimization level.")
+
+  SECTION_xtensa
+  SECTION_debug
+
+  /DISCARD/ : { *(.dynstr*) }
+  /DISCARD/ : { *(.hash*) }
+  /DISCARD/ : { *(.interp) }
+  /DISCARD/ : { *(.got*) }
+  /DISCARD/ : { *(.dynsym) }
+}
diff --git a/arch/xtensa/dts/Makefile b/arch/xtensa/dts/Makefile
new file mode 100644
index 0000000..e14cdac
--- /dev/null
+++ b/arch/xtensa/dts/Makefile
@@ -0,0 +1,15 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+dtb-$(CONFIG_XTFPGA) += ml605.dtb ml605_nommu.dtb kc705.dtb kc705_nommu.dtb
+
+targets += $(dtb-y)
+
+DTC_FLAGS +=
+
+PHONY += dtbs
+dtbs: $(addprefix $(obj)/, $(dtb-y))
+	@:
+
+clean-files := *.dtb
diff --git a/arch/xtensa/dts/include/dt-bindings b/arch/xtensa/dts/include/dt-bindings
new file mode 120000
index 0000000..0cecb3d
--- /dev/null
+++ b/arch/xtensa/dts/include/dt-bindings
@@ -0,0 +1 @@
+../../../../include/dt-bindings
\ No newline at end of file
diff --git a/arch/xtensa/dts/kc705.dts b/arch/xtensa/dts/kc705.dts
new file mode 100644
index 0000000..3b89e83
--- /dev/null
+++ b/arch/xtensa/dts/kc705.dts
@@ -0,0 +1,15 @@
+/dts-v1/;
+/include/ "xtfpga.dtsi"
+/include/ "xtfpga-flash-128m.dtsi"
+
+/ {
+	compatible = "cdns,xtensa-kc705";
+	chosen {
+		bootargs = "earlycon=uart8250,mmio32native,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug";
+		stdout-path = &serial0;
+	};
+	memory@0 {
+		device_type = "memory";
+		reg = <0x00000000 0x38000000>;
+	};
+};
diff --git a/arch/xtensa/dts/kc705_nommu.dts b/arch/xtensa/dts/kc705_nommu.dts
new file mode 100644
index 0000000..57f0dab
--- /dev/null
+++ b/arch/xtensa/dts/kc705_nommu.dts
@@ -0,0 +1,17 @@
+/dts-v1/;
+/include/ "xtfpga.dtsi"
+/include/ "xtfpga-flash-128m.dtsi"
+
+/ {
+	compatible = "cdns,xtensa-kc705";
+	chosen {
+		bootargs = "earlycon=uart8250,mmio32native,0x9d050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug";
+	};
+	memory@0 {
+		device_type = "memory";
+		reg = <0x60000000 0x10000000>;
+	};
+	soc {
+		ranges = <0x00000000 0x90000000 0x10000000>;
+	};
+};
diff --git a/arch/xtensa/dts/ml605.dts b/arch/xtensa/dts/ml605.dts
new file mode 100644
index 0000000..f323f96
--- /dev/null
+++ b/arch/xtensa/dts/ml605.dts
@@ -0,0 +1,15 @@
+/dts-v1/;
+/include/ "xtfpga.dtsi"
+/include/ "xtfpga-flash-16m.dtsi"
+
+/ {
+	compatible = "cdns,xtensa-ml605";
+	chosen {
+		bootargs = "earlycon=uart8250,mmio32native,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug";
+		stdout-path = &serial0;
+	};
+	memory@0 {
+		device_type = "memory";
+		reg = <0x00000000 0x18000000>;
+	};
+};
diff --git a/arch/xtensa/dts/ml605_nommu.dts b/arch/xtensa/dts/ml605_nommu.dts
new file mode 100644
index 0000000..6bdf400
--- /dev/null
+++ b/arch/xtensa/dts/ml605_nommu.dts
@@ -0,0 +1,18 @@
+/dts-v1/;
+/include/ "xtfpga.dtsi"
+/include/ "xtfpga-flash-16m.dtsi"
+
+/ {
+	compatible = "cdns,xtensa-ml605";
+	chosen {
+		bootargs = "earlycon=uart8250,mmio32native,0x9d050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug";
+		stdout-path = &serial0;
+	};
+	memory@0 {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>;
+	};
+	soc {
+		ranges = <0x00000000 0x90000000 0x10000000>;
+	};
+};
diff --git a/arch/xtensa/dts/xtfpga-flash-128m.dtsi b/arch/xtensa/dts/xtfpga-flash-128m.dtsi
new file mode 100644
index 0000000..d3a88e0
--- /dev/null
+++ b/arch/xtensa/dts/xtfpga-flash-128m.dtsi
@@ -0,0 +1,28 @@
+/ {
+	soc {
+		flash: flash@00000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x00000000 0x08000000>;
+			bank-width = <2>;
+			device-width = <2>;
+			partition@0x0 {
+				label = "data";
+				reg = <0x00000000 0x06000000>;
+			};
+			partition@0x6000000 {
+				label = "boot loader area";
+				reg = <0x06000000 0x00800000>;
+			};
+			partition@0x6800000 {
+				label = "kernel image";
+				reg = <0x06800000 0x017e0000>;
+			};
+			partition@0x7fe0000 {
+				label = "boot environment";
+				reg = <0x07fe0000 0x00020000>;
+			};
+		};
+        };
+};
diff --git a/arch/xtensa/dts/xtfpga-flash-16m.dtsi b/arch/xtensa/dts/xtfpga-flash-16m.dtsi
new file mode 100644
index 0000000..1d97203
--- /dev/null
+++ b/arch/xtensa/dts/xtfpga-flash-16m.dtsi
@@ -0,0 +1,28 @@
+/ {
+	soc {
+		flash: flash@08000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x08000000 0x01000000>;
+			bank-width = <2>;
+			device-width = <2>;
+			partition@0x0 {
+				label = "boot loader area";
+				reg = <0x00000000 0x00400000>;
+			};
+			partition@0x400000 {
+				label = "kernel image";
+				reg = <0x00400000 0x00600000>;
+			};
+			partition@0xa00000 {
+				label = "data";
+				reg = <0x00a00000 0x005e0000>;
+			};
+			partition@0xfe0000 {
+				label = "boot environment";
+				reg = <0x00fe0000 0x00020000>;
+			};
+		};
+	};
+};
diff --git a/arch/xtensa/dts/xtfpga.dtsi b/arch/xtensa/dts/xtfpga.dtsi
new file mode 100644
index 0000000..cd45f9c2
--- /dev/null
+++ b/arch/xtensa/dts/xtfpga.dtsi
@@ -0,0 +1,137 @@
+/ {
+	compatible = "cdns,xtensa-xtfpga";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&pic>;
+
+	chosen {
+		bootargs = "earlycon=uart8250,mmio32native,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x00000000 0x06000000>;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu@0 {
+			compatible = "cdns,xtensa-cpu";
+			reg = <0>;
+			/* Filled in by platform_setup from FPGA register
+			 * clock-frequency = <100000000>;
+			 */
+		};
+	};
+
+	pic: pic {
+		compatible = "cdns,xtensa-pic";
+		/* one cell: internal irq number,
+		 * two cells: second cell == 0: internal irq number
+		 *            second cell == 1: external irq number
+		 */
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	clocks {
+		osc: main-oscillator {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+		};
+
+		clk54: clk54 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <54000000>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges = <0x00000000 0xf0000000 0x10000000>;
+
+		serial0: serial@0d050020 {
+			device_type = "serial";
+			compatible = "ns16550a";
+			no-loopback-test;
+			reg = <0x0d050020 0x20>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			native-endian;
+			interrupts = <0 1>; /* external irq 0 */
+			clocks = <&osc>;
+		};
+
+		enet0: ethoc@0d030000 {
+			compatible = "opencores,ethoc";
+			reg = <0x0d030000 0x4000 0x0d800000 0x4000>;
+			native-endian;
+			interrupts = <1 1>; /* external irq 1 */
+			local-mac-address = [00 50 c2 13 6f 00];
+			clocks = <&osc>;
+		};
+
+		i2s0: xtfpga-i2s@0d080000 {
+			#sound-dai-cells = <0>;
+			compatible = "cdns,xtfpga-i2s";
+			reg = <0x0d080000 0x40>;
+			interrupts = <2 1>; /* external irq 2 */
+			clocks = <&cdce706 4>;
+		};
+
+		i2c0: i2c-master@0d090000 {
+			compatible = "opencores,i2c-ocores";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0d090000 0x20>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			native-endian;
+			interrupts = <4 1>;
+			clocks = <&osc>;
+
+			cdce706: clock-synth@69 {
+				compatible = "ti,cdce706";
+				#clock-cells = <1>;
+				reg = <0x69>;
+				clocks = <&clk54>;
+				clock-names = "clk_in0";
+			};
+		};
+
+		spi0: spi-master@0d0a0000 {
+			compatible = "cdns,xtfpga-spi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0d0a0000 0xc>;
+
+			tlv320aic23: sound-codec@0 {
+				#sound-dai-cells = <0>;
+				compatible = "tlv320aic23";
+				reg = <0>;
+				spi-max-frequency = <12500000>;
+			};
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,mclk-fs = <256>;
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&tlv320aic23>;
+			simple-audio-card,bitclock-master = <0>;
+			simple-audio-card,frame-master = <0>;
+			clocks = <&cdce706 4>;
+		};
+	};
+};
diff --git a/arch/xtensa/include/asm/addrspace.h b/arch/xtensa/include/asm/addrspace.h
new file mode 100644
index 0000000..1d62259
--- /dev/null
+++ b/arch/xtensa/include/asm/addrspace.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2008-2013 Tensilica Inc.
+ * Copyright (C) 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_ADDRSPACE_H
+#define _XTENSA_ADDRSPACE_H
+
+#include <asm/arch/core.h>
+
+/*
+ * MMU Memory Map
+ *
+ * noMMU and v3 MMU have identity mapped address space on reset.
+ * V2 MMU:
+ *   IO (uncached)	f0000000..ffffffff	-> f000000
+ *   IO (cached)	e0000000..efffffff	-> f000000
+ *   MEM (uncached)	d8000000..dfffffff	-> 0000000
+ *   MEM (cached)	d0000000..d7ffffff	-> 0000000
+ *
+ * The actual location of memory and IO is the board property.
+ */
+
+#define IOADDR(x)		(CONFIG_SYS_IO_BASE + (x))
+#define MEMADDR(x)		(CONFIG_SYS_MEMORY_BASE + (x))
+#define PHYSADDR(x)		((x) - XCHAL_VECBASE_RESET_VADDR + \
+				 XCHAL_VECBASE_RESET_PADDR)
+
+#endif	/* _XTENSA_ADDRSPACE_H */
diff --git a/arch/xtensa/include/asm/arch-dc232b/core.h b/arch/xtensa/include/asm/arch-dc232b/core.h
new file mode 100644
index 0000000..548c971
--- /dev/null
+++ b/arch/xtensa/include/asm/arch-dc232b/core.h
@@ -0,0 +1,423 @@
+/*
+ * Xtensa processor core configuration information.
+ * This file is autogenerated, please do not edit.
+ *
+ * Copyright (C) 1999-2007 Tensilica Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_CORE_CONFIGURATION_H
+#define _XTENSA_CORE_CONFIGURATION_H
+
+
+/****************************************************************************
+	    Parameters Useful for Any Code, USER or PRIVILEGED
+ ****************************************************************************/
+
+/*
+ *  Note:  Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is
+ *  configured, and a value of 0 otherwise.  These macros are always defined.
+ */
+
+
+/*----------------------------------------------------------------------
+				ISA
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_BE			0	/* big-endian byte ordering */
+#define XCHAL_HAVE_WINDOWED		1	/* windowed registers option */
+#define XCHAL_NUM_AREGS			32	/* num of physical addr regs */
+#define XCHAL_NUM_AREGS_LOG2		5	/* log2(XCHAL_NUM_AREGS) */
+#define XCHAL_MAX_INSTRUCTION_SIZE	3	/* max instr bytes (3..8) */
+#define XCHAL_HAVE_DEBUG		1	/* debug option */
+#define XCHAL_HAVE_DENSITY		1	/* 16-bit instructions */
+#define XCHAL_HAVE_LOOPS		1	/* zero-overhead loops */
+#define XCHAL_HAVE_NSA			1	/* NSA/NSAU instructions */
+#define XCHAL_HAVE_MINMAX		1	/* MIN/MAX instructions */
+#define XCHAL_HAVE_SEXT			1	/* SEXT instruction */
+#define XCHAL_HAVE_CLAMPS		1	/* CLAMPS instruction */
+#define XCHAL_HAVE_MUL16		1	/* MUL16S/MUL16U instructions */
+#define XCHAL_HAVE_MUL32		1	/* MULL instruction */
+#define XCHAL_HAVE_MUL32_HIGH		0	/* MULUH/MULSH instructions */
+#define XCHAL_HAVE_DIV32		1	/* QUOS/QUOU/REMS/REMU instructions */
+#define XCHAL_HAVE_L32R			1	/* L32R instruction */
+#define XCHAL_HAVE_ABSOLUTE_LITERALS	1	/* non-PC-rel (extended) L32R */
+#define XCHAL_HAVE_CONST16		0	/* CONST16 instruction */
+#define XCHAL_HAVE_ADDX			1	/* ADDX#/SUBX# instructions */
+#define XCHAL_HAVE_WIDE_BRANCHES	0	/* B*.W18 or B*.W15 instr's */
+#define XCHAL_HAVE_PREDICTED_BRANCHES	0	/* B[EQ/EQZ/NE/NEZ]T instr's */
+#define XCHAL_HAVE_CALL4AND12		1	/* (obsolete option) */
+#define XCHAL_HAVE_ABS			1	/* ABS instruction */
+/*#define XCHAL_HAVE_POPC		0*/	/* POPC instruction */
+/*#define XCHAL_HAVE_CRC		0*/	/* CRC instruction */
+#define XCHAL_HAVE_RELEASE_SYNC		1	/* L32AI/S32RI instructions */
+#define XCHAL_HAVE_S32C1I		1	/* S32C1I instruction */
+#define XCHAL_HAVE_SPECULATION		0	/* speculation */
+#define XCHAL_HAVE_FULL_RESET		1	/* all regs/state reset */
+#define XCHAL_NUM_CONTEXTS		1	/* */
+#define XCHAL_NUM_MISC_REGS		2	/* num of scratch regs (0..4) */
+#define XCHAL_HAVE_TAP_MASTER		0	/* JTAG TAP control instr's */
+#define XCHAL_HAVE_PRID			1	/* processor ID register */
+#define XCHAL_HAVE_THREADPTR		1	/* THREADPTR register */
+#define XCHAL_HAVE_BOOLEANS		0	/* boolean registers */
+#define XCHAL_HAVE_CP			1	/* CPENABLE reg (coprocessor) */
+#define XCHAL_CP_MAXCFG			8	/* max allowed cp id plus one */
+#define XCHAL_HAVE_MAC16		1	/* MAC16 package */
+#define XCHAL_HAVE_VECTORFPU2005	0	/* vector floating-point pkg */
+#define XCHAL_HAVE_FP			0	/* floating point pkg */
+#define XCHAL_HAVE_VECTRA1		0	/* Vectra I  pkg */
+#define XCHAL_HAVE_VECTRALX		0	/* Vectra LX pkg */
+#define XCHAL_HAVE_HIFI2		0	/* HiFi2 Audio Engine pkg */
+
+
+/*----------------------------------------------------------------------
+				MISC
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_WRITEBUFFER_ENTRIES	8	/* size of write buffer */
+#define XCHAL_INST_FETCH_WIDTH		4	/* instr-fetch width in bytes */
+#define XCHAL_DATA_WIDTH		4	/* data width in bytes */
+/*  In T1050, applies to selected core load and store instructions (see ISA): */
+#define XCHAL_UNALIGNED_LOAD_EXCEPTION	1	/* unaligned loads cause exc. */
+#define XCHAL_UNALIGNED_STORE_EXCEPTION	1	/* unaligned stores cause exc.*/
+
+#define XCHAL_SW_VERSION		701001	/* sw version of this header */
+
+#define XCHAL_CORE_ID			"dc232b"	/* alphanum core name
+						   (CoreID) set in the Xtensa
+						   Processor Generator */
+
+#define XCHAL_CORE_DESCRIPTION		"Diamond 232L Standard Core Rev.B (LE)"
+#define XCHAL_BUILD_UNIQUE_ID		0x0000BEEF	/* 22-bit sw build ID */
+
+/*
+ *  These definitions describe the hardware targeted by this software.
+ */
+#define XCHAL_HW_CONFIGID0		0xC56307FE	/* ConfigID hi 32 bits*/
+#define XCHAL_HW_CONFIGID1		0x0D40BEEF	/* ConfigID lo 32 bits*/
+#define XCHAL_HW_VERSION_NAME		"LX2.1.1"	/* full version name */
+#define XCHAL_HW_VERSION_MAJOR		2210	/* major ver# of targeted hw */
+#define XCHAL_HW_VERSION_MINOR		1	/* minor ver# of targeted hw */
+#define XCHAL_HW_VERSION		221001	/* major*100+minor */
+#define XCHAL_HW_REL_LX2		1
+#define XCHAL_HW_REL_LX2_1		1
+#define XCHAL_HW_REL_LX2_1_1		1
+#define XCHAL_HW_CONFIGID_RELIABLE	1
+/*  If software targets a *range* of hardware versions, these are the bounds: */
+#define XCHAL_HW_MIN_VERSION_MAJOR	2210	/* major v of earliest tgt hw */
+#define XCHAL_HW_MIN_VERSION_MINOR	1	/* minor v of earliest tgt hw */
+#define XCHAL_HW_MIN_VERSION		221001	/* earliest targeted hw */
+#define XCHAL_HW_MAX_VERSION_MAJOR	2210	/* major v of latest tgt hw */
+#define XCHAL_HW_MAX_VERSION_MINOR	1	/* minor v of latest tgt hw */
+#define XCHAL_HW_MAX_VERSION		221001	/* latest targeted hw */
+
+
+/*----------------------------------------------------------------------
+				CACHE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_ICACHE_LINESIZE		32	/* I-cache line size in bytes */
+#define XCHAL_DCACHE_LINESIZE		32	/* D-cache line size in bytes */
+#define XCHAL_ICACHE_LINEWIDTH		5	/* log2(I line size in bytes) */
+#define XCHAL_DCACHE_LINEWIDTH		5	/* log2(D line size in bytes) */
+
+#define XCHAL_ICACHE_SIZE		16384	/* I-cache size in bytes or 0 */
+#define XCHAL_DCACHE_SIZE		16384	/* D-cache size in bytes or 0 */
+
+#define XCHAL_DCACHE_IS_WRITEBACK	1	/* writeback feature */
+
+
+
+
+/****************************************************************************
+    Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code
+ ****************************************************************************/
+
+
+#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY
+
+/*----------------------------------------------------------------------
+				CACHE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_PIF			1	/* any outbound PIF present */
+
+/*  If present, cache size in bytes == (ways * 2^(linewidth + setwidth)).  */
+
+/*  Number of cache sets in log2(lines per way):  */
+#define XCHAL_ICACHE_SETWIDTH		7
+#define XCHAL_DCACHE_SETWIDTH		7
+
+/*  Cache set associativity (number of ways):  */
+#define XCHAL_ICACHE_WAYS		4
+#define XCHAL_DCACHE_WAYS		4
+
+/*  Cache features:  */
+#define XCHAL_ICACHE_LINE_LOCKABLE	1
+#define XCHAL_DCACHE_LINE_LOCKABLE	1
+#define XCHAL_ICACHE_ECC_PARITY		0
+#define XCHAL_DCACHE_ECC_PARITY		0
+
+/*  Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits):  */
+#define XCHAL_CA_BITS			4
+
+
+/*----------------------------------------------------------------------
+			INTERNAL I/D RAM/ROMs and XLMI
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_INSTROM		0	/* number of core instr. ROMs */
+#define XCHAL_NUM_INSTRAM		0	/* number of core instr. RAMs */
+#define XCHAL_NUM_DATAROM		0	/* number of core data ROMs */
+#define XCHAL_NUM_DATARAM		0	/* number of core data RAMs */
+#define XCHAL_NUM_URAM			0	/* number of core unified RAMs*/
+#define XCHAL_NUM_XLMI			0	/* number of core XLMI ports */
+
+
+/*----------------------------------------------------------------------
+			INTERRUPTS and TIMERS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_INTERRUPTS		1	/* interrupt option */
+#define XCHAL_HAVE_HIGHPRI_INTERRUPTS	1	/* med/high-pri. interrupts */
+#define XCHAL_HAVE_NMI			1	/* non-maskable interrupt */
+#define XCHAL_HAVE_CCOUNT		1	/* CCOUNT reg. (timer option) */
+#define XCHAL_NUM_TIMERS		3	/* number of CCOMPAREn regs */
+#define XCHAL_NUM_INTERRUPTS		22	/* number of interrupts */
+#define XCHAL_NUM_INTERRUPTS_LOG2	5	/* ceil(log2(NUM_INTERRUPTS)) */
+#define XCHAL_NUM_EXTINTERRUPTS		17	/* num of external interrupts */
+#define XCHAL_NUM_INTLEVELS		6	/* number of interrupt levels
+						   (not including level zero) */
+#define XCHAL_EXCM_LEVEL		3	/* level masked by PS.EXCM */
+	/* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */
+
+/*  Masks of interrupts at each interrupt level:  */
+#define XCHAL_INTLEVEL1_MASK		0x001F80FF
+#define XCHAL_INTLEVEL2_MASK		0x00000100
+#define XCHAL_INTLEVEL3_MASK		0x00200E00
+#define XCHAL_INTLEVEL4_MASK		0x00001000
+#define XCHAL_INTLEVEL5_MASK		0x00002000
+#define XCHAL_INTLEVEL6_MASK		0x00000000
+#define XCHAL_INTLEVEL7_MASK		0x00004000
+
+/*  Masks of interrupts at each range 1..n of interrupt levels:  */
+#define XCHAL_INTLEVEL1_ANDBELOW_MASK	0x001F80FF
+#define XCHAL_INTLEVEL2_ANDBELOW_MASK	0x001F81FF
+#define XCHAL_INTLEVEL3_ANDBELOW_MASK	0x003F8FFF
+#define XCHAL_INTLEVEL4_ANDBELOW_MASK	0x003F9FFF
+#define XCHAL_INTLEVEL5_ANDBELOW_MASK	0x003FBFFF
+#define XCHAL_INTLEVEL6_ANDBELOW_MASK	0x003FBFFF
+#define XCHAL_INTLEVEL7_ANDBELOW_MASK	0x003FFFFF
+
+/*  Level of each interrupt:  */
+#define XCHAL_INT0_LEVEL		1
+#define XCHAL_INT1_LEVEL		1
+#define XCHAL_INT2_LEVEL		1
+#define XCHAL_INT3_LEVEL		1
+#define XCHAL_INT4_LEVEL		1
+#define XCHAL_INT5_LEVEL		1
+#define XCHAL_INT6_LEVEL		1
+#define XCHAL_INT7_LEVEL		1
+#define XCHAL_INT8_LEVEL		2
+#define XCHAL_INT9_LEVEL		3
+#define XCHAL_INT10_LEVEL		3
+#define XCHAL_INT11_LEVEL		3
+#define XCHAL_INT12_LEVEL		4
+#define XCHAL_INT13_LEVEL		5
+#define XCHAL_INT14_LEVEL		7
+#define XCHAL_INT15_LEVEL		1
+#define XCHAL_INT16_LEVEL		1
+#define XCHAL_INT17_LEVEL		1
+#define XCHAL_INT18_LEVEL		1
+#define XCHAL_INT19_LEVEL		1
+#define XCHAL_INT20_LEVEL		1
+#define XCHAL_INT21_LEVEL		3
+#define XCHAL_DEBUGLEVEL		6	/* debug interrupt level */
+#define XCHAL_HAVE_DEBUG_EXTERN_INT	1	/* OCD external db interrupt */
+#define XCHAL_NMILEVEL			7	/* NMI "level" (for use with
+						   EXCSAVE/EPS/EPC_n, RFI n) */
+
+/*  Type of each interrupt:  */
+#define XCHAL_INT0_TYPE		XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT1_TYPE		XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT2_TYPE		XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT3_TYPE		XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT4_TYPE		XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT5_TYPE		XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT6_TYPE		XTHAL_INTTYPE_TIMER
+#define XCHAL_INT7_TYPE		XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT8_TYPE		XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT9_TYPE		XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT10_TYPE	XTHAL_INTTYPE_TIMER
+#define XCHAL_INT11_TYPE	XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT12_TYPE	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT13_TYPE	XTHAL_INTTYPE_TIMER
+#define XCHAL_INT14_TYPE	XTHAL_INTTYPE_NMI
+#define XCHAL_INT15_TYPE	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT16_TYPE	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT17_TYPE	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT18_TYPE	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT19_TYPE	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT20_TYPE	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT21_TYPE	XTHAL_INTTYPE_EXTERN_EDGE
+
+/*  Masks of interrupts for each type of interrupt:  */
+#define XCHAL_INTTYPE_MASK_UNCONFIGURED	0xFFC00000
+#define XCHAL_INTTYPE_MASK_SOFTWARE	0x00000880
+#define XCHAL_INTTYPE_MASK_EXTERN_EDGE	0x003F8000
+#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL	0x0000133F
+#define XCHAL_INTTYPE_MASK_TIMER	0x00002440
+#define XCHAL_INTTYPE_MASK_NMI		0x00004000
+#define XCHAL_INTTYPE_MASK_WRITE_ERROR	0x00000000
+
+/*  Interrupt numbers assigned to specific interrupt sources:  */
+#define XCHAL_TIMER0_INTERRUPT		6	/* CCOMPARE0 */
+#define XCHAL_TIMER1_INTERRUPT		10	/* CCOMPARE1 */
+#define XCHAL_TIMER2_INTERRUPT		13	/* CCOMPARE2 */
+#define XCHAL_TIMER3_INTERRUPT		XTHAL_TIMER_UNCONFIGURED
+#define XCHAL_NMI_INTERRUPT		14	/* non-maskable interrupt */
+
+/*  Interrupt numbers for levels at which only one interrupt is configured:  */
+#define XCHAL_INTLEVEL2_NUM		8
+#define XCHAL_INTLEVEL4_NUM		12
+#define XCHAL_INTLEVEL5_NUM		13
+#define XCHAL_INTLEVEL7_NUM		14
+/*  (There are many interrupts each at level(s) 1, 3.)  */
+
+
+/*
+ *  External interrupt vectors/levels.
+ *  These macros describe how Xtensa processor interrupt numbers
+ *  (as numbered internally, eg. in INTERRUPT and INTENABLE registers)
+ *  map to external BInterrupt<n> pins, for those interrupts
+ *  configured as external (level-triggered, edge-triggered, or NMI).
+ *  See the Xtensa processor databook for more details.
+ */
+
+/*  Core interrupt numbers mapped to each EXTERNAL interrupt number:  */
+#define XCHAL_EXTINT0_NUM		0	/* (intlevel 1) */
+#define XCHAL_EXTINT1_NUM		1	/* (intlevel 1) */
+#define XCHAL_EXTINT2_NUM		2	/* (intlevel 1) */
+#define XCHAL_EXTINT3_NUM		3	/* (intlevel 1) */
+#define XCHAL_EXTINT4_NUM		4	/* (intlevel 1) */
+#define XCHAL_EXTINT5_NUM		5	/* (intlevel 1) */
+#define XCHAL_EXTINT6_NUM		8	/* (intlevel 2) */
+#define XCHAL_EXTINT7_NUM		9	/* (intlevel 3) */
+#define XCHAL_EXTINT8_NUM		12	/* (intlevel 4) */
+#define XCHAL_EXTINT9_NUM		14	/* (intlevel 7) */
+#define XCHAL_EXTINT10_NUM		15	/* (intlevel 1) */
+#define XCHAL_EXTINT11_NUM		16	/* (intlevel 1) */
+#define XCHAL_EXTINT12_NUM		17	/* (intlevel 1) */
+#define XCHAL_EXTINT13_NUM		18	/* (intlevel 1) */
+#define XCHAL_EXTINT14_NUM		19	/* (intlevel 1) */
+#define XCHAL_EXTINT15_NUM		20	/* (intlevel 1) */
+#define XCHAL_EXTINT16_NUM		21	/* (intlevel 3) */
+
+
+/*----------------------------------------------------------------------
+			EXCEPTIONS and VECTORS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_XEA_VERSION		2	/* Xtensa Exception Architecture
+						   number: 1 == XEA1 (old)
+							   2 == XEA2 (new)
+							   0 == XEAX (extern) */
+#define XCHAL_HAVE_XEA1			0	/* Exception Architecture 1 */
+#define XCHAL_HAVE_XEA2			1	/* Exception Architecture 2 */
+#define XCHAL_HAVE_XEAX			0	/* External Exception Arch. */
+#define XCHAL_HAVE_EXCEPTIONS		1	/* exception option */
+#define XCHAL_HAVE_MEM_ECC_PARITY	0	/* local memory ECC/parity */
+#define XCHAL_HAVE_VECTOR_SELECT	1	/* relocatable vectors */
+#define XCHAL_HAVE_VECBASE		1	/* relocatable vectors */
+#define XCHAL_VECBASE_RESET_VADDR	0xD0000000  /* VECBASE reset value */
+#define XCHAL_VECBASE_RESET_PADDR	0x00000000
+#define XCHAL_RESET_VECBASE_OVERLAP	0
+
+#define XCHAL_RESET_VECTOR0_VADDR	0xFE000000
+#define XCHAL_RESET_VECTOR0_PADDR	0xFE000000
+#define XCHAL_RESET_VECTOR1_VADDR	0xD8000500
+#define XCHAL_RESET_VECTOR1_PADDR	0x00000500
+#define XCHAL_RESET_VECTOR_VADDR	0xFE000000
+#define XCHAL_RESET_VECTOR_PADDR	0xFE000000
+#define XCHAL_USER_VECOFS		0x00000340
+#define XCHAL_USER_VECTOR_VADDR		0xD0000340
+#define XCHAL_USER_VECTOR_PADDR		0x00000340
+#define XCHAL_KERNEL_VECOFS		0x00000300
+#define XCHAL_KERNEL_VECTOR_VADDR	0xD0000300
+#define XCHAL_KERNEL_VECTOR_PADDR	0x00000300
+#define XCHAL_DOUBLEEXC_VECOFS		0x000003C0
+#define XCHAL_DOUBLEEXC_VECTOR_VADDR	0xD00003C0
+#define XCHAL_DOUBLEEXC_VECTOR_PADDR	0x000003C0
+#define XCHAL_WINDOW_OF4_VECOFS		0x00000000
+#define XCHAL_WINDOW_UF4_VECOFS		0x00000040
+#define XCHAL_WINDOW_OF8_VECOFS		0x00000080
+#define XCHAL_WINDOW_UF8_VECOFS		0x000000C0
+#define XCHAL_WINDOW_OF12_VECOFS	0x00000100
+#define XCHAL_WINDOW_UF12_VECOFS	0x00000140
+#define XCHAL_WINDOW_VECTORS_VADDR	0xD0000000
+#define XCHAL_WINDOW_VECTORS_PADDR	0x00000000
+#define XCHAL_INTLEVEL2_VECOFS		0x00000180
+#define XCHAL_INTLEVEL2_VECTOR_VADDR	0xD0000180
+#define XCHAL_INTLEVEL2_VECTOR_PADDR	0x00000180
+#define XCHAL_INTLEVEL3_VECOFS		0x000001C0
+#define XCHAL_INTLEVEL3_VECTOR_VADDR	0xD00001C0
+#define XCHAL_INTLEVEL3_VECTOR_PADDR	0x000001C0
+#define XCHAL_INTLEVEL4_VECOFS		0x00000200
+#define XCHAL_INTLEVEL4_VECTOR_VADDR	0xD0000200
+#define XCHAL_INTLEVEL4_VECTOR_PADDR	0x00000200
+#define XCHAL_INTLEVEL5_VECOFS		0x00000240
+#define XCHAL_INTLEVEL5_VECTOR_VADDR	0xD0000240
+#define XCHAL_INTLEVEL5_VECTOR_PADDR	0x00000240
+#define XCHAL_INTLEVEL6_VECOFS		0x00000280
+#define XCHAL_INTLEVEL6_VECTOR_VADDR	0xD0000280
+#define XCHAL_INTLEVEL6_VECTOR_PADDR	0x00000280
+#define XCHAL_DEBUG_VECOFS		XCHAL_INTLEVEL6_VECOFS
+#define XCHAL_DEBUG_VECTOR_VADDR	XCHAL_INTLEVEL6_VECTOR_VADDR
+#define XCHAL_DEBUG_VECTOR_PADDR	XCHAL_INTLEVEL6_VECTOR_PADDR
+#define XCHAL_NMI_VECOFS		0x000002C0
+#define XCHAL_NMI_VECTOR_VADDR		0xD00002C0
+#define XCHAL_NMI_VECTOR_PADDR		0x000002C0
+#define XCHAL_INTLEVEL7_VECOFS		XCHAL_NMI_VECOFS
+#define XCHAL_INTLEVEL7_VECTOR_VADDR	XCHAL_NMI_VECTOR_VADDR
+#define XCHAL_INTLEVEL7_VECTOR_PADDR	XCHAL_NMI_VECTOR_PADDR
+
+
+/*----------------------------------------------------------------------
+				DEBUG
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_OCD			1	/* OnChipDebug option */
+#define XCHAL_NUM_IBREAK		2	/* number of IBREAKn regs */
+#define XCHAL_NUM_DBREAK		2	/* number of DBREAKn regs */
+#define XCHAL_HAVE_OCD_DIR_ARRAY	1	/* faster OCD option */
+
+
+/*----------------------------------------------------------------------
+				MMU
+  ----------------------------------------------------------------------*/
+
+/*  See core-matmap.h header file for more details.  */
+
+#define XCHAL_HAVE_TLBS			1	/* inverse of HAVE_CACHEATTR */
+#define XCHAL_HAVE_SPANNING_WAY		0	/* one way maps I+D 4GB vaddr */
+#define XCHAL_HAVE_IDENTITY_MAP		0	/* vaddr == paddr always */
+#define XCHAL_HAVE_CACHEATTR		0	/* CACHEATTR register present */
+#define XCHAL_HAVE_MIMIC_CACHEATTR	0	/* region protection */
+#define XCHAL_HAVE_XLT_CACHEATTR	0	/* region prot. w/translation */
+#define XCHAL_HAVE_PTP_MMU		1	/* full MMU (with page table
+						   [autorefill] and protection)
+						   usable for an MMU-based OS */
+/*  If none of the above last 4 are set, it's a custom TLB configuration.  */
+#define XCHAL_ITLB_ARF_ENTRIES_LOG2	2	/* log2(autorefill way size) */
+#define XCHAL_DTLB_ARF_ENTRIES_LOG2	2	/* log2(autorefill way size) */
+
+#define XCHAL_MMU_ASID_BITS		8	/* number of bits in ASIDs */
+#define XCHAL_MMU_RINGS			4	/* number of rings (1..4) */
+#define XCHAL_MMU_RING_BITS		2	/* num of bits in RING field */
+
+#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */
+
+
+#endif /* _XTENSA_CORE_CONFIGURATION_H */
+
diff --git a/arch/xtensa/include/asm/arch-dc232b/tie-asm.h b/arch/xtensa/include/asm/arch-dc232b/tie-asm.h
new file mode 100644
index 0000000..501d885
--- /dev/null
+++ b/arch/xtensa/include/asm/arch-dc232b/tie-asm.h
@@ -0,0 +1,121 @@
+/*
+ * This header file contains assembly-language definitions (assembly
+ * macros, etc.) for this specific Xtensa processor's TIE extensions
+ * and options.  It is customized to this Xtensa processor configuration.
+ * This file is autogenerated, please do not edit.
+ *
+ * Copyright (C) 1999-2007 Tensilica Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_CORE_TIE_ASM_H
+#define _XTENSA_CORE_TIE_ASM_H
+
+/*  Selection parameter values for save-area save/restore macros:  */
+/*  Option vs. TIE:  */
+#define XTHAL_SAS_TIE	0x0001	/* custom extension or coprocessor */
+#define XTHAL_SAS_OPT	0x0002	/* optional (and not a coprocessor) */
+/*  Whether used automatically by compiler:  */
+#define XTHAL_SAS_NOCC	0x0004	/* not used by compiler w/o special opts/code */
+#define XTHAL_SAS_CC	0x0008	/* used by compiler without special opts/code */
+/*  ABI handling across function calls:  */
+#define XTHAL_SAS_CALR	0x0010	/* caller-saved */
+#define XTHAL_SAS_CALE	0x0020	/* callee-saved */
+#define XTHAL_SAS_GLOB	0x0040	/* global across function calls (in thread) */
+/*  Misc  */
+#define XTHAL_SAS_ALL	0xFFFF	/* include all default NCP contents */
+
+
+
+/* Macro to save all non-coprocessor (extra) custom TIE and optional state
+ * (not including zero-overhead loop registers).
+ * Save area ptr (clobbered):  ptr  (1 byte aligned)
+ * Scratch regs  (clobbered):  at1..at4  (only first XCHAL_NCP_NUM_ATMPS needed)
+ */
+	.macro xchal_ncp_store  ptr at1 at2 at3 at4  continue=0 ofs=-1 select=XTHAL_SAS_ALL
+	xchal_sa_start	\continue, \ofs
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~\select
+	xchal_sa_align	\ptr, 0, 1024-8, 4, 4
+	rsr	\at1, ACCLO		// MAC16 accumulator
+	rsr	\at2, ACCHI
+	s32i	\at1, \ptr, .Lxchal_ofs_ + 0
+	s32i	\at2, \ptr, .Lxchal_ofs_ + 4
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 8
+	.endif
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~\select
+	xchal_sa_align	\ptr, 0, 1024-16, 4, 4
+	rsr	\at1, M0		// MAC16 registers
+	rsr	\at2, M1
+	s32i	\at1, \ptr, .Lxchal_ofs_ + 0
+	s32i	\at2, \ptr, .Lxchal_ofs_ + 4
+	rsr	\at1, M2
+	rsr	\at2, M3
+	s32i	\at1, \ptr, .Lxchal_ofs_ + 8
+	s32i	\at2, \ptr, .Lxchal_ofs_ + 12
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 16
+	.endif
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~\select
+	xchal_sa_align	\ptr, 0, 1024-4, 4, 4
+	rsr	\at1, SCOMPARE1		// conditional store option
+	s32i	\at1, \ptr, .Lxchal_ofs_ + 0
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 4
+	.endif
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~\select
+	xchal_sa_align	\ptr, 0, 1024-4, 4, 4
+	rur	\at1, THREADPTR		// threadptr option
+	s32i	\at1, \ptr, .Lxchal_ofs_ + 0
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 4
+	.endif
+	.endm	// xchal_ncp_store
+
+/* Macro to save all non-coprocessor (extra) custom TIE and optional state
+ * (not including zero-overhead loop registers).
+ * Save area ptr (clobbered):  ptr  (1 byte aligned)
+ * Scratch regs  (clobbered):  at1..at4  (only first XCHAL_NCP_NUM_ATMPS needed)
+ */
+	.macro xchal_ncp_load  ptr at1 at2 at3 at4  continue=0 ofs=-1 select=XTHAL_SAS_ALL
+	xchal_sa_start	\continue, \ofs
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~\select
+	xchal_sa_align	\ptr, 0, 1024-8, 4, 4
+	l32i	\at1, \ptr, .Lxchal_ofs_ + 0
+	l32i	\at2, \ptr, .Lxchal_ofs_ + 4
+	wsr	\at1, ACCLO		// MAC16 accumulator
+	wsr	\at2, ACCHI
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 8
+	.endif
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~\select
+	xchal_sa_align	\ptr, 0, 1024-16, 4, 4
+	l32i	\at1, \ptr, .Lxchal_ofs_ + 0
+	l32i	\at2, \ptr, .Lxchal_ofs_ + 4
+	wsr	\at1, M0		// MAC16 registers
+	wsr	\at2, M1
+	l32i	\at1, \ptr, .Lxchal_ofs_ + 8
+	l32i	\at2, \ptr, .Lxchal_ofs_ + 12
+	wsr	\at1, M2
+	wsr	\at2, M3
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 16
+	.endif
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~\select
+	xchal_sa_align	\ptr, 0, 1024-4, 4, 4
+	l32i	\at1, \ptr, .Lxchal_ofs_ + 0
+	wsr	\at1, SCOMPARE1		// conditional store option
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 4
+	.endif
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~\select
+	xchal_sa_align	\ptr, 0, 1024-4, 4, 4
+	l32i	\at1, \ptr, .Lxchal_ofs_ + 0
+	wur	\at1, THREADPTR		// threadptr option
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 4
+	.endif
+	.endm	// xchal_ncp_load
+
+
+
+#define XCHAL_NCP_NUM_ATMPS	2
+
+
+#define XCHAL_SA_NUM_ATMPS	2
+
+#endif /*_XTENSA_CORE_TIE_ASM_H*/
+
diff --git a/arch/xtensa/include/asm/arch-dc232b/tie.h b/arch/xtensa/include/asm/arch-dc232b/tie.h
new file mode 100644
index 0000000..8479a01
--- /dev/null
+++ b/arch/xtensa/include/asm/arch-dc232b/tie.h
@@ -0,0 +1,130 @@
+/*
+ * This header file describes this specific Xtensa processor's TIE extensions
+ * that extend basic Xtensa core functionality.  It is customized to this
+ * Xtensa processor configuration.
+ * This file is autogenerated, please do not edit.
+ *
+ * Copyright (C) 1999-2007 Tensilica Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_CORE_TIE_H
+#define _XTENSA_CORE_TIE_H
+
+#define XCHAL_CP_NUM			1	/* number of coprocessors */
+#define XCHAL_CP_MAX			8	/* max CP ID + 1 (0 if none) */
+#define XCHAL_CP_MASK			0x80	/* bitmask of all CPs by ID */
+#define XCHAL_CP_PORT_MASK		0x80	/* bitmask of only port CPs */
+
+/*  Basic parameters of each coprocessor:  */
+#define XCHAL_CP7_NAME			"XTIOP"
+#define XCHAL_CP7_IDENT			XTIOP
+#define XCHAL_CP7_SA_SIZE		0	/* size of state save area */
+#define XCHAL_CP7_SA_ALIGN		1	/* min alignment of save area */
+#define XCHAL_CP_ID_XTIOP		7	/* coprocessor ID (0..7) */
+
+/*  Filler info for unassigned coprocessors, to simplify arrays etc:  */
+#define XCHAL_CP0_SA_SIZE		0
+#define XCHAL_CP0_SA_ALIGN		1
+#define XCHAL_CP1_SA_SIZE		0
+#define XCHAL_CP1_SA_ALIGN		1
+#define XCHAL_CP2_SA_SIZE		0
+#define XCHAL_CP2_SA_ALIGN		1
+#define XCHAL_CP3_SA_SIZE		0
+#define XCHAL_CP3_SA_ALIGN		1
+#define XCHAL_CP4_SA_SIZE		0
+#define XCHAL_CP4_SA_ALIGN		1
+#define XCHAL_CP5_SA_SIZE		0
+#define XCHAL_CP5_SA_ALIGN		1
+#define XCHAL_CP6_SA_SIZE		0
+#define XCHAL_CP6_SA_ALIGN		1
+
+/*  Save area for non-coprocessor optional and custom (TIE) state:  */
+#define XCHAL_NCP_SA_SIZE		32
+#define XCHAL_NCP_SA_ALIGN		4
+
+/*  Total save area for optional and custom state (NCP + CPn):  */
+#define XCHAL_TOTAL_SA_SIZE		32	/* with 16-byte align padding */
+#define XCHAL_TOTAL_SA_ALIGN		4	/* actual minimum alignment */
+
+/*
+ * Detailed contents of save areas.
+ * NOTE:  caller must define the XCHAL_SA_REG macro (not defined here)
+ * before expanding the XCHAL_xxx_SA_LIST() macros.
+ *
+ * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize,
+ *		dbnum,base,regnum,bitsz,gapsz,reset,x...)
+ *
+ *	s = passed from XCHAL_*_LIST(s), eg. to select how to expand
+ *	ccused = set if used by compiler without special options or code
+ *	abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global)
+ *	kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg)
+ *	opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg)
+ *	name = lowercase reg name (no quotes)
+ *	galign = group byte alignment (power of 2) (galign >= align)
+ *	align = register byte alignment (power of 2)
+ *	asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz)
+ *	  (not including any pad bytes required to galign this or next reg)
+ *	dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>)
+ *	base = reg shortname w/o index (or sr=special, ur=TIE user reg)
+ *	regnum = reg index in regfile, or special/TIE-user reg number
+ *	bitsz = number of significant bits (regfile width, or ur/sr mask bits)
+ *	gapsz = intervening bits, if bitsz bits not stored contiguously
+ *	(padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize)
+ *	reset = register reset value (or 0 if undefined at reset)
+ *	x = reserved for future use (0 until then)
+ *
+ *  To filter out certain registers, e.g. to expand only the non-global
+ *  registers used by the compiler, you can do something like this:
+ *
+ *  #define XCHAL_SA_REG(s,ccused,p...)	SELCC##ccused(p)
+ *  #define SELCC0(p...)
+ *  #define SELCC1(abikind,p...)	SELAK##abikind(p)
+ *  #define SELAK0(p...)		REG(p)
+ *  #define SELAK1(p...)		REG(p)
+ *  #define SELAK2(p...)
+ *  #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \
+ *		...what you want to expand...
+ */
+
+#define XCHAL_NCP_SA_NUM	8
+#define XCHAL_NCP_SA_LIST(s)	\
+ XCHAL_SA_REG(s,1,0,0,1,          acclo, 4, 4, 4,0x0210,  sr,16 , 32,0,0,0) \
+ XCHAL_SA_REG(s,1,0,0,1,          acchi, 4, 4, 4,0x0211,  sr,17 ,  8,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,             m0, 4, 4, 4,0x0220,  sr,32 , 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,             m1, 4, 4, 4,0x0221,  sr,33 , 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,             m2, 4, 4, 4,0x0222,  sr,34 , 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,             m3, 4, 4, 4,0x0223,  sr,35 , 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,      scompare1, 4, 4, 4,0x020C,  sr,12 , 32,0,0,0) \
+ XCHAL_SA_REG(s,1,2,1,1,      threadptr, 4, 4, 4,0x03E7,  ur,231, 32,0,0,0)
+
+#define XCHAL_CP0_SA_NUM	0
+#define XCHAL_CP0_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP1_SA_NUM	0
+#define XCHAL_CP1_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP2_SA_NUM	0
+#define XCHAL_CP2_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP3_SA_NUM	0
+#define XCHAL_CP3_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP4_SA_NUM	0
+#define XCHAL_CP4_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP5_SA_NUM	0
+#define XCHAL_CP5_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP6_SA_NUM	0
+#define XCHAL_CP6_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP7_SA_NUM	0
+#define XCHAL_CP7_SA_LIST(s)	/* empty */
+
+/* Byte length of instruction from its first nibble (op0 field), per FLIX.  */
+#define XCHAL_OP0_FORMAT_LENGTHS	3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3
+
+#endif /*_XTENSA_CORE_TIE_H*/
+
diff --git a/arch/xtensa/include/asm/arch-dc233c/core.h b/arch/xtensa/include/asm/arch-dc233c/core.h
new file mode 100644
index 0000000..fd2c0e8
--- /dev/null
+++ b/arch/xtensa/include/asm/arch-dc233c/core.h
@@ -0,0 +1,454 @@
+/*
+ * Xtensa processor core configuration information.
+ * This file is autogenerated, please do not edit.
+ *
+ * Copyright (C) 1999-2010 Tensilica Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_CORE_CONFIGURATION_H
+#define _XTENSA_CORE_CONFIGURATION_H
+
+
+/****************************************************************************
+	    Parameters Useful for Any Code, USER or PRIVILEGED
+ ****************************************************************************/
+
+/*
+ *  Note:  Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is
+ *  configured, and a value of 0 otherwise.  These macros are always defined.
+ */
+
+
+/*----------------------------------------------------------------------
+				ISA
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_BE			0	/* big-endian byte ordering */
+#define XCHAL_HAVE_WINDOWED		1	/* windowed registers option */
+#define XCHAL_NUM_AREGS			32	/* num of physical addr regs */
+#define XCHAL_NUM_AREGS_LOG2		5	/* log2(XCHAL_NUM_AREGS) */
+#define XCHAL_MAX_INSTRUCTION_SIZE	3	/* max instr bytes (3..8) */
+#define XCHAL_HAVE_DEBUG		1	/* debug option */
+#define XCHAL_HAVE_DENSITY		1	/* 16-bit instructions */
+#define XCHAL_HAVE_LOOPS		1	/* zero-overhead loops */
+#define XCHAL_HAVE_NSA			1	/* NSA/NSAU instructions */
+#define XCHAL_HAVE_MINMAX		1	/* MIN/MAX instructions */
+#define XCHAL_HAVE_SEXT			1	/* SEXT instruction */
+#define XCHAL_HAVE_CLAMPS		1	/* CLAMPS instruction */
+#define XCHAL_HAVE_MUL16		1	/* MUL16S/MUL16U instructions */
+#define XCHAL_HAVE_MUL32		1	/* MULL instruction */
+#define XCHAL_HAVE_MUL32_HIGH		0	/* MULUH/MULSH instructions */
+#define XCHAL_HAVE_DIV32		1	/* QUOS/QUOU/REMS/REMU instructions */
+#define XCHAL_HAVE_L32R			1	/* L32R instruction */
+#define XCHAL_HAVE_ABSOLUTE_LITERALS	1	/* non-PC-rel (extended) L32R */
+#define XCHAL_HAVE_CONST16		0	/* CONST16 instruction */
+#define XCHAL_HAVE_ADDX			1	/* ADDX#/SUBX# instructions */
+#define XCHAL_HAVE_WIDE_BRANCHES	0	/* B*.W18 or B*.W15 instr's */
+#define XCHAL_HAVE_PREDICTED_BRANCHES	0	/* B[EQ/EQZ/NE/NEZ]T instr's */
+#define XCHAL_HAVE_CALL4AND12		1	/* (obsolete option) */
+#define XCHAL_HAVE_ABS			1	/* ABS instruction */
+/*#define XCHAL_HAVE_POPC		0*/	/* POPC instruction */
+/*#define XCHAL_HAVE_CRC		0*/	/* CRC instruction */
+#define XCHAL_HAVE_RELEASE_SYNC		1	/* L32AI/S32RI instructions */
+#define XCHAL_HAVE_S32C1I		1	/* S32C1I instruction */
+#define XCHAL_HAVE_SPECULATION		0	/* speculation */
+#define XCHAL_HAVE_FULL_RESET		1	/* all regs/state reset */
+#define XCHAL_NUM_CONTEXTS		1	/* */
+#define XCHAL_NUM_MISC_REGS		2	/* num of scratch regs (0..4) */
+#define XCHAL_HAVE_TAP_MASTER		0	/* JTAG TAP control instr's */
+#define XCHAL_HAVE_PRID			1	/* processor ID register */
+#define XCHAL_HAVE_EXTERN_REGS		1	/* WER/RER instructions */
+#define XCHAL_HAVE_MP_INTERRUPTS	0	/* interrupt distributor port */
+#define XCHAL_HAVE_MP_RUNSTALL		0	/* core RunStall control port */
+#define XCHAL_HAVE_THREADPTR		1	/* THREADPTR register */
+#define XCHAL_HAVE_BOOLEANS		0	/* boolean registers */
+#define XCHAL_HAVE_CP			1	/* CPENABLE reg (coprocessor) */
+#define XCHAL_CP_MAXCFG			8	/* max allowed cp id plus one */
+#define XCHAL_HAVE_MAC16		1	/* MAC16 package */
+#define XCHAL_HAVE_VECTORFPU2005	0	/* vector floating-point pkg */
+#define XCHAL_HAVE_FP			0	/* floating point pkg */
+#define XCHAL_HAVE_DFP			0	/* double precision FP pkg */
+#define XCHAL_HAVE_DFP_accel		0	/* double precision FP acceleration pkg */
+#define XCHAL_HAVE_VECTRA1		0	/* Vectra I  pkg */
+#define XCHAL_HAVE_VECTRALX		0	/* Vectra LX pkg */
+#define XCHAL_HAVE_HIFIPRO		0	/* HiFiPro Audio Engine pkg */
+#define XCHAL_HAVE_HIFI2		0	/* HiFi2 Audio Engine pkg */
+#define XCHAL_HAVE_HIFI2EP	0	/* HiFi2EP */
+#define XCHAL_HAVE_CONNXD2		0	/* ConnX D2 pkg */
+#define XCHAL_HAVE_BBE16		0	/* ConnX BBE16 pkg */
+#define XCHAL_HAVE_BBE16_RSQRT		0	/* BBE16 & vector recip sqrt */
+#define XCHAL_HAVE_BBE16_VECDIV		0	/* BBE16 & vector divide */
+#define XCHAL_HAVE_BBE16_DESPREAD	0	/* BBE16 & despread */
+#define XCHAL_HAVE_BSP3			0	/* ConnX BSP3 pkg */
+#define XCHAL_HAVE_SSP16		0	/* ConnX SSP16 pkg */
+#define XCHAL_HAVE_SSP16_VITERBI	0	/* SSP16 & viterbi */
+#define XCHAL_HAVE_TURBO16		0	/* ConnX Turbo16 pkg */
+#define XCHAL_HAVE_BBP16		0	/* ConnX BBP16 pkg */
+
+
+/*----------------------------------------------------------------------
+				MISC
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_WRITEBUFFER_ENTRIES	8	/* size of write buffer */
+#define XCHAL_INST_FETCH_WIDTH		4	/* instr-fetch width in bytes */
+#define XCHAL_DATA_WIDTH		4	/* data width in bytes */
+/*  In T1050, applies to selected core load and store instructions (see ISA): */
+#define XCHAL_UNALIGNED_LOAD_EXCEPTION	1	/* unaligned loads cause exc. */
+#define XCHAL_UNALIGNED_STORE_EXCEPTION	1	/* unaligned stores cause exc.*/
+#define XCHAL_UNALIGNED_LOAD_HW		0	/* unaligned loads work in hw */
+#define XCHAL_UNALIGNED_STORE_HW	0	/* unaligned stores work in hw*/
+
+#define XCHAL_SW_VERSION		900001	/* sw version of this header */
+
+#define XCHAL_CORE_ID			"dc233c"	/* alphanum core name
+						   (CoreID) set in the Xtensa
+						   Processor Generator */
+
+#define XCHAL_CORE_DESCRIPTION		"dc233c"
+#define XCHAL_BUILD_UNIQUE_ID		0x00004B21	/* 22-bit sw build ID */
+
+/*
+ *  These definitions describe the hardware targeted by this software.
+ */
+#define XCHAL_HW_CONFIGID0		0xC56707FE	/* ConfigID hi 32 bits*/
+#define XCHAL_HW_CONFIGID1		0x14404B21	/* ConfigID lo 32 bits*/
+#define XCHAL_HW_VERSION_NAME		"LX4.0.1"	/* full version name */
+#define XCHAL_HW_VERSION_MAJOR		2400	/* major ver# of targeted hw */
+#define XCHAL_HW_VERSION_MINOR		1	/* minor ver# of targeted hw */
+#define XCHAL_HW_VERSION		240001	/* major*100+minor */
+#define XCHAL_HW_REL_LX4		1
+#define XCHAL_HW_REL_LX4_0		1
+#define XCHAL_HW_REL_LX4_0_1		1
+#define XCHAL_HW_CONFIGID_RELIABLE	1
+/*  If software targets a *range* of hardware versions, these are the bounds: */
+#define XCHAL_HW_MIN_VERSION_MAJOR	2400	/* major v of earliest tgt hw */
+#define XCHAL_HW_MIN_VERSION_MINOR	1	/* minor v of earliest tgt hw */
+#define XCHAL_HW_MIN_VERSION		240001	/* earliest targeted hw */
+#define XCHAL_HW_MAX_VERSION_MAJOR	2400	/* major v of latest tgt hw */
+#define XCHAL_HW_MAX_VERSION_MINOR	1	/* minor v of latest tgt hw */
+#define XCHAL_HW_MAX_VERSION		240001	/* latest targeted hw */
+
+
+/*----------------------------------------------------------------------
+				CACHE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_ICACHE_LINESIZE		32	/* I-cache line size in bytes */
+#define XCHAL_DCACHE_LINESIZE		32	/* D-cache line size in bytes */
+#define XCHAL_ICACHE_LINEWIDTH		5	/* log2(I line size in bytes) */
+#define XCHAL_DCACHE_LINEWIDTH		5	/* log2(D line size in bytes) */
+
+#define XCHAL_ICACHE_SIZE		16384	/* I-cache size in bytes or 0 */
+#define XCHAL_DCACHE_SIZE		16384	/* D-cache size in bytes or 0 */
+
+#define XCHAL_DCACHE_IS_WRITEBACK	1	/* writeback feature */
+#define XCHAL_DCACHE_IS_COHERENT	0	/* MP coherence feature */
+
+#define XCHAL_HAVE_PREFETCH		0	/* PREFCTL register */
+
+
+
+
+/****************************************************************************
+    Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code
+ ****************************************************************************/
+
+
+#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY
+
+/*----------------------------------------------------------------------
+				CACHE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_PIF			1	/* any outbound PIF present */
+
+/*  If present, cache size in bytes == (ways * 2^(linewidth + setwidth)).  */
+
+/*  Number of cache sets in log2(lines per way):  */
+#define XCHAL_ICACHE_SETWIDTH		7
+#define XCHAL_DCACHE_SETWIDTH		7
+
+/*  Cache set associativity (number of ways):  */
+#define XCHAL_ICACHE_WAYS		4
+#define XCHAL_DCACHE_WAYS		4
+
+/*  Cache features:  */
+#define XCHAL_ICACHE_LINE_LOCKABLE	1
+#define XCHAL_DCACHE_LINE_LOCKABLE	1
+#define XCHAL_ICACHE_ECC_PARITY		0
+#define XCHAL_DCACHE_ECC_PARITY		0
+
+/*  Cache access size in bytes (affects operation of SICW instruction):  */
+#define XCHAL_ICACHE_ACCESS_SIZE	4
+#define XCHAL_DCACHE_ACCESS_SIZE	4
+
+/*  Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits):  */
+#define XCHAL_CA_BITS			4
+
+
+/*----------------------------------------------------------------------
+			INTERNAL I/D RAM/ROMs and XLMI
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_INSTROM		0	/* number of core instr. ROMs */
+#define XCHAL_NUM_INSTRAM		0	/* number of core instr. RAMs */
+#define XCHAL_NUM_DATAROM		0	/* number of core data ROMs */
+#define XCHAL_NUM_DATARAM		0	/* number of core data RAMs */
+#define XCHAL_NUM_URAM			0	/* number of core unified RAMs*/
+#define XCHAL_NUM_XLMI			0	/* number of core XLMI ports */
+
+#define XCHAL_HAVE_IMEM_LOADSTORE	1	/* can load/store to IROM/IRAM*/
+
+
+/*----------------------------------------------------------------------
+			INTERRUPTS and TIMERS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_INTERRUPTS		1	/* interrupt option */
+#define XCHAL_HAVE_HIGHPRI_INTERRUPTS	1	/* med/high-pri. interrupts */
+#define XCHAL_HAVE_NMI			1	/* non-maskable interrupt */
+#define XCHAL_HAVE_CCOUNT		1	/* CCOUNT reg. (timer option) */
+#define XCHAL_NUM_TIMERS		3	/* number of CCOMPAREn regs */
+#define XCHAL_NUM_INTERRUPTS		22	/* number of interrupts */
+#define XCHAL_NUM_INTERRUPTS_LOG2	5	/* ceil(log2(NUM_INTERRUPTS)) */
+#define XCHAL_NUM_EXTINTERRUPTS		17	/* num of external interrupts */
+#define XCHAL_NUM_INTLEVELS		6	/* number of interrupt levels
+						   (not including level zero) */
+#define XCHAL_EXCM_LEVEL		3	/* level masked by PS.EXCM */
+	/* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */
+
+/*  Masks of interrupts at each interrupt level:  */
+#define XCHAL_INTLEVEL1_MASK		0x001F80FF
+#define XCHAL_INTLEVEL2_MASK		0x00000100
+#define XCHAL_INTLEVEL3_MASK		0x00200E00
+#define XCHAL_INTLEVEL4_MASK		0x00001000
+#define XCHAL_INTLEVEL5_MASK		0x00002000
+#define XCHAL_INTLEVEL6_MASK		0x00000000
+#define XCHAL_INTLEVEL7_MASK		0x00004000
+
+/*  Masks of interrupts at each range 1..n of interrupt levels:  */
+#define XCHAL_INTLEVEL1_ANDBELOW_MASK	0x001F80FF
+#define XCHAL_INTLEVEL2_ANDBELOW_MASK	0x001F81FF
+#define XCHAL_INTLEVEL3_ANDBELOW_MASK	0x003F8FFF
+#define XCHAL_INTLEVEL4_ANDBELOW_MASK	0x003F9FFF
+#define XCHAL_INTLEVEL5_ANDBELOW_MASK	0x003FBFFF
+#define XCHAL_INTLEVEL6_ANDBELOW_MASK	0x003FBFFF
+#define XCHAL_INTLEVEL7_ANDBELOW_MASK	0x003FFFFF
+
+/*  Level of each interrupt:  */
+#define XCHAL_INT0_LEVEL		1
+#define XCHAL_INT1_LEVEL		1
+#define XCHAL_INT2_LEVEL		1
+#define XCHAL_INT3_LEVEL		1
+#define XCHAL_INT4_LEVEL		1
+#define XCHAL_INT5_LEVEL		1
+#define XCHAL_INT6_LEVEL		1
+#define XCHAL_INT7_LEVEL		1
+#define XCHAL_INT8_LEVEL		2
+#define XCHAL_INT9_LEVEL		3
+#define XCHAL_INT10_LEVEL		3
+#define XCHAL_INT11_LEVEL		3
+#define XCHAL_INT12_LEVEL		4
+#define XCHAL_INT13_LEVEL		5
+#define XCHAL_INT14_LEVEL		7
+#define XCHAL_INT15_LEVEL		1
+#define XCHAL_INT16_LEVEL		1
+#define XCHAL_INT17_LEVEL		1
+#define XCHAL_INT18_LEVEL		1
+#define XCHAL_INT19_LEVEL		1
+#define XCHAL_INT20_LEVEL		1
+#define XCHAL_INT21_LEVEL		3
+#define XCHAL_DEBUGLEVEL		6	/* debug interrupt level */
+#define XCHAL_HAVE_DEBUG_EXTERN_INT	1	/* OCD external db interrupt */
+#define XCHAL_NMILEVEL			7	/* NMI "level" (for use with
+						   EXCSAVE/EPS/EPC_n, RFI n) */
+
+/*  Type of each interrupt:  */
+#define XCHAL_INT0_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT1_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT2_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT3_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT4_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT5_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT6_TYPE 	XTHAL_INTTYPE_TIMER
+#define XCHAL_INT7_TYPE 	XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT8_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT9_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT10_TYPE 	XTHAL_INTTYPE_TIMER
+#define XCHAL_INT11_TYPE 	XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT12_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT13_TYPE 	XTHAL_INTTYPE_TIMER
+#define XCHAL_INT14_TYPE 	XTHAL_INTTYPE_NMI
+#define XCHAL_INT15_TYPE 	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT16_TYPE 	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT17_TYPE 	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT18_TYPE 	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT19_TYPE 	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT20_TYPE 	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT21_TYPE 	XTHAL_INTTYPE_EXTERN_EDGE
+
+/*  Masks of interrupts for each type of interrupt:  */
+#define XCHAL_INTTYPE_MASK_UNCONFIGURED	0xFFC00000
+#define XCHAL_INTTYPE_MASK_SOFTWARE	0x00000880
+#define XCHAL_INTTYPE_MASK_EXTERN_EDGE	0x003F8000
+#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL	0x0000133F
+#define XCHAL_INTTYPE_MASK_TIMER	0x00002440
+#define XCHAL_INTTYPE_MASK_NMI		0x00004000
+#define XCHAL_INTTYPE_MASK_WRITE_ERROR	0x00000000
+
+/*  Interrupt numbers assigned to specific interrupt sources:  */
+#define XCHAL_TIMER0_INTERRUPT		6	/* CCOMPARE0 */
+#define XCHAL_TIMER1_INTERRUPT		10	/* CCOMPARE1 */
+#define XCHAL_TIMER2_INTERRUPT		13	/* CCOMPARE2 */
+#define XCHAL_TIMER3_INTERRUPT		XTHAL_TIMER_UNCONFIGURED
+#define XCHAL_NMI_INTERRUPT		14	/* non-maskable interrupt */
+
+/*  Interrupt numbers for levels at which only one interrupt is configured:  */
+#define XCHAL_INTLEVEL2_NUM		8
+#define XCHAL_INTLEVEL4_NUM		12
+#define XCHAL_INTLEVEL5_NUM		13
+#define XCHAL_INTLEVEL7_NUM		14
+/*  (There are many interrupts each at level(s) 1, 3.)  */
+
+
+/*
+ *  External interrupt vectors/levels.
+ *  These macros describe how Xtensa processor interrupt numbers
+ *  (as numbered internally, eg. in INTERRUPT and INTENABLE registers)
+ *  map to external BInterrupt<n> pins, for those interrupts
+ *  configured as external (level-triggered, edge-triggered, or NMI).
+ *  See the Xtensa processor databook for more details.
+ */
+
+/*  Core interrupt numbers mapped to each EXTERNAL interrupt number:  */
+#define XCHAL_EXTINT0_NUM		0	/* (intlevel 1) */
+#define XCHAL_EXTINT1_NUM		1	/* (intlevel 1) */
+#define XCHAL_EXTINT2_NUM		2	/* (intlevel 1) */
+#define XCHAL_EXTINT3_NUM		3	/* (intlevel 1) */
+#define XCHAL_EXTINT4_NUM		4	/* (intlevel 1) */
+#define XCHAL_EXTINT5_NUM		5	/* (intlevel 1) */
+#define XCHAL_EXTINT6_NUM		8	/* (intlevel 2) */
+#define XCHAL_EXTINT7_NUM		9	/* (intlevel 3) */
+#define XCHAL_EXTINT8_NUM		12	/* (intlevel 4) */
+#define XCHAL_EXTINT9_NUM		14	/* (intlevel 7) */
+#define XCHAL_EXTINT10_NUM		15	/* (intlevel 1) */
+#define XCHAL_EXTINT11_NUM		16	/* (intlevel 1) */
+#define XCHAL_EXTINT12_NUM		17	/* (intlevel 1) */
+#define XCHAL_EXTINT13_NUM		18	/* (intlevel 1) */
+#define XCHAL_EXTINT14_NUM		19	/* (intlevel 1) */
+#define XCHAL_EXTINT15_NUM		20	/* (intlevel 1) */
+#define XCHAL_EXTINT16_NUM		21	/* (intlevel 3) */
+
+
+/*----------------------------------------------------------------------
+			EXCEPTIONS and VECTORS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_XEA_VERSION		2	/* Xtensa Exception Architecture
+						   number: 1 == XEA1 (old)
+							   2 == XEA2 (new)
+							   0 == XEAX (extern) or TX */
+#define XCHAL_HAVE_XEA1			0	/* Exception Architecture 1 */
+#define XCHAL_HAVE_XEA2			1	/* Exception Architecture 2 */
+#define XCHAL_HAVE_XEAX			0	/* External Exception Arch. */
+#define XCHAL_HAVE_EXCEPTIONS		1	/* exception option */
+#define XCHAL_HAVE_HALT			0	/* halt architecture option */
+#define XCHAL_HAVE_BOOTLOADER		0	/* boot loader (for TX) */
+#define XCHAL_HAVE_MEM_ECC_PARITY	0	/* local memory ECC/parity */
+#define XCHAL_HAVE_VECTOR_SELECT	1	/* relocatable vectors */
+#define XCHAL_HAVE_VECBASE		1	/* relocatable vectors */
+#define XCHAL_VECBASE_RESET_VADDR	0x00002000  /* VECBASE reset value */
+#define XCHAL_VECBASE_RESET_PADDR	0x00002000
+#define XCHAL_RESET_VECBASE_OVERLAP	0
+
+#define XCHAL_RESET_VECTOR0_VADDR	0xFE000000
+#define XCHAL_RESET_VECTOR0_PADDR	0xFE000000
+#define XCHAL_RESET_VECTOR1_VADDR	0x00001000
+#define XCHAL_RESET_VECTOR1_PADDR	0x00001000
+#define XCHAL_RESET_VECTOR_VADDR	0xFE000000
+#define XCHAL_RESET_VECTOR_PADDR	0xFE000000
+#define XCHAL_USER_VECOFS		0x00000340
+#define XCHAL_USER_VECTOR_VADDR		0x00002340
+#define XCHAL_USER_VECTOR_PADDR		0x00002340
+#define XCHAL_KERNEL_VECOFS		0x00000300
+#define XCHAL_KERNEL_VECTOR_VADDR	0x00002300
+#define XCHAL_KERNEL_VECTOR_PADDR	0x00002300
+#define XCHAL_DOUBLEEXC_VECOFS		0x000003C0
+#define XCHAL_DOUBLEEXC_VECTOR_VADDR	0x000023C0
+#define XCHAL_DOUBLEEXC_VECTOR_PADDR	0x000023C0
+#define XCHAL_WINDOW_OF4_VECOFS		0x00000000
+#define XCHAL_WINDOW_UF4_VECOFS		0x00000040
+#define XCHAL_WINDOW_OF8_VECOFS		0x00000080
+#define XCHAL_WINDOW_UF8_VECOFS		0x000000C0
+#define XCHAL_WINDOW_OF12_VECOFS	0x00000100
+#define XCHAL_WINDOW_UF12_VECOFS	0x00000140
+#define XCHAL_WINDOW_VECTORS_VADDR	0x00002000
+#define XCHAL_WINDOW_VECTORS_PADDR	0x00002000
+#define XCHAL_INTLEVEL2_VECOFS		0x00000180
+#define XCHAL_INTLEVEL2_VECTOR_VADDR	0x00002180
+#define XCHAL_INTLEVEL2_VECTOR_PADDR	0x00002180
+#define XCHAL_INTLEVEL3_VECOFS		0x000001C0
+#define XCHAL_INTLEVEL3_VECTOR_VADDR	0x000021C0
+#define XCHAL_INTLEVEL3_VECTOR_PADDR	0x000021C0
+#define XCHAL_INTLEVEL4_VECOFS		0x00000200
+#define XCHAL_INTLEVEL4_VECTOR_VADDR	0x00002200
+#define XCHAL_INTLEVEL4_VECTOR_PADDR	0x00002200
+#define XCHAL_INTLEVEL5_VECOFS		0x00000240
+#define XCHAL_INTLEVEL5_VECTOR_VADDR	0x00002240
+#define XCHAL_INTLEVEL5_VECTOR_PADDR	0x00002240
+#define XCHAL_INTLEVEL6_VECOFS		0x00000280
+#define XCHAL_INTLEVEL6_VECTOR_VADDR	0x00002280
+#define XCHAL_INTLEVEL6_VECTOR_PADDR	0x00002280
+#define XCHAL_DEBUG_VECOFS		XCHAL_INTLEVEL6_VECOFS
+#define XCHAL_DEBUG_VECTOR_VADDR	XCHAL_INTLEVEL6_VECTOR_VADDR
+#define XCHAL_DEBUG_VECTOR_PADDR	XCHAL_INTLEVEL6_VECTOR_PADDR
+#define XCHAL_NMI_VECOFS		0x000002C0
+#define XCHAL_NMI_VECTOR_VADDR		0x000022C0
+#define XCHAL_NMI_VECTOR_PADDR		0x000022C0
+#define XCHAL_INTLEVEL7_VECOFS		XCHAL_NMI_VECOFS
+#define XCHAL_INTLEVEL7_VECTOR_VADDR	XCHAL_NMI_VECTOR_VADDR
+#define XCHAL_INTLEVEL7_VECTOR_PADDR	XCHAL_NMI_VECTOR_PADDR
+
+
+/*----------------------------------------------------------------------
+				DEBUG
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_OCD			1	/* OnChipDebug option */
+#define XCHAL_NUM_IBREAK		2	/* number of IBREAKn regs */
+#define XCHAL_NUM_DBREAK		2	/* number of DBREAKn regs */
+#define XCHAL_HAVE_OCD_DIR_ARRAY	1	/* faster OCD option */
+
+
+/*----------------------------------------------------------------------
+				MMU
+  ----------------------------------------------------------------------*/
+
+/*  See core-matmap.h header file for more details.  */
+
+#define XCHAL_HAVE_TLBS			1	/* inverse of HAVE_CACHEATTR */
+#define XCHAL_HAVE_SPANNING_WAY		1	/* one way maps I+D 4GB vaddr */
+#define XCHAL_SPANNING_WAY		6	/* TLB spanning way number */
+#define XCHAL_HAVE_IDENTITY_MAP		0	/* vaddr == paddr always */
+#define XCHAL_HAVE_CACHEATTR		0	/* CACHEATTR register present */
+#define XCHAL_HAVE_MIMIC_CACHEATTR	0	/* region protection */
+#define XCHAL_HAVE_XLT_CACHEATTR	0	/* region prot. w/translation */
+#define XCHAL_HAVE_PTP_MMU		1	/* full MMU (with page table
+						   [autorefill] and protection)
+						   usable for an MMU-based OS */
+/*  If none of the above last 4 are set, it's a custom TLB configuration.  */
+#define XCHAL_ITLB_ARF_ENTRIES_LOG2	2	/* log2(autorefill way size) */
+#define XCHAL_DTLB_ARF_ENTRIES_LOG2	2	/* log2(autorefill way size) */
+
+#define XCHAL_MMU_ASID_BITS		8	/* number of bits in ASIDs */
+#define XCHAL_MMU_RINGS			4	/* number of rings (1..4) */
+#define XCHAL_MMU_RING_BITS		2	/* num of bits in RING field */
+
+#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */
+
+
+#endif /* _XTENSA_CORE_CONFIGURATION_H */
+
diff --git a/arch/xtensa/include/asm/arch-dc233c/tie-asm.h b/arch/xtensa/include/asm/arch-dc233c/tie-asm.h
new file mode 100644
index 0000000..38217ec
--- /dev/null
+++ b/arch/xtensa/include/asm/arch-dc233c/tie-asm.h
@@ -0,0 +1,173 @@
+/*
+ * This header file contains assembly-language definitions (assembly
+ * macros, etc.) for this specific Xtensa processor's TIE extensions
+ * and options.  It is customized to this Xtensa processor configuration.
+ * This file is autogenerated, please do not edit.
+ *
+ * Copyright (C) 1999-2010 Tensilica Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_CORE_TIE_ASM_H
+#define _XTENSA_CORE_TIE_ASM_H
+
+/*  Selection parameter values for save-area save/restore macros:  */
+/*  Option vs. TIE:  */
+#define XTHAL_SAS_TIE	0x0001	/* custom extension or coprocessor */
+#define XTHAL_SAS_OPT	0x0002	/* optional (and not a coprocessor) */
+#define XTHAL_SAS_ANYOT	0x0003	/* both of the above */
+/*  Whether used automatically by compiler:  */
+#define XTHAL_SAS_NOCC	0x0004	/* not used by compiler w/o special opts/code */
+#define XTHAL_SAS_CC	0x0008	/* used by compiler without special opts/code */
+#define XTHAL_SAS_ANYCC	0x000C	/* both of the above */
+/*  ABI handling across function calls:  */
+#define XTHAL_SAS_CALR	0x0010	/* caller-saved */
+#define XTHAL_SAS_CALE	0x0020	/* callee-saved */
+#define XTHAL_SAS_GLOB	0x0040	/* global across function calls (in thread) */
+#define XTHAL_SAS_ANYABI 0x0070	/* all of the above three */
+/*  Misc  */
+#define XTHAL_SAS_ALL	0xFFFF	/* include all default NCP contents */
+#define XTHAL_SAS3(optie,ccuse,abi)	( ((optie) & XTHAL_SAS_ANYOT)  \
+					| ((ccuse) & XTHAL_SAS_ANYCC)  \
+					| ((abi)   & XTHAL_SAS_ANYABI) )
+
+
+
+    /*
+     *  Macro to save all non-coprocessor (extra) custom TIE and optional state
+     *  (not including zero-overhead loop registers).
+     *  Required parameters:
+     *      ptr		Save area pointer address register (clobbered)
+     *			(register must contain a 4 byte aligned address).
+     *      at1..at4	Four temporary address registers (first XCHAL_NCP_NUM_ATMPS
+     *			registers are clobbered, the remaining are unused).
+     *  Optional parameters:
+     *      continue	If macro invoked as part of a larger store sequence, set to 1
+     *			if this is not the first in the sequence.  Defaults to 0.
+     *      ofs		Offset from start of larger sequence (from value of first ptr
+     *			in sequence) at which to store.  Defaults to next available space
+     *			(or 0 if <continue> is 0).
+     *      select	Select what category(ies) of registers to store, as a bitmask
+     *			(see XTHAL_SAS_xxx constants).  Defaults to all registers.
+     *      alloc	Select what category(ies) of registers to allocate; if any
+     *			category is selected here that is not in <select>, space for
+     *			the corresponding registers is skipped without doing any store.
+     */
+    .macro xchal_ncp_store  ptr at1 at2 at3 at4  continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0
+	xchal_sa_start	\continue, \ofs
+	// Optional global register used by default by the compiler:
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select)
+	xchal_sa_align	\ptr, 0, 1020, 4, 4
+	rur.THREADPTR	\at1		// threadptr option
+	s32i	\at1, \ptr, .Lxchal_ofs_+0
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 4
+	.elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0
+	xchal_sa_align	\ptr, 0, 1020, 4, 4
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 4
+	.endif
+	// Optional caller-saved registers used by default by the compiler:
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\select)
+	xchal_sa_align	\ptr, 0, 1016, 4, 4
+	rsr	\at1, ACCLO			// MAC16 option
+	s32i	\at1, \ptr, .Lxchal_ofs_+0
+	rsr	\at1, ACCHI			// MAC16 option
+	s32i	\at1, \ptr, .Lxchal_ofs_+4
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 8
+	.elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\alloc)) == 0
+	xchal_sa_align	\ptr, 0, 1016, 4, 4
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 8
+	.endif
+	// Optional caller-saved registers not used by default by the compiler:
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select)
+	xchal_sa_align	\ptr, 0, 1004, 4, 4
+	rsr	\at1, M0			// MAC16 option
+	s32i	\at1, \ptr, .Lxchal_ofs_+0
+	rsr	\at1, M1			// MAC16 option
+	s32i	\at1, \ptr, .Lxchal_ofs_+4
+	rsr	\at1, M2			// MAC16 option
+	s32i	\at1, \ptr, .Lxchal_ofs_+8
+	rsr	\at1, M3			// MAC16 option
+	s32i	\at1, \ptr, .Lxchal_ofs_+12
+	rsr	\at1, SCOMPARE1			// conditional store option
+	s32i	\at1, \ptr, .Lxchal_ofs_+16
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 20
+	.elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0
+	xchal_sa_align	\ptr, 0, 1004, 4, 4
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 20
+	.endif
+    .endm	// xchal_ncp_store
+
+    /*
+     *  Macro to restore all non-coprocessor (extra) custom TIE and optional state
+     *  (not including zero-overhead loop registers).
+     *  Required parameters:
+     *      ptr		Save area pointer address register (clobbered)
+     *			(register must contain a 4 byte aligned address).
+     *      at1..at4	Four temporary address registers (first XCHAL_NCP_NUM_ATMPS
+     *			registers are clobbered, the remaining are unused).
+     *  Optional parameters:
+     *      continue	If macro invoked as part of a larger load sequence, set to 1
+     *			if this is not the first in the sequence.  Defaults to 0.
+     *      ofs		Offset from start of larger sequence (from value of first ptr
+     *			in sequence) at which to load.  Defaults to next available space
+     *			(or 0 if <continue> is 0).
+     *      select	Select what category(ies) of registers to load, as a bitmask
+     *			(see XTHAL_SAS_xxx constants).  Defaults to all registers.
+     *      alloc	Select what category(ies) of registers to allocate; if any
+     *			category is selected here that is not in <select>, space for
+     *			the corresponding registers is skipped without doing any load.
+     */
+    .macro xchal_ncp_load  ptr at1 at2 at3 at4  continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0
+	xchal_sa_start	\continue, \ofs
+	// Optional global register used by default by the compiler:
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select)
+	xchal_sa_align	\ptr, 0, 1020, 4, 4
+	l32i	\at1, \ptr, .Lxchal_ofs_+0
+	wur.THREADPTR	\at1		// threadptr option
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 4
+	.elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0
+	xchal_sa_align	\ptr, 0, 1020, 4, 4
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 4
+	.endif
+	// Optional caller-saved registers used by default by the compiler:
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\select)
+	xchal_sa_align	\ptr, 0, 1016, 4, 4
+	l32i	\at1, \ptr, .Lxchal_ofs_+0
+	wsr	\at1, ACCLO			// MAC16 option
+	l32i	\at1, \ptr, .Lxchal_ofs_+4
+	wsr	\at1, ACCHI			// MAC16 option
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 8
+	.elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\alloc)) == 0
+	xchal_sa_align	\ptr, 0, 1016, 4, 4
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 8
+	.endif
+	// Optional caller-saved registers not used by default by the compiler:
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select)
+	xchal_sa_align	\ptr, 0, 1004, 4, 4
+	l32i	\at1, \ptr, .Lxchal_ofs_+0
+	wsr	\at1, M0			// MAC16 option
+	l32i	\at1, \ptr, .Lxchal_ofs_+4
+	wsr	\at1, M1			// MAC16 option
+	l32i	\at1, \ptr, .Lxchal_ofs_+8
+	wsr	\at1, M2			// MAC16 option
+	l32i	\at1, \ptr, .Lxchal_ofs_+12
+	wsr	\at1, M3			// MAC16 option
+	l32i	\at1, \ptr, .Lxchal_ofs_+16
+	wsr	\at1, SCOMPARE1			// conditional store option
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 20
+	.elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0
+	xchal_sa_align	\ptr, 0, 1004, 4, 4
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 20
+	.endif
+    .endm	// xchal_ncp_load
+
+
+#define XCHAL_NCP_NUM_ATMPS	1
+
+
+
+#define XCHAL_SA_NUM_ATMPS	1
+
+#endif /*_XTENSA_CORE_TIE_ASM_H*/
+
diff --git a/arch/xtensa/include/asm/arch-dc233c/tie.h b/arch/xtensa/include/asm/arch-dc233c/tie.h
new file mode 100644
index 0000000..32a714f
--- /dev/null
+++ b/arch/xtensa/include/asm/arch-dc233c/tie.h
@@ -0,0 +1,130 @@
+/*
+ * This header file describes this specific Xtensa processor's TIE extensions
+ * that extend basic Xtensa core functionality.  It is customized to this
+ * Xtensa processor configuration.
+ * This file is autogenerated, please do not edit.
+ *
+ * Copyright (C) 1999-2010 Tensilica Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_CORE_TIE_H
+#define _XTENSA_CORE_TIE_H
+
+#define XCHAL_CP_NUM			1	/* number of coprocessors */
+#define XCHAL_CP_MAX			8	/* max CP ID + 1 (0 if none) */
+#define XCHAL_CP_MASK			0x80	/* bitmask of all CPs by ID */
+#define XCHAL_CP_PORT_MASK		0x80	/* bitmask of only port CPs */
+
+/*  Basic parameters of each coprocessor:  */
+#define XCHAL_CP7_NAME			"XTIOP"
+#define XCHAL_CP7_IDENT			XTIOP
+#define XCHAL_CP7_SA_SIZE		0	/* size of state save area */
+#define XCHAL_CP7_SA_ALIGN		1	/* min alignment of save area */
+#define XCHAL_CP_ID_XTIOP		7	/* coprocessor ID (0..7) */
+
+/*  Filler info for unassigned coprocessors, to simplify arrays etc:  */
+#define XCHAL_CP0_SA_SIZE		0
+#define XCHAL_CP0_SA_ALIGN		1
+#define XCHAL_CP1_SA_SIZE		0
+#define XCHAL_CP1_SA_ALIGN		1
+#define XCHAL_CP2_SA_SIZE		0
+#define XCHAL_CP2_SA_ALIGN		1
+#define XCHAL_CP3_SA_SIZE		0
+#define XCHAL_CP3_SA_ALIGN		1
+#define XCHAL_CP4_SA_SIZE		0
+#define XCHAL_CP4_SA_ALIGN		1
+#define XCHAL_CP5_SA_SIZE		0
+#define XCHAL_CP5_SA_ALIGN		1
+#define XCHAL_CP6_SA_SIZE		0
+#define XCHAL_CP6_SA_ALIGN		1
+
+/*  Save area for non-coprocessor optional and custom (TIE) state:  */
+#define XCHAL_NCP_SA_SIZE		32
+#define XCHAL_NCP_SA_ALIGN		4
+
+/*  Total save area for optional and custom state (NCP + CPn):  */
+#define XCHAL_TOTAL_SA_SIZE		32	/* with 16-byte align padding */
+#define XCHAL_TOTAL_SA_ALIGN		4	/* actual minimum alignment */
+
+/*
+ * Detailed contents of save areas.
+ * NOTE:  caller must define the XCHAL_SA_REG macro (not defined here)
+ * before expanding the XCHAL_xxx_SA_LIST() macros.
+ *
+ * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize,
+ *		dbnum,base,regnum,bitsz,gapsz,reset,x...)
+ *
+ *	s = passed from XCHAL_*_LIST(s), eg. to select how to expand
+ *	ccused = set if used by compiler without special options or code
+ *	abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global)
+ *	kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg)
+ *	opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg)
+ *	name = lowercase reg name (no quotes)
+ *	galign = group byte alignment (power of 2) (galign >= align)
+ *	align = register byte alignment (power of 2)
+ *	asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz)
+ *	  (not including any pad bytes required to galign this or next reg)
+ *	dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>)
+ *	base = reg shortname w/o index (or sr=special, ur=TIE user reg)
+ *	regnum = reg index in regfile, or special/TIE-user reg number
+ *	bitsz = number of significant bits (regfile width, or ur/sr mask bits)
+ *	gapsz = intervening bits, if bitsz bits not stored contiguously
+ *	(padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize)
+ *	reset = register reset value (or 0 if undefined at reset)
+ *	x = reserved for future use (0 until then)
+ *
+ *  To filter out certain registers, e.g. to expand only the non-global
+ *  registers used by the compiler, you can do something like this:
+ *
+ *  #define XCHAL_SA_REG(s,ccused,p...)	SELCC##ccused(p)
+ *  #define SELCC0(p...)
+ *  #define SELCC1(abikind,p...)	SELAK##abikind(p)
+ *  #define SELAK0(p...)		REG(p)
+ *  #define SELAK1(p...)		REG(p)
+ *  #define SELAK2(p...)
+ *  #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \
+ *		...what you want to expand...
+ */
+
+#define XCHAL_NCP_SA_NUM	8
+#define XCHAL_NCP_SA_LIST(s)	\
+ XCHAL_SA_REG(s,1,2,1,1,      threadptr, 4, 4, 4,0x03E7,  ur,231, 32,0,0,0) \
+ XCHAL_SA_REG(s,1,0,0,1,          acclo, 4, 4, 4,0x0210,  sr,16 , 32,0,0,0) \
+ XCHAL_SA_REG(s,1,0,0,1,          acchi, 4, 4, 4,0x0211,  sr,17 ,  8,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,             m0, 4, 4, 4,0x0220,  sr,32 , 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,             m1, 4, 4, 4,0x0221,  sr,33 , 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,             m2, 4, 4, 4,0x0222,  sr,34 , 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,             m3, 4, 4, 4,0x0223,  sr,35 , 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,      scompare1, 4, 4, 4,0x020C,  sr,12 , 32,0,0,0)
+
+#define XCHAL_CP0_SA_NUM	0
+#define XCHAL_CP0_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP1_SA_NUM	0
+#define XCHAL_CP1_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP2_SA_NUM	0
+#define XCHAL_CP2_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP3_SA_NUM	0
+#define XCHAL_CP3_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP4_SA_NUM	0
+#define XCHAL_CP4_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP5_SA_NUM	0
+#define XCHAL_CP5_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP6_SA_NUM	0
+#define XCHAL_CP6_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP7_SA_NUM	0
+#define XCHAL_CP7_SA_LIST(s)	/* empty */
+
+/* Byte length of instruction from its first nibble (op0 field), per FLIX.  */
+#define XCHAL_OP0_FORMAT_LENGTHS	3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3
+
+#endif /*_XTENSA_CORE_TIE_H*/
+
diff --git a/arch/xtensa/include/asm/arch-de212/core.h b/arch/xtensa/include/asm/arch-de212/core.h
new file mode 100644
index 0000000..be13501
--- /dev/null
+++ b/arch/xtensa/include/asm/arch-de212/core.h
@@ -0,0 +1,573 @@
+/*
+ * Xtensa processor core configuration information.
+ * This file is autogenerated, please do not edit.
+ *
+ * Copyright (C) 1999-2015 Tensilica Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_CORE_CONFIGURATION_H
+#define _XTENSA_CORE_CONFIGURATION_H
+
+
+/****************************************************************************
+	    Parameters Useful for Any Code, USER or PRIVILEGED
+ ****************************************************************************/
+
+/*
+ *  Note:  Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is
+ *  configured, and a value of 0 otherwise.  These macros are always defined.
+ */
+
+
+/*----------------------------------------------------------------------
+				ISA
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_BE			0	/* big-endian byte ordering */
+#define XCHAL_HAVE_WINDOWED		1	/* windowed registers option */
+#define XCHAL_NUM_AREGS			32	/* num of physical addr regs */
+#define XCHAL_NUM_AREGS_LOG2		5	/* log2(XCHAL_NUM_AREGS) */
+#define XCHAL_MAX_INSTRUCTION_SIZE	3	/* max instr bytes (3..8) */
+#define XCHAL_HAVE_DEBUG		1	/* debug option */
+#define XCHAL_HAVE_DENSITY		1	/* 16-bit instructions */
+#define XCHAL_HAVE_LOOPS		1	/* zero-overhead loops */
+#define XCHAL_LOOP_BUFFER_SIZE		0	/* zero-ov. loop instr buffer size */
+#define XCHAL_HAVE_NSA			1	/* NSA/NSAU instructions */
+#define XCHAL_HAVE_MINMAX		1	/* MIN/MAX instructions */
+#define XCHAL_HAVE_SEXT			1	/* SEXT instruction */
+#define XCHAL_HAVE_DEPBITS		0	/* DEPBITS instruction */
+#define XCHAL_HAVE_CLAMPS		1	/* CLAMPS instruction */
+#define XCHAL_HAVE_MUL16		1	/* MUL16S/MUL16U instructions */
+#define XCHAL_HAVE_MUL32		1	/* MULL instruction */
+#define XCHAL_HAVE_MUL32_HIGH		0	/* MULUH/MULSH instructions */
+#define XCHAL_HAVE_DIV32		1	/* QUOS/QUOU/REMS/REMU instructions */
+#define XCHAL_HAVE_L32R			1	/* L32R instruction */
+#define XCHAL_HAVE_ABSOLUTE_LITERALS	0	/* non-PC-rel (extended) L32R */
+#define XCHAL_HAVE_CONST16		0	/* CONST16 instruction */
+#define XCHAL_HAVE_ADDX			1	/* ADDX#/SUBX# instructions */
+#define XCHAL_HAVE_WIDE_BRANCHES	0	/* B*.W18 or B*.W15 instr's */
+#define XCHAL_HAVE_PREDICTED_BRANCHES	0	/* B[EQ/EQZ/NE/NEZ]T instr's */
+#define XCHAL_HAVE_CALL4AND12		1	/* (obsolete option) */
+#define XCHAL_HAVE_ABS			1	/* ABS instruction */
+/*#define XCHAL_HAVE_POPC		0*/	/* POPC instruction */
+/*#define XCHAL_HAVE_CRC		0*/	/* CRC instruction */
+#define XCHAL_HAVE_RELEASE_SYNC		1	/* L32AI/S32RI instructions */
+#define XCHAL_HAVE_S32C1I		1	/* S32C1I instruction */
+#define XCHAL_HAVE_SPECULATION		0	/* speculation */
+#define XCHAL_HAVE_FULL_RESET		1	/* all regs/state reset */
+#define XCHAL_NUM_CONTEXTS		1	/* */
+#define XCHAL_NUM_MISC_REGS		2	/* num of scratch regs (0..4) */
+#define XCHAL_HAVE_TAP_MASTER		0	/* JTAG TAP control instr's */
+#define XCHAL_HAVE_PRID			1	/* processor ID register */
+#define XCHAL_HAVE_EXTERN_REGS		1	/* WER/RER instructions */
+#define XCHAL_HAVE_MX			0	/* MX core (Tensilica internal) */
+#define XCHAL_HAVE_MP_INTERRUPTS	0	/* interrupt distributor port */
+#define XCHAL_HAVE_MP_RUNSTALL		0	/* core RunStall control port */
+#define XCHAL_HAVE_PSO			0	/* Power Shut-Off */
+#define XCHAL_HAVE_PSO_CDM		0	/* core/debug/mem pwr domains */
+#define XCHAL_HAVE_PSO_FULL_RETENTION	0	/* all regs preserved on PSO */
+#define XCHAL_HAVE_THREADPTR		0	/* THREADPTR register */
+#define XCHAL_HAVE_BOOLEANS		0	/* boolean registers */
+#define XCHAL_HAVE_CP			0	/* CPENABLE reg (coprocessor) */
+#define XCHAL_CP_MAXCFG			0	/* max allowed cp id plus one */
+#define XCHAL_HAVE_MAC16		1	/* MAC16 package */
+
+#define XCHAL_HAVE_FUSION		 0	/* Fusion*/
+#define XCHAL_HAVE_FUSION_FP	 0	        /* Fusion FP option */
+#define XCHAL_HAVE_FUSION_LOW_POWER 0	/* Fusion Low Power option */
+#define XCHAL_HAVE_FUSION_AES	 0	        /* Fusion BLE/Wifi AES-128 CCM option */
+#define XCHAL_HAVE_FUSION_CONVENC	 0       /* Fusion Conv Encode option */
+#define XCHAL_HAVE_FUSION_LFSR_CRC	 0	/* Fusion LFSR-CRC option */
+#define XCHAL_HAVE_FUSION_BITOPS	 0	/* Fusion Bit Operations Support option */
+#define XCHAL_HAVE_FUSION_AVS	 0	/* Fusion AVS option */
+#define XCHAL_HAVE_FUSION_16BIT_BASEBAND	 0	/* Fusion 16-bit Baseband option */
+#define XCHAL_HAVE_HIFIPRO		0	/* HiFiPro Audio Engine pkg */
+#define XCHAL_HAVE_HIFI4		0	/* HiFi4 Audio Engine pkg */
+#define XCHAL_HAVE_HIFI4_VFPU		0	/* HiFi4 Audio Engine VFPU option */
+#define XCHAL_HAVE_HIFI3		0	/* HiFi3 Audio Engine pkg */
+#define XCHAL_HAVE_HIFI3_VFPU		0	/* HiFi3 Audio Engine VFPU option */
+#define XCHAL_HAVE_HIFI2		0	/* HiFi2 Audio Engine pkg */
+#define XCHAL_HAVE_HIFI2EP		0	/* HiFi2EP */
+#define XCHAL_HAVE_HIFI_MINI		0	
+
+
+#define XCHAL_HAVE_VECTORFPU2005	0	/* vector or user floating-point pkg */
+#define XCHAL_HAVE_USER_DPFPU         0       /* user DP floating-point pkg */
+#define XCHAL_HAVE_USER_SPFPU         0       /* user DP floating-point pkg */
+#define XCHAL_HAVE_FP                 0      /* single prec floating point */
+#define XCHAL_HAVE_FP_DIV             0  /* FP with DIV instructions */
+#define XCHAL_HAVE_FP_RECIP           0        /* FP with RECIP instructions */
+#define XCHAL_HAVE_FP_SQRT            0 /* FP with SQRT instructions */
+#define XCHAL_HAVE_FP_RSQRT           0        /* FP with RSQRT instructions */
+#define XCHAL_HAVE_DFP                        0     /* double precision FP pkg */
+#define XCHAL_HAVE_DFP_DIV            0 /* DFP with DIV instructions */
+#define XCHAL_HAVE_DFP_RECIP          0       /* DFP with RECIP instructions*/
+#define XCHAL_HAVE_DFP_SQRT           0        /* DFP with SQRT instructions */
+#define XCHAL_HAVE_DFP_RSQRT          0       /* DFP with RSQRT instructions*/
+#define XCHAL_HAVE_DFP_ACCEL		0	/* double precision FP acceleration pkg */
+#define XCHAL_HAVE_DFP_accel		XCHAL_HAVE_DFP_ACCEL				/* for backward compatibility */
+
+#define XCHAL_HAVE_DFPU_SINGLE_ONLY    0                 	/* DFPU Coprocessor, single precision only */
+#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE  0               	/* DFPU Coprocessor, single and double precision */
+#define XCHAL_HAVE_VECTRA1		0	/* Vectra I  pkg */
+#define XCHAL_HAVE_VECTRALX		0	/* Vectra LX pkg */
+#define XCHAL_HAVE_PDX4		        0	/* PDX4 */
+#define XCHAL_HAVE_CONNXD2		0	/* ConnX D2 pkg */
+#define XCHAL_HAVE_CONNXD2_DUALLSFLIX   0	/* ConnX D2 & Dual LoadStore Flix */
+#define XCHAL_HAVE_BBE16		0	/* ConnX BBE16 pkg */
+#define XCHAL_HAVE_BBE16_RSQRT		0	/* BBE16 & vector recip sqrt */
+#define XCHAL_HAVE_BBE16_VECDIV		0	/* BBE16 & vector divide */
+#define XCHAL_HAVE_BBE16_DESPREAD	0	/* BBE16 & despread */
+#define XCHAL_HAVE_BBENEP		0	/* ConnX BBENEP pkgs */
+#define XCHAL_HAVE_BSP3			0	/* ConnX BSP3 pkg */
+#define XCHAL_HAVE_BSP3_TRANSPOSE	0	/* BSP3 & transpose32x32 */
+#define XCHAL_HAVE_SSP16		0	/* ConnX SSP16 pkg */
+#define XCHAL_HAVE_SSP16_VITERBI	0	/* SSP16 & viterbi */
+#define XCHAL_HAVE_TURBO16		0	/* ConnX Turbo16 pkg */
+#define XCHAL_HAVE_BBP16		0	/* ConnX BBP16 pkg */
+#define XCHAL_HAVE_FLIX3		0	/* basic 3-way FLIX option */
+#define XCHAL_HAVE_GRIVPEP              0   /*  GRIVPEP is General Release of IVPEP */
+#define XCHAL_HAVE_GRIVPEP_HISTOGRAM    0   /* Histogram option on GRIVPEP */
+
+
+/*----------------------------------------------------------------------
+				MISC
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_LOADSTORE_UNITS	1	/* load/store units */
+#define XCHAL_NUM_WRITEBUFFER_ENTRIES	8	/* size of write buffer */
+#define XCHAL_INST_FETCH_WIDTH		4	/* instr-fetch width in bytes */
+#define XCHAL_DATA_WIDTH		4	/* data width in bytes */
+#define XCHAL_DATA_PIPE_DELAY		1	/* d-side pipeline delay
+						   (1 = 5-stage, 2 = 7-stage) */
+#define XCHAL_CLOCK_GATING_GLOBAL	0	/* global clock gating */
+#define XCHAL_CLOCK_GATING_FUNCUNIT	0	/* funct. unit clock gating */
+/*  In T1050, applies to selected core load and store instructions (see ISA): */
+#define XCHAL_UNALIGNED_LOAD_EXCEPTION	1	/* unaligned loads cause exc. */
+#define XCHAL_UNALIGNED_STORE_EXCEPTION	1	/* unaligned stores cause exc.*/
+#define XCHAL_UNALIGNED_LOAD_HW		0	/* unaligned loads work in hw */
+#define XCHAL_UNALIGNED_STORE_HW	0	/* unaligned stores work in hw*/
+
+#define XCHAL_SW_VERSION		1100002	/* sw version of this header */
+
+#define XCHAL_CORE_ID			"de212"	/* alphanum core name
+						   (CoreID) set in the Xtensa
+						   Processor Generator */
+
+#define XCHAL_BUILD_UNIQUE_ID		0x0005A985	/* 22-bit sw build ID */
+
+/*
+ *  These definitions describe the hardware targeted by this software.
+ */
+#define XCHAL_HW_CONFIGID0		0xC283DFFE	/* ConfigID hi 32 bits*/
+#define XCHAL_HW_CONFIGID1		0x1C85A985	/* ConfigID lo 32 bits*/
+#define XCHAL_HW_VERSION_NAME		"LX6.0.2"	/* full version name */
+#define XCHAL_HW_VERSION_MAJOR		2600	/* major ver# of targeted hw */
+#define XCHAL_HW_VERSION_MINOR		2	/* minor ver# of targeted hw */
+#define XCHAL_HW_VERSION		260002	/* major*100+minor */
+#define XCHAL_HW_REL_LX6		1
+#define XCHAL_HW_REL_LX6_0		1
+#define XCHAL_HW_REL_LX6_0_2		1
+#define XCHAL_HW_CONFIGID_RELIABLE	1
+/*  If software targets a *range* of hardware versions, these are the bounds: */
+#define XCHAL_HW_MIN_VERSION_MAJOR	2600	/* major v of earliest tgt hw */
+#define XCHAL_HW_MIN_VERSION_MINOR	2	/* minor v of earliest tgt hw */
+#define XCHAL_HW_MIN_VERSION		260002	/* earliest targeted hw */
+#define XCHAL_HW_MAX_VERSION_MAJOR	2600	/* major v of latest tgt hw */
+#define XCHAL_HW_MAX_VERSION_MINOR	2	/* minor v of latest tgt hw */
+#define XCHAL_HW_MAX_VERSION		260002	/* latest targeted hw */
+
+
+/*----------------------------------------------------------------------
+				CACHE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_ICACHE_LINESIZE		32	/* I-cache line size in bytes */
+#define XCHAL_DCACHE_LINESIZE		32	/* D-cache line size in bytes */
+#define XCHAL_ICACHE_LINEWIDTH		5	/* log2(I line size in bytes) */
+#define XCHAL_DCACHE_LINEWIDTH		5	/* log2(D line size in bytes) */
+
+#define XCHAL_ICACHE_SIZE		8192	/* I-cache size in bytes or 0 */
+#define XCHAL_DCACHE_SIZE		8192	/* D-cache size in bytes or 0 */
+
+#define XCHAL_DCACHE_IS_WRITEBACK	1	/* writeback feature */
+#define XCHAL_DCACHE_IS_COHERENT	0	/* MP coherence feature */
+
+#define XCHAL_HAVE_PREFETCH		0	/* PREFCTL register */
+#define XCHAL_HAVE_PREFETCH_L1		0	/* prefetch to L1 dcache */
+#define XCHAL_PREFETCH_CASTOUT_LINES	0	/* dcache pref. castout bufsz */
+#define XCHAL_PREFETCH_ENTRIES		0	/* cache prefetch entries */
+#define XCHAL_PREFETCH_BLOCK_ENTRIES	0	/* prefetch block streams */
+#define XCHAL_HAVE_CACHE_BLOCKOPS	0	/* block prefetch for caches */
+#define XCHAL_HAVE_ICACHE_TEST		1	/* Icache test instructions */
+#define XCHAL_HAVE_DCACHE_TEST		1	/* Dcache test instructions */
+#define XCHAL_HAVE_ICACHE_DYN_WAYS	0	/* Icache dynamic way support */
+#define XCHAL_HAVE_DCACHE_DYN_WAYS	0	/* Dcache dynamic way support */
+
+
+
+
+/****************************************************************************
+    Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code
+ ****************************************************************************/
+
+
+#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY
+
+/*----------------------------------------------------------------------
+				CACHE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_PIF			1	/* any outbound PIF present */
+
+/*  If present, cache size in bytes == (ways * 2^(linewidth + setwidth)).  */
+
+/*  Number of cache sets in log2(lines per way):  */
+#define XCHAL_ICACHE_SETWIDTH		7
+#define XCHAL_DCACHE_SETWIDTH		7
+
+/*  Cache set associativity (number of ways):  */
+#define XCHAL_ICACHE_WAYS		2
+#define XCHAL_DCACHE_WAYS		2
+
+/*  Cache features:  */
+#define XCHAL_ICACHE_LINE_LOCKABLE	1
+#define XCHAL_DCACHE_LINE_LOCKABLE	1
+#define XCHAL_ICACHE_ECC_PARITY		0
+#define XCHAL_DCACHE_ECC_PARITY		0
+
+/*  Cache access size in bytes (affects operation of SICW instruction):  */
+#define XCHAL_ICACHE_ACCESS_SIZE	4
+#define XCHAL_DCACHE_ACCESS_SIZE	4
+
+#define XCHAL_DCACHE_BANKS		1	/* number of banks */
+
+/*  Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits):  */
+#define XCHAL_CA_BITS			4
+
+/*  Whether MEMCTL register has anything useful  */
+#define XCHAL_USE_MEMCTL		(((XCHAL_LOOP_BUFFER_SIZE > 0)	||	\
+					   XCHAL_DCACHE_IS_COHERENT	||	\
+					   XCHAL_HAVE_ICACHE_DYN_WAYS	||	\
+					   XCHAL_HAVE_DCACHE_DYN_WAYS)	&&	\
+					   (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RE_2012_0))
+
+
+/*----------------------------------------------------------------------
+			INTERNAL I/D RAM/ROMs and XLMI
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_INSTROM		0	/* number of core instr. ROMs */
+#define XCHAL_NUM_INSTRAM		1	/* number of core instr. RAMs */
+#define XCHAL_NUM_DATAROM		0	/* number of core data ROMs */
+#define XCHAL_NUM_DATARAM		1	/* number of core data RAMs */
+#define XCHAL_NUM_URAM			0	/* number of core unified RAMs*/
+#define XCHAL_NUM_XLMI			1	/* number of core XLMI ports */
+
+/*  Instruction RAM 0:  */
+#define XCHAL_INSTRAM0_VADDR		0x40000000	/* virtual address */
+#define XCHAL_INSTRAM0_PADDR		0x40000000	/* physical address */
+#define XCHAL_INSTRAM0_SIZE		131072	/* size in bytes */
+#define XCHAL_INSTRAM0_ECC_PARITY	0	/* ECC/parity type, 0=none */
+
+/*  Data RAM 0:  */
+#define XCHAL_DATARAM0_VADDR		0x3FFE0000	/* virtual address */
+#define XCHAL_DATARAM0_PADDR		0x3FFE0000	/* physical address */
+#define XCHAL_DATARAM0_SIZE		131072	/* size in bytes */
+#define XCHAL_DATARAM0_ECC_PARITY	0	/* ECC/parity type, 0=none */
+#define XCHAL_DATARAM0_BANKS		1	/* number of banks */
+
+/*  XLMI Port 0:  */
+#define XCHAL_XLMI0_VADDR		0x3FFC0000	/* virtual address */
+#define XCHAL_XLMI0_PADDR		0x3FFC0000	/* physical address */
+#define XCHAL_XLMI0_SIZE		131072	/* size in bytes */
+#define XCHAL_XLMI0_ECC_PARITY	0	/* ECC/parity type, 0=none */
+
+#define XCHAL_HAVE_IMEM_LOADSTORE	1	/* can load/store to IROM/IRAM*/
+
+
+/*----------------------------------------------------------------------
+			INTERRUPTS and TIMERS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_INTERRUPTS		1	/* interrupt option */
+#define XCHAL_HAVE_HIGHPRI_INTERRUPTS	1	/* med/high-pri. interrupts */
+#define XCHAL_HAVE_NMI			1	/* non-maskable interrupt */
+#define XCHAL_HAVE_CCOUNT		1	/* CCOUNT reg. (timer option) */
+#define XCHAL_NUM_TIMERS		3	/* number of CCOMPAREn regs */
+#define XCHAL_NUM_INTERRUPTS		22	/* number of interrupts */
+#define XCHAL_NUM_INTERRUPTS_LOG2	5	/* ceil(log2(NUM_INTERRUPTS)) */
+#define XCHAL_NUM_EXTINTERRUPTS		17	/* num of external interrupts */
+#define XCHAL_NUM_INTLEVELS		6	/* number of interrupt levels
+						   (not including level zero) */
+#define XCHAL_EXCM_LEVEL		3	/* level masked by PS.EXCM */
+	/* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */
+
+/*  Masks of interrupts at each interrupt level:  */
+#define XCHAL_INTLEVEL1_MASK		0x001F80FF
+#define XCHAL_INTLEVEL2_MASK		0x00000100
+#define XCHAL_INTLEVEL3_MASK		0x00200E00
+#define XCHAL_INTLEVEL4_MASK		0x00001000
+#define XCHAL_INTLEVEL5_MASK		0x00002000
+#define XCHAL_INTLEVEL6_MASK		0x00000000
+#define XCHAL_INTLEVEL7_MASK		0x00004000
+
+/*  Masks of interrupts at each range 1..n of interrupt levels:  */
+#define XCHAL_INTLEVEL1_ANDBELOW_MASK	0x001F80FF
+#define XCHAL_INTLEVEL2_ANDBELOW_MASK	0x001F81FF
+#define XCHAL_INTLEVEL3_ANDBELOW_MASK	0x003F8FFF
+#define XCHAL_INTLEVEL4_ANDBELOW_MASK	0x003F9FFF
+#define XCHAL_INTLEVEL5_ANDBELOW_MASK	0x003FBFFF
+#define XCHAL_INTLEVEL6_ANDBELOW_MASK	0x003FBFFF
+#define XCHAL_INTLEVEL7_ANDBELOW_MASK	0x003FFFFF
+
+/*  Level of each interrupt:  */
+#define XCHAL_INT0_LEVEL		1
+#define XCHAL_INT1_LEVEL		1
+#define XCHAL_INT2_LEVEL		1
+#define XCHAL_INT3_LEVEL		1
+#define XCHAL_INT4_LEVEL		1
+#define XCHAL_INT5_LEVEL		1
+#define XCHAL_INT6_LEVEL		1
+#define XCHAL_INT7_LEVEL		1
+#define XCHAL_INT8_LEVEL		2
+#define XCHAL_INT9_LEVEL		3
+#define XCHAL_INT10_LEVEL		3
+#define XCHAL_INT11_LEVEL		3
+#define XCHAL_INT12_LEVEL		4
+#define XCHAL_INT13_LEVEL		5
+#define XCHAL_INT14_LEVEL		7
+#define XCHAL_INT15_LEVEL		1
+#define XCHAL_INT16_LEVEL		1
+#define XCHAL_INT17_LEVEL		1
+#define XCHAL_INT18_LEVEL		1
+#define XCHAL_INT19_LEVEL		1
+#define XCHAL_INT20_LEVEL		1
+#define XCHAL_INT21_LEVEL		3
+#define XCHAL_DEBUGLEVEL		6	/* debug interrupt level */
+#define XCHAL_HAVE_DEBUG_EXTERN_INT	1	/* OCD external db interrupt */
+#define XCHAL_NMILEVEL			7	/* NMI "level" (for use with
+						   EXCSAVE/EPS/EPC_n, RFI n) */
+
+/*  Type of each interrupt:  */
+#define XCHAL_INT0_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT1_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT2_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT3_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT4_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT5_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT6_TYPE 	XTHAL_INTTYPE_TIMER
+#define XCHAL_INT7_TYPE 	XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT8_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT9_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT10_TYPE 	XTHAL_INTTYPE_TIMER
+#define XCHAL_INT11_TYPE 	XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT12_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT13_TYPE 	XTHAL_INTTYPE_TIMER
+#define XCHAL_INT14_TYPE 	XTHAL_INTTYPE_NMI
+#define XCHAL_INT15_TYPE 	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT16_TYPE 	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT17_TYPE 	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT18_TYPE 	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT19_TYPE 	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT20_TYPE 	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT21_TYPE 	XTHAL_INTTYPE_EXTERN_EDGE
+
+/*  Masks of interrupts for each type of interrupt:  */
+#define XCHAL_INTTYPE_MASK_UNCONFIGURED	0xFFC00000
+#define XCHAL_INTTYPE_MASK_SOFTWARE	0x00000880
+#define XCHAL_INTTYPE_MASK_EXTERN_EDGE	0x003F8000
+#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL	0x0000133F
+#define XCHAL_INTTYPE_MASK_TIMER	0x00002440
+#define XCHAL_INTTYPE_MASK_NMI		0x00004000
+#define XCHAL_INTTYPE_MASK_WRITE_ERROR	0x00000000
+#define XCHAL_INTTYPE_MASK_PROFILING	0x00000000
+
+/*  Interrupt numbers assigned to specific interrupt sources:  */
+#define XCHAL_TIMER0_INTERRUPT		6	/* CCOMPARE0 */
+#define XCHAL_TIMER1_INTERRUPT		10	/* CCOMPARE1 */
+#define XCHAL_TIMER2_INTERRUPT		13	/* CCOMPARE2 */
+#define XCHAL_TIMER3_INTERRUPT		XTHAL_TIMER_UNCONFIGURED
+#define XCHAL_NMI_INTERRUPT		14	/* non-maskable interrupt */
+
+/*  Interrupt numbers for levels at which only one interrupt is configured:  */
+#define XCHAL_INTLEVEL2_NUM		8
+#define XCHAL_INTLEVEL4_NUM		12
+#define XCHAL_INTLEVEL5_NUM		13
+#define XCHAL_INTLEVEL7_NUM		14
+/*  (There are many interrupts each at level(s) 1, 3.)  */
+
+
+/*
+ *  External interrupt mapping.
+ *  These macros describe how Xtensa processor interrupt numbers
+ *  (as numbered internally, eg. in INTERRUPT and INTENABLE registers)
+ *  map to external BInterrupt<n> pins, for those interrupts
+ *  configured as external (level-triggered, edge-triggered, or NMI).
+ *  See the Xtensa processor databook for more details.
+ */
+
+/*  Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number:  */
+#define XCHAL_EXTINT0_NUM		0	/* (intlevel 1) */
+#define XCHAL_EXTINT1_NUM		1	/* (intlevel 1) */
+#define XCHAL_EXTINT2_NUM		2	/* (intlevel 1) */
+#define XCHAL_EXTINT3_NUM		3	/* (intlevel 1) */
+#define XCHAL_EXTINT4_NUM		4	/* (intlevel 1) */
+#define XCHAL_EXTINT5_NUM		5	/* (intlevel 1) */
+#define XCHAL_EXTINT6_NUM		8	/* (intlevel 2) */
+#define XCHAL_EXTINT7_NUM		9	/* (intlevel 3) */
+#define XCHAL_EXTINT8_NUM		12	/* (intlevel 4) */
+#define XCHAL_EXTINT9_NUM		14	/* (intlevel 7) */
+#define XCHAL_EXTINT10_NUM		15	/* (intlevel 1) */
+#define XCHAL_EXTINT11_NUM		16	/* (intlevel 1) */
+#define XCHAL_EXTINT12_NUM		17	/* (intlevel 1) */
+#define XCHAL_EXTINT13_NUM		18	/* (intlevel 1) */
+#define XCHAL_EXTINT14_NUM		19	/* (intlevel 1) */
+#define XCHAL_EXTINT15_NUM		20	/* (intlevel 1) */
+#define XCHAL_EXTINT16_NUM		21	/* (intlevel 3) */
+/*  EXTERNAL BInterrupt pin numbers mapped to each core interrupt number:  */
+#define XCHAL_INT0_EXTNUM		0	/* (intlevel 1) */
+#define XCHAL_INT1_EXTNUM		1	/* (intlevel 1) */
+#define XCHAL_INT2_EXTNUM		2	/* (intlevel 1) */
+#define XCHAL_INT3_EXTNUM		3	/* (intlevel 1) */
+#define XCHAL_INT4_EXTNUM		4	/* (intlevel 1) */
+#define XCHAL_INT5_EXTNUM		5	/* (intlevel 1) */
+#define XCHAL_INT8_EXTNUM		6	/* (intlevel 2) */
+#define XCHAL_INT9_EXTNUM		7	/* (intlevel 3) */
+#define XCHAL_INT12_EXTNUM		8	/* (intlevel 4) */
+#define XCHAL_INT14_EXTNUM		9	/* (intlevel 7) */
+#define XCHAL_INT15_EXTNUM		10	/* (intlevel 1) */
+#define XCHAL_INT16_EXTNUM		11	/* (intlevel 1) */
+#define XCHAL_INT17_EXTNUM		12	/* (intlevel 1) */
+#define XCHAL_INT18_EXTNUM		13	/* (intlevel 1) */
+#define XCHAL_INT19_EXTNUM		14	/* (intlevel 1) */
+#define XCHAL_INT20_EXTNUM		15	/* (intlevel 1) */
+#define XCHAL_INT21_EXTNUM		16	/* (intlevel 3) */
+
+
+/*----------------------------------------------------------------------
+			EXCEPTIONS and VECTORS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_XEA_VERSION		2	/* Xtensa Exception Architecture
+						   number: 1 == XEA1 (old)
+							   2 == XEA2 (new)
+							   0 == XEAX (extern) or TX */
+#define XCHAL_HAVE_XEA1			0	/* Exception Architecture 1 */
+#define XCHAL_HAVE_XEA2			1	/* Exception Architecture 2 */
+#define XCHAL_HAVE_XEAX			0	/* External Exception Arch. */
+#define XCHAL_HAVE_EXCEPTIONS		1	/* exception option */
+#define XCHAL_HAVE_HALT			0	/* halt architecture option */
+#define XCHAL_HAVE_BOOTLOADER		0	/* boot loader (for TX) */
+#define XCHAL_HAVE_MEM_ECC_PARITY	0	/* local memory ECC/parity */
+#define XCHAL_HAVE_VECTOR_SELECT	1	/* relocatable vectors */
+#define XCHAL_HAVE_VECBASE		1	/* relocatable vectors */
+#define XCHAL_VECBASE_RESET_VADDR	0x60000000  /* VECBASE reset value */
+#define XCHAL_VECBASE_RESET_PADDR	0x60000000
+#define XCHAL_RESET_VECBASE_OVERLAP	0
+
+#define XCHAL_RESET_VECTOR0_VADDR	0x50000000
+#define XCHAL_RESET_VECTOR0_PADDR	0x50000000
+#define XCHAL_RESET_VECTOR1_VADDR	0x40000400
+#define XCHAL_RESET_VECTOR1_PADDR	0x40000400
+#define XCHAL_RESET_VECTOR_VADDR	0x50000000
+#define XCHAL_RESET_VECTOR_PADDR	0x50000000
+#define XCHAL_USER_VECOFS		0x00000340
+#define XCHAL_USER_VECTOR_VADDR		0x60000340
+#define XCHAL_USER_VECTOR_PADDR		0x60000340
+#define XCHAL_KERNEL_VECOFS		0x00000300
+#define XCHAL_KERNEL_VECTOR_VADDR	0x60000300
+#define XCHAL_KERNEL_VECTOR_PADDR	0x60000300
+#define XCHAL_DOUBLEEXC_VECOFS		0x000003C0
+#define XCHAL_DOUBLEEXC_VECTOR_VADDR	0x600003C0
+#define XCHAL_DOUBLEEXC_VECTOR_PADDR	0x600003C0
+#define XCHAL_WINDOW_OF4_VECOFS		0x00000000
+#define XCHAL_WINDOW_UF4_VECOFS		0x00000040
+#define XCHAL_WINDOW_OF8_VECOFS		0x00000080
+#define XCHAL_WINDOW_UF8_VECOFS		0x000000C0
+#define XCHAL_WINDOW_OF12_VECOFS	0x00000100
+#define XCHAL_WINDOW_UF12_VECOFS	0x00000140
+#define XCHAL_WINDOW_VECTORS_VADDR	0x60000000
+#define XCHAL_WINDOW_VECTORS_PADDR	0x60000000
+#define XCHAL_INTLEVEL2_VECOFS		0x00000180
+#define XCHAL_INTLEVEL2_VECTOR_VADDR	0x60000180
+#define XCHAL_INTLEVEL2_VECTOR_PADDR	0x60000180
+#define XCHAL_INTLEVEL3_VECOFS		0x000001C0
+#define XCHAL_INTLEVEL3_VECTOR_VADDR	0x600001C0
+#define XCHAL_INTLEVEL3_VECTOR_PADDR	0x600001C0
+#define XCHAL_INTLEVEL4_VECOFS		0x00000200
+#define XCHAL_INTLEVEL4_VECTOR_VADDR	0x60000200
+#define XCHAL_INTLEVEL4_VECTOR_PADDR	0x60000200
+#define XCHAL_INTLEVEL5_VECOFS		0x00000240
+#define XCHAL_INTLEVEL5_VECTOR_VADDR	0x60000240
+#define XCHAL_INTLEVEL5_VECTOR_PADDR	0x60000240
+#define XCHAL_INTLEVEL6_VECOFS		0x00000280
+#define XCHAL_INTLEVEL6_VECTOR_VADDR	0x60000280
+#define XCHAL_INTLEVEL6_VECTOR_PADDR	0x60000280
+#define XCHAL_DEBUG_VECOFS		XCHAL_INTLEVEL6_VECOFS
+#define XCHAL_DEBUG_VECTOR_VADDR	XCHAL_INTLEVEL6_VECTOR_VADDR
+#define XCHAL_DEBUG_VECTOR_PADDR	XCHAL_INTLEVEL6_VECTOR_PADDR
+#define XCHAL_NMI_VECOFS		0x000002C0
+#define XCHAL_NMI_VECTOR_VADDR		0x600002C0
+#define XCHAL_NMI_VECTOR_PADDR		0x600002C0
+#define XCHAL_INTLEVEL7_VECOFS		XCHAL_NMI_VECOFS
+#define XCHAL_INTLEVEL7_VECTOR_VADDR	XCHAL_NMI_VECTOR_VADDR
+#define XCHAL_INTLEVEL7_VECTOR_PADDR	XCHAL_NMI_VECTOR_PADDR
+
+
+/*----------------------------------------------------------------------
+				DEBUG MODULE
+  ----------------------------------------------------------------------*/
+
+/*  Misc  */
+#define XCHAL_HAVE_DEBUG_ERI		1	/* ERI to debug module */
+#define XCHAL_HAVE_DEBUG_APB		0	/* APB to debug module */
+#define XCHAL_HAVE_DEBUG_JTAG		1	/* JTAG to debug module */
+
+/*  On-Chip Debug (OCD)  */
+#define XCHAL_HAVE_OCD			1	/* OnChipDebug option */
+#define XCHAL_NUM_IBREAK		2	/* number of IBREAKn regs */
+#define XCHAL_NUM_DBREAK		2	/* number of DBREAKn regs */
+#define XCHAL_HAVE_OCD_DIR_ARRAY	0	/* faster OCD option (to LX4) */
+#define XCHAL_HAVE_OCD_LS32DDR		1	/* L32DDR/S32DDR (faster OCD) */
+
+/*  TRAX (in core)  */
+#define XCHAL_HAVE_TRAX			1	/* TRAX in debug module */
+#define XCHAL_TRAX_MEM_SIZE		262144	/* TRAX memory size in bytes */
+#define XCHAL_TRAX_MEM_SHAREABLE	0	/* start/end regs; ready sig. */
+#define XCHAL_TRAX_ATB_WIDTH		0	/* ATB width (bits), 0=no ATB */
+#define XCHAL_TRAX_TIME_WIDTH		0	/* timestamp bitwidth, 0=none */
+
+/*  Perf counters  */
+#define XCHAL_NUM_PERF_COUNTERS		0	/* performance counters */
+
+
+/*----------------------------------------------------------------------
+				MMU
+  ----------------------------------------------------------------------*/
+
+/*  See core-matmap.h header file for more details.  */
+
+#define XCHAL_HAVE_TLBS			1	/* inverse of HAVE_CACHEATTR */
+#define XCHAL_HAVE_SPANNING_WAY		1	/* one way maps I+D 4GB vaddr */
+#define XCHAL_SPANNING_WAY		0	/* TLB spanning way number */
+#define XCHAL_HAVE_IDENTITY_MAP		1	/* vaddr == paddr always */
+#define XCHAL_HAVE_CACHEATTR		0	/* CACHEATTR register present */
+#define XCHAL_HAVE_MIMIC_CACHEATTR	1	/* region protection */
+#define XCHAL_HAVE_XLT_CACHEATTR	0	/* region prot. w/translation */
+#define XCHAL_HAVE_PTP_MMU		0	/* full MMU (with page table
+						   [autorefill] and protection)
+						   usable for an MMU-based OS */
+/*  If none of the above last 4 are set, it's a custom TLB configuration.  */
+
+#define XCHAL_MMU_ASID_BITS		0	/* number of bits in ASIDs */
+#define XCHAL_MMU_RINGS			1	/* number of rings (1..4) */
+#define XCHAL_MMU_RING_BITS		0	/* num of bits in RING field */
+
+#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */
+
+
+#endif /* _XTENSA_CORE_CONFIGURATION_H */
+
diff --git a/arch/xtensa/include/asm/arch-de212/tie-asm.h b/arch/xtensa/include/asm/arch-de212/tie-asm.h
new file mode 100644
index 0000000..7213550
--- /dev/null
+++ b/arch/xtensa/include/asm/arch-de212/tie-asm.h
@@ -0,0 +1,150 @@
+/*
+ * This header file contains assembly-language definitions (assembly
+ * macros, etc.) for this specific Xtensa processor's TIE extensions
+ * and options.  It is customized to this Xtensa processor configuration.
+ * This file is autogenerated, please do not edit.
+ *
+ * Copyright (C) 1999-2015 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_CORE_TIE_ASM_H
+#define _XTENSA_CORE_TIE_ASM_H
+
+/*  Selection parameter values for save-area save/restore macros:  */
+/*  Option vs. TIE:  */
+#define XTHAL_SAS_TIE	0x0001	/* custom extension or coprocessor */
+#define XTHAL_SAS_OPT	0x0002	/* optional (and not a coprocessor) */
+#define XTHAL_SAS_ANYOT	0x0003	/* both of the above */
+/*  Whether used automatically by compiler:  */
+#define XTHAL_SAS_NOCC	0x0004	/* not used by compiler w/o special opts/code */
+#define XTHAL_SAS_CC	0x0008	/* used by compiler without special opts/code */
+#define XTHAL_SAS_ANYCC	0x000C	/* both of the above */
+/*  ABI handling across function calls:  */
+#define XTHAL_SAS_CALR	0x0010	/* caller-saved */
+#define XTHAL_SAS_CALE	0x0020	/* callee-saved */
+#define XTHAL_SAS_GLOB	0x0040	/* global across function calls (in thread) */
+#define XTHAL_SAS_ANYABI	0x0070	/* all of the above three */
+/*  Misc  */
+#define XTHAL_SAS_ALL	0xFFFF	/* include all default NCP contents */
+#define XTHAL_SAS3(optie,ccuse,abi)	( ((optie) & XTHAL_SAS_ANYOT)  \
+					| ((ccuse) & XTHAL_SAS_ANYCC)  \
+					| ((abi)   & XTHAL_SAS_ANYABI) )
+
+
+    /*
+      *  Macro to store all non-coprocessor (extra) custom TIE and optional state
+      *  (not including zero-overhead loop registers).
+      *  Required parameters:
+      *      ptr         Save area pointer address register (clobbered)
+      *                  (register must contain a 4 byte aligned address).
+      *      at1..at4    Four temporary address registers (first XCHAL_NCP_NUM_ATMPS
+      *                  registers are clobbered, the remaining are unused).
+      *  Optional parameters:
+      *      continue    If macro invoked as part of a larger store sequence, set to 1
+      *                  if this is not the first in the sequence.  Defaults to 0.
+      *      ofs         Offset from start of larger sequence (from value of first ptr
+      *                  in sequence) at which to store.  Defaults to next available space
+      *                  (or 0 if <continue> is 0).
+      *      select      Select what category(ies) of registers to store, as a bitmask
+      *                  (see XTHAL_SAS_xxx constants).  Defaults to all registers.
+      *      alloc       Select what category(ies) of registers to allocate; if any
+      *                  category is selected here that is not in <select>, space for
+      *                  the corresponding registers is skipped without doing any store.
+      */
+    .macro xchal_ncp_store  ptr at1 at2 at3 at4  continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0
+	xchal_sa_start	\continue, \ofs
+	// Optional caller-saved registers used by default by the compiler:
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\select)
+	xchal_sa_align	\ptr, 0, 1016, 4, 4
+	rsr.ACCLO	\at1		// MAC16 option
+	s32i	\at1, \ptr, .Lxchal_ofs_+0
+	rsr.ACCHI	\at1		// MAC16 option
+	s32i	\at1, \ptr, .Lxchal_ofs_+4
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 8
+	.elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\alloc)) == 0
+	xchal_sa_align	\ptr, 0, 1016, 4, 4
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 8
+	.endif
+	// Optional caller-saved registers not used by default by the compiler:
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select)
+	xchal_sa_align	\ptr, 0, 1004, 4, 4
+	rsr.SCOMPARE1	\at1		// conditional store option
+	s32i	\at1, \ptr, .Lxchal_ofs_+0
+	rsr.M0	\at1		// MAC16 option
+	s32i	\at1, \ptr, .Lxchal_ofs_+4
+	rsr.M1	\at1		// MAC16 option
+	s32i	\at1, \ptr, .Lxchal_ofs_+8
+	rsr.M2	\at1		// MAC16 option
+	s32i	\at1, \ptr, .Lxchal_ofs_+12
+	rsr.M3	\at1		// MAC16 option
+	s32i	\at1, \ptr, .Lxchal_ofs_+16
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 20
+	.elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0
+	xchal_sa_align	\ptr, 0, 1004, 4, 4
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 20
+	.endif
+    .endm	// xchal_ncp_store
+
+    /*
+      *  Macro to load all non-coprocessor (extra) custom TIE and optional state
+      *  (not including zero-overhead loop registers).
+      *  Required parameters:
+      *      ptr         Save area pointer address register (clobbered)
+      *                  (register must contain a 4 byte aligned address).
+      *      at1..at4    Four temporary address registers (first XCHAL_NCP_NUM_ATMPS
+      *                  registers are clobbered, the remaining are unused).
+      *  Optional parameters:
+      *      continue    If macro invoked as part of a larger load sequence, set to 1
+      *                  if this is not the first in the sequence.  Defaults to 0.
+      *      ofs         Offset from start of larger sequence (from value of first ptr
+      *                  in sequence) at which to load.  Defaults to next available space
+      *                  (or 0 if <continue> is 0).
+      *      select      Select what category(ies) of registers to load, as a bitmask
+      *                  (see XTHAL_SAS_xxx constants).  Defaults to all registers.
+      *      alloc       Select what category(ies) of registers to allocate; if any
+      *                  category is selected here that is not in <select>, space for
+      *                  the corresponding registers is skipped without doing any load.
+      */
+    .macro xchal_ncp_load  ptr at1 at2 at3 at4  continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0
+	xchal_sa_start	\continue, \ofs
+	// Optional caller-saved registers used by default by the compiler:
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\select)
+	xchal_sa_align	\ptr, 0, 1016, 4, 4
+	l32i	\at1, \ptr, .Lxchal_ofs_+0
+	wsr.ACCLO	\at1		// MAC16 option
+	l32i	\at1, \ptr, .Lxchal_ofs_+4
+	wsr.ACCHI	\at1		// MAC16 option
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 8
+	.elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\alloc)) == 0
+	xchal_sa_align	\ptr, 0, 1016, 4, 4
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 8
+	.endif
+	// Optional caller-saved registers not used by default by the compiler:
+	.ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select)
+	xchal_sa_align	\ptr, 0, 1004, 4, 4
+	l32i	\at1, \ptr, .Lxchal_ofs_+0
+	wsr.SCOMPARE1	\at1		// conditional store option
+	l32i	\at1, \ptr, .Lxchal_ofs_+4
+	wsr.M0	\at1		// MAC16 option
+	l32i	\at1, \ptr, .Lxchal_ofs_+8
+	wsr.M1	\at1		// MAC16 option
+	l32i	\at1, \ptr, .Lxchal_ofs_+12
+	wsr.M2	\at1		// MAC16 option
+	l32i	\at1, \ptr, .Lxchal_ofs_+16
+	wsr.M3	\at1		// MAC16 option
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 20
+	.elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0
+	xchal_sa_align	\ptr, 0, 1004, 4, 4
+	.set	.Lxchal_ofs_, .Lxchal_ofs_ + 20
+	.endif
+    .endm	// xchal_ncp_load
+
+
+#define XCHAL_NCP_NUM_ATMPS	1
+
+#define XCHAL_SA_NUM_ATMPS	1
+
+#endif /*_XTENSA_CORE_TIE_ASM_H*/
+
diff --git a/arch/xtensa/include/asm/arch-de212/tie.h b/arch/xtensa/include/asm/arch-de212/tie.h
new file mode 100644
index 0000000..fd0fbfe
--- /dev/null
+++ b/arch/xtensa/include/asm/arch-de212/tie.h
@@ -0,0 +1,116 @@
+/*
+ * This header file describes this specific Xtensa processor's TIE extensions
+ * that extend basic Xtensa core functionality.  It is customized to this
+ * Xtensa processor configuration.
+ * This file is autogenerated, please do not edit.
+ *
+ * Copyright (C) 1999-2015 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_CORE_TIE_H
+#define _XTENSA_CORE_TIE_H
+
+#define XCHAL_CP_NUM			0	/* number of coprocessors */
+#define XCHAL_CP_MAX			0	/* max CP ID + 1 (0 if none) */
+#define XCHAL_CP_MASK			0x00	/* bitmask of all CPs by ID */
+#define XCHAL_CP_PORT_MASK		0x00	/* bitmask of only port CPs */
+
+/*  Save area for non-coprocessor optional and custom (TIE) state:  */
+#define XCHAL_NCP_SA_SIZE		28
+#define XCHAL_NCP_SA_ALIGN		4
+
+/*  Total save area for optional and custom state (NCP + CPn):  */
+#define XCHAL_TOTAL_SA_SIZE		32	/* with 16-byte align padding */
+#define XCHAL_TOTAL_SA_ALIGN		4	/* actual minimum alignment */
+
+/*
+ * Detailed contents of save areas.
+ * NOTE:  caller must define the XCHAL_SA_REG macro (not defined here)
+ * before expanding the XCHAL_xxx_SA_LIST() macros.
+ *
+ * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize,
+ *		dbnum,base,regnum,bitsz,gapsz,reset,x...)
+ *
+ *	s = passed from XCHAL_*_LIST(s), eg. to select how to expand
+ *	ccused = set if used by compiler without special options or code
+ *	abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global)
+ *	kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg)
+ *	opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg)
+ *	name = lowercase reg name (no quotes)
+ *	galign = group byte alignment (power of 2) (galign >= align)
+ *	align = register byte alignment (power of 2)
+ *	asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz)
+ *	  (not including any pad bytes required to galign this or next reg)
+ *	dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>)
+ *	base = reg shortname w/o index (or sr=special, ur=TIE user reg)
+ *	regnum = reg index in regfile, or special/TIE-user reg number
+ *	bitsz = number of significant bits (regfile width, or ur/sr mask bits)
+ *	gapsz = intervening bits, if bitsz bits not stored contiguously
+ *	(padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize)
+ *	reset = register reset value (or 0 if undefined at reset)
+ *	x = reserved for future use (0 until then)
+ *
+ *  To filter out certain registers, e.g. to expand only the non-global
+ *  registers used by the compiler, you can do something like this:
+ *
+ *  #define XCHAL_SA_REG(s,ccused,p...)	SELCC##ccused(p)
+ *  #define SELCC0(p...)
+ *  #define SELCC1(abikind,p...)	SELAK##abikind(p)
+ *  #define SELAK0(p...)		REG(p)
+ *  #define SELAK1(p...)		REG(p)
+ *  #define SELAK2(p...)
+ *  #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \
+ *		...what you want to expand...
+ */
+
+#define XCHAL_NCP_SA_NUM	7
+#define XCHAL_NCP_SA_LIST(s)	\
+ XCHAL_SA_REG(s,1,0,0,1,          acclo, 4, 4, 4,0x0210,  sr,16 , 32,0,0,0) \
+ XCHAL_SA_REG(s,1,0,0,1,          acchi, 4, 4, 4,0x0211,  sr,17 ,  8,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,      scompare1, 4, 4, 4,0x020C,  sr,12 , 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,             m0, 4, 4, 4,0x0220,  sr,32 , 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,             m1, 4, 4, 4,0x0221,  sr,33 , 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,             m2, 4, 4, 4,0x0222,  sr,34 , 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,             m3, 4, 4, 4,0x0223,  sr,35 , 32,0,0,0)
+
+#define XCHAL_CP0_SA_NUM	0
+#define XCHAL_CP0_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP1_SA_NUM	0
+#define XCHAL_CP1_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP2_SA_NUM	0
+#define XCHAL_CP2_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP3_SA_NUM	0
+#define XCHAL_CP3_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP4_SA_NUM	0
+#define XCHAL_CP4_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP5_SA_NUM	0
+#define XCHAL_CP5_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP6_SA_NUM	0
+#define XCHAL_CP6_SA_LIST(s)	/* empty */
+
+#define XCHAL_CP7_SA_NUM	0
+#define XCHAL_CP7_SA_LIST(s)	/* empty */
+
+/* Byte length of instruction from its first nibble (op0 field), per FLIX.  */
+#define XCHAL_OP0_FORMAT_LENGTHS	3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3
+/* Byte length of instruction from its first byte, per FLIX.  */
+#define XCHAL_BYTE0_FORMAT_LENGTHS	\
+	3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3,\
+	3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3,\
+	3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3,\
+	3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3,\
+	3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3,\
+	3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3,\
+	3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3,\
+	3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3
+
+#endif /*_XTENSA_CORE_TIE_H*/
+
diff --git a/arch/xtensa/include/asm/asmmacro.h b/arch/xtensa/include/asm/asmmacro.h
new file mode 100644
index 0000000..b7adc7e
--- /dev/null
+++ b/arch/xtensa/include/asm/asmmacro.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2005 - 2013 Tensilica Inc.
+ * Copyright (C) 2014 - 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_ASMMACRO_H
+#define _XTENSA_ASMMACRO_H
+
+#include <asm/arch/core.h>
+
+/*
+ * Function entry and return macros for supported ABIs.
+ */
+
+#if defined(__XTENSA_WINDOWED_ABI__)
+#define abi_entry	entry	sp, 16
+#define abi_ret		retw
+#elif defined(__XTENSA_CALL0_ABI__)
+#define abi_entry
+#define abi_ret		ret
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+/*
+ * Some little helpers for loops. Use zero-overhead-loops
+ * where applicable and if supported by the processor.
+ *
+ * __loopi ar, at, size, inc
+ *         ar	register initialized with the start address
+ *	   at	scratch register used by macro
+ *	   size	size immediate value
+ *	   inc	increment
+ *
+ * __loops ar, as, at, inc_log2[, mask_log2][, cond][, ncond]
+ *	   ar	register initialized with the start address
+ *	   as	register initialized with the size
+ *	   at	scratch register use by macro
+ *	   inc_log2	increment [in log2]
+ *	   mask_log2	mask [in log2]
+ *	   cond		true condition (used in loop'cond')
+ *	   ncond	false condition (used in b'ncond')
+ *
+ * __loop  as
+ *	   restart loop. 'as' register must not have been modified!
+ *
+ * __endla ar, as, incr
+ *	   ar	start address (modified)
+ *	   as	scratch register used by __loops/__loopi macros or
+ *		end address used by __loopt macro
+ *	   inc	increment
+ */
+
+#if XCHAL_HAVE_LOOPS
+
+.macro	__loopi ar, at, size, incr
+	movi	\at, ((\size + \incr - 1) / (\incr))
+	loop	\at, 99f
+.endm
+
+
+.macro	__loops	ar, as, at, incr_log2, mask_log2, cond, ncond
+	.ifgt \incr_log2 - 1
+		addi	\at, \as, (1 << \incr_log2) - 1
+		.ifnc \mask_log2,
+			extui	\at, \at, \incr_log2, \mask_log2
+		.else
+			srli	\at, \at, \incr_log2
+		.endif
+	.endif
+	loop\cond	\at, 99f
+.endm
+
+
+.macro	__loopt	ar, as, at, incr_log2
+	sub	\at, \as, \ar
+	.ifgt	\incr_log2 - 1
+		addi	\at, \at, (1 << \incr_log2) - 1
+		srli	\at, \at, \incr_log2
+	.endif
+	loop	\at, 99f
+.endm
+
+
+.macro	__loop	as
+	loop	\as, 99f
+.endm
+
+
+.macro	__endl	ar, as
+99:
+.endm
+
+
+#else
+
+.macro	__loopi ar, at, size, incr
+	movi	\at, ((\size + \incr - 1) / (\incr))
+	addi	\at, \ar, \size
+98:
+.endm
+
+
+.macro	__loops	ar, as, at, incr_log2, mask_log2, cond, ncond
+	.ifnc \mask_log2,
+		extui	\at, \as, \incr_log2, \mask_log2
+	.else
+		.ifnc \ncond,
+			srli	\at, \as, \incr_log2
+		.endif
+	.endif
+	.ifnc \ncond,
+		b\ncond	\at, 99f
+
+	.endif
+	.ifnc \mask_log2,
+		slli	\at, \at, \incr_log2
+		add	\at, \ar, \at
+	.else
+		add	\at, \ar, \as
+	.endif
+98:
+.endm
+
+.macro	__loopt	ar, as, at, incr_log2
+98:
+.endm
+
+
+.macro	__loop	as
+98:
+.endm
+
+
+.macro	__endl	ar, as
+	bltu	\ar, \as, 98b
+99:
+.endm
+
+
+#endif
+
+
+.macro	__endla	ar, as, incr
+	addi	\ar, \ar, \incr
+	__endl	\ar \as
+.endm
+
+
+#endif /* _XTENSA_ASMMACRO_H */
diff --git a/arch/xtensa/include/asm/atomic.h b/arch/xtensa/include/asm/atomic.h
new file mode 100644
index 0000000..a75baa0
--- /dev/null
+++ b/arch/xtensa/include/asm/atomic.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_ATOMIC_H
+#define _XTENSA_ATOMIC_H
+
+#include <asm/system.h>
+
+typedef struct { volatile int counter; } atomic_t;
+
+#define ATOMIC_INIT(i)	{ (i) }
+
+#define atomic_read(v)		((v)->counter)
+#define atomic_set(v, i)	((v)->counter = (i))
+
+static inline void atomic_add(int i, atomic_t *v)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	v->counter += i;
+	local_irq_restore(flags);
+}
+
+static inline void atomic_sub(int i, atomic_t *v)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	v->counter -= i;
+	local_irq_restore(flags);
+}
+
+static inline void atomic_inc(atomic_t *v)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	++v->counter;
+	local_irq_restore(flags);
+}
+
+static inline void atomic_dec(atomic_t *v)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	--v->counter;
+	local_irq_restore(flags);
+}
+
+#endif
diff --git a/arch/xtensa/include/asm/bitops.h b/arch/xtensa/include/asm/bitops.h
new file mode 100644
index 0000000..550d12f
--- /dev/null
+++ b/arch/xtensa/include/asm/bitops.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2001 - 2012 Tensilica Inc.
+ * Copyright (C) 2014 - 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_BITOPS_H
+#define _XTENSA_BITOPS_H
+
+#include <asm/system.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/__ffs.h>
+
+static inline int test_bit(int nr, const void *addr)
+{
+	return ((unsigned char *)addr)[nr >> 3] & (1u << (nr & 7));
+}
+
+static inline int test_and_set_bit(int nr, volatile void *addr)
+{
+	unsigned long flags;
+	unsigned char tmp;
+	unsigned char mask = 1u << (nr & 7);
+
+	local_irq_save(flags);
+	tmp = ((unsigned char *)addr)[nr >> 3];
+	((unsigned char *)addr)[nr >> 3] |= mask;
+	local_irq_restore(flags);
+
+	return tmp & mask;
+}
+
+#endif	/* _XTENSA_BITOPS_H */
diff --git a/arch/xtensa/include/asm/bootparam.h b/arch/xtensa/include/asm/bootparam.h
new file mode 100644
index 0000000..a2a9013
--- /dev/null
+++ b/arch/xtensa/include/asm/bootparam.h
@@ -0,0 +1,54 @@
+/*
+ * Definition of the Linux/Xtensa boot parameter structure
+ *
+ * Copyright (C) 2001 - 2009  Tensilica Inc.
+ *
+ * (Concept borrowed from the 68K port)
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_BOOTPARAM_H
+#define _XTENSA_BOOTPARAM_H
+
+#define BP_VERSION 0x0001
+
+#define BP_TAG_COMMAND_LINE	0x1001	/* command line (0-terminated string)*/
+#define BP_TAG_INITRD		0x1002	/* ramdisk addr and size (bp_meminfo) */
+#define BP_TAG_MEMORY		0x1003	/* memory addr and size (bp_meminfo) */
+#define BP_TAG_SERIAL_BAUDRATE	0x1004	/* baud rate of current console */
+#define BP_TAG_SERIAL_PORT	0x1005	/* serial device of current console */
+#define BP_TAG_FDT		0x1006	/* flat device tree */
+
+#define BP_TAG_FIRST		0x7B0B  /* first tag with a version number */
+#define BP_TAG_LAST		0x7E0B	/* last tag */
+
+#ifndef __ASSEMBLY__
+
+/* All records are aligned to 4 bytes */
+
+struct bp_tag {
+	unsigned short id;	/* tag id */
+	unsigned short size;	/* size of this record excluding the structure*/
+	unsigned long data[0];	/* data */
+};
+
+#define bp_tag_next(tag)						\
+	((struct bp_tag *)((unsigned long)((tag) + 1) + (tag)->size))
+
+struct meminfo {
+	unsigned long type;
+	unsigned long start;
+	unsigned long end;
+};
+
+#define MEMORY_TYPE_CONVENTIONAL     0x1000
+#define MEMORY_TYPE_NONE             0x2000
+
+struct sysmem_info {
+	int nr_banks;
+	struct meminfo bank[0];
+};
+
+#endif
+#endif
diff --git a/arch/xtensa/include/asm/byteorder.h b/arch/xtensa/include/asm/byteorder.h
new file mode 100644
index 0000000..278653c
--- /dev/null
+++ b/arch/xtensa/include/asm/byteorder.h
@@ -0,0 +1,83 @@
+/*
+ * Based on Linux/Xtensa kernel version
+ *
+ * Copyright (C) 2001 - 2007 Tensilica Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_BYTEORDER_H
+#define _XTENSA_BYTEORDER_H
+
+#include <asm/types.h>
+
+static inline __attribute__((const)) __u32 ___arch__swab32(__u32 x)
+{
+	__u32 res;
+
+	/* instruction sequence from Xtensa ISA release 2/2000 */
+	__asm__("ssai     8\n\t"
+		"srli     %0, %1, 16\n\t"
+		"src      %0, %0, %1\n\t"
+		"src      %0, %0, %0\n\t"
+		"src      %0, %1, %0\n"
+		: "=&a" (res)
+		: "a" (x)
+		);
+	return res;
+}
+
+static inline __attribute__((const)) __u16 ___arch__swab16(__u16 x)
+{
+	/*
+	 * Given that 'short' values are signed (i.e., can be negative),
+	 * we cannot assume that the upper 16-bits of the register are
+	 * zero.  We are careful to mask values after shifting.
+	 */
+
+	/*
+	 * There exists an anomaly between xt-gcc and xt-xcc.  xt-gcc
+	 * inserts an extui instruction after putting this function inline
+	 * to ensure that it uses only the least-significant 16 bits of
+	 * the result.  xt-xcc doesn't use an extui, but assumes the
+	 * __asm__ macro follows convention that the upper 16 bits of an
+	 * 'unsigned short' result are still zero.  This macro doesn't
+	 * follow convention; indeed, it leaves garbage in the upport 16
+	 * bits of the register.
+	 *
+	 * Declaring the temporary variables 'res' and 'tmp' to be 32-bit
+	 * types while the return type of the function is a 16-bit type
+	 * forces both compilers to insert exactly one extui instruction
+	 * (or equivalent) to mask off the upper 16 bits.
+	 */
+
+	__u32 res;
+	__u32 tmp;
+
+	__asm__("extui    %1, %2, 8, 8\n\t"
+		"slli     %0, %2, 8\n\t"
+		"or       %0, %0, %1\n"
+		: "=&a" (res), "=&a" (tmp)
+		: "a" (x)
+		);
+
+	return res;
+}
+
+#define __arch__swab32(x) ___arch__swab32(x)
+#define __arch__swab16(x) ___arch__swab16(x)
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#  define __BYTEORDER_HAS_U64__
+#  define __SWAB_64_THRU_32__
+#endif
+
+#ifdef __XTENSA_EL__
+# include <linux/byteorder/little_endian.h>
+#elif defined(__XTENSA_EB__)
+# include <linux/byteorder/big_endian.h>
+#else
+# error processor byte order undefined!
+#endif
+
+#endif /* _XTENSA_BYTEORDER_H */
diff --git a/arch/xtensa/include/asm/cache.h b/arch/xtensa/include/asm/cache.h
new file mode 100644
index 0000000..08c534c
--- /dev/null
+++ b/arch/xtensa/include/asm/cache.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009 Tensilica Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#ifndef _XTENSA_CACHE_H
+#define _XTENSA_CACHE_H
+
+#include <asm/arch/core.h>
+
+#define ARCH_DMA_MINALIGN	XCHAL_DCACHE_LINESIZE
+
+#ifndef __ASSEMBLY__
+
+void __flush_dcache_all(void);
+void __flush_invalidate_dcache_range(unsigned long addr, unsigned long size);
+void __invalidate_dcache_all(void);
+void __invalidate_dcache_range(unsigned long addr, unsigned long size);
+
+void __invalidate_icache_all(void);
+void __invalidate_icache_range(unsigned long addr, unsigned long size);
+
+#endif
+
+#endif	/* _XTENSA_CACHE_H */
diff --git a/arch/xtensa/include/asm/cacheasm.h b/arch/xtensa/include/asm/cacheasm.h
new file mode 100644
index 0000000..342a817
--- /dev/null
+++ b/arch/xtensa/include/asm/cacheasm.h
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2006 Tensilica Inc.
+ * Copyright (C) 2014 - 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_CACHEASM_H
+#define _XTENSA_CACHEASM_H
+
+#include <asm/cache.h>
+#include <asm/asmmacro.h>
+#include <linux/stringify.h>
+
+#define PAGE_SIZE 4096
+#define DCACHE_WAY_SIZE (XCHAL_DCACHE_SIZE/XCHAL_DCACHE_WAYS)
+#define ICACHE_WAY_SIZE (XCHAL_ICACHE_SIZE/XCHAL_ICACHE_WAYS)
+#define DCACHE_WAY_SHIFT (XCHAL_DCACHE_SETWIDTH + XCHAL_DCACHE_LINEWIDTH)
+#define ICACHE_WAY_SHIFT (XCHAL_ICACHE_SETWIDTH + XCHAL_ICACHE_LINEWIDTH)
+
+/*
+ * Define cache functions as macros here so that they can be used
+ * by the kernel and boot loader. We should consider moving them to a
+ * library that can be linked by both.
+ *
+ * Locking
+ *
+ *   ___unlock_dcache_all
+ *   ___unlock_icache_all
+ *
+ * Flush and invaldating
+ *
+ *   ___flush_invalidate_dcache_{all|range|page}
+ *   ___flush_dcache_{all|range|page}
+ *   ___invalidate_dcache_{all|range|page}
+ *   ___invalidate_icache_{all|range|page}
+ *
+ */
+
+	.macro	__loop_cache_all ar at insn size line_width
+
+	movi	\ar, 0
+
+	__loopi	\ar, \at, \size, (4 << (\line_width))
+
+	\insn	\ar, 0 << (\line_width)
+	\insn	\ar, 1 << (\line_width)
+	\insn	\ar, 2 << (\line_width)
+	\insn	\ar, 3 << (\line_width)
+
+	__endla	\ar, \at, 4 << (\line_width)
+
+	.endm
+
+
+	.macro	__loop_cache_range ar as at insn line_width
+
+	extui	\at, \ar, 0, \line_width
+	add	\as, \as, \at
+
+	__loops	\ar, \as, \at, \line_width
+	\insn	\ar, 0
+	__endla	\ar, \at, (1 << (\line_width))
+
+	.endm
+
+
+	.macro	__loop_cache_page ar at insn line_width
+
+	__loopi	\ar, \at, PAGE_SIZE, 4 << (\line_width)
+
+	\insn	\ar, 0 << (\line_width)
+	\insn	\ar, 1 << (\line_width)
+	\insn	\ar, 2 << (\line_width)
+	\insn	\ar, 3 << (\line_width)
+
+	__endla	\ar, \at, 4 << (\line_width)
+
+	.endm
+
+
+	.macro	___unlock_dcache_all ar at
+
+#if XCHAL_DCACHE_LINE_LOCKABLE && XCHAL_DCACHE_SIZE
+	__loop_cache_all \ar \at diu XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH
+#endif
+
+	.endm
+
+
+	.macro	___unlock_icache_all ar at
+
+#if XCHAL_ICACHE_LINE_LOCKABLE && XCHAL_ICACHE_SIZE
+	__loop_cache_all \ar \at iiu XCHAL_ICACHE_SIZE XCHAL_ICACHE_LINEWIDTH
+#endif
+
+	.endm
+
+
+	.macro	___flush_invalidate_dcache_all ar at
+
+#if XCHAL_DCACHE_SIZE
+	__loop_cache_all \ar \at diwbi XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH
+#endif
+
+	.endm
+
+
+	.macro	___flush_dcache_all ar at
+
+#if XCHAL_DCACHE_SIZE
+	__loop_cache_all \ar \at diwb XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH
+#endif
+
+	.endm
+
+
+	.macro	___invalidate_dcache_all ar at
+
+#if XCHAL_DCACHE_SIZE
+	__loop_cache_all \ar \at dii __stringify(DCACHE_WAY_SIZE) \
+			 XCHAL_DCACHE_LINEWIDTH
+#endif
+
+	.endm
+
+
+	.macro	___invalidate_icache_all ar at
+
+#if XCHAL_ICACHE_SIZE
+	__loop_cache_all \ar \at iii __stringify(ICACHE_WAY_SIZE) \
+			 XCHAL_ICACHE_LINEWIDTH
+#endif
+
+	.endm
+
+
+
+	.macro	___flush_invalidate_dcache_range ar as at
+
+#if XCHAL_DCACHE_SIZE
+	__loop_cache_range \ar \as \at dhwbi XCHAL_DCACHE_LINEWIDTH
+#endif
+
+	.endm
+
+
+	.macro	___flush_dcache_range ar as at
+
+#if XCHAL_DCACHE_SIZE
+	__loop_cache_range \ar \as \at dhwb XCHAL_DCACHE_LINEWIDTH
+#endif
+
+	.endm
+
+
+	.macro	___invalidate_dcache_range ar as at
+
+#if XCHAL_DCACHE_SIZE
+	__loop_cache_range \ar \as \at dhi XCHAL_DCACHE_LINEWIDTH
+#endif
+
+	.endm
+
+
+	.macro	___invalidate_icache_range ar as at
+
+#if XCHAL_ICACHE_SIZE
+	__loop_cache_range \ar \as \at ihi XCHAL_ICACHE_LINEWIDTH
+#endif
+
+	.endm
+
+
+
+	.macro	___flush_invalidate_dcache_page ar as
+
+#if XCHAL_DCACHE_SIZE
+	__loop_cache_page \ar \as dhwbi XCHAL_DCACHE_LINEWIDTH
+#endif
+
+	.endm
+
+
+	.macro ___flush_dcache_page ar as
+
+#if XCHAL_DCACHE_SIZE
+	__loop_cache_page \ar \as dhwb XCHAL_DCACHE_LINEWIDTH
+#endif
+
+	.endm
+
+
+	.macro	___invalidate_dcache_page ar as
+
+#if XCHAL_DCACHE_SIZE
+	__loop_cache_page \ar \as dhi XCHAL_DCACHE_LINEWIDTH
+#endif
+
+	.endm
+
+
+	.macro	___invalidate_icache_page ar as
+
+#if XCHAL_ICACHE_SIZE
+	__loop_cache_page \ar \as ihi XCHAL_ICACHE_LINEWIDTH
+#endif
+
+	.endm
+
+#endif	/* _XTENSA_CACHEASM_H */
diff --git a/arch/xtensa/include/asm/config.h b/arch/xtensa/include/asm/config.h
new file mode 100644
index 0000000..db1ea87
--- /dev/null
+++ b/arch/xtensa/include/asm/config.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2009 Tensilica Inc.
+ * Copyright (C) 2014 - 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _ASM_CONFIG_H_
+#define _ASM_CONFIG_H_
+
+#include <asm/arch/core.h>
+
+#define CONFIG_LMB
+
+/*
+ * Make boot parameters available in the MMUv2 virtual memory layout by
+ * restricting used physical memory to the first 128MB.
+ */
+#if XCHAL_HAVE_PTP_MMU
+#define CONFIG_VERY_BIG_RAM
+#define CONFIG_MAX_MEM_MAPPED (128 << 20)
+#endif
+
+#endif
diff --git a/arch/xtensa/include/asm/errno.h b/arch/xtensa/include/asm/errno.h
new file mode 100644
index 0000000..4c82b50
--- /dev/null
+++ b/arch/xtensa/include/asm/errno.h
@@ -0,0 +1 @@
+#include <asm-generic/errno.h>
diff --git a/arch/xtensa/include/asm/global_data.h b/arch/xtensa/include/asm/global_data.h
new file mode 100644
index 0000000..4569345
--- /dev/null
+++ b/arch/xtensa/include/asm/global_data.h
@@ -0,0 +1,20 @@
+/*
+ * (C) Copyright 2007, Tensilica Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef	_XTENSA_GBL_DATA_H
+#define _XTENSA_GBL_DATA_H
+
+/* Architecture-specific global data */
+
+struct arch_global_data {
+	unsigned long cpu_clk;
+};
+
+#include <asm-generic/global_data.h>
+
+#define DECLARE_GLOBAL_DATA_PTR     extern gd_t *gd
+
+#endif	/* _XTENSA_GBL_DATA_H */
diff --git a/arch/xtensa/include/asm/io.h b/arch/xtensa/include/asm/io.h
new file mode 100644
index 0000000..e34d6e1
--- /dev/null
+++ b/arch/xtensa/include/asm/io.h
@@ -0,0 +1,148 @@
+/*
+ * IO header file
+ *
+ * Copyright (C) 2001-2007 Tensilica Inc.
+ * Based on the Linux/Xtensa version of this header.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_IO_H
+#define _XTENSA_IO_H
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+/*
+ * swap functions to change byte order from little-endian to big-endian and
+ * vice versa.
+ */
+
+static inline unsigned short _swapw(unsigned short v)
+{
+	return (v << 8) | (v >> 8);
+}
+
+static inline unsigned int _swapl(unsigned int v)
+{
+	return (v << 24) | ((v & 0xff00) << 8) |
+		((v >> 8) & 0xff00) | (v >> 24);
+}
+
+/*
+ * Generic I/O
+ */
+
+#define readb(addr) \
+	({ unsigned char __v = (*(volatile unsigned char *)(addr)); __v; })
+#define readw(addr) \
+	({ unsigned short __v = (*(volatile unsigned short *)(addr)); __v; })
+#define readl(addr) \
+	({ unsigned int __v = (*(volatile unsigned int *)(addr)); __v; })
+#define writeb(b, addr) (void)((*(volatile unsigned char *)(addr)) = (b))
+#define writew(b, addr) (void)((*(volatile unsigned short *)(addr)) = (b))
+#define writel(b, addr) (void)((*(volatile unsigned int *)(addr)) = (b))
+
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+
+/* These are the definitions for the x86 IO instructions
+ * inb/inw/inl/outb/outw/outl, the "string" versions
+ * insb/insw/insl/outsb/outsw/outsl, and the "pausing" versions
+ * inb_p/inw_p/...
+ * The macros don't do byte-swapping.
+ */
+
+#define inb(port)		readb((u8 *)((port)))
+#define outb(val, port)		writeb((val), (u8 *)((unsigned long)(port)))
+#define inw(port)		readw((u16 *)((port)))
+#define outw(val, port)		writew((val), (u16 *)((unsigned long)(port)))
+#define inl(port)		readl((u32 *)((port)))
+#define outl(val, port)		writel((val), (u32 *)((unsigned long)(port)))
+
+#define inb_p(port)		inb((port))
+#define outb_p(val, port)	outb((val), (port))
+#define inw_p(port)		inw((port))
+#define outw_p(val, port)	outw((val), (port))
+#define inl_p(port)		inl((port))
+#define outl_p(val, port)	outl((val), (port))
+
+void insb(unsigned long port, void *dst, unsigned long count);
+void insw(unsigned long port, void *dst, unsigned long count);
+void insl(unsigned long port, void *dst, unsigned long count);
+void outsb(unsigned long port, const void *src, unsigned long count);
+void outsw(unsigned long port, const void *src, unsigned long count);
+void outsl(unsigned long port, const void *src, unsigned long count);
+
+#define IO_SPACE_LIMIT ~0
+
+#define memset_io(a, b, c)	memset((void *)(a), (b), (c))
+#define memcpy_fromio(a, b, c)	memcpy((a), (void *)(b), (c))
+#define memcpy_toio(a, b, c)	memcpy((void *)(a), (b), (c))
+
+/* At this point the Xtensa doesn't provide byte swap instructions */
+
+#ifdef __XTENSA_EB__
+# define in_8(addr) (*(u8 *)(addr))
+# define in_le16(addr) _swapw(*(u16 *)(addr))
+# define in_le32(addr) _swapl(*(u32 *)(addr))
+# define out_8(b, addr) *(u8 *)(addr) = (b)
+# define out_le16(b, addr) *(u16 *)(addr) = _swapw(b)
+# define out_le32(b, addr) *(u32 *)(addr) = _swapl(b)
+#elif defined(__XTENSA_EL__)
+# define in_8(addr)  (*(u8 *)(addr))
+# define in_le16(addr) (*(u16 *)(addr))
+# define in_le32(addr) (*(u32 *)(addr))
+# define out_8(b, addr) *(u8 *)(addr) = (b)
+# define out_le16(b, addr) *(u16 *)(addr) = (b)
+# define out_le32(b, addr) *(u32 *)(addr) = (b)
+#else
+# error processor byte order undefined!
+#endif
+
+
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem access
+ */
+#define xlate_dev_mem_ptr(p)    __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p)   p
+
+#define MAP_NOCACHE	(0)
+#define MAP_WRCOMBINE	(0)
+#define MAP_WRBACK	(0)
+#define MAP_WRTHROUGH	(0)
+
+static inline void *
+map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
+{
+	return (void *)paddr;
+}
+
+/*
+ * Take down a mapping set up by map_physmem().
+ */
+static inline void unmap_physmem(void *vaddr, unsigned long flags)
+{
+}
+
+static inline phys_addr_t virt_to_phys(void *vaddr)
+{
+	return (phys_addr_t)((unsigned long)vaddr);
+}
+
+/*
+ * Dummy function to keep U-Boot's cfi_flash.c driver happy.
+ */
+static inline void sync(void)
+{
+}
+
+#endif	/* _XTENSA_IO_H */
diff --git a/arch/xtensa/include/asm/ldscript.h b/arch/xtensa/include/asm/ldscript.h
new file mode 100644
index 0000000..62a1c05
--- /dev/null
+++ b/arch/xtensa/include/asm/ldscript.h
@@ -0,0 +1,222 @@
+/*
+ * (C) Copyright 2007 Tensilica, Inc.
+ * (C) Copyright 2014 - 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_LDSCRIPT_H
+#define _XTENSA_LDSCRIPT_H
+
+/*
+ * This linker script is pre-processed with CPP to avoid hard-coding
+ * addresses that depend on the Xtensa core configuration, because
+ * this FPGA board can be used with a huge variety of Xtensa cores.
+ */
+
+#include <asm/arch/core.h>
+#include <asm/addrspace.h>
+
+#define ALIGN_LMA	4
+#define LMA_EQ_VMA
+#define FORCE_OUTPUT	. = .
+#define FOLLOWING(sec)							\
+	AT(((LOADADDR(sec) + SIZEOF(sec) + ALIGN_LMA-1)) & ~(ALIGN_LMA-1))
+
+/*
+ * Specify an output section that will be added to the ROM store table
+ * (PACKED_SECTION) or one that will be resident in ROM (RESIDENT_SECTION).
+ * 'symname' is a base name for section boundary symbols *_start & *_end.
+ * 'lma' is the load address at which a section will be packed in ROM.
+ * 'region' is the basename identifying a memory region and program header.
+ * 'keep' prevents removal of empty sections (must be 'KEEP' or 'NOKEEP').
+ */
+
+#define RELOCATE1(_sec_)						\
+	LONG(_##_sec_##_start);						\
+	LONG(_##_sec_##_end);						\
+	LONG(LOADADDR(.##_sec_));
+
+#define RELOCATE2(_sym_, _sec_)						\
+	LONG(_##_sym_##_##_sec_##_start);				\
+	LONG(_##_sym_##_##_sec_##_end);					\
+	LONG(LOADADDR(.##_sym_##.##_sec_));
+
+#define SECTION_VECTOR(_sym_, _sec_, _vma_, _lma_)			\
+.##_sym_##.##_sec_ _vma_ : _lma_					\
+{									\
+	. = ALIGN(4);							\
+	_##_sym_##_##_sec_##_start = ABSOLUTE(.);			\
+	KEEP(*(.##_sym_##.##_sec_))					\
+	_##_sym_##_##_sec_##_end = ABSOLUTE(.);				\
+}
+
+/* In MMU configs there are two aliases of SYSROM, cached and uncached.
+ * For various reasons it is simpler to use the uncached mapping for load
+ * addresses, so ROM sections end up contiguous with the reset vector and
+ * we get a compact binary image. However we can gain performance by doing
+ * the unpacking from the cached ROM mapping. So we adjust all the load
+ * addresses in the ROM store table with an offset to the cached mapping,
+ * including the symbols referring to the ROM store table itself.
+ */
+
+#define SECTION_ResetVector(_vma_, _lma_)				\
+	.ResetVector.text _vma_ : _lma_					\
+	{								\
+		FORCE_OUTPUT;						\
+		KEEP(*(.ResetVector.text));				\
+		KEEP(*(.reset.literal .reset.text))			\
+	}
+
+#define SECTION_text(_vma_, _lma_)					\
+	.text _vma_ : _lma_						\
+	{								\
+		_text_start = ABSOLUTE(.);				\
+		*(.literal .text)					\
+		*(.literal.* .text.* .stub)				\
+		*(.gnu.warning .gnu.linkonce.literal.*)			\
+		*(.gnu.linkonce.t.*.literal .gnu.linkonce.t.*)		\
+		*(.fini.literal)					\
+		*(.fini)						\
+		*(.gnu.version)						\
+		_text_end = ABSOLUTE(.);				\
+	}
+
+#define SECTION_rodata(_vma_, _lma_)					\
+	.rodata _vma_ : _lma_						\
+	{								\
+		_rodata_start = ABSOLUTE(.);				\
+		*(.rodata)						\
+		*(.rodata.*)						\
+		*(.dtb.init.rodata)					\
+		*(.gnu.linkonce.r.*)					\
+		*(.rodata1)						\
+		__XT_EXCEPTION_TABLE__ = ABSOLUTE(.);			\
+		*(.xt_except_table)					\
+		*(.gcc_except_table)					\
+		*(.gnu.linkonce.e.*)					\
+		*(.gnu.version_r)					\
+		. = ALIGN(16);						\
+		 _rodata_end = ABSOLUTE(.);				\
+	}
+
+#define SECTION_u_boot_list(_vma_, _lma_)				\
+	.u_boot_list _vma_ : _lma_					\
+	{								\
+		_u_boot_list_start = ABSOLUTE(.);			\
+		KEEP(*(SORT(.u_boot_list*)));				\
+		_u_boot_list_end = ABSOLUTE(.);				\
+	}
+
+#define SECTION_data(_vma_, _lma_)					\
+	.data _vma_ : _lma_						\
+	{								\
+		_data_start = ABSOLUTE(.);				\
+		*(.data)						\
+		*(.data.*)						\
+		*(.gnu.linkonce.d.*)					\
+		*(.data1)						\
+		*(.sdata)						\
+		*(.sdata.*)						\
+		*(.gnu.linkonce.s.*)					\
+		*(.sdata2)						\
+		*(.sdata2.*)						\
+		*(.gnu.linkonce.s2.*)					\
+		*(.jcr)							\
+		*(.eh_frame)						\
+		*(.dynamic)						\
+		*(.gnu.version_d)					\
+		_data_end = ABSOLUTE(.);				\
+	}
+
+#define SECTION_lit4(_vma_, _lma_)					\
+	.lit4 _vma_ : _lma_						\
+	{								\
+		_lit4_start = ABSOLUTE(.);				\
+		*(*.lit4)						\
+		*(.gnu.linkonce.lit4.*)					\
+		_lit4_end = ABSOLUTE(.);				\
+	}
+
+#define SECTION_bss(_vma_, _lma_)					\
+	.bss _vma_ : _lma_						\
+	{								\
+		. = ALIGN(8);						\
+		_bss_start = ABSOLUTE(.);				\
+		__bss_start = ABSOLUTE(.);				\
+		*(.dynsbss)						\
+		*(.sbss)						\
+		*(.sbss.*)						\
+		*(.gnu.linkonce.sb.*)					\
+		*(.scommon)						\
+		*(.sbss2)						\
+		*(.sbss2.*)						\
+		*(.gnu.linkonce.sb2.*)					\
+		*(.dynbss)						\
+		*(.bss)							\
+		*(.bss.*)						\
+		*(.gnu.linkonce.b.*)					\
+		*(COMMON)						\
+		*(.sram.bss)						\
+		. = ALIGN(8);						\
+		_bss_end = ABSOLUTE(.);					\
+		__bss_end = ABSOLUTE(.);				\
+		_end = ALIGN(0x8);					\
+		PROVIDE(end = ALIGN(0x8));				\
+		_stack_sentry = ALIGN(0x8);				\
+	}
+
+#define SECTION_debug							\
+	.debug           0 :  { *(.debug) }				\
+	.line            0 :  { *(.line) }				\
+	.debug_srcinfo   0 :  { *(.debug_srcinfo) }			\
+	.debug_sfnames   0 :  { *(.debug_sfnames) }			\
+	.debug_aranges   0 :  { *(.debug_aranges) }			\
+	.debug_pubnames  0 :  { *(.debug_pubnames) }			\
+	.debug_info      0 :  { *(.debug_info) }			\
+	.debug_abbrev    0 :  { *(.debug_abbrev) }			\
+	.debug_line      0 :  { *(.debug_line) }			\
+	.debug_frame     0 :  { *(.debug_frame) }			\
+	.debug_str       0 :  { *(.debug_str) }				\
+	.debug_loc       0 :  { *(.debug_loc) }				\
+	.debug_macinfo   0 :  { *(.debug_macinfo) }			\
+	.debug_weaknames 0 :  { *(.debug_weaknames) }			\
+	.debug_funcnames 0 :  { *(.debug_funcnames) }			\
+	.debug_typenames 0 :  { *(.debug_typenames) }			\
+	.debug_varnames  0 :  { *(.debug_varnames) }
+
+#define SECTION_xtensa							\
+	.xt.insn 0 :							\
+	{								\
+		KEEP (*(.xt.insn))					\
+		KEEP (*(.gnu.linkonce.x.*))				\
+	}								\
+	.xt.prop 0 :							\
+	{								\
+		KEEP (*(.xt.prop))					\
+		KEEP (*(.xt.prop.*))					\
+		KEEP (*(.gnu.linkonce.prop.*))				\
+	}								\
+	.xt.lit 0 :							\
+	{								\
+		KEEP (*(.xt.lit))					\
+		KEEP (*(.xt.lit.*))					\
+		KEEP (*(.gnu.linkonce.p.*))				\
+	}								\
+	.xt.profile_range 0 :						\
+	{								\
+		KEEP (*(.xt.profile_range))				\
+		KEEP (*(.gnu.linkonce.profile_range.*))			\
+	}								\
+	.xt.profile_ranges 0 :						\
+	{								\
+		KEEP (*(.xt.profile_ranges))				\
+		KEEP (*(.gnu.linkonce.xt.profile_ranges.*))		\
+	}								\
+	.xt.profile_files 0 :						\
+	{								\
+		KEEP (*(.xt.profile_files))				\
+		KEEP (*(.gnu.linkonce.xt.profile_files.*))		\
+	}
+
+#endif	/* _XTENSA_LDSCRIPT_H */
diff --git a/arch/xtensa/include/asm/linkage.h b/arch/xtensa/include/asm/linkage.h
new file mode 100644
index 0000000..3f46161
--- /dev/null
+++ b/arch/xtensa/include/asm/linkage.h
@@ -0,0 +1,4 @@
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+#endif
diff --git a/arch/xtensa/include/asm/misc.h b/arch/xtensa/include/asm/misc.h
new file mode 100644
index 0000000..5a2708f
--- /dev/null
+++ b/arch/xtensa/include/asm/misc.h
@@ -0,0 +1,20 @@
+/*
+ * (C) Copyright 2008, Tensilica Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ ********************************************************************
+ * NOTE: This header file defines an interface to U-Boot. Including
+ * this (unmodified) header file in another file is considered normal
+ * use of U-Boot, and does *not* fall under the heading of "derived
+ * work".
+ ********************************************************************
+ */
+
+#ifndef _XTENSA_MISC_H
+#define _XTENSA_MISC_H
+
+/* Used in cpu/xtensa/cpu.c */
+void board_reset(void);
+
+#endif	/* _XTENSA_MISC_H */
diff --git a/arch/xtensa/include/asm/posix_types.h b/arch/xtensa/include/asm/posix_types.h
new file mode 100644
index 0000000..821115c
--- /dev/null
+++ b/arch/xtensa/include/asm/posix_types.h
@@ -0,0 +1,74 @@
+/*
+ *  Copyright (C) 2007, Tensilica Inc.
+ *
+ * Based on the ARM version: Copyright (C) 1996-1998 Russell King.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#ifndef _XTENSA_POSIX_TYPES_H
+#define _XTENSA_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned short		__kernel_dev_t;
+typedef unsigned long		__kernel_ino_t;
+typedef unsigned short		__kernel_mode_t;
+typedef unsigned short		__kernel_nlink_t;
+typedef long			__kernel_off_t;
+typedef int			__kernel_pid_t;
+typedef unsigned short		__kernel_ipc_pid_t;
+typedef unsigned short		__kernel_uid_t;
+typedef unsigned short		__kernel_gid_t;
+typedef unsigned int		__kernel_size_t;
+typedef int			__kernel_ssize_t;
+typedef int			__kernel_ptrdiff_t;
+typedef long			__kernel_time_t;
+typedef long			__kernel_suseconds_t;
+typedef long			__kernel_clock_t;
+typedef int			__kernel_daddr_t;
+typedef char *			__kernel_caddr_t;
+typedef unsigned short		__kernel_uid16_t;
+typedef unsigned short		__kernel_gid16_t;
+typedef unsigned int		__kernel_uid32_t;
+typedef unsigned int		__kernel_gid32_t;
+
+typedef unsigned short		__kernel_old_uid_t;
+typedef unsigned short		__kernel_old_gid_t;
+
+#ifdef __GNUC__
+typedef long long		__kernel_loff_t;
+#endif
+
+typedef struct {
+#if defined(__KERNEL__) || defined(__USE_ALL)
+	int	val[2];
+#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+	int	__val[2];
+#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+} __kernel_fsid_t;
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#undef	__FD_SET
+#define __FD_SET(fd, fdsetp) \
+	(((fd_set *)fdsetp)->fds_bits[fd >> 5] |= (1<<(fd & 31)))
+
+#undef	__FD_CLR
+#define __FD_CLR(fd, fdsetp) \
+	(((fd_set *)fdsetp)->fds_bits[fd >> 5] &= ~(1<<(fd & 31)))
+
+#undef	__FD_ISSET
+#define __FD_ISSET(fd, fdsetp) \
+	((((fd_set *)fdsetp)->fds_bits[fd >> 5] & (1<<(fd & 31))) != 0)
+
+#undef	__FD_ZERO
+#define __FD_ZERO(fdsetp) \
+	(memset(fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
+
+#endif
+
+#endif	/* _XTENSA_POSIX_TYPES_H */
diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h
new file mode 100644
index 0000000..8822f80
--- /dev/null
+++ b/arch/xtensa/include/asm/processor.h
@@ -0,0 +1,11 @@
+/*
+ *  Copyright (C) 1997 Tensilica Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_PROCESSOR_H
+#define _XTENSA_PROCESSOR_H
+
+
+#endif /* _XTENSA_PROCESSOR_H */
diff --git a/arch/xtensa/include/asm/ptrace.h b/arch/xtensa/include/asm/ptrace.h
new file mode 100644
index 0000000..d187dbf
--- /dev/null
+++ b/arch/xtensa/include/asm/ptrace.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2001 - 2007 Tensilica Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_PTRACE_H
+#define _XTENSA_PTRACE_H
+
+#include <compiler.h>
+
+/*
+ * Kernel stack
+ *
+ *		+-----------------------+  -------- STACK_SIZE
+ *		|     register file     |  |
+ *		+-----------------------+  |
+ *		|    struct pt_regs     |  |
+ *		+-----------------------+  | ------ PT_REGS_OFFSET
+ * double	:  16 bytes spill area  :  |  ^
+ * exception	:- - - - - - - - - - - -:  |  |
+ * frame	:    struct pt_regs     :  |  |
+ *		:- - - - - - - - - - - -:  |  |
+ *		|                       |  |  |
+ *		|     memory stack      |  |  |
+ *		|                       |  |  |
+ *		~                       ~  ~  ~
+ *		~                       ~  ~  ~
+ *		|                       |  |  |
+ *		|                       |  |  |
+ *		+-----------------------+  |  | --- STACK_BIAS
+ *		|  struct task_struct   |  |  |  ^
+ *  current --> +-----------------------+  |  |  |
+ *		|  struct thread_info   |  |  |  |
+ *		+-----------------------+ --------
+ */
+
+#define KERNEL_STACK_SIZE (2 * PAGE_SIZE)
+
+/*  Offsets for exception_handlers[] (3 x 64-entries x 4-byte tables) */
+
+#define EXC_TABLE_KSTK		0x004	/* Kernel Stack */
+#define EXC_TABLE_DOUBLE_SAVE	0x008	/* Double exception save area for a0 */
+#define EXC_TABLE_FIXUP		0x00c	/* Fixup handler */
+#define EXC_TABLE_PARAM		0x010	/* For passing a parameter to fixup */
+#define EXC_TABLE_SYSCALL_SAVE	0x014	/* For fast syscall handler */
+#define EXC_TABLE_FAST_USER	0x100	/* Fast user exception handler */
+#define EXC_TABLE_FAST_KERNEL	0x200	/* Fast kernel exception handler */
+#define EXC_TABLE_DEFAULT	0x300	/* Default C-Handler */
+#define EXC_TABLE_SIZE		0x400
+
+/* Registers used by strace */
+
+#define REG_A_BASE	0xfc000000
+#define REG_AR_BASE	0x04000000
+#define REG_PC		0x14000000
+#define REG_PS		0x080000e6
+#define REG_WB		0x08000048
+#define REG_WS		0x08000049
+#define REG_LBEG	0x08000000
+#define REG_LEND	0x08000001
+#define REG_LCOUNT	0x08000002
+#define REG_SAR		0x08000003
+#define REG_DEPC	0x080000c0
+#define REG_EXCCAUSE	0x080000e8
+#define REG_EXCVADDR	0x080000ee
+#define SYSCALL_NR	0x1
+
+#define AR_REGNO_TO_A_REGNO(ar, wb) (ar - wb*4) & ~(XCHAL_NUM_AREGS - 1)
+
+/* Other PTRACE_ values defined in <linux/ptrace.h> using values 0-9,16,17,24 */
+
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13
+#define PTRACE_GETFPREGS          14
+#define PTRACE_SETFPREGS          15
+#define PTRACE_GETFPREGSIZE       18
+
+#ifndef __ASSEMBLY__
+
+/*
+ * This struct defines the way the registers are stored on the
+ * kernel stack during a system call or other kernel entry.
+ */
+struct pt_regs {
+	unsigned long pc;		/*   4 */
+	unsigned long ps;		/*   8 */
+	unsigned long depc;		/*  12 */
+	unsigned long exccause;		/*  16 */
+	unsigned long excvaddr;		/*  20 */
+	unsigned long debugcause;	/*  24 */
+	unsigned long wmask;		/*  28 */
+	unsigned long lbeg;		/*  32 */
+	unsigned long lend;		/*  36 */
+	unsigned long lcount;		/*  40 */
+	unsigned long sar;		/*  44 */
+	unsigned long windowbase;	/*  48 */
+	unsigned long windowstart;	/*  52 */
+	unsigned long syscall;		/*  56 */
+	unsigned long icountlevel;	/*  60 */
+	int reserved[1];		/*  64 */
+
+	/* Make sure the areg field is 16 bytes aligned */
+	int align[0] __aligned(16);
+
+	/* current register frame.
+	 * Note: The ESF for kernel exceptions ends after 16 registers!
+	 */
+	unsigned long areg[16];		/* 128 (64) */
+};
+
+#ifdef __KERNEL__
+
+# define task_pt_regs(tsk) ((struct pt_regs *) \
+	(task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1)
+# define user_mode(regs) (((regs)->ps & 0x00000020) != 0)
+# define instruction_pointer(regs) ((regs)->pc)
+void show_regs(struct pt_regs *);
+
+# ifndef CONFIG_SMP
+#  define profile_pc(regs) instruction_pointer(regs)
+# endif
+#endif /* __KERNEL__ */
+
+#else	/* __ASSEMBLY__ */
+
+#ifdef __KERNEL__
+# include <asm/asm-offsets.h>
+#define PT_REGS_OFFSET	  (KERNEL_STACK_SIZE - PT_USER_SIZE)
+#endif
+
+#endif	/* !__ASSEMBLY__ */
+#endif	/* _XTENSA_PTRACE_H */
diff --git a/arch/xtensa/include/asm/regs.h b/arch/xtensa/include/asm/regs.h
new file mode 100644
index 0000000..0a82a22
--- /dev/null
+++ b/arch/xtensa/include/asm/regs.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2006 Tensilica, Inc.  All Rights Reserved.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_REGS_H
+#define _XTENSA_REGS_H
+
+/*  Special registers  */
+
+#define IBREAKA		128
+#define DBREAKA		144
+#define DBREAKC		160
+
+/*  Special names for read-only and write-only interrupt registers  */
+
+#define INTREAD		226
+#define INTSET		226
+#define INTCLEAR	227
+
+/*  EXCCAUSE register fields  */
+
+#define EXCCAUSE_EXCCAUSE_SHIFT	0
+#define EXCCAUSE_EXCCAUSE_MASK	0x3F
+
+#define EXCCAUSE_ILLEGAL_INSTRUCTION		0
+#define EXCCAUSE_SYSTEM_CALL			1
+#define EXCCAUSE_INSTRUCTION_FETCH_ERROR	2
+#define EXCCAUSE_LOAD_STORE_ERROR		3
+#define EXCCAUSE_LEVEL1_INTERRUPT		4
+#define EXCCAUSE_ALLOCA				5
+#define EXCCAUSE_INTEGER_DIVIDE_BY_ZERO		6
+#define EXCCAUSE_SPECULATION			7
+#define EXCCAUSE_PRIVILEGED			8
+#define EXCCAUSE_UNALIGNED			9
+#define EXCCAUSE_INSTR_DATA_ERROR		12
+#define EXCCAUSE_LOAD_STORE_DATA_ERROR		13
+#define EXCCAUSE_INSTR_ADDR_ERROR		14
+#define EXCCAUSE_LOAD_STORE_ADDR_ERROR		15
+#define EXCCAUSE_ITLB_MISS			16
+#define EXCCAUSE_ITLB_MULTIHIT			17
+#define EXCCAUSE_ITLB_PRIVILEGE			18
+#define EXCCAUSE_ITLB_SIZE_RESTRICTION		19
+#define EXCCAUSE_FETCH_CACHE_ATTRIBUTE		20
+#define EXCCAUSE_DTLB_MISS			24
+#define EXCCAUSE_DTLB_MULTIHIT			25
+#define EXCCAUSE_DTLB_PRIVILEGE			26
+#define EXCCAUSE_DTLB_SIZE_RESTRICTION		27
+#define EXCCAUSE_LOAD_CACHE_ATTRIBUTE		28
+#define EXCCAUSE_STORE_CACHE_ATTRIBUTE		29
+#define EXCCAUSE_COPROCESSOR0_DISABLED		32
+#define EXCCAUSE_COPROCESSOR1_DISABLED		33
+#define EXCCAUSE_COPROCESSOR2_DISABLED		34
+#define EXCCAUSE_COPROCESSOR3_DISABLED		35
+#define EXCCAUSE_COPROCESSOR4_DISABLED		36
+#define EXCCAUSE_COPROCESSOR5_DISABLED		37
+#define EXCCAUSE_COPROCESSOR6_DISABLED		38
+#define EXCCAUSE_COPROCESSOR7_DISABLED		39
+#define EXCCAUSE_LAST				63
+
+/*  PS register fields  */
+
+#define PS_WOE_BIT		18
+#define PS_CALLINC_SHIFT	16
+#define PS_CALLINC_MASK		0x00030000
+#define PS_OWB_SHIFT		8
+#define PS_OWB_MASK		0x00000F00
+#define PS_RING_SHIFT		6
+#define PS_RING_MASK		0x000000C0
+#define PS_UM_BIT		5
+#define PS_EXCM_BIT		4
+#define PS_INTLEVEL_SHIFT	0
+#define PS_INTLEVEL_MASK	0x0000000F
+
+/*  DBREAKCn register fields  */
+
+#define DBREAKC_MASK_BIT		0
+#define DBREAKC_MASK_MASK		0x0000003F
+#define DBREAKC_LOAD_BIT		30
+#define DBREAKC_LOAD_MASK		0x40000000
+#define DBREAKC_STOR_BIT		31
+#define DBREAKC_STOR_MASK		0x80000000
+
+/*  DEBUGCAUSE register fields  */
+
+#define DEBUGCAUSE_DEBUGINT_BIT		5	/* External debug interrupt */
+#define DEBUGCAUSE_BREAKN_BIT		4	/* BREAK.N instruction */
+#define DEBUGCAUSE_BREAK_BIT		3	/* BREAK instruction */
+#define DEBUGCAUSE_DBREAK_BIT		2	/* DBREAK match */
+#define DEBUGCAUSE_IBREAK_BIT		1	/* IBREAK match */
+#define DEBUGCAUSE_ICOUNT_BIT		0	/* ICOUNT would incr. to zero */
+
+#endif /* _XTENSA_SPECREG_H */
+
diff --git a/arch/xtensa/include/asm/relocate.h b/arch/xtensa/include/asm/relocate.h
new file mode 100644
index 0000000..9c4ce23
--- /dev/null
+++ b/arch/xtensa/include/asm/relocate.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _ASM_XTENSA_RELOCATE_H
+#define _ASM_XTENSA_RELOCATE_H
+
+#include <common.h>
+
+int clear_bss(void);
+
+#endif	/* _ASM_XTENSA_RELOCATE_H */
diff --git a/arch/xtensa/include/asm/sections.h b/arch/xtensa/include/asm/sections.h
new file mode 100644
index 0000000..2309b14
--- /dev/null
+++ b/arch/xtensa/include/asm/sections.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2012 The Chromium OS Authors.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __ASM_XTENSA_SECTIONS_H
+#define __ASM_XTENSA_SECTIONS_H
+
+#include <asm-generic/sections.h>
+
+#endif
diff --git a/arch/xtensa/include/asm/string.h b/arch/xtensa/include/asm/string.h
new file mode 100644
index 0000000..65a3601
--- /dev/null
+++ b/arch/xtensa/include/asm/string.h
@@ -0,0 +1,10 @@
+#ifndef _XTENSA_STRING_H
+#define _XTENSA_STRING_H
+
+/*
+ * Use the generic string functions in U-Boot's lib_generic.
+ * In the boot loader we care about compactness more than performance.
+ * Prototypes will be taken from <linux/string.h>
+ */
+
+#endif	/* _XTENSA_STRING_H */
diff --git a/arch/xtensa/include/asm/system.h b/arch/xtensa/include/asm/system.h
new file mode 100644
index 0000000..5b71008
--- /dev/null
+++ b/arch/xtensa/include/asm/system.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_SYSTEM_H
+#define _XTENSA_SYSTEM_H
+
+#include <asm/arch/core.h>
+
+#if XCHAL_HAVE_INTERRUPTS
+#define local_irq_save(flags) \
+	__asm__ __volatile__ ("rsil %0, %1" \
+			      : "=a"(flags) \
+			      : "I"(XCHAL_EXCM_LEVEL) \
+			      : "memory")
+#define local_irq_restore(flags) \
+	__asm__ __volatile__ ("wsr %0, ps\n\t" \
+			      "rsync" \
+			      :: "a"(flags) : "memory")
+#else
+#define local_irq_save(flags) ((void)(flags))
+#define local_irq_restore(flags) ((void)(flags))
+#endif
+
+#endif
diff --git a/arch/xtensa/include/asm/types.h b/arch/xtensa/include/asm/types.h
new file mode 100644
index 0000000..f7eda9d
--- /dev/null
+++ b/arch/xtensa/include/asm/types.h
@@ -0,0 +1,60 @@
+/*
+ *  Copyright (C) 1997 Tensilica Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _XTENSA_TYPES_H
+#define _XTENSA_TYPES_H
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+#define BITS_PER_LONG 32
+
+/* Dma addresses are 32-bits wide */
+
+typedef u32 dma_addr_t;
+
+typedef unsigned long phys_addr_t;
+typedef unsigned long phys_size_t;
+
+
+#endif /* __KERNEL__ */
+
+#endif /* _XTENSA_TYPES_H */
diff --git a/arch/xtensa/include/asm/u-boot.h b/arch/xtensa/include/asm/u-boot.h
new file mode 100644
index 0000000..cfdc036
--- /dev/null
+++ b/arch/xtensa/include/asm/u-boot.h
@@ -0,0 +1,41 @@
+/*
+ * (C) Copyright 2007, Tensilica Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ ********************************************************************
+ * NOTE: This header file defines an interface to U-Boot. Including
+ * this (unmodified) header file in another file is considered normal
+ * use of U-Boot, and does *not* fall under the heading of "derived
+ * work".
+ ********************************************************************
+ */
+
+#ifndef _XTENSA_U_BOOT_H
+#define _XTENSA_U_BOOT_H
+
+#ifdef CONFIG_SYS_GENERIC_BOARD
+/* Use the generic board which requires a unified bd_info */
+#include <asm-generic/u-boot.h>
+#else
+
+#ifndef __ASSEMBLY__
+typedef struct bd_info {
+	int		bi_baudrate;	/* serial console baudrate */
+	unsigned long	bi_ip_addr;	/* IP Address */
+	unsigned char	bi_enetaddr[6];	/* Ethernet adress */
+	unsigned long	bi_boot_params;	/* where this board expects params */
+	unsigned long	bi_memstart;	/* start of DRAM memory VA */
+	unsigned long	bi_memsize;	/* size	 of DRAM memory in bytes */
+	unsigned long	bi_flashstart;	/* start of FLASH memory */
+	unsigned long	bi_flashsize;	/* size  of FLASH memory */
+	unsigned long	bi_flashoffset;	/* offset to skip UBoot image */
+} bd_t;
+#endif	/* __ ASSEMBLY__ */
+
+#endif	/* CONFIG_SYS_GENERIC_BOARD */
+
+/* For image.h:image_check_target_arch() */
+#define IH_ARCH_DEFAULT IH_ARCH_XTENSA
+
+#endif	/* _XTENSA_U_BOOT_H */
diff --git a/arch/xtensa/include/asm/unaligned.h b/arch/xtensa/include/asm/unaligned.h
new file mode 100644
index 0000000..536f364
--- /dev/null
+++ b/arch/xtensa/include/asm/unaligned.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_XTENSA_UNALIGNED_H
+#define _ASM_XTENSA_UNALIGNED_H
+
+#include <asm-generic/unaligned.h>
+
+#endif /* _ASM_XTENSA_UNALIGNED_H */
diff --git a/arch/xtensa/lib/Makefile b/arch/xtensa/lib/Makefile
new file mode 100644
index 0000000..7c7d8d5
--- /dev/null
+++ b/arch/xtensa/lib/Makefile
@@ -0,0 +1,10 @@
+#
+# (C) Copyright 2007 - 2013 Tensilica Inc.
+# (C) Copyright 2014 - 2016 Cadence Design Systems Inc.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_CMD_BOOTM) += bootm.o
+
+obj-y 	+= cache.o misc.o relocate.o time.o
diff --git a/arch/xtensa/lib/bootm.c b/arch/xtensa/lib/bootm.c
new file mode 100644
index 0000000..1604bb9
--- /dev/null
+++ b/arch/xtensa/lib/bootm.c
@@ -0,0 +1,197 @@
+/*
+ * (C) Copyright 2008 - 2013 Tensilica Inc.
+ * (C) Copyright 2014 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <u-boot/zlib.h>
+#include <asm/byteorder.h>
+#include <asm/addrspace.h>
+#include <asm/bootparam.h>
+#include <asm/cache.h>
+#include <image.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Setup boot-parameters.
+ */
+
+static struct bp_tag *setup_first_tag(struct bp_tag *params)
+{
+	params->id = BP_TAG_FIRST;
+	params->size = sizeof(long);
+	*(unsigned long *)&params->data = BP_VERSION;
+
+	return bp_tag_next(params);
+}
+
+static struct bp_tag *setup_last_tag(struct bp_tag *params)
+{
+	params->id = BP_TAG_LAST;
+	params->size = 0;
+
+	return bp_tag_next(params);
+}
+
+static struct bp_tag *setup_memory_tag(struct bp_tag *params)
+{
+	struct bd_info *bd = gd->bd;
+	struct meminfo *mem;
+
+	params->id = BP_TAG_MEMORY;
+	params->size = sizeof(struct meminfo);
+	mem = (struct meminfo *)params->data;
+	mem->type = MEMORY_TYPE_CONVENTIONAL;
+	mem->start = bd->bi_memstart;
+	mem->end = bd->bi_memstart + bd->bi_memsize;
+
+	printf("   MEMORY:          tag:0x%04x, type:0X%lx, start:0X%lx, end:0X%lx\n",
+	       BP_TAG_MEMORY, mem->type, mem->start, mem->end);
+
+	return bp_tag_next(params);
+}
+
+static struct bp_tag *setup_commandline_tag(struct bp_tag *params,
+					    char *cmdline)
+{
+	int len;
+
+	if (!cmdline)
+		return params;
+
+	len = strlen(cmdline);
+
+	params->id = BP_TAG_COMMAND_LINE;
+	params->size = (len + 3) & -4;
+	strcpy((char *)params->data, cmdline);
+
+	printf("   COMMAND_LINE:    tag:0x%04x, size:%u, data:'%s'\n",
+	       BP_TAG_COMMAND_LINE, params->size, cmdline);
+
+	return bp_tag_next(params);
+}
+
+static struct bp_tag *setup_ramdisk_tag(struct bp_tag *params,
+					unsigned long rd_start,
+					unsigned long rd_end)
+{
+	struct meminfo *mem;
+
+	if (rd_start == rd_end)
+		return params;
+
+	/* Add a single banked memory */
+
+	params->id = BP_TAG_INITRD;
+	params->size = sizeof(struct meminfo);
+
+	mem = (struct meminfo *)params->data;
+	mem->type =  MEMORY_TYPE_CONVENTIONAL;
+	mem->start = PHYSADDR(rd_start);
+	mem->end = PHYSADDR(rd_end);
+
+	printf("   INITRD:          tag:0x%x, type:0X%04lx, start:0X%lx, end:0X%lx\n",
+	       BP_TAG_INITRD, mem->type, mem->start, mem->end);
+
+	return bp_tag_next(params);
+}
+
+static struct bp_tag *setup_serial_tag(struct bp_tag *params)
+{
+	params->id = BP_TAG_SERIAL_BAUDRATE;
+	params->size = sizeof(unsigned long);
+	params->data[0] = gd->baudrate;
+
+	printf("   SERIAL_BAUDRATE: tag:0x%04x, size:%u, baudrate:%lu\n",
+	       BP_TAG_SERIAL_BAUDRATE, params->size, params->data[0]);
+
+	return bp_tag_next(params);
+}
+
+#ifdef CONFIG_OF_LIBFDT
+
+static struct bp_tag *setup_fdt_tag(struct bp_tag *params, void *fdt_start)
+{
+	params->id = BP_TAG_FDT;
+	params->size = sizeof(unsigned long);
+	params->data[0] = (unsigned long)fdt_start;
+
+	printf("   FDT:             tag:0x%04x, size:%u, start:0x%lx\n",
+	       BP_TAG_FDT, params->size, params->data[0]);
+
+	return bp_tag_next(params);
+}
+
+#endif
+
+/*
+ * Boot Linux.
+ */
+
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+	struct bp_tag *params, *params_start;
+	ulong initrd_start, initrd_end;
+	char *commandline = getenv("bootargs");
+
+	if (!(flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)))
+		return 0;
+
+	show_boot_progress(15);
+
+	if (images->rd_start) {
+		initrd_start = images->rd_start;
+		initrd_end = images->rd_end;
+	} else {
+		initrd_start = 0;
+		initrd_end = 0;
+	}
+
+	params_start = (struct bp_tag *)gd->bd->bi_boot_params;
+	params = params_start;
+	params = setup_first_tag(params);
+	params = setup_memory_tag(params);
+	params = setup_commandline_tag(params, commandline);
+	params = setup_serial_tag(params);
+
+	if (initrd_start)
+		params = setup_ramdisk_tag(params, initrd_start, initrd_end);
+
+#ifdef CONFIG_OF_LIBFDT
+	if (images->ft_addr)
+		params = setup_fdt_tag(params, images->ft_addr);
+#endif
+
+	printf("\n");
+
+	params = setup_last_tag(params);
+
+	show_boot_progress(15);
+
+	printf("Transferring Control to Linux @0x%08lx ...\n\n",
+	       (ulong)images->ep);
+
+	flush_dcache_range((unsigned long)params_start, (unsigned long)params);
+
+	if (flag & BOOTM_STATE_OS_FAKE_GO)
+		return 0;
+
+	/*
+	 * _start() in vmlinux expects boot params in register a2.
+	 * NOTE:
+	 *    Disable/delete your u-boot breakpoints before stepping into linux.
+	 */
+	asm volatile ("mov	a2, %0\n\t"
+		      "jx	%1\n\t"
+		      : : "a" (params_start), "a" (images->ep)
+		      : "a2");
+
+	/* Does not return */
+
+	return 1;
+}
+
diff --git a/arch/xtensa/lib/cache.c b/arch/xtensa/lib/cache.c
new file mode 100644
index 0000000..2680839
--- /dev/null
+++ b/arch/xtensa/lib/cache.c
@@ -0,0 +1,60 @@
+/*
+ * (C) Copyright 2008 - 2013 Tensilica Inc.
+ * (C) Copyright 2014 - 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/cache.h>
+
+/*
+ * We currently run always with caches enabled when running from memory.
+ * Xtensa version D or later will support changing cache behavior, so
+ * we could implement it if necessary.
+ */
+
+int dcache_status(void)
+{
+	return 1;
+}
+
+void dcache_enable(void)
+{
+}
+
+void dcache_disable(void)
+{
+}
+
+void flush_cache(ulong start_addr, ulong size)
+{
+	__flush_invalidate_dcache_range(start_addr, size);
+	__invalidate_icache_range(start_addr, size);
+}
+
+void flush_dcache_all(void)
+{
+	__flush_dcache_all();
+	__invalidate_icache_all();
+}
+
+void flush_dcache_range(ulong start_addr, ulong end_addr)
+{
+	__flush_invalidate_dcache_range(start_addr, end_addr - start_addr);
+}
+
+void invalidate_dcache_range(ulong start, ulong stop)
+{
+	__invalidate_dcache_range(start, stop - start);
+}
+
+void invalidate_dcache_all(void)
+{
+	__invalidate_dcache_all();
+}
+
+void invalidate_icache_all(void)
+{
+	__invalidate_icache_all();
+}
diff --git a/arch/xtensa/lib/misc.S b/arch/xtensa/lib/misc.S
new file mode 100644
index 0000000..449a6db
--- /dev/null
+++ b/arch/xtensa/lib/misc.S
@@ -0,0 +1,179 @@
+/*
+ * Miscellaneous assembly functions.
+ *
+ * Copyright (C) 2001 - 2007 Tensilica Inc.
+ * Copyright (C) 2014 - 2016 Cadence Design Systems Inc.
+ *
+ * Chris Zankel	<chris@zankel.net>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+
+#include <linux/linkage.h>
+#include <asm/asmmacro.h>
+#include <asm/cacheasm.h>
+
+/*
+ * void __invalidate_icache_page(ulong start)
+ */
+
+ENTRY(__invalidate_icache_page)
+
+	abi_entry
+
+	___invalidate_icache_page a2 a3
+	isync
+
+	abi_ret
+
+ENDPROC(__invalidate_icache_page)
+
+/*
+ * void __invalidate_dcache_page(ulong start)
+ */
+
+ENTRY(__invalidate_dcache_page)
+
+	abi_entry
+
+	___invalidate_dcache_page a2 a3
+	dsync
+
+	abi_ret
+
+ENDPROC(__invalidate_dcache_page)
+
+/*
+ * void __flush_invalidate_dcache_page(ulong start)
+ */
+
+ENTRY(__flush_invalidate_dcache_page)
+
+	abi_entry
+
+	___flush_invalidate_dcache_page a2 a3
+
+	dsync
+	abi_ret
+
+ENDPROC(__flush_invalidate_dcache_page)
+
+/*
+ * void __flush_dcache_page(ulong start)
+ */
+
+ENTRY(__flush_dcache_page)
+
+	abi_entry
+
+	___flush_dcache_page a2 a3
+
+	dsync
+	abi_ret
+
+ENDPROC(__flush_dcache_page)
+
+/*
+ * void __invalidate_icache_range(ulong start, ulong size)
+ */
+
+ENTRY(__invalidate_icache_range)
+
+	abi_entry
+
+	___invalidate_icache_range a2 a3 a4
+	isync
+
+	abi_ret
+
+ENDPROC(__invalidate_icache_range)
+
+/*
+ * void __flush_invalidate_dcache_range(ulong start, ulong size)
+ */
+
+ENTRY(__flush_invalidate_dcache_range)
+
+	abi_entry
+
+	___flush_invalidate_dcache_range a2 a3 a4
+	dsync
+
+	abi_ret
+
+ENDPROC(__flush_invalidate_dcache_range)
+
+/*
+ * void _flush_dcache_range(ulong start, ulong size)
+ */
+
+ENTRY(__flush_dcache_range)
+
+	abi_entry
+
+	___flush_dcache_range a2 a3 a4
+	dsync
+
+	abi_ret
+
+ENDPROC(__flush_dcache_range)
+
+/*
+ * void _invalidate_dcache_range(ulong start, ulong size)
+ */
+
+ENTRY(__invalidate_dcache_range)
+
+	abi_entry
+
+	___invalidate_dcache_range a2 a3 a4
+
+	abi_ret
+
+ENDPROC(__invalidate_dcache_range)
+
+/*
+ * void _invalidate_icache_all(void)
+ */
+
+ENTRY(__invalidate_icache_all)
+
+	abi_entry
+
+	___invalidate_icache_all a2 a3
+	isync
+
+	abi_ret
+
+ENDPROC(__invalidate_icache_all)
+
+/*
+ * void _flush_invalidate_dcache_all(void)
+ */
+
+ENTRY(__flush_invalidate_dcache_all)
+
+	abi_entry
+
+	___flush_invalidate_dcache_all a2 a3
+	dsync
+
+	abi_ret
+
+ENDPROC(__flush_invalidate_dcache_all)
+
+/*
+ * void _invalidate_dcache_all(void)
+ */
+
+ENTRY(__invalidate_dcache_all)
+
+	abi_entry
+
+	___invalidate_dcache_all a2 a3
+	dsync
+
+	abi_ret
+
+ENDPROC(__invalidate_dcache_all)
diff --git a/arch/xtensa/lib/relocate.c b/arch/xtensa/lib/relocate.c
new file mode 100644
index 0000000..3f747ec
--- /dev/null
+++ b/arch/xtensa/lib/relocate.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/relocate.h>
+#include <asm/sections.h>
+#include <asm/string.h>
+
+int clear_bss(void)
+{
+	size_t len = (size_t)&__bss_end - (size_t)&__bss_start;
+
+	memset((void *)&__bss_start, 0x00, len);
+	return 0;
+}
+
diff --git a/arch/xtensa/lib/time.c b/arch/xtensa/lib/time.c
new file mode 100644
index 0000000..1332072
--- /dev/null
+++ b/arch/xtensa/lib/time.c
@@ -0,0 +1,121 @@
+/*
+ * (C) Copyright 2008 - 2013 Tensilica Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/global_data.h>
+#include <linux/stringify.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if XCHAL_HAVE_CCOUNT
+static ulong get_ccount(void)
+{
+	ulong ccount;
+	asm volatile ("rsr %0,"__stringify(CCOUNT) : "=a" (ccount));
+	return ccount;
+}
+#else
+static ulong fake_ccount;
+#define get_ccount() fake_ccount
+#endif
+
+static void delay_cycles(unsigned cycles)
+{
+#if XCHAL_HAVE_CCOUNT
+	unsigned expiry = get_ccount() + cycles;
+	while ((signed)(expiry - get_ccount()) > 0)
+		;
+#else
+#warning "Without Xtensa timer option, timing will not be accurate."
+
+	/*
+	 * Approximate the cycle count by a loop iteration count.
+	 * This is highly dependent on config and optimization.
+	 */
+
+	volatile unsigned i;
+	for (i = cycles >> 4U; i > 0; --i)
+		;
+	fake_ccount += cycles;
+#endif
+}
+
+/*
+ * Delay (busy-wait) for a number of microseconds.
+ */
+
+void __udelay(unsigned long usec)
+{
+	ulong lo, hi, i;
+	ulong mhz = CONFIG_SYS_CLK_FREQ / 1000000;
+
+	/* Scale to support full 32-bit usec range */
+
+	lo = usec & ((1<<22)-1);
+	hi = usec >> 22UL;
+	for (i = 0; i < hi; ++i)
+		delay_cycles(mhz << 22);
+	delay_cycles(mhz * lo);
+}
+
+
+/*
+ * Return the elapsed time (ticks) since 'base'.
+ */
+
+ulong get_timer(ulong base)
+{
+	/* Don't tie up a timer; use cycle counter if available (or fake it) */
+
+#if XCHAL_HAVE_CCOUNT
+	register ulong ccount;
+	__asm__ volatile ("rsr %0, CCOUNT" : "=a"(ccount));
+	return ccount / (CONFIG_SYS_CLK_FREQ / CONFIG_SYS_HZ) - base;
+#else
+	/*
+	 * Add at least the overhead of this call (in cycles).
+	 * Avoids hanging in case caller doesn't use udelay().
+	 * Note that functions that don't call udelay() (such as
+	 * the "sleep" command) will not get a significant delay
+	 * because there is no time reference.
+	 */
+
+	fake_ccount += 20;
+	return fake_ccount / (CONFIG_SYS_CLK_FREQ / CONFIG_SYS_HZ) - base;
+#endif
+}
+
+
+/*
+ * This function is derived from ARM/PowerPC code (read timebase as long long).
+ * On Xtensa it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+/*
+ * This function is derived from ARM/PowerPC code (timebase clock frequency).
+ * On Xtensa it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+	ulong tbclk;
+
+	tbclk = CONFIG_SYS_HZ;
+	return tbclk;
+}
+
+#if XCHAL_HAVE_CCOUNT
+unsigned long timer_get_us(void)
+{
+	unsigned long ccount;
+
+	__asm__ volatile ("rsr %0, CCOUNT" : "=a"(ccount));
+	return ccount / (CONFIG_SYS_CLK_FREQ / 1000000);
+}
+#endif
diff --git a/board/Barix/ipam390/README.ipam390 b/board/Barix/ipam390/README.ipam390
index 5c45fca..be09280 100644
--- a/board/Barix/ipam390/README.ipam390
+++ b/board/Barix/ipam390/README.ipam390
@@ -31,9 +31,9 @@
 
 Compilation
 ===========
-run "./MAKEALL ipam390" in the u-boot source tree.
-Once this build completes you will have a u-boot.ais file that needs to
-be written to the nand flash.
+run "tools/buildman/buildman -k ipam390" in the u-boot source tree.
+Once this build completes you will have a ../current/ipam390/u-boot.ais file
+that needs to be written to the nand flash.
 
 Flashing the images to NAND
 ==========================
@@ -71,13 +71,13 @@
 - cd to the u-boot source tree
 
 - compile the u-boot for the ipam390 board:
-$ ./MAKEALL ipam390
+$ tools/buildman/buildman -k ipam390
 
   -> Now we shall have u-boot.bin
 
 - Create u-boot-uart-ais.bin
-$ mono HexAIS_OMAP-L138.exe -entrypoint 0xC1080000 -ini
-ipam390-ais-uart.cfg -o ./uboot-uart-ais.bin ./u-boot.bin@0xC1080000;
+$ mono HexAIS_OMAP-L138.exe -entrypoint 0xC1080000 -ini ipam390-ais-uart.cfg \
+	-o ../current/ipam390/uboot-uart-ais.bin ./u-boot.bin@0xC1080000;
 
 Note: The ipam390-ais-uart.cfg is found in the board directory
 for the ipam390 board, u-boot:/board/Barix/ipam390/ipam390-ais-uart.cfg
diff --git a/board/advantech/Kconfig b/board/advantech/Kconfig
new file mode 100644
index 0000000..a8d4969
--- /dev/null
+++ b/board/advantech/Kconfig
@@ -0,0 +1,28 @@
+if VENDOR_ADVANTECH
+
+choice
+	prompt "Mainboard model"
+	optional
+
+config TARGET_SOM_DB5800_SOM_6867
+	bool "Advantech SOM-DB5800 & SOM-6867"
+	help
+	  Advantech SOM-DB5800 COM Express development board with SOM-6867
+	  installed.
+
+	  SOM-6867 is a COM Express Type 6 Compact Module with either an Intel
+	  Atom E3845 or Celeron N2920 processor.
+
+	  SOM-DB5800 is a COM Express Development board with:
+	    10/100/1000 Ethernet
+	    PCIe slots
+	    4x USB ports
+	    HDMI/DisplayPort/DVI, LVDS, VGA
+	    SATA ports
+	    ALC892 HD Audio Codec
+
+endchoice
+
+source "board/advantech/som-db5800-som-6867/Kconfig"
+
+endif
diff --git a/board/advantech/som-db5800-som-6867/.gitignore b/board/advantech/som-db5800-som-6867/.gitignore
new file mode 100644
index 0000000..6eb8a54
--- /dev/null
+++ b/board/advantech/som-db5800-som-6867/.gitignore
@@ -0,0 +1,3 @@
+dsdt.aml
+dsdt.asl.tmp
+dsdt.c
diff --git a/board/advantech/som-db5800-som-6867/Kconfig b/board/advantech/som-db5800-som-6867/Kconfig
new file mode 100644
index 0000000..f6f3748
--- /dev/null
+++ b/board/advantech/som-db5800-som-6867/Kconfig
@@ -0,0 +1,28 @@
+if TARGET_SOM_DB5800_SOM_6867
+
+config SYS_BOARD
+	default "som-db5800-som-6867"
+
+config SYS_VENDOR
+	default "advantech"
+
+config SYS_SOC
+	default "baytrail"
+
+config SYS_CONFIG_NAME
+	default "som-db5800-som-6867"
+
+config SYS_TEXT_BASE
+	default 0xfff00000 if !EFI_STUB
+	default 0x01110000 if EFI_STUB
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+	select X86_RESET_VECTOR if !EFI_STUB
+	select INTEL_BAYTRAIL
+	select BOARD_ROMSIZE_KB_8192
+
+config PCIE_ECAM_BASE
+	default 0xe0000000
+
+endif
diff --git a/board/advantech/som-db5800-som-6867/MAINTAINERS b/board/advantech/som-db5800-som-6867/MAINTAINERS
new file mode 100644
index 0000000..92989bf
--- /dev/null
+++ b/board/advantech/som-db5800-som-6867/MAINTAINERS
@@ -0,0 +1,7 @@
+Advantech SOM-DB5800-SOM-6867
+M:	George McCollister <george.mccollister@gmail.com>
+S:	Maintained
+F:	board/advantech/som-db5800-som-6867
+F:	include/configs/som-db5800-som-6867.h
+F:	configs/som-db5800-som-6867_defconfig
+F:	arch/x86/dts/baytrail_som-db5800-som-6867.dts
diff --git a/board/advantech/som-db5800-som-6867/Makefile b/board/advantech/som-db5800-som-6867/Makefile
new file mode 100644
index 0000000..9837aa0
--- /dev/null
+++ b/board/advantech/som-db5800-som-6867/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright (C) 2015, Google, Inc
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	+= som-db5800-som-6867.o start.o
+obj-$(CONFIG_GENERATE_ACPI_TABLE) += dsdt.o
diff --git a/board/advantech/som-db5800-som-6867/acpi/mainboard.asl b/board/advantech/som-db5800-som-6867/acpi/mainboard.asl
new file mode 100644
index 0000000..21785ea
--- /dev/null
+++ b/board/advantech/som-db5800-som-6867/acpi/mainboard.asl
@@ -0,0 +1,11 @@
+/*
+ * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/* Power Button */
+Device (PWRB)
+{
+	Name(_HID, EISAID("PNP0C0C"))
+}
diff --git a/board/advantech/som-db5800-som-6867/dsdt.asl b/board/advantech/som-db5800-som-6867/dsdt.asl
new file mode 100644
index 0000000..6042011
--- /dev/null
+++ b/board/advantech/som-db5800-som-6867/dsdt.asl
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+DefinitionBlock("dsdt.aml", "DSDT", 2, "U-BOOT", "U-BOOTBL", 0x00010000)
+{
+	/* platform specific */
+	#include <asm/arch/acpi/platform.asl>
+
+	/* board specific */
+	#include "acpi/mainboard.asl"
+}
diff --git a/board/advantech/som-db5800-som-6867/som-db5800-som-6867.c b/board/advantech/som-db5800-som-6867/som-db5800-som-6867.c
new file mode 100644
index 0000000..5bed2c1
--- /dev/null
+++ b/board/advantech/som-db5800-som-6867/som-db5800-som-6867.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ * Copyright (C) 2016 George McCollister <george.mccollister@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+
+int board_early_init_f(void)
+{
+	/*
+	 * The FSP enables the BayTrail internal legacy UART (again).
+	 * Disable it again, so that the one on the EC can be used.
+	 */
+	setup_internal_uart(0);
+
+	return 0;
+}
+
+int arch_early_init_r(void)
+{
+	return 0;
+}
diff --git a/board/advantech/som-db5800-som-6867/start.S b/board/advantech/som-db5800-som-6867/start.S
new file mode 100644
index 0000000..2c941a4
--- /dev/null
+++ b/board/advantech/som-db5800-som-6867/start.S
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2015, Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+.globl early_board_init
+early_board_init:
+	jmp	early_board_init_ret
diff --git a/board/aristainetos/aristainetos.c b/board/aristainetos/aristainetos.c
index e95ec81..d1e6850 100644
--- a/board/aristainetos/aristainetos.c
+++ b/board/aristainetos/aristainetos.c
@@ -102,7 +102,7 @@
 
 int dram_init(void)
 {
-	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
+	gd->ram_size = imx_ddr_size();
 
 	return 0;
 }
diff --git a/board/armltd/vexpress/Makefile b/board/armltd/vexpress/Makefile
index 1dd6780..95f4ec0 100644
--- a/board/armltd/vexpress/Makefile
+++ b/board/armltd/vexpress/Makefile
@@ -6,3 +6,4 @@
 #
 
 obj-y	:= vexpress_common.o
+obj-$(CONFIG_TARGET_VEXPRESS_CA15_TC2)	+= vexpress_tc2.o
diff --git a/board/armltd/vexpress/vexpress_tc2.c b/board/armltd/vexpress/vexpress_tc2.c
new file mode 100644
index 0000000..ebb41a8
--- /dev/null
+++ b/board/armltd/vexpress/vexpress_tc2.c
@@ -0,0 +1,33 @@
+/*
+ * (C) Copyright 2016 Linaro
+ * Jon Medhurst <tixy@linaro.org>
+ *
+ * TC2 specific code for Versatile Express.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/io.h>
+
+#define SCC_BASE	0x7fff0000
+
+bool armv7_boot_nonsec_default(void)
+{
+#ifdef CONFIG_ARMV7_BOOT_SEC_DEFAULT
+	return false
+#else
+	/*
+	 * The Serial Configuration Controller (SCC) register at address 0x700
+	 * contains flags for configuring the behaviour of the Boot Monitor
+	 * (which CPUs execute from reset). Two of these bits are of interest:
+	 *
+	 * bit 12 = Use per-cpu mailboxes for power management
+	 * bit 13 = Power down the non-boot cluster
+	 *
+	 * It is only when both of these are false that U-Boot's current
+	 * implementation of 'nonsec' mode can work as expected because we
+	 * rely on getting all CPUs to execute _nonsec_init, so let's check that.
+	 */
+	return (readl((u32 *)(SCC_BASE + 0x700)) & ((1 << 12) | (1 << 13))) == 0;
+#endif
+}
diff --git a/board/armltd/vexpress64/vexpress64.c b/board/armltd/vexpress64/vexpress64.c
index 973b579..e34af6c 100644
--- a/board/armltd/vexpress64/vexpress64.c
+++ b/board/armltd/vexpress64/vexpress64.c
@@ -31,13 +31,15 @@
 
 static struct mm_region vexpress64_mem_map[] = {
 	{
-		.base = 0x0UL,
+		.virt = 0x0UL,
+		.phys = 0x0UL,
 		.size = 0x80000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE |
 			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
 	}, {
-		.base = 0x80000000UL,
+		.virt = 0x80000000UL,
+		.phys = 0x80000000UL,
 		.size = 0xff80000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_INNER_SHARE
diff --git a/board/cadence/xtfpga/Kconfig b/board/cadence/xtfpga/Kconfig
new file mode 100644
index 0000000..69296be
--- /dev/null
+++ b/board/cadence/xtfpga/Kconfig
@@ -0,0 +1,39 @@
+if TARGET_XTFPGA
+
+choice
+	prompt "XTFPGA board type select"
+
+config XTFPGA_LX60
+	bool "Support Avnet LX60"
+config XTFPGA_LX110
+	bool "Support Avnet LX110"
+config XTFPGA_LX200
+	bool "Support Avnet LX200"
+config XTFPGA_ML605
+	bool "Support Xilinx ML605"
+config XTFPGA_KC705
+	bool "Support Xilinx KC705"
+
+endchoice
+
+config SYS_BOARD
+	string
+	default "xtfpga"
+
+config SYS_VENDOR
+	string
+	default "cadence"
+
+config SYS_CONFIG_NAME
+	string
+	default "xtfpga"
+
+config BOARD_SDRAM_SIZE
+	hex
+	default 0x04000000 if XTFPGA_LX60
+	default 0x03000000 if XTFPGA_LX110
+	default 0x06000000 if XTFPGA_LX200
+	default 0x18000000 if XTFPGA_ML605
+	default 0x38000000 if XTFPGA_KC705
+
+endif
diff --git a/board/cadence/xtfpga/MAINTAINERS b/board/cadence/xtfpga/MAINTAINERS
new file mode 100644
index 0000000..f4a2b94
--- /dev/null
+++ b/board/cadence/xtfpga/MAINTAINERS
@@ -0,0 +1,7 @@
+XTFPGA BOARD
+M:	Max Filippov <jcmvbkbc@gmail.com>
+S:	Maintained
+F:	board/cadence/xtfpga/
+F:	include/configs/xtfpga.h
+F:	configs/xtfpga_defconfig
+F:	drivers/sysreset/sysreset_xtfpga.c
diff --git a/board/cadence/xtfpga/Makefile b/board/cadence/xtfpga/Makefile
new file mode 100644
index 0000000..fd8f720
--- /dev/null
+++ b/board/cadence/xtfpga/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2007 - 2013, Tensilica Inc.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y				+= ${BOARD}.o
diff --git a/board/cadence/xtfpga/README b/board/cadence/xtfpga/README
new file mode 100644
index 0000000..5f29e25
--- /dev/null
+++ b/board/cadence/xtfpga/README
@@ -0,0 +1,125 @@
+		Tensilica 'xtfpga' Evaluation Boards
+		====================================
+
+Tensilica's 'xtfpga' evaluation boards are actually a set of different
+boards that share configurations. The following is a list of supported
+hardware by this board type:
+
+- XT-AV60  / LX60
+- XT-AV110 / LX110
+- XT-AV200 / LX200
+- ML605
+- KC705
+
+All boards provide the following common configurations:
+
+- An Xtensa or Diamond processor core.
+- An on-chip-debug (OCD) JTAG interface.
+- A 16550 compatible UART and serial port.
+- An OpenCores Wishbone 10/100-base-T ethernet interface.
+- A 32 char two line LCD display. (except for the LX200)
+
+LX60/LX110/LX200:
+
+- Virtex-4 (XC4VLX60 / XCV4LX200) / Virtext-5 (XC5VLX110)
+- 128MB / 64MB (LX60) memory
+- 16MB / 4MB (LX60) Linear Flash
+
+ML605
+
+- Virtex-6 (XC6VLX240T)
+- 512MB DDR3 memory
+- 16MB Linear BPI Flash
+
+KC705 (Xilinx)
+
+- Kintex-7 XC7K325T FPGA
+- 1GB DDR3 memory
+- 128MB Linear BPI Flash
+
+
+Setting up the Board
+--------------------
+
+The serial port defaults to 115200 baud, no parity and 1 stop bit.
+A terminal emulator must be set accordingly to see the U-Boot prompt.
+
+
+Board Configurations LX60/LX110/LX200/ML605/KC705
+-------------------------------------------------
+
+The LX60/LX110/LX200/ML605 contain an 8-way DIP switch that controls
+the boot mapping and selects from a range of default ethernet MAC
+addresses.
+
+Boot Mapping (DIP switch 8):
+
+    DIP switch 8 maps the system ROM address space (in which the
+    reset vector resides) to either SRAM (off, 0, down) or Flash
+    (on, 1, up).  This mapping is implemented in the FPGA bitstream
+    and cannot be disabled by software, therefore DIP switch 8 is no
+    available for application use. Note DIP switch 7 is reserved by
+    Tensilica for future possible hardware use.
+
+    Mapping to SRAM allows U-Boot to be debugged with an OCD/JTAG
+    tool such as the Xtensa OCD Daemon connected via a suppored probe.
+    See the tools documentation for supported probes and how to
+    connect them.  Be aware that the board has only 128 KB of SRAM,
+    therefore U-Boot must fit within this space to debug an image
+    intended for the Flash.  This issues is discussed in a separate
+    section toward the end.
+
+    Mapping to flash allows U-Boot to start on reset, provided it
+    has been programmed into the first two 64 KB sectors of the Flash.
+
+    The Flash is always mapped at a device (memory mapped I/O) address
+    (the address is board specific and is expressed as CFG_FLASH_BASE).
+    The device address is used by U-Boot to program the flash, and may
+    be used to specify an application to run or U-Boot image to boot.
+
+Default MAC Address (DIP switches 1-6):
+
+    When the board is first powered on, or after the environment has
+    been reinitialized, the ethernet MAC address receives a default
+    value whose least significant 6 bits come from DIP switches 1-6.
+    The default is 00:50:C2:13:6F:xx where xx ranges from 0..3F
+    according to the DIP switches, where "on"==1 and "off"==0, and
+    switch 1 is the least-significant bit.
+
+    After initial startup, the MAC address is stored in the U-Boot
+    environment variable 'ethaddr'. The user may change this to any
+    other address with the "setenv" comamnd. After the environment
+    has been saved to Flash by the "saveenv" command, this will be
+    used and the DIP switches no longer consulted. DIP swithes 1-6
+    may then be used for application purposes.
+
+The KC705 board contains 4-way DIP switch, way 1 is the boot mapping
+switch and ways 2-4 control the low three bits of the MAC address.
+
+
+Limitation of SDRAM Size for OCD Debugging on the LX60
+------------------------------------------------------
+
+The XT-AV60 board has only 128 KB of SDRAM that can be mapped
+to the system ROM address space for debugging a ROM image under
+OCD/JTAG. This limits the useful size of U-Boot to 128 KB (0x20000)
+or the first 2 sectors of the flash.
+
+This can pose a problem if all the sources are compiled with -O0
+for debugging. The code size is then too large, in which case it
+would be necessary to temporarily alter the linker script to place
+the load addresses (LMA) in the RAM (VMA) so that OCD loads U-Boot
+directly there and does not unpack. In practice this is not really
+necessary as long as only a limited set of sources need to be
+debugged, because the image can still fit into the 128 KB SRAM.
+
+The recommended procedure for debugging is to first build U-Boot
+with the default optimization level (-Os), and then touch and
+rebuild incrementally with -O0 so that only the touched sources
+are recompiled with -O0. To build with -O0, pass it in the KCFLAGS
+variable to make.
+
+Because this problem is easy to fall into and difficult to debug
+if one doesn't expect it, the linker script provides a link-time
+check and fatal error message if the image size exceeds 128 KB.
+
diff --git a/board/cadence/xtfpga/xtfpga.c b/board/cadence/xtfpga/xtfpga.c
new file mode 100644
index 0000000..5899aa6
--- /dev/null
+++ b/board/cadence/xtfpga/xtfpga.c
@@ -0,0 +1,115 @@
+/*
+ * (C) Copyright 2007 - 2013 Tensilica Inc.
+ * (C) Copyright 2014 - 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm/platdata.h>
+#include <dm/platform_data/net_ethoc.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/stringify.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Check board idendity.
+ * (Print information about the board to stdout.)
+ */
+
+
+#if defined(CONFIG_XTFPGA_LX60)
+const char *board = "XT_AV60";
+const char *description = "Avnet Xilinx LX60 FPGA Evaluation Board / ";
+#elif defined(CONFIG_XTFPGA_LX110)
+const char *board = "XT_AV110";
+const char *description = "Avnet Xilinx Virtex-5 LX110 Evaluation Kit / ";
+#elif defined(CONFIG_XTFPGA_LX200)
+const char *board = "XT_AV200";
+const char *description = "Avnet Xilinx Virtex-4 LX200 Evaluation Kit / ";
+#elif defined(CONFIG_XTFPGA_ML605)
+const char *board = "XT_ML605";
+const char *description = "Xilinx Virtex-6 FPGA ML605 Evaluation Kit / ";
+#elif defined(CONFIG_XTFPGA_KC705)
+const char *board = "XT_KC705";
+const char *description = "Xilinx Kintex-7 FPGA KC705 Evaluation Kit / ";
+#else
+const char *board = "<unknown>";
+const char *description = "";
+#endif
+
+int checkboard(void)
+{
+	printf("Board: %s: %sTensilica bitstream\n", board, description);
+	return 0;
+}
+
+void dram_init_banksize(void)
+{
+	gd->bd->bi_memstart = PHYSADDR(CONFIG_SYS_SDRAM_BASE);
+	gd->bd->bi_memsize = CONFIG_SYS_SDRAM_SIZE;
+}
+
+int board_postclk_init(void)
+{
+	/*
+	 * Obtain CPU clock frequency from board and cache in global
+	 * data structure (Hz). Return 0 on success (OK to continue),
+	 * else non-zero (hang).
+	 */
+
+#ifdef CONFIG_SYS_FPGAREG_FREQ
+	gd->cpu_clk = (*(volatile unsigned long *)CONFIG_SYS_FPGAREG_FREQ);
+#else
+	/* early Tensilica bitstreams lack this reg, but most run at 50 MHz */
+	gd->cpu_clk = 50000000UL;
+#endif
+	return 0;
+}
+
+/*
+ *  Miscellaneous late initializations.
+ *  The environment has been set up, so we can set the Ethernet address.
+ */
+
+int misc_init_r(void)
+{
+#ifdef CONFIG_CMD_NET
+	/*
+	 * Initialize ethernet environment variables and board info.
+	 * Default MAC address comes from CONFIG_ETHADDR + DIP switches 1-6.
+	 */
+
+	char *s = getenv("ethaddr");
+	if (s == 0) {
+		unsigned int x;
+		char s[] = __stringify(CONFIG_ETHBASE);
+		x = (*(volatile u32 *)CONFIG_SYS_FPGAREG_DIPSW)
+			& FPGAREG_MAC_MASK;
+		sprintf(&s[15], "%02x", x);
+		setenv("ethaddr", s);
+	}
+#endif /* CONFIG_CMD_NET */
+
+	return 0;
+}
+
+U_BOOT_DEVICE(sysreset) = {
+	.name = "xtfpga_sysreset",
+};
+
+static struct ethoc_eth_pdata ethoc_pdata = {
+	.eth_pdata = {
+		.iobase = CONFIG_SYS_ETHOC_BASE,
+	},
+	.packet_base = CONFIG_SYS_ETHOC_BUFFER_ADDR,
+};
+
+U_BOOT_DEVICE(ethoc) = {
+	.name = "ethoc",
+	.platdata = &ethoc_pdata,
+};
diff --git a/board/cavium/thunderx/thunderx.c b/board/cavium/thunderx/thunderx.c
index 9131a38..960ca53 100644
--- a/board/cavium/thunderx/thunderx.c
+++ b/board/cavium/thunderx/thunderx.c
@@ -45,16 +45,19 @@
 
 static struct mm_region thunderx_mem_map[] = {
 	{
-		.base = 0x000000000000UL,
+		.virt = 0x000000000000UL,
+		.phys = 0x000000000000UL,
 		.size = 0x40000000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE,
 	}, {
-		.base = 0x800000000000UL,
+		.virt = 0x800000000000UL,
+		.phys = 0x800000000000UL,
 		.size = 0x40000000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE,
 	}, {
-		.base = 0x840000000000UL,
+		.virt = 0x840000000000UL,
+		.phys = 0x840000000000UL,
 		.size = 0x40000000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE,
diff --git a/board/chipspark/popmetal_rk3288/Kconfig b/board/chipspark/popmetal_rk3288/Kconfig
new file mode 100644
index 0000000..a5f4043
--- /dev/null
+++ b/board/chipspark/popmetal_rk3288/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_POPMETAL_RK3288
+
+config SYS_BOARD
+	default "popmetal_rk3288"
+
+config SYS_VENDOR
+	default "chipspark"
+
+config SYS_CONFIG_NAME
+	default "popmetal_rk3288"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+
+endif
diff --git a/board/chipspark/popmetal_rk3288/MAINTAINERS b/board/chipspark/popmetal_rk3288/MAINTAINERS
new file mode 100644
index 0000000..1a6a1bb
--- /dev/null
+++ b/board/chipspark/popmetal_rk3288/MAINTAINERS
@@ -0,0 +1,6 @@
+POPMETAL-RK3288
+M:	Lin Huang <hl@rock-chips.com>
+S:	Maintained
+F:	board/chipspark/popmetal_rk3288
+F:	include/configs/popmetal_rk3288.h
+F:	configs/popmetal-rk3288_defconfig
diff --git a/board/chipspark/popmetal_rk3288/Makefile b/board/chipspark/popmetal_rk3288/Makefile
new file mode 100644
index 0000000..86d66b0
--- /dev/null
+++ b/board/chipspark/popmetal_rk3288/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2016 Rockchip Electronics Co., Ltd
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y	+= popmetal-rk3288.o
diff --git a/board/chipspark/popmetal_rk3288/popmetal-rk3288.c b/board/chipspark/popmetal_rk3288/popmetal-rk3288.c
new file mode 100644
index 0000000..aad74ef
--- /dev/null
+++ b/board/chipspark/popmetal_rk3288/popmetal-rk3288.c
@@ -0,0 +1,15 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <spl.h>
+
+void board_boot_order(u32 *spl_boot_list)
+{
+	/* eMMC prior to sdcard */
+	spl_boot_list[0] = BOOT_DEVICE_MMC2;
+	spl_boot_list[1] = BOOT_DEVICE_MMC1;
+}
diff --git a/board/compulab/cm_fx6/cm_fx6.c b/board/compulab/cm_fx6/cm_fx6.c
index a21e7b0..566c19b 100644
--- a/board/compulab/cm_fx6/cm_fx6.c
+++ b/board/compulab/cm_fx6/cm_fx6.c
@@ -12,6 +12,7 @@
 #include <dm.h>
 #include <fsl_esdhc.h>
 #include <miiphy.h>
+#include <mtd_node.h>
 #include <netdev.h>
 #include <errno.h>
 #include <usb.h>
@@ -28,6 +29,7 @@
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <dm/platform_data/serial_mxc.h>
+#include <jffs2/load_kernel.h>
 #include "common.h"
 #include "../common/eeprom.h"
 #include "../common/common.h"
@@ -581,6 +583,17 @@
 
 #ifdef CONFIG_OF_BOARD_SETUP
 #define USDHC3_PATH	"/soc/aips-bus@02100000/usdhc@02198000/"
+
+struct node_info nodes[] = {
+	/*
+	 * Both entries target the same flash chip. The st,m25p compatible
+	 * is used in the vendor device trees, while upstream uses (the
+	 * documented) jedec,spi-nor comptatible.
+	 */
+	{ "st,m25p",	MTD_DEV_TYPE_NOR,	},
+	{ "jedec,spi-nor",	MTD_DEV_TYPE_NOR,	},
+};
+
 int ft_board_setup(void *blob, bd_t *bd)
 {
 	u32 baseboard_rev;
@@ -589,6 +602,8 @@
 	char baseboard_name[16];
 	int err;
 
+	fdt_shrink_to_minimum(blob); /* Make room for new properties */
+
 	/* MAC addr */
 	if (eth_getenv_enetaddr("ethaddr", enetaddr)) {
 		fdt_find_and_setprop(blob,
@@ -607,15 +622,16 @@
 		return 0; /* Assume not an early revision SB-FX6m baseboard */
 
 	if (!strncmp("SB-FX6m", baseboard_name, 7) && baseboard_rev <= 120) {
-		fdt_shrink_to_minimum(blob); /* Make room for new properties */
 		nodeoffset = fdt_path_offset(blob, USDHC3_PATH);
 		fdt_delprop(blob, nodeoffset, "cd-gpios");
-		fdt_find_and_setprop(blob, USDHC3_PATH, "non-removable",
+		fdt_find_and_setprop(blob, USDHC3_PATH, "broken-cd",
 				     NULL, 0, 1);
 		fdt_find_and_setprop(blob, USDHC3_PATH, "keep-power-in-suspend",
 				     NULL, 0, 1);
 	}
 
+	fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
+
 	return 0;
 }
 #endif
diff --git a/board/congatec/cgtqmx6eval/cgtqmx6eval.c b/board/congatec/cgtqmx6eval/cgtqmx6eval.c
index 225de7c..3fbd3d2 100644
--- a/board/congatec/cgtqmx6eval/cgtqmx6eval.c
+++ b/board/congatec/cgtqmx6eval/cgtqmx6eval.c
@@ -678,14 +678,6 @@
 	return 1;
 }
 
-static bool is_mx6q(void)
-{
-	if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
-		return true;
-	else
-		return false;
-}
-
 int board_early_init_f(void)
 {
 	setup_iomux_uart();
@@ -703,7 +695,7 @@
 	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
 
 
-	if (is_mx6q())
+	if (is_mx6dq())
 		setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6q_i2c_pad_info1);
 	else
 		setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6dl_i2c_pad_info1);
@@ -760,7 +752,7 @@
 int board_late_init(void)
 {
 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
-	if (is_mx6q())
+	if (is_mx6dq())
 		setenv("board_rev", "MX6Q");
 	else
 		setenv("board_rev", "MX6DL");
@@ -1053,7 +1045,7 @@
 		return;
 	}
 
-	if (is_mx6q()) {
+	if (is_mx6dq()) {
 		mx6dq_dram_iocfg(width, &mx6q_ddr_ioregs, &mx6q_grp_ioregs);
 		mx6_dram_cfg(&sysinfo, &mx6q_mmcd_calib, &mem_ddr_2g);
 	} else if (is_cpu_type(MXC_CPU_MX6SOLO)) {
diff --git a/board/congatec/conga-qeval20-qa3-e3845/MAINTAINERS b/board/congatec/conga-qeval20-qa3-e3845/MAINTAINERS
index 5a4d4dc..3d7e8e2 100644
--- a/board/congatec/conga-qeval20-qa3-e3845/MAINTAINERS
+++ b/board/congatec/conga-qeval20-qa3-e3845/MAINTAINERS
@@ -4,4 +4,5 @@
 F:	board/congatec/conga-qeval20-qa3-e3845
 F:	include/configs/conga-qeval20-qa3-e3845.h
 F:	configs/conga-qeval20-qa3-e3845_defconfig
+F:	configs/conga-qeval20-qa3-e3845-internal-uart_defconfig
 F:	arch/x86/dts/conga-qeval20-qa3-e3845.dts
diff --git a/board/congatec/conga-qeval20-qa3-e3845/conga-qeval20-qa3.c b/board/congatec/conga-qeval20-qa3-e3845/conga-qeval20-qa3.c
index 6a946d5..7a5b765 100644
--- a/board/congatec/conga-qeval20-qa3-e3845/conga-qeval20-qa3.c
+++ b/board/congatec/conga-qeval20-qa3-e3845/conga-qeval20-qa3.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <i2c.h>
 #include <winbond_w83627.h>
 #include <asm/gpio.h>
 #include <asm/ibmpc.h>
@@ -12,6 +13,7 @@
 
 int board_early_init_f(void)
 {
+#ifndef CONFIG_INTERNAL_UART
 	/*
 	 * The FSP enables the BayTrail internal legacy UART (again).
 	 * Disable it again, so that the Winbond one can be used.
@@ -21,6 +23,7 @@
 	/* Enable the legacy UART in the Winbond W83627 Super IO chip */
 	winbond_enable_serial(PNP_DEV(WINBOND_IO_PORT, W83627DHG_SP1),
 			      UART0_BASE, UART0_IRQ);
+#endif
 
 	return 0;
 }
@@ -29,3 +32,42 @@
 {
 	return 0;
 }
+
+int board_late_init(void)
+{
+	struct udevice *dev;
+	u8 buf[8];
+	int ret;
+
+	/* Configure SMSC USB2513 USB Hub: 7bit address 0x2c */
+	ret = i2c_get_chip_for_busnum(0, 0x2c, 1, &dev);
+	if (ret) {
+		printf("Cannot find USB2513: %d\n", ret);
+		return 0;
+	}
+
+	/*
+	 * The first access to the USB Hub fails sometimes, so lets read
+	 * a dummy byte to be sure here
+	 */
+	dm_i2c_read(dev, 0x00, buf, 1);
+
+	/*
+	 * The SMSC hub is not visible on the I2C bus after the first
+	 * configuration at power-up. The following code deliberately
+	 * does not report upon failure of these I2C write calls.
+	 */
+	buf[0] = 0x93;
+	dm_i2c_write(dev, 0x06, buf, 1);
+
+	buf[0] = 0xaa;
+	dm_i2c_write(dev, 0xf8, buf, 1);
+
+	buf[0] = 0x0f;
+	dm_i2c_write(dev, 0xfa, buf, 1);
+
+	buf[0] = 0x01;
+	dm_i2c_write(dev, 0xff, buf, 1);
+
+	return 0;
+}
diff --git a/board/dfi/Kconfig b/board/dfi/Kconfig
new file mode 100644
index 0000000..25d0a11
--- /dev/null
+++ b/board/dfi/Kconfig
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+if VENDOR_DFI
+
+choice
+	prompt "Mainboard model"
+	optional
+
+config TARGET_DFI_BT700
+	bool "DFI BT700 BayTrail"
+	help
+	  This is the DFI Q7X-151 baseboard equipped with the
+	  DFI BayTrail Bt700 SoM. It contains an Atom E3845 with
+	  Ethernet (in non-PCIe-x4 configuration), micro-SD, USB 2,
+	  USB 3, SATA, serial console and DisplayPort video out.
+	  It requires some binary blobs - see README.x86 for details.
+
+	  Note that PCIE_ECAM_BASE is set up by the FSP so the value used
+	  by U-Boot matches that value.
+
+endchoice
+
+source "board/dfi/dfi-bt700/Kconfig"
+
+endif
diff --git a/board/dfi/dfi-bt700/Kconfig b/board/dfi/dfi-bt700/Kconfig
new file mode 100644
index 0000000..3f0acb3
--- /dev/null
+++ b/board/dfi/dfi-bt700/Kconfig
@@ -0,0 +1,28 @@
+if TARGET_DFI_BT700
+
+config SYS_BOARD
+	default "dfi-bt700"
+
+config SYS_VENDOR
+	default "dfi"
+
+config SYS_SOC
+	default "baytrail"
+
+config SYS_CONFIG_NAME
+	default "dfi-bt700"
+
+config SYS_TEXT_BASE
+	default 0xfff00000 if !EFI_STUB
+	default 0x01110000 if EFI_STUB
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+	select X86_RESET_VECTOR if !EFI_STUB
+	select INTEL_BAYTRAIL
+	select BOARD_ROMSIZE_KB_8192
+
+config PCIE_ECAM_BASE
+	default 0xe0000000
+
+endif
diff --git a/board/dfi/dfi-bt700/MAINTAINERS b/board/dfi/dfi-bt700/MAINTAINERS
new file mode 100644
index 0000000..6639787
--- /dev/null
+++ b/board/dfi/dfi-bt700/MAINTAINERS
@@ -0,0 +1,10 @@
+congatec DFI-BT700
+M:	Stefan Roese <sr@denx.de>
+S:	Maintained
+F:	board/dfi/dfi-bt700
+F:	include/configs/dfi-bt700.h
+F:	configs/dfi-bt700-q7x-151_defconfig
+F:	configs/theadorable-x86-dfi-bt700_defconfig
+F:	arch/x86/dts/dfi-bt700.dtsi
+F:	arch/x86/dts/dfi-bt700-q7x-151.dts
+F:	arch/x86/dts/theadorable-x86-dfi-bt700.dts
diff --git a/board/dfi/dfi-bt700/Makefile b/board/dfi/dfi-bt700/Makefile
new file mode 100644
index 0000000..8052f5e
--- /dev/null
+++ b/board/dfi/dfi-bt700/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright (C) 2015, Google, Inc
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	+= dfi-bt700.o start.o
+obj-$(CONFIG_GENERATE_ACPI_TABLE) += dsdt.o
diff --git a/board/dfi/dfi-bt700/acpi/mainboard.asl b/board/dfi/dfi-bt700/acpi/mainboard.asl
new file mode 100644
index 0000000..544a049
--- /dev/null
+++ b/board/dfi/dfi-bt700/acpi/mainboard.asl
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/* Power Button */
+Device (PWRB)
+{
+	Name(_HID, EISAID("PNP0C0C"))
+}
+
+/* TODO: Need add Nuvoton SuperIO chipset NCT6102D ASL codes */
diff --git a/board/dfi/dfi-bt700/dfi-bt700.c b/board/dfi/dfi-bt700/dfi-bt700.c
new file mode 100644
index 0000000..8645bdc
--- /dev/null
+++ b/board/dfi/dfi-bt700/dfi-bt700.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <nuvoton_nct6102d.h>
+#include <asm/gpio.h>
+#include <asm/ibmpc.h>
+#include <asm/pnp_def.h>
+
+int board_early_init_f(void)
+{
+#ifdef CONFIG_INTERNAL_UART
+	/* Disable the legacy UART which is enabled per default */
+	nct6102d_uarta_disable();
+#else
+	/*
+	 * The FSP enables the BayTrail internal legacy UART (again).
+	 * Disable it again, so that the Nuvoton one can be used.
+	 */
+	setup_internal_uart(0);
+#endif
+
+	/* Disable the watchdog which is enabled per default */
+	nct6102d_wdt_disable();
+
+	return 0;
+}
diff --git a/board/dfi/dfi-bt700/dsdt.asl b/board/dfi/dfi-bt700/dsdt.asl
new file mode 100644
index 0000000..6042011
--- /dev/null
+++ b/board/dfi/dfi-bt700/dsdt.asl
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+DefinitionBlock("dsdt.aml", "DSDT", 2, "U-BOOT", "U-BOOTBL", 0x00010000)
+{
+	/* platform specific */
+	#include <asm/arch/acpi/platform.asl>
+
+	/* board specific */
+	#include "acpi/mainboard.asl"
+}
diff --git a/board/dfi/dfi-bt700/start.S b/board/dfi/dfi-bt700/start.S
new file mode 100644
index 0000000..2c941a4
--- /dev/null
+++ b/board/dfi/dfi-bt700/start.S
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2015, Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+.globl early_board_init
+early_board_init:
+	jmp	early_board_init_ret
diff --git a/board/el/el6x/Kconfig b/board/el/el6x/Kconfig
new file mode 100644
index 0000000..aa9bf25
--- /dev/null
+++ b/board/el/el6x/Kconfig
@@ -0,0 +1,25 @@
+if TARGET_ZC5202
+
+config SYS_BOARD
+	default "el6x"
+
+config SYS_VENDOR
+	default "el"
+
+config SYS_CONFIG_NAME
+	default "zc5202"
+
+endif
+
+if TARGET_ZC5601
+
+config SYS_BOARD
+	default "el6x"
+
+config SYS_VENDOR
+	default "el"
+
+config SYS_CONFIG_NAME
+	default "zc5601"
+
+endif
diff --git a/board/el/el6x/MAINTAINERS b/board/el/el6x/MAINTAINERS
new file mode 100644
index 0000000..9a40010
--- /dev/null
+++ b/board/el/el6x/MAINTAINERS
@@ -0,0 +1,8 @@
+EL6X BOARD
+M:	Stefano Babic <sbabic@denx.de>
+S:	Maintained
+F:	board/el/el6x/
+F:	include/configs/zc5202.h
+F:	include/configs/zc5601.h
+F:	configs/zc5202_defconfig
+F:	configs/zc5601_defconfig
diff --git a/board/el/el6x/Makefile b/board/el/el6x/Makefile
new file mode 100644
index 0000000..48d5ad9
--- /dev/null
+++ b/board/el/el6x/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) Stefano Babic <sbabic@denx.de>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y  := el6x.o
diff --git a/board/el/el6x/el6x.c b/board/el/el6x/el6x.c
new file mode 100644
index 0000000..3b0fb32
--- /dev/null
+++ b/board/el/el6x/el6x.c
@@ -0,0 +1,640 @@
+/*
+ * Copyright (C) Stefano Babic <sbabic@denx.de>
+ *
+ * Based on other i.MX6 boards
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/errno.h>
+#include <asm/gpio.h>
+#include <asm/imx-common/mxc_i2c.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/boot_mode.h>
+#include <asm/imx-common/video.h>
+#include <mmc.h>
+#include <fsl_esdhc.h>
+#include <miiphy.h>
+#include <netdev.h>
+#include <asm/arch/mxc_hdmi.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/io.h>
+#include <asm/arch/sys_proto.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/pfuze100_pmic.h>
+#include <asm/arch/mx6-ddr.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define OPEN_PAD_CTRL  (PAD_CTL_ODE  | PAD_CTL_DSE_DISABLE | (0 << 12))
+
+#define UART_PAD_CTRL  (PAD_CTL_PUS_100K_UP |			\
+	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm |			\
+	PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
+
+#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP |			\
+	PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm |			\
+	PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
+
+#define ENET_PAD_CTRL  (PAD_CTL_PUS_100K_UP |			\
+	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
+
+#define ENET_PAD_CTRL_PD  (PAD_CTL_PUS_100K_DOWN |		\
+	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
+
+#define ENET_PAD_CTRL_CLK  ((PAD_CTL_PUS_100K_UP & ~PAD_CTL_PKE) | \
+	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
+
+#define SPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_SPEED_MED | \
+	PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
+
+#define I2C_PAD_CTRL  (PAD_CTL_PUS_100K_UP |			\
+	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS |	\
+	PAD_CTL_ODE | PAD_CTL_SRE_FAST)
+
+#define I2C_PMIC	1
+
+#define I2C_PAD MUX_PAD_CTRL(I2C_PAD_CTRL)
+
+#define ETH_PHY_RESET	IMX_GPIO_NR(2, 4)
+
+int dram_init(void)
+{
+	gd->ram_size = imx_ddr_size();
+
+	return 0;
+}
+
+iomux_v3_cfg_t const uart2_pads[] = {
+	MX6_PAD_SD3_DAT5__UART2_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_SD3_DAT4__UART2_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+static void setup_iomux_uart(void)
+{
+	imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
+}
+
+#ifdef CONFIG_TARGET_ZC5202
+iomux_v3_cfg_t const enet_pads[] = {
+	MX6_PAD_GPIO_18__ENET_RX_CLK		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_RXD0__ENET_RX_DATA0	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_RXD1__ENET_RX_DATA1	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_KEY_COL2__ENET_RX_DATA2		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_KEY_COL0__ENET_RX_DATA3		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_CRS_DV__ENET_RX_EN		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_REF_CLK__ENET_TX_CLK	| MUX_PAD_CTRL(ENET_PAD_CTRL_CLK),
+	MX6_PAD_ENET_TXD0__ENET_TX_DATA0	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_TXD1__ENET_TX_DATA1	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_GPIO_19__ENET_TX_ER		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_KEY_ROW2__ENET_TX_DATA2		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_KEY_ROW0__ENET_TX_DATA3		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_TX_EN__ENET_TX_EN		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_RX_ER__ENET_RX_ER		| MUX_PAD_CTRL(ENET_PAD_CTRL_PD),
+	/* Switch Reset */
+	MX6_PAD_NANDF_D4__GPIO2_IO04		| MUX_PAD_CTRL(ENET_PAD_CTRL_PD),
+	/* Switch Interrupt */
+	MX6_PAD_NANDF_D5__GPIO2_IO05		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	/* use CRS and COL pads as GPIOs */
+	MX6_PAD_KEY_COL3__GPIO4_IO12		| MUX_PAD_CTRL(OPEN_PAD_CTRL),
+	MX6_PAD_KEY_ROW1__GPIO4_IO09		| MUX_PAD_CTRL(OPEN_PAD_CTRL),
+
+};
+
+#define BOARD_NAME "EL6x-ZC5202"
+#else
+iomux_v3_cfg_t const enet_pads[] = {
+	MX6_PAD_ENET_MDIO__ENET_MDIO	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_MDC__ENET_MDC	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TXC__RGMII_TXC	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TD0__RGMII_TD0	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TD1__RGMII_TD1	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TD2__RGMII_TD2	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TD3__RGMII_TD3	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_REF_CLK__ENET_TX_CLK	| MUX_PAD_CTRL(ENET_PAD_CTRL_CLK),
+	MX6_PAD_RGMII_RXC__RGMII_RXC	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_RD0__RGMII_RD0	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_RD1__RGMII_RD1	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_RD2__RGMII_RD2	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_RD3__RGMII_RD3	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_NANDF_D4__GPIO2_IO04		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_NANDF_D5__GPIO2_IO05		| MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+#define BOARD_NAME "EL6x-ZC5601"
+#endif
+
+static void setup_iomux_enet(void)
+{
+	imx_iomux_v3_setup_multiple_pads(enet_pads, ARRAY_SIZE(enet_pads));
+
+#ifdef CONFIG_TARGET_ZC5202
+	/* set CRS and COL to input */
+	gpio_direction_input(IMX_GPIO_NR(4, 9));
+	gpio_direction_input(IMX_GPIO_NR(4, 12));
+
+	/* Reset Switch */
+	gpio_direction_output(ETH_PHY_RESET , 0);
+	mdelay(2);
+	gpio_set_value(ETH_PHY_RESET, 1);
+#endif
+}
+
+int board_phy_config(struct phy_device *phydev)
+{
+	if (phydev->drv->config)
+		phydev->drv->config(phydev);
+
+	return 0;
+}
+
+#ifdef CONFIG_MXC_SPI
+#ifdef CONFIG_TARGET_ZC5202
+iomux_v3_cfg_t const ecspi1_pads[] = {
+	MX6_PAD_DISP0_DAT20__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_DISP0_DAT21__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_DISP0_DAT22__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_DISP0_DAT23__GPIO5_IO17  | MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_DISP0_DAT15__GPIO5_IO09  | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const ecspi3_pads[] = {
+	MX6_PAD_DISP0_DAT0__ECSPI3_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_DISP0_DAT2__ECSPI3_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_DISP0_DAT1__ECSPI3_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_DISP0_DAT7__GPIO4_IO28	 | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_DISP0_DAT8__GPIO4_IO29	 | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_DISP0_DAT9__GPIO4_IO30	 | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_DISP0_DAT10__GPIO4_IO31	 | MUX_PAD_CTRL(SPI_PAD_CTRL),
+};
+#endif
+
+iomux_v3_cfg_t const ecspi4_pads[] = {
+	MX6_PAD_EIM_D21__ECSPI4_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_EIM_D28__ECSPI4_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_EIM_D22__ECSPI4_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_EIM_D20__GPIO3_IO20  | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+int board_spi_cs_gpio(unsigned bus, unsigned cs)
+{
+	return (bus == CONFIG_SF_DEFAULT_BUS && cs == CONFIG_SF_DEFAULT_CS)
+		? (IMX_GPIO_NR(3, 20)) : -1;
+}
+
+static void setup_spi(void)
+{
+#ifdef CONFIG_TARGET_ZC5202
+	gpio_request(IMX_GPIO_NR(5, 17), "spi_cs0");
+	gpio_request(IMX_GPIO_NR(5, 9), "spi_cs1");
+	gpio_direction_output(IMX_GPIO_NR(5, 17), 1);
+	gpio_direction_output(IMX_GPIO_NR(5, 9), 1);
+	imx_iomux_v3_setup_multiple_pads(ecspi1_pads, ARRAY_SIZE(ecspi1_pads));
+#endif
+
+	gpio_request(IMX_GPIO_NR(3, 20), "spi4_cs0");
+	gpio_direction_output(IMX_GPIO_NR(3, 20), 1);
+	imx_iomux_v3_setup_multiple_pads(ecspi4_pads, ARRAY_SIZE(ecspi4_pads));
+
+	enable_spi_clk(true, 3);
+}
+#endif
+
+static struct i2c_pads_info i2c_pad_info1 = {
+	.scl = {
+		.i2c_mode = MX6_PAD_EIM_EB2__I2C2_SCL | I2C_PAD,
+		.gpio_mode = MX6_PAD_EIM_EB2__GPIO2_IO30 | I2C_PAD,
+		.gp = IMX_GPIO_NR(2, 30)
+	},
+	.sda = {
+		.i2c_mode = MX6_PAD_KEY_ROW3__I2C2_SDA | I2C_PAD,
+		.gpio_mode = MX6_PAD_KEY_ROW3__GPIO4_IO13 | I2C_PAD,
+		.gp = IMX_GPIO_NR(4, 13)
+	}
+};
+
+static struct i2c_pads_info i2c_pad_info2 = {
+	.scl = {
+		.i2c_mode = MX6_PAD_GPIO_5__I2C3_SCL | I2C_PAD,
+		.gpio_mode = MX6_PAD_GPIO_5__GPIO1_IO05 | I2C_PAD,
+		.gp = IMX_GPIO_NR(1, 5)
+	},
+	.sda = {
+		.i2c_mode = MX6_PAD_GPIO_16__I2C3_SDA | I2C_PAD,
+		.gpio_mode = MX6_PAD_GPIO_16__GPIO7_IO11 | I2C_PAD,
+		.gp = IMX_GPIO_NR(7, 11)
+	}
+};
+
+iomux_v3_cfg_t const usdhc2_pads[] = {
+	MX6_PAD_SD2_CLK__SD2_CLK	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD2_CMD__SD2_CMD	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD2_DAT0__SD2_DATA0	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD2_DAT1__SD2_DATA1	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD2_DAT2__SD2_DATA2	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD2_DAT3__SD2_DATA3	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_GPIO_4__SD2_CD_B	| MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
+};
+
+iomux_v3_cfg_t const usdhc4_pads[] = {
+	MX6_PAD_SD4_CLK__SD4_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_CMD__SD4_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT0__SD4_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT1__SD4_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT2__SD4_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT3__SD4_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT4__SD4_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT5__SD4_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT6__SD4_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT7__SD4_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+};
+
+#ifdef CONFIG_FSL_ESDHC
+struct fsl_esdhc_cfg usdhc_cfg[2] = {
+	{USDHC2_BASE_ADDR},
+	{USDHC4_BASE_ADDR},
+};
+
+#define USDHC2_CD_GPIO	IMX_GPIO_NR(1, 4)
+
+int board_mmc_getcd(struct mmc *mmc)
+{
+	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+	int ret = 0;
+
+	switch (cfg->esdhc_base) {
+	case USDHC2_BASE_ADDR:
+		ret = !gpio_get_value(USDHC2_CD_GPIO);
+		break;
+	case USDHC4_BASE_ADDR:
+		ret = 1; /* eMMC/uSDHC4 is always present */
+		break;
+	}
+
+	return ret;
+}
+
+int board_mmc_init(bd_t *bis)
+{
+#ifndef CONFIG_SPL_BUILD
+	int ret;
+	int i;
+
+	/*
+	 * According to the board_mmc_init() the following map is done:
+	 * (U-boot device node)    (Physical Port)
+	 * mmc0                    SD2
+	 * mmc1                    SD3
+	 * mmc2                    eMMC
+	 */
+	for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) {
+		switch (i) {
+		case 0:
+			imx_iomux_v3_setup_multiple_pads(
+				usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
+			gpio_direction_input(USDHC2_CD_GPIO);
+			usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
+			break;
+		case 1:
+			imx_iomux_v3_setup_multiple_pads(
+				usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
+			usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
+			break;
+		default:
+			printf("Warning: you configured more USDHC controllers"
+			       "(%d) then supported by the board (%d)\n",
+			       i + 1, CONFIG_SYS_FSL_USDHC_NUM);
+			return -EINVAL;
+		}
+
+		ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+#else
+	struct src *psrc = (struct src *)SRC_BASE_ADDR;
+	unsigned reg = readl(&psrc->sbmr1) >> 11;
+
+	/*
+	 * Upon reading BOOT_CFG register the following map is done:
+	 * Bit 11 and 12 of BOOT_CFG register can determine the current
+	 * mmc port
+	 * 0x1                  SD1
+	 * 0x2                  SD2
+	 * 0x3                  SD4
+	 */
+
+	switch (reg & 0x3) {
+	case 0x1:
+		imx_iomux_v3_setup_multiple_pads(
+			usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
+		usdhc_cfg[0].esdhc_base = USDHC2_BASE_ADDR;
+		usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
+		gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk;
+		break;
+	case 0x3:
+		imx_iomux_v3_setup_multiple_pads(
+			usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
+		usdhc_cfg[0].esdhc_base = USDHC4_BASE_ADDR;
+		usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
+		gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk;
+		break;
+	}
+
+	return fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
+#endif
+
+}
+#endif
+
+
+/*
+ * Do not overwrite the console
+ * Use always serial for U-Boot console
+ */
+int overwrite_console(void)
+{
+	return 1;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	setup_iomux_enet();
+	enable_enet_clk(1);
+
+	return cpu_eth_init(bis);
+}
+
+int board_early_init_f(void)
+{
+
+	setup_iomux_uart();
+	setup_spi();
+
+	return 0;
+}
+
+int board_init(void)
+{
+	/* address of boot parameters */
+	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
+
+	setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
+	setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
+
+	return 0;
+}
+
+int power_init_board(void)
+{
+	struct pmic *p;
+	int ret;
+	unsigned int reg;
+
+	ret = power_pfuze100_init(I2C_PMIC);
+	if (ret)
+		return ret;
+
+	p = pmic_get("PFUZE100");
+	ret = pmic_probe(p);
+	if (ret)
+		return ret;
+
+	pmic_reg_read(p, PFUZE100_DEVICEID, &reg);
+	printf("PMIC:  PFUZE100 ID=0x%02x\n", reg);
+
+	/* Increase VGEN3 from 2.5 to 2.8V */
+	pmic_reg_read(p, PFUZE100_VGEN3VOL, &reg);
+	reg &= ~LDO_VOL_MASK;
+	reg |= LDOB_2_80V;
+	pmic_reg_write(p, PFUZE100_VGEN3VOL, reg);
+
+	/* Increase VGEN5 from 2.8 to 3V */
+	pmic_reg_read(p, PFUZE100_VGEN5VOL, &reg);
+	reg &= ~LDO_VOL_MASK;
+	reg |= LDOB_3_00V;
+	pmic_reg_write(p, PFUZE100_VGEN5VOL, reg);
+
+	/* Set SW1AB stanby volage to 0.975V */
+	pmic_reg_read(p, PFUZE100_SW1ABSTBY, &reg);
+	reg &= ~SW1x_STBY_MASK;
+	reg |= SW1x_0_975V;
+	pmic_reg_write(p, PFUZE100_SW1ABSTBY, reg);
+
+	/* Set SW1AB/VDDARM step ramp up time from 16us to 4us/25mV */
+	pmic_reg_read(p, PFUZE100_SW1ABCONF, &reg);
+	reg &= ~SW1xCONF_DVSSPEED_MASK;
+	reg |= SW1xCONF_DVSSPEED_4US;
+	pmic_reg_write(p, PFUZE100_SW1ABCONF, reg);
+
+	/* Set SW1C standby voltage to 0.975V */
+	pmic_reg_read(p, PFUZE100_SW1CSTBY, &reg);
+	reg &= ~SW1x_STBY_MASK;
+	reg |= SW1x_0_975V;
+	pmic_reg_write(p, PFUZE100_SW1CSTBY, reg);
+
+	/* Set SW1C/VDDSOC step ramp up time from 16us to 4us/25mV */
+	pmic_reg_read(p, PFUZE100_SW1CCONF, &reg);
+	reg &= ~SW1xCONF_DVSSPEED_MASK;
+	reg |= SW1xCONF_DVSSPEED_4US;
+	pmic_reg_write(p, PFUZE100_SW1CCONF, reg);
+
+	return 0;
+}
+
+#ifdef CONFIG_CMD_BMODE
+static const struct boot_mode board_boot_modes[] = {
+	/* 4 bit bus width */
+	{"sd2",	 MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
+	/* 8 bit bus width */
+	{"emmc", MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)},
+	{NULL,	 0},
+};
+#endif
+
+int board_late_init(void)
+{
+#ifdef CONFIG_CMD_BMODE
+	add_board_boot_modes(board_boot_modes);
+#endif
+
+	setenv("board_name", BOARD_NAME);
+	return 0;
+}
+
+int checkboard(void)
+{
+	puts("Board: ");
+	puts(BOARD_NAME "\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_SPL_BUILD
+#include <spl.h>
+#include <libfdt.h>
+
+const struct mx6dq_iomux_ddr_regs mx6_ddr_ioregs = {
+	.dram_sdclk_0 =  0x00020030,
+	.dram_sdclk_1 =  0x00020030,
+	.dram_cas =  0x00020030,
+	.dram_ras =  0x00020030,
+	.dram_reset =  0x00020030,
+	.dram_sdcke0 =  0x00003000,
+	.dram_sdcke1 =  0x00003000,
+	.dram_sdba2 =  0x00000000,
+	.dram_sdodt0 =  0x00003030,
+	.dram_sdodt1 =  0x00003030,
+	.dram_sdqs0 =  0x00000030,
+	.dram_sdqs1 =  0x00000030,
+	.dram_sdqs2 =  0x00000030,
+	.dram_sdqs3 =  0x00000030,
+	.dram_sdqs4 =  0x00000030,
+	.dram_sdqs5 =  0x00000030,
+	.dram_sdqs6 =  0x00000030,
+	.dram_sdqs7 =  0x00000030,
+	.dram_dqm0 =  0x00020030,
+	.dram_dqm1 =  0x00020030,
+	.dram_dqm2 =  0x00020030,
+	.dram_dqm3 =  0x00020030,
+	.dram_dqm4 =  0x00020030,
+	.dram_dqm5 =  0x00020030,
+	.dram_dqm6 =  0x00020030,
+	.dram_dqm7 =  0x00020030,
+};
+
+const struct mx6dq_iomux_grp_regs mx6_grp_ioregs = {
+	.grp_ddr_type =  0x000C0000,
+	.grp_ddrmode_ctl =  0x00020000,
+	.grp_ddrpke =  0x00000000,
+	.grp_addds =  0x00000030,
+	.grp_ctlds =  0x00000030,
+	.grp_ddrmode =  0x00020000,
+	.grp_b0ds =  0x00000030,
+	.grp_b1ds =  0x00000030,
+	.grp_b2ds =  0x00000030,
+	.grp_b3ds =  0x00000030,
+	.grp_b4ds =  0x00000030,
+	.grp_b5ds =  0x00000030,
+	.grp_b6ds =  0x00000030,
+	.grp_b7ds =  0x00000030,
+};
+
+const struct mx6_mmdc_calibration mx6_mmcd_calib = {
+	.p0_mpwldectrl0 =  0x001F001F,
+	.p0_mpwldectrl1 =  0x001F001F,
+	.p1_mpwldectrl0 =  0x00440044,
+	.p1_mpwldectrl1 =  0x00440044,
+	.p0_mpdgctrl0 =  0x434B0350,
+	.p0_mpdgctrl1 =  0x034C0359,
+	.p1_mpdgctrl0 =  0x434B0350,
+	.p1_mpdgctrl1 =  0x03650348,
+	.p0_mprddlctl =  0x4436383B,
+	.p1_mprddlctl =  0x39393341,
+	.p0_mpwrdlctl =  0x35373933,
+	.p1_mpwrdlctl =  0x48254A36,
+};
+
+/* MT41K128M16JT-125 */
+static struct mx6_ddr3_cfg mem_ddr = {
+	.mem_speed = 1600,
+	.density = 2,
+	.width = 16,
+	.banks = 8,
+	.rowaddr = 14,
+	.coladdr = 10,
+	.pagesz = 2,
+	.trcd = 1375,
+	.trcmin = 4875,
+	.trasmin = 3500,
+};
+
+static void ccgr_init(void)
+{
+	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+	writel(0x00C03F3F, &ccm->CCGR0);
+	writel(0x0030FC03, &ccm->CCGR1);
+	writel(0x0FFFC000, &ccm->CCGR2);
+	writel(0x3FF00000, &ccm->CCGR3);
+	writel(0x00FFF300, &ccm->CCGR4);
+	writel(0x0F0000C3, &ccm->CCGR5);
+	writel(0x000003FF, &ccm->CCGR6);
+}
+
+static void gpr_init(void)
+{
+	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+
+	/* enable AXI cache for VDOA/VPU/IPU */
+	writel(0xF00000CF, &iomux->gpr[4]);
+	/* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
+	writel(0x007F007F, &iomux->gpr[6]);
+	writel(0x007F007F, &iomux->gpr[7]);
+}
+
+/*
+ * This section requires the differentiation between iMX6 Sabre boards, but
+ * for now, it will configure only for the mx6q variant.
+ */
+static void spl_dram_init(void)
+{
+	struct mx6_ddr_sysinfo sysinfo = {
+		/* width of data bus:0=16,1=32,2=64 */
+		.dsize = 2,
+		/* config for full 4GB range so that get_mem_size() works */
+		.cs_density = 32, /* 32Gb per CS */
+		/* single chip select */
+		.ncs = 1,
+		.cs1_mirror = 0,
+		.rtt_wr = 1 /*DDR3_RTT_60_OHM*/,	/* RTT_Wr = RZQ/4 */
+		.rtt_nom = 1 /*DDR3_RTT_60_OHM*/,	/* RTT_Nom = RZQ/4 */
+		.walat = 1,	/* Write additional latency */
+		.ralat = 5,	/* Read additional latency */
+		.mif3_mode = 3,	/* Command prediction working mode */
+		.bi_on = 1,	/* Bank interleaving enabled */
+		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
+		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+		.ddr_type = DDR_TYPE_DDR3,
+	};
+
+	mx6dq_dram_iocfg(64, &mx6_ddr_ioregs, &mx6_grp_ioregs);
+	mx6_dram_cfg(&sysinfo, &mx6_mmcd_calib, &mem_ddr);
+}
+
+void board_init_f(ulong dummy)
+{
+	/* setup AIPS and disable watchdog */
+	arch_cpu_init();
+
+	ccgr_init();
+	gpr_init();
+
+	/* iomux and setup of i2c */
+	board_early_init_f();
+
+	/* setup GP timer */
+	timer_init();
+
+	/* UART clocks enabled and gd valid - init serial console */
+	preloader_console_init();
+
+	/* DDR initialization */
+	spl_dram_init();
+
+	/* Clear the BSS. */
+	memset(__bss_start, 0, __bss_end - __bss_start);
+
+	/* load/boot image from boot device */
+	board_init_r(NULL, 0);
+}
+
+#endif
diff --git a/board/evb_rk3036/evb_rk3036/evb_rk3036.c b/board/evb_rk3036/evb_rk3036/evb_rk3036.c
deleted file mode 100644
index f5758b1..0000000
--- a/board/evb_rk3036/evb_rk3036/evb_rk3036.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * (C) Copyright 2015 Rockchip Electronics Co., Ltd
- *
- * SPDX-License-Identifier:     GPL-2.0+
- */
-
-#include <common.h>
-#include <dm.h>
-#include <asm/io.h>
-#include <asm/arch/uart.h>
-#include <asm/arch/sdram_rk3036.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-void get_ddr_config(struct rk3036_ddr_config *config)
-{
-	/* K4B4G1646Q config */
-	config->ddr_type = 3;
-	config->rank = 2;
-	config->cs0_row = 15;
-	config->cs1_row = 15;
-
-	/* 8bank */
-	config->bank = 3;
-	config->col = 10;
-
-	/* 16bit bw */
-	config->bw = 1;
-}
-
-int board_init(void)
-{
-	return 0;
-}
-
-int dram_init(void)
-{
-	gd->ram_size = sdram_size();
-
-	return 0;
-}
-
-#ifndef CONFIG_SYS_DCACHE_OFF
-void enable_caches(void)
-{
-	/* Enable D-cache. I-cache is already enabled in start.S */
-	dcache_enable();
-}
-#endif
diff --git a/board/freescale/b4860qds/MAINTAINERS b/board/freescale/b4860qds/MAINTAINERS
index ac02bb7..97304c5 100644
--- a/board/freescale/b4860qds/MAINTAINERS
+++ b/board/freescale/b4860qds/MAINTAINERS
@@ -12,6 +12,6 @@
 F:	configs/B4860QDS_SRIO_PCIE_BOOT_defconfig
 
 B4860QDS_SECURE_BOOT BOARD
-M:	Aneesh Bansal <aneesh.bansal@freescale.com>
+M:	Ruchika Gupta <ruchika.gupta@nxp.com>
 S:	Maintained
 F:	configs/B4860QDS_SECURE_BOOT_defconfig
diff --git a/board/freescale/bsc9132qds/MAINTAINERS b/board/freescale/bsc9132qds/MAINTAINERS
index 3de62d3..c58fc50 100644
--- a/board/freescale/bsc9132qds/MAINTAINERS
+++ b/board/freescale/bsc9132qds/MAINTAINERS
@@ -13,7 +13,7 @@
 F:	configs/BSC9132QDS_SPIFLASH_DDRCLK133_defconfig
 
 BSC9132QDS_NAND_DDRCLK100_SECURE BOARD
-M:	Aneesh Bansal <aneesh.bansal@freescale.com>
+M:	Ruchika Gupta <ruchika.gupta@nxp.com>
 S:	Maintained
 F:	configs/BSC9132QDS_NAND_DDRCLK100_SECURE_defconfig
 F:	configs/BSC9132QDS_NAND_DDRCLK133_SECURE_defconfig
diff --git a/board/freescale/common/fsl_chain_of_trust.c b/board/freescale/common/fsl_chain_of_trust.c
index ecfcc82..dea231b 100644
--- a/board/freescale/common/fsl_chain_of_trust.c
+++ b/board/freescale/common/fsl_chain_of_trust.c
@@ -6,7 +6,21 @@
 
 #include <common.h>
 #include <fsl_validate.h>
+#include <fsl_secboot_err.h>
 #include <fsl_sfp.h>
+#include <dm/root.h>
+
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_FRAMEWORK)
+#include <spl.h>
+#endif
+
+#ifdef CONFIG_ADDR_MAP
+#include <asm/mmu.h>
+#endif
+
+#ifdef CONFIG_FSL_CORENET
+#include <asm/fsl_pamu.h>
+#endif
 
 #ifdef CONFIG_LS102XA
 #include <asm/arch/immap_ls102xa.h>
@@ -52,6 +66,7 @@
 	return 0;
 }
 
+#ifndef CONFIG_SPL_BUILD
 int fsl_setenv_chain_of_trust(void)
 {
 	/* Check Boot Mode
@@ -68,3 +83,76 @@
 	setenv("bootcmd", CONFIG_CHAIN_BOOT_CMD);
 	return 0;
 }
+#endif
+
+#ifdef CONFIG_SPL_BUILD
+void spl_validate_uboot(uint32_t hdr_addr, uintptr_t img_addr)
+{
+	int res;
+
+	/*
+	 * Check Boot Mode
+	 * If Boot Mode is Non-Secure, skip validation
+	 */
+	if (fsl_check_boot_mode_secure() == 0)
+		return;
+
+	printf("SPL: Validating U-Boot image\n");
+
+#ifdef CONFIG_ADDR_MAP
+	init_addr_map();
+#endif
+
+#ifdef CONFIG_FSL_CORENET
+	if (pamu_init() < 0)
+		fsl_secboot_handle_error(ERROR_ESBC_PAMU_INIT);
+#endif
+
+#ifdef CONFIG_FSL_CAAM
+	if (sec_init() < 0)
+		fsl_secboot_handle_error(ERROR_ESBC_SEC_INIT);
+#endif
+
+/*
+ * dm_init_and_scan() is called as part of common SPL framework, so no
+ * need to call it again but in case of powerpc platforms which currently
+ * do not use common SPL framework, so need to call this function here.
+ */
+#if defined(CONFIG_SPL_DM) && (!defined(CONFIG_SPL_FRAMEWORK))
+	dm_init_and_scan(true);
+#endif
+	res = fsl_secboot_validate(hdr_addr, CONFIG_SPL_UBOOT_KEY_HASH,
+				   &img_addr);
+
+	if (res == 0)
+		printf("SPL: Validation of U-boot successful\n");
+}
+
+#ifdef CONFIG_SPL_FRAMEWORK
+/* Override weak funtion defined in SPL framework to enable validation
+ * of main u-boot image before jumping to u-boot image.
+ */
+void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
+{
+	typedef void __noreturn (*image_entry_noargs_t)(void);
+	uint32_t hdr_addr;
+
+	image_entry_noargs_t image_entry =
+		(image_entry_noargs_t)(unsigned long)spl_image->entry_point;
+
+	hdr_addr = (spl_image->entry_point + spl_image->size -
+			CONFIG_U_BOOT_HDR_SIZE);
+	spl_validate_uboot(hdr_addr, (uintptr_t)spl_image->entry_point);
+	/*
+	 * In case of failure in validation, spl_validate_uboot would
+	 * not return back in case of Production environment with ITS=1.
+	 * Thus U-Boot will not start.
+	 * In Development environment (ITS=0 and SB_EN=1), the function
+	 * may return back in case of non-fatal failures.
+	 */
+
+	debug("image entry point: 0x%X\n", spl_image->entry_point);
+	image_entry();
+}
+#endif /* ifdef CONFIG_SPL_FRAMEWORK */
+#endif /* ifdef CONFIG_SPL_BUILD */
diff --git a/board/freescale/corenet_ds/MAINTAINERS b/board/freescale/corenet_ds/MAINTAINERS
index 73b0553..708e812 100644
--- a/board/freescale/corenet_ds/MAINTAINERS
+++ b/board/freescale/corenet_ds/MAINTAINERS
@@ -30,7 +30,7 @@
 F:	configs/P5040DS_SECURE_BOOT_defconfig
 
 CORENET_DS_SECURE_BOOT BOARD
-M:	Aneesh Bansal <aneesh.bansal@freescale.com>
+M:	Ruchika Gupta <ruchika.gupta@nxp.com>
 S:	Maintained
 F:	configs/P3041DS_NAND_SECURE_BOOT_defconfig
 F:	configs/P5020DS_NAND_SECURE_BOOT_defconfig
diff --git a/board/freescale/ls1021aqds/Makefile b/board/freescale/ls1021aqds/Makefile
index ab02344..f0390c1 100644
--- a/board/freescale/ls1021aqds/Makefile
+++ b/board/freescale/ls1021aqds/Makefile
@@ -8,3 +8,4 @@
 obj-y += ddr.o
 obj-y += eth.o
 obj-$(CONFIG_FSL_DCU_FB) += dcu.o
+obj-$(CONFIG_ARMV7_PSCI) += psci.o
diff --git a/board/freescale/ls1021aqds/psci.S b/board/freescale/ls1021aqds/psci.S
new file mode 100644
index 0000000..598168c
--- /dev/null
+++ b/board/freescale/ls1021aqds/psci.S
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2016 NXP Semiconductor.
+ * Author: Wang Dongsheng <dongsheng.wang@freescale.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+
+#include <asm/armv7.h>
+#include <asm/psci.h>
+
+	.pushsection ._secure.text, "ax"
+
+	.arch_extension sec
+
+	.align	5
+
+.globl	psci_system_off
+psci_system_off:
+	@ Get QIXIS base address
+	movw	r1, #(QIXIS_BASE & 0xffff)
+	movt	r1, #(QIXIS_BASE >> 16)
+
+	ldrb	r2, [r1, #QIXIS_PWR_CTL]
+	orr	r2, r2, #QIXIS_PWR_CTL_POWEROFF
+	strb	r2, [r1, #QIXIS_PWR_CTL]
+
+1:	wfi
+	b	1b
+
+	.popsection
diff --git a/board/freescale/ls1021atwr/MAINTAINERS b/board/freescale/ls1021atwr/MAINTAINERS
index b997bb0..06d888f 100644
--- a/board/freescale/ls1021atwr/MAINTAINERS
+++ b/board/freescale/ls1021atwr/MAINTAINERS
@@ -9,3 +9,7 @@
 F:	configs/ls1021atwr_sdcard_ifc_defconfig
 F:	configs/ls1021atwr_sdcard_qspi_defconfig
 F:	configs/ls1021atwr_qspi_defconfig
+
+M:	Sumit Garg <sumit.garg@nxp.com>
+S:	Maintained
+F:	configs/ls1021atwr_sdcard_ifc_SECURE_BOOT_defconfig
diff --git a/board/freescale/ls1021atwr/Makefile b/board/freescale/ls1021atwr/Makefile
index 01296c0..5238b15 100644
--- a/board/freescale/ls1021atwr/Makefile
+++ b/board/freescale/ls1021atwr/Makefile
@@ -6,3 +6,4 @@
 
 obj-y += ls1021atwr.o
 obj-$(CONFIG_FSL_DCU_FB) += dcu.o
+obj-$(CONFIG_ARMV7_PSCI) += psci.o
diff --git a/board/freescale/ls1021atwr/ls1021atwr.c b/board/freescale/ls1021atwr/ls1021atwr.c
index c69c9cb..77482a9 100644
--- a/board/freescale/ls1021atwr/ls1021atwr.c
+++ b/board/freescale/ls1021atwr/ls1021atwr.c
@@ -503,6 +503,13 @@
 	return 0;
 }
 
+#if defined(CONFIG_SPL_BUILD)
+void spl_board_init(void)
+{
+	ls102xa_smmu_stream_id_init();
+}
+#endif
+
 #ifdef CONFIG_BOARD_LATE_INIT
 int board_late_init(void)
 {
diff --git a/board/freescale/ls1021atwr/psci.S b/board/freescale/ls1021atwr/psci.S
new file mode 100644
index 0000000..bec7356
--- /dev/null
+++ b/board/freescale/ls1021atwr/psci.S
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016 NXP Semiconductor.
+ * Author: Wang Dongsheng <dongsheng.wang@freescale.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+
+#include <asm/armv7.h>
+#include <asm/psci.h>
+
+	.pushsection ._secure.text, "ax"
+
+	.arch_extension sec
+
+	.align	5
+
+.globl	psci_system_off
+psci_system_off:
+1:	wfi
+	b	1b
+
+	.popsection
diff --git a/board/freescale/ls1043aqds/MAINTAINERS b/board/freescale/ls1043aqds/MAINTAINERS
index 65a0af1..992c54c 100644
--- a/board/freescale/ls1043aqds/MAINTAINERS
+++ b/board/freescale/ls1043aqds/MAINTAINERS
@@ -9,3 +9,4 @@
 F:	configs/ls1043aqds_sdcard_ifc_defconfig
 F:	configs/ls1043aqds_sdcard_qspi_defconfig
 F:	configs/ls1043aqds_qspi_defconfig
+F:	configs/ls1043aqds_lpuart_defconfig
diff --git a/board/freescale/ls1043aqds/ddr.c b/board/freescale/ls1043aqds/ddr.c
index 0fd835d..d4540d0 100644
--- a/board/freescale/ls1043aqds/ddr.c
+++ b/board/freescale/ls1043aqds/ddr.c
@@ -128,7 +128,7 @@
 void dram_init_banksize(void)
 {
 	/*
-	 * gd->secure_ram tracks the location of secure memory.
+	 * gd->arch.secure_ram tracks the location of secure memory.
 	 * It was set as if the memory starts from 0.
 	 * The address needs to add the offset of its bank.
 	 */
@@ -139,16 +139,17 @@
 		gd->bd->bi_dram[1].size = gd->ram_size -
 					  CONFIG_SYS_DDR_BLOCK1_SIZE;
 #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
-		gd->secure_ram = gd->bd->bi_dram[1].start +
-				 gd->secure_ram -
-				 CONFIG_SYS_DDR_BLOCK1_SIZE;
-		gd->secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
+		gd->arch.secure_ram = gd->bd->bi_dram[1].start +
+				      gd->arch.secure_ram -
+				      CONFIG_SYS_DDR_BLOCK1_SIZE;
+		gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
 #endif
 	} else {
 		gd->bd->bi_dram[0].size = gd->ram_size;
 #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
-		gd->secure_ram = gd->bd->bi_dram[0].start + gd->secure_ram;
-		gd->secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
+		gd->arch.secure_ram = gd->bd->bi_dram[0].start +
+				      gd->arch.secure_ram;
+		gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
 #endif
 	}
 }
diff --git a/board/freescale/ls1043aqds/ls1043aqds.c b/board/freescale/ls1043aqds/ls1043aqds.c
index b7e9c21..941dfbc 100644
--- a/board/freescale/ls1043aqds/ls1043aqds.c
+++ b/board/freescale/ls1043aqds/ls1043aqds.c
@@ -327,6 +327,7 @@
 {
 	u64 base[CONFIG_NR_DRAM_BANKS];
 	u64 size[CONFIG_NR_DRAM_BANKS];
+	u8 reg;
 
 	/* fixup DT for the two DDR banks */
 	base[0] = gd->bd->bi_dram[0].start;
@@ -341,6 +342,15 @@
 	fdt_fixup_fman_ethernet(blob);
 	fdt_fixup_board_enet(blob);
 #endif
+
+	reg = QIXIS_READ(brdcfg[0]);
+	reg = (reg & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT;
+
+	/* Disable IFC if QSPI is enabled */
+	if (reg == 0xF)
+		do_fixup_by_compat(blob, "fsl,ifc",
+				   "status", "disabled", 8 + 1, 1);
+
 	return 0;
 }
 #endif
diff --git a/board/freescale/ls1043ardb/MAINTAINERS b/board/freescale/ls1043ardb/MAINTAINERS
index 84ffb63..0503a3f 100644
--- a/board/freescale/ls1043ardb/MAINTAINERS
+++ b/board/freescale/ls1043ardb/MAINTAINERS
@@ -9,6 +9,6 @@
 F:	configs/ls1043ardb_sdcard_defconfig
 
 LS1043A_SECURE_BOOT BOARD
-M:	Aneesh Bansal <aneesh.bansal@freescale.com>
+M:	Ruchika Gupta <ruchika.gupta@nxp.com>
 S:	Maintained
 F:	configs/ls1043ardb_SECURE_BOOT_defconfig
diff --git a/board/freescale/ls1043ardb/ddr.c b/board/freescale/ls1043ardb/ddr.c
index 1e2fd2e..61b1cc4 100644
--- a/board/freescale/ls1043ardb/ddr.c
+++ b/board/freescale/ls1043ardb/ddr.c
@@ -189,7 +189,7 @@
 void dram_init_banksize(void)
 {
 	/*
-	 * gd->secure_ram tracks the location of secure memory.
+	 * gd->arch.secure_ram tracks the location of secure memory.
 	 * It was set as if the memory starts from 0.
 	 * The address needs to add the offset of its bank.
 	 */
@@ -200,16 +200,17 @@
 		gd->bd->bi_dram[1].size = gd->ram_size -
 					  CONFIG_SYS_DDR_BLOCK1_SIZE;
 #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
-		gd->secure_ram = gd->bd->bi_dram[1].start +
-				 gd->secure_ram -
-				 CONFIG_SYS_DDR_BLOCK1_SIZE;
-		gd->secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
+		gd->arch.secure_ram = gd->bd->bi_dram[1].start +
+				      gd->arch.secure_ram -
+				      CONFIG_SYS_DDR_BLOCK1_SIZE;
+		gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
 #endif
 	} else {
 		gd->bd->bi_dram[0].size = gd->ram_size;
 #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
-		gd->secure_ram = gd->bd->bi_dram[0].start + gd->secure_ram;
-		gd->secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
+		gd->arch.secure_ram = gd->bd->bi_dram[0].start +
+				      gd->arch.secure_ram;
+		gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
 #endif
 	}
 }
diff --git a/board/freescale/ls1043ardb/ls1043ardb.c b/board/freescale/ls1043ardb/ls1043ardb.c
index 1436520..d3e37b4 100644
--- a/board/freescale/ls1043ardb/ls1043ardb.c
+++ b/board/freescale/ls1043ardb/ls1043ardb.c
@@ -24,7 +24,9 @@
 #ifdef CONFIG_U_QE
 #include <fsl_qe.h>
 #endif
-
+#ifdef CONFIG_FSL_LS_PPA
+#include <asm/arch/ppa.h>
+#endif
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -92,6 +94,10 @@
 	enable_layerscape_ns_access();
 #endif
 
+#ifdef CONFIG_FSL_LS_PPA
+	ppa_init();
+#endif
+
 #ifdef CONFIG_U_QE
 	u_qe_init();
 #endif
diff --git a/board/freescale/ls2080a/ddr.c b/board/freescale/ls2080a/ddr.c
index 1827ddc..e6130ec 100644
--- a/board/freescale/ls2080a/ddr.c
+++ b/board/freescale/ls2080a/ddr.c
@@ -177,7 +177,7 @@
 #endif
 
 	/*
-	 * gd->secure_ram tracks the location of secure memory.
+	 * gd->arch.secure_ram tracks the location of secure memory.
 	 * It was set as if the memory starts from 0.
 	 * The address needs to add the offset of its bank.
 	 */
@@ -188,16 +188,17 @@
 		gd->bd->bi_dram[1].size = gd->ram_size -
 					  CONFIG_SYS_LS2_DDR_BLOCK1_SIZE;
 #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
-		gd->secure_ram = gd->bd->bi_dram[1].start +
-				 gd->secure_ram -
-				 CONFIG_SYS_LS2_DDR_BLOCK1_SIZE;
-		gd->secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
+		gd->arch.secure_ram = gd->bd->bi_dram[1].start +
+				      gd->arch.secure_ram -
+				      CONFIG_SYS_LS2_DDR_BLOCK1_SIZE;
+		gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
 #endif
 	} else {
 		gd->bd->bi_dram[0].size = gd->ram_size;
 #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
-		gd->secure_ram = gd->bd->bi_dram[0].start + gd->secure_ram;
-		gd->secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
+		gd->arch.secure_ram = gd->bd->bi_dram[0].start +
+				      gd->arch.secure_ram;
+		gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
 #endif
 	}
 
diff --git a/board/freescale/ls2080aqds/MAINTAINERS b/board/freescale/ls2080aqds/MAINTAINERS
index 0765326..8f78b67 100644
--- a/board/freescale/ls2080aqds/MAINTAINERS
+++ b/board/freescale/ls2080aqds/MAINTAINERS
@@ -6,6 +6,7 @@
 F:	include/configs/ls2080aqds.h
 F:	configs/ls2080aqds_defconfig
 F:	configs/ls2080aqds_nand_defconfig
+F:	configs/ls2080aqds_qspi_defconfig
 
 LS2080A_SECURE_BOOT BOARD
 M:	Saksham Jain <saksham.jain@nxp.freescale.com>
diff --git a/board/freescale/ls2080aqds/ddr.c b/board/freescale/ls2080aqds/ddr.c
index fcb0366..9c6f477 100644
--- a/board/freescale/ls2080aqds/ddr.c
+++ b/board/freescale/ls2080aqds/ddr.c
@@ -177,7 +177,7 @@
 #endif
 
 	/*
-	 * gd->secure_ram tracks the location of secure memory.
+	 * gd->arch.secure_ram tracks the location of secure memory.
 	 * It was set as if the memory starts from 0.
 	 * The address needs to add the offset of its bank.
 	 */
@@ -188,16 +188,17 @@
 		gd->bd->bi_dram[1].size = gd->ram_size -
 					  CONFIG_SYS_LS2_DDR_BLOCK1_SIZE;
 #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
-		gd->secure_ram = gd->bd->bi_dram[1].start +
-				 gd->secure_ram -
-				 CONFIG_SYS_LS2_DDR_BLOCK1_SIZE;
-		gd->secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
+		gd->arch.secure_ram = gd->bd->bi_dram[1].start +
+				      gd->arch.secure_ram -
+				      CONFIG_SYS_LS2_DDR_BLOCK1_SIZE;
+		gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
 #endif
 	} else {
 		gd->bd->bi_dram[0].size = gd->ram_size;
 #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
-		gd->secure_ram = gd->bd->bi_dram[0].start + gd->secure_ram;
-		gd->secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
+		gd->arch.secure_ram = gd->bd->bi_dram[0].start +
+				      gd->arch.secure_ram;
+		gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
 #endif
 	}
 
diff --git a/board/freescale/ls2080ardb/ddr.c b/board/freescale/ls2080ardb/ddr.c
index a04d21b..ecd1e71 100644
--- a/board/freescale/ls2080ardb/ddr.c
+++ b/board/freescale/ls2080ardb/ddr.c
@@ -177,7 +177,7 @@
 #endif
 
 	/*
-	 * gd->secure_ram tracks the location of secure memory.
+	 * gd->arch.secure_ram tracks the location of secure memory.
 	 * It was set as if the memory starts from 0.
 	 * The address needs to add the offset of its bank.
 	 */
@@ -188,16 +188,17 @@
 		gd->bd->bi_dram[1].size = gd->ram_size -
 					  CONFIG_SYS_LS2_DDR_BLOCK1_SIZE;
 #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
-		gd->secure_ram = gd->bd->bi_dram[1].start +
-				 gd->secure_ram -
-				 CONFIG_SYS_LS2_DDR_BLOCK1_SIZE;
-		gd->secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
+		gd->arch.secure_ram = gd->bd->bi_dram[1].start +
+				      gd->arch.secure_ram -
+				      CONFIG_SYS_LS2_DDR_BLOCK1_SIZE;
+		gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
 #endif
 	} else {
 		gd->bd->bi_dram[0].size = gd->ram_size;
 #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
-		gd->secure_ram = gd->bd->bi_dram[0].start + gd->secure_ram;
-		gd->secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
+		gd->arch.secure_ram = gd->bd->bi_dram[0].start +
+				      gd->arch.secure_ram;
+		gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
 #endif
 	}
 
diff --git a/board/freescale/mx6qsabreauto/mx6qsabreauto.c b/board/freescale/mx6qsabreauto/mx6qsabreauto.c
index d63a979..a3ed4cd 100644
--- a/board/freescale/mx6qsabreauto/mx6qsabreauto.c
+++ b/board/freescale/mx6qsabreauto/mx6qsabreauto.c
@@ -64,7 +64,7 @@
 
 int dram_init(void)
 {
-	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
+	gd->ram_size = imx_ddr_size();
 
 	return 0;
 }
diff --git a/board/freescale/mx6slevk/mx6slevk.c b/board/freescale/mx6slevk/mx6slevk.c
index 256d602..f978e50 100644
--- a/board/freescale/mx6slevk/mx6slevk.c
+++ b/board/freescale/mx6slevk/mx6slevk.c
@@ -61,7 +61,7 @@
 
 int dram_init(void)
 {
-	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
+	gd->ram_size = imx_ddr_size();
 
 	return 0;
 }
diff --git a/board/freescale/mx6sxsabreauto/mx6sxsabreauto.c b/board/freescale/mx6sxsabreauto/mx6sxsabreauto.c
index 886373c..44e6a7d 100644
--- a/board/freescale/mx6sxsabreauto/mx6sxsabreauto.c
+++ b/board/freescale/mx6sxsabreauto/mx6sxsabreauto.c
@@ -106,7 +106,7 @@
 
 int dram_init(void)
 {
-	gd->ram_size = PHYS_SDRAM_SIZE;
+	gd->ram_size = imx_ddr_size();
 
 	return 0;
 }
diff --git a/board/freescale/mx6sxsabresd/mx6sxsabresd.c b/board/freescale/mx6sxsabresd/mx6sxsabresd.c
index 25e009e..8d95c51 100644
--- a/board/freescale/mx6sxsabresd/mx6sxsabresd.c
+++ b/board/freescale/mx6sxsabresd/mx6sxsabresd.c
@@ -64,7 +64,7 @@
 
 int dram_init(void)
 {
-	gd->ram_size = PHYS_SDRAM_SIZE;
+	gd->ram_size = imx_ddr_size();
 
 	return 0;
 }
diff --git a/board/freescale/mx6ul_14x14_evk/mx6ul_14x14_evk.c b/board/freescale/mx6ul_14x14_evk/mx6ul_14x14_evk.c
index 92c9211..66d6795 100644
--- a/board/freescale/mx6ul_14x14_evk/mx6ul_14x14_evk.c
+++ b/board/freescale/mx6ul_14x14_evk/mx6ul_14x14_evk.c
@@ -60,9 +60,6 @@
 
 #define ENET_CLK_PAD_CTRL  (PAD_CTL_DSE_40ohm   | PAD_CTL_SRE_FAST)
 
-#define ENET_RX_PAD_CTRL  (PAD_CTL_PKE | PAD_CTL_PUE |          \
-	PAD_CTL_SPEED_HIGH   | PAD_CTL_SRE_FAST)
-
 #define IOX_SDI IMX_GPIO_NR(5, 10)
 #define IOX_STCP IMX_GPIO_NR(5, 7)
 #define IOX_SHCP IMX_GPIO_NR(5, 11)
diff --git a/board/freescale/mx7dsabresd/MAINTAINERS b/board/freescale/mx7dsabresd/MAINTAINERS
index b96642a..c7a22fc 100644
--- a/board/freescale/mx7dsabresd/MAINTAINERS
+++ b/board/freescale/mx7dsabresd/MAINTAINERS
@@ -4,3 +4,4 @@
 F:	board/freescale/mx7dsabresd
 F:	include/configs/mx7dsabresd.h
 F:	configs/mx7dsabresd_defconfig
+F:	configs/mx7dsabresd_secure_defconfig
diff --git a/board/freescale/t1040qds/MAINTAINERS b/board/freescale/t1040qds/MAINTAINERS
index 640538f..fb3565a 100644
--- a/board/freescale/t1040qds/MAINTAINERS
+++ b/board/freescale/t1040qds/MAINTAINERS
@@ -7,6 +7,6 @@
 F:	configs/T1040QDS_DDR4_defconfig
 
 T1040QDS_SECURE_BOOT BOARD
-M:	Aneesh Bansal <aneesh.bansal@freescale.com>
+M:	Ruchika Gupta <ruchika.gupta@nxp.com>
 S:	Maintained
 F:	configs/T1040QDS_SECURE_BOOT_defconfig
diff --git a/board/freescale/t104xrdb/MAINTAINERS b/board/freescale/t104xrdb/MAINTAINERS
index 7597800..0578989 100644
--- a/board/freescale/t104xrdb/MAINTAINERS
+++ b/board/freescale/t104xrdb/MAINTAINERS
@@ -26,9 +26,13 @@
 F:	configs/T1042RDB_PI_SDCARD_defconfig
 
 T1040RDB_SECURE_BOOT BOARD
-M:	Aneesh Bansal  <aneesh.bansal@freescale.com>
+M:	Ruchika Gupta <ruchika.gupta@nxp.com>
 S:	Maintained
 F:	configs/T1040RDB_SECURE_BOOT_defconfig
 F:	configs/T1040D4RDB_SECURE_BOOT_defconfig
 F:	configs/T1042RDB_SECURE_BOOT_defconfig
 F:	configs/T1042D4RDB_SECURE_BOOT_defconfig
+
+M:	Sumit Garg <sumit.garg@nxp.com>
+S:	Maintained
+F:	configs/T1042RDB_PI_NAND_SECURE_BOOT_defconfig
diff --git a/board/freescale/t104xrdb/t104x_pbi_sb.cfg b/board/freescale/t104xrdb/t104x_pbi_sb.cfg
new file mode 100644
index 0000000..98dc8e4
--- /dev/null
+++ b/board/freescale/t104xrdb/t104x_pbi_sb.cfg
@@ -0,0 +1,38 @@
+#PBI commands
+#Software Workaround for errata A-007662 to train PCIe2 controller in Gen2 speed
+09250100 00000400
+09250108 00002000
+#Software Workaround for errata A-008007 to reset PVR register
+09000010 0000000b
+09000014 c0000000
+09000018 81d00017
+89020400 a1000000
+091380c0 000f0000
+89020400 00000000
+#Initialize CPC1
+09010000 00200400
+09138000 00000000
+091380c0 00000100
+#Configure CPC1 as 256KB SRAM
+09010100 00000000
+09010104 bffc0007
+09010f00 081e000d
+09010000 80000000
+#Configure LAW for CPC1
+09000cd0 00000000
+09000cd4 bffc0000
+09000cd8 81000011
+#Configure alternate space
+09000010 00000000
+09000014 bf000000
+09000018 81000000
+#Configure SPI controller
+09110000 80000403
+09110020 2d170008
+09110024 00100008
+09110028 00100008
+0911002c 00100008
+#Flush PBL data
+091380c0 000FFFFF
+090e0200 bffd0000
+091380c0 000FFFFF
diff --git a/board/freescale/t104xrdb/tlb.c b/board/freescale/t104xrdb/tlb.c
index 95c15aa..7c0511e 100644
--- a/board/freescale/t104xrdb/tlb.c
+++ b/board/freescale/t104xrdb/tlb.c
@@ -28,7 +28,8 @@
 
 	/* TLB 1 */
 	/* *I*** - Covers boot page */
-#if defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SYS_INIT_L3_ADDR)
+#if defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SYS_INIT_L3_ADDR) && \
+	!defined(CONFIG_SECURE_BOOT)
 	/*
 	 * *I*G - L3SRAM. When L3 is used as 256K SRAM, the address of the
 	 * SRAM is at 0xfffc0000, it covered the 0xfffff000.
@@ -36,6 +37,18 @@
 	SET_TLB_ENTRY(1, CONFIG_SYS_INIT_L3_ADDR, CONFIG_SYS_INIT_L3_ADDR,
 		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
 		      0, 0, BOOKE_PAGESZ_256K, 1),
+
+#elif defined(CONFIG_SECURE_BOOT) && defined(CONFIG_SPL_BUILD)
+	/*
+	 * *I*G - L3SRAM. When L3 is used as 256K SRAM, in case of Secure Boot
+	 * the physical address of the SRAM is at 0xbffc0000,
+	 * and virtual address is 0xfffc0000
+	 */
+
+	SET_TLB_ENTRY(1, CONFIG_SYS_INIT_L3_VADDR,
+		      CONFIG_SYS_INIT_L3_ADDR,
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 0, BOOKE_PAGESZ_256K, 1),
 #else
 	SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
 		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
diff --git a/board/freescale/t208xqds/MAINTAINERS b/board/freescale/t208xqds/MAINTAINERS
index d747de3..790b009 100644
--- a/board/freescale/t208xqds/MAINTAINERS
+++ b/board/freescale/t208xqds/MAINTAINERS
@@ -15,6 +15,6 @@
 F:	configs/T2081QDS_SRIO_PCIE_BOOT_defconfig
 
 T2080QDS_SECURE_BOOT BOARD
-M:	Aneesh Bansal <aneesh.bansal@freescale.com>
+M:	Ruchika Gupta <ruchika.gupta@nxp.com>
 S:	Maintained
 F:	configs/T2080QDS_SECURE_BOOT_defconfig
diff --git a/board/freescale/t208xrdb/MAINTAINERS b/board/freescale/t208xrdb/MAINTAINERS
index ccbfbab..f894f77 100644
--- a/board/freescale/t208xrdb/MAINTAINERS
+++ b/board/freescale/t208xrdb/MAINTAINERS
@@ -10,6 +10,6 @@
 F:	configs/T2080RDB_SRIO_PCIE_BOOT_defconfig
 
 T2080RDB_SECURE_BOOT BOARD
-M:	Aneesh Bansal <aneesh.bansal@freescale.com>
+M:	Ruchika Gupta <ruchika.gupta@nxp.com>
 S:	Maintained
 F:	configs/T2080RDB_SECURE_BOOT_defconfig
diff --git a/board/freescale/t4qds/MAINTAINERS b/board/freescale/t4qds/MAINTAINERS
index b159113..b288571 100644
--- a/board/freescale/t4qds/MAINTAINERS
+++ b/board/freescale/t4qds/MAINTAINERS
@@ -12,7 +12,7 @@
 F:	configs/T4240QDS_SRIO_PCIE_BOOT_defconfig
 
 T4160QDS_SECURE_BOOT BOARD
-M:	Aneesh Bansal <aneesh.bansal@freescale.com>
+M:	Ruchika Gupta <ruchika.gupta@nxp.com>
 S:	Maintained
 F:	configs/T4160QDS_SECURE_BOOT_defconfig
 F:	configs/T4240QDS_SECURE_BOOT_defconfig
diff --git a/board/gateworks/gw_ventana/common.c b/board/gateworks/gw_ventana/common.c
index 929dde9..4065c56 100644
--- a/board/gateworks/gw_ventana/common.c
+++ b/board/gateworks/gw_ventana/common.c
@@ -132,14 +132,14 @@
 
 /* common to add baseboards */
 static iomux_v3_cfg_t const gw_gpio_pads[] = {
-	/* RS232_EN# */
-	IOMUX_PADS(PAD_SD4_DAT3__GPIO2_IO11 | DIO_PAD_CFG),
 	/* SD3_VSELECT */
 	IOMUX_PADS(PAD_NANDF_CS1__GPIO6_IO14 | DIO_PAD_CFG),
 };
 
 /* prototype */
 static iomux_v3_cfg_t const gwproto_gpio_pads[] = {
+	/* RS232_EN# */
+	IOMUX_PADS(PAD_SD4_DAT3__GPIO2_IO11 | DIO_PAD_CFG),
 	/* PANLEDG# */
 	IOMUX_PADS(PAD_KEY_COL0__GPIO4_IO06 | DIO_PAD_CFG),
 	/* PANLEDR# */
@@ -183,6 +183,8 @@
 };
 
 static iomux_v3_cfg_t const gw52xx_gpio_pads[] = {
+	/* RS232_EN# */
+	IOMUX_PADS(PAD_SD4_DAT3__GPIO2_IO11 | DIO_PAD_CFG),
 	/* MSATA_EN */
 	IOMUX_PADS(PAD_SD4_DAT0__GPIO2_IO08 | DIO_PAD_CFG),
 	/* PANLEDG# */
@@ -214,6 +216,8 @@
 };
 
 static iomux_v3_cfg_t const gw53xx_gpio_pads[] = {
+	/* RS232_EN# */
+	IOMUX_PADS(PAD_SD4_DAT3__GPIO2_IO11 | DIO_PAD_CFG),
 	/* MSATA_EN */
 	IOMUX_PADS(PAD_SD4_DAT0__GPIO2_IO08 | DIO_PAD_CFG),
 	/* CAN_STBY */
@@ -245,6 +249,8 @@
 };
 
 static iomux_v3_cfg_t const gw54xx_gpio_pads[] = {
+	/* RS232_EN# */
+	IOMUX_PADS(PAD_SD4_DAT3__GPIO2_IO11 | DIO_PAD_CFG),
 	/* MSATA_EN */
 	IOMUX_PADS(PAD_SD4_DAT0__GPIO2_IO08 | DIO_PAD_CFG),
 	/* CAN_STBY */
@@ -332,6 +338,219 @@
 	IOMUX_PADS(PAD_GPIO_17__GPIO7_IO12 | DIO_PAD_CFG),
 };
 
+/* Digital I/O */
+struct dio_cfg gw51xx_dio[] = {
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) },
+		IMX_GPIO_NR(1, 16),
+		{ 0, 0 },
+		0
+	},
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) },
+		IMX_GPIO_NR(1, 19),
+		{ IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) },
+		2
+	},
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) },
+		IMX_GPIO_NR(1, 17),
+		{ IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) },
+		3
+	},
+	{
+		{ IOMUX_PADS(PAD_SD1_CMD__GPIO1_IO18) },
+		IMX_GPIO_NR(1, 18),
+		{ IOMUX_PADS(PAD_SD1_CMD__PWM4_OUT) },
+		4
+	},
+};
+
+struct dio_cfg gw52xx_dio[] = {
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) },
+		IMX_GPIO_NR(1, 16),
+		{ 0, 0 },
+		0
+	},
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) },
+		IMX_GPIO_NR(1, 19),
+		{ IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) },
+		2
+	},
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) },
+		IMX_GPIO_NR(1, 17),
+		{ IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) },
+		3
+	},
+	{
+		{ IOMUX_PADS(PAD_SD1_CLK__GPIO1_IO20) },
+		IMX_GPIO_NR(1, 20),
+		{ 0, 0 },
+		0
+	},
+};
+
+struct dio_cfg gw53xx_dio[] = {
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) },
+		IMX_GPIO_NR(1, 16),
+		{ 0, 0 },
+		0
+	},
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) },
+		IMX_GPIO_NR(1, 19),
+		{ IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) },
+		2
+	},
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) },
+		IMX_GPIO_NR(1, 17),
+		{ IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) },
+		3
+	},
+	{
+		{IOMUX_PADS(PAD_SD1_CLK__GPIO1_IO20) },
+		IMX_GPIO_NR(1, 20),
+		{ 0, 0 },
+		0
+	},
+};
+
+struct dio_cfg gw54xx_dio[] = {
+	{
+		{ IOMUX_PADS(PAD_GPIO_9__GPIO1_IO09) },
+		IMX_GPIO_NR(1, 9),
+		{ IOMUX_PADS(PAD_GPIO_9__PWM1_OUT) },
+		1
+	},
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) },
+		IMX_GPIO_NR(1, 19),
+		{ IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) },
+		2
+	},
+	{
+		{ IOMUX_PADS(PAD_SD4_DAT1__GPIO2_IO09) },
+		IMX_GPIO_NR(2, 9),
+		{ IOMUX_PADS(PAD_SD4_DAT1__PWM3_OUT) },
+		3
+	},
+	{
+		{ IOMUX_PADS(PAD_SD4_DAT2__GPIO2_IO10) },
+		IMX_GPIO_NR(2, 10),
+		{ IOMUX_PADS(PAD_SD4_DAT2__PWM4_OUT) },
+		4
+	},
+};
+
+struct dio_cfg gw551x_dio[] = {
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) },
+		IMX_GPIO_NR(1, 19),
+		{ IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) },
+		2
+	},
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) },
+		IMX_GPIO_NR(1, 17),
+		{ IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) },
+		3
+	},
+};
+
+struct dio_cfg gw552x_dio[] = {
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) },
+		IMX_GPIO_NR(1, 16),
+		{ 0, 0 },
+		0
+	},
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) },
+		IMX_GPIO_NR(1, 19),
+		{ IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) },
+		2
+	},
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) },
+		IMX_GPIO_NR(1, 17),
+		{ IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) },
+		3
+	},
+	{
+		{IOMUX_PADS(PAD_SD1_CLK__GPIO1_IO20) },
+		IMX_GPIO_NR(1, 20),
+		{ 0, 0 },
+		0
+	},
+	{
+		{IOMUX_PADS(PAD_CSI0_PIXCLK__GPIO5_IO18) },
+		IMX_GPIO_NR(5, 18),
+		{ 0, 0 },
+		0
+	},
+	{
+		{IOMUX_PADS(PAD_CSI0_DATA_EN__GPIO5_IO20) },
+		IMX_GPIO_NR(5, 20),
+		{ 0, 0 },
+		0
+	},
+	{
+		{IOMUX_PADS(PAD_CSI0_VSYNC__GPIO5_IO21) },
+		IMX_GPIO_NR(5, 21),
+		{ 0, 0 },
+		0
+	},
+	{
+		{IOMUX_PADS(PAD_CSI0_DAT4__GPIO5_IO22) },
+		IMX_GPIO_NR(5, 22),
+		{ 0, 0 },
+		0
+	},
+	{
+		{IOMUX_PADS(PAD_CSI0_DAT5__GPIO5_IO23) },
+		IMX_GPIO_NR(5, 23),
+		{ 0, 0 },
+		0
+	},
+	{
+		{IOMUX_PADS(PAD_CSI0_DAT7__GPIO5_IO25) },
+		IMX_GPIO_NR(5, 25),
+		{ 0, 0 },
+		0
+	},
+};
+
+struct dio_cfg gw553x_dio[] = {
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) },
+		IMX_GPIO_NR(1, 16),
+		{ 0, 0 },
+		0
+	},
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) },
+		IMX_GPIO_NR(1, 19),
+		{ IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) },
+		2
+	},
+	{
+		{ IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) },
+		IMX_GPIO_NR(1, 17),
+		{ IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) },
+		3
+	},
+	{
+		{ IOMUX_PADS(PAD_SD1_CMD__GPIO1_IO18) },
+		IMX_GPIO_NR(1, 18),
+		{ IOMUX_PADS(PAD_SD1_CMD__PWM4_OUT) },
+		4
+	},
+};
 
 /*
  * Board Specific GPIO
@@ -341,33 +560,8 @@
 	{
 		.gpio_pads = gw54xx_gpio_pads,
 		.num_pads = ARRAY_SIZE(gw54xx_gpio_pads)/2,
-		.dio_cfg = {
-			{
-				{ IOMUX_PADS(PAD_GPIO_9__GPIO1_IO09) },
-				IMX_GPIO_NR(1, 9),
-				{ IOMUX_PADS(PAD_GPIO_9__PWM1_OUT) },
-				1
-			},
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) },
-				IMX_GPIO_NR(1, 19),
-				{ IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) },
-				2
-			},
-			{
-				{ IOMUX_PADS(PAD_SD4_DAT1__GPIO2_IO09) },
-				IMX_GPIO_NR(2, 9),
-				{ IOMUX_PADS(PAD_SD4_DAT1__PWM3_OUT) },
-				3
-			},
-			{
-				{ IOMUX_PADS(PAD_SD4_DAT2__GPIO2_IO10) },
-				IMX_GPIO_NR(2, 10),
-				{ IOMUX_PADS(PAD_SD4_DAT2__PWM4_OUT) },
-				4
-			},
-		},
-		.num_gpios = 4,
+		.dio_cfg = gw54xx_dio,
+		.dio_num = ARRAY_SIZE(gw54xx_dio),
 		.leds = {
 			IMX_GPIO_NR(4, 6),
 			IMX_GPIO_NR(4, 10),
@@ -385,33 +579,8 @@
 	{
 		.gpio_pads = gw51xx_gpio_pads,
 		.num_pads = ARRAY_SIZE(gw51xx_gpio_pads)/2,
-		.dio_cfg = {
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) },
-				IMX_GPIO_NR(1, 16),
-				{ 0, 0 },
-				0
-			},
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) },
-				IMX_GPIO_NR(1, 19),
-				{ IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) },
-				2
-			},
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) },
-				IMX_GPIO_NR(1, 17),
-				{ IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) },
-				3
-			},
-			{
-				{ IOMUX_PADS(PAD_SD1_CMD__GPIO1_IO18) },
-				IMX_GPIO_NR(1, 18),
-				{ IOMUX_PADS(PAD_SD1_CMD__PWM4_OUT) },
-				4
-			},
-		},
-		.num_gpios = 4,
+		.dio_cfg = gw51xx_dio,
+		.dio_num = ARRAY_SIZE(gw51xx_dio),
 		.leds = {
 			IMX_GPIO_NR(4, 6),
 			IMX_GPIO_NR(4, 10),
@@ -428,33 +597,8 @@
 	{
 		.gpio_pads = gw52xx_gpio_pads,
 		.num_pads = ARRAY_SIZE(gw52xx_gpio_pads)/2,
-		.dio_cfg = {
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) },
-				IMX_GPIO_NR(1, 16),
-				{ 0, 0 },
-				0
-			},
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) },
-				IMX_GPIO_NR(1, 19),
-				{ IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) },
-				2
-			},
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) },
-				IMX_GPIO_NR(1, 17),
-				{ IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) },
-				3
-			},
-			{
-				{ IOMUX_PADS(PAD_SD1_CLK__GPIO1_IO20) },
-				IMX_GPIO_NR(1, 20),
-				{ 0, 0 },
-				0
-			},
-		},
-		.num_gpios = 4,
+		.dio_cfg = gw52xx_dio,
+		.dio_num = ARRAY_SIZE(gw52xx_dio),
 		.leds = {
 			IMX_GPIO_NR(4, 6),
 			IMX_GPIO_NR(4, 7),
@@ -468,39 +612,15 @@
 		.usb_sel = IMX_GPIO_NR(1, 2),
 		.wdis = IMX_GPIO_NR(7, 12),
 		.msata_en = GP_MSATA_SEL,
+		.rs232_en = GP_RS232_EN,
 	},
 
 	/* GW53xx */
 	{
 		.gpio_pads = gw53xx_gpio_pads,
 		.num_pads = ARRAY_SIZE(gw53xx_gpio_pads)/2,
-		.dio_cfg = {
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) },
-				IMX_GPIO_NR(1, 16),
-				{ 0, 0 },
-				0
-			},
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) },
-				IMX_GPIO_NR(1, 19),
-				{ IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) },
-				2
-			},
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) },
-				IMX_GPIO_NR(1, 17),
-				{ IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) },
-				3
-			},
-			{
-				{IOMUX_PADS(PAD_SD1_CLK__GPIO1_IO20) },
-				IMX_GPIO_NR(1, 20),
-				{ 0, 0 },
-				0
-			},
-		},
-		.num_gpios = 4,
+		.dio_cfg = gw53xx_dio,
+		.dio_num = ARRAY_SIZE(gw53xx_dio),
 		.leds = {
 			IMX_GPIO_NR(4, 6),
 			IMX_GPIO_NR(4, 7),
@@ -513,39 +633,15 @@
 		.vidin_en = IMX_GPIO_NR(3, 31),
 		.wdis = IMX_GPIO_NR(7, 12),
 		.msata_en = GP_MSATA_SEL,
+		.rs232_en = GP_RS232_EN,
 	},
 
 	/* GW54xx */
 	{
 		.gpio_pads = gw54xx_gpio_pads,
 		.num_pads = ARRAY_SIZE(gw54xx_gpio_pads)/2,
-		.dio_cfg = {
-			{
-				{ IOMUX_PADS(PAD_GPIO_9__GPIO1_IO09) },
-				IMX_GPIO_NR(1, 9),
-				{ IOMUX_PADS(PAD_GPIO_9__PWM1_OUT) },
-				1
-			},
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) },
-				IMX_GPIO_NR(1, 19),
-				{ IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) },
-				2
-			},
-			{
-				{ IOMUX_PADS(PAD_SD4_DAT1__GPIO2_IO09) },
-				IMX_GPIO_NR(2, 9),
-				{ IOMUX_PADS(PAD_SD4_DAT1__PWM3_OUT) },
-				3
-			},
-			{
-				{ IOMUX_PADS(PAD_SD4_DAT2__GPIO2_IO10) },
-				IMX_GPIO_NR(2, 10),
-				{ IOMUX_PADS(PAD_SD4_DAT2__PWM4_OUT) },
-				4
-			},
-		},
-		.num_gpios = 4,
+		.dio_cfg = gw54xx_dio,
+		.dio_num = ARRAY_SIZE(gw54xx_dio),
 		.leds = {
 			IMX_GPIO_NR(4, 6),
 			IMX_GPIO_NR(4, 7),
@@ -560,27 +656,15 @@
 		.pcie_sson = IMX_GPIO_NR(1, 20),
 		.wdis = IMX_GPIO_NR(5, 17),
 		.msata_en = GP_MSATA_SEL,
+		.rs232_en = GP_RS232_EN,
 	},
 
 	/* GW551x */
 	{
 		.gpio_pads = gw551x_gpio_pads,
 		.num_pads = ARRAY_SIZE(gw551x_gpio_pads)/2,
-		.dio_cfg = {
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) },
-				IMX_GPIO_NR(1, 19),
-				{ IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) },
-				2
-			},
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) },
-				IMX_GPIO_NR(1, 17),
-				{ IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) },
-				3
-			},
-		},
-		.num_gpios = 2,
+		.dio_cfg = gw551x_dio,
+		.dio_num = ARRAY_SIZE(gw551x_dio),
 		.leds = {
 			IMX_GPIO_NR(4, 7),
 		},
@@ -592,33 +676,8 @@
 	{
 		.gpio_pads = gw552x_gpio_pads,
 		.num_pads = ARRAY_SIZE(gw552x_gpio_pads)/2,
-		.dio_cfg = {
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) },
-				IMX_GPIO_NR(1, 16),
-				{ 0, 0 },
-				0
-			},
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) },
-				IMX_GPIO_NR(1, 19),
-				{ IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) },
-				2
-			},
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) },
-				IMX_GPIO_NR(1, 17),
-				{ IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) },
-				3
-			},
-			{
-				{IOMUX_PADS(PAD_SD1_CLK__GPIO1_IO20) },
-				IMX_GPIO_NR(1, 20),
-				{ 0, 0 },
-				0
-			},
-		},
-		.num_gpios = 4,
+		.dio_cfg = gw552x_dio,
+		.dio_num = ARRAY_SIZE(gw552x_dio),
 		.leds = {
 			IMX_GPIO_NR(4, 6),
 			IMX_GPIO_NR(4, 7),
@@ -634,33 +693,8 @@
 	{
 		.gpio_pads = gw553x_gpio_pads,
 		.num_pads = ARRAY_SIZE(gw553x_gpio_pads)/2,
-		.dio_cfg = {
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) },
-				IMX_GPIO_NR(1, 16),
-				{ 0, 0 },
-				0
-			},
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) },
-				IMX_GPIO_NR(1, 19),
-				{ IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) },
-				2
-			},
-			{
-				{ IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) },
-				IMX_GPIO_NR(1, 17),
-				{ IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) },
-				3
-			},
-			{
-				{ IOMUX_PADS(PAD_SD1_CMD__GPIO1_IO18) },
-				IMX_GPIO_NR(1, 18),
-				{ IOMUX_PADS(PAD_SD1_CMD__PWM4_OUT) },
-				4
-			},
-		},
-		.num_gpios = 4,
+		.dio_cfg = gw553x_dio,
+		.dio_num = ARRAY_SIZE(gw553x_dio),
 		.leds = {
 			IMX_GPIO_NR(4, 10),
 			IMX_GPIO_NR(4, 11),
@@ -682,10 +716,6 @@
 	gpio_request(GP_USB_OTG_PWR, "usbotg_pwr");
 	gpio_direction_output(GP_USB_OTG_PWR, 0);
 
-	/* RS232_EN# */
-	gpio_request(GP_RS232_EN, "rs232_en");
-	gpio_direction_output(GP_RS232_EN, 0);
-
 	if (board >= GW_UNKNOWN)
 		return;
 
@@ -693,6 +723,12 @@
 	imx_iomux_v3_setup_multiple_pads(gpio_cfg[board].gpio_pads,
 					 gpio_cfg[board].num_pads);
 
+	/* RS232_EN# */
+	if (gpio_cfg[board].rs232_en) {
+		gpio_request(gpio_cfg[board].rs232_en, "rs232_en");
+		gpio_direction_output(gpio_cfg[board].rs232_en, 0);
+	}
+
 	/* GW522x Uses GPIO3_IO23 for PCIE_RST# */
 	if (board == GW52xx && info->model[4] == '2')
 		gpio_cfg[board].pcie_rst = IMX_GPIO_NR(3, 23);
@@ -788,7 +824,10 @@
 		return;
 
 	/* RS232_EN# */
-	gpio_direction_output(GP_RS232_EN, (hwconfig("rs232")) ? 0 : 1);
+	if (gpio_cfg[board].rs232_en) {
+		gpio_direction_output(gpio_cfg[board].rs232_en,
+				      (hwconfig("rs232")) ? 0 : 1);
+	}
 
 	/* MSATA Enable */
 	if (gpio_cfg[board].msata_en && is_cpu_type(MXC_CPU_MX6Q)) {
@@ -806,7 +845,7 @@
 	 * Configure DIO pinmux/padctl registers
 	 * see IMX6DQRM/IMX6SDLRM IOMUXC_SW_PAD_CTL_PAD_* register definitions
 	 */
-	for (i = 0; i < gpio_cfg[board].num_gpios; i++) {
+	for (i = 0; i < gpio_cfg[board].dio_num; i++) {
 		struct dio_cfg *cfg = &gpio_cfg[board].dio_cfg[i];
 		iomux_v3_cfg_t ctrl = DIO_PAD_CFG;
 		unsigned cputype = is_cpu_type(MXC_CPU_MX6Q) ? 0 : 1;
@@ -851,8 +890,10 @@
 			printf("MSATA: %s\n", (hwconfig("msata") ?
 			       "enabled" : "disabled"));
 		}
-		printf("RS232: %s\n", (hwconfig("rs232")) ?
-		       "enabled" : "disabled");
+		if (gpio_cfg[board].rs232_en) {
+			printf("RS232: %s\n", (hwconfig("rs232")) ?
+			       "enabled" : "disabled");
+		}
 	}
 }
 
diff --git a/board/gateworks/gw_ventana/common.h b/board/gateworks/gw_ventana/common.h
index d037767..3d7aff1 100644
--- a/board/gateworks/gw_ventana/common.h
+++ b/board/gateworks/gw_ventana/common.h
@@ -48,8 +48,8 @@
 #define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
 
 /*
- * each baseboard has 4 user configurable Digital IO lines which can
- * be pinmuxed as a GPIO or in some cases a PWM
+ * each baseboard has an optional set user configurable Digital IO lines which
+ * can be pinmuxed as a GPIO or in some cases a PWM
  */
 struct dio_cfg {
 	iomux_v3_cfg_t gpio_padmux[2];
@@ -63,8 +63,8 @@
 	iomux_v3_cfg_t const *gpio_pads;
 	int num_pads;
 	/* DIO pinmux/val */
-	struct dio_cfg dio_cfg[4];
-	int num_gpios;
+	struct dio_cfg *dio_cfg;
+	int dio_num;
 	/* various gpios (0 if non-existent) */
 	int leds[3];
 	int pcie_rst;
@@ -78,6 +78,8 @@
 	int usb_sel;
 	int wdis;
 	int msata_en;
+	int rs232_en;
+	/* various features */
 	bool usd_vsel;
 };
 
diff --git a/board/gateworks/gw_ventana/gw_ventana.c b/board/gateworks/gw_ventana/gw_ventana.c
index 70395ac..5d871ce 100644
--- a/board/gateworks/gw_ventana/gw_ventana.c
+++ b/board/gateworks/gw_ventana/gw_ventana.c
@@ -491,14 +491,54 @@
  * GPIO's as PERST# signals for its downstream ports - configure the GPIO's
  * properly and assert reset for 100ms.
  */
+#define MAX_PCI_DEVS	32
+struct pci_dev {
+	pci_dev_t devfn;
+	unsigned short vendor;
+	unsigned short device;
+	unsigned short class;
+	unsigned short busno; /* subbordinate busno */
+	struct pci_dev *ppar;
+};
+struct pci_dev pci_devs[MAX_PCI_DEVS];
+int pci_devno;
+int pci_bridgeno;
+
 void board_pci_fixup_dev(struct pci_controller *hose, pci_dev_t dev,
 			 unsigned short vendor, unsigned short device,
 			 unsigned short class)
 {
+	int i;
 	u32 dw;
+	struct pci_dev *pdev = &pci_devs[pci_devno++];
 
 	debug("%s: %02d:%02d.%02d: %04x:%04x\n", __func__,
 	      PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev), vendor, device);
+
+	/* store array of devs for later use in device-tree fixup */
+	pdev->devfn = dev;
+	pdev->vendor = vendor;
+	pdev->device = device;
+	pdev->class = class;
+	pdev->ppar = NULL;
+	if (class == PCI_CLASS_BRIDGE_PCI)
+		pdev->busno = ++pci_bridgeno;
+	else
+		pdev->busno = 0;
+
+	/* fixup RC - it should be 00:00.0 not 00:01.0 */
+	if (PCI_BUS(dev) == 0)
+		pdev->devfn = 0;
+
+	/* find dev's parent */
+	for (i = 0; i < pci_devno; i++) {
+		if (pci_devs[i].busno == PCI_BUS(pdev->devfn)) {
+			pdev->ppar = &pci_devs[i];
+			break;
+		}
+	}
+
+	/* assert downstream PERST# */
 	if (vendor == PCI_VENDOR_ID_PLX &&
 	    (device & 0xfff0) == 0x8600 &&
 	    PCI_DEV(dev) == 0 && PCI_FUNC(dev) == 0) {
@@ -660,13 +700,14 @@
 int misc_init_r(void)
 {
 	struct ventana_board_info *info = &ventana_info;
+	char buf[256];
+	int i;
 
 	/* set env vars based on EEPROM data */
 	if (ventana_info.model[0]) {
 		char str[16], fdt[36];
 		char *p;
 		const char *cputype = "";
-		int i;
 
 		/*
 		 * FDT name will be prefixed with CPU type.  Three versions
@@ -729,6 +770,19 @@
 		setenv("mem_mb", str);
 	}
 
+	/* Set a non-initialized hwconfig based on board configuration */
+	if (!strcmp(getenv("hwconfig"), "_UNKNOWN_")) {
+		sprintf(buf, "hwconfig=");
+		if (gpio_cfg[board_type].rs232_en)
+			strcat(buf, "rs232;");
+		for (i = 0; i < gpio_cfg[board_type].dio_num; i++) {
+			char buf1[32];
+			sprintf(buf1, "dio%d:mode=gpio;", i);
+			if (strlen(buf) + strlen(buf1) < sizeof(buf))
+				strcat(buf, buf1);
+		}
+		setenv("hwconfig", buf);
+	}
 
 	/* setup baseboard specific GPIO based on board and env */
 	setup_board_gpio(board_type, info);
@@ -800,9 +854,227 @@
 		debug("removing %s/%s\n", path, name);
 		fdt_delprop(blob, i, name);
 	}
+}
+
+#if defined(CONFIG_CMD_PCI)
+#define PCI_ID(x) ( \
+	(PCI_BUS(x->devfn)<<16)| \
+	(PCI_DEV(x->devfn)<<11)| \
+	(PCI_FUNC(x->devfn)<<8) \
+	)
+#define PCIE_PATH	"/soc/pcie@0x01000000"
+int fdt_add_pci_node(void *blob, int par, struct pci_dev *dev)
+{
+	uint32_t reg[5];
+	char node[32];
+	int np;
+
+	sprintf(node, "pcie@%d,%d,%d", PCI_BUS(dev->devfn),
+		PCI_DEV(dev->devfn), PCI_FUNC(dev->devfn));
+
+	np = fdt_subnode_offset(blob, par, node);
+	if (np >= 0)
+		return np;
+	np = fdt_add_subnode(blob, par, node);
+	if (np < 0) {
+		printf("   %s failed: no space\n", __func__);
+		return np;
+	}
+
+	memset(reg, 0, sizeof(reg));
+	reg[0] = cpu_to_fdt32(PCI_ID(dev));
+	fdt_setprop(blob, np, "reg", reg, sizeof(reg));
+
+	return np;
+}
+
+/* build a path of nested PCI devs for all bridges passed through */
+int fdt_add_pci_path(void *blob, struct pci_dev *dev)
+{
+	struct pci_dev *bridges[MAX_PCI_DEVS];
+	int k, np;
+
+	/* build list of parents */
+	np = fdt_path_offset(blob, PCIE_PATH);
+	if (np < 0)
+		return np;
+
+	k = 0;
+	while (dev) {
+		bridges[k++] = dev;
+		dev = dev->ppar;
+	};
+
+	/* now add them the to DT in reverse order */
+	while (k--) {
+		np = fdt_add_pci_node(blob, np, bridges[k]);
+		if (np < 0)
+			break;
+	}
+
+	return np;
 }
 
 /*
+ * The GW16082 has a hardware errata errata such that it's
+ * INTA/B/C/D are mis-mapped to its four slots (slot12-15). Because
+ * of this normal PCI interrupt swizzling will not work so we will
+ * provide an irq-map via device-tree.
+ */
+int fdt_fixup_gw16082(void *blob, int np, struct pci_dev *dev)
+{
+	int len;
+	int host;
+	uint32_t imap_new[8*4*4];
+	const uint32_t *imap;
+	uint32_t irq[4];
+	uint32_t reg[4];
+	int i;
+
+	/* build irq-map based on host controllers map */
+	host = fdt_path_offset(blob, PCIE_PATH);
+	if (host < 0) {
+		printf("   %s failed: missing host\n", __func__);
+		return host;
+	}
+
+	/* use interrupt data from root complex's node */
+	imap = fdt_getprop(blob, host, "interrupt-map", &len);
+	if (!imap || len != 128) {
+		printf("   %s failed: invalid interrupt-map\n",
+		       __func__);
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	/* obtain irq's of host controller in pin order */
+	for (i = 0; i < 4; i++)
+		irq[(fdt32_to_cpu(imap[(i*8)+3])-1)%4] = imap[(i*8)+6];
+
+	/*
+	 * determine number of swizzles necessary:
+	 *   For each bridge we pass through we need to swizzle
+	 *   the number of the slot we are on.
+	 */
+	struct pci_dev *d;
+	int b;
+	b = 0;
+	d = dev->ppar;
+	while(d && d->ppar) {
+		b += PCI_DEV(d->devfn);
+		d = d->ppar;
+	}
+
+	/* create new irq mappings for slots12-15
+	 * <skt> <idsel> <slot> <skt-inta> <skt-intb>
+	 * J3    AD28    12     INTD      INTA
+	 * J4    AD29    13     INTC      INTD
+	 * J5    AD30    14     INTB      INTC
+	 * J2    AD31    15     INTA      INTB
+	 */
+	for (i = 0; i < 4; i++) {
+		/* addr matches bus:dev:func */
+		u32 addr = dev->busno << 16 | (12+i) << 11;
+
+		/* default cells from root complex */
+		memcpy(&imap_new[i*32], imap, 128);
+		/* first cell is PCI device address (BDF) */
+		imap_new[(i*32)+(0*8)+0] = cpu_to_fdt32(addr);
+		imap_new[(i*32)+(1*8)+0] = cpu_to_fdt32(addr);
+		imap_new[(i*32)+(2*8)+0] = cpu_to_fdt32(addr);
+		imap_new[(i*32)+(3*8)+0] = cpu_to_fdt32(addr);
+		/* third cell is pin */
+		imap_new[(i*32)+(0*8)+3] = cpu_to_fdt32(1);
+		imap_new[(i*32)+(1*8)+3] = cpu_to_fdt32(2);
+		imap_new[(i*32)+(2*8)+3] = cpu_to_fdt32(3);
+		imap_new[(i*32)+(3*8)+3] = cpu_to_fdt32(4);
+		/* sixth cell is relative interrupt */
+		imap_new[(i*32)+(0*8)+6] = irq[(15-(12+i)+b+0)%4];
+		imap_new[(i*32)+(1*8)+6] = irq[(15-(12+i)+b+1)%4];
+		imap_new[(i*32)+(2*8)+6] = irq[(15-(12+i)+b+2)%4];
+		imap_new[(i*32)+(3*8)+6] = irq[(15-(12+i)+b+3)%4];
+	}
+	fdt_setprop(blob, np, "interrupt-map", imap_new,
+		    sizeof(imap_new));
+	reg[0] = cpu_to_fdt32(0xfff00);
+	reg[1] = 0;
+	reg[2] = 0;
+	reg[3] = cpu_to_fdt32(0x7);
+	fdt_setprop(blob, np, "interrupt-map-mask", reg, sizeof(reg));
+	fdt_setprop_cell(blob, np, "#interrupt-cells", 1);
+	fdt_setprop_string(blob, np, "device_type", "pci");
+	fdt_setprop_cell(blob, np, "#address-cells", 3);
+	fdt_setprop_cell(blob, np, "#size-cells", 2);
+	printf("   Added custom interrupt-map for GW16082\n");
+
+	return 0;
+}
+
+/* The sky2 GigE MAC obtains it's MAC addr from device-tree by default */
+int fdt_fixup_sky2(void *blob, int np, struct pci_dev *dev)
+{
+	char *tmp, *end;
+	char mac[16];
+	unsigned char mac_addr[6];
+	int j;
+
+	sprintf(mac, "eth1addr");
+	tmp = getenv(mac);
+	if (tmp) {
+		for (j = 0; j < 6; j++) {
+			mac_addr[j] = tmp ?
+				      simple_strtoul(tmp, &end,16) : 0;
+			if (tmp)
+				tmp = (*end) ? end+1 : end;
+		}
+		fdt_setprop(blob, np, "local-mac-address", mac_addr,
+			    sizeof(mac_addr));
+		printf("   Added mac addr for eth1\n");
+		return 0;
+	}
+
+	return -1;
+}
+
+/*
+ * PCI DT nodes must be nested therefore if we need to apply a DT fixup
+ * we will walk the PCI bus and add bridge nodes up to the device receiving
+ * the fixup.
+ */
+void ft_board_pci_fixup(void *blob, bd_t *bd)
+{
+	int i, np;
+	struct pci_dev *dev;
+
+	for (i = 0; i < pci_devno; i++) {
+		dev = &pci_devs[i];
+
+		/*
+		 * The GW16082 consists of a TI XIO2001 PCIe-to-PCI bridge and
+		 * an EEPROM at i2c1-0x50.
+		 */
+		if ((dev->vendor == PCI_VENDOR_ID_TI) &&
+		    (dev->device == 0x8240) &&
+		    (i2c_set_bus_num(1) == 0) &&
+		    (i2c_probe(0x50) == 0))
+		{
+			np = fdt_add_pci_path(blob, dev);
+			if (np > 0)
+				fdt_fixup_gw16082(blob, np, dev);
+		}
+
+		/* ethernet1 mac address */
+		else if ((dev->vendor == PCI_VENDOR_ID_MARVELL) &&
+		         (dev->device == 0x4380))
+		{
+			np = fdt_add_pci_path(blob, dev);
+			if (np > 0)
+				fdt_fixup_sky2(blob, np, dev);
+		}
+	}
+}
+#endif /* if defined(CONFIG_CMD_PCI) */
+
+/*
  * called prior to booting kernel or by 'fdt boardsetup' command
  *
  * unless 'fdt_noauto' env var is set we will update the following in the DTB:
@@ -811,6 +1083,10 @@
  *  - board (full model from EEPROM)
  *  - peripherals removed from DTB if not loaded on board (per EEPROM config)
  */
+#define UART1_PATH	"/soc/aips-bus@02100000/serial@021ec000"
+#define WDOG1_PATH	"/soc/aips-bus@02000000/wdog@020bc000"
+#define WDOG2_PATH	"/soc/aips-bus@02000000/wdog@020c0000"
+#define GPIO3_PATH	"/soc/aips-bus@02000000/gpio@020a4000"
 int ft_board_setup(void *blob, bd_t *bd)
 {
 	struct ventana_board_info *info = &ventana_info;
@@ -864,94 +1140,140 @@
 	ft_sethdmiinfmt(blob, getenv("hdmiinfmt"));
 
 	/*
-	 * disable serial2 node for GW54xx for compatibility with older
-	 * 3.10.x kernel that improperly had this node enabled in the DT
-	 */
-	if (board_type == GW54xx) {
-		i = fdt_path_offset(blob,
-				    "/soc/aips-bus@02100000/serial@021ec000");
-		if (i)
-			fdt_del_node(blob, i);
-	}
-
-	/*
-	 * disable wdog1/wdog2 nodes for GW51xx below revC to work around
-	 * errata causing wdog timer to be unreliable.
+	 * Board model specific fixups
 	 */
-	if (board_type == GW51xx && rev >= 'A' && rev < 'C') {
-		i = fdt_path_offset(blob,
-				    "/soc/aips-bus@02000000/wdog@020bc000");
-		if (i)
-			fdt_status_disabled(blob, i);
-	}
+	switch (board_type) {
+	case GW51xx:
+		/*
+		 * disable wdog node for GW51xx-A/B to work around
+		 * errata causing wdog timer to be unreliable.
+		 */
+		if (rev >= 'A' && rev < 'C') {
+			i = fdt_path_offset(blob, WDOG1_PATH);
+			if (i)
+				fdt_status_disabled(blob, i);
+		}
 
-	/* GW522x Uses GPIO3_IO23 instead of GPIO1_IO29 */
-	else if (board_type == GW52xx && info->model[4] == '2') {
-		u32 handle = 0;
-		u32 *range = NULL;
+		/* GW51xx-E adds WDOG1_B external reset */
+		if (rev < 'E')
+			ft_delprop_path(blob, WDOG1_PATH,
+					"fsl,ext-reset-output");
+		break;
 
-		i = fdt_node_offset_by_compatible(blob, -1, "fsl,imx6q-pcie");
-		if (i)
-			range = (u32 *)fdt_getprop(blob, i, "reset-gpio",
-						   NULL);
+	case GW52xx:
+		/* GW522x Uses GPIO3_IO23 instead of GPIO1_IO29 */
+		if (info->model[4] == '2') {
+			u32 handle = 0;
+			u32 *range = NULL;
 
-		if (range) {
-			i = fdt_path_offset(blob,
-					    "/soc/aips-bus@02000000/gpio@020a4000");
+			i = fdt_node_offset_by_compatible(blob, -1,
+							  "fsl,imx6q-pcie");
 			if (i)
-				handle = fdt_get_phandle(blob, i);
-			if (handle) {
-				range[0] = cpu_to_fdt32(handle);
-				range[1] = cpu_to_fdt32(23);
+				range = (u32 *)fdt_getprop(blob, i,
+							   "reset-gpio", NULL);
+
+			if (range) {
+				i = fdt_path_offset(blob, GPIO3_PATH);
+				if (i)
+					handle = fdt_get_phandle(blob, i);
+				if (handle) {
+					range[0] = cpu_to_fdt32(handle);
+					range[1] = cpu_to_fdt32(23);
+				}
 			}
-		}
 
-		/* these have broken usd_vsel */
-		if (strstr((const char *)info->model, "SP318-B") ||
-		    strstr((const char *)info->model, "SP331-B"))
-			gpio_cfg[board_type].usd_vsel = 0;
-	}
+			/* these have broken usd_vsel */
+			if (strstr((const char *)info->model, "SP318-B") ||
+			    strstr((const char *)info->model, "SP331-B"))
+				gpio_cfg[board_type].usd_vsel = 0;
 
-	/*
-	 * isolate CSI0_DATA_EN for GW551x below revB to work around
-	 * errata causing non functional digital video in (it is not hooked up)
-	 */
-	else if (board_type == GW551x && rev == 'A') {
-		u32 *range = NULL;
-		int len;
-		const u32 *handle = NULL;
+			/* GW520x-E adds WDOG1_B external reset */
+			if (info->model[4] == '0' && rev < 'E')
+				ft_delprop_path(blob, WDOG1_PATH,
+						"fsl,ext-reset-output");
 
-		i = fdt_node_offset_by_compatible(blob, -1,
-						  "fsl,imx-tda1997x-video");
-		if (i)
-			handle = fdt_getprop(blob, i, "pinctrl-0", NULL);
-		if (handle)
-			i = fdt_node_offset_by_phandle(blob,
-						       fdt32_to_cpu(*handle));
+			/* GW522x-B adds WDOG1_B external reset */
+			if (info->model[4] == '2' && rev < 'B')
+				ft_delprop_path(blob, WDOG1_PATH,
+						"fsl,ext-reset-output");
+		}
+		break;
+
+	case GW53xx:
+		/* GW53xx-E adds WDOG1_B external reset */
+		if (rev < 'E')
+			ft_delprop_path(blob, WDOG1_PATH,
+					"fsl,ext-reset-output");
+		break;
+
+	case GW54xx:
+		/*
+		 * disable serial2 node for GW54xx for compatibility with older
+		 * 3.10.x kernel that improperly had this node enabled in the DT
+		 */
+		i = fdt_path_offset(blob, UART1_PATH);
 		if (i)
-			range = (u32 *)fdt_getprop(blob, i, "fsl,pins", &len);
-		if (range) {
-			len /= sizeof(u32);
-			for (i = 0; i < len; i += 6) {
-				u32 mux_reg = fdt32_to_cpu(range[i+0]);
-				u32 conf_reg = fdt32_to_cpu(range[i+1]);
-				/* mux PAD_CSI0_DATA_EN to GPIO */
-				if (is_cpu_type(MXC_CPU_MX6Q) &&
-				    mux_reg == 0x260 && conf_reg == 0x630)
-					range[i+3] = cpu_to_fdt32(0x5);
-				else if (!is_cpu_type(MXC_CPU_MX6Q) &&
-				    mux_reg == 0x08c && conf_reg == 0x3a0)
-					range[i+3] = cpu_to_fdt32(0x5);
+			fdt_del_node(blob, i);
+
+		/* GW54xx-E adds WDOG2_B external reset */
+		if (rev < 'E')
+			ft_delprop_path(blob, WDOG2_PATH,
+					"fsl,ext-reset-output");
+		break;
+
+	case GW551x:
+		/*
+		 * isolate CSI0_DATA_EN for GW551x-A to work around errata
+		 * causing non functional digital video in (it is not hooked up)
+		 */
+		if (rev == 'A') {
+			u32 *range = NULL;
+			int len;
+			const u32 *handle = NULL;
+
+			i = fdt_node_offset_by_compatible(blob, -1,
+						"fsl,imx-tda1997x-video");
+			if (i)
+				handle = fdt_getprop(blob, i, "pinctrl-0",
+						     NULL);
+			if (handle)
+				i = fdt_node_offset_by_phandle(blob,
+							fdt32_to_cpu(*handle));
+			if (i)
+				range = (u32 *)fdt_getprop(blob, i, "fsl,pins",
+							   &len);
+			if (range) {
+				len /= sizeof(u32);
+				for (i = 0; i < len; i += 6) {
+					u32 mux_reg = fdt32_to_cpu(range[i+0]);
+					u32 conf_reg = fdt32_to_cpu(range[i+1]);
+					/* mux PAD_CSI0_DATA_EN to GPIO */
+					if (is_cpu_type(MXC_CPU_MX6Q) &&
+					    mux_reg == 0x260 &&
+					    conf_reg == 0x630)
+						range[i+3] = cpu_to_fdt32(0x5);
+					else if (!is_cpu_type(MXC_CPU_MX6Q) &&
+						 mux_reg == 0x08c &&
+						 conf_reg == 0x3a0)
+						range[i+3] = cpu_to_fdt32(0x5);
+				}
+				fdt_setprop_inplace(blob, i, "fsl,pins", range,
+						    len);
 			}
-			fdt_setprop_inplace(blob, i, "fsl,pins", range, len);
+
+			/* set BT656 video format */
+			ft_sethdmiinfmt(blob, "yuv422bt656");
 		}
 
-		/* set BT656 video format */
-		ft_sethdmiinfmt(blob, "yuv422bt656");
+		/* GW551x-C adds WDOG1_B external reset */
+		if (rev < 'C')
+			ft_delprop_path(blob, WDOG1_PATH,
+					"fsl,ext-reset-output");
+		break;
 	}
 
 	/* Configure DIO */
-	for (i = 0; i < gpio_cfg[board_type].num_gpios; i++) {
+	for (i = 0; i < gpio_cfg[board_type].dio_num; i++) {
 		struct dio_cfg *cfg = &gpio_cfg[board_type].dio_cfg[i];
 		char arg[10];
 
@@ -976,6 +1298,11 @@
 				"no-1-8-v");
 	}
 
+#if defined(CONFIG_CMD_PCI)
+	if (!getenv("nopcifixup"))
+		ft_board_pci_fixup(blob, bd);
+#endif
+
 	/*
 	 * Peripheral Config:
 	 *  remove nodes by alias path if EEPROM config tells us the
diff --git a/board/gdsys/405ep/405ep.c b/board/gdsys/405ep/405ep.c
index 426dc05..35fa06a 100644
--- a/board/gdsys/405ep/405ep.c
+++ b/board/gdsys/405ep/405ep.c
@@ -31,14 +31,6 @@
 	return gd->arch.fpga_state[dev];
 }
 
-void print_fpga_state(unsigned dev)
-{
-	if (gd->arch.fpga_state[dev] & FPGA_STATE_DONE_FAILED)
-		puts("       Waiting for FPGA-DONE timed out.\n");
-	if (gd->arch.fpga_state[dev] & FPGA_STATE_REFLECTION_FAILED)
-		puts("       FPGA reflection test failed.\n");
-}
-
 int board_early_init_f(void)
 {
 	unsigned k;
diff --git a/board/gdsys/405ep/dlvision-10g.c b/board/gdsys/405ep/dlvision-10g.c
index 54c7eb3..e400d19 100644
--- a/board/gdsys/405ep/dlvision-10g.c
+++ b/board/gdsys/405ep/dlvision-10g.c
@@ -109,7 +109,10 @@
 	    && !((hardware_version == HWVER_101)
 		 && (fpga_state == FPGA_STATE_DONE_FAILED))) {
 		puts("not available\n");
-		print_fpga_state(dev);
+		if (fpga_state & FPGA_STATE_DONE_FAILED)
+			puts("       Waiting for FPGA-DONE timed out.\n");
+		if (fpga_state & FPGA_STATE_REFLECTION_FAILED)
+			puts("       FPGA reflection test failed.\n");
 		return;
 	}
 
diff --git a/board/gdsys/405ep/io.c b/board/gdsys/405ep/io.c
index 03d796c..81b4965 100644
--- a/board/gdsys/405ep/io.c
+++ b/board/gdsys/405ep/io.c
@@ -172,8 +172,17 @@
 
 	print_fpga_info();
 
-	miiphy_register(CONFIG_SYS_GBIT_MII_BUSNAME,
-		bb_miiphy_read, bb_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, CONFIG_SYS_GBIT_MII_BUSNAME, MDIO_NAME_LEN);
+	mdiodev->read = bb_miiphy_read;
+	mdiodev->write = bb_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 
 	for (k = 0; k < 32; ++k)
 		configure_gbit_phy(k);
diff --git a/board/gdsys/405ep/iocon.c b/board/gdsys/405ep/iocon.c
index 7484624..7db0e29 100644
--- a/board/gdsys/405ep/iocon.c
+++ b/board/gdsys/405ep/iocon.c
@@ -405,8 +405,17 @@
 	}
 
 	if (!legacy && (feature_carrier_speed == CARRIER_SPEED_1G)) {
-		miiphy_register(bb_miiphy_buses[0].name, bb_miiphy_read,
-				bb_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, bb_miiphy_buses[0].name, MDIO_NAME_LEN);
+		mdiodev->read = bb_miiphy_read;
+		mdiodev->write = bb_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 		for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) {
 			if ((mux_ch == 1) && !ch0_rgmii2_present)
 				continue;
@@ -437,8 +446,18 @@
 		print_fpga_info(k, false);
 		osd_probe(k);
 		if (feature_carrier_speed == CARRIER_SPEED_1G) {
-			miiphy_register(bb_miiphy_buses[k].name,
-					bb_miiphy_read, bb_miiphy_write);
+			int retval;
+			struct mii_dev *mdiodev = mdio_alloc();
+			if (!mdiodev)
+				return -ENOMEM;
+			strncpy(mdiodev->name, bb_miiphy_buses[k].name,
+				MDIO_NAME_LEN);
+			mdiodev->read = bb_miiphy_read;
+			mdiodev->write = bb_miiphy_write;
+
+			retval = mdio_register(mdiodev);
+			if (retval < 0)
+				return retval;
 			setup_88e1518(bb_miiphy_buses[k].name, 0);
 		}
 	}
diff --git a/board/gdsys/405ex/405ex.c b/board/gdsys/405ex/405ex.c
index c1a583f..9e1c57f 100644
--- a/board/gdsys/405ex/405ex.c
+++ b/board/gdsys/405ex/405ex.c
@@ -24,14 +24,6 @@
 	return gd->arch.fpga_state[dev];
 }
 
-void print_fpga_state(unsigned dev)
-{
-	if (gd->arch.fpga_state[dev] & FPGA_STATE_DONE_FAILED)
-		puts("       Waiting for FPGA-DONE timed out.\n");
-	if (gd->arch.fpga_state[dev] & FPGA_STATE_REFLECTION_FAILED)
-		puts("       FPGA reflection test failed.\n");
-}
-
 int board_early_init_f(void)
 {
 	u32 val;
diff --git a/board/gdsys/405ex/io64.c b/board/gdsys/405ex/io64.c
index 3a075c4..848cdde 100644
--- a/board/gdsys/405ex/io64.c
+++ b/board/gdsys/405ex/io64.c
@@ -246,8 +246,17 @@
 	/* setup Gbit PHYs */
 	puts("TRANS: ");
 	puts(str_phys);
-	miiphy_register(CONFIG_SYS_GBIT_MII_BUSNAME,
-		bb_miiphy_read, bb_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, CONFIG_SYS_GBIT_MII_BUSNAME, MDIO_NAME_LEN);
+	mdiodev->read = bb_miiphy_read;
+	mdiodev->write = bb_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 
 	for (k = 0; k < 32; ++k) {
 		configure_gbit_phy(CONFIG_SYS_GBIT_MII_BUSNAME, k);
@@ -255,8 +264,16 @@
 		putc(slash[k % 8]);
 	}
 
-	miiphy_register(CONFIG_SYS_GBIT_MII1_BUSNAME,
-		bb_miiphy_read, bb_miiphy_write);
+	mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, CONFIG_SYS_GBIT_MII1_BUSNAME, MDIO_NAME_LEN);
+	mdiodev->read = bb_miiphy_read;
+	mdiodev->write = bb_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 
 	for (k = 0; k < 32; ++k) {
 		configure_gbit_phy(CONFIG_SYS_GBIT_MII1_BUSNAME, k);
diff --git a/board/gdsys/mpc8308/hrcon.c b/board/gdsys/mpc8308/hrcon.c
index 880b638..f55893f 100644
--- a/board/gdsys/mpc8308/hrcon.c
+++ b/board/gdsys/mpc8308/hrcon.c
@@ -162,8 +162,17 @@
 	}
 
 	if (hw_type_cat) {
-		miiphy_register(bb_miiphy_buses[0].name, bb_miiphy_read,
-				bb_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, bb_miiphy_buses[0].name, MDIO_NAME_LEN);
+		mdiodev->read = bb_miiphy_read;
+		mdiodev->write = bb_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 		for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) {
 			if ((mux_ch == 1) && !ch0_rgmii2_present)
 				continue;
@@ -199,8 +208,18 @@
 		osd_probe(k + 4);
 #endif
 		if (hw_type_cat) {
-			miiphy_register(bb_miiphy_buses[k].name,
-					bb_miiphy_read, bb_miiphy_write);
+			int retval;
+			struct mii_dev *mdiodev = mdio_alloc();
+			if (!mdiodev)
+				return -ENOMEM;
+			strncpy(mdiodev->name, bb_miiphy_buses[k].name,
+				MDIO_NAME_LEN);
+			mdiodev->read = bb_miiphy_read;
+			mdiodev->write = bb_miiphy_write;
+
+			retval = mdio_register(mdiodev);
+			if (retval < 0)
+				return retval;
 			setup_88e1514(bb_miiphy_buses[k].name, 0);
 		}
 	}
diff --git a/board/gdsys/mpc8308/mpc8308.c b/board/gdsys/mpc8308/mpc8308.c
index 4338a33..1b8e035 100644
--- a/board/gdsys/mpc8308/mpc8308.c
+++ b/board/gdsys/mpc8308/mpc8308.c
@@ -31,14 +31,6 @@
 	return gd->arch.fpga_state[dev];
 }
 
-void print_fpga_state(unsigned dev)
-{
-	if (gd->arch.fpga_state[dev] & FPGA_STATE_DONE_FAILED)
-		puts("       Waiting for FPGA-DONE timed out.\n");
-	if (gd->arch.fpga_state[dev] & FPGA_STATE_REFLECTION_FAILED)
-		puts("       FPGA reflection test failed.\n");
-}
-
 int board_early_init_f(void)
 {
 	unsigned k;
diff --git a/board/gdsys/mpc8308/strider.c b/board/gdsys/mpc8308/strider.c
index 121977d..b8dde5f 100644
--- a/board/gdsys/mpc8308/strider.c
+++ b/board/gdsys/mpc8308/strider.c
@@ -179,8 +179,17 @@
 	}
 
 	if (hw_type_cat) {
-		miiphy_register(bb_miiphy_buses[0].name, bb_miiphy_read,
-				bb_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, bb_miiphy_buses[0].name, MDIO_NAME_LEN);
+		mdiodev->read = bb_miiphy_read;
+		mdiodev->write = bb_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 		for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) {
 			if ((mux_ch == 1) && !ch0_sgmii2_present)
 				continue;
@@ -252,8 +261,18 @@
 		dp501_probe(k, false);
 #endif
 		if (hw_type_cat) {
-			miiphy_register(bb_miiphy_buses[k].name,
-					bb_miiphy_read, bb_miiphy_write);
+			int retval;
+			struct mii_dev *mdiodev = mdio_alloc();
+			if (!mdiodev)
+				return -ENOMEM;
+			strncpy(mdiodev->name, bb_miiphy_buses[k].name,
+				MDIO_NAME_LEN);
+			mdiodev->read = bb_miiphy_read;
+			mdiodev->write = bb_miiphy_write;
+
+			retval = mdio_register(mdiodev);
+			if (retval < 0)
+				return retval;
 			setup_88e1514(bb_miiphy_buses[k].name, 0);
 		}
 	}
diff --git a/board/ge/bx50v3/bx50v3.c b/board/ge/bx50v3/bx50v3.c
index d45ed44..e9729f8 100644
--- a/board/ge/bx50v3/bx50v3.c
+++ b/board/ge/bx50v3/bx50v3.c
@@ -60,7 +60,7 @@
 
 int dram_init(void)
 {
-	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
+	gd->ram_size = imx_ddr_size();
 
 	return 0;
 }
diff --git a/board/gumstix/duovero/duovero.c b/board/gumstix/duovero/duovero.c
index 9671c5a..3786842 100644
--- a/board/gumstix/duovero/duovero.c
+++ b/board/gumstix/duovero/duovero.c
@@ -128,7 +128,7 @@
 #define GPMC_BASEADDR_MASK	0x3F
 #define GPMC_CS_ENABLE		0x1
 
-static void enable_gpmc_net_config(const u32 *gpmc_config, struct gpmc_cs *cs,
+static void enable_gpmc_net_config(const u32 *gpmc_config, const struct gpmc_cs *cs,
 		u32 base, u32 size)
 {
 	writel(0, &cs->config7);
diff --git a/board/hisilicon/hikey/hikey.c b/board/hisilicon/hikey/hikey.c
index 7abc678..72d6334 100644
--- a/board/hisilicon/hikey/hikey.c
+++ b/board/hisilicon/hikey/hikey.c
@@ -93,12 +93,14 @@
 
 static struct mm_region hikey_mem_map[] = {
 	{
-		.base = 0x0UL,
+		.virt = 0x0UL,
+		.phys = 0x0UL,
 		.size = 0x80000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_INNER_SHARE
 	}, {
-		.base = 0x80000000UL,
+		.virt = 0x80000000UL,
+		.phys = 0x80000000UL,
 		.size = 0x80000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE |
diff --git a/board/intel/bayleybay/acpi/mainboard.asl b/board/intel/bayleybay/acpi/mainboard.asl
index 21785ea..8b7ee3f 100644
--- a/board/intel/bayleybay/acpi/mainboard.asl
+++ b/board/intel/bayleybay/acpi/mainboard.asl
@@ -9,3 +9,41 @@
 {
 	Name(_HID, EISAID("PNP0C0C"))
 }
+
+/* PS/2 keyboard and mouse */
+Scope (\_SB.PCI0.LPCB)
+{
+	/* 8042 Keyboard */
+	Device (PS2K)
+	{
+		Name(_HID, EISAID("PNP0303"))
+		Name(_CRS, ResourceTemplate()
+		{
+			IO(Decode16, 0x60, 0x60, 0x00, 0x01)
+			IO(Decode16, 0x64, 0x64, 0x00, 0x01)
+			IRQNoFlags() { 1 }
+		})
+
+		Method(_STA, 0, Serialized)
+		{
+			Return (STA_VISIBLE)
+		}
+	}
+
+	/* 8042 Mouse */
+	Device (PS2M)
+	{
+		Name(_HID, EISAID("PNP0F03"))
+		Name(_CRS, ResourceTemplate()
+		{
+			IO(Decode16, 0x60, 0x60, 0x00, 0x01)
+			IO(Decode16, 0x64, 0x64, 0x00, 0x01)
+			IRQNoFlags() { 12 }
+		})
+
+		Method(_STA, 0, Serialized)
+		{
+			Return (STA_VISIBLE)
+		}
+	}
+}
diff --git a/board/inversepath/usbarmory/usbarmory.c b/board/inversepath/usbarmory/usbarmory.c
index a809039..c875e78 100644
--- a/board/inversepath/usbarmory/usbarmory.c
+++ b/board/inversepath/usbarmory/usbarmory.c
@@ -415,3 +415,34 @@
 	puts("Board: Inverse Path USB armory MkI\n");
 	return 0;
 }
+
+#ifndef CONFIG_CMDLINE
+static char *ext2_argv[] = {
+	"ext2load",
+	"mmc",
+	"0:1",
+	USBARMORY_FIT_ADDR,
+	USBARMORY_FIT_PATH
+};
+
+static char *bootm_argv[] = {
+	"bootm",
+	USBARMORY_FIT_ADDR
+};
+
+int board_run_command(const char *cmdline)
+{
+	printf("%s %s %s %s %s\n", ext2_argv[0], ext2_argv[1], ext2_argv[2],
+	       ext2_argv[3], ext2_argv[4]);
+
+	if (do_ext2load(NULL, 0, 5, ext2_argv) != 0) {
+		udelay(5*1000*1000);
+		return 1;
+	}
+
+	printf("%s %s\n", bootm_argv[0], bootm_argv[1]);
+	do_bootm(NULL, 0, 2, bootm_argv);
+
+	return 1;
+}
+#endif
diff --git a/board/isee/igep00x0/igep00x0.c b/board/isee/igep00x0/igep00x0.c
index d1a6a6f..808955e 100644
--- a/board/isee/igep00x0/igep00x0.c
+++ b/board/isee/igep00x0/igep00x0.c
@@ -10,6 +10,7 @@
 #include <ns16550.h>
 #include <twl4030.h>
 #include <netdev.h>
+#include <spl.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch/mem.h>
@@ -17,21 +18,32 @@
 #include <asm/arch/mux.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/mach-types.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/onenand.h>
+#include <jffs2/load_kernel.h>
 #include "igep00x0.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#if defined(CONFIG_CMD_NET)
-/* GPMC definitions for LAN9221 chips */
-static const u32 gpmc_lan_config[] = {
-	NET_LAN9221_GPMC_CONFIG1,
-	NET_LAN9221_GPMC_CONFIG2,
-	NET_LAN9221_GPMC_CONFIG3,
-	NET_LAN9221_GPMC_CONFIG4,
-	NET_LAN9221_GPMC_CONFIG5,
-	NET_LAN9221_GPMC_CONFIG6,
-};
+const omap3_sysinfo sysinfo = {
+	DDR_STACKED,
+#if (CONFIG_MACH_TYPE == MACH_TYPE_IGEP0020)
+	"IGEPv2",
+#endif
+#if (CONFIG_MACH_TYPE == MACH_TYPE_IGEP0030)
+	"IGEP COM MODULE/ELECTRON",
+#endif
+#if (CONFIG_MACH_TYPE == MACH_TYPE_IGEP0032)
+	"IGEP COM PROTON",
+#endif
+#if defined(CONFIG_ENV_IS_IN_ONENAND)
+	"ONENAND",
+#else
+	"NAND",
 #endif
+};
 
 static const struct ns16550_platdata igep_serial = {
 	.base = OMAP34XX_UART3,
@@ -50,7 +62,25 @@
  */
 int board_init(void)
 {
-	gpmc_init(); /* in SRAM or SDRAM, finish GPMC */
+	int loops = 100;
+
+	/* find out flash memory type, assume NAND first */
+	gpmc_cs0_flash = MTD_DEV_TYPE_NAND;
+	gpmc_init();
+
+	/* Issue a RESET and then READID */
+	writeb(NAND_CMD_RESET, &gpmc_cfg->cs[0].nand_cmd);
+	writeb(NAND_CMD_STATUS, &gpmc_cfg->cs[0].nand_cmd);
+	while ((readl(&gpmc_cfg->cs[0].nand_dat) & NAND_STATUS_READY)
+	                                        != NAND_STATUS_READY) {
+		udelay(1);
+		if (--loops == 0) {
+			gpmc_cs0_flash = MTD_DEV_TYPE_ONENAND;
+			gpmc_init();	/* reinitialize for OneNAND */
+			break;
+		}
+	}
+
 	/* boot param addr */
 	gd->bd->bi_boot_params = (OMAP34XX_SDRC_CS0 + 0x100);
 
@@ -63,45 +93,60 @@
 
 #ifdef CONFIG_SPL_BUILD
 /*
- * Routine: omap_rev_string
- * Description: For SPL builds output board rev
- */
-void omap_rev_string(void)
-{
-}
-
-/*
  * Routine: get_board_mem_timings
  * Description: If we use SPL then there is no x-loader nor config header
  * so we have to setup the DDR timings ourself on both banks.
  */
 void get_board_mem_timings(struct board_sdrc_timings *timings)
 {
-	timings->mr = MICRON_V_MR_165;
-#ifdef CONFIG_BOOT_NAND
-	timings->mcfg = MICRON_V_MCFG_200(256 << 20);
-	timings->ctrla = MICRON_V_ACTIMA_200;
-	timings->ctrlb = MICRON_V_ACTIMB_200;
-	timings->rfr_ctrl = SDP_3430_SDRC_RFR_CTRL_200MHz;
-#else
-	if (get_cpu_family() == CPU_OMAP34XX) {
-		timings->mcfg = NUMONYX_V_MCFG_165(256 << 20);
-		timings->ctrla = NUMONYX_V_ACTIMA_165;
-		timings->ctrlb = NUMONYX_V_ACTIMB_165;
-		timings->rfr_ctrl = SDP_3430_SDRC_RFR_CTRL_165MHz;
+	int mfr, id, err = identify_nand_chip(&mfr, &id);
 
-	} else {
-		timings->mcfg = NUMONYX_V_MCFG_200(256 << 20);
-		timings->ctrla = NUMONYX_V_ACTIMA_200;
-		timings->ctrlb = NUMONYX_V_ACTIMB_200;
+	timings->mr = MICRON_V_MR_165;
+	if (!err && mfr == NAND_MFR_MICRON) {
+		timings->mcfg = MICRON_V_MCFG_200(256 << 20);
+		timings->ctrla = MICRON_V_ACTIMA_200;
+		timings->ctrlb = MICRON_V_ACTIMB_200;
 		timings->rfr_ctrl = SDP_3430_SDRC_RFR_CTRL_200MHz;
+		gpmc_cs0_flash = MTD_DEV_TYPE_NAND;
+	} else {
+		if (get_cpu_family() == CPU_OMAP34XX) {
+			timings->mcfg = NUMONYX_V_MCFG_165(256 << 20);
+			timings->ctrla = NUMONYX_V_ACTIMA_165;
+			timings->ctrlb = NUMONYX_V_ACTIMB_165;
+			timings->rfr_ctrl = SDP_3430_SDRC_RFR_CTRL_165MHz;
+		} else {
+			timings->mcfg = NUMONYX_V_MCFG_200(256 << 20);
+			timings->ctrla = NUMONYX_V_ACTIMA_200;
+			timings->ctrlb = NUMONYX_V_ACTIMB_200;
+			timings->rfr_ctrl = SDP_3430_SDRC_RFR_CTRL_200MHz;
+		}
+		gpmc_cs0_flash = MTD_DEV_TYPE_ONENAND;
 	}
-#endif
+}
+
+#ifdef CONFIG_SPL_OS_BOOT
+int spl_start_uboot(void)
+{
+	/* break into full u-boot on 'c' */
+	if (serial_tstc() && serial_getc() == 'c')
+		return 1;
+
+	return 0;
 }
 #endif
+#endif
 
-#if defined(CONFIG_CMD_NET)
+int onenand_board_init(struct mtd_info *mtd)
+{
+	if (gpmc_cs0_flash == MTD_DEV_TYPE_ONENAND) {
+		struct onenand_chip *this = mtd->priv;
+		this->base = (void *)CONFIG_SYS_ONENAND_BASE;
+		return 0;
+	}
+	return 1;
+}
 
+#if defined(CONFIG_CMD_NET)
 static void reset_net_chip(int gpio)
 {
 	if (!gpio_request(gpio, "eth nrst")) {
@@ -122,6 +167,14 @@
 static void setup_net_chip(void)
 {
 	struct ctrl *ctrl_base = (struct ctrl *)OMAP34XX_CTRL_BASE;
+	static const u32 gpmc_lan_config[] = {
+		NET_LAN9221_GPMC_CONFIG1,
+		NET_LAN9221_GPMC_CONFIG2,
+		NET_LAN9221_GPMC_CONFIG3,
+		NET_LAN9221_GPMC_CONFIG4,
+		NET_LAN9221_GPMC_CONFIG5,
+		NET_LAN9221_GPMC_CONFIG6,
+	};
 
 	enable_gpmc_cs_config(gpmc_lan_config, &gpmc_cfg->cs[5],
 			CONFIG_SMC911X_BASE, GPMC_SIZE_16M);
@@ -136,6 +189,15 @@
 
 	reset_net_chip(64);
 }
+
+int board_eth_init(bd_t *bis)
+{
+#ifdef CONFIG_SMC911X
+	return smc911x_initialize(0, CONFIG_SMC911X_BASE);
+#else
+	return 0;
+#endif
+}
 #else
 static inline void setup_net_chip(void) {}
 #endif
@@ -183,6 +245,23 @@
 	return 0;
 }
 
+void board_mtdparts_default(const char **mtdids, const char **mtdparts)
+{
+	struct mtd_info *mtd = get_mtd_device(NULL, 0);
+	if (mtd) {
+		static char ids[24];
+		static char parts[48];
+		const char *linux_name = "omap2-nand";
+		if (strncmp(mtd->name, "onenand0", 8) == 0)
+			linux_name = "omap2-onenand";
+		snprintf(ids, sizeof(ids), "%s=%s", mtd->name, linux_name);
+		snprintf(parts, sizeof(parts), "mtdparts=%s:%dk(SPL),-(UBI)",
+		         linux_name, 4 * mtd->erasesize >> 10);
+		*mtdids = ids;
+		*mtdparts = parts;
+	}
+}
+
 /*
  * Routine: set_muxconf_regs
  * Description: Setting up the configuration Mux registers specific to the
@@ -201,14 +280,3 @@
 	MUX_IGEP0030();
 #endif
 }
-
-#if defined(CONFIG_CMD_NET)
-int board_eth_init(bd_t *bis)
-{
-#ifdef CONFIG_SMC911X
-	return smc911x_initialize(0, CONFIG_SMC911X_BASE);
-#else
-	return 0;
-#endif
-}
-#endif
diff --git a/board/isee/igep00x0/igep00x0.h b/board/isee/igep00x0/igep00x0.h
index 3c7ff9b..5698efa 100644
--- a/board/isee/igep00x0/igep00x0.h
+++ b/board/isee/igep00x0/igep00x0.h
@@ -7,26 +7,6 @@
 #ifndef _IGEP00X0_H_
 #define _IGEP00X0_H_
 
-const omap3_sysinfo sysinfo = {
-	DDR_STACKED,
-#if (CONFIG_MACH_TYPE == MACH_TYPE_IGEP0020)
-	"IGEPv2",
-#endif
-#if (CONFIG_MACH_TYPE == MACH_TYPE_IGEP0030)
-	"IGEP COM MODULE/ELECTRON",
-#endif
-#if (CONFIG_MACH_TYPE == MACH_TYPE_IGEP0032)
-	"IGEP COM PROTON",
-#endif
-#if defined(CONFIG_ENV_IS_IN_ONENAND)
-	"ONENAND",
-#else
-	"NAND",
-#endif
-};
-
-static void setup_net_chip(void);
-
 /*
  * IEN  - Input Enable
  * IDIS - Input Disable
diff --git a/board/keymile/common/common.c b/board/keymile/common/common.c
index a42f3ec..0829b7f 100644
--- a/board/keymile/common/common.c
+++ b/board/keymile/common/common.c
@@ -53,7 +53,7 @@
 	sprintf((char *)buf, "0x%x", pnvramaddr);
 	setenv("pnvramaddr", (char *)buf);
 
-	/* try to read rootfssize (ram image) from envrionment */
+	/* try to read rootfssize (ram image) from environment */
 	p = getenv("rootfssize");
 	if (p != NULL)
 		strict_strtoul(p, 16, &rootfssize);
diff --git a/board/keymile/kmp204x/ddr.c b/board/keymile/kmp204x/ddr.c
index 34ac697..77af184 100644
--- a/board/keymile/kmp204x/ddr.c
+++ b/board/keymile/kmp204x/ddr.c
@@ -36,7 +36,7 @@
 	/* we have only one module, half str should be OK */
 	popts->half_strength_driver_enable = 1;
 
-	/* wrlvl values overriden as recommended by ddr init func */
+	/* wrlvl values overridden as recommended by ddr init func */
 	popts->wrlvl_override = 1;
 	popts->wrlvl_sample = 0xf;
 	popts->wrlvl_start = 0x6;
diff --git a/board/kylin/kylin_rk3036/MAINTAINERS b/board/kylin/kylin_rk3036/MAINTAINERS
deleted file mode 100644
index e69de29..0000000
--- a/board/kylin/kylin_rk3036/MAINTAINERS
+++ /dev/null
diff --git a/board/kylin/kylin_rk3036/kylin_rk3036.c b/board/kylin/kylin_rk3036/kylin_rk3036.c
deleted file mode 100644
index 2a25871..0000000
--- a/board/kylin/kylin_rk3036/kylin_rk3036.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * (C) Copyright 2015 Rockchip Electronics Co., Ltd
- *
- * SPDX-License-Identifier:     GPL-2.0+
- */
-
-#include <common.h>
-#include <dm.h>
-#include <asm/io.h>
-#include <asm/arch/uart.h>
-#include <asm/arch-rockchip/grf_rk3036.h>
-#include <asm/arch/sdram_rk3036.h>
-#include <asm/gpio.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#define GRF_BASE	0x20008000
-
-void get_ddr_config(struct rk3036_ddr_config *config)
-{
-	/* K4B4G1646Q config */
-	config->ddr_type = 3;
-	config->rank = 1;
-	config->cs0_row = 15;
-	config->cs1_row = 15;
-
-	/* 8bank */
-	config->bank = 3;
-	config->col = 10;
-
-	/* 16bit bw */
-	config->bw = 1;
-}
-
-#define FASTBOOT_KEY_GPIO 93
-
-int fastboot_key_pressed(void)
-{
-	gpio_request(FASTBOOT_KEY_GPIO, "fastboot_key");
-	gpio_direction_input(FASTBOOT_KEY_GPIO);
-	return !gpio_get_value(FASTBOOT_KEY_GPIO);
-}
-
-#define ROCKCHIP_BOOT_MODE_FASTBOOT	0x5242C309
-
-int board_late_init(void)
-{
-	struct rk3036_grf * const grf = (void *)GRF_BASE;
-	int boot_mode = readl(&grf->os_reg[4]);
-
-	/* Clear boot mode */
-	writel(0, &grf->os_reg[4]);
-
-	if (boot_mode == ROCKCHIP_BOOT_MODE_FASTBOOT ||
-	    fastboot_key_pressed()) {
-		printf("enter fastboot!\n");
-		setenv("preboot", "setenv preboot; fastboot usb0");
-	}
-
-	return 0;
-}
-
-int board_init(void)
-{
-	return 0;
-}
-
-int dram_init(void)
-{
-	gd->ram_size = sdram_size();
-
-	return 0;
-}
-
-#ifndef CONFIG_SYS_DCACHE_OFF
-void enable_caches(void)
-{
-	/* Enable D-cache. I-cache is already enabled in start.S */
-	dcache_enable();
-}
-#endif
diff --git a/board/logicpd/zoom1/zoom1.c b/board/logicpd/zoom1/zoom1.c
index 982619c..2821ee2 100644
--- a/board/logicpd/zoom1/zoom1.c
+++ b/board/logicpd/zoom1/zoom1.c
@@ -19,6 +19,7 @@
 #include <ns16550.h>
 #include <netdev.h>
 #include <twl4030.h>
+#include <linux/mtd/omap_gpmc.h>
 #include <asm/io.h>
 #include <asm/arch/mem.h>
 #include <asm/arch/mmc_host_def.h>
@@ -29,10 +30,10 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-/* gpmc_cfg is initialized by gpmc_init and we use it here */
-extern struct gpmc *gpmc_cfg;
-
-/* GPMC definitions for Ethenet Controller LAN9211 */
+/*
+ * gpmc_cfg is initialized by gpmc_init and we use it here.
+ * GPMC definitions for Ethenet Controller LAN9211
+ */
 static const u32 gpmc_lab_enet[] = {
 	ZOOM1_ENET_GPMC_CONF1,
 	ZOOM1_ENET_GPMC_CONF2,
diff --git a/board/micronas/vct/ebi_onenand.c b/board/micronas/vct/ebi_onenand.c
index 62eb648..ef892ca 100644
--- a/board/micronas/vct/ebi_onenand.c
+++ b/board/micronas/vct/ebi_onenand.c
@@ -169,7 +169,7 @@
 	return 0;
 }
 
-void onenand_board_init(struct mtd_info *mtd)
+int onenand_board_init(struct mtd_info *mtd)
 {
 	struct onenand_chip *chip = mtd->priv;
 
@@ -181,4 +181,6 @@
 
 	chip->read_bufferram = ebi_read_bufferram;
 	chip->write_bufferram = ebi_write_bufferram;
+
+	return 0;
 }
diff --git a/board/nvidia/p2371-2180/p2371-2180.c b/board/nvidia/p2371-2180/p2371-2180.c
index 0f587ea..dbdc1b6 100644
--- a/board/nvidia/p2371-2180/p2371-2180.c
+++ b/board/nvidia/p2371-2180/p2371-2180.c
@@ -30,6 +30,28 @@
 	ret = dm_i2c_write(dev, MAX77620_CNFG1_L2_REG, &val, 1);
 	if (ret)
 		printf("i2c_write 0 0x3c 0x27 failed: %d\n", ret);
+
+	/* Disable LDO4 discharge */
+	ret = dm_i2c_read(dev, MAX77620_CNFG2_L4_REG, &val, 1);
+	if (ret) {
+		printf("i2c_read 0 0x3c 0x2c failed: %d\n", ret);
+	} else {
+		val &= ~BIT(1); /* ADE */
+		ret = dm_i2c_write(dev, MAX77620_CNFG2_L4_REG, &val, 1);
+		if (ret)
+			printf("i2c_write 0 0x3c 0x2c failed: %d\n", ret);
+	}
+
+	/* Set MBLPD */
+	ret = dm_i2c_read(dev, MAX77620_CNFGGLBL1_REG, &val, 1);
+	if (ret) {
+		printf("i2c_write 0 0x3c 0x00 failed: %d\n", ret);
+	} else {
+		val |= BIT(6); /* MBLPD */
+		ret = dm_i2c_write(dev, MAX77620_CNFGGLBL1_REG, &val, 1);
+		if (ret)
+			printf("i2c_write 0 0x3c 0x00 failed: %d\n", ret);
+	}
 }
 
 /*
diff --git a/board/nvidia/p2571/max77620_init.h b/board/nvidia/p2571/max77620_init.h
index 92c3719..39e5501 100644
--- a/board/nvidia/p2571/max77620_init.h
+++ b/board/nvidia/p2571/max77620_init.h
@@ -13,6 +13,8 @@
 #define MAX77620_I2C_ADDR		0x78
 #define MAX77620_I2C_ADDR_7BIT		0x3C
 
+#define MAX77620_CNFGGLBL1_REG		0x00
+
 #define MAX77620_SD0_REG		0x16
 #define MAX77620_SD1_REG		0x17
 #define MAX77620_SD2_REG		0x18
diff --git a/board/nvidia/p2771-0000/p2771-0000.c b/board/nvidia/p2771-0000/p2771-0000.c
index 4ba8ebc..529ed9d 100644
--- a/board/nvidia/p2771-0000/p2771-0000.c
+++ b/board/nvidia/p2771-0000/p2771-0000.c
@@ -5,3 +5,51 @@
  */
 
 #include <common.h>
+#include <i2c.h>
+#include "../p2571/max77620_init.h"
+
+int tegra_board_init(void)
+{
+	struct udevice *dev;
+	uchar val;
+	int ret;
+
+	/* Turn on MAX77620 LDO3 to 3.3V for SD card power */
+	debug("%s: Set LDO3 for VDDIO_SDMMC_AP power to 3.3V\n", __func__);
+	ret = i2c_get_chip_for_busnum(0, MAX77620_I2C_ADDR_7BIT, 1, &dev);
+	if (ret) {
+		printf("%s: Cannot find MAX77620 I2C chip\n", __func__);
+		return ret;
+	}
+	/* 0xF2 for 3.3v, enabled: bit7:6 = 11 = enable, bit5:0 = voltage */
+	val = 0xF2;
+	ret = dm_i2c_write(dev, MAX77620_CNFG1_L3_REG, &val, 1);
+	if (ret) {
+		printf("i2c_write 0 0x3c 0x27 failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int tegra_pcie_board_init(void)
+{
+	struct udevice *dev;
+	uchar val;
+	int ret;
+
+	/* Turn on MAX77620 LDO7 to 1.05V for PEX power */
+	debug("%s: Set LDO7 for PEX power to 1.05V\n", __func__);
+	ret = i2c_get_chip_for_busnum(0, MAX77620_I2C_ADDR_7BIT, 1, &dev);
+	if (ret) {
+		printf("%s: Cannot find MAX77620 I2C chip\n", __func__);
+		return -1;
+	}
+	/* 0xC5 for 1.05v, enabled: bit7:6 = 11 = enable, bit5:0 = voltage */
+	val = 0xC5;
+	ret = dm_i2c_write(dev, MAX77620_CNFG1_L7_REG, &val, 1);
+	if (ret)
+		printf("i2c_write 0 0x3c 0x31 failed: %d\n", ret);
+
+	return 0;
+}
diff --git a/board/nvidia/venice2/as3722_init.c b/board/nvidia/venice2/as3722_init.c
index 960fea7..1770ec2 100644
--- a/board/nvidia/venice2/as3722_init.c
+++ b/board/nvidia/venice2/as3722_init.c
@@ -32,7 +32,18 @@
 {
 	debug("%s entry\n", __func__);
 
-	/* Don't need to set up VDD_CORE - already done - by OTP */
+#ifdef AS3722_SD1VOLTAGE_DATA
+	/* Set up VDD_CORE, for boards where OTP is incorrect*/
+	debug("%s: Setting VDD_CORE via AS3722 reg 1\n", __func__);
+	/* Configure VDD_CORE via the AS3722 PMIC on the PWR I2C bus */
+	tegra_i2c_ll_write_addr(AS3722_I2C_ADDR, 2);
+	tegra_i2c_ll_write_data(AS3722_SD1VOLTAGE_DATA, I2C_SEND_2_BYTES);
+	/*
+	 * Don't write SDCONTROL - it's already 0x7F, i.e. all SDs enabled.
+	 * tegra_i2c_ll_write_data(AS3722_SD1CONTROL_DATA, I2C_SEND_2_BYTES);
+	 */
+	udelay(10 * 1000);
+#endif
 
 	debug("%s: Setting VDD_CPU to 1.0V via AS3722 reg 0/4D\n", __func__);
 	/*
diff --git a/board/nvidia/venice2/as3722_init.h b/board/nvidia/venice2/as3722_init.h
index 992b11f..c6b1247 100644
--- a/board/nvidia/venice2/as3722_init.h
+++ b/board/nvidia/venice2/as3722_init.h
@@ -25,8 +25,10 @@
 #endif
 #define AS3722_SD0CONTROL_DATA	(0x0100 | AS3722_SDCONTROL_REG)
 
-#define AS3722_SD1VOLTAGE_DATA	(0x3200 | AS3722_SD1VOLTAGE_REG)
+#ifdef CONFIG_TARGET_JETSON_TK1
+#define AS3722_SD1VOLTAGE_DATA	(0x2800 | AS3722_SD1VOLTAGE_REG)
 #define AS3722_SD1CONTROL_DATA	(0x0200 | AS3722_SDCONTROL_REG)
+#endif
 
 #define AS3722_SD6CONTROL_DATA	(0x4000 | AS3722_SDCONTROL_REG)
 #define AS3722_SD6VOLTAGE_DATA	(0x2800 | AS3722_SD6VOLTAGE_REG)
diff --git a/board/phytec/pcm058/Kconfig b/board/phytec/pcm058/Kconfig
new file mode 100644
index 0000000..d099275
--- /dev/null
+++ b/board/phytec/pcm058/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_PCM058
+
+config SYS_BOARD
+	default "pcm058"
+
+config SYS_VENDOR
+	default "phytec"
+
+config SYS_CONFIG_NAME
+	default "pcm058"
+
+endif
diff --git a/board/phytec/pcm058/MAINTAINERS b/board/phytec/pcm058/MAINTAINERS
new file mode 100644
index 0000000..b0ca402
--- /dev/null
+++ b/board/phytec/pcm058/MAINTAINERS
@@ -0,0 +1,6 @@
+PHYTEC PHYBOARD MIRA
+M:	Stefano Babic <sbabic@denx.de>
+S:	Maintained
+F:	board/phytec/pcm058/
+F:	include/configs/pcm058.h
+F:	configs/pcm058_defconfig
diff --git a/board/phytec/pcm058/Makefile b/board/phytec/pcm058/Makefile
new file mode 100644
index 0000000..97733b1
--- /dev/null
+++ b/board/phytec/pcm058/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de>
+#
+# (C) Copyright 2011 Freescale Semiconductor, Inc.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y  := pcm058.o
diff --git a/board/phytec/pcm058/README b/board/phytec/pcm058/README
new file mode 100644
index 0000000..3327135
--- /dev/null
+++ b/board/phytec/pcm058/README
@@ -0,0 +1,35 @@
+Board information
+-----------------
+
+The SBC produced by Phytec has a SOM based on a i.MX6Q.
+The SOM is sold in two versions, with eMMC or with NAND. Support
+here is for the SOM with NAND.
+The evaluation board "phyBoard-Mira" is thought to be used
+together with the SOM.
+
+More information on the board can be found on manufacturer's
+website:
+
+http://www.phytec.de/produkt/single-board-computer/phyboard-mira/
+http://www.phytec.de/fileadmin/user_upload/images/content/1.Products/SOMs/phyCORE-i.MX6/L-808e_1.pdf
+
+Building U-Boot
+-------------------------------
+
+$ make pcm058_defconfig
+$ make
+
+This generates the artifacts SPL and u-boot.img.
+The SOM can boot from NAND or from SD-Card, having the SPI-NOR
+as second option.
+The dip switch "DIP-1" on the board let choose between
+NAND and SD.
+
+DIP-1 set to off:	Boot first from NAND, then try SPI
+DIP-1 set to on:	Boot first from SD, then try SPI
+
+The bootloader was tested with DIP-1 set to on. If a SD-card
+is present, then the RBL tries to load SPL from the SD Card, if not,
+RBL loads from SPI-NOR. The SPL tries then to load from the same
+device where SPL was loaded (SD or SPI). Booting from NAND is
+not supported.
diff --git a/board/phytec/pcm058/pcm058.c b/board/phytec/pcm058/pcm058.c
new file mode 100644
index 0000000..0ba4a2e
--- /dev/null
+++ b/board/phytec/pcm058/pcm058.c
@@ -0,0 +1,582 @@
+/*
+ * Copyright (C) 2016 Stefano Babic <sbabic@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/*
+ * Please note: there are two version of the board
+ * one with NAND and the other with eMMC.
+ * Both NAND and eMMC cannot be set because they share the
+ * same pins (SD4)
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/arch/mx6-ddr.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/boot_mode.h>
+#include <asm/imx-common/mxc_i2c.h>
+#include <asm/imx-common/spi.h>
+#include <asm/errno.h>
+#include <asm/gpio.h>
+#include <mmc.h>
+#include <i2c.h>
+#include <fsl_esdhc.h>
+#include <nand.h>
+#include <miiphy.h>
+#include <netdev.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/sections.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define UART_PAD_CTRL  (PAD_CTL_PUS_100K_UP |			\
+	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm |			\
+	PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
+
+#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP |			\
+	PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm |			\
+	PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
+
+#define ENET_PAD_CTRL  (PAD_CTL_PUS_100K_UP |			\
+	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
+
+#define SPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_SPEED_MED | \
+		      PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
+
+#define I2C_PAD_CTRL  (PAD_CTL_PUS_100K_UP |			\
+	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS |	\
+	PAD_CTL_ODE | PAD_CTL_SRE_FAST)
+
+#define I2C_PAD MUX_PAD_CTRL(I2C_PAD_CTRL)
+
+#define ASRC_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_100K_UP  |	\
+		      PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
+
+#define NAND_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
+	       PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
+
+#define ENET_PHY_RESET_GPIO IMX_GPIO_NR(1, 14)
+#define USDHC1_CD_GPIO	IMX_GPIO_NR(6, 31)
+#define USER_LED	IMX_GPIO_NR(1, 4)
+#define IMX6Q_DRIVE_STRENGTH	0x30
+
+int dram_init(void)
+{
+	gd->ram_size = imx_ddr_size();
+	return 0;
+}
+
+void board_turn_off_led(void)
+{
+	gpio_direction_output(USER_LED, 0);
+}
+
+static iomux_v3_cfg_t const uart1_pads[] = {
+	MX6_PAD_EIM_D26__UART2_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_EIM_D27__UART2_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+static iomux_v3_cfg_t const enet_pads[] = {
+	MX6_PAD_ENET_MDIO__ENET_MDIO		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_MDC__ENET_MDC		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TXC__RGMII_TXC	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TD0__RGMII_TD0	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TD1__RGMII_TD1	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TD2__RGMII_TD2	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TD3__RGMII_TD3	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_REF_CLK__ENET_TX_CLK	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_RXC__RGMII_RXC	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_RD0__RGMII_RD0	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_RD1__RGMII_RD1	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_RD2__RGMII_RD2	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_RD3__RGMII_RD3	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_SD2_DAT1__GPIO1_IO14	| MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+static iomux_v3_cfg_t const ecspi1_pads[] = {
+	MX6_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_EIM_D19__GPIO3_IO19 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+/* NAND */
+static iomux_v3_cfg_t const nfc_pads[] = {
+	MX6_PAD_NANDF_CLE__NAND_CLE     | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_NANDF_ALE__NAND_ALE     | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_NANDF_WP_B__NAND_WP_B   | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_NANDF_RB0__NAND_READY_B | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_NANDF_CS0__NAND_CE0_B   | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_NANDF_CS1__NAND_CE1_B	| MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_NANDF_CS2__NAND_CE2_B	| MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_NANDF_CS3__NAND_CE3_B	| MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_SD4_CMD__NAND_RE_B      | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_SD4_CLK__NAND_WE_B      | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_NANDF_D0__NAND_DATA00   | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_NANDF_D1__NAND_DATA01   | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_NANDF_D2__NAND_DATA02   | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_NANDF_D3__NAND_DATA03   | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_NANDF_D4__NAND_DATA04   | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_NANDF_D5__NAND_DATA05   | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_NANDF_D6__NAND_DATA06   | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_NANDF_D7__NAND_DATA07   | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX6_PAD_SD4_DAT0__NAND_DQS	| MUX_PAD_CTRL(NAND_PAD_CTRL),
+};
+
+
+/* GPIOS */
+static iomux_v3_cfg_t const gpios_pads[] = {
+};
+
+static struct i2c_pads_info i2c_pad_info2 = {
+	.scl = {
+		.i2c_mode = MX6_PAD_GPIO_5__I2C3_SCL | I2C_PAD,
+		.gpio_mode = MX6_PAD_GPIO_5__GPIO1_IO05 | I2C_PAD,
+		.gp = IMX_GPIO_NR(1, 5)
+	},
+	.sda = {
+		.i2c_mode = MX6_PAD_GPIO_6__I2C3_SDA | I2C_PAD,
+		.gpio_mode = MX6_PAD_GPIO_6__GPIO1_IO06 | I2C_PAD,
+		.gp = IMX_GPIO_NR(1, 6)
+	}
+};
+
+static struct fsl_esdhc_cfg usdhc_cfg[] = {
+	{.esdhc_base = USDHC1_BASE_ADDR,
+	.max_bus_width = 4},
+#ifndef CONFIG_CMD_NAND
+	{USDHC4_BASE_ADDR},
+#endif
+};
+
+static iomux_v3_cfg_t const usdhc1_pads[] = {
+	MX6_PAD_SD1_CLK__SD1_CLK	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD1_CMD__SD1_CMD	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD1_DAT0__SD1_DATA0	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD1_DAT1__SD1_DATA1	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD1_DAT2__SD1_DATA2	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD1_DAT3__SD1_DATA3	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_EIM_BCLK__GPIO6_IO31	| MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
+};
+
+#ifndef CONFIG_CMD_NAND
+static iomux_v3_cfg_t const usdhc4_pads[] = {
+	MX6_PAD_SD4_CLK__SD4_CLK	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_CMD__SD4_CMD	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT0__SD4_DATA0	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT1__SD4_DATA1	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT2__SD4_DATA2	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT3__SD4_DATA3	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT4__SD4_DATA4	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT5__SD4_DATA5	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT6__SD4_DATA6	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT7__SD4_DATA7	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+};
+#endif
+
+int board_mmc_get_env_dev(int devno)
+{
+	return devno - 1;
+}
+
+int board_mmc_getcd(struct mmc *mmc)
+{
+	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+	int ret = 0;
+
+	switch (cfg->esdhc_base) {
+	case USDHC1_BASE_ADDR:
+		ret = !gpio_get_value(USDHC1_CD_GPIO);
+		break;
+	case USDHC4_BASE_ADDR:
+		ret = 1; /* eMMC/uSDHC4 is always present */
+		break;
+	}
+
+	return ret;
+}
+
+int board_mmc_init(bd_t *bis)
+{
+#ifndef CONFIG_SPL_BUILD
+	int ret;
+	int i;
+
+	for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) {
+		switch (i) {
+		case 0:
+			imx_iomux_v3_setup_multiple_pads(
+				usdhc1_pads, ARRAY_SIZE(usdhc1_pads));
+			gpio_direction_input(USDHC1_CD_GPIO);
+			usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
+			break;
+#ifndef CONFIG_CMD_NAND
+		case 1:
+			imx_iomux_v3_setup_multiple_pads(
+				usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
+			usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
+			break;
+#endif
+		default:
+			printf("Warning: you configured more USDHC controllers"
+			       "(%d) then supported by the board (%d)\n",
+			       i + 1, CONFIG_SYS_FSL_USDHC_NUM);
+			return -EINVAL;
+		}
+
+		ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+#else
+	struct src *psrc = (struct src *)SRC_BASE_ADDR;
+	unsigned reg = readl(&psrc->sbmr1) >> 11;
+	/*
+	 * Upon reading BOOT_CFG register the following map is done:
+	 * Bit 11 and 12 of BOOT_CFG register can determine the current
+	 * mmc port
+	 * 0x1                  SD1
+	 * 0x2                  SD2
+	 * 0x3                  SD4
+	 */
+
+	switch (reg & 0x3) {
+	case 0x0:
+		imx_iomux_v3_setup_multiple_pads(
+			usdhc1_pads, ARRAY_SIZE(usdhc1_pads));
+		gpio_direction_input(USDHC1_CD_GPIO);
+		usdhc_cfg[0].esdhc_base = USDHC1_BASE_ADDR;
+		usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
+		usdhc_cfg[0].max_bus_width = 4;
+		gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk;
+		break;
+	}
+	return fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
+#endif
+}
+
+static void setup_iomux_uart(void)
+{
+	imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
+}
+
+static void setup_iomux_enet(void)
+{
+	imx_iomux_v3_setup_multiple_pads(enet_pads, ARRAY_SIZE(enet_pads));
+
+	gpio_direction_output(ENET_PHY_RESET_GPIO, 0);
+	mdelay(10);
+	gpio_set_value(ENET_PHY_RESET_GPIO, 1);
+	mdelay(30);
+}
+
+static void setup_spi(void)
+{
+	gpio_request(IMX_GPIO_NR(3, 19), "spi_cs0");
+	gpio_direction_output(IMX_GPIO_NR(3, 19), 1);
+
+	imx_iomux_v3_setup_multiple_pads(ecspi1_pads, ARRAY_SIZE(ecspi1_pads));
+
+	enable_spi_clk(true, 0);
+}
+
+#ifdef CONFIG_CMD_NAND
+static void setup_gpmi_nand(void)
+{
+	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+	/* config gpmi nand iomux */
+	imx_iomux_v3_setup_multiple_pads(nfc_pads, ARRAY_SIZE(nfc_pads));
+
+	/* gate ENFC_CLK_ROOT clock first,before clk source switch */
+	clrbits_le32(&mxc_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK);
+
+	/* config gpmi and bch clock to 100 MHz */
+	clrsetbits_le32(&mxc_ccm->cs2cdr,
+			MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK |
+			MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK |
+			MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK,
+			MXC_CCM_CS2CDR_ENFC_CLK_PODF(0) |
+			MXC_CCM_CS2CDR_ENFC_CLK_PRED(3) |
+			MXC_CCM_CS2CDR_ENFC_CLK_SEL(3));
+
+	/* enable ENFC_CLK_ROOT clock */
+	setbits_le32(&mxc_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK);
+
+	/* enable gpmi and bch clock gating */
+	setbits_le32(&mxc_ccm->CCGR4,
+		     MXC_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB_MASK |
+		     MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH_MASK |
+		     MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK |
+		     MXC_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB_MASK |
+		     MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_OFFSET);
+
+	/* enable apbh clock gating */
+	setbits_le32(&mxc_ccm->CCGR0, MXC_CCM_CCGR0_APBHDMA_MASK);
+}
+#endif
+
+int board_spi_cs_gpio(unsigned bus, unsigned cs)
+{
+	if (bus != 0 || (cs != 0))
+		return -EINVAL;
+
+	return IMX_GPIO_NR(3, 19);
+}
+
+int board_eth_init(bd_t *bis)
+{
+	setup_iomux_enet();
+
+	return cpu_eth_init(bis);
+}
+
+int board_early_init_f(void)
+{
+	setup_iomux_uart();
+
+	return 0;
+}
+
+int board_init(void)
+{
+	/* address of boot parameters */
+	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
+
+#ifdef CONFIG_SYS_I2C_MXC
+	setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
+#endif
+
+#ifdef CONFIG_MXC_SPI
+	setup_spi();
+#endif
+
+#ifdef CONFIG_CMD_NAND
+	setup_gpmi_nand();
+#endif
+	return 0;
+}
+
+
+#ifdef CONFIG_CMD_BMODE
+/*
+ * BOOT_CFG1, BOOT_CFG2, BOOT_CFG3, BOOT_CFG4
+ * see Table 8-11 and Table 5-9
+ *  BOOT_CFG1[7] = 1 (boot from NAND)
+ *  BOOT_CFG1[5] = 0 - raw NAND
+ *  BOOT_CFG1[4] = 0 - default pad settings
+ *  BOOT_CFG1[3:2] = 00 - devices = 1
+ *  BOOT_CFG1[1:0] = 00 - Row Address Cycles = 3
+ *  BOOT_CFG2[4:3] = 00 - Boot Search Count = 2
+ *  BOOT_CFG2[2:1] = 01 - Pages In Block = 64
+ *  BOOT_CFG2[0] = 0 - Reset time 12ms
+ */
+static const struct boot_mode board_boot_modes[] = {
+	/* NAND: 64pages per block, 3 row addr cycles, 2 copies of FCB/DBBT */
+	{"nand", MAKE_CFGVAL(0x80, 0x02, 0x00, 0x00)},
+	{"mmc0",  MAKE_CFGVAL(0x40, 0x20, 0x00, 0x00)},
+	{NULL, 0},
+};
+#endif
+
+int board_late_init(void)
+{
+#ifdef CONFIG_CMD_BMODE
+	add_board_boot_modes(board_boot_modes);
+#endif
+
+	return 0;
+}
+
+#ifdef CONFIG_SPL_BUILD
+#include <spl.h>
+#include <libfdt.h>
+
+static const struct mx6dq_iomux_ddr_regs mx6_ddr_ioregs = {
+	.dram_sdclk_0 = 0x00000030,
+	.dram_sdclk_1 = 0x00000030,
+	.dram_cas = 0x00000030,
+	.dram_ras = 0x00000030,
+	.dram_reset = 0x00000030,
+	.dram_sdcke0 = 0x00000030,
+	.dram_sdcke1 = 0x00000030,
+	.dram_sdba2 = 0x00000000,
+	.dram_sdodt0 = 0x00000030,
+	.dram_sdodt1 = 0x00000030,
+	.dram_sdqs0 = 0x00000030,
+	.dram_sdqs1 = 0x00000030,
+	.dram_sdqs2 = 0x00000030,
+	.dram_sdqs3 = 0x00000030,
+	.dram_sdqs4 = 0x00000030,
+	.dram_sdqs5 = 0x00000030,
+	.dram_sdqs6 = 0x00000030,
+	.dram_sdqs7 = 0x00000030,
+	.dram_dqm0 = 0x00000030,
+	.dram_dqm1 = 0x00000030,
+	.dram_dqm2 = 0x00000030,
+	.dram_dqm3 = 0x00000030,
+	.dram_dqm4 = 0x00000030,
+	.dram_dqm5 = 0x00000030,
+	.dram_dqm6 = 0x00000030,
+	.dram_dqm7 = 0x00000030,
+};
+
+static const struct mx6dq_iomux_grp_regs mx6_grp_ioregs = {
+	.grp_ddr_type =  0x000C0000,
+	.grp_ddrmode_ctl =  0x00020000,
+	.grp_ddrpke =  0x00000000,
+	.grp_addds = IMX6Q_DRIVE_STRENGTH,
+	.grp_ctlds = IMX6Q_DRIVE_STRENGTH,
+	.grp_ddrmode =  0x00020000,
+	.grp_b0ds = IMX6Q_DRIVE_STRENGTH,
+	.grp_b1ds = IMX6Q_DRIVE_STRENGTH,
+	.grp_b2ds = IMX6Q_DRIVE_STRENGTH,
+	.grp_b3ds = IMX6Q_DRIVE_STRENGTH,
+	.grp_b4ds = IMX6Q_DRIVE_STRENGTH,
+	.grp_b5ds = IMX6Q_DRIVE_STRENGTH,
+	.grp_b6ds = IMX6Q_DRIVE_STRENGTH,
+	.grp_b7ds = IMX6Q_DRIVE_STRENGTH,
+};
+
+static const struct mx6_mmdc_calibration mx6_mmcd_calib = {
+	.p0_mpwldectrl0 =  0x00140014,
+	.p0_mpwldectrl1 =  0x000A0015,
+	.p1_mpwldectrl0 =  0x000A001E,
+	.p1_mpwldectrl1 =  0x000A0015,
+	.p0_mpdgctrl0 =  0x43080314,
+	.p0_mpdgctrl1 =  0x02680300,
+	.p1_mpdgctrl0 =  0x430C0318,
+	.p1_mpdgctrl1 =  0x03000254,
+	.p0_mprddlctl =  0x3A323234,
+	.p1_mprddlctl =  0x3E3C3242,
+	.p0_mpwrdlctl =  0x2A2E3632,
+	.p1_mpwrdlctl =  0x3C323E34,
+};
+
+static struct mx6_ddr3_cfg mem_ddr = {
+	.mem_speed = 1600,
+	.density = 2,
+	.width = 16,
+	.banks = 8,
+	.rowaddr = 14,
+	.coladdr = 10,
+	.pagesz = 2,
+	.trcd = 1375,
+	.trcmin = 4875,
+	.trasmin = 3500,
+	.SRT       = 1,
+};
+
+static void ccgr_init(void)
+{
+	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+	writel(0x00C03F3F, &ccm->CCGR0);
+	writel(0x0030FC03, &ccm->CCGR1);
+	writel(0x0FFFC000, &ccm->CCGR2);
+	writel(0x3FF00000, &ccm->CCGR3);
+	writel(0x00FFF300, &ccm->CCGR4);
+	writel(0x0F0000C3, &ccm->CCGR5);
+	writel(0x000003FF, &ccm->CCGR6);
+}
+
+static void gpr_init(void)
+{
+	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+
+	/* enable AXI cache for VDOA/VPU/IPU */
+	writel(0xF00000CF, &iomux->gpr[4]);
+	/* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
+	writel(0x007F007F, &iomux->gpr[6]);
+	writel(0x007F007F, &iomux->gpr[7]);
+}
+
+
+static void spl_dram_init(void)
+{
+	struct mx6_ddr_sysinfo sysinfo = {
+		/* width of data bus:0=16,1=32,2=64 */
+		.dsize = 2,
+		/* config for full 4GB range so that get_mem_size() works */
+		.cs_density = 32, /* 32Gb per CS */
+		/* single chip select */
+		.ncs = 1,
+		.cs1_mirror = 0,
+		.rtt_wr = 1 /*DDR3_RTT_60_OHM*/,	/* RTT_Wr = RZQ/4 */
+		.rtt_nom = 1 /*DDR3_RTT_60_OHM*/,	/* RTT_Nom = RZQ/4 */
+		.walat = 1,	/* Write additional latency */
+		.ralat = 5,	/* Read additional latency */
+		.mif3_mode = 3,	/* Command prediction working mode */
+		.bi_on = 1,	/* Bank interleaving enabled */
+		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
+		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+		.ddr_type = DDR_TYPE_DDR3,
+	};
+
+	mx6dq_dram_iocfg(64, &mx6_ddr_ioregs, &mx6_grp_ioregs);
+	mx6_dram_cfg(&sysinfo, &mx6_mmcd_calib, &mem_ddr);
+}
+
+void board_boot_order(u32 *spl_boot_list)
+{
+	spl_boot_list[0] = spl_boot_device();
+	printf("Boot device %x\n", spl_boot_list[0]);
+	switch (spl_boot_list[0]) {
+	case BOOT_DEVICE_SPI:
+		spl_boot_list[1] = BOOT_DEVICE_UART;
+		break;
+	case BOOT_DEVICE_MMC1:
+		spl_boot_list[1] = BOOT_DEVICE_SPI;
+		spl_boot_list[2] = BOOT_DEVICE_UART;
+		break;
+	default:
+		printf("Boot device %x\n", spl_boot_list[0]);
+	}
+}
+
+void board_init_f(ulong dummy)
+{
+#ifdef CONFIG_CMD_NAND
+	/* Enable NAND */
+	setup_gpmi_nand();
+#endif
+
+	/* setup clock gating */
+	ccgr_init();
+
+	/* setup AIPS and disable watchdog */
+	arch_cpu_init();
+
+	/* setup AXI */
+	gpr_init();
+
+	board_early_init_f();
+
+	/* setup GP timer */
+	timer_init();
+
+	setup_spi();
+
+	/* UART clocks enabled and gd valid - init serial console */
+	preloader_console_init();
+
+	/* DDR initialization */
+	spl_dram_init();
+
+	/* Clear the BSS. */
+	memset(__bss_start, 0, __bss_end - __bss_start);
+
+	/* load/boot image from boot device */
+	board_init_r(NULL, 0);
+}
+#endif
diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index c45ddb1..fbfbf6c 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -234,12 +234,14 @@
 #ifdef CONFIG_ARM64
 static struct mm_region bcm2837_mem_map[] = {
 	{
-		.base = 0x00000000UL,
+		.virt = 0x00000000UL,
+		.phys = 0x00000000UL,
 		.size = 0x3f000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_INNER_SHARE
 	}, {
-		.base = 0x3f000000UL,
+		.virt = 0x3f000000UL,
+		.phys = 0x3f000000UL,
 		.size = 0x01000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE |
diff --git a/board/evb_rk3036/evb_rk3036/Kconfig b/board/rockchip/evb_rk3036/Kconfig
similarity index 89%
rename from board/evb_rk3036/evb_rk3036/Kconfig
rename to board/rockchip/evb_rk3036/Kconfig
index ae2a9eb..ef45f62 100644
--- a/board/evb_rk3036/evb_rk3036/Kconfig
+++ b/board/rockchip/evb_rk3036/Kconfig
@@ -4,7 +4,7 @@
 	default "evb_rk3036"
 
 config SYS_VENDOR
-	default "evb_rk3036"
+	default "rockchip"
 
 config SYS_CONFIG_NAME
 	default "evb_rk3036"
diff --git a/board/rockchip/evb_rk3036/MAINTAINERS b/board/rockchip/evb_rk3036/MAINTAINERS
new file mode 100644
index 0000000..91f8a83
--- /dev/null
+++ b/board/rockchip/evb_rk3036/MAINTAINERS
@@ -0,0 +1,6 @@
+EVB-RK3036
+M:      huang lin <hl@rock-chips.com>
+S:      Maintained
+F:      board/rockchip/evb_rk3036
+F:      include/configs/evb_rk3036.h
+F:      configs/evb-rk3036_defconfig
diff --git a/board/evb_rk3036/evb_rk3036/Makefile b/board/rockchip/evb_rk3036/Makefile
similarity index 100%
rename from board/evb_rk3036/evb_rk3036/Makefile
rename to board/rockchip/evb_rk3036/Makefile
diff --git a/board/rockchip/evb_rk3036/evb_rk3036.c b/board/rockchip/evb_rk3036/evb_rk3036.c
new file mode 100644
index 0000000..e5582b4
--- /dev/null
+++ b/board/rockchip/evb_rk3036/evb_rk3036.c
@@ -0,0 +1,95 @@
+/*
+ * (C) Copyright 2015 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <asm/arch/uart.h>
+#include <asm/arch/sdram_rk3036.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void get_ddr_config(struct rk3036_ddr_config *config)
+{
+	/* K4B4G1646Q config */
+	config->ddr_type = 3;
+	config->rank = 2;
+	config->cs0_row = 15;
+	config->cs1_row = 15;
+
+	/* 8bank */
+	config->bank = 3;
+	config->col = 10;
+
+	/* 16bit bw */
+	config->bw = 1;
+}
+
+int board_init(void)
+{
+	return 0;
+}
+
+int dram_init(void)
+{
+	gd->ram_size = sdram_size();
+
+	return 0;
+}
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void enable_caches(void)
+{
+	/* Enable D-cache. I-cache is already enabled in start.S */
+	dcache_enable();
+}
+#endif
+
+#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
+#include <usb.h>
+#include <usb/dwc2_udc.h>
+
+static struct dwc2_plat_otg_data rk3036_otg_data = {
+	.rx_fifo_sz	= 512,
+	.np_tx_fifo_sz	= 16,
+	.tx_fifo_sz	= 128,
+};
+
+int board_usb_init(int index, enum usb_init_type init)
+{
+	int node;
+	const char *mode;
+	bool matched = false;
+	const void *blob = gd->fdt_blob;
+
+	/* find the usb_otg node */
+	node = fdt_node_offset_by_compatible(blob, -1,
+					"rockchip,rk3288-usb");
+
+	while (node > 0) {
+		mode = fdt_getprop(blob, node, "dr_mode", NULL);
+		if (mode && strcmp(mode, "otg") == 0) {
+			matched = true;
+			break;
+		}
+
+		node = fdt_node_offset_by_compatible(blob, node,
+					"rockchip,rk3288-usb");
+	}
+	if (!matched) {
+		debug("Not found usb_otg device\n");
+		return -ENODEV;
+	}
+	rk3036_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg");
+
+	return dwc2_udc_probe(&rk3036_otg_data);
+}
+
+int board_usb_cleanup(int index, enum usb_init_type init)
+{
+	return 0;
+}
+#endif
diff --git a/board/rockchip/evb_rk3288/Kconfig b/board/rockchip/evb_rk3288/Kconfig
new file mode 100644
index 0000000..8ab07f4
--- /dev/null
+++ b/board/rockchip/evb_rk3288/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_EVB_RK3288
+
+config SYS_BOARD
+	default "evb_rk3288"
+
+config SYS_VENDOR
+	default "rockchip"
+
+config SYS_CONFIG_NAME
+	default "evb_rk3288"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+
+endif
diff --git a/board/rockchip/evb_rk3288/MAINTAINERS b/board/rockchip/evb_rk3288/MAINTAINERS
new file mode 100644
index 0000000..8a4f127
--- /dev/null
+++ b/board/rockchip/evb_rk3288/MAINTAINERS
@@ -0,0 +1,6 @@
+EVB-RK3288
+M:	Lin Huang <hl@rock-chips.com>
+S:	Maintained
+F:	board/rockchip/evb_rk3288
+F:	include/configs/evb_rk3288.h
+F:	configs/evb-rk3288_defconfig
diff --git a/board/rockchip/evb_rk3288/Makefile b/board/rockchip/evb_rk3288/Makefile
new file mode 100644
index 0000000..c11b657
--- /dev/null
+++ b/board/rockchip/evb_rk3288/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2016 Rockchip Electronics Co., Ltd
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y	+= evb-rk3288.o
diff --git a/board/rockchip/evb_rk3288/evb-rk3288.c b/board/rockchip/evb_rk3288/evb-rk3288.c
new file mode 100644
index 0000000..a82f0ae
--- /dev/null
+++ b/board/rockchip/evb_rk3288/evb-rk3288.c
@@ -0,0 +1,15 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <spl.h>
+
+void board_boot_order(u32 *spl_boot_list)
+{
+	/* eMMC prior to sdcard. */
+	spl_boot_list[0] = BOOT_DEVICE_MMC2;
+	spl_boot_list[1] = BOOT_DEVICE_MMC1;
+}
diff --git a/board/rockchip/evb_rk3399/Kconfig b/board/rockchip/evb_rk3399/Kconfig
new file mode 100644
index 0000000..412b81c
--- /dev/null
+++ b/board/rockchip/evb_rk3399/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_EVB_RK3399
+
+config SYS_BOARD
+	default "evb_rk3399"
+
+config SYS_VENDOR
+	default "rockchip"
+
+config SYS_CONFIG_NAME
+	default "evb_rk3399"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+
+endif
diff --git a/board/evb_rk3036/evb_rk3036/MAINTAINERS b/board/rockchip/evb_rk3399/MAINTAINERS
similarity index 100%
rename from board/evb_rk3036/evb_rk3036/MAINTAINERS
rename to board/rockchip/evb_rk3399/MAINTAINERS
diff --git a/board/rockchip/evb_rk3399/Makefile b/board/rockchip/evb_rk3399/Makefile
new file mode 100644
index 0000000..aaa51c2
--- /dev/null
+++ b/board/rockchip/evb_rk3399/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2016 Rockchip Electronics Co., Ltd
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y	+= evb-rk3399.o
diff --git a/board/rockchip/evb_rk3399/README b/board/rockchip/evb_rk3399/README
new file mode 100644
index 0000000..fb8bb19
--- /dev/null
+++ b/board/rockchip/evb_rk3399/README
@@ -0,0 +1,73 @@
+Introduction
+============
+
+RK3399 key features we might use in U-Boot:
+* CPU: ARMv8 64bit Big-Little architecture,
+*      Big: dual-core Cortex-A72
+*      Little: quad-core Cortex-A53
+* IRAM: 200KB
+* DRAM: 4GB-128MB dual-channel
+* eMMC: support eMMC 5.0/5.1, suport HS400, HS200, DDR50
+* SD/MMC: support SD 3.0, MMC 4.51
+* USB: USB3.0 typc-C port *2 with dwc3 controller
+*      USB2.0 EHCI host port *2
+* Display: RGB/HDMI/DP/MIPI/EDP
+
+evb key features:
+* regulator: pwm regulator for CPU B/L
+* PMIC: rk808
+* debug console: UART2
+
+In order to support Arm Trust Firmware(ATF), we need to use the
+miniloader from rockchip which:
+* do DRAM init
+* load and verify ATF image
+* load and verify U-Boot image
+
+Here is the step-by-step to boot to U-Boot on rk3399.
+
+Get the Source and prebuild binary
+==================================
+
+  > mkdir ~/evb_rk3399
+  > cd ~/evb_rk3399
+  > git clone https://github.com/ARM-software/arm-trusted-firmware.git
+  > git clone https://github.com/rockchip-linux/rkbin
+  > git clone https://github.com/rockchip-linux/rkflashtool
+
+Compile the ATF
+===============
+
+  > cd arm-trusted-firmware
+  > make realclean
+  > make CROSS_COMPILE=aarch64-linux-gnu- PLAT=rk3399 bl31
+
+Compile the U-Boot
+==================
+
+  > cd ../u-boot
+  > make CROSS_COMPILE=aarch64-linux-gnu- evb-rk3399_defconfig all
+
+Compile the rkflashtool
+=======================
+
+  > cd ../rkflashtool
+  > make
+
+Package the image for miniloader
+================================
+  > cd ..
+  > cp arm-trusted-firmware/build/rk3399/release/bl31.bin rkbin/rk33
+  > ./rkbin/tools/trust_merger rkbin/tools/RK3399TRUST.ini
+  > ./rkbin/tools/loaderimage --pack --uboot u-boot/u-boot-dtb.bin uboot.img
+  > mkdir image
+  > mv trust.img ./image/
+  > mv uboot.img ./image/rk3399evb-uboot.bin
+
+Flash the image
+===============
+Power on(or reset with RESET KEY) with MASKROM KEY preesed, and then:
+
+  > ./rkflashtool/rkflashloader rk3399evb
+
+You should be able to get U-Boot log message in console/UART2 now.
diff --git a/board/rockchip/evb_rk3399/evb-rk3399.c b/board/rockchip/evb_rk3399/evb-rk3399.c
new file mode 100644
index 0000000..cb2d97d
--- /dev/null
+++ b/board/rockchip/evb_rk3399/evb-rk3399.c
@@ -0,0 +1,27 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+#include <common.h>
+#include <asm/armv8/mmu.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_init(void)
+{
+	return 0;
+}
+
+int dram_init(void)
+{
+	gd->ram_size = 0x80000000;
+	return 0;
+}
+
+void dram_init_banksize(void)
+{
+	/* Reserve 0x200000 for ATF bl31 */
+	gd->bd->bi_dram[0].start = 0x200000;
+	gd->bd->bi_dram[0].size = 0x80000000;
+}
diff --git a/board/rockchip/fennec_rk3288/Kconfig b/board/rockchip/fennec_rk3288/Kconfig
new file mode 100644
index 0000000..1dcfcf0
--- /dev/null
+++ b/board/rockchip/fennec_rk3288/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_FENNEC_RK3288
+
+config SYS_BOARD
+	default "fennec_rk3288"
+
+config SYS_VENDOR
+	default "rockchip"
+
+config SYS_CONFIG_NAME
+	default "fennec_rk3288"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+
+endif
diff --git a/board/rockchip/fennec_rk3288/MAINTAINERS b/board/rockchip/fennec_rk3288/MAINTAINERS
new file mode 100644
index 0000000..78a389b
--- /dev/null
+++ b/board/rockchip/fennec_rk3288/MAINTAINERS
@@ -0,0 +1,6 @@
+FENNEC-RK3288
+M:	Lin Huang <hl@rock-chips.com>
+S:	Maintained
+F:	board/rockchip/fennec_rk3288
+F:	include/configs/fennec_rk3288.h
+F:	configs/fennec-rk3288_defconfig
diff --git a/board/rockchip/fennec_rk3288/Makefile b/board/rockchip/fennec_rk3288/Makefile
new file mode 100644
index 0000000..b287db6
--- /dev/null
+++ b/board/rockchip/fennec_rk3288/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2016 Rockchip Electronics Co., Ltd
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y	+= fennec-rk3288.o
diff --git a/board/rockchip/fennec_rk3288/fennec-rk3288.c b/board/rockchip/fennec_rk3288/fennec-rk3288.c
new file mode 100644
index 0000000..aad74ef
--- /dev/null
+++ b/board/rockchip/fennec_rk3288/fennec-rk3288.c
@@ -0,0 +1,15 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <spl.h>
+
+void board_boot_order(u32 *spl_boot_list)
+{
+	/* eMMC prior to sdcard */
+	spl_boot_list[0] = BOOT_DEVICE_MMC2;
+	spl_boot_list[1] = BOOT_DEVICE_MMC1;
+}
diff --git a/board/kylin/kylin_rk3036/Kconfig b/board/rockchip/kylin_rk3036/Kconfig
similarity index 90%
rename from board/kylin/kylin_rk3036/Kconfig
rename to board/rockchip/kylin_rk3036/Kconfig
index 5d75c1f..8d35b4e 100644
--- a/board/kylin/kylin_rk3036/Kconfig
+++ b/board/rockchip/kylin_rk3036/Kconfig
@@ -4,7 +4,7 @@
 	default "kylin_rk3036"
 
 config SYS_VENDOR
-	default "kylin"
+	default "rockchip"
 
 config SYS_CONFIG_NAME
 	default "kylin_rk3036"
diff --git a/board/rockchip/kylin_rk3036/MAINTAINERS b/board/rockchip/kylin_rk3036/MAINTAINERS
new file mode 100644
index 0000000..5453e7d
--- /dev/null
+++ b/board/rockchip/kylin_rk3036/MAINTAINERS
@@ -0,0 +1,6 @@
+KYLIN-RK3036
+M:      huang lin <hl@rock-chips.com>
+S:      Maintained
+F:      board/rockchip/kylin_rk3036
+F:      include/configs/kylin_rk3036.h
+F:      configs/kylin-rk3036_defconfig
diff --git a/board/kylin/kylin_rk3036/Makefile b/board/rockchip/kylin_rk3036/Makefile
similarity index 100%
rename from board/kylin/kylin_rk3036/Makefile
rename to board/rockchip/kylin_rk3036/Makefile
diff --git a/board/rockchip/kylin_rk3036/kylin_rk3036.c b/board/rockchip/kylin_rk3036/kylin_rk3036.c
new file mode 100644
index 0000000..5ade695
--- /dev/null
+++ b/board/rockchip/kylin_rk3036/kylin_rk3036.c
@@ -0,0 +1,127 @@
+/*
+ * (C) Copyright 2015 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <asm/arch/uart.h>
+#include <asm/arch-rockchip/grf_rk3036.h>
+#include <asm/arch/sdram_rk3036.h>
+#include <asm/gpio.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define GRF_BASE	0x20008000
+
+void get_ddr_config(struct rk3036_ddr_config *config)
+{
+	/* K4B4G1646Q config */
+	config->ddr_type = 3;
+	config->rank = 1;
+	config->cs0_row = 15;
+	config->cs1_row = 15;
+
+	/* 8bank */
+	config->bank = 3;
+	config->col = 10;
+
+	/* 16bit bw */
+	config->bw = 1;
+}
+
+#define FASTBOOT_KEY_GPIO 93
+
+int fastboot_key_pressed(void)
+{
+	gpio_request(FASTBOOT_KEY_GPIO, "fastboot_key");
+	gpio_direction_input(FASTBOOT_KEY_GPIO);
+	return !gpio_get_value(FASTBOOT_KEY_GPIO);
+}
+
+#define ROCKCHIP_BOOT_MODE_FASTBOOT	0x5242C309
+
+int board_late_init(void)
+{
+	struct rk3036_grf * const grf = (void *)GRF_BASE;
+	int boot_mode = readl(&grf->os_reg[4]);
+
+	/* Clear boot mode */
+	writel(0, &grf->os_reg[4]);
+
+	if (boot_mode == ROCKCHIP_BOOT_MODE_FASTBOOT ||
+	    fastboot_key_pressed()) {
+		printf("enter fastboot!\n");
+		setenv("preboot", "setenv preboot; fastboot usb0");
+	}
+
+	return 0;
+}
+
+int board_init(void)
+{
+	return 0;
+}
+
+int dram_init(void)
+{
+	gd->ram_size = sdram_size();
+
+	return 0;
+}
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void enable_caches(void)
+{
+	/* Enable D-cache. I-cache is already enabled in start.S */
+	dcache_enable();
+}
+#endif
+
+#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
+#include <usb.h>
+#include <usb/dwc2_udc.h>
+
+static struct dwc2_plat_otg_data rk3036_otg_data = {
+	.rx_fifo_sz	= 512,
+	.np_tx_fifo_sz	= 16,
+	.tx_fifo_sz	= 128,
+};
+
+int board_usb_init(int index, enum usb_init_type init)
+{
+	int node;
+	const char *mode;
+	bool matched = false;
+	const void *blob = gd->fdt_blob;
+
+	/* find the usb_otg node */
+	node = fdt_node_offset_by_compatible(blob, -1,
+					"rockchip,rk3288-usb");
+
+	while (node > 0) {
+		mode = fdt_getprop(blob, node, "dr_mode", NULL);
+		if (mode && strcmp(mode, "otg") == 0) {
+			matched = true;
+			break;
+		}
+
+		node = fdt_node_offset_by_compatible(blob, node,
+					"rockchip,rk3288-usb");
+	}
+	if (!matched) {
+		debug("Not found usb_otg device\n");
+		return -ENODEV;
+	}
+	rk3036_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg");
+
+	return dwc2_udc_probe(&rk3036_otg_data);
+}
+
+int board_usb_cleanup(int index, enum usb_init_type init)
+{
+	return 0;
+}
+#endif
diff --git a/board/rockchip/miniarm_rk3288/Kconfig b/board/rockchip/miniarm_rk3288/Kconfig
new file mode 100644
index 0000000..529c09f
--- /dev/null
+++ b/board/rockchip/miniarm_rk3288/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_MINIARM_RK3288
+
+config SYS_BOARD
+	default "miniarm_rk3288"
+
+config SYS_VENDOR
+	default "rockchip"
+
+config SYS_CONFIG_NAME
+	default "miniarm_rk3288"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+
+endif
diff --git a/board/rockchip/miniarm_rk3288/MAINTAINERS b/board/rockchip/miniarm_rk3288/MAINTAINERS
new file mode 100644
index 0000000..7537b8f
--- /dev/null
+++ b/board/rockchip/miniarm_rk3288/MAINTAINERS
@@ -0,0 +1,6 @@
+MINIARM-RK3288
+M:	Lin Huang <hl@rock-chips.com>
+S:	Maintained
+F:	board/rockchip/miniarm_rk3288
+F:	include/configs/miniarm_rk3288.h
+F:	configs/miniarm-rk3288_defconfig
diff --git a/board/rockchip/miniarm_rk3288/Makefile b/board/rockchip/miniarm_rk3288/Makefile
new file mode 100644
index 0000000..9419b91
--- /dev/null
+++ b/board/rockchip/miniarm_rk3288/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2016 Rockchip Electronics Co., Ltd
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y	+= miniarm-rk3288.o
diff --git a/board/rockchip/miniarm_rk3288/miniarm-rk3288.c b/board/rockchip/miniarm_rk3288/miniarm-rk3288.c
new file mode 100644
index 0000000..aad74ef
--- /dev/null
+++ b/board/rockchip/miniarm_rk3288/miniarm-rk3288.c
@@ -0,0 +1,15 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <spl.h>
+
+void board_boot_order(u32 *spl_boot_list)
+{
+	/* eMMC prior to sdcard */
+	spl_boot_list[0] = BOOT_DEVICE_MMC2;
+	spl_boot_list[1] = BOOT_DEVICE_MMC1;
+}
diff --git a/board/samsung/goni/onenand.c b/board/samsung/goni/onenand.c
index b74d8e8..cbe1d12f 100644
--- a/board/samsung/goni/onenand.c
+++ b/board/samsung/goni/onenand.c
@@ -11,11 +11,13 @@
 #include <linux/mtd/samsung_onenand.h>
 #include <onenand_uboot.h>
 
-void onenand_board_init(struct mtd_info *mtd)
+int onenand_board_init(struct mtd_info *mtd)
 {
 	struct onenand_chip *this = mtd->priv;
 
 	this->base = (void *)CONFIG_SYS_ONENAND_BASE;
 	this->options |= ONENAND_RUNTIME_BADBLOCK_CHECK;
 	this->chip_probe = s5pc110_chip_probe;
+
+	return 0;
 }
diff --git a/board/samsung/smdkc100/onenand.c b/board/samsung/smdkc100/onenand.c
index 577c1a5..994d91d 100644
--- a/board/samsung/smdkc100/onenand.c
+++ b/board/samsung/smdkc100/onenand.c
@@ -16,7 +16,7 @@
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 
-void onenand_board_init(struct mtd_info *mtd)
+int onenand_board_init(struct mtd_info *mtd)
 {
 	struct onenand_chip *this = mtd->priv;
 	struct s5pc100_clock *clk =
@@ -65,4 +65,6 @@
 	writel(value, &onenand->int_err_mask);
 
 	s3c_onenand_init(mtd);
+
+	return 0;
 }
diff --git a/board/samsung/universal_c210/onenand.c b/board/samsung/universal_c210/onenand.c
index 28bc811..147a95e2 100644
--- a/board/samsung/universal_c210/onenand.c
+++ b/board/samsung/universal_c210/onenand.c
@@ -10,11 +10,13 @@
 #include <linux/mtd/onenand.h>
 #include <linux/mtd/samsung_onenand.h>
 
-void onenand_board_init(struct mtd_info *mtd)
+int onenand_board_init(struct mtd_info *mtd)
 {
 	struct onenand_chip *this = mtd->priv;
 
 	this->base = (void *)CONFIG_SYS_ONENAND_BASE;
 	this->options |= ONENAND_RUNTIME_BADBLOCK_CHECK;
 	this->chip_probe = s5pc210_chip_probe;
+
+	return 0;
 }
diff --git a/board/sandbox/MAINTAINERS b/board/sandbox/MAINTAINERS
index f5db773..4dcbf4b 100644
--- a/board/sandbox/MAINTAINERS
+++ b/board/sandbox/MAINTAINERS
@@ -11,3 +11,10 @@
 F:	board/sandbox/
 F:	include/configs/sandbox.h
 F:	configs/sandbox_noblk_defconfig
+
+SANDBOX SPL BOARD
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	board/sandbox/
+F:	include/configs/sandbox_spl.h
+F:	configs/sandbox_spl_defconfig
diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
index 9fe3bf1..ed820d3 100644
--- a/board/sandbox/README.sandbox
+++ b/board/sandbox/README.sandbox
@@ -44,6 +44,9 @@
       make sandbox_defconfig all NO_SDL=1
       ./u-boot
 
+   If you are building on a 32-bit machine you may get errors from __ffs.h
+   about shifting more than the machine word size. Edit the config file
+   include/configs/sandbox.h and change CONFIG_SANDBOX_BITS_PER_LONG to 32.
 
 U-Boot will start on your computer, showing a sandbox emulation of the serial
 console:
diff --git a/board/solidrun/mx6cuboxi/mx6cuboxi.c b/board/solidrun/mx6cuboxi/mx6cuboxi.c
index bcc9729..cafa348 100644
--- a/board/solidrun/mx6cuboxi/mx6cuboxi.c
+++ b/board/solidrun/mx6cuboxi/mx6cuboxi.c
@@ -367,14 +367,6 @@
 	return 0;
 }
 
-static bool is_mx6q(void)
-{
-	if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
-		return true;
-	else
-		return false;
-}
-
 int board_late_init(void)
 {
 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
@@ -383,7 +375,7 @@
 	else
 		setenv("board_name", "CUBOXI");
 
-	if (is_mx6q())
+	if (is_mx6dq())
 		setenv("board_rev", "MX6Q");
 	else
 		setenv("board_rev", "MX6DL");
@@ -615,7 +607,7 @@
 		.ddr_type = DDR_TYPE_DDR3,
 	};
 
-	if (is_cpu_type(MXC_CPU_MX6D) || is_cpu_type(MXC_CPU_MX6Q))
+	if (is_mx6dq())
 		mx6dq_dram_iocfg(width, &mx6q_ddr_ioregs, &mx6q_grp_ioregs);
 	else
 		mx6sdl_dram_iocfg(width, &mx6dl_ddr_ioregs, &mx6sdl_grp_ioregs);
diff --git a/board/st/stm32f746-disco/stm32f746-disco.c b/board/st/stm32f746-disco/stm32f746-disco.c
index 0e04d14..404fdfa 100644
--- a/board/st/stm32f746-disco/stm32f746-disco.c
+++ b/board/st/stm32f746-disco/stm32f746-disco.c
@@ -10,6 +10,8 @@
 #include <asm/armv7m.h>
 #include <asm/arch/stm32.h>
 #include <asm/arch/gpio.h>
+#include <asm/arch/rcc.h>
+#include <asm/arch/fmc.h>
 #include <dm/platdata.h>
 #include <dm/platform_data/serial_stm32x7.h>
 #include <asm/arch/stm32_periph.h>
@@ -33,6 +35,221 @@
 	.af = STM32_GPIO_AF7
 };
 
+const struct stm32_gpio_ctl gpio_ctl_fmc = {
+	.mode = STM32_GPIO_MODE_AF,
+	.otype = STM32_GPIO_OTYPE_PP,
+	.speed = STM32_GPIO_SPEED_100M,
+	.pupd = STM32_GPIO_PUPD_NO,
+	.af = STM32_GPIO_AF12
+};
+
+static const struct stm32_gpio_dsc ext_ram_fmc_gpio[] = {
+	/* Chip is LQFP144, see DM00077036.pdf for details */
+	{STM32_GPIO_PORT_D, STM32_GPIO_PIN_10},	/* 79, FMC_D15 */
+	{STM32_GPIO_PORT_D, STM32_GPIO_PIN_9},	/* 78, FMC_D14 */
+	{STM32_GPIO_PORT_D, STM32_GPIO_PIN_8},	/* 77, FMC_D13 */
+	{STM32_GPIO_PORT_E, STM32_GPIO_PIN_15},	/* 68, FMC_D12 */
+	{STM32_GPIO_PORT_E, STM32_GPIO_PIN_14},	/* 67, FMC_D11 */
+	{STM32_GPIO_PORT_E, STM32_GPIO_PIN_13},	/* 66, FMC_D10 */
+	{STM32_GPIO_PORT_E, STM32_GPIO_PIN_12},	/* 65, FMC_D9 */
+	{STM32_GPIO_PORT_E, STM32_GPIO_PIN_11},	/* 64, FMC_D8 */
+	{STM32_GPIO_PORT_E, STM32_GPIO_PIN_10},	/* 63, FMC_D7 */
+	{STM32_GPIO_PORT_E, STM32_GPIO_PIN_9},	/* 60, FMC_D6 */
+	{STM32_GPIO_PORT_E, STM32_GPIO_PIN_8},	/* 59, FMC_D5 */
+	{STM32_GPIO_PORT_E, STM32_GPIO_PIN_7},	/* 58, FMC_D4 */
+	{STM32_GPIO_PORT_D, STM32_GPIO_PIN_1},	/* 115, FMC_D3 */
+	{STM32_GPIO_PORT_D, STM32_GPIO_PIN_0},	/* 114, FMC_D2 */
+	{STM32_GPIO_PORT_D, STM32_GPIO_PIN_15},	/* 86, FMC_D1 */
+	{STM32_GPIO_PORT_D, STM32_GPIO_PIN_14},	/* 85, FMC_D0 */
+
+	{STM32_GPIO_PORT_E, STM32_GPIO_PIN_1},	/* 142, FMC_NBL1 */
+	{STM32_GPIO_PORT_E, STM32_GPIO_PIN_0},	/* 141, FMC_NBL0 */
+
+	{STM32_GPIO_PORT_G, STM32_GPIO_PIN_5},	/* 90, FMC_A15, BA1 */
+	{STM32_GPIO_PORT_G, STM32_GPIO_PIN_4},	/* 89, FMC_A14, BA0 */
+
+	{STM32_GPIO_PORT_G, STM32_GPIO_PIN_1},	/* 57, FMC_A11 */
+	{STM32_GPIO_PORT_G, STM32_GPIO_PIN_0},	/* 56, FMC_A10 */
+	{STM32_GPIO_PORT_F, STM32_GPIO_PIN_15},	/* 55, FMC_A9 */
+	{STM32_GPIO_PORT_F, STM32_GPIO_PIN_14},	/* 54, FMC_A8 */
+	{STM32_GPIO_PORT_F, STM32_GPIO_PIN_13},	/* 53, FMC_A7 */
+	{STM32_GPIO_PORT_F, STM32_GPIO_PIN_12},	/* 50, FMC_A6 */
+	{STM32_GPIO_PORT_F, STM32_GPIO_PIN_5},	/* 15, FMC_A5 */
+	{STM32_GPIO_PORT_F, STM32_GPIO_PIN_4},	/* 14, FMC_A4 */
+	{STM32_GPIO_PORT_F, STM32_GPIO_PIN_3},	/* 13, FMC_A3 */
+	{STM32_GPIO_PORT_F, STM32_GPIO_PIN_2},	/* 12, FMC_A2 */
+	{STM32_GPIO_PORT_F, STM32_GPIO_PIN_1},	/* 11, FMC_A1 */
+	{STM32_GPIO_PORT_F, STM32_GPIO_PIN_0},	/* 10, FMC_A0 */
+
+	{STM32_GPIO_PORT_H, STM32_GPIO_PIN_3},	/* 136, SDRAM_NE */
+	{STM32_GPIO_PORT_F, STM32_GPIO_PIN_11},	/* 49, SDRAM_NRAS */
+	{STM32_GPIO_PORT_G, STM32_GPIO_PIN_15},	/* 132, SDRAM_NCAS */
+	{STM32_GPIO_PORT_H, STM32_GPIO_PIN_5},	/* 26, SDRAM_NWE */
+	{STM32_GPIO_PORT_C, STM32_GPIO_PIN_3},	/* 135, SDRAM_CKE */
+
+	{STM32_GPIO_PORT_G, STM32_GPIO_PIN_8},	/* 93, SDRAM_CLK */
+};
+
+static int fmc_setup_gpio(void)
+{
+	int rv = 0;
+	int i;
+
+	clock_setup(GPIO_B_CLOCK_CFG);
+	clock_setup(GPIO_C_CLOCK_CFG);
+	clock_setup(GPIO_D_CLOCK_CFG);
+	clock_setup(GPIO_E_CLOCK_CFG);
+	clock_setup(GPIO_F_CLOCK_CFG);
+	clock_setup(GPIO_G_CLOCK_CFG);
+	clock_setup(GPIO_H_CLOCK_CFG);
+
+	for (i = 0; i < ARRAY_SIZE(ext_ram_fmc_gpio); i++) {
+		rv = stm32_gpio_config(&ext_ram_fmc_gpio[i],
+				&gpio_ctl_fmc);
+		if (rv)
+			goto out;
+	}
+
+out:
+	return rv;
+}
+
+/*
+ * STM32 RCC FMC specific definitions
+ */
+#define RCC_ENR_FMC	(1 << 0)	/* FMC module clock  */
+
+static inline u32 _ns2clk(u32 ns, u32 freq)
+{
+	u32 tmp = freq/1000000;
+	return (tmp * ns) / 1000;
+}
+
+#define NS2CLK(ns) (_ns2clk(ns, freq))
+
+/*
+ * Following are timings for IS42S16400J, from corresponding datasheet
+ */
+#define SDRAM_CAS	3	/* 3 cycles */
+#define SDRAM_NB	1	/* Number of banks */
+#define SDRAM_MWID	1	/* 16 bit memory */
+
+#define SDRAM_NR	0x1	/* 12-bit row */
+#define SDRAM_NC	0x0	/* 8-bit col */
+#define SDRAM_RBURST	0x1	/* Single read requests always as bursts */
+#define SDRAM_RPIPE	0x0	/* No HCLK clock cycle delay */
+
+#define SDRAM_TRRD	NS2CLK(12)
+#define SDRAM_TRCD	NS2CLK(18)
+#define SDRAM_TRP	NS2CLK(18)
+#define SDRAM_TRAS	NS2CLK(42)
+#define SDRAM_TRC	NS2CLK(60)
+#define SDRAM_TRFC	NS2CLK(60)
+#define SDRAM_TCDL	(1 - 1)
+#define SDRAM_TRDL	NS2CLK(12)
+#define SDRAM_TBDL	(1 - 1)
+#define SDRAM_TREF	(NS2CLK(64000000 / 8192) - 20)
+#define SDRAM_TCCD	(1 - 1)
+
+#define SDRAM_TXSR	SDRAM_TRFC	/* Row cycle time after precharge */
+#define SDRAM_TMRD	1		/* Page 10, Mode Register Set */
+
+
+/* Last data in to row precharge, need also comply ineq on page 1648 */
+#define SDRAM_TWR	max(\
+	(int)max((int)SDRAM_TRDL, (int)(SDRAM_TRAS - SDRAM_TRCD)), \
+	(int)(SDRAM_TRC - SDRAM_TRCD - SDRAM_TRP)\
+)
+
+
+#define SDRAM_MODE_BL_SHIFT	0
+#define SDRAM_MODE_CAS_SHIFT	4
+#define SDRAM_MODE_BL		0
+#define SDRAM_MODE_CAS		SDRAM_CAS
+
+int dram_init(void)
+{
+	u32 freq;
+	int rv;
+
+	rv = fmc_setup_gpio();
+	if (rv)
+		return rv;
+
+	setbits_le32(RCC_BASE + RCC_AHB3ENR, RCC_ENR_FMC);
+
+	/*
+	 * Get frequency for NS2CLK calculation.
+	 */
+	freq = clock_get(CLOCK_AHB) / CONFIG_SYS_RAM_FREQ_DIV;
+
+	writel(
+		CONFIG_SYS_RAM_FREQ_DIV << FMC_SDCR_SDCLK_SHIFT
+		| SDRAM_CAS << FMC_SDCR_CAS_SHIFT
+		| SDRAM_NB << FMC_SDCR_NB_SHIFT
+		| SDRAM_MWID << FMC_SDCR_MWID_SHIFT
+		| SDRAM_NR << FMC_SDCR_NR_SHIFT
+		| SDRAM_NC << FMC_SDCR_NC_SHIFT
+		| SDRAM_RPIPE << FMC_SDCR_RPIPE_SHIFT
+		| SDRAM_RBURST << FMC_SDCR_RBURST_SHIFT,
+		&STM32_SDRAM_FMC->sdcr1);
+
+	writel(
+		SDRAM_TRCD << FMC_SDTR_TRCD_SHIFT
+		| SDRAM_TRP << FMC_SDTR_TRP_SHIFT
+		| SDRAM_TWR << FMC_SDTR_TWR_SHIFT
+		| SDRAM_TRC << FMC_SDTR_TRC_SHIFT
+		| SDRAM_TRAS << FMC_SDTR_TRAS_SHIFT
+		| SDRAM_TXSR << FMC_SDTR_TXSR_SHIFT
+		| SDRAM_TMRD << FMC_SDTR_TMRD_SHIFT,
+		&STM32_SDRAM_FMC->sdtr1);
+
+	writel(FMC_SDCMR_BANK_1 | FMC_SDCMR_MODE_START_CLOCK,
+	       &STM32_SDRAM_FMC->sdcmr);
+
+	udelay(200);	/* 200 us delay, page 10, "Power-Up" */
+	FMC_BUSY_WAIT();
+
+	writel(FMC_SDCMR_BANK_1 | FMC_SDCMR_MODE_PRECHARGE,
+	       &STM32_SDRAM_FMC->sdcmr);
+
+	udelay(100);
+	FMC_BUSY_WAIT();
+
+	writel((FMC_SDCMR_BANK_1 | FMC_SDCMR_MODE_AUTOREFRESH
+		| 7 << FMC_SDCMR_NRFS_SHIFT), &STM32_SDRAM_FMC->sdcmr);
+
+	udelay(100);
+	FMC_BUSY_WAIT();
+
+	writel(FMC_SDCMR_BANK_1 | (SDRAM_MODE_BL << SDRAM_MODE_BL_SHIFT
+		| SDRAM_MODE_CAS << SDRAM_MODE_CAS_SHIFT)
+		<< FMC_SDCMR_MODE_REGISTER_SHIFT | FMC_SDCMR_MODE_WRITE_MODE,
+		&STM32_SDRAM_FMC->sdcmr);
+
+	udelay(100);
+
+	FMC_BUSY_WAIT();
+
+	writel(FMC_SDCMR_BANK_1 | FMC_SDCMR_MODE_NORMAL,
+	       &STM32_SDRAM_FMC->sdcmr);
+
+	FMC_BUSY_WAIT();
+
+	/* Refresh timer */
+	writel(SDRAM_TREF, &STM32_SDRAM_FMC->sdrtr);
+
+	/*
+	 * Fill in global info with description of SRAM configuration
+	 */
+	gd->bd->bi_dram[0].start = CONFIG_SYS_RAM_BASE;
+	gd->bd->bi_dram[0].size  = CONFIG_SYS_RAM_SIZE;
+
+	gd->ram_size = CONFIG_SYS_RAM_SIZE;
+
+	return rv;
+}
+
 static const struct stm32_gpio_dsc usart_gpio[] = {
 	{STM32_GPIO_PORT_A, STM32_GPIO_PIN_9},	/* TX */
 	{STM32_GPIO_PORT_B, STM32_GPIO_PIN_7},	/* RX */
@@ -88,12 +305,3 @@
 
 	return 0;
 }
-
-int dram_init(void)
-{
-	gd->bd->bi_dram[0].start = CONFIG_SYS_RAM_BASE;
-	gd->bd->bi_dram[0].size  = CONFIG_SYS_RAM_SIZE;
-
-	gd->ram_size = CONFIG_SYS_RAM_SIZE;
-	return 0;
-}
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig
index 323e972..1b30669 100644
--- a/board/sunxi/Kconfig
+++ b/board/sunxi/Kconfig
@@ -249,7 +249,7 @@
 	Only enable this if you really know what you are doing.
 
 config OLD_SUNXI_KERNEL_COMPAT
-	boolean "Enable workarounds for booting old kernels"
+	bool "Enable workarounds for booting old kernels"
 	default n
 	---help---
 	Set this to enable various workarounds for old kernels, this results in
@@ -419,13 +419,13 @@
 endif
 
 config AXP_GPIO
-	boolean "Enable support for gpio-s on axp PMICs"
+	bool "Enable support for gpio-s on axp PMICs"
 	default n
 	---help---
 	Say Y here to enable support for the gpio pins of the axp PMIC ICs.
 
 config VIDEO
-	boolean "Enable graphical uboot console on HDMI, LCD or VGA"
+	bool "Enable graphical uboot console on HDMI, LCD or VGA"
 	depends on !MACH_SUN8I_A83T && !MACH_SUN8I_H3 && !MACH_SUN9I && !MACH_SUN50I_A64
 	default y
 	---help---
@@ -434,21 +434,21 @@
 	info on how to select the video output and mode.
 
 config VIDEO_HDMI
-	boolean "HDMI output support"
+	bool "HDMI output support"
 	depends on VIDEO && !MACH_SUN8I
 	default y
 	---help---
 	Say Y here to add support for outputting video over HDMI.
 
 config VIDEO_VGA
-	boolean "VGA output support"
+	bool "VGA output support"
 	depends on VIDEO && (MACH_SUN4I || MACH_SUN7I)
 	default n
 	---help---
 	Say Y here to add support for outputting video over VGA.
 
 config VIDEO_VGA_VIA_LCD
-	boolean "VGA via LCD controller support"
+	bool "VGA via LCD controller support"
 	depends on VIDEO && (MACH_SUN5I || MACH_SUN6I || MACH_SUN8I)
 	default n
 	---help---
@@ -457,7 +457,7 @@
 	Olimex A13 boards.
 
 config VIDEO_VGA_VIA_LCD_FORCE_SYNC_ACTIVE_HIGH
-	boolean "Force sync active high for VGA via LCD controller support"
+	bool "Force sync active high for VGA via LCD controller support"
 	depends on VIDEO_VGA_VIA_LCD
 	default n
 	---help---
@@ -475,7 +475,7 @@
 	format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H.
 
 config VIDEO_COMPOSITE
-	boolean "Composite video output support"
+	bool "Composite video output support"
 	depends on VIDEO && (MACH_SUN4I || MACH_SUN5I || MACH_SUN7I)
 	default n
 	---help---
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index d2dfebe..de719cd 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -56,8 +56,10 @@
 F:	configs/gt90h_v4_defconfig
 F:	configs/inet86dz_defconfig
 F:	configs/orangepi_2_defconfig
+F:	configs/orangepi_lite_defconfig
 F:	configs/orangepi_one_defconfig
 F:	configs/orangepi_pc_defconfig
+F:	configs/orangepi_pc_plus_defconfig
 F:	configs/orangepi_plus_defconfig
 F:	configs/polaroid_mid2407pxe03_defconfig
 F:	configs/polaroid_mid2809pxe04_defconfig
diff --git a/board/sunxi/README.pine64 b/board/sunxi/README.pine64
new file mode 100644
index 0000000..5553415
--- /dev/null
+++ b/board/sunxi/README.pine64
@@ -0,0 +1,98 @@
+Pine64 board README
+====================
+
+The Pine64(+) is a single board computer equipped with an AArch64 capable ARMv8
+compliant Allwinner A64 SoC.
+This chip has ARM Cortex A-53 cores and thus can run both in AArch32
+(compatible to 32-bit ARMv7) and AArch64 modes. Upon reset the SoC starts
+in AArch32 mode and executes 32-bit code from the Boot ROM (BROM).
+This has some implications on U-Boot.
+
+Quick start
+============
+- Get hold of a boot0.img file (see below for more details).
+- Get the boot0img tool source from the tools directory in [1] and compile
+  that on your host.
+- Build U-Boot:
+$ export CROSS_COMPILE=aarch64-linux-gnu-
+$ make pine64_plus_defconfig
+$ make
+- You also need a compiled ARM Trusted Firmware (ATF) binary. Checkout the
+  "allwinner" branch from the github repository [2] and build it:
+$ export CROSS_COMPILE=aarch64-linux-gnu-
+$ make PLAT=sun50iw1p1 DEBUG=1 bl31
+  The resulting binary is build/sun50iw1p1/debug/bl31.bin.
+
+Now put an empty (or disposable) micro SD card in your card reader and learn
+its device file name, replacing /dev/sd<x> below with the result (that could
+be /dev/mmcblk<x> as well):
+
+$ ./boot0img --device /dev/sd<x> -e -u u-boot.bin -B boot0.img \
+	-d trampoline64:0x44000 -s bl31.bin -a 0x44008 -p 100
+(either copying the respective files to the working directory or specifying
+the paths directly)
+
+This will create a new partition table (with a 100 MB FAT boot partition),
+copies boot0.img, ATF and U-Boot to the proper locations on the SD card and
+will fill in the magic Allwinner header to be recognized by boot0.
+Prefix the above call with "sudo" if you don't have write access to the
+uSD card. You can also use "-o output.img" instead of "--device /dev/sd<x>"
+to create an image file and "dd" that to the uSD card.
+Omitting the "-p" option will skip the partition table.
+
+Now put this uSD card in the board and power it on. You should be greeted by
+the U-Boot prompt.
+
+
+Main U-Boot
+============
+The main U-Boot proper is a real 64-bit ARMv8 port and runs entirely in the
+64-bit AArch64 mode. It can load any AArch64 code, EFI applications or arm64
+Linux kernel images (often named "Image") using the booti command.
+Launching 32-bit code and kernels is technically possible, though not without
+drawbacks (or hacks to avoid them) and currently not implemented.
+
+SPL support
+============
+The main task of the SPL support is to bring up the DRAM controller and make
+DRAM actually accessible. At the moment there is no documentation or source
+code available which would do this.
+There are currently two ways to overcome this situation: using a tainted 32-bit
+SPL (involving some hacks and resulting in a non-redistributable binary, thus
+not described here) or using the Allwinner boot0 blob.
+
+boot0 method
+-------------
+boot0 is Allwiner's secondary program loader and it can be used as some kind
+of SPL replacement to get U-Boot up and running.
+The binary is a 32 KByte blob and contained on every Pine64 image distributed
+so far. It can be easily extracted from a micro SD card or an image file:
+# dd if=/dev/sd<x> of=boot0.bin bs=8k skip=1 count=4
+where /dev/sd<x> is the device name of the uSD card or the name of the image
+file. Apparently Allwinner allows re-distribution of this proprietary code
+as-is.
+For the time being this boot0 blob is the only redistributable way of making
+U-Boot work on the Pine64. Beside loading the various parts of the (original)
+firmware it also switches the core into AArch64 mode.
+The original boot0 code looks for U-Boot at a certain place on an uSD card
+(at 19096 KB), also it expects a header with magic bytes and a checksum.
+There is a tool called boot0img[1] which takes a boot0.bin image and a compiled
+U-Boot binary (plus other binaries) and will populate that header accordingly.
+To make space for the magic header, the pine64_plus_defconfig will make sure
+there is sufficient space at the beginning of the U-Boot binary.
+boot0img will also take care of putting the different binaries at the right
+places on the uSD card and works around unused, but mandatory parts by using
+trampoline code. See the output of "boot0img -h" for more information.
+boot0img can also patch boot0 to avoid loading U-Boot from 19MB, instead
+fetching it from just behind the boot0 binary (-B option).
+
+FEL boot
+=========
+FEL is the name of the Allwinner defined USB boot protocol built-in the
+mask ROM of most Allwinner SoCs. It allows to bootstrap a board solely
+by using the USB-OTG interface and a host port on another computer.
+Since FEL boot does not work with boot0, it requires the libdram hack, which
+is not described here.
+
+[1] https://github.com/apritzel/pine64/
+[2] https://github.com/apritzel/arm-trusted-firmware.git
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index c8bf316..209fb1c 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -20,12 +20,16 @@
 #include <asm/arch/dram.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/spl.h>
 #include <asm/arch/usb_phy.h>
 #ifndef CONFIG_ARM64
 #include <asm/armv7.h>
 #endif
 #include <asm/gpio.h>
 #include <asm/io.h>
+#include <crc.h>
+#include <environment.h>
+#include <libfdt.h>
 #include <nand.h>
 #include <net.h>
 #include <sy8106a.h>
@@ -133,7 +137,7 @@
 	return 0;
 }
 
-#if defined(CONFIG_NAND_SUNXI) && defined(CONFIG_SPL_BUILD)
+#if defined(CONFIG_NAND_SUNXI)
 static void nand_pinmux_setup(void)
 {
 	unsigned int pin;
@@ -170,6 +174,9 @@
 {
 	nand_pinmux_setup();
 	nand_clock_setup();
+#ifndef CONFIG_SPL_BUILD
+	sunxi_nand_init();
+#endif
 }
 #endif
 
@@ -366,8 +373,7 @@
 	 * are searched there first. Note we only do this for u-boot proper,
 	 * not for the SPL, see spl_boot_device().
 	 */
-	if (!sunxi_mmc_has_egon_boot_signature(mmc0) &&
-	    sunxi_mmc_has_egon_boot_signature(mmc1)) {
+	if (readb(SPL_ADDR + 0x28) == SUNXI_BOOTED_FROM_MMC2) {
 		/* Booting from emmc / mmc2, swap */
 		mmc0->block_dev.devnum = 1;
 		mmc1->block_dev.devnum = 0;
@@ -571,9 +577,6 @@
 }
 #endif
 
-#if !defined(CONFIG_SPL_BUILD)
-#include <asm/arch/spl.h>
-
 /*
  * Check the SPL header for the "sunxi" variant. If found: parse values
  * that might have been passed by the loader ("fel" utility), and update
@@ -582,50 +585,88 @@
 static void parse_spl_header(const uint32_t spl_addr)
 {
 	struct boot_file_head *spl = (void *)(ulong)spl_addr;
-	if (memcmp(spl->spl_signature, SPL_SIGNATURE, 3) == 0) {
-		uint8_t spl_header_version = spl->spl_signature[3];
-		if (spl_header_version == SPL_HEADER_VERSION) {
-			if (spl->fel_script_address)
-				setenv_hex("fel_scriptaddr",
-					   spl->fel_script_address);
-			return;
-		}
+	if (memcmp(spl->spl_signature, SPL_SIGNATURE, 3) != 0)
+		return; /* signature mismatch, no usable header */
+
+	uint8_t spl_header_version = spl->spl_signature[3];
+	if (spl_header_version != SPL_HEADER_VERSION) {
 		printf("sunxi SPL version mismatch: expected %u, got %u\n",
 		       SPL_HEADER_VERSION, spl_header_version);
+		return;
 	}
+	if (!spl->fel_script_address)
+		return;
+
+	if (spl->fel_uEnv_length != 0) {
+		/*
+		 * data is expected in uEnv.txt compatible format, so "env
+		 * import -t" the string(s) at fel_script_address right away.
+		 */
+		himport_r(&env_htab, (char *)spl->fel_script_address,
+			  spl->fel_uEnv_length, '\n', H_NOCLEAR, 0, 0, NULL);
+		return;
+	}
+	/* otherwise assume .scr format (mkimage-type script) */
+	setenv_hex("fel_scriptaddr", spl->fel_script_address);
 }
-#endif
 
-#ifdef CONFIG_MISC_INIT_R
-int misc_init_r(void)
+/*
+ * Note this function gets called multiple times.
+ * It must not make any changes to env variables which already exist.
+ */
+static void setup_environment(const void *fdt)
 {
 	char serial_string[17] = { 0 };
 	unsigned int sid[4];
 	uint8_t mac_addr[6];
-	int ret;
+	char ethaddr[16];
+	int i, ret;
 
-#if !defined(CONFIG_SPL_BUILD)
-	setenv("fel_booted", NULL);
-	setenv("fel_scriptaddr", NULL);
-	/* determine if we are running in FEL mode */
-	if (!is_boot0_magic(SPL_ADDR + 4)) { /* eGON.BT0 */
-		setenv("fel_booted", "1");
-		parse_spl_header(SPL_ADDR);
-	}
+	ret = sunxi_get_sid(sid);
+	if (ret == 0 && sid[0] != 0) {
+		/*
+		 * The single words 1 - 3 of the SID have quite a few bits
+		 * which are the same on many models, so we take a crc32
+		 * of all 3 words, to get a more unique value.
+		 *
+		 * Note we only do this on newer SoCs as we cannot change
+		 * the algorithm on older SoCs since those have been using
+		 * fixed mac-addresses based on only using word 3 for a
+		 * long time and changing a fixed mac-address with an
+		 * u-boot update is not good.
+		 */
+#if !defined(CONFIG_MACH_SUN4I) && !defined(CONFIG_MACH_SUN5I) && \
+    !defined(CONFIG_MACH_SUN6I) && !defined(CONFIG_MACH_SUN7I) && \
+    !defined(CONFIG_MACH_SUN8I_A23) && !defined(CONFIG_MACH_SUN8I_A33)
+		sid[3] = crc32(0, (unsigned char *)&sid[1], 12);
 #endif
 
-	ret = sunxi_get_sid(sid);
-	if (ret == 0 && sid[0] != 0 && sid[3] != 0) {
-		if (!getenv("ethaddr")) {
+		/* Ensure the NIC specific bytes of the mac are not all 0 */
+		if ((sid[3] & 0xffffff) == 0)
+			sid[3] |= 0x800000;
+
+		for (i = 0; i < 4; i++) {
+			sprintf(ethaddr, "ethernet%d", i);
+			if (!fdt_get_alias(fdt, ethaddr))
+				continue;
+
+			if (i == 0)
+				strcpy(ethaddr, "ethaddr");
+			else
+				sprintf(ethaddr, "eth%daddr", i);
+
+			if (getenv(ethaddr))
+				continue;
+
 			/* Non OUI / registered MAC address */
-			mac_addr[0] = 0x02;
+			mac_addr[0] = (i << 4) | 0x02;
 			mac_addr[1] = (sid[0] >>  0) & 0xff;
 			mac_addr[2] = (sid[3] >> 24) & 0xff;
 			mac_addr[3] = (sid[3] >> 16) & 0xff;
 			mac_addr[4] = (sid[3] >>  8) & 0xff;
 			mac_addr[5] = (sid[3] >>  0) & 0xff;
 
-			eth_setenv_enetaddr("ethaddr", mac_addr);
+			eth_setenv_enetaddr(ethaddr, mac_addr);
 		}
 
 		if (!getenv("serial#")) {
@@ -635,6 +676,21 @@
 			setenv("serial#", serial_string);
 		}
 	}
+}
+
+int misc_init_r(void)
+{
+	__maybe_unused int ret;
+
+	setenv("fel_booted", NULL);
+	setenv("fel_scriptaddr", NULL);
+	/* determine if we are running in FEL mode */
+	if (!is_boot0_magic(SPL_ADDR + 4)) { /* eGON.BT0 */
+		setenv("fel_booted", "1");
+		parse_spl_header(SPL_ADDR);
+	}
+
+	setup_environment(gd->fdt_blob);
 
 #ifndef CONFIG_MACH_SUN9I
 	ret = sunxi_usb_phy_probe();
@@ -645,12 +701,17 @@
 
 	return 0;
 }
-#endif
 
 int ft_board_setup(void *blob, bd_t *bd)
 {
 	int __maybe_unused r;
 
+	/*
+	 * Call setup_environment again in case the boot fdt has
+	 * ethernet aliases the u-boot copy does not have.
+	 */
+	setup_environment(blob);
+
 #ifdef CONFIG_VIDEO_DT_SIMPLEFB
 	r = sunxi_simplefb_setup(blob);
 	if (r)
diff --git a/board/synopsys/Kconfig b/board/synopsys/Kconfig
index 8ab48cd..27e5509 100644
--- a/board/synopsys/Kconfig
+++ b/board/synopsys/Kconfig
@@ -1,9 +1,9 @@
-if TARGET_ARCANGEL4
+if TARGET_NSIM
 
 config SYS_VENDOR
 	default "synopsys"
 
 config SYS_CONFIG_NAME
-	default "arcangel4"
+	default "nsim"
 
 endif
diff --git a/board/synopsys/MAINTAINERS b/board/synopsys/MAINTAINERS
index 43114ce..b9bfd3c 100644
--- a/board/synopsys/MAINTAINERS
+++ b/board/synopsys/MAINTAINERS
@@ -1,6 +1,8 @@
 - BOARD
 M:	Alexey Brodkin <abrodkin@synopsys.com>
 S:	Maintained
-F:	include/configs/arcangel4.h
-F:	configs/arcangel4_defconfig
-F:	configs/arcangel4-be_defconfig
+F:	include/configs/nsim.h
+F:	configs/nsim_700_defconfig
+F:	configs/nsim_700be_defconfig
+F:	configs/nsim_hs38_defconfig
+F:	configs/nsim_hs38be_defconfig
diff --git a/board/synopsys/axs101/Makefile b/board/synopsys/axs101/Makefile
deleted file mode 100644
index f0965f7..0000000
--- a/board/synopsys/axs101/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-obj-y	+= axs101.o
-obj-$(CONFIG_CMD_NAND) += nand.o
diff --git a/board/synopsys/axs101/Kconfig b/board/synopsys/axs10x/Kconfig
similarity index 62%
rename from board/synopsys/axs101/Kconfig
rename to board/synopsys/axs10x/Kconfig
index 79e5400..c60b6a2 100644
--- a/board/synopsys/axs101/Kconfig
+++ b/board/synopsys/axs10x/Kconfig
@@ -1,12 +1,12 @@
-if TARGET_AXS101
+if TARGET_AXS10X
 
 config SYS_BOARD
-	default "axs101"
+	default "axs10x"
 
 config SYS_VENDOR
 	default "synopsys"
 
 config SYS_CONFIG_NAME
-	default "axs101"
+	default "axs10x"
 
 endif
diff --git a/board/synopsys/axs101/MAINTAINERS b/board/synopsys/axs10x/MAINTAINERS
similarity index 62%
rename from board/synopsys/axs101/MAINTAINERS
rename to board/synopsys/axs10x/MAINTAINERS
index 79fff8e..abb890b 100644
--- a/board/synopsys/axs101/MAINTAINERS
+++ b/board/synopsys/axs10x/MAINTAINERS
@@ -1,7 +1,7 @@
-AXS101 BOARD
+AXS10X BOARD
 M:	Alexey Brodkin <abrodkin@synopsys.com>
 S:	Maintained
-F:	board/synopsys/axs101/
-F:	include/configs/axs101.h
+F:	board/synopsys/axs10x/
+F:	include/configs/axs10x.h
 F:	configs/axs101_defconfig
 F:	configs/axs103_defconfig
diff --git a/board/synopsys/axs10x/Makefile b/board/synopsys/axs10x/Makefile
new file mode 100644
index 0000000..e29d520
--- /dev/null
+++ b/board/synopsys/axs10x/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright (C) 2013-2016 Synopsys, Inc. All rights reserved.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	+= axs10x.o
+obj-$(CONFIG_CMD_NAND) += nand.o
diff --git a/board/synopsys/axs101/axs101.c b/board/synopsys/axs10x/axs10x.c
similarity index 100%
rename from board/synopsys/axs101/axs101.c
rename to board/synopsys/axs10x/axs10x.c
diff --git a/board/synopsys/axs101/axs10x.h b/board/synopsys/axs10x/axs10x.h
similarity index 100%
rename from board/synopsys/axs101/axs10x.h
rename to board/synopsys/axs10x/axs10x.h
diff --git a/board/synopsys/axs101/nand.c b/board/synopsys/axs10x/nand.c
similarity index 100%
rename from board/synopsys/axs101/nand.c
rename to board/synopsys/axs10x/nand.c
diff --git a/board/technexion/pico-imx6ul/README b/board/technexion/pico-imx6ul/README
new file mode 100644
index 0000000..2f66095
--- /dev/null
+++ b/board/technexion/pico-imx6ul/README
@@ -0,0 +1,57 @@
+How to Update U-Boot on Pico-imx6ul board
+-----------------------------------------
+
+Required software on the host PC:
+
+- imx_usb_loader: https://github.com/boundarydevices/imx_usb_loader
+
+- dfu-util: http://dfu-util.sourceforge.net/releases/
+
+Build U-Boot for Pico:
+
+$ make mrproper
+$ make pico-imx6ul_defconfig
+$ make
+
+This will generate the U-Boot binary called u-boot.imx.
+
+Put pico board in USB download mode (refer to the document
+http://www.wandboard.org/images/hobbit/hobbitboard-imx6ul-reva1.pdf page 15)
+
+Connect a USB to serial adapter between the host PC and pico
+
+Connect a USB cable between the OTG pico port and the host PC
+
+Open a terminal program such as minicom
+
+Copy u-boot.imx to the imx_usb_loader folder.
+
+Load u-boot.imx via USB:
+
+$ sudo ./imx_usb u-boot.imx
+
+Then U-Boot should start and its messages will appear in the console program.
+
+Use the default environment variables:
+
+=> env default -f -a
+=> saveenv
+
+Run the DFU command:
+=> dfu 0 mmc 0
+
+Transfer u-boot.imx that will be flashed into the eMMC:
+
+$ sudo dfu-util -D u-boot.imx -a boot
+
+Then on the U-Boot prompt the following message should be seen after a
+successful upgrade:
+
+#DOWNLOAD ... OK
+Ctrl+C to exit ...
+
+Remove power from the pico board.
+
+Put pico board into normal boot mode
+
+Power up the board and the new updated U-Boot should boot from eMMC.
diff --git a/board/technexion/pico-imx6ul/pico-imx6ul.c b/board/technexion/pico-imx6ul/pico-imx6ul.c
index c038d43..5cbf803 100644
--- a/board/technexion/pico-imx6ul/pico-imx6ul.c
+++ b/board/technexion/pico-imx6ul/pico-imx6ul.c
@@ -14,11 +14,18 @@
 #include <asm/arch/sys_proto.h>
 #include <asm/gpio.h>
 #include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/mxc_i2c.h>
 #include <asm/io.h>
 #include <common.h>
+#include <miiphy.h>
+#include <netdev.h>
 #include <fsl_esdhc.h>
+#include <i2c.h>
 #include <linux/sizes.h>
 #include <usb.h>
+#include <power/pmic.h>
+#include <power/pfuze3000_pmic.h>
+#include "../../freescale/common/pfuze.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -30,10 +37,113 @@
 	PAD_CTL_PUS_22K_UP  | PAD_CTL_SPEED_LOW |		\
 	PAD_CTL_DSE_80ohm   | PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
 
+#define I2C_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_PUE |		\
+	PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED |		\
+	PAD_CTL_DSE_40ohm | PAD_CTL_HYS |			\
+	PAD_CTL_ODE)
+
 #define OTG_ID_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE |		\
 	PAD_CTL_PUS_47K_UP  | PAD_CTL_SPEED_LOW |		\
 	PAD_CTL_DSE_80ohm   | PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
 
+#define MDIO_PAD_CTRL  (PAD_CTL_PUS_100K_UP | PAD_CTL_PUE |     \
+	PAD_CTL_DSE_48ohm   | PAD_CTL_SRE_FAST | PAD_CTL_ODE)
+
+#define ENET_PAD_CTRL  (PAD_CTL_PUS_100K_UP | PAD_CTL_PUE |     \
+	PAD_CTL_SPEED_HIGH   |                                   \
+	PAD_CTL_DSE_48ohm   | PAD_CTL_SRE_FAST)
+
+#define ENET_CLK_PAD_CTRL  (PAD_CTL_DSE_40ohm   | PAD_CTL_SRE_FAST)
+
+#define RMII_PHY_RESET IMX_GPIO_NR(1, 28)
+
+#ifdef CONFIG_SYS_I2C_MXC
+#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
+/* I2C2 for PMIC */
+struct i2c_pads_info i2c_pad_info1 = {
+	.scl = {
+		.i2c_mode =  MX6_PAD_GPIO1_IO02__I2C1_SCL | PC,
+		.gpio_mode = MX6_PAD_GPIO1_IO02__GPIO1_IO02 | PC,
+		.gp = IMX_GPIO_NR(1, 2),
+	},
+	.sda = {
+		.i2c_mode = MX6_PAD_GPIO1_IO03__I2C1_SDA | PC,
+		.gpio_mode = MX6_PAD_GPIO1_IO03__GPIO1_IO03 | PC,
+		.gp = IMX_GPIO_NR(1, 3),
+	},
+};
+#endif
+
+static iomux_v3_cfg_t const fec_pads[] = {
+	MX6_PAD_ENET1_TX_EN__ENET2_MDC		| MUX_PAD_CTRL(MDIO_PAD_CTRL),
+	MX6_PAD_ENET1_TX_DATA1__ENET2_MDIO	| MUX_PAD_CTRL(MDIO_PAD_CTRL),
+	MX6_PAD_ENET2_TX_DATA0__ENET2_TDATA00	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET2_TX_DATA1__ENET2_TDATA01	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET2_TX_CLK__ENET2_REF_CLK2	| MUX_PAD_CTRL(ENET_CLK_PAD_CTRL),
+	MX6_PAD_ENET2_TX_EN__ENET2_TX_EN	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET2_RX_DATA0__ENET2_RDATA00	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET2_RX_DATA1__ENET2_RDATA01	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET2_RX_EN__ENET2_RX_EN	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET2_RX_ER__ENET2_RX_ER	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_UART4_TX_DATA__GPIO1_IO28	| MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+static void setup_iomux_fec(void)
+{
+	imx_iomux_v3_setup_multiple_pads(fec_pads, ARRAY_SIZE(fec_pads));
+}
+
+int board_eth_init(bd_t *bis)
+{
+	setup_iomux_fec();
+
+	gpio_direction_output(RMII_PHY_RESET, 0);
+	/*
+	 * According to KSZ8081MNX-RNB manual:
+	 * For warm reset, the reset (RST#) pin should be asserted low for a
+	 * minimum of 500μs.  The strap-in pin values are read and updated
+	 * at the de-assertion of reset.
+	 */
+	udelay(500);
+
+	gpio_direction_output(RMII_PHY_RESET, 1);
+	/*
+	 * According to KSZ8081MNX-RNB manual:
+	 * After the de-assertion of reset, wait a minimum of 100μs before
+	 * starting programming on the MIIM (MDC/MDIO) interface.
+	 */
+	udelay(100);
+
+	return fecmxc_initialize(bis);
+}
+
+static int setup_fec(void)
+{
+	struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
+	int ret;
+
+	clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC2_MASK,
+			IOMUX_GPR1_FEC2_CLOCK_MUX1_SEL_MASK);
+
+	ret = enable_fec_anatop_clock(1, ENET_50MHZ);
+	if (ret)
+		return ret;
+
+	enable_enet_clk(1);
+
+	return 0;
+}
+
+int board_phy_config(struct phy_device *phydev)
+{
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x8190);
+
+	if (phydev->drv->config)
+		phydev->drv->config(phydev);
+
+	return 0;
+}
+
 int dram_init(void)
 {
 	gd->ram_size = imx_ddr_size();
@@ -59,6 +169,9 @@
 	MX6_PAD_NAND_CLE__USDHC1_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 };
 
+#define USB_OTHERREGS_OFFSET	0x800
+#define UCTRL_PWR_POL		(1 << 9)
+
 static iomux_v3_cfg_t const usb_otg_pad[] = {
 	MX6_PAD_GPIO1_IO00__ANATOP_OTG1_ID | MUX_PAD_CTRL(OTG_ID_PAD_CTRL),
 };
@@ -96,16 +209,79 @@
 	return 0;
 }
 
+#ifdef CONFIG_POWER
+#define I2C_PMIC       0
+static struct pmic *pfuze;
+int power_init_board(void)
+{
+	int ret;
+	unsigned int reg, rev_id;
+
+	ret = power_pfuze3000_init(I2C_PMIC);
+	if (ret)
+		return ret;
+
+	pfuze = pmic_get("PFUZE3000");
+	ret = pmic_probe(pfuze);
+	if (ret)
+		return ret;
+
+	pmic_reg_read(pfuze, PFUZE3000_DEVICEID, &reg);
+	pmic_reg_read(pfuze, PFUZE3000_REVID, &rev_id);
+	printf("PMIC: PFUZE3000 DEV_ID=0x%x REV_ID=0x%x\n", reg, rev_id);
+
+	/* disable Low Power Mode during standby mode */
+	pmic_reg_read(pfuze, PFUZE3000_LDOGCTL, &reg);
+	reg |= 0x1;
+	pmic_reg_write(pfuze, PFUZE3000_LDOGCTL, reg);
+
+	/* SW1B step ramp up time from 2us to 4us/25mV */
+	pmic_reg_write(pfuze, PFUZE3000_SW1BCONF, 0x40);
+
+	/* SW1B mode to APS/PFM */
+	pmic_reg_write(pfuze, PFUZE3000_SW1BMODE, 0xc);
+
+	/* SW1B standby voltage set to 0.975V */
+	pmic_reg_write(pfuze, PFUZE3000_SW1BSTBY, 0xb);
+
+	return 0;
+}
+#endif
+
 int board_usb_phy_mode(int port)
 {
-	return USB_INIT_DEVICE;
+	if (port == 1)
+		return USB_INIT_HOST;
+	else
+		return USB_INIT_DEVICE;
 }
 
+int board_ehci_hcd_init(int port)
+{
+	u32 *usbnc_usb_ctrl;
+
+	if (port > 1)
+		return -EINVAL;
+
+	usbnc_usb_ctrl = (u32 *)(USB_BASE_ADDR + USB_OTHERREGS_OFFSET +
+				 port * 4);
+
+	/* Set Power polarity */
+	setbits_le32(usbnc_usb_ctrl, UCTRL_PWR_POL);
+
+	return 0;
+}
+
 int board_init(void)
 {
 	/* Address of boot parameters */
 	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
 
+	#ifdef CONFIG_SYS_I2C_MXC
+		setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
+	#endif
+
+	setup_fec();
 	setup_usb();
 
 	return 0;
diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c
index f005762..27c311e 100644
--- a/board/ti/am43xx/board.c
+++ b/board/ti/am43xx/board.c
@@ -13,6 +13,7 @@
 #include <asm/errno.h>
 #include <spl.h>
 #include <usb.h>
+#include <asm/omap_sec_common.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/mux.h>
@@ -862,3 +863,10 @@
 		return -1;
 }
 #endif
+
+#ifdef CONFIG_TI_SECURE_DEVICE
+void board_fit_image_post_process(void **p_image, size_t *p_size)
+{
+	secure_boot_verify_image(p_image, p_size);
+}
+#endif
diff --git a/board/ti/am57xx/board.c b/board/ti/am57xx/board.c
index 08cf14d..927d136 100644
--- a/board/ti/am57xx/board.c
+++ b/board/ti/am57xx/board.c
@@ -13,6 +13,7 @@
 #include <sata.h>
 #include <usb.h>
 #include <asm/omap_common.h>
+#include <asm/omap_sec_common.h>
 #include <asm/emif.h>
 #include <asm/gpio.h>
 #include <asm/arch/gpio.h>
@@ -750,3 +751,10 @@
 		return -1;
 }
 #endif
+
+#ifdef CONFIG_TI_SECURE_DEVICE
+void board_fit_image_post_process(void **p_image, size_t *p_size)
+{
+	secure_boot_verify_image(p_image, p_size);
+}
+#endif
diff --git a/board/ti/dra7xx/evm.c b/board/ti/dra7xx/evm.c
index 6a4d027..99e8254 100644
--- a/board/ti/dra7xx/evm.c
+++ b/board/ti/dra7xx/evm.c
@@ -17,6 +17,8 @@
 #include <asm/gpio.h>
 #include <usb.h>
 #include <linux/usb/gadget.h>
+#include <asm/omap_common.h>
+#include <asm/omap_sec_common.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/dra7xx_iodelay.h>
 #include <asm/emif.h>
@@ -834,3 +836,10 @@
 		return -1;
 }
 #endif
+
+#ifdef CONFIG_TI_SECURE_DEVICE
+void board_fit_image_post_process(void **p_image, size_t *p_size)
+{
+	secure_boot_verify_image(p_image, p_size);
+}
+#endif
diff --git a/board/ti/evm/Kconfig b/board/ti/evm/Kconfig
index f02aa31..4f490dd 100644
--- a/board/ti/evm/Kconfig
+++ b/board/ti/evm/Kconfig
@@ -10,29 +10,3 @@
 	default "omap3_evm"
 
 endif
-
-if TARGET_OMAP3_EVM_QUICK_MMC
-
-config SYS_BOARD
-	default "evm"
-
-config SYS_VENDOR
-	default "ti"
-
-config SYS_CONFIG_NAME
-	default "omap3_evm_quick_mmc"
-
-endif
-
-if TARGET_OMAP3_EVM_QUICK_NAND
-
-config SYS_BOARD
-	default "evm"
-
-config SYS_VENDOR
-	default "ti"
-
-config SYS_CONFIG_NAME
-	default "omap3_evm_quick_nand"
-
-endif
diff --git a/board/ti/evm/MAINTAINERS b/board/ti/evm/MAINTAINERS
index 90c3f6b..612a08a 100644
--- a/board/ti/evm/MAINTAINERS
+++ b/board/ti/evm/MAINTAINERS
@@ -3,8 +3,4 @@
 S:	Maintained
 F:	board/ti/evm/
 F:	include/configs/omap3_evm.h
-F:	include/configs/omap3_evm_quick_mmc.h
-F:	include/configs/omap3_evm_quick_nand.h
 F:	configs/omap3_evm_defconfig
-F:	configs/omap3_evm_quick_mmc_defconfig
-F:	configs/omap3_evm_quick_nand_defconfig
diff --git a/board/toradex/colibri_imx7/Kconfig b/board/toradex/colibri_imx7/Kconfig
new file mode 100644
index 0000000..7bba26b
--- /dev/null
+++ b/board/toradex/colibri_imx7/Kconfig
@@ -0,0 +1,20 @@
+if TARGET_COLIBRI_IMX7
+
+config SYS_BOARD
+	default "colibri_imx7"
+
+config SYS_VENDOR
+	default "toradex"
+
+config SYS_CONFIG_NAME
+	default "colibri_imx7"
+
+config COLIBRI_IMX7_EXT_PHYCLK
+	bool "External oscillator for Ethernet PHY clock provided"
+	help
+	  Select this if your module provides a external Ethernet PHY
+	  clock source.
+	default y
+
+
+endif
diff --git a/board/toradex/colibri_imx7/MAINTAINERS b/board/toradex/colibri_imx7/MAINTAINERS
new file mode 100644
index 0000000..5ffb241
--- /dev/null
+++ b/board/toradex/colibri_imx7/MAINTAINERS
@@ -0,0 +1,6 @@
+Colibri iMX7
+M:	Stefan Agner <stefan.agner@toradex.com>
+S:	Maintained
+F:	board/toradex/colibri_imx7/
+F:	include/configs/colibri_imx7.h
+F:	configs/colibri_imx7_defconfig
diff --git a/board/toradex/colibri_imx7/Makefile b/board/toradex/colibri_imx7/Makefile
new file mode 100644
index 0000000..ea597de
--- /dev/null
+++ b/board/toradex/colibri_imx7/Makefile
@@ -0,0 +1,6 @@
+# Copyright (C) 2016 Toradex AG
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y  := colibri_imx7.o
diff --git a/board/toradex/colibri_imx7/colibri_imx7.c b/board/toradex/colibri_imx7/colibri_imx7.c
new file mode 100644
index 0000000..8eedd65
--- /dev/null
+++ b/board/toradex/colibri_imx7/colibri_imx7.c
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2016 Toradex AG
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/arch/clock.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/mx7-pins.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/gpio.h>
+#include <asm/imx-common/boot_mode.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/mxc_i2c.h>
+#include <asm/io.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/platform_data/serial_mxc.h>
+#include <fsl_esdhc.h>
+#include <i2c.h>
+#include <linux/sizes.h>
+#include <mmc.h>
+#include <miiphy.h>
+#include <netdev.h>
+#include <usb/ehci-ci.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define UART_PAD_CTRL  (PAD_CTL_DSE_3P3V_49OHM | \
+	PAD_CTL_PUS_PU100KOHM | PAD_CTL_HYS)
+
+#define USDHC_PAD_CTRL (PAD_CTL_DSE_3P3V_32OHM | PAD_CTL_SRE_SLOW | \
+	PAD_CTL_HYS | PAD_CTL_PUE | PAD_CTL_PUS_PU47KOHM)
+
+#define ENET_PAD_CTRL  (PAD_CTL_PUS_PU100KOHM | PAD_CTL_DSE_3P3V_49OHM)
+#define ENET_PAD_CTRL_MII  (PAD_CTL_DSE_3P3V_32OHM)
+
+#define ENET_RX_PAD_CTRL  (PAD_CTL_PUS_PU100KOHM | PAD_CTL_DSE_3P3V_49OHM)
+
+#define I2C_PAD_CTRL    (PAD_CTL_DSE_3P3V_32OHM | PAD_CTL_SRE_SLOW | \
+	PAD_CTL_HYS | PAD_CTL_PUE | PAD_CTL_PUS_PU100KOHM)
+
+#define LCD_PAD_CTRL    (PAD_CTL_HYS | PAD_CTL_PUS_PU100KOHM | \
+	PAD_CTL_DSE_3P3V_49OHM)
+
+#define NAND_PAD_CTRL (PAD_CTL_DSE_3P3V_49OHM | PAD_CTL_SRE_SLOW | PAD_CTL_HYS)
+
+#define NAND_PAD_READY0_CTRL (PAD_CTL_DSE_3P3V_49OHM | PAD_CTL_PUS_PU5KOHM)
+
+#ifdef CONFIG_SYS_I2C_MXC
+#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
+/* I2C1 for PMIC */
+static struct i2c_pads_info i2c_pad_info1 = {
+	.scl = {
+		.i2c_mode = MX7D_PAD_GPIO1_IO04__I2C1_SCL | PC,
+		.gpio_mode = MX7D_PAD_GPIO1_IO04__GPIO1_IO4 | PC,
+		.gp = IMX_GPIO_NR(1, 4),
+	},
+	.sda = {
+		.i2c_mode = MX7D_PAD_GPIO1_IO05__I2C1_SDA | PC,
+		.gpio_mode = MX7D_PAD_GPIO1_IO05__GPIO1_IO5 | PC,
+		.gp = IMX_GPIO_NR(1, 5),
+	},
+};
+/* I2C4 for Colibri I2C */
+static struct i2c_pads_info i2c_pad_info4 = {
+	.scl = {
+		.i2c_mode = MX7D_PAD_ENET1_RGMII_TD2__I2C4_SCL | PC,
+		.gpio_mode = MX7D_PAD_ENET1_RGMII_TD2__GPIO7_IO8 | PC,
+		.gp = IMX_GPIO_NR(7, 8),
+	},
+	.sda = {
+		.i2c_mode = MX7D_PAD_ENET1_RGMII_TD3__I2C4_SDA | PC,
+		.gpio_mode = MX7D_PAD_ENET1_RGMII_TD3__GPIO7_IO9 | PC,
+		.gp = IMX_GPIO_NR(7, 9),
+	},
+};
+#endif
+
+int dram_init(void)
+{
+	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
+
+	return 0;
+}
+
+static iomux_v3_cfg_t const uart1_pads[] = {
+	MX7D_PAD_UART1_RX_DATA__UART1_DTE_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX7D_PAD_UART1_TX_DATA__UART1_DTE_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX7D_PAD_SAI2_TX_BCLK__UART1_DTE_CTS | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX7D_PAD_SAI2_TX_SYNC__UART1_DTE_RTS | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+static iomux_v3_cfg_t const usdhc1_pads[] = {
+	MX7D_PAD_SD1_CLK__SD1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX7D_PAD_SD1_CMD__SD1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX7D_PAD_SD1_DATA0__SD1_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX7D_PAD_SD1_DATA1__SD1_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX7D_PAD_SD1_DATA2__SD1_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX7D_PAD_SD1_DATA3__SD1_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+
+	MX7D_PAD_GPIO1_IO00__GPIO1_IO0 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+#ifdef CONFIG_NAND_MXS
+static iomux_v3_cfg_t const gpmi_pads[] = {
+	MX7D_PAD_SD3_DATA0__NAND_DATA00 | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX7D_PAD_SD3_DATA1__NAND_DATA01 | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX7D_PAD_SD3_DATA2__NAND_DATA02 | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX7D_PAD_SD3_DATA3__NAND_DATA03 | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX7D_PAD_SD3_DATA4__NAND_DATA04 | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX7D_PAD_SD3_DATA5__NAND_DATA05 | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX7D_PAD_SD3_DATA6__NAND_DATA06 | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX7D_PAD_SD3_DATA7__NAND_DATA07 | MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX7D_PAD_SD3_CLK__NAND_CLE	| MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX7D_PAD_SD3_CMD__NAND_ALE	| MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX7D_PAD_SD3_STROBE__NAND_RE_B	| MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX7D_PAD_SD3_RESET_B__NAND_WE_B	| MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX7D_PAD_SAI1_RX_DATA__NAND_CE1_B	| MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX7D_PAD_SAI1_TX_BCLK__NAND_CE0_B	| MUX_PAD_CTRL(NAND_PAD_CTRL),
+	MX7D_PAD_SAI1_TX_DATA__NAND_READY_B	| MUX_PAD_CTRL(NAND_PAD_READY0_CTRL),
+};
+
+static void setup_gpmi_nand(void)
+{
+	imx_iomux_v3_setup_multiple_pads(gpmi_pads, ARRAY_SIZE(gpmi_pads));
+
+	/* NAND_USDHC_BUS_CLK is set in rom */
+	set_clk_nand();
+}
+#endif
+
+static iomux_v3_cfg_t const usdhc3_emmc_pads[] = {
+	MX7D_PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX7D_PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX7D_PAD_SD3_DATA0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX7D_PAD_SD3_DATA1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX7D_PAD_SD3_DATA2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX7D_PAD_SD3_DATA3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX7D_PAD_SD3_DATA4__SD3_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX7D_PAD_SD3_DATA5__SD3_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX7D_PAD_SD3_DATA6__SD3_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX7D_PAD_SD3_DATA7__SD3_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX7D_PAD_SD3_STROBE__SD3_STROBE	 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+
+	MX7D_PAD_SD3_RESET_B__GPIO6_IO11 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+};
+
+#ifdef CONFIG_VIDEO_MXS
+static iomux_v3_cfg_t const lcd_pads[] = {
+	MX7D_PAD_LCD_CLK__LCD_CLK | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_ENABLE__LCD_ENABLE | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_HSYNC__LCD_HSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_VSYNC__LCD_VSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA00__LCD_DATA0 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA01__LCD_DATA1 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA02__LCD_DATA2 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA03__LCD_DATA3 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA04__LCD_DATA4 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA05__LCD_DATA5 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA06__LCD_DATA6 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA07__LCD_DATA7 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA08__LCD_DATA8 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA09__LCD_DATA9 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA10__LCD_DATA10 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA11__LCD_DATA11 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA12__LCD_DATA12 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA13__LCD_DATA13 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA14__LCD_DATA14 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA15__LCD_DATA15 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA16__LCD_DATA16 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+	MX7D_PAD_LCD_DATA17__LCD_DATA17 | MUX_PAD_CTRL(LCD_PAD_CTRL),
+};
+
+static iomux_v3_cfg_t const backlight_pads[] = {
+	/* Backlight On */
+	MX7D_PAD_SD1_WP__GPIO5_IO1 | MUX_PAD_CTRL(NO_PAD_CTRL),
+	/* Backlight PWM<A> (multiplexed pin) */
+	MX7D_PAD_GPIO1_IO08__GPIO1_IO8   | MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX7D_PAD_ECSPI2_MOSI__GPIO4_IO21 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+#define GPIO_BL_ON IMX_GPIO_NR(5, 1)
+#define GPIO_PWM_A IMX_GPIO_NR(1, 8)
+
+static int setup_lcd(void)
+{
+	imx_iomux_v3_setup_multiple_pads(lcd_pads, ARRAY_SIZE(lcd_pads));
+
+	imx_iomux_v3_setup_multiple_pads(backlight_pads, ARRAY_SIZE(backlight_pads));
+
+	/* Set BL_ON */
+	gpio_request(GPIO_BL_ON, "BL_ON");
+	gpio_direction_output(GPIO_BL_ON, 1);
+
+	/* Set PWM<A> to full brightness (assuming inversed polarity) */
+	gpio_request(GPIO_PWM_A, "PWM<A>");
+	gpio_direction_output(GPIO_PWM_A, 0);
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_FEC_MXC
+static iomux_v3_cfg_t const fec1_pads[] = {
+#ifndef CONFIG_COLIBRI_IMX7_EXT_PHYCLK
+	MX7D_PAD_GPIO1_IO12__CCM_ENET_REF_CLK1 | MUX_PAD_CTRL(ENET_PAD_CTRL) | MUX_MODE_SION,
+#else
+	MX7D_PAD_GPIO1_IO12__CCM_ENET_REF_CLK1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+#endif
+	MX7D_PAD_SD2_CD_B__ENET1_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL_MII),
+	MX7D_PAD_SD2_WP__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL_MII),
+	MX7D_PAD_ENET1_RGMII_RD0__ENET1_RGMII_RD0 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
+	MX7D_PAD_ENET1_RGMII_RD1__ENET1_RGMII_RD1 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
+	MX7D_PAD_ENET1_RGMII_RXC__ENET1_RX_ER | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
+	MX7D_PAD_ENET1_RGMII_RX_CTL__ENET1_RGMII_RX_CTL	  | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
+	MX7D_PAD_ENET1_RGMII_TD0__ENET1_RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX7D_PAD_ENET1_RGMII_TD1__ENET1_RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX7D_PAD_ENET1_RGMII_TX_CTL__ENET1_RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
+};
+
+static void setup_iomux_fec(void)
+{
+	imx_iomux_v3_setup_multiple_pads(fec1_pads, ARRAY_SIZE(fec1_pads));
+}
+#endif
+
+static void setup_iomux_uart(void)
+{
+	imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
+}
+
+#ifdef CONFIG_FSL_ESDHC
+
+#define USDHC1_CD_GPIO	IMX_GPIO_NR(1, 0)
+
+static struct fsl_esdhc_cfg usdhc_cfg[] = {
+	{USDHC1_BASE_ADDR, 0, 4},
+};
+
+int board_mmc_getcd(struct mmc *mmc)
+{
+	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+	int ret = 0;
+
+	switch (cfg->esdhc_base) {
+	case USDHC1_BASE_ADDR:
+		ret = !gpio_get_value(USDHC1_CD_GPIO);
+		break;
+	}
+
+	return ret;
+}
+
+int board_mmc_init(bd_t *bis)
+{
+	int i, ret;
+	/* USDHC1 is mmc0 */
+	for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) {
+		switch (i) {
+		case 0:
+			imx_iomux_v3_setup_multiple_pads(
+				usdhc1_pads, ARRAY_SIZE(usdhc1_pads));
+			gpio_request(USDHC1_CD_GPIO, "usdhc1_cd");
+			gpio_direction_input(USDHC1_CD_GPIO);
+			usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
+			break;
+		default:
+			printf("Warning: you configured more USDHC controllers"
+				"(%d) than supported by the board\n", i + 1);
+			return -EINVAL;
+		}
+
+		ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_FEC_MXC
+int board_eth_init(bd_t *bis)
+{
+	int ret;
+
+	setup_iomux_fec();
+
+	ret = fecmxc_initialize_multi(bis, 0,
+		CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE);
+	if (ret)
+		printf("FEC1 MXC: %s:failed\n", __func__);
+
+	return ret;
+}
+
+static int setup_fec(void)
+{
+	struct iomuxc_gpr_base_regs *const iomuxc_gpr_regs
+		= (struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
+
+#ifndef CONFIG_COLIBRI_IMX7_EXT_PHYCLK
+	/*
+	 * Use 50M anatop REF_CLK1 for ENET1, clear gpr1[13], set gpr1[17]
+	 * and output it on the pin
+	 */
+	clrsetbits_le32(&iomuxc_gpr_regs->gpr[1],
+			IOMUXC_GPR_GPR1_GPR_ENET1_TX_CLK_SEL_MASK,
+			IOMUXC_GPR_GPR1_GPR_ENET1_CLK_DIR_MASK);
+#else
+	/* Use 50M external CLK for ENET1, set gpr1[13], clear gpr1[17] */
+	clrsetbits_le32(&iomuxc_gpr_regs->gpr[1],
+			IOMUXC_GPR_GPR1_GPR_ENET1_CLK_DIR_MASK,
+			IOMUXC_GPR_GPR1_GPR_ENET1_TX_CLK_SEL_MASK);
+#endif
+
+	return set_clk_enet(ENET_50MHz);
+}
+
+int board_phy_config(struct phy_device *phydev)
+{
+	if (phydev->drv->config)
+		phydev->drv->config(phydev);
+	return 0;
+}
+#endif
+
+int board_early_init_f(void)
+{
+	setup_iomux_uart();
+
+#ifdef CONFIG_SYS_I2C_MXC
+	setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
+	setup_i2c(3, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info4);
+#endif
+
+	return 0;
+}
+
+int board_init(void)
+{
+	/* address of boot parameters */
+	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
+
+#ifdef CONFIG_FEC_MXC
+	setup_fec();
+#endif
+
+#ifdef CONFIG_NAND_MXS
+	setup_gpmi_nand();
+#endif
+
+#ifdef CONFIG_VIDEO_MXS
+	setup_lcd();
+#endif
+
+	return 0;
+}
+
+#ifdef CONFIG_CMD_BMODE
+static const struct boot_mode board_boot_modes[] = {
+	/* 4 bit bus width */
+	{"nand", MAKE_CFGVAL(0x40, 0x34, 0x00, 0x00)},
+	{"sd1", MAKE_CFGVAL(0x10, 0x10, 0x00, 0x00)},
+	{NULL, 0},
+};
+#endif
+
+int board_late_init(void)
+{
+#ifdef CONFIG_CMD_BMODE
+	add_board_boot_modes(board_boot_modes);
+#endif
+
+	return 0;
+}
+
+int checkboard(void)
+{
+	printf("Model: Toradex Colibri iMX7%c\n",
+	       is_cpu_type(MXC_CPU_MX7D) ? 'D' : 'S');
+
+	return 0;
+}
+
+#ifdef CONFIG_USB_EHCI_MX7
+static iomux_v3_cfg_t const usb_otg2_pads[] = {
+	MX7D_PAD_UART3_CTS_B__USB_OTG2_PWR | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+int board_ehci_hcd_init(int port)
+{
+	switch (port) {
+	case 0:
+		break;
+	case 1:
+		if (is_cpu_type(MXC_CPU_MX7S))
+			return -ENODEV;
+
+		imx_iomux_v3_setup_multiple_pads(usb_otg2_pads,
+						 ARRAY_SIZE(usb_otg2_pads));
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+#endif
+
+static struct mxc_serial_platdata mxc_serial_plat = {
+	.reg = (struct mxc_uart *)UART1_IPS_BASE_ADDR,
+	.use_dte = true,
+};
+
+U_BOOT_DEVICE(mxc_serial) = {
+	.name = "serial_mxc",
+	.platdata = &mxc_serial_plat,
+};
diff --git a/board/toradex/colibri_imx7/imximage.cfg b/board/toradex/colibri_imx7/imximage.cfg
new file mode 100644
index 0000000..d891e82
--- /dev/null
+++ b/board/toradex/colibri_imx7/imximage.cfg
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *               2015 Toradex AG
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * Refer docs/README.imxmage for more details about how-to configure
+ * and create imximage boot image
+ *
+ * The syntax is taken as close as possible with the kwbimage
+ */
+
+#define __ASSEMBLY__
+#include <config.h>
+
+/* image version */
+
+IMAGE_VERSION 2
+
+/*
+ * Boot Device : sd
+ */
+
+BOOT_FROM	sd
+
+/*
+ * Secure boot support
+ */
+#ifdef CONFIG_SECURE_BOOT
+CSF CONFIG_CSF_SIZE
+#endif
+
+/*
+ * Device Configuration Data (DCD)
+ *
+ * Each entry must have the format:
+ * Addr-type           Address        Value
+ *
+ * where:
+ *	Addr-type register length (1,2 or 4 bytes)
+ *	Address	  absolute address of the register
+ *	value	  value to be stored in the register
+ */
+
+/* IOMUXC_GPR_GPR1 */
+DATA 4 0x30340004 0x4F400005
+
+/* DDR3L */
+/* assuming MEMC_FREQ_RATIO = 2 */
+/* SRC_DDRC_RCR */
+DATA 4 0x30391000 0x00000002
+/* DDRC_MSTR */
+DATA 4 0x307a0000 0x01040001
+/* DDRC_DFIUPD0 */
+DATA 4 0x307a01a0 0x80400003
+/* DDRC_DFIUPD1 */
+DATA 4 0x307a01a4 0x00100020
+/* DDRC_DFIUPD2 */
+DATA 4 0x307a01a8 0x80100004
+/* DDRC_RFSHTMG */
+DATA 4 0x307a0064 0x00400045
+/* DDRC_MP_PCTRL_0 */
+DATA 4 0x307a0490 0x00000001
+/* DDRC_INIT0 */
+DATA 4 0x307a00d0 0x00020083
+/* DDRC_INIT1 */
+DATA 4 0x307a00d4 0x00690000
+/* DDRC_INIT3 MR0/MR1 */
+DATA 4 0x307a00dc 0x09300004
+/* DDRC_INIT4 MR2/MR3 */
+DATA 4 0x307a00e0 0x04480000
+/* DDRC_INIT5 */
+DATA 4 0x307a00e4 0x00100004
+/* DDRC_RANKCTL */
+DATA 4 0x307a00f4 0x0000033f
+/* DDRC_DRAMTMG0 */
+DATA 4 0x307a0100 0x090b090a
+/* DDRC_DRAMTMG1 */
+DATA 4 0x307a0104 0x000d020d
+/* DDRC_DRAMTMG2 */
+DATA 4 0x307a0108 0x03040307
+/* DDRC_DRAMTMG3 */
+DATA 4 0x307a010c 0x00002006
+/* DDRC_DRAMTMG4 */
+DATA 4 0x307a0110 0x04020205
+/* DDRC_DRAMTMG5 */
+DATA 4 0x307a0114 0x03030202
+/* DDRC_DRAMTMG8 */
+DATA 4 0x307a0120 0x00000803
+/* DDRC_ZQCTL0 */
+DATA 4 0x307a0180 0x00800020
+/* DDRC_ZQCTL1 */
+DATA 4 0x307a0184 0x02001000
+/* DDRC_DFITMG0 */
+DATA 4 0x307a0190 0x02098204
+/* DDRC_DFITMG1 */
+DATA 4 0x307a0194 0x00030303
+/* DDRC_ADDRMAP0 */
+DATA 4 0x307a0200 0x0000001f
+/* DDRC_ADDRMAP1 */
+DATA 4 0x307a0204 0x00080808
+/* DDRC_ADDRMAP5 */
+DATA 4 0x307a0214 0x07070707
+/* DDRC_ADDRMAP6 */
+DATA 4 0x307a0218 0x07070707
+/* DDRC_ODTCFG */
+DATA 4 0x307a0240 0x06000601
+/* DDRC_ODTMAP */
+DATA 4 0x307a0244 0x00000011
+/* SRC_DDRC_RCR */
+DATA 4 0x30391000 0x00000000
+/* DDR_PHY_PHY_CON0 */
+DATA 4 0x30790000 0x17420f40
+/* DDR_PHY_PHY_CON1 */
+DATA 4 0x30790004 0x10210100
+/* DDR_PHY_PHY_CON4 */
+DATA 4 0x30790010 0x00060807
+/* DDR_PHY_MDLL_CON0 */
+DATA 4 0x307900b0 0x1010007e
+/* DDR_PHY_DRVDS_CON0 */
+DATA 4 0x3079009c 0x00000d6e
+/* DDR_PHY_OFFSET_RD_CON0 */
+DATA 4 0x30790020 0x08080808
+/* DDR_PHY_OFFSET_WR_CON0 */
+DATA 4 0x30790030 0x08080808
+/* DDR_PHY_CMD_SDLL_CON0 */
+DATA 4 0x30790050 0x01000010
+DATA 4 0x30790050 0x00000010
+
+/* DDR_PHY_ZQ_CON0 */
+DATA 4 0x307900c0 0x0e407304
+DATA 4 0x307900c0 0x0e447304
+DATA 4 0x307900c0 0x0e447306
+/* DDR_PHY_ZQ_CON1 */
+CHECK_BITS_SET 4 0x307900c4 0x1
+/* DDR_PHY_ZQ_CON0 */
+DATA 4 0x307900c0 0x0e447304
+DATA 4 0x307900c0 0x0e407304
+
+/* CCM_CCGRn */
+DATA 4 0x30384130 0x00000000
+/* IOMUXC_GPR_GPR8 */
+DATA 4 0x30340020 0x00000178
+/* CCM_CCGRn */
+DATA 4 0x30384130 0x00000002
+/* DDR_PHY_LP_CON0 */
+DATA 4 0x30790018 0x0000000f
+
+/* DDRC_STAT */
+CHECK_BITS_SET 4 0x307a0004 0x1
diff --git a/board/wandboard/wandboard.c b/board/wandboard/wandboard.c
index 4ce74cd..1de1e0b 100644
--- a/board/wandboard/wandboard.c
+++ b/board/wandboard/wandboard.c
@@ -19,6 +19,7 @@
 #include <asm/imx-common/mxc_i2c.h>
 #include <asm/imx-common/boot_mode.h>
 #include <asm/imx-common/video.h>
+#include <asm/imx-common/sata.h>
 #include <asm/io.h>
 #include <linux/sizes.h>
 #include <common.h>
@@ -345,6 +346,12 @@
 #if defined(CONFIG_VIDEO_IPUV3)
 	setup_display();
 #endif
+#ifdef CONFIG_CMD_SATA
+	/* Only mx6q wandboard has SATA */
+	if (is_cpu_type(MXC_CPU_MX6Q))
+		setup_sata();
+#endif
+
 	return 0;
 }
 
@@ -384,7 +391,7 @@
 #endif
 
 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
-	if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
+	if (is_mx6dq())
 		setenv("board_rev", "MX6Q");
 	else
 		setenv("board_rev", "MX6DL");
@@ -403,7 +410,7 @@
 	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
 
 	setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6dl_i2c2_pad_info);
-	if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
+	if (is_mx6dq())
 		setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6q_i2c2_pad_info);
 	else
 		setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6dl_i2c2_pad_info);
diff --git a/board/warp/warp.c b/board/warp/warp.c
index 49dfdb6..0bc0a6a 100644
--- a/board/warp/warp.c
+++ b/board/warp/warp.c
@@ -46,7 +46,7 @@
 
 int dram_init(void)
 {
-	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
+	gd->ram_size = imx_ddr_size();
 
 	return 0;
 }
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
index f15dc5d..0c5d997 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -307,3 +307,8 @@
 	return 0;
 }
 #endif
+
+void reset_misc(void)
+{
+	psci_system_reset(true);
+}
diff --git a/cmd/Kconfig b/cmd/Kconfig
index d69b817..d28da54 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -114,6 +114,8 @@
 
 endmenu
 
+source "cmd/fastboot/Kconfig"
+
 comment "Commands"
 
 menu "Info commands"
@@ -165,6 +167,13 @@
 	help
 	  Boot the Linux zImage
 
+config CMD_BOOTI
+	bool "booti"
+	depends on ARM64
+	default y
+	help
+	  Boot an AArch64 Linux Kernel image from memory.
+
 config CMD_BOOTEFI
 	bool "bootefi"
 	depends on EFI_LOADER
diff --git a/cmd/Makefile b/cmd/Makefile
index a1731be..a1ecf73 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -26,6 +26,8 @@
 obj-$(CONFIG_CMD_BOOTMENU) += bootmenu.o
 obj-$(CONFIG_CMD_BOOTLDR) += bootldr.o
 obj-$(CONFIG_CMD_BOOTSTAGE) += bootstage.o
+obj-$(CONFIG_CMD_BOOTZ) += bootz.o
+obj-$(CONFIG_CMD_BOOTI) += booti.o
 obj-$(CONFIG_CMD_CACHE) += cache.o
 obj-$(CONFIG_CMD_CBFS) += cbfs.o
 obj-$(CONFIG_CMD_CLK) += clk.o
diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c
index 1c4bed9..ae3027a 100644
--- a/cmd/bdinfo.c
+++ b/cmd/bdinfo.c
@@ -69,6 +69,105 @@
 	printf("%-12s= %6s MHz\n", name, strmhz(buf, hz));
 }
 
+
+static inline void print_bi_boot_params(const bd_t *bd)
+{
+	print_num("boot_params",	(ulong)bd->bi_boot_params);
+}
+
+static inline void print_bi_mem(const bd_t *bd)
+{
+#if defined(CONFIG_SH)
+	print_num("mem start      ",	(ulong)bd->bi_memstart);
+	print_lnum("mem size       ",	(u64)bd->bi_memsize);
+#elif defined(CONFIG_ARC)
+	print_num("mem start",		(ulong)bd->bi_memstart);
+	print_lnum("mem size",		(u64)bd->bi_memsize);
+#elif defined(CONFIG_AVR32)
+	print_num("memstart",		(ulong)bd->bi_dram[0].start);
+	print_lnum("memsize",		(u64)bd->bi_dram[0].size);
+#else
+	print_num("memstart",		(ulong)bd->bi_memstart);
+	print_lnum("memsize",		(u64)bd->bi_memsize);
+#endif
+}
+
+static inline void print_bi_dram(const bd_t *bd)
+{
+#ifdef CONFIG_NR_DRAM_BANKS
+	int i;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
+		if (bd->bi_dram[i].size) {
+			print_num("DRAM bank",	i);
+			print_num("-> start",	bd->bi_dram[i].start);
+			print_num("-> size",	bd->bi_dram[i].size);
+		}
+	}
+#endif
+}
+
+static inline void print_bi_flash(const bd_t *bd)
+{
+#if defined(CONFIG_MICROBLAZE) || defined(CONFIG_SH)
+	print_num("flash start    ",	(ulong)bd->bi_flashstart);
+	print_num("flash size     ",	(ulong)bd->bi_flashsize);
+	print_num("flash offset   ",	(ulong)bd->bi_flashoffset);
+
+#elif defined(CONFIG_NIOS2) || defined(CONFIG_OPENRISC)
+	print_num("flash start",	(ulong)bd->bi_flashstart);
+	print_num("flash size",		(ulong)bd->bi_flashsize);
+	print_num("flash offset",	(ulong)bd->bi_flashoffset);
+#else
+	print_num("flashstart",		(ulong)bd->bi_flashstart);
+	print_num("flashsize",		(ulong)bd->bi_flashsize);
+	print_num("flashoffset",	(ulong)bd->bi_flashoffset);
+#endif
+}
+
+static inline void print_eth_ip_addr(void)
+{
+#if defined(CONFIG_CMD_NET)
+	print_eth(0);
+#if defined(CONFIG_HAS_ETH1)
+	print_eth(1);
+#endif
+#if defined(CONFIG_HAS_ETH2)
+	print_eth(2);
+#endif
+#if defined(CONFIG_HAS_ETH3)
+	print_eth(3);
+#endif
+#if defined(CONFIG_HAS_ETH4)
+	print_eth(4);
+#endif
+#if defined(CONFIG_HAS_ETH5)
+	print_eth(5);
+#endif
+	printf("IP addr     = %s\n", getenv("ipaddr"));
+#endif
+}
+
+static inline void print_baudrate(void)
+{
+#if defined(CONFIG_PPC)
+	printf("baudrate    = %6u bps\n", gd->baudrate);
+#elif defined(CONFIG_SPARC)
+	printf("baudrate               = %6u bps\n", gd->baudrate);
+#else
+	printf("baudrate    = %u bps\n", gd->baudrate);
+#endif
+}
+
+static inline void print_std_bdinfo(const bd_t *bd)
+{
+	print_bi_boot_params(bd);
+	print_bi_mem(bd);
+	print_bi_flash(bd);
+	print_eth_ip_addr();
+	print_baudrate();
+}
+
 #if defined(CONFIG_PPC)
 void __weak board_detail(void)
 {
@@ -82,11 +181,8 @@
 #ifdef DEBUG
 	print_num("bd address",		(ulong)bd);
 #endif
-	print_num("memstart",		bd->bi_memstart);
-	print_lnum("memsize",		bd->bi_memsize);
-	print_num("flashstart",		bd->bi_flashstart);
-	print_num("flashsize",		bd->bi_flashsize);
-	print_num("flashoffset",	bd->bi_flashoffset);
+	print_bi_mem(bd);
+	print_bi_flash(bd);
 	print_num("sramstart",		bd->bi_sramstart);
 	print_num("sramsize",		bd->bi_sramsize);
 #if	defined(CONFIG_5xx)  || defined(CONFIG_8xx) || \
@@ -127,27 +223,10 @@
 #else
 	puts("addressing  = 32-bit\n");
 #endif
-#endif
-
-	print_eth(0);
-#if defined(CONFIG_HAS_ETH1)
-	print_eth(1);
-#endif
-#if defined(CONFIG_HAS_ETH2)
-	print_eth(2);
-#endif
-#if defined(CONFIG_HAS_ETH3)
-	print_eth(3);
-#endif
-#if defined(CONFIG_HAS_ETH4)
-	print_eth(4);
-#endif
-#if defined(CONFIG_HAS_ETH5)
-	print_eth(5);
 #endif
 
-	printf("IP addr     = %s\n", getenv("ipaddr"));
-	printf("baudrate    = %6u bps\n", gd->baudrate);
+	print_eth_ip_addr();
+	print_baudrate();
 	print_num("relocaddr", gd->relocaddr);
 	board_detail();
 	return 0;
@@ -157,30 +236,18 @@
 
 int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	int i;
 	bd_t *bd = gd->bd;
 
-	for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
-		print_num("DRAM bank",	i);
-		print_num("-> start",	bd->bi_dram[i].start);
-		print_num("-> size",	bd->bi_dram[i].size);
-	}
-
-	print_num("flash start",	(ulong)bd->bi_flashstart);
-	print_num("flash size",		(ulong)bd->bi_flashsize);
-	print_num("flash offset",	(ulong)bd->bi_flashoffset);
+	print_bi_dram(bd);
+	print_bi_flash(bd);
 
 #if defined(CONFIG_SYS_SRAM_BASE)
 	print_num ("sram start",	(ulong)bd->bi_sramstart);
 	print_num ("sram size",		(ulong)bd->bi_sramsize);
 #endif
 
-#if defined(CONFIG_CMD_NET)
-	print_eth(0);
-	printf("ip_addr     = %s\n", getenv("ipaddr"));
-#endif
-
-	printf("baudrate    = %u bps\n", gd->baudrate);
+	print_eth_ip_addr();
+	print_baudrate();
 
 	return 0;
 }
@@ -190,17 +257,9 @@
 int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	bd_t *bd = gd->bd;
-	int i;
 
-	for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
-		print_num("DRAM bank",	i);
-		print_num("-> start",	bd->bi_dram[i].start);
-		print_num("-> size",	bd->bi_dram[i].size);
-	}
-
-	print_num("flash start    ",	(ulong)bd->bi_flashstart);
-	print_num("flash size     ",	(ulong)bd->bi_flashsize);
-	print_num("flash offset   ",	(ulong)bd->bi_flashoffset);
+	print_bi_dram(bd);
+	print_bi_flash(bd);
 #if defined(CONFIG_SYS_SRAM_BASE)
 	print_num("sram start     ",	(ulong)bd->bi_sramstart);
 	print_num("sram size      ",	(ulong)bd->bi_sramsize);
@@ -208,7 +267,7 @@
 #if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
 	print_eths();
 #endif
-	printf("baudrate    = %u bps\n", gd->baudrate);
+	print_baudrate();
 	print_num("relocaddr", gd->relocaddr);
 	print_num("reloc off", gd->reloc_off);
 	print_num("fdt_blob", (ulong)gd->fdt_blob);
@@ -243,11 +302,8 @@
 	printf("CONFIG_SYS_GBL_DATA_OFFSET    = 0x%x (%d)\n", CONFIG_SYS_GBL_DATA_OFFSET,
 	       GENERATED_GBL_DATA_SIZE);
 
-#if defined(CONFIG_CMD_NET)
-	print_eth(0);
-	printf("ip_addr     = %s\n", getenv("ipaddr"));
-#endif
-	printf("baudrate               = %6u bps\n", gd->baudrate);
+	print_eth_ip_addr();
+	print_baudrate();
 	return 0;
 }
 
@@ -257,11 +313,8 @@
 {
 	bd_t *bd = gd->bd;
 
-	print_num("memstart",		(ulong)bd->bi_memstart);
-	print_lnum("memsize",		(u64)bd->bi_memsize);
-	print_num("flashstart",		(ulong)bd->bi_flashstart);
-	print_num("flashsize",		(ulong)bd->bi_flashsize);
-	print_num("flashoffset",	(ulong)bd->bi_flashoffset);
+	print_bi_mem(bd);
+	print_bi_flash(bd);
 #if defined(CONFIG_SYS_INIT_RAM_ADDR)
 	print_num("sramstart",		(ulong)bd->bi_sramstart);
 	print_num("sramsize",		(ulong)bd->bi_sramsize);
@@ -279,21 +332,8 @@
 	print_mhz("inpfreq",		bd->bi_inpfreq);
 	print_mhz("vcofreq",		bd->bi_vcofreq);
 #endif
-#if defined(CONFIG_CMD_NET)
-	print_eth(0);
-#if defined(CONFIG_HAS_ETH1)
-	print_eth(1);
-#endif
-#if defined(CONFIG_HAS_ETH2)
-	print_eth(2);
-#endif
-#if defined(CONFIG_HAS_ETH3)
-	print_eth(3);
-#endif
-
-	printf("ip_addr     = %s\n", getenv("ipaddr"));
-#endif
-	printf("baudrate    = %u bps\n", gd->baudrate);
+	print_eth_ip_addr();
+	print_baudrate();
 
 	return 0;
 }
@@ -311,16 +351,7 @@
 	print_mhz("CCLK",	bd->bi_cclk);
 	print_mhz("SCLK",	bd->bi_sclk);
 
-	print_num("boot_params",	(ulong)bd->bi_boot_params);
-	print_num("memstart",		(ulong)bd->bi_memstart);
-	print_lnum("memsize",		(u64)bd->bi_memsize);
-	print_num("flashstart",		(ulong)bd->bi_flashstart);
-	print_num("flashsize",		(ulong)bd->bi_flashsize);
-	print_num("flashoffset",	(ulong)bd->bi_flashoffset);
-
-	print_eth(0);
-	printf("ip_addr     = %s\n", getenv("ipaddr"));
-	printf("baudrate    = %u bps\n", gd->baudrate);
+	print_std_bdinfo(bd);
 
 	return 0;
 }
@@ -329,18 +360,7 @@
 
 int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	bd_t *bd = gd->bd;
-
-	print_num("boot_params",	(ulong)bd->bi_boot_params);
-	print_num("memstart",		(ulong)bd->bi_memstart);
-	print_lnum("memsize",		(u64)bd->bi_memsize);
-	print_num("flashstart",		(ulong)bd->bi_flashstart);
-	print_num("flashsize",		(ulong)bd->bi_flashsize);
-	print_num("flashoffset",	(ulong)bd->bi_flashoffset);
-
-	print_eth(0);
-	printf("ip_addr     = %s\n", getenv("ipaddr"));
-	printf("baudrate    = %u bps\n", gd->baudrate);
+	print_std_bdinfo(gd->bd);
 	print_num("relocaddr", gd->relocaddr);
 	print_num("reloc off", gd->reloc_off);
 
@@ -351,19 +371,7 @@
 
 int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	bd_t *bd = gd->bd;
-
-	print_num("boot_params",	(ulong)bd->bi_boot_params);
-	print_num("memstart",		(ulong)bd->bi_dram[0].start);
-	print_lnum("memsize",		(u64)bd->bi_dram[0].size);
-	print_num("flashstart",		(ulong)bd->bi_flashstart);
-	print_num("flashsize",		(ulong)bd->bi_flashsize);
-	print_num("flashoffset",	(ulong)bd->bi_flashoffset);
-
-	print_eth(0);
-	printf("ip_addr     = %s\n", getenv("ipaddr"));
-	printf("baudrate    = %u bps\n", gd->baudrate);
-
+	print_std_bdinfo(gd->bd);
 	return 0;
 }
 
@@ -372,28 +380,22 @@
 static int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc,
 			char * const argv[])
 {
-	int i;
 	bd_t *bd = gd->bd;
 
 	print_num("arch_number",	bd->bi_arch_number);
-	print_num("boot_params",	(ulong)bd->bi_boot_params);
-
-	for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
-		print_num("DRAM bank",	i);
-		print_num("-> start",	bd->bi_dram[i].start);
-		print_num("-> size",	bd->bi_dram[i].size);
-	}
+	print_bi_boot_params(bd);
+	print_bi_dram(bd);
 
 #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
-	if (gd->secure_ram & MEM_RESERVE_SECURE_SECURED) {
+	if (gd->arch.secure_ram & MEM_RESERVE_SECURE_SECURED) {
 		print_num("Secure ram",
-			  gd->secure_ram & MEM_RESERVE_SECURE_ADDR_MASK);
+			  gd->arch.secure_ram & MEM_RESERVE_SECURE_ADDR_MASK);
 	}
 #endif
 #if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
 	print_eths();
 #endif
-	printf("baudrate    = %u bps\n", gd->baudrate);
+	print_baudrate();
 #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
 	print_num("TLB addr", gd->arch.tlb_addr);
 #endif
@@ -416,6 +418,11 @@
 #ifdef CONFIG_BOARD_TYPES
 	printf("Board Type  = %ld\n", gd->board_type);
 #endif
+#ifdef CONFIG_SYS_MALLOC_F
+	printf("Early malloc usage: %lx / %x\n", gd->malloc_ptr,
+	       CONFIG_SYS_MALLOC_F_LEN);
+#endif
+
 	return 0;
 }
 
@@ -424,17 +431,11 @@
 int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	bd_t *bd = gd->bd;
-	print_num("mem start      ",	(ulong)bd->bi_memstart);
-	print_lnum("mem size       ",	(u64)bd->bi_memsize);
-	print_num("flash start    ",	(ulong)bd->bi_flashstart);
-	print_num("flash size     ",	(ulong)bd->bi_flashsize);
-	print_num("flash offset   ",	(ulong)bd->bi_flashoffset);
 
-#if defined(CONFIG_CMD_NET)
-	print_eth(0);
-	printf("ip_addr     = %s\n", getenv("ipaddr"));
-#endif
-	printf("baudrate    = %u bps\n", gd->baudrate);
+	print_bi_mem(bd);
+	print_bi_flash(bd);
+	print_eth_ip_addr();
+	print_baudrate();
 	return 0;
 }
 
@@ -442,33 +443,17 @@
 
 int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	int i;
 	bd_t *bd = gd->bd;
 
-	print_num("boot_params",	(ulong)bd->bi_boot_params);
-	print_num("bi_memstart",	bd->bi_memstart);
-	print_num("bi_memsize",		bd->bi_memsize);
-	print_num("bi_flashstart",	bd->bi_flashstart);
-	print_num("bi_flashsize",	bd->bi_flashsize);
-	print_num("bi_flashoffset",	bd->bi_flashoffset);
-	print_num("bi_sramstart",	bd->bi_sramstart);
-	print_num("bi_sramsize",	bd->bi_sramsize);
-	print_num("bi_bootflags",	bd->bi_bootflags);
-	print_mhz("cpufreq",		bd->bi_intfreq);
-	print_mhz("busfreq",		bd->bi_busfreq);
+	print_bi_boot_params(bd);
 
-	for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
-		print_num("DRAM bank",	i);
-		print_num("-> start",	bd->bi_dram[i].start);
-		print_num("-> size",	bd->bi_dram[i].size);
-	}
+	print_bi_dram(bd);
 
 #if defined(CONFIG_CMD_NET)
-	print_eth(0);
-	printf("ip_addr     = %s\n", getenv("ipaddr"));
+	print_eth_ip_addr();
 	print_mhz("ethspeed",	    bd->bi_ethspeed);
 #endif
-	printf("baudrate    = %u bps\n", gd->baudrate);
+	print_baudrate();
 
 	return 0;
 }
@@ -477,21 +462,12 @@
 
 int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	int i;
 	bd_t *bd = gd->bd;
 
-	print_num("boot_params", (ulong)bd->bi_boot_params);
-
-	for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
-		print_num("DRAM bank", i);
-		print_num("-> start", bd->bi_dram[i].start);
-		print_num("-> size", bd->bi_dram[i].size);
-	}
+	print_bi_boot_params(bd);
+	print_bi_dram(bd);
+	print_eth_ip_addr();
 
-#if defined(CONFIG_CMD_NET)
-	print_eth(0);
-	printf("ip_addr     = %s\n", getenv("ipaddr"));
-#endif
 #if defined(CONFIG_LCD) || defined(CONFIG_VIDEO)
 	print_num("FB base  ", gd->fb_base);
 #endif
@@ -502,23 +478,13 @@
 
 int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	int i;
 	bd_t *bd = gd->bd;
 
 	print_num("arch_number",	bd->bi_arch_number);
-	print_num("boot_params",	(ulong)bd->bi_boot_params);
-
-	for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
-		print_num("DRAM bank",	i);
-		print_num("-> start",	bd->bi_dram[i].start);
-		print_num("-> size",	bd->bi_dram[i].size);
-	}
-
-#if defined(CONFIG_CMD_NET)
-	print_eth(0);
-	printf("ip_addr     = %s\n", getenv("ipaddr"));
-#endif
-	printf("baudrate    = %u bps\n", gd->baudrate);
+	print_bi_boot_params(bd);
+	print_bi_dram(bd);
+	print_eth_ip_addr();
+	print_baudrate();
 
 	return 0;
 }
@@ -529,18 +495,10 @@
 {
 	bd_t *bd = gd->bd;
 
-	print_num("mem start",		(ulong)bd->bi_memstart);
-	print_lnum("mem size",		(u64)bd->bi_memsize);
-	print_num("flash start",	(ulong)bd->bi_flashstart);
-	print_num("flash size",		(ulong)bd->bi_flashsize);
-	print_num("flash offset",	(ulong)bd->bi_flashoffset);
-
-#if defined(CONFIG_CMD_NET)
-	print_eth(0);
-	printf("ip_addr     = %s\n", getenv("ipaddr"));
-#endif
-
-	printf("baudrate    = %u bps\n", gd->baudrate);
+	print_bi_mem(bd);
+	print_bi_flash(bd);
+	print_eth_ip_addr();
+	print_baudrate();
 
 	return 0;
 }
@@ -551,15 +509,18 @@
 {
 	bd_t *bd = gd->bd;
 
-	print_num("mem start",		bd->bi_memstart);
-	print_lnum("mem size",		bd->bi_memsize);
+	print_bi_mem(bd);
+	print_eth_ip_addr();
+	print_baudrate();
 
-#if defined(CONFIG_CMD_NET)
-	print_eth(0);
-	printf("ip_addr     = %s\n", getenv("ipaddr"));
-#endif
-	printf("baudrate    = %d bps\n", gd->baudrate);
+	return 0;
+}
 
+#elif defined(CONFIG_XTENSA)
+
+int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	print_std_bdinfo(gd->bd);
 	return 0;
 }
 
diff --git a/cmd/blob.c b/cmd/blob.c
index ac8b268..bdd4cfd 100644
--- a/cmd/blob.c
+++ b/cmd/blob.c
@@ -54,7 +54,7 @@
  */
 static int do_blob(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 {
-	uint32_t key_addr, src_addr, dst_addr, len;
+	ulong key_addr, src_addr, dst_addr, len;
 	uint8_t *km_ptr, *src_ptr, *dst_ptr;
 	int enc, ret = 0;
 
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 011f62c..21fe42c 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <dm/device.h>
 #include <efi_loader.h>
 #include <errno.h>
 #include <libfdt.h>
@@ -225,7 +226,7 @@
 	int r = 0;
 
 	if (argc < 2)
-		return 1;
+		return CMD_RET_USAGE;
 	saddr = argv[1];
 
 	addr = simple_strtoul(saddr, NULL, 16);
@@ -265,18 +266,30 @@
 	char devname[32] = { 0 }; /* dp->str is u16[32] long */
 	char *colon;
 
-	/* Assemble the condensed device name we use in efi_disk.c */
-	snprintf(devname, sizeof(devname), "%s%s", dev, devnr);
+#if defined(CONFIG_BLK) || defined(CONFIG_ISO_PARTITION)
+	desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10));
+#endif
+
+#ifdef CONFIG_BLK
+	if (desc) {
+		snprintf(devname, sizeof(devname), "%s", desc->bdev->name);
+	} else
+#endif
+
+	{
+		/* Assemble the condensed device name we use in efi_disk.c */
+		snprintf(devname, sizeof(devname), "%s%s", dev, devnr);
+	}
+
 	colon = strchr(devname, ':');
 
 #ifdef CONFIG_ISO_PARTITION
 	/* For ISOs we create partition block devices */
-	desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10));
 	if (desc && (desc->type != DEV_TYPE_UNKNOWN) &&
 	    (desc->part_type == PART_TYPE_ISO)) {
 		if (!colon)
-			snprintf(devname, sizeof(devname), "%s%s:1", dev,
-				 devnr);
+			snprintf(devname, sizeof(devname), "%s:1", devname);
+
 		colon = NULL;
 	}
 #endif
@@ -290,6 +303,11 @@
 
 	/* Patch bootefi_image_path to the target file path */
 	memset(bootefi_image_path[0].str, 0, sizeof(bootefi_image_path[0].str));
-	snprintf(devname, sizeof(devname), "%s", path);
+	if (strcmp(dev, "Net")) {
+		/* Add leading / to fs paths, because they're absolute */
+		snprintf(devname, sizeof(devname), "/%s", path);
+	} else {
+		snprintf(devname, sizeof(devname), "%s", path);
+	}
 	ascii2unicode(bootefi_image_path[0].str, devname);
 }
diff --git a/cmd/booti.c b/cmd/booti.c
new file mode 100644
index 0000000..6c1c998
--- /dev/null
+++ b/cmd/booti.c
@@ -0,0 +1,161 @@
+/*
+ * (C) Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <bootm.h>
+#include <command.h>
+#include <image.h>
+#include <lmb.h>
+#include <mapmem.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* See Documentation/arm64/booting.txt in the Linux kernel */
+struct Image_header {
+	uint32_t	code0;		/* Executable code */
+	uint32_t	code1;		/* Executable code */
+	uint64_t	text_offset;	/* Image load offset, LE */
+	uint64_t	image_size;	/* Effective Image size, LE */
+	uint64_t	res1;		/* reserved */
+	uint64_t	res2;		/* reserved */
+	uint64_t	res3;		/* reserved */
+	uint64_t	res4;		/* reserved */
+	uint32_t	magic;		/* Magic number */
+	uint32_t	res5;
+};
+
+#define LINUX_ARM64_IMAGE_MAGIC	0x644d5241
+
+static int booti_setup(bootm_headers_t *images)
+{
+	struct Image_header *ih;
+	uint64_t dst;
+	uint64_t image_size;
+
+	ih = (struct Image_header *)map_sysmem(images->ep, 0);
+
+	if (ih->magic != le32_to_cpu(LINUX_ARM64_IMAGE_MAGIC)) {
+		puts("Bad Linux ARM64 Image magic!\n");
+		return 1;
+	}
+	
+	if (ih->image_size == 0) {
+		puts("Image lacks image_size field, assuming 16MiB\n");
+		image_size = 16 << 20;
+	} else {
+		image_size = le64_to_cpu(ih->image_size);
+	}
+
+	/*
+	 * If we are not at the correct run-time location, set the new
+	 * correct location and then move the image there.
+	 */
+	dst = gd->bd->bi_dram[0].start + le64_to_cpu(ih->text_offset);
+
+	unmap_sysmem(ih);
+
+	if (images->ep != dst) {
+		void *src;
+
+		debug("Moving Image from 0x%lx to 0x%llx\n", images->ep, dst);
+
+		src = (void *)images->ep;
+		images->ep = dst;
+		memmove((void *)dst, src, image_size);
+	}
+
+	return 0;
+}
+
+/*
+ * Image booting support
+ */
+static int booti_start(cmd_tbl_t *cmdtp, int flag, int argc,
+			char * const argv[], bootm_headers_t *images)
+{
+	int ret;
+	struct Image_header *ih;
+
+	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
+			      images, 1);
+
+	/* Setup Linux kernel Image entry point */
+	if (!argc) {
+		images->ep = load_addr;
+		debug("*  kernel: default image load address = 0x%08lx\n",
+				load_addr);
+	} else {
+		images->ep = simple_strtoul(argv[0], NULL, 16);
+		debug("*  kernel: cmdline image address = 0x%08lx\n",
+			images->ep);
+	}
+
+	ret = booti_setup(images);
+	if (ret != 0)
+		return 1;
+
+	ih = (struct Image_header *)map_sysmem(images->ep, 0);
+
+	lmb_reserve(&images->lmb, images->ep, le32_to_cpu(ih->image_size));
+
+	unmap_sysmem(ih);
+
+	/*
+	 * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
+	 * have a header that provide this informaiton.
+	 */
+	if (bootm_find_images(flag, argc, argv))
+		return 1;
+
+	return 0;
+}
+
+int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int ret;
+
+	/* Consume 'booti' */
+	argc--; argv++;
+
+	if (booti_start(cmdtp, flag, argc, argv, &images))
+		return 1;
+
+	/*
+	 * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
+	 * disable interrupts ourselves
+	 */
+	bootm_disable_interrupts();
+
+	images.os.os = IH_OS_LINUX;
+	ret = do_bootm_states(cmdtp, flag, argc, argv,
+			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
+			      BOOTM_STATE_OS_GO,
+			      &images, 1);
+
+	return ret;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char booti_help_text[] =
+	"[addr [initrd[:size]] [fdt]]\n"
+	"    - boot arm64 Linux Image stored in memory\n"
+	"\tThe argument 'initrd' is optional and specifies the address\n"
+	"\tof an initrd in memory. The optional parameter ':size' allows\n"
+	"\tspecifying the size of a RAW initrd.\n"
+#if defined(CONFIG_OF_LIBFDT)
+	"\tSince booting a Linux kernel requires a flat device-tree, a\n"
+	"\tthird argument providing the address of the device-tree blob\n"
+	"\tis required. To boot a kernel with a device-tree blob but\n"
+	"\twithout an initrd image, use a '-' for the initrd argument.\n"
+#endif
+	"";
+#endif
+
+U_BOOT_CMD(
+	booti,	CONFIG_SYS_MAXARGS,	1,	do_booti,
+	"boot arm64 Linux Image image from memory", booti_help_text
+);
diff --git a/cmd/bootm.c b/cmd/bootm.c
index 16fdea5..e02a1c5 100644
--- a/cmd/bootm.c
+++ b/cmd/bootm.c
@@ -14,12 +14,9 @@
 #include <environment.h>
 #include <errno.h>
 #include <image.h>
-#include <lmb.h>
 #include <malloc.h>
-#include <mapmem.h>
 #include <nand.h>
 #include <asm/byteorder.h>
-#include <linux/compiler.h>
 #include <linux/ctype.h>
 #include <linux/err.h>
 #include <u-boot/zlib.h>
@@ -40,8 +37,6 @@
 static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 #endif
 
-bootm_headers_t images;		/* pointers to os/initrd/fdt images */
-
 /* we overload the cmd field with our state machine info instead of a
  * function pointer */
 static cmd_tbl_t cmd_bootm_sub[] = {
@@ -539,249 +534,4 @@
 	"    - Prints information about all images found at sector/block\n"
 	"      boundaries in nor/nand flash."
 );
-#endif
-
-#ifdef CONFIG_CMD_BOOTZ
-
-int __weak bootz_setup(ulong image, ulong *start, ulong *end)
-{
-	/* Please define bootz_setup() for your platform */
-
-	puts("Your platform's zImage format isn't supported yet!\n");
-	return -1;
-}
-
-/*
- * zImage booting support
- */
-static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
-			char * const argv[], bootm_headers_t *images)
-{
-	int ret;
-	ulong zi_start, zi_end;
-
-	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
-			      images, 1);
-
-	/* Setup Linux kernel zImage entry point */
-	if (!argc) {
-		images->ep = load_addr;
-		debug("*  kernel: default image load address = 0x%08lx\n",
-				load_addr);
-	} else {
-		images->ep = simple_strtoul(argv[0], NULL, 16);
-		debug("*  kernel: cmdline image address = 0x%08lx\n",
-			images->ep);
-	}
-
-	ret = bootz_setup(images->ep, &zi_start, &zi_end);
-	if (ret != 0)
-		return 1;
-
-	lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);
-
-	/*
-	 * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
-	 * have a header that provide this informaiton.
-	 */
-	if (bootm_find_images(flag, argc, argv))
-		return 1;
-
-	return 0;
-}
-
-int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-	int ret;
-
-	/* Consume 'bootz' */
-	argc--; argv++;
-
-	if (bootz_start(cmdtp, flag, argc, argv, &images))
-		return 1;
-
-	/*
-	 * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
-	 * disable interrupts ourselves
-	 */
-	bootm_disable_interrupts();
-
-	images.os.os = IH_OS_LINUX;
-	ret = do_bootm_states(cmdtp, flag, argc, argv,
-			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
-			      BOOTM_STATE_OS_GO,
-			      &images, 1);
-
-	return ret;
-}
-
-#ifdef CONFIG_SYS_LONGHELP
-static char bootz_help_text[] =
-	"[addr [initrd[:size]] [fdt]]\n"
-	"    - boot Linux zImage stored in memory\n"
-	"\tThe argument 'initrd' is optional and specifies the address\n"
-	"\tof the initrd in memory. The optional argument ':size' allows\n"
-	"\tspecifying the size of RAW initrd.\n"
-#if defined(CONFIG_OF_LIBFDT)
-	"\tWhen booting a Linux kernel which requires a flat device-tree\n"
-	"\ta third argument is required which is the address of the\n"
-	"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
-	"\tuse a '-' for the second argument. If you do not pass a third\n"
-	"\ta bd_info struct will be passed instead\n"
-#endif
-	"";
-#endif
-
-U_BOOT_CMD(
-	bootz,	CONFIG_SYS_MAXARGS,	1,	do_bootz,
-	"boot Linux zImage image from memory", bootz_help_text
-);
-#endif	/* CONFIG_CMD_BOOTZ */
-
-#ifdef CONFIG_CMD_BOOTI
-/* See Documentation/arm64/booting.txt in the Linux kernel */
-struct Image_header {
-	uint32_t	code0;		/* Executable code */
-	uint32_t	code1;		/* Executable code */
-	uint64_t	text_offset;	/* Image load offset, LE */
-	uint64_t	image_size;	/* Effective Image size, LE */
-	uint64_t	res1;		/* reserved */
-	uint64_t	res2;		/* reserved */
-	uint64_t	res3;		/* reserved */
-	uint64_t	res4;		/* reserved */
-	uint32_t	magic;		/* Magic number */
-	uint32_t	res5;
-};
-
-#define LINUX_ARM64_IMAGE_MAGIC	0x644d5241
-
-static int booti_setup(bootm_headers_t *images)
-{
-	struct Image_header *ih;
-	uint64_t dst;
-	uint64_t image_size;
-
-	ih = (struct Image_header *)map_sysmem(images->ep, 0);
-
-	if (ih->magic != le32_to_cpu(LINUX_ARM64_IMAGE_MAGIC)) {
-		puts("Bad Linux ARM64 Image magic!\n");
-		return 1;
-	}
-	
-	if (ih->image_size == 0) {
-		puts("Image lacks image_size field, assuming 16MiB\n");
-		image_size = 16 << 20;
-	} else {
-		image_size = le64_to_cpu(ih->image_size);
-	}
-
-	/*
-	 * If we are not at the correct run-time location, set the new
-	 * correct location and then move the image there.
-	 */
-	dst = gd->bd->bi_dram[0].start + le64_to_cpu(ih->text_offset);
-
-	unmap_sysmem(ih);
-
-	if (images->ep != dst) {
-		void *src;
-
-		debug("Moving Image from 0x%lx to 0x%llx\n", images->ep, dst);
-
-		src = (void *)images->ep;
-		images->ep = dst;
-		memmove((void *)dst, src, image_size);
-	}
-
-	return 0;
-}
-
-/*
- * Image booting support
- */
-static int booti_start(cmd_tbl_t *cmdtp, int flag, int argc,
-			char * const argv[], bootm_headers_t *images)
-{
-	int ret;
-	struct Image_header *ih;
-
-	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
-			      images, 1);
-
-	/* Setup Linux kernel Image entry point */
-	if (!argc) {
-		images->ep = load_addr;
-		debug("*  kernel: default image load address = 0x%08lx\n",
-				load_addr);
-	} else {
-		images->ep = simple_strtoul(argv[0], NULL, 16);
-		debug("*  kernel: cmdline image address = 0x%08lx\n",
-			images->ep);
-	}
-
-	ret = booti_setup(images);
-	if (ret != 0)
-		return 1;
-
-	ih = (struct Image_header *)map_sysmem(images->ep, 0);
-
-	lmb_reserve(&images->lmb, images->ep, le32_to_cpu(ih->image_size));
-
-	unmap_sysmem(ih);
-
-	/*
-	 * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
-	 * have a header that provide this informaiton.
-	 */
-	if (bootm_find_images(flag, argc, argv))
-		return 1;
-
-	return 0;
-}
-
-int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-	int ret;
-
-	/* Consume 'booti' */
-	argc--; argv++;
-
-	if (booti_start(cmdtp, flag, argc, argv, &images))
-		return 1;
-
-	/*
-	 * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
-	 * disable interrupts ourselves
-	 */
-	bootm_disable_interrupts();
-
-	images.os.os = IH_OS_LINUX;
-	ret = do_bootm_states(cmdtp, flag, argc, argv,
-			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
-			      BOOTM_STATE_OS_GO,
-			      &images, 1);
-
-	return ret;
-}
-
-#ifdef CONFIG_SYS_LONGHELP
-static char booti_help_text[] =
-	"[addr [initrd[:size]] [fdt]]\n"
-	"    - boot arm64 Linux Image stored in memory\n"
-	"\tThe argument 'initrd' is optional and specifies the address\n"
-	"\tof an initrd in memory. The optional parameter ':size' allows\n"
-	"\tspecifying the size of a RAW initrd.\n"
-#if defined(CONFIG_OF_LIBFDT)
-	"\tSince booting a Linux kernel requires a flat device-tree, a\n"
-	"\tthird argument providing the address of the device-tree blob\n"
-	"\tis required. To boot a kernel with a device-tree blob but\n"
-	"\twithout an initrd image, use a '-' for the initrd argument.\n"
-#endif
-	"";
 #endif
-
-U_BOOT_CMD(
-	booti,	CONFIG_SYS_MAXARGS,	1,	do_booti,
-	"boot arm64 Linux Image image from memory", booti_help_text
-);
-#endif	/* CONFIG_CMD_BOOTI */
diff --git a/cmd/bootz.c b/cmd/bootz.c
new file mode 100644
index 0000000..9648fe9
--- /dev/null
+++ b/cmd/bootz.c
@@ -0,0 +1,106 @@
+/*
+ * (C) Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <bootm.h>
+#include <command.h>
+#include <lmb.h>
+#include <linux/compiler.h>
+
+int __weak bootz_setup(ulong image, ulong *start, ulong *end)
+{
+	/* Please define bootz_setup() for your platform */
+
+	puts("Your platform's zImage format isn't supported yet!\n");
+	return -1;
+}
+
+/*
+ * zImage booting support
+ */
+static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
+			char * const argv[], bootm_headers_t *images)
+{
+	int ret;
+	ulong zi_start, zi_end;
+
+	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
+			      images, 1);
+
+	/* Setup Linux kernel zImage entry point */
+	if (!argc) {
+		images->ep = load_addr;
+		debug("*  kernel: default image load address = 0x%08lx\n",
+				load_addr);
+	} else {
+		images->ep = simple_strtoul(argv[0], NULL, 16);
+		debug("*  kernel: cmdline image address = 0x%08lx\n",
+			images->ep);
+	}
+
+	ret = bootz_setup(images->ep, &zi_start, &zi_end);
+	if (ret != 0)
+		return 1;
+
+	lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);
+
+	/*
+	 * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
+	 * have a header that provide this informaiton.
+	 */
+	if (bootm_find_images(flag, argc, argv))
+		return 1;
+
+	return 0;
+}
+
+int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int ret;
+
+	/* Consume 'bootz' */
+	argc--; argv++;
+
+	if (bootz_start(cmdtp, flag, argc, argv, &images))
+		return 1;
+
+	/*
+	 * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
+	 * disable interrupts ourselves
+	 */
+	bootm_disable_interrupts();
+
+	images.os.os = IH_OS_LINUX;
+	ret = do_bootm_states(cmdtp, flag, argc, argv,
+			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
+			      BOOTM_STATE_OS_GO,
+			      &images, 1);
+
+	return ret;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char bootz_help_text[] =
+	"[addr [initrd[:size]] [fdt]]\n"
+	"    - boot Linux zImage stored in memory\n"
+	"\tThe argument 'initrd' is optional and specifies the address\n"
+	"\tof the initrd in memory. The optional argument ':size' allows\n"
+	"\tspecifying the size of RAW initrd.\n"
+#if defined(CONFIG_OF_LIBFDT)
+	"\tWhen booting a Linux kernel which requires a flat device-tree\n"
+	"\ta third argument is required which is the address of the\n"
+	"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
+	"\tuse a '-' for the second argument. If you do not pass a third\n"
+	"\ta bd_info struct will be passed instead\n"
+#endif
+	"";
+#endif
+
+U_BOOT_CMD(
+	bootz,	CONFIG_SYS_MAXARGS,	1,	do_bootz,
+	"boot Linux zImage image from memory", bootz_help_text
+);
diff --git a/cmd/fastboot/Kconfig b/cmd/fastboot/Kconfig
new file mode 100644
index 0000000..a93d1c0
--- /dev/null
+++ b/cmd/fastboot/Kconfig
@@ -0,0 +1,60 @@
+comment "FASTBOOT"
+
+config FASTBOOT
+	bool ""
+
+menu "Fastboot support"
+	depends on FASTBOOT
+
+config USB_FUNCTION_FASTBOOT
+	bool "Enable USB fastboot gadget"
+	help
+	  This enables the USB part of the fastboot gadget.
+
+config CMD_FASTBOOT
+	bool "Enable FASTBOOT command"
+	help
+	  This enables the command "fastboot" which enables the Android
+	  fastboot mode for the platform's USB device. Fastboot is a USB
+	  protocol for downloading images, flashing and device control
+	  used on Android devices.
+
+config ANDROID_BOOT_IMAGE
+	bool "Enable support for Android Boot Images"
+	help
+	  This enables support for booting images which use the Android
+	  image format header.
+
+if USB_FUNCTION_FASTBOOT
+
+config FASTBOOT_BUF_ADDR
+	hex "Define FASTBOOT buffer address"
+	help
+	  The fastboot protocol requires a large memory buffer for
+	  downloads. Define this to the starting RAM address to use for
+	  downloaded images.
+
+config FASTBOOT_BUF_SIZE
+	hex "Define FASTBOOT buffer size"
+	help
+	  The fastboot protocol requires a large memory buffer for
+	  downloads. This buffer should be as large as possible for a
+	  platform. Define this to the size available RAM for fastboot.
+
+config FASTBOOT_FLASH
+	bool "Enable FASTBOOT FLASH command"
+	help
+	  The fastboot protocol includes a "flash" command for writing
+	  the downloaded image to a non-volatile storage device. Define
+	  this to enable the "fastboot flash" command.
+
+config FASTBOOT_FLASH_MMC_DEV
+	int "Define FASTBOOT MMC FLASH default device"
+	help
+	  The fastboot "flash" command requires additional information
+	  regarding the non-volatile storage device. Define this to
+	  the eMMC device that fastboot should use to store the image.
+
+endif # USB_FUNCTION_FASTBOOT
+
+endmenu
diff --git a/cmd/fdt.c b/cmd/fdt.c
index 898217f..58af772 100644
--- a/cmd/fdt.c
+++ b/cmd/fdt.c
@@ -87,7 +87,7 @@
 	/*
 	 * Set the address of the fdt
 	 */
-	if (argv[1][0] == 'a') {
+	if (strncmp(argv[1], "ad", 2) == 0) {
 		unsigned long addr;
 		int control = 0;
 		struct fdt_header *blob;
@@ -639,6 +639,27 @@
 #endif
 
 	}
+#ifdef CONFIG_OF_LIBFDT_OVERLAY
+	/* apply an overlay */
+	else if (strncmp(argv[1], "ap", 2) == 0) {
+		unsigned long addr;
+		struct fdt_header *blob;
+
+		if (argc != 3)
+			return CMD_RET_USAGE;
+
+		if (!working_fdt)
+			return CMD_RET_FAILURE;
+
+		addr = simple_strtoul(argv[2], NULL, 16);
+		blob = map_sysmem(addr, 0);
+		if (!fdt_valid(&blob))
+			return CMD_RET_FAILURE;
+
+		if (fdt_overlay_apply(working_fdt, blob))
+			return CMD_RET_FAILURE;
+	}
+#endif
 	/* resize the fdt */
 	else if (strncmp(argv[1], "re", 2) == 0) {
 		fdt_shrink_to_minimum(working_fdt);
@@ -1025,6 +1046,9 @@
 #ifdef CONFIG_SYS_LONGHELP
 static char fdt_help_text[] =
 	"addr [-c]  <addr> [<length>]   - Set the [control] fdt location to <addr>\n"
+#ifdef CONFIG_OF_LIBFDT_OVERLAY
+	"fdt apply <addr>                    - Apply overlay to the DT\n"
+#endif
 #ifdef CONFIG_OF_BOARD_SETUP
 	"fdt boardsetup                      - Do board-specific set up\n"
 #endif
diff --git a/cmd/gpt.c b/cmd/gpt.c
index 3d9706b..897596a 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -298,8 +298,8 @@
 		if (extract_env(val, &p))
 			p = val;
 		if ((strcmp(p, "-") == 0)) {
-			/* remove first usable lba and last block */
-			parts[i].size = dev_desc->lba - 34  - 1 - offset;
+			/* Let part efi module to auto extend the size */
+			parts[i].size = 0;
 		} else {
 			size_ll = ustrtoull(p, &p, 0);
 			parts[i].size = lldiv(size_ll, dev_desc->blksz);
diff --git a/cmd/i2c.c b/cmd/i2c.c
index 18ce789..473153f 100644
--- a/cmd/i2c.c
+++ b/cmd/i2c.c
@@ -178,7 +178,7 @@
  * i2c_init_board() - Board-specific I2C bus init
  *
  * This function is the default no-op implementation of I2C bus
- * initialization. This function can be overriden by board-specific
+ * initialization. This function can be overridden by board-specific
  * implementation if needed.
  */
 __weak
diff --git a/cmd/lzmadec.c b/cmd/lzmadec.c
index 1ad9ed6..c78df82 100644
--- a/cmd/lzmadec.c
+++ b/cmd/lzmadec.c
@@ -20,7 +20,7 @@
 static int do_lzmadec(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 {
 	unsigned long src, dst;
-	unsigned long src_len = ~0UL, dst_len = ~0UL;
+	SizeT src_len = ~0UL, dst_len = ~0UL;
 	int ret;
 
 	switch (argc) {
@@ -40,7 +40,8 @@
 
 	if (ret != SZ_OK)
 		return 1;
-	printf("Uncompressed size: %ld = 0x%lX\n", src_len, src_len);
+	printf("Uncompressed size: %ld = %#lX\n", (ulong)src_len,
+	       (ulong)src_len);
 	setenv_hex("filesize", src_len);
 
 	return 0;
diff --git a/cmd/misc.c b/cmd/misc.c
index 39d8683..efcbb90 100644
--- a/cmd/misc.c
+++ b/cmd/misc.c
@@ -15,13 +15,31 @@
 static int do_sleep(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	ulong start = get_timer(0);
+	ulong mdelay = 0;
 	ulong delay;
+	char *frpart;
 
 	if (argc != 2)
 		return CMD_RET_USAGE;
 
 	delay = simple_strtoul(argv[1], NULL, 10) * CONFIG_SYS_HZ;
 
+	frpart = strchr(argv[1], '.');
+
+	if (frpart) {
+		uint mult = CONFIG_SYS_HZ / 10;
+		for (frpart++; *frpart != '\0' && mult > 0; frpart++) {
+			if (*frpart < '0' || *frpart > '9') {
+				mdelay = 0;
+				break;
+			}
+			mdelay += (*frpart - '0') * mult;
+			mult /= 10;
+		}
+	}
+
+	delay += mdelay;
+
 	while (get_timer(start) < delay) {
 		if (ctrlc())
 			return (-1);
@@ -36,7 +54,8 @@
 	sleep ,    2,    1,     do_sleep,
 	"delay execution for some time",
 	"N\n"
-	"    - delay execution for N seconds (N is _decimal_ !!!)"
+	"    - delay execution for N seconds (N is _decimal_ and can be\n"
+	"      fractional)"
 );
 
 #ifdef CONFIG_CMD_TIMER
diff --git a/cmd/mtdparts.c b/cmd/mtdparts.c
index 44b2c3a..b9b160d 100644
--- a/cmd/mtdparts.c
+++ b/cmd/mtdparts.c
@@ -109,17 +109,17 @@
 #define MTD_WRITEABLE_CMD		1
 
 /* default values for mtdids and mtdparts variables */
-#if defined(MTDIDS_DEFAULT)
-static const char *const mtdids_default = MTDIDS_DEFAULT;
-#else
-static const char *const mtdids_default = NULL;
+#if !defined(MTDIDS_DEFAULT)
+#define MTDIDS_DEFAULT NULL
 #endif
-
-#if defined(MTDPARTS_DEFAULT)
-static const char *const mtdparts_default = MTDPARTS_DEFAULT;
-#else
-static const char *const mtdparts_default = NULL;
+#if !defined(MTDPARTS_DEFAULT)
+#define MTDPARTS_DEFAULT NULL
+#endif
+#if defined(CONFIG_SYS_MTDPARTS_RUNTIME)
+extern void board_mtdparts_default(const char **mtdids, const char **mtdparts);
 #endif
+static const char *mtdids_default = MTDIDS_DEFAULT;
+static const char *mtdparts_default = MTDPARTS_DEFAULT;
 
 /* copies of last seen 'mtdids', 'mtdparts' and 'partition' env variables */
 #define MTDIDS_MAXLEN		128
@@ -142,6 +142,8 @@
 struct mtd_device *current_mtd_dev = NULL;
 u8 current_mtd_partnum = 0;
 
+u8 use_defaults;
+
 static struct part_info* mtd_part_info(struct mtd_device *dev, unsigned int part_num);
 
 /* command line only routines */
@@ -1491,7 +1493,7 @@
 			part = list_entry(pentry, struct part_info, link);
 
 			debug("spread_partitions: device = %s%d, partition %d ="
-				" (%s) 0x%08x@0x%08x\n",
+				" (%s) 0x%08llx@0x%08llx\n",
 				MTD_DEV_TYPE(dev->id->type), dev->id->num,
 				part_num, part->name, part->size,
 				part->offset);
@@ -1516,6 +1518,23 @@
 #endif /* CONFIG_CMD_MTDPARTS_SPREAD */
 
 /**
+ * The mtdparts variable tends to be long. If we need to access it
+ * before the env is relocated, then we need to use our own stack
+ * buffer.  gd->env_buf will be too small.
+ *
+ * @param buf temporary buffer pointer MTDPARTS_MAXLEN long
+ * @return mtdparts variable string, NULL if not found
+ */
+static const char *getenv_mtdparts(char *buf)
+{
+	if (gd->flags & GD_FLG_ENV_READY)
+		return getenv("mtdparts");
+	if (getenv_f("mtdparts", buf, MTDPARTS_MAXLEN) != -1)
+		return buf;
+	return NULL;
+}
+
+/**
  * Accept character string describing mtd partitions and call device_parse()
  * for each entry. Add created devices to the global devices list.
  *
@@ -1524,7 +1543,7 @@
  */
 static int parse_mtdparts(const char *const mtdparts)
 {
-	const char *p = mtdparts;
+	const char *p;
 	struct mtd_device *dev;
 	int err = 1;
 	char tmp_parts[MTDPARTS_MAXLEN];
@@ -1538,12 +1557,9 @@
 	}
 
 	/* re-read 'mtdparts' variable, mtd_devices_init may be updating env */
-	if (gd->flags & GD_FLG_ENV_READY) {
-		p = getenv("mtdparts");
-	} else {
-		p = tmp_parts;
-		getenv_f("mtdparts", tmp_parts, MTDPARTS_MAXLEN);
-	}
+	p = getenv_mtdparts(tmp_parts);
+	if (!p)
+		p = mtdparts;
 
 	if (strncmp(p, "mtdparts=", 9) != 0) {
 		printf("mtdparts variable doesn't start with 'mtdparts='\n");
@@ -1551,7 +1567,7 @@
 	}
 	p += 9;
 
-	while (p && (*p != '\0')) {
+	while (*p != '\0') {
 		err = 1;
 		if ((device_parse(p, &p, &dev) != 0) || (!dev))
 			break;
@@ -1569,12 +1585,10 @@
 		list_add_tail(&dev->link, &devices);
 		err = 0;
 	}
-	if (err == 1) {
+	if (err == 1)
 		device_delall(&devices);
-		return 1;
-	}
 
-	return 0;
+	return err;
 }
 
 /**
@@ -1688,6 +1702,7 @@
 	return 0;
 }
 
+
 /**
  * Parse and initialize global mtdids mapping and create global
  * device/partition list.
@@ -1710,22 +1725,16 @@
 		memset(last_ids, 0, MTDIDS_MAXLEN);
 		memset(last_parts, 0, MTDPARTS_MAXLEN);
 		memset(last_partition, 0, PARTITION_MAXLEN);
+#if defined(CONFIG_SYS_MTDPARTS_RUNTIME)
+		board_mtdparts_default(&mtdids_default, &mtdparts_default);
+#endif
+		use_defaults = 1;
 		initialized = 1;
 	}
 
 	/* get variables */
 	ids = getenv("mtdids");
-	/*
-	 * The mtdparts variable tends to be long. If we need to access it
-	 * before the env is relocated, then we need to use our own stack
-	 * buffer.  gd->env_buf will be too small.
-	 */
-	if (gd->flags & GD_FLG_ENV_READY) {
-		parts = getenv("mtdparts");
-	} else {
-		parts = tmp_parts;
-		getenv_f("mtdparts", tmp_parts, MTDPARTS_MAXLEN);
-	}
+	parts = getenv_mtdparts(tmp_parts);
 	current_partition = getenv("partition");
 
 	/* save it for later parsing, cannot rely on current partition pointer
@@ -1758,10 +1767,16 @@
 		return 1;
 	}
 
-	/* do no try to use defaults when mtdparts variable is not defined,
-	 * just check the length */
-	if (!parts)
-		printf("mtdparts variable not set, see 'help mtdparts'\n");
+	/* use defaults when mtdparts variable is not defined
+	 * once mtdparts is saved environment, drop use_defaults flag */
+	if (!parts) {
+		if (mtdparts_default && use_defaults) {
+			parts = mtdparts_default;
+			if (setenv("mtdparts", (char *)parts) == 0)
+				use_defaults = 0;
+		} else
+			printf("mtdparts variable not set, see 'help mtdparts'\n");
+	}
 
 	if (parts && (strlen(parts) > MTDPARTS_MAXLEN - 1)) {
 		printf("mtdparts too long (> %d)\n", MTDPARTS_MAXLEN);
@@ -1933,9 +1948,10 @@
 {
 	if (argc == 2) {
 		if (strcmp(argv[1], "default") == 0) {
-			setenv("mtdids", (char *)mtdids_default);
-			setenv("mtdparts", (char *)mtdparts_default);
+			setenv("mtdids", NULL);
+			setenv("mtdparts", NULL);
 			setenv("partition", NULL);
+			use_defaults = 1;
 
 			mtdparts_init();
 			return 0;
@@ -2009,7 +2025,7 @@
 
 		if (!strcmp(&argv[1][3], ".spread")) {
 			spread_partition(mtd, p, &next_offset);
-			debug("increased %s to %d bytes\n", p->name, p->size);
+			debug("increased %s to %llu bytes\n", p->name, p->size);
 		}
 #endif
 
diff --git a/cmd/nand.c b/cmd/nand.c
index ffdeea4..e10349a 100644
--- a/cmd/nand.c
+++ b/cmd/nand.c
@@ -306,7 +306,7 @@
 }
 
 static int raw_access(struct mtd_info *mtd, ulong addr, loff_t off,
-		      ulong count, int read)
+		      ulong count, int read, int no_verify)
 {
 	int ret = 0;
 
@@ -324,7 +324,7 @@
 			ret = mtd_read_oob(mtd, off, &ops);
 		} else {
 			ret = mtd_write_oob(mtd, off, &ops);
-			if (!ret)
+			if (!ret && !no_verify)
 				ret = nand_verify_page_oob(mtd, &ops, off);
 		}
 
@@ -546,6 +546,7 @@
 		ulong pagecount = 1;
 		int read;
 		int raw = 0;
+		int no_verify = 0;
 
 		if (argc < 4)
 			goto usage;
@@ -557,9 +558,12 @@
 
 		s = strchr(cmd, '.');
 
-		if (s && !strcmp(s, ".raw")) {
+		if (s && !strncmp(s, ".raw", 4)) {
 			raw = 1;
 
+			if (!strcmp(s, ".raw.noverify"))
+				no_verify = 1;
+
 			if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
 					MTD_DEV_TYPE_NAND,
 					nand_info[dev]->size))
@@ -633,7 +637,8 @@
 			else
 				ret = mtd_write_oob(mtd, off, &ops);
 		} else if (raw) {
-			ret = raw_access(mtd, addr, off, pagecount, read);
+			ret = raw_access(mtd, addr, off, pagecount, read,
+					 no_verify);
 		} else {
 			printf("Unknown nand command suffix '%s'.\n", s);
 			return 1;
@@ -786,7 +791,7 @@
 	"    read/write 'size' bytes starting at offset 'off'\n"
 	"    to/from memory address 'addr', skipping bad blocks.\n"
 	"nand read.raw - addr off|partition [count]\n"
-	"nand write.raw - addr off|partition [count]\n"
+	"nand write.raw[.noverify] - addr off|partition [count]\n"
 	"    Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
 #ifdef CONFIG_CMD_NAND_TRIMFFS
 	"nand write.trimffs - addr off|partition size\n"
diff --git a/cmd/sf.c b/cmd/sf.c
index 42862d9..286906c 100644
--- a/cmd/sf.c
+++ b/cmd/sf.c
@@ -88,6 +88,8 @@
 #ifdef CONFIG_DM_SPI_FLASH
 	struct udevice *new, *bus_dev;
 	int ret;
+	/* In DM mode defaults will be taken from DT */
+	speed = 0, mode = 0;
 #else
 	struct spi_flash *new;
 #endif
diff --git a/cmd/usb_mass_storage.c b/cmd/usb_mass_storage.c
index b05913a..86398fc 100644
--- a/cmd/usb_mass_storage.c
+++ b/cmd/usb_mass_storage.c
@@ -22,7 +22,7 @@
 	struct blk_desc *block_dev = &ums_dev->block_dev;
 	lbaint_t blkstart = start + ums_dev->start_sector;
 
-	return block_dev->block_read(block_dev, blkstart, blkcnt, buf);
+	return blk_dread(block_dev, blkstart, blkcnt, buf);
 }
 
 static int ums_write_sector(struct ums *ums_dev,
@@ -31,7 +31,7 @@
 	struct blk_desc *block_dev = &ums_dev->block_dev;
 	lbaint_t blkstart = start + ums_dev->start_sector;
 
-	return block_dev->block_write(block_dev, blkstart, blkcnt, buf);
+	return blk_dwrite(block_dev, blkstart, blkcnt, buf);
 }
 
 static struct ums *ums;
diff --git a/common/Kconfig b/common/Kconfig
index 8adc821..46e7173 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -197,3 +197,9 @@
 	  tstc() and getc() will use this in preference to real device input.
 	  The buffer is allocated immediately after the malloc() region is
 	  ready.
+
+config SYS_NO_FLASH
+	bool "Disable support for parallel NOR flash"
+	default n
+	help
+	  This option is used to disable support for parallel NOR flash.
diff --git a/common/Makefile b/common/Makefile
index e08cd3e..21619b3 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -26,6 +26,8 @@
 obj-$(CONFIG_DISPLAY_BOARDINFO_LATE) += board_info.o
 
 obj-$(CONFIG_CMD_BOOTM) += bootm.o bootm_os.o
+obj-$(CONFIG_CMD_BOOTZ) += bootm.o bootm_os.o
+obj-$(CONFIG_CMD_BOOTI) += bootm.o bootm_os.o
 
 # environment
 obj-y += env_attr.o
diff --git a/common/board_f.c b/common/board_f.c
index d405b5b..da381db 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -54,6 +54,8 @@
 #include <asm/sections.h>
 #if defined(CONFIG_X86) || defined(CONFIG_ARC)
 #include <asm/init_helpers.h>
+#endif
+#if defined(CONFIG_X86) || defined(CONFIG_ARC) || defined(CONFIG_XTENSA)
 #include <asm/relocate.h>
 #endif
 #ifdef CONFIG_SANDBOX
@@ -117,10 +119,11 @@
 # if defined(CONFIG_HW_WATCHDOG) && (defined(CONFIG_BLACKFIN) || \
 	defined(CONFIG_M68K) || defined(CONFIG_MICROBLAZE) || \
 	defined(CONFIG_SH) || defined(CONFIG_AT91SAM9_WATCHDOG) || \
+	defined(CONFIG_DESIGNWARE_WATCHDOG) || \
 	defined(CONFIG_IMX_WATCHDOG))
 	hw_watchdog_init();
-# endif
 	puts("       Watchdog enabled\n");
+# endif
 	WATCHDOG_RESET();
 
 	return 0;
@@ -270,7 +273,8 @@
 	gd->mon_len = (ulong)&__bss_end - (ulong)_start;
 #elif defined(CONFIG_SANDBOX) || defined(CONFIG_EFI_APP)
 	gd->mon_len = (ulong)&_end - (ulong)_init;
-#elif defined(CONFIG_BLACKFIN) || defined(CONFIG_NIOS2)
+#elif defined(CONFIG_BLACKFIN) || defined(CONFIG_NIOS2) || \
+	defined(CONFIG_XTENSA)
 	gd->mon_len = CONFIG_SYS_MONITOR_LEN;
 #elif defined(CONFIG_NDS32)
 	gd->mon_len = (ulong)(&__bss_end) - (ulong)(&_start);
@@ -339,7 +343,7 @@
 	 * Record secure memory location. Need recalcuate if memory splits
 	 * into banks, or the ram base is not zero.
 	 */
-	gd->secure_ram = gd->ram_size;
+	gd->arch.secure_ram = gd->ram_size;
 #endif
 	/*
 	 * Subtract specified amount of memory to hide so that it won't
@@ -432,6 +436,15 @@
 	gd->arch.tlb_addr = gd->relocaddr;
 	debug("TLB table from %08lx to %08lx\n", gd->arch.tlb_addr,
 	      gd->arch.tlb_addr + gd->arch.tlb_size);
+
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+	/*
+	 * Record allocated tlb_addr in case gd->tlb_addr to be overwritten
+	 * with location within secure ram.
+	 */
+	gd->arch.tlb_allocated = gd->arch.tlb_addr;
+#endif
+
 	return 0;
 }
 #endif
@@ -961,7 +974,7 @@
 	 *  - board info struct
 	 */
 	setup_dest_addr,
-#if defined(CONFIG_BLACKFIN)
+#if defined(CONFIG_BLACKFIN) || defined(CONFIG_XTENSA)
 	/* Blackfin u-boot monitor should be on top of the ram */
 	reserve_uboot,
 #endif
@@ -993,7 +1006,7 @@
 # endif
 #endif /* CONFIG_DM_VIDEO */
 	reserve_trace,
-#if !defined(CONFIG_BLACKFIN)
+#if !defined(CONFIG_BLACKFIN) && !defined(CONFIG_XTENSA)
 	reserve_uboot,
 #endif
 #ifndef CONFIG_SPL_BUILD
@@ -1026,6 +1039,9 @@
 	clear_bss,
 	do_elf_reloc_fixups,
 #endif
+#if defined(CONFIG_XTENSA)
+	clear_bss,
+#endif
 #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
 	jump_to_copy,
 #endif
diff --git a/common/bootm.c b/common/bootm.c
index 2431019..a4d22a6 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -41,6 +41,8 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+bootm_headers_t images;		/* pointers to os/initrd/fdt images */
+
 static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
 				   char * const argv[], bootm_headers_t *images,
 				   ulong *os_data, ulong *os_len);
@@ -635,10 +637,6 @@
 			goto err;
 		else if (ret == BOOTM_ERR_OVERLAP)
 			ret = 0;
-#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
-		if (images->os.os == IH_OS_LINUX)
-			fixup_silent_linux();
-#endif
 	}
 
 	/* Relocate the ramdisk */
@@ -678,13 +676,19 @@
 		return 1;
 	}
 
+
 	/* Call various other states that are not generally used */
 	if (!ret && (states & BOOTM_STATE_OS_CMDLINE))
 		ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images);
 	if (!ret && (states & BOOTM_STATE_OS_BD_T))
 		ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images);
-	if (!ret && (states & BOOTM_STATE_OS_PREP))
+	if (!ret && (states & BOOTM_STATE_OS_PREP)) {
+#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
+		if (images->os.os == IH_OS_LINUX)
+			fixup_silent_linux();
+#endif
 		ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images);
+	}
 
 #ifdef CONFIG_TRACE
 	/* Pretend to run the OS, then run a user command */
diff --git a/common/bootm_os.c b/common/bootm_os.c
index 9ec84bd..e3f5a46 100644
--- a/common/bootm_os.c
+++ b/common/bootm_os.c
@@ -481,6 +481,7 @@
 
 	/* Stand-alone may return when 'autostart' is 'no' */
 	if (images->os.type == IH_TYPE_STANDALONE ||
+	    IS_ENABLED(CONFIG_SANDBOX) ||
 	    state == BOOTM_STATE_OS_FAKE_GO) /* We expect to return */
 		return 0;
 	bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED);
diff --git a/common/cli_readline.c b/common/cli_readline.c
index c1476e4..ecded11 100644
--- a/common/cli_readline.c
+++ b/common/cli_readline.c
@@ -283,46 +283,82 @@
 		 * handle standard linux xterm esc sequences for arrow key, etc.
 		 */
 		if (esc_len != 0) {
+			enum { ESC_REJECT, ESC_SAVE, ESC_CONVERTED } act = ESC_REJECT;
+
 			if (esc_len == 1) {
-				if (ichar == '[') {
-					esc_save[esc_len] = ichar;
-					esc_len = 2;
-				} else {
-					cread_add_str(esc_save, esc_len,
-						      insert, &num, &eol_num,
-						      buf, *len);
-					esc_len = 0;
+				if (ichar == '[' || ichar == 'O')
+					act = ESC_SAVE;
+			} else if (esc_len == 2) {
+				switch (ichar) {
+				case 'D':	/* <- key */
+					ichar = CTL_CH('b');
+					act = ESC_CONVERTED;
+					break;	/* pass off to ^B handler */
+				case 'C':	/* -> key */
+					ichar = CTL_CH('f');
+					act = ESC_CONVERTED;
+					break;	/* pass off to ^F handler */
+				case 'H':	/* Home key */
+					ichar = CTL_CH('a');
+					act = ESC_CONVERTED;
+					break;	/* pass off to ^A handler */
+				case 'F':	/* End key */
+					ichar = CTL_CH('e');
+					act = ESC_CONVERTED;
+					break;	/* pass off to ^E handler */
+				case 'A':	/* up arrow */
+					ichar = CTL_CH('p');
+					act = ESC_CONVERTED;
+					break;	/* pass off to ^P handler */
+				case 'B':	/* down arrow */
+					ichar = CTL_CH('n');
+					act = ESC_CONVERTED;
+					break;	/* pass off to ^N handler */
+				case '1':
+				case '3':
+				case '4':
+				case '7':
+				case '8':
+					if (esc_save[1] == '[') {
+						/* see if next character is ~ */
+						act = ESC_SAVE;
+					}
+					break;
 				}
-				continue;
+			} else if (esc_len == 3) {
+				if (ichar == '~') {
+					switch (esc_save[2]) {
+					case '3':	/* Delete key */
+						ichar = CTL_CH('d');
+						act = ESC_CONVERTED;
+						break;	/* pass to ^D handler */
+					case '1':	/* Home key */
+					case '7':
+						ichar = CTL_CH('a');
+						act = ESC_CONVERTED;
+						break;	/* pass to ^A handler */
+					case '4':	/* End key */
+					case '8':
+						ichar = CTL_CH('e');
+						act = ESC_CONVERTED;
+						break;	/* pass to ^E handler */
+					}
+				}
 			}
 
-			switch (ichar) {
-			case 'D':	/* <- key */
-				ichar = CTL_CH('b');
-				esc_len = 0;
-				break;
-			case 'C':	/* -> key */
-				ichar = CTL_CH('f');
-				esc_len = 0;
-				break;	/* pass off to ^F handler */
-			case 'H':	/* Home key */
-				ichar = CTL_CH('a');
-				esc_len = 0;
-				break;	/* pass off to ^A handler */
-			case 'A':	/* up arrow */
-				ichar = CTL_CH('p');
-				esc_len = 0;
-				break;	/* pass off to ^P handler */
-			case 'B':	/* down arrow */
-				ichar = CTL_CH('n');
-				esc_len = 0;
-				break;	/* pass off to ^N handler */
-			default:
+			switch (act) {
+			case ESC_SAVE:
+				esc_save[esc_len++] = ichar;
+				continue;
+			case ESC_REJECT:
 				esc_save[esc_len++] = ichar;
 				cread_add_str(esc_save, esc_len, insert,
 					      &num, &eol_num, buf, *len);
 				esc_len = 0;
 				continue;
+			case ESC_CONVERTED:
+				esc_len = 0;
+				break;
 			}
 		}
 
diff --git a/common/env_common.c b/common/env_common.c
index 13db7dc..560cad0 100644
--- a/common/env_common.c
+++ b/common/env_common.c
@@ -145,7 +145,7 @@
  * env_aes_cbc_get_key() - Get AES-128-CBC key for the environment
  *
  * This function shall return 16-byte array containing AES-128 key used
- * to encrypt and decrypt the environment. This function must be overriden
+ * to encrypt and decrypt the environment. This function must be overridden
  * by the implementer as otherwise the environment encryption will not
  * work.
  */
diff --git a/common/env_nand.c b/common/env_nand.c
index fc99a5e..2e28171 100644
--- a/common/env_nand.c
+++ b/common/env_nand.c
@@ -163,6 +163,9 @@
 {
 	int ret = 0;
 
+	if (!nand_info[0])
+		return 1;
+
 	printf("Erasing %s...\n", location->name);
 	if (nand_erase_opts(nand_info[0], &location->erase_opts))
 		return 1;
@@ -247,10 +250,10 @@
 	size_t blocksize, len;
 	u_char *char_ptr;
 
-	blocksize = nand_info[0]->erasesize;
-	if (!blocksize)
+	if (!nand_info[0])
 		return 1;
 
+	blocksize = nand_info[0]->erasesize;
 	len = min(blocksize, (size_t)CONFIG_ENV_SIZE);
 
 	while (amount_loaded < CONFIG_ENV_SIZE && offset < end) {
@@ -387,12 +390,12 @@
 	ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
 
 #if defined(CONFIG_ENV_OFFSET_OOB)
-	ret = get_nand_env_oob(nand_info[0], &nand_env_oob_offset);
 	/*
 	 * If unable to read environment offset from NAND OOB then fall through
 	 * to the normal environment reading code below
 	 */
-	if (!ret) {
+	if (nand_info[0] && !get_nand_env_oob(nand_info[0],
+					      &nand_env_oob_offset)) {
 		printf("Found Environment offset in OOB..\n");
 	} else {
 		set_default_env("!no env offset in OOB");
diff --git a/common/env_sf.c b/common/env_sf.c
index 273098c..c53200f 100644
--- a/common/env_sf.c
+++ b/common/env_sf.c
@@ -55,9 +55,9 @@
 #ifdef CONFIG_DM_SPI_FLASH
 	struct udevice *new;
 
+	/* speed and mode will be read from DT */
 	ret = spi_flash_probe_bus_cs(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
-				     CONFIG_ENV_SPI_MAX_HZ,
-				     CONFIG_ENV_SPI_MODE, &new);
+				     0, 0, &new);
 	if (ret) {
 		set_default_env("!spi_flash_probe_bus_cs() failed");
 		return 1;
@@ -245,9 +245,9 @@
 #ifdef CONFIG_DM_SPI_FLASH
 	struct udevice *new;
 
+	/* speed and mode will be read from DT */
 	ret = spi_flash_probe_bus_cs(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
-				     CONFIG_ENV_SPI_MAX_HZ,
-				     CONFIG_ENV_SPI_MODE, &new);
+				     0, 0, &new);
 	if (ret) {
 		set_default_env("!spi_flash_probe_bus_cs() failed");
 		return 1;
diff --git a/common/fb_mmc.c b/common/fb_mmc.c
index c739651..8d0524d 100644
--- a/common/fb_mmc.c
+++ b/common/fb_mmc.c
@@ -191,7 +191,7 @@
 	printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment\n",
 	       blks_start, blks_start + blks_size);
 
-	blks = dev_desc->block_erase(dev_desc, blks_start, blks_size);
+	blks = blk_derase(dev_desc, blks_start, blks_size);
 	if (blks != blks_size) {
 		error("failed erasing from device %d", dev_desc->devnum);
 		fastboot_fail("failed erasing from device");
diff --git a/common/fdt_support.c b/common/fdt_support.c
index 5d8eb12..2020586 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -997,8 +997,8 @@
 struct of_bus {
 	const char	*name;
 	const char	*addresses;
-	int		(*match)(void *blob, int parentoffset);
-	void		(*count_cells)(void *blob, int parentoffset,
+	int		(*match)(const void *blob, int parentoffset);
+	void		(*count_cells)(const void *blob, int parentoffset,
 				int *addrc, int *sizec);
 	u64		(*map)(fdt32_t *addr, const fdt32_t *range,
 				int na, int ns, int pna);
@@ -1006,7 +1006,7 @@
 };
 
 /* Default translator (generic bus) */
-void of_bus_default_count_cells(void *blob, int parentoffset,
+void of_bus_default_count_cells(const void *blob, int parentoffset,
 					int *addrc, int *sizec)
 {
 	const fdt32_t *prop;
@@ -1055,7 +1055,7 @@
 #ifdef CONFIG_OF_ISA_BUS
 
 /* ISA bus translator */
-static int of_bus_isa_match(void *blob, int parentoffset)
+static int of_bus_isa_match(const void *blob, int parentoffset)
 {
 	const char *name;
 
@@ -1066,7 +1066,7 @@
 	return !strcmp(name, "isa");
 }
 
-static void of_bus_isa_count_cells(void *blob, int parentoffset,
+static void of_bus_isa_count_cells(const void *blob, int parentoffset,
 				   int *addrc, int *sizec)
 {
 	if (addrc)
@@ -1126,7 +1126,7 @@
 	},
 };
 
-static struct of_bus *of_match_bus(void *blob, int parentoffset)
+static struct of_bus *of_match_bus(const void *blob, int parentoffset)
 {
 	struct of_bus *bus;
 
@@ -1148,7 +1148,7 @@
 	return NULL;
 }
 
-static int of_translate_one(void * blob, int parent, struct of_bus *bus,
+static int of_translate_one(const void *blob, int parent, struct of_bus *bus,
 			    struct of_bus *pbus, fdt32_t *addr,
 			    int na, int ns, int pna, const char *rprop)
 {
@@ -1211,8 +1211,8 @@
  * that can be mapped to a cpu physical address). This is not really specified
  * that way, but this is traditionally the way IBM at least do things
  */
-static u64 __of_translate_address(void *blob, int node_offset, const fdt32_t *in_addr,
-				  const char *rprop)
+static u64 __of_translate_address(const void *blob, int node_offset,
+				  const fdt32_t *in_addr, const char *rprop)
 {
 	int parent;
 	struct of_bus *bus, *pbus;
@@ -1284,7 +1284,8 @@
 	return result;
 }
 
-u64 fdt_translate_address(void *blob, int node_offset, const fdt32_t *in_addr)
+u64 fdt_translate_address(const void *blob, int node_offset,
+			  const fdt32_t *in_addr)
 {
 	return __of_translate_address(blob, node_offset, in_addr, "ranges");
 }
diff --git a/common/image-fdt.c b/common/image-fdt.c
index 6cac7db..d6ee225 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -458,11 +458,6 @@
 	return 1;
 }
 
-__weak int arch_fixup_fdt(void *blob)
-{
-	return 0;
-}
-
 int image_setup_libfdt(bootm_headers_t *images, void *blob,
 		       int of_size, struct lmb *lmb)
 {
@@ -479,10 +474,12 @@
 		printf("ERROR: /chosen node create failed\n");
 		goto err;
 	}
+#ifdef CONFIG_ARCH_FIXUP_FDT
 	if (arch_fixup_fdt(blob) < 0) {
 		printf("ERROR: arch-specific fdt fixup failed\n");
 		goto err;
 	}
+#endif
 	if (IMAGE_OF_BOARD_SETUP) {
 		fdt_ret = ft_board_setup(blob, gd->bd);
 		if (fdt_ret) {
diff --git a/common/image-fit.c b/common/image-fit.c
index 6f920da..d8d4e95 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -11,9 +11,9 @@
 
 #ifdef USE_HOSTCC
 #include "mkimage.h"
-#include <image.h>
 #include <time.h>
 #else
+#include <linux/compiler.h>
 #include <common.h>
 #include <errno.h>
 #include <mapmem.h>
@@ -21,6 +21,7 @@
 DECLARE_GLOBAL_DATA_PTR;
 #endif /* !USE_HOSTCC*/
 
+#include <image.h>
 #include <bootstage.h>
 #include <u-boot/crc.h>
 #include <u-boot/md5.h>
@@ -1507,6 +1508,12 @@
 
 static int fit_image_select(const void *fit, int rd_noffset, int verify)
 {
+#if !defined(USE_HOSTCC) && defined(CONFIG_FIT_IMAGE_POST_PROCESS)
+	const void *data;
+	size_t size;
+	int ret;
+#endif
+
 	fit_image_print(fit, rd_noffset, "   ");
 
 	if (verify) {
@@ -1518,6 +1525,23 @@
 		puts("OK\n");
 	}
 
+#if !defined(USE_HOSTCC) && defined(CONFIG_FIT_IMAGE_POST_PROCESS)
+	ret = fit_image_get_data(fit, rd_noffset, &data, &size);
+	if (ret)
+		return ret;
+
+	/* perform any post-processing on the image data */
+	board_fit_image_post_process((void **)&data, &size);
+
+	/*
+	 * update U-Boot's understanding of the "data" property start address
+	 * and size according to the performed post-processing
+	 */
+	ret = fdt_setprop((void *)fit, rd_noffset, FIT_DATA_PROP, data, size);
+	if (ret)
+		return ret;
+#endif
+
 	return 0;
 }
 
@@ -1684,12 +1708,13 @@
 
 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL);
 	type_ok = fit_image_check_type(fit, noffset, image_type) ||
-		(image_type == IH_TYPE_KERNEL &&
-			fit_image_check_type(fit, noffset,
-					     IH_TYPE_KERNEL_NOLOAD));
+		  fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE) ||
+		  (image_type == IH_TYPE_KERNEL &&
+		   fit_image_check_type(fit, noffset, IH_TYPE_KERNEL_NOLOAD));
 
 	os_ok = image_type == IH_TYPE_FLATDT || IH_TYPE_FPGA ||
 		fit_image_check_os(fit, noffset, IH_OS_LINUX) ||
+		fit_image_check_os(fit, noffset, IH_OS_U_BOOT) ||
 		fit_image_check_os(fit, noffset, IH_OS_OPENRTOS);
 
 	/*
diff --git a/common/image.c b/common/image.c
index 0be09e5..7ad04ca 100644
--- a/common/image.c
+++ b/common/image.c
@@ -69,7 +69,7 @@
 #endif
 
 static const table_entry_t uimage_arch[] = {
-	{	IH_ARCH_INVALID,	NULL,		"Invalid ARCH",	},
+	{	IH_ARCH_INVALID,	"invalid",	"Invalid ARCH",	},
 	{	IH_ARCH_ALPHA,		"alpha",	"Alpha",	},
 	{	IH_ARCH_ARM,		"arm",		"ARM",		},
 	{	IH_ARCH_I386,		"x86",		"Intel x86",	},
@@ -93,11 +93,12 @@
 	{	IH_ARCH_ARM64,		"arm64",	"AArch64",	},
 	{	IH_ARCH_ARC,		"arc",		"ARC",		},
 	{	IH_ARCH_X86_64,		"x86_64",	"AMD x86_64",	},
+	{	IH_ARCH_XTENSA,		"xtensa",	"Xtensa",	},
 	{	-1,			"",		"",		},
 };
 
 static const table_entry_t uimage_os[] = {
-	{	IH_OS_INVALID,	NULL,		"Invalid OS",		},
+	{	IH_OS_INVALID,	"invalid",	"Invalid OS",		},
 	{	IH_OS_LINUX,	"linux",	"Linux",		},
 #if defined(CONFIG_LYNXKDI) || defined(USE_HOSTCC)
 	{	IH_OS_LYNXOS,	"lynxos",	"LynxOS",		},
@@ -144,7 +145,7 @@
 	{	IH_TYPE_KERNEL_NOLOAD, "kernel_noload",  "Kernel Image (no loading done)", },
 	{	IH_TYPE_KWBIMAGE,   "kwbimage",   "Kirkwood Boot Image",},
 	{	IH_TYPE_IMXIMAGE,   "imximage",   "Freescale i.MX Boot Image",},
-	{	IH_TYPE_INVALID,    NULL,	  "Invalid Image",	},
+	{	IH_TYPE_INVALID,    "invalid",	  "Invalid Image",	},
 	{	IH_TYPE_MULTI,	    "multi",	  "Multi-File Image",	},
 	{	IH_TYPE_OMAPIMAGE,  "omapimage",  "TI OMAP SPL With GP CH",},
 	{	IH_TYPE_PBLIMAGE,   "pblimage",   "Freescale PBL Boot Image",},
@@ -176,6 +177,19 @@
 	{	-1,		"",		"",			},
 };
 
+struct table_info {
+	const char *desc;
+	int count;
+	const table_entry_t *table;
+};
+
+static const struct table_info table_info[IH_COUNT] = {
+	{ "architecture", IH_ARCH_COUNT, uimage_arch },
+	{ "compression", IH_COMP_COUNT, uimage_comp },
+	{ "operating system", IH_OS_COUNT, uimage_os },
+	{ "image type", IH_TYPE_COUNT, uimage_type },
+};
+
 /*****************************************************************************/
 /* Legacy format routines */
 /*****************************************************************************/
@@ -570,6 +584,74 @@
 	return NULL;
 }
 
+static const char *unknown_msg(enum ih_category category)
+{
+	static char msg[30];
+
+	strcpy(msg, "Unknown ");
+	strcat(msg, table_info[category].desc);
+
+	return msg;
+}
+
+/**
+ * get_cat_table_entry_name - translate entry id to long name
+ * @category: category to look up (enum ih_category)
+ * @id: entry id to be translated
+ *
+ * This will scan the translation table trying to find the entry that matches
+ * the given id.
+ *
+ * @retur long entry name if translation succeeds; error string on failure
+ */
+const char *genimg_get_cat_name(enum ih_category category, uint id)
+{
+	const table_entry_t *entry;
+
+	entry = get_table_entry(table_info[category].table, id);
+	if (!entry)
+		return unknown_msg(category);
+#if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC)
+	return entry->lname;
+#else
+	return entry->lname + gd->reloc_off;
+#endif
+}
+
+/**
+ * get_cat_table_entry_short_name - translate entry id to short name
+ * @category: category to look up (enum ih_category)
+ * @id: entry id to be translated
+ *
+ * This will scan the translation table trying to find the entry that matches
+ * the given id.
+ *
+ * @retur short entry name if translation succeeds; error string on failure
+ */
+const char *genimg_get_cat_short_name(enum ih_category category, uint id)
+{
+	const table_entry_t *entry;
+
+	entry = get_table_entry(table_info[category].table, id);
+	if (!entry)
+		return unknown_msg(category);
+#if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC)
+	return entry->sname;
+#else
+	return entry->sname + gd->reloc_off;
+#endif
+}
+
+int genimg_get_cat_count(enum ih_category category)
+{
+	return table_info[category].count;
+}
+
+const char *genimg_get_cat_desc(enum ih_category category)
+{
+	return table_info[category].desc;
+}
+
 /**
  * get_table_entry_name - translate entry id to long name
  * @table: pointer to a translation table for entries of a specific type
diff --git a/common/miiphyutil.c b/common/miiphyutil.c
index 7e41957..08aa854 100644
--- a/common/miiphyutil.c
+++ b/common/miiphyutil.c
@@ -65,79 +65,6 @@
 	current_mii = NULL;
 }
 
-static int legacy_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
-{
-	unsigned short val;
-	int ret;
-	struct legacy_mii_dev *ldev = bus->priv;
-
-	ret = ldev->read(bus->name, addr, reg, &val);
-
-	return ret ? -1 : (int)val;
-}
-
-static int legacy_miiphy_write(struct mii_dev *bus, int addr, int devad,
-				int reg, u16 val)
-{
-	struct legacy_mii_dev *ldev = bus->priv;
-
-	return ldev->write(bus->name, addr, reg, val);
-}
-
-/*****************************************************************************
- *
- * Register read and write MII access routines for the device <name>.
- * This API is now deprecated. Please use mdio_alloc and mdio_register, instead.
- */
-void miiphy_register(const char *name,
-		      int (*read)(const char *devname, unsigned char addr,
-				   unsigned char reg, unsigned short *value),
-		      int (*write)(const char *devname, unsigned char addr,
-				    unsigned char reg, unsigned short value))
-{
-	struct mii_dev *new_dev;
-	struct legacy_mii_dev *ldev;
-
-	BUG_ON(strlen(name) >= MDIO_NAME_LEN);
-
-	/* check if we have unique name */
-	new_dev = miiphy_get_dev_by_name(name);
-	if (new_dev) {
-		printf("miiphy_register: non unique device name '%s'\n", name);
-		return;
-	}
-
-	/* allocate memory */
-	new_dev = mdio_alloc();
-	ldev = malloc(sizeof(*ldev));
-
-	if (new_dev == NULL || ldev == NULL) {
-		printf("miiphy_register: cannot allocate memory for '%s'\n",
-			name);
-		free(ldev);
-		mdio_free(new_dev);
-		return;
-	}
-
-	/* initalize mii_dev struct fields */
-	new_dev->read = legacy_miiphy_read;
-	new_dev->write = legacy_miiphy_write;
-	strncpy(new_dev->name, name, MDIO_NAME_LEN);
-	new_dev->name[MDIO_NAME_LEN - 1] = 0;
-	ldev->read = read;
-	ldev->write = write;
-	new_dev->priv = ldev;
-
-	debug("miiphy_register: added '%s', read=0x%08lx, write=0x%08lx\n",
-	       new_dev->name, ldev->read, ldev->write);
-
-	/* add it to the list */
-	list_add_tail(&new_dev->link, &mii_devs);
-
-	if (!current_mii)
-		current_mii = new_dev;
-}
-
 struct mii_dev *mdio_alloc(void)
 {
 	struct mii_dev *bus;
diff --git a/common/spl/Makefile b/common/spl/Makefile
index 2e0f695..b15f0f6 100644
--- a/common/spl/Makefile
+++ b/common/spl/Makefile
@@ -13,8 +13,11 @@
 obj-$(CONFIG_SPL_LOAD_FIT) += spl_fit.o
 obj-$(CONFIG_SPL_NOR_SUPPORT) += spl_nor.o
 obj-$(CONFIG_SPL_YMODEM_SUPPORT) += spl_ymodem.o
+ifndef CONFIG_SPL_UBI
 obj-$(CONFIG_SPL_NAND_SUPPORT) += spl_nand.o
 obj-$(CONFIG_SPL_ONENAND_SUPPORT) += spl_onenand.o
+endif
+obj-$(CONFIG_SPL_UBI) += spl_ubi.o
 obj-$(CONFIG_SPL_NET_SUPPORT) += spl_net.o
 obj-$(CONFIG_SPL_MMC_SUPPORT) += spl_mmc.o
 obj-$(CONFIG_SPL_USB_SUPPORT) += spl_usb.o
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 840910a..b7ec333 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -13,7 +13,6 @@
 #include <nand.h>
 #include <fat.h>
 #include <version.h>
-#include <i2c.h>
 #include <image.h>
 #include <malloc.h>
 #include <dm/root.h>
@@ -57,6 +56,15 @@
 	puts("SPL: Direct Linux boot not active!\n");
 	return 1;
 }
+
+/*
+ * Weak default function for arch specific zImage check. Return zero
+ * and fill start and end address if image is recognized.
+ */
+int __weak bootz_setup(ulong image, ulong *start, ulong *end)
+{
+	 return 1;
+}
 #endif
 
 /*
@@ -125,6 +133,20 @@
 		/* Signature not found, proceed to other boot methods. */
 		return -EINVAL;
 #else
+#ifdef CONFIG_SPL_OS_BOOT
+		ulong start, end;
+
+		if (!bootz_setup((ulong)header, &start, &end)) {
+			spl_image.name = "Linux";
+			spl_image.os = IH_OS_LINUX;
+			spl_image.load_addr = CONFIG_SYS_LOAD_ADDR;
+			spl_image.entry_point = CONFIG_SYS_LOAD_ADDR;
+			spl_image.size = end - start;
+			debug("spl: payload zImage, load addr: 0x%x size: %d\n",
+			      spl_image.load_addr, spl_image.size);
+			return 0;
+		}
+#endif
 		/* Signature not found - assume u-boot.bin */
 		debug("mkimage signature not found - ih_magic = %x\n",
 			header->ih_magic);
@@ -203,7 +225,7 @@
 	gd->malloc_limit = CONFIG_SYS_MALLOC_F_LEN;
 	gd->malloc_ptr = 0;
 #endif
-	if (CONFIG_IS_ENABLED(OF_CONTROL)) {
+	if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
 		ret = fdtdec_setup();
 		if (ret) {
 			debug("fdtdec_setup() returned error %d\n", ret);
@@ -211,7 +233,8 @@
 		}
 	}
 	if (IS_ENABLED(CONFIG_SPL_DM)) {
-		ret = dm_init_and_scan(true);
+		/* With CONFIG_OF_PLATDATA, bring in all devices */
+		ret = dm_init_and_scan(!CONFIG_IS_ENABLED(OF_PLATDATA));
 		if (ret) {
 			debug("dm_init_and_scan() returned error %d\n", ret);
 			return ret;
@@ -270,7 +293,7 @@
 #ifdef CONFIG_SPL_YMODEM_SUPPORT
 	{ BOOT_DEVICE_UART, "UART" },
 #endif
-#ifdef CONFIG_SPL_SPI_SUPPORT
+#if defined(CONFIG_SPL_SPI_SUPPORT) || defined(CONFIG_SPL_SPI_FLASH_SUPPORT)
 	{ BOOT_DEVICE_SPI, "SPI" },
 #endif
 #ifdef CONFIG_SPL_ETH_SUPPORT
@@ -330,6 +353,11 @@
 	case BOOT_DEVICE_MMC2_2:
 		return spl_mmc_load_image(boot_device);
 #endif
+#ifdef CONFIG_SPL_UBI
+	case BOOT_DEVICE_NAND:
+	case BOOT_DEVICE_ONENAND:
+		return spl_ubi_load_image(boot_device);
+#else
 #ifdef CONFIG_SPL_NAND_SUPPORT
 	case BOOT_DEVICE_NAND:
 		return spl_nand_load_image();
@@ -338,6 +366,7 @@
 	case BOOT_DEVICE_ONENAND:
 		return spl_onenand_load_image();
 #endif
+#endif
 #ifdef CONFIG_SPL_NOR_SUPPORT
 	case BOOT_DEVICE_NOR:
 		return spl_nor_load_image();
@@ -346,7 +375,7 @@
 	case BOOT_DEVICE_UART:
 		return spl_ymodem_load_image();
 #endif
-#ifdef CONFIG_SPL_SPI_SUPPORT
+#if defined(CONFIG_SPL_SPI_SUPPORT) || defined(CONFIG_SPL_SPI_FLASH_SUPPORT)
 	case BOOT_DEVICE_SPI:
 		return spl_spi_load_image();
 #endif
diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c
index db67618..73d33f5 100644
--- a/common/spl/spl_fat.c
+++ b/common/spl/spl_fat.c
@@ -88,7 +88,8 @@
 		if (err)
 			goto end;
 
-		err = file_fat_read(filename, (u8 *)spl_image.load_addr, 0);
+		err = file_fat_read(filename,
+				    (u8 *)(uintptr_t)spl_image.load_addr, 0);
 	}
 
 end:
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 9874708..be86072 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -115,8 +115,10 @@
 static int get_aligned_image_size(struct spl_load_info *info, int data_size,
 				  int offset)
 {
+	data_size = data_size + get_aligned_image_overhead(info, offset);
+
 	if (info->filename)
-		return data_size + get_aligned_image_overhead(info, offset);
+		return data_size;
 
 	return (data_size + info->bl_len - 1) / info->bl_len;
 }
@@ -132,7 +134,7 @@
 	int data_offset, data_size;
 	int base_offset, align_len = ARCH_DMA_MINALIGN - 1;
 	int src_sector;
-	void *dst;
+	void *dst, *src;
 
 	/*
 	 * Figure out where the external images start. This is the base for the
@@ -206,8 +208,13 @@
 		return -EIO;
 	debug("image: dst=%p, data_offset=%x, size=%x\n", dst, data_offset,
 	      data_size);
-	memcpy(dst, dst + get_aligned_image_overhead(info, data_offset),
-	       data_size);
+	src = dst + get_aligned_image_overhead(info, data_offset);
+
+#ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS
+	board_fit_image_post_process((void **)&src, (size_t *)&data_size);
+#endif
+
+	memcpy(dst, src, data_size);
 
 	/* Figure out which device tree the board wants to use */
 	fdt_len = spl_fit_select_fdt(fit, images, &fdt_offset);
@@ -236,8 +243,14 @@
 	 */
 	debug("fdt: dst=%p, data_offset=%x, size=%x\n", dst, fdt_offset,
 	      fdt_len);
-	memcpy(load_ptr + data_size,
-	       dst + get_aligned_image_overhead(info, fdt_offset), fdt_len);
+	src = dst + get_aligned_image_overhead(info, fdt_offset);
+	dst = load_ptr + data_size;
+
+#ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS
+	board_fit_image_post_process((void **)&src, (size_t *)&fdt_len);
+#endif
+
+	memcpy(dst, src, fdt_len);
 
 	return 0;
 }
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index c44f1b5..7c7f329 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -155,7 +155,7 @@
 	disk_partition_t info;
 	int err;
 
-	err = part_get_info(&mmc->block_dev, partition, &info);
+	err = part_get_info(mmc_get_blk_desc(mmc), partition, &info);
 	if (err) {
 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
 		puts("spl: partition error\n");
@@ -184,7 +184,7 @@
 	unsigned long count;
 	int ret;
 
-	count = mmc->block_dev.block_read(&mmc->block_dev,
+	count = blk_dread(mmc_get_blk_desc(mmc),
 		CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR,
 		CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS,
 		(void *) CONFIG_SYS_SPL_ARGS_ADDR);
@@ -225,13 +225,13 @@
 
 #ifdef CONFIG_SPL_FAT_SUPPORT
 	if (!spl_start_uboot()) {
-		err = spl_load_image_fat_os(&mmc->block_dev,
+		err = spl_load_image_fat_os(mmc_get_blk_desc(mmc),
 			CONFIG_SYS_MMCSD_FS_BOOT_PARTITION);
 		if (!err)
 			return err;
 	}
 #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
-	err = spl_load_image_fat(&mmc->block_dev,
+	err = spl_load_image_fat(mmc_get_blk_desc(mmc),
 				 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
 				 CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
 	if (!err)
diff --git a/common/spl/spl_nor.c b/common/spl/spl_nor.c
index da2422f..8ea874c 100644
--- a/common/spl/spl_nor.c
+++ b/common/spl/spl_nor.c
@@ -40,11 +40,11 @@
 
 			/*
 			 * Copy DT blob (fdt) to SDRAM. Passing pointer to
-			 * flash doesn't work (16 KiB should be enough for DT)
+			 * flash doesn't work
 			 */
 			memcpy((void *)CONFIG_SYS_SPL_ARGS_ADDR,
 			       (void *)(CONFIG_SYS_FDT_BASE),
-			       (16 << 10));
+			       CONFIG_SYS_FDT_SIZE);
 
 			return 0;
 		} else {
diff --git a/common/spl/spl_ubi.c b/common/spl/spl_ubi.c
new file mode 100644
index 0000000..f97e1ef
--- /dev/null
+++ b/common/spl/spl_ubi.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016
+ * Ladislav Michl <ladis@linux-mips.org>
+ *
+ * SPDX-License-Identifier: GPL 2.0+ BSD-3-Clause
+ */
+
+#include <common.h>
+#include <config.h>
+#include <nand.h>
+#include <onenand_uboot.h>
+#include <ubispl.h>
+#include <spl.h>
+
+int spl_ubi_load_image(u32 boot_device)
+{
+	struct image_header *header;
+	struct ubispl_info info;
+	struct ubispl_load volumes[2];
+	int ret = 1;
+
+	switch (boot_device) {
+#ifdef CONFIG_SPL_NAND_SUPPORT
+	case BOOT_DEVICE_NAND:
+		nand_init();
+		info.read = nand_spl_read_block;
+		info.peb_size = CONFIG_SYS_NAND_BLOCK_SIZE;
+		break;
+#endif
+#ifdef CONFIG_SPL_ONENAND_SUPPORT
+	case BOOT_DEVICE_ONENAND:
+		info.read = onenand_spl_read_block;
+		info.peb_size = CONFIG_SYS_ONENAND_BLOCK_SIZE;
+		break;
+#endif
+	default:
+		goto out;
+	}
+	info.ubi = (struct ubi_scan_info *)CONFIG_SPL_UBI_INFO_ADDR;
+	info.fastmap = 1;
+
+	info.peb_offset = CONFIG_SPL_UBI_PEB_OFFSET;
+	info.vid_offset = CONFIG_SPL_UBI_VID_OFFSET;
+	info.leb_start = CONFIG_SPL_UBI_LEB_START;
+	info.peb_count = CONFIG_SPL_UBI_MAX_PEBS - info.peb_offset;
+
+#ifdef CONFIG_SPL_OS_BOOT
+	if (!spl_start_uboot()) {
+		volumes[0].vol_id = CONFIG_SPL_UBI_LOAD_KERNEL_ID;
+		volumes[0].load_addr = (void *)CONFIG_SYS_LOAD_ADDR;
+		volumes[1].vol_id = CONFIG_SPL_UBI_LOAD_ARGS_ID;
+		volumes[1].load_addr = (void *)CONFIG_SYS_SPL_ARGS_ADDR;
+
+		ret = ubispl_load_volumes(&info, volumes, 2);
+		if (!ret) {
+			header = (struct image_header *)volumes[0].load_addr;
+			spl_parse_image_header(header);
+			puts("Linux loaded.\n");
+			goto out;
+		}
+		puts("Loading Linux failed, falling back to U-Boot.\n");
+	}
+#endif
+	header = (struct image_header *)
+		(CONFIG_SYS_TEXT_BASE - sizeof(struct image_header));
+	volumes[0].vol_id = CONFIG_SPL_UBI_LOAD_MONITOR_ID;
+	volumes[0].load_addr = (void *)header;
+
+	ret = ubispl_load_volumes(&info, volumes, 1);
+	if (!ret)
+		spl_parse_image_header(header);
+out:
+#ifdef CONFIG_SPL_NAND_SUPPORT
+	if (boot_device == BOOT_DEVICE_NAND)
+		nand_deselect();
+#endif
+	return ret;
+}
diff --git a/common/splash.c b/common/splash.c
index 561d35b..89af437 100644
--- a/common/splash.c
+++ b/common/splash.c
@@ -24,9 +24,37 @@
 #include <splash.h>
 #include <lcd.h>
 
+static struct splash_location default_splash_locations[] = {
+	{
+		.name = "sf",
+		.storage = SPLASH_STORAGE_SF,
+		.flags = SPLASH_STORAGE_RAW,
+		.offset = 0x0,
+	},
+	{
+		.name = "mmc_fs",
+		.storage = SPLASH_STORAGE_MMC,
+		.flags = SPLASH_STORAGE_FS,
+		.devpart = "0:1",
+	},
+	{
+		.name = "usb_fs",
+		.storage = SPLASH_STORAGE_USB,
+		.flags = SPLASH_STORAGE_FS,
+		.devpart = "0:1",
+	},
+	{
+		.name = "sata_fs",
+		.storage = SPLASH_STORAGE_SATA,
+		.flags = SPLASH_STORAGE_FS,
+		.devpart = "0:1",
+	},
+};
+
 __weak int splash_screen_prepare(void)
 {
-	return 0;
+	return splash_source_load(default_splash_locations,
+				  ARRAY_SIZE(default_splash_locations));
 }
 
 #ifdef CONFIG_SPLASH_SCREEN_ALIGN
diff --git a/common/splash_source.c b/common/splash_source.c
index 914f12f..230b2db 100644
--- a/common/splash_source.c
+++ b/common/splash_source.c
@@ -146,7 +146,11 @@
 	if (err)
 		return err;
 
-	return usb_stor_scan(1) < 0 ? -ENODEV : 0;
+#ifndef CONFIG_DM_USB
+	err = usb_stor_scan(1) < 0 ? -ENODEV : 0;
+#endif
+
+	return err;
 }
 #else
 static inline int splash_init_usb(void)
diff --git a/common/usb_hub.c b/common/usb_hub.c
index 0f39c9f..ff9cd50 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -36,7 +36,6 @@
 #include <asm/state.h>
 #endif
 #include <asm/unaligned.h>
-#include <dm/root.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -755,12 +754,6 @@
 	return usb_hub_configure(udev);
 }
 
-static int usb_hub_post_bind(struct udevice *dev)
-{
-	/* Scan the bus for devices */
-	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
-}
-
 static int usb_hub_post_probe(struct udevice *dev)
 {
 	debug("%s\n", __func__);
@@ -782,7 +775,7 @@
 UCLASS_DRIVER(usb_hub) = {
 	.id		= UCLASS_USB_HUB,
 	.name		= "usb_hub",
-	.post_bind	= usb_hub_post_bind,
+	.post_bind	= dm_scan_fdt_dev,
 	.post_probe	= usb_hub_post_probe,
 	.child_pre_probe	= usb_child_pre_probe,
 	.per_child_auto_alloc_size = sizeof(struct usb_device),
diff --git a/configs/C29XPCIE_NAND_defconfig b/configs/C29XPCIE_NAND_defconfig
index bc2ddca..7db345e 100644
--- a/configs/C29XPCIE_NAND_defconfig
+++ b/configs/C29XPCIE_NAND_defconfig
@@ -7,7 +7,7 @@
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="C29XPCIE,36BIT,NAND"
+CONFIG_SYS_EXTRA_OPTIONS="C29XPCIE,NAND"
 CONFIG_BOOTDELAY=-1
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_SF=y
diff --git a/configs/C29XPCIE_NOR_SECBOOT_defconfig b/configs/C29XPCIE_NOR_SECBOOT_defconfig
index 99b437a..8b81f9f 100644
--- a/configs/C29XPCIE_NOR_SECBOOT_defconfig
+++ b/configs/C29XPCIE_NOR_SECBOOT_defconfig
@@ -6,7 +6,7 @@
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="C29XPCIE,36BIT,SECURE_BOOT"
+CONFIG_SYS_EXTRA_OPTIONS="C29XPCIE,SECURE_BOOT"
 CONFIG_BOOTDELAY=-1
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_SF=y
diff --git a/configs/C29XPCIE_SPIFLASH_SECBOOT_defconfig b/configs/C29XPCIE_SPIFLASH_SECBOOT_defconfig
index 491fba2..bc3ba82 100644
--- a/configs/C29XPCIE_SPIFLASH_SECBOOT_defconfig
+++ b/configs/C29XPCIE_SPIFLASH_SECBOOT_defconfig
@@ -6,7 +6,7 @@
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="C29XPCIE,36BIT,SPIFLASH,SECURE_BOOT"
+CONFIG_SYS_EXTRA_OPTIONS="C29XPCIE,SPIFLASH,SECURE_BOOT"
 CONFIG_BOOTDELAY=-1
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_SF=y
diff --git a/configs/C29XPCIE_SPIFLASH_defconfig b/configs/C29XPCIE_SPIFLASH_defconfig
index f2d9772..ff16c7a 100644
--- a/configs/C29XPCIE_SPIFLASH_defconfig
+++ b/configs/C29XPCIE_SPIFLASH_defconfig
@@ -5,7 +5,7 @@
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="C29XPCIE,36BIT,SPIFLASH"
+CONFIG_SYS_EXTRA_OPTIONS="C29XPCIE,SPIFLASH"
 CONFIG_BOOTDELAY=-1
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_SF=y
diff --git a/configs/C29XPCIE_defconfig b/configs/C29XPCIE_defconfig
index 9ccf0e8..8dd57d2 100644
--- a/configs/C29XPCIE_defconfig
+++ b/configs/C29XPCIE_defconfig
@@ -5,7 +5,7 @@
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="C29XPCIE,36BIT"
+CONFIG_SYS_EXTRA_OPTIONS="C29XPCIE"
 CONFIG_BOOTDELAY=-1
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_SF=y
diff --git a/configs/Hummingbird_A31_defconfig b/configs/Hummingbird_A31_defconfig
index 02bcdbf..3b0c439 100644
--- a/configs/Hummingbird_A31_defconfig
+++ b/configs/Hummingbird_A31_defconfig
@@ -9,7 +9,7 @@
 CONFIG_DEFAULT_DEVICE_TREE="sun6i-a31-hummingbird"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL=y
-CONFIG_SYS_EXTRA_OPTIONS="SUNXI_GMAC,RGMII,MACPWR=SUNXI_GPA(21)"
+CONFIG_SYS_EXTRA_OPTIONS="SUNXI_GMAC,RGMII"
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_FPGA is not set
diff --git a/configs/MPC8536DS_36BIT_defconfig b/configs/MPC8536DS_36BIT_defconfig
index 2ffc647..7e221bb 100644
--- a/configs/MPC8536DS_36BIT_defconfig
+++ b/configs/MPC8536DS_36BIT_defconfig
@@ -1,9 +1,9 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_MPC8536DS=y
+CONFIG_PHYS_64BIT=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="36BIT"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/MPC8548CDS_36BIT_defconfig b/configs/MPC8548CDS_36BIT_defconfig
index 066eaf2..5d834e6 100644
--- a/configs/MPC8548CDS_36BIT_defconfig
+++ b/configs/MPC8548CDS_36BIT_defconfig
@@ -1,9 +1,9 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_MPC8548CDS=y
+CONFIG_PHYS_64BIT=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="36BIT"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_I2C=y
diff --git a/configs/MPC8572DS_36BIT_defconfig b/configs/MPC8572DS_36BIT_defconfig
index 8218ef6..4ca98ab 100644
--- a/configs/MPC8572DS_36BIT_defconfig
+++ b/configs/MPC8572DS_36BIT_defconfig
@@ -1,11 +1,11 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_MPC8572DS=y
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="36BIT"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_I2C=y
diff --git a/configs/MPC8641HPCN_36BIT_defconfig b/configs/MPC8641HPCN_36BIT_defconfig
index b90e6ea..2292360 100644
--- a/configs/MPC8641HPCN_36BIT_defconfig
+++ b/configs/MPC8641HPCN_36BIT_defconfig
@@ -1,9 +1,9 @@
 CONFIG_PPC=y
 CONFIG_MPC86xx=y
 CONFIG_TARGET_MPC8641HPCN=y
+CONFIG_PHYS_64BIT=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="PHYS_64BIT"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_I2C=y
diff --git a/configs/P1010RDB-PA_36BIT_NAND_SECBOOT_defconfig b/configs/P1010RDB-PA_36BIT_NAND_SECBOOT_defconfig
index 5e05795..e750ab2 100644
--- a/configs/P1010RDB-PA_36BIT_NAND_SECBOOT_defconfig
+++ b/configs/P1010RDB-PA_36BIT_NAND_SECBOOT_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
-# CONFIG_SYS_MALLOC_F is not set
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1010RDB=y
+# CONFIG_SYS_MALLOC_F is not set
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PA,36BIT,NAND_SECBOOT,SECURE_BOOT"
+CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PA,NAND_SECBOOT,SECURE_BOOT"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1010RDB-PA_36BIT_NAND_defconfig b/configs/P1010RDB-PA_36BIT_NAND_defconfig
index 5e12add..cdc140d 100644
--- a/configs/P1010RDB-PA_36BIT_NAND_defconfig
+++ b/configs/P1010RDB-PA_36BIT_NAND_defconfig
@@ -1,13 +1,14 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1010RDB=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_TPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PA,36BIT,NAND"
+CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PA,NAND"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1010RDB-PA_36BIT_NOR_SECBOOT_defconfig b/configs/P1010RDB-PA_36BIT_NOR_SECBOOT_defconfig
index b63475c..a9b6c58 100644
--- a/configs/P1010RDB-PA_36BIT_NOR_SECBOOT_defconfig
+++ b/configs/P1010RDB-PA_36BIT_NOR_SECBOOT_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
-# CONFIG_SYS_MALLOC_F is not set
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1010RDB=y
+# CONFIG_SYS_MALLOC_F is not set
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PA,36BIT,SECURE_BOOT"
+CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PA,SECURE_BOOT"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1010RDB-PA_36BIT_NOR_defconfig b/configs/P1010RDB-PA_36BIT_NOR_defconfig
index 74168da..22231ab 100644
--- a/configs/P1010RDB-PA_36BIT_NOR_defconfig
+++ b/configs/P1010RDB-PA_36BIT_NOR_defconfig
@@ -1,11 +1,12 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1010RDB=y
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PA,36BIT"
+CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PA"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1010RDB-PA_36BIT_SDCARD_defconfig b/configs/P1010RDB-PA_36BIT_SDCARD_defconfig
index 2e34a10..f41535b 100644
--- a/configs/P1010RDB-PA_36BIT_SDCARD_defconfig
+++ b/configs/P1010RDB-PA_36BIT_SDCARD_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1010RDB=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PA,36BIT,SDCARD"
+CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PA,SDCARD"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1010RDB-PA_36BIT_SPIFLASH_SECBOOT_defconfig b/configs/P1010RDB-PA_36BIT_SPIFLASH_SECBOOT_defconfig
index d5bf946..536eeff 100644
--- a/configs/P1010RDB-PA_36BIT_SPIFLASH_SECBOOT_defconfig
+++ b/configs/P1010RDB-PA_36BIT_SPIFLASH_SECBOOT_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
-# CONFIG_SYS_MALLOC_F is not set
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1010RDB=y
+# CONFIG_SYS_MALLOC_F is not set
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PA,36BIT,SPIFLASH,SECURE_BOOT"
+CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PA,SPIFLASH,SECURE_BOOT"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1010RDB-PA_36BIT_SPIFLASH_defconfig b/configs/P1010RDB-PA_36BIT_SPIFLASH_defconfig
index aa08a59..fbadc0a 100644
--- a/configs/P1010RDB-PA_36BIT_SPIFLASH_defconfig
+++ b/configs/P1010RDB-PA_36BIT_SPIFLASH_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1010RDB=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PA,36BIT,SPIFLASH"
+CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PA,SPIFLASH"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1010RDB-PB_36BIT_NAND_SECBOOT_defconfig b/configs/P1010RDB-PB_36BIT_NAND_SECBOOT_defconfig
index e8564f9..2e97f06 100644
--- a/configs/P1010RDB-PB_36BIT_NAND_SECBOOT_defconfig
+++ b/configs/P1010RDB-PB_36BIT_NAND_SECBOOT_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
-# CONFIG_SYS_MALLOC_F is not set
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1010RDB=y
+# CONFIG_SYS_MALLOC_F is not set
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PB,36BIT,NAND_SECBOOT,SECURE_BOOT"
+CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PB,NAND_SECBOOT,SECURE_BOOT"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1010RDB-PB_36BIT_NAND_defconfig b/configs/P1010RDB-PB_36BIT_NAND_defconfig
index 425344b..14ba390 100644
--- a/configs/P1010RDB-PB_36BIT_NAND_defconfig
+++ b/configs/P1010RDB-PB_36BIT_NAND_defconfig
@@ -1,13 +1,14 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1010RDB=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_TPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PB,36BIT,NAND"
+CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PB,NAND"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1010RDB-PB_36BIT_NOR_SECBOOT_defconfig b/configs/P1010RDB-PB_36BIT_NOR_SECBOOT_defconfig
index dce2a1a..c31a152 100644
--- a/configs/P1010RDB-PB_36BIT_NOR_SECBOOT_defconfig
+++ b/configs/P1010RDB-PB_36BIT_NOR_SECBOOT_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
-# CONFIG_SYS_MALLOC_F is not set
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1010RDB=y
+# CONFIG_SYS_MALLOC_F is not set
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PB,36BIT,SECURE_BOOT"
+CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PB,SECURE_BOOT"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1010RDB-PB_36BIT_NOR_defconfig b/configs/P1010RDB-PB_36BIT_NOR_defconfig
index 883de6f..5929f00 100644
--- a/configs/P1010RDB-PB_36BIT_NOR_defconfig
+++ b/configs/P1010RDB-PB_36BIT_NOR_defconfig
@@ -1,11 +1,12 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1010RDB=y
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PB,36BIT"
+CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PB"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1010RDB-PB_36BIT_SDCARD_defconfig b/configs/P1010RDB-PB_36BIT_SDCARD_defconfig
index 381caad..e6bba19 100644
--- a/configs/P1010RDB-PB_36BIT_SDCARD_defconfig
+++ b/configs/P1010RDB-PB_36BIT_SDCARD_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1010RDB=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PB,36BIT,SDCARD"
+CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PB,SDCARD"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1010RDB-PB_36BIT_SPIFLASH_SECBOOT_defconfig b/configs/P1010RDB-PB_36BIT_SPIFLASH_SECBOOT_defconfig
index 293a945..a8aff01 100644
--- a/configs/P1010RDB-PB_36BIT_SPIFLASH_SECBOOT_defconfig
+++ b/configs/P1010RDB-PB_36BIT_SPIFLASH_SECBOOT_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
-# CONFIG_SYS_MALLOC_F is not set
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1010RDB=y
+# CONFIG_SYS_MALLOC_F is not set
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PB,36BIT,SPIFLASH,SECURE_BOOT"
+CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PB,SPIFLASH,SECURE_BOOT"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1010RDB-PB_36BIT_SPIFLASH_defconfig b/configs/P1010RDB-PB_36BIT_SPIFLASH_defconfig
index 0c8ae44..d7fe891 100644
--- a/configs/P1010RDB-PB_36BIT_SPIFLASH_defconfig
+++ b/configs/P1010RDB-PB_36BIT_SPIFLASH_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1010RDB=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PB,36BIT,SPIFLASH"
+CONFIG_SYS_EXTRA_OPTIONS="P1010RDB_PB,SPIFLASH"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1020MBG-PC_36BIT_SDCARD_defconfig b/configs/P1020MBG-PC_36BIT_SDCARD_defconfig
index bb27831..ecd189f 100644
--- a/configs/P1020MBG-PC_36BIT_SDCARD_defconfig
+++ b/configs/P1020MBG-PC_36BIT_SDCARD_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1020MBG,SDCARD,36BIT"
+CONFIG_SYS_EXTRA_OPTIONS="P1020MBG,SDCARD"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1020MBG-PC_36BIT_defconfig b/configs/P1020MBG-PC_36BIT_defconfig
index 79a4282..69ccc3e 100644
--- a/configs/P1020MBG-PC_36BIT_defconfig
+++ b/configs/P1020MBG-PC_36BIT_defconfig
@@ -1,11 +1,12 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1020MBG,36BIT"
+CONFIG_SYS_EXTRA_OPTIONS="P1020MBG"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1020RDB-PC_36BIT_NAND_defconfig b/configs/P1020RDB-PC_36BIT_NAND_defconfig
index 1c98b55..c1937e4 100644
--- a/configs/P1020RDB-PC_36BIT_NAND_defconfig
+++ b/configs/P1020RDB-PC_36BIT_NAND_defconfig
@@ -1,13 +1,14 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_TPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1020RDB_PC,36BIT,NAND"
+CONFIG_SYS_EXTRA_OPTIONS="P1020RDB_PC,NAND"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1020RDB-PC_36BIT_SDCARD_defconfig b/configs/P1020RDB-PC_36BIT_SDCARD_defconfig
index e5bff61..8d99c18 100644
--- a/configs/P1020RDB-PC_36BIT_SDCARD_defconfig
+++ b/configs/P1020RDB-PC_36BIT_SDCARD_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1020RDB_PC,36BIT,SDCARD"
+CONFIG_SYS_EXTRA_OPTIONS="P1020RDB_PC,SDCARD"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1020RDB-PC_36BIT_SPIFLASH_defconfig b/configs/P1020RDB-PC_36BIT_SPIFLASH_defconfig
index dda50fb..4a2a213 100644
--- a/configs/P1020RDB-PC_36BIT_SPIFLASH_defconfig
+++ b/configs/P1020RDB-PC_36BIT_SPIFLASH_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1020RDB_PC,36BIT,SPIFLASH"
+CONFIG_SYS_EXTRA_OPTIONS="P1020RDB_PC,SPIFLASH"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1020RDB-PC_36BIT_defconfig b/configs/P1020RDB-PC_36BIT_defconfig
index b693705..aea06d0 100644
--- a/configs/P1020RDB-PC_36BIT_defconfig
+++ b/configs/P1020RDB-PC_36BIT_defconfig
@@ -1,11 +1,12 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1020RDB_PC,36BIT"
+CONFIG_SYS_EXTRA_OPTIONS="P1020RDB_PC"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1020UTM-PC_36BIT_SDCARD_defconfig b/configs/P1020UTM-PC_36BIT_SDCARD_defconfig
index 6dfe195..5807c80 100644
--- a/configs/P1020UTM-PC_36BIT_SDCARD_defconfig
+++ b/configs/P1020UTM-PC_36BIT_SDCARD_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1020UTM,36BIT,SDCARD"
+CONFIG_SYS_EXTRA_OPTIONS="P1020UTM,SDCARD"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1020UTM-PC_36BIT_defconfig b/configs/P1020UTM-PC_36BIT_defconfig
index 98f9285..f0ca548 100644
--- a/configs/P1020UTM-PC_36BIT_defconfig
+++ b/configs/P1020UTM-PC_36BIT_defconfig
@@ -1,11 +1,12 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1020UTM,36BIT"
+CONFIG_SYS_EXTRA_OPTIONS="P1020UTM"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1021RDB-PC_36BIT_NAND_defconfig b/configs/P1021RDB-PC_36BIT_NAND_defconfig
index eeb232d..1dc9170 100644
--- a/configs/P1021RDB-PC_36BIT_NAND_defconfig
+++ b/configs/P1021RDB-PC_36BIT_NAND_defconfig
@@ -1,13 +1,14 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_TPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1021RDB,36BIT,NAND"
+CONFIG_SYS_EXTRA_OPTIONS="P1021RDB,NAND"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1021RDB-PC_36BIT_SDCARD_defconfig b/configs/P1021RDB-PC_36BIT_SDCARD_defconfig
index d2f83fa..e26d221 100644
--- a/configs/P1021RDB-PC_36BIT_SDCARD_defconfig
+++ b/configs/P1021RDB-PC_36BIT_SDCARD_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1021RDB,36BIT,SDCARD"
+CONFIG_SYS_EXTRA_OPTIONS="P1021RDB,SDCARD"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1021RDB-PC_36BIT_SPIFLASH_defconfig b/configs/P1021RDB-PC_36BIT_SPIFLASH_defconfig
index 09ba6ea..af880fd 100644
--- a/configs/P1021RDB-PC_36BIT_SPIFLASH_defconfig
+++ b/configs/P1021RDB-PC_36BIT_SPIFLASH_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1021RDB,36BIT,SPIFLASH"
+CONFIG_SYS_EXTRA_OPTIONS="P1021RDB,SPIFLASH"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1021RDB-PC_36BIT_defconfig b/configs/P1021RDB-PC_36BIT_defconfig
index 7652d29..2e1d165 100644
--- a/configs/P1021RDB-PC_36BIT_defconfig
+++ b/configs/P1021RDB-PC_36BIT_defconfig
@@ -1,11 +1,12 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1021RDB,36BIT"
+CONFIG_SYS_EXTRA_OPTIONS="P1021RDB"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1022DS_36BIT_NAND_defconfig b/configs/P1022DS_36BIT_NAND_defconfig
index 352305d..65e46e1 100644
--- a/configs/P1022DS_36BIT_NAND_defconfig
+++ b/configs/P1022DS_36BIT_NAND_defconfig
@@ -1,13 +1,14 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1022DS=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_TPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="36BIT,NAND"
+CONFIG_SYS_EXTRA_OPTIONS="NAND"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1022DS_36BIT_SDCARD_defconfig b/configs/P1022DS_36BIT_SDCARD_defconfig
index 68a6c11..13e3cd5 100644
--- a/configs/P1022DS_36BIT_SDCARD_defconfig
+++ b/configs/P1022DS_36BIT_SDCARD_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1022DS=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="36BIT,SDCARD"
+CONFIG_SYS_EXTRA_OPTIONS="SDCARD"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1022DS_36BIT_SPIFLASH_defconfig b/configs/P1022DS_36BIT_SPIFLASH_defconfig
index 21300da..b01781c 100644
--- a/configs/P1022DS_36BIT_SPIFLASH_defconfig
+++ b/configs/P1022DS_36BIT_SPIFLASH_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1022DS=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="36BIT,SPIFLASH"
+CONFIG_SYS_EXTRA_OPTIONS="SPIFLASH"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1022DS_36BIT_defconfig b/configs/P1022DS_36BIT_defconfig
index c63abc3..7ad8ec0 100644
--- a/configs/P1022DS_36BIT_defconfig
+++ b/configs/P1022DS_36BIT_defconfig
@@ -1,11 +1,11 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1022DS=y
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="36BIT"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1024RDB_36BIT_defconfig b/configs/P1024RDB_36BIT_defconfig
index d3731a8..42a3e35 100644
--- a/configs/P1024RDB_36BIT_defconfig
+++ b/configs/P1024RDB_36BIT_defconfig
@@ -1,11 +1,12 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1024RDB,36BIT"
+CONFIG_SYS_EXTRA_OPTIONS="P1024RDB"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1025RDB_36BIT_defconfig b/configs/P1025RDB_36BIT_defconfig
index 9864486..0da4178 100644
--- a/configs/P1025RDB_36BIT_defconfig
+++ b/configs/P1025RDB_36BIT_defconfig
@@ -1,11 +1,12 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P1025RDB,36BIT"
+CONFIG_SYS_EXTRA_OPTIONS="P1025RDB"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P2020RDB-PC_36BIT_NAND_defconfig b/configs/P2020RDB-PC_36BIT_NAND_defconfig
index 2421a73..1e163f5 100644
--- a/configs/P2020RDB-PC_36BIT_NAND_defconfig
+++ b/configs/P2020RDB-PC_36BIT_NAND_defconfig
@@ -1,13 +1,14 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_TPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P2020RDB,36BIT,NAND"
+CONFIG_SYS_EXTRA_OPTIONS="P2020RDB,NAND"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P2020RDB-PC_36BIT_SDCARD_defconfig b/configs/P2020RDB-PC_36BIT_SDCARD_defconfig
index fce023b..d6e287c 100644
--- a/configs/P2020RDB-PC_36BIT_SDCARD_defconfig
+++ b/configs/P2020RDB-PC_36BIT_SDCARD_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P2020RDB,36BIT,SDCARD"
+CONFIG_SYS_EXTRA_OPTIONS="P2020RDB,SDCARD"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P2020RDB-PC_36BIT_SPIFLASH_defconfig b/configs/P2020RDB-PC_36BIT_SPIFLASH_defconfig
index a316264..d3082bf 100644
--- a/configs/P2020RDB-PC_36BIT_SPIFLASH_defconfig
+++ b/configs/P2020RDB-PC_36BIT_SPIFLASH_defconfig
@@ -1,12 +1,13 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_SPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P2020RDB,36BIT,SPIFLASH"
+CONFIG_SYS_EXTRA_OPTIONS="P2020RDB,SPIFLASH"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P2020RDB-PC_36BIT_defconfig b/configs/P2020RDB-PC_36BIT_defconfig
index 0bc2d1a..59edb0e 100644
--- a/configs/P2020RDB-PC_36BIT_defconfig
+++ b/configs/P2020RDB-PC_36BIT_defconfig
@@ -1,11 +1,12 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1_P2_RDB_PC=y
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="P2020RDB,36BIT"
+CONFIG_SYS_EXTRA_OPTIONS="P2020RDB"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
diff --git a/configs/T1042RDB_PI_NAND_SECURE_BOOT_defconfig b/configs/T1042RDB_PI_NAND_SECURE_BOOT_defconfig
new file mode 100644
index 0000000..2e16255
--- /dev/null
+++ b/configs/T1042RDB_PI_NAND_SECURE_BOOT_defconfig
@@ -0,0 +1,30 @@
+CONFIG_PPC=y
+CONFIG_MPC85xx=y
+CONFIG_TARGET_T104XRDB=y
+CONFIG_SPL=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_OF_BOARD_SETUP=y
+CONFIG_OF_STDOUT_VIA_ALIAS=y
+CONFIG_SYS_EXTRA_OPTIONS="PPC_T1042,T1042RDB_PI,RAMBOOT_PBL,SPL_FSL_PBL,NAND,SECURE_BOOT"
+CONFIG_BOOTDELAY=0
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_GREPENV=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_FAT=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_NETDEVICES=y
+CONFIG_E1000=y
+CONFIG_SYS_NS16550=y
+CONFIG_FSL_ESPI=y
+CONFIG_OF_LIBFDT=y
+CONFIG_RSA=y
+CONFIG_DM=y
diff --git a/configs/am335x_boneblack_vboot_defconfig b/configs/am335x_boneblack_vboot_defconfig
index 903f518..c2f09cb 100644
--- a/configs/am335x_boneblack_vboot_defconfig
+++ b/configs/am335x_boneblack_vboot_defconfig
@@ -49,3 +49,4 @@
 CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
 CONFIG_G_DNL_VENDOR_NUM=0x0451
 CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_DM_I2C=y
diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig
index 696024c..6885230 100644
--- a/configs/am335x_evm_defconfig
+++ b/configs/am335x_evm_defconfig
@@ -49,3 +49,4 @@
 CONFIG_SPL_OF_LIBFDT=y
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_OF_LIST="am335x-evm am335x-bone am335x-boneblack am335x-evmsk am335x-bonegreen am335x-icev2"
+CONFIG_DM_I2C=y
diff --git a/configs/am43xx_evm_defconfig b/configs/am43xx_evm_defconfig
index cb3de11..56782f1 100644
--- a/configs/am43xx_evm_defconfig
+++ b/configs/am43xx_evm_defconfig
@@ -37,6 +37,7 @@
 CONFIG_DM_MMC=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_BAR=y
 CONFIG_SYS_NS16550=y
 CONFIG_TI_QSPI=y
 CONFIG_TIMER=y
@@ -54,3 +55,5 @@
 CONFIG_G_DNL_VENDOR_NUM=0x0403
 CONFIG_G_DNL_PRODUCT_NUM=0xbd00
 CONFIG_SPL_OF_LIBFDT=y
+CONFIG_DM_I2C=y
+CONFIG_DM_ETH=y
diff --git a/configs/am43xx_hs_evm_defconfig b/configs/am43xx_hs_evm_defconfig
index 4856a19..1553196 100644
--- a/configs/am43xx_hs_evm_defconfig
+++ b/configs/am43xx_hs_evm_defconfig
@@ -13,6 +13,7 @@
 CONFIG_FIT=y
 CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=1, NAND"
 CONFIG_SPL_LOAD_FIT=y
+CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
@@ -57,3 +58,5 @@
 CONFIG_G_DNL_VENDOR_NUM=0x0403
 CONFIG_G_DNL_PRODUCT_NUM=0xbd00
 CONFIG_SPL_OF_LIBFDT=y
+CONFIG_DM_I2C=y
+CONFIG_DM_ETH=y
diff --git a/configs/am57xx_evm_defconfig b/configs/am57xx_evm_defconfig
index c29a05a..c95f45a 100644
--- a/configs/am57xx_evm_defconfig
+++ b/configs/am57xx_evm_defconfig
@@ -40,3 +40,9 @@
 CONFIG_SPL_OF_LIBFDT=y
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_OF_LIST="am57xx-beagle-x15 am572x-idk"
+CONFIG_DM_I2C=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_TI_QSPI=y
+CONFIG_CMD_SF=y
diff --git a/configs/am57xx_evm_nodt_defconfig b/configs/am57xx_evm_nodt_defconfig
index 4c5a0de..f518e6f 100644
--- a/configs/am57xx_evm_nodt_defconfig
+++ b/configs/am57xx_evm_nodt_defconfig
@@ -26,3 +26,8 @@
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_OF_LIBFDT=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_TI_QSPI=y
+CONFIG_CMD_SF=y
diff --git a/configs/am57xx_hs_evm_defconfig b/configs/am57xx_hs_evm_defconfig
index e01e504..a4bfdd5 100644
--- a/configs/am57xx_hs_evm_defconfig
+++ b/configs/am57xx_hs_evm_defconfig
@@ -40,4 +40,11 @@
 CONFIG_FIT=y
 CONFIG_SPL_OF_LIBFDT=y
 CONFIG_SPL_LOAD_FIT=y
+CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y
 CONFIG_OF_LIST="am57xx-beagle-x15"
+CONFIG_DM_I2C=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_TI_QSPI=y
+CONFIG_CMD_SF=y
diff --git a/configs/axs101_defconfig b/configs/axs101_defconfig
index 10e802d..dd82581 100644
--- a/configs/axs101_defconfig
+++ b/configs/axs101_defconfig
@@ -1,7 +1,7 @@
 CONFIG_ARC=y
 CONFIG_SYS_DCACHE_OFF=y
-CONFIG_DM_SERIAL=y
 CONFIG_SYS_CLK_FREQ=750000000
+CONFIG_DM_SERIAL=y
 CONFIG_SYS_TEXT_BASE=0x81000000
 CONFIG_DEFAULT_DEVICE_TREE="axs10x"
 CONFIG_BOOTDELAY=3
diff --git a/configs/axs103_defconfig b/configs/axs103_defconfig
index c8474de..4fb26af 100644
--- a/configs/axs103_defconfig
+++ b/configs/axs103_defconfig
@@ -1,7 +1,7 @@
 CONFIG_ARC=y
 CONFIG_ISA_ARCV2=y
-CONFIG_DM_SERIAL=y
 CONFIG_SYS_CLK_FREQ=100000000
+CONFIG_DM_SERIAL=y
 CONFIG_SYS_TEXT_BASE=0x81000000
 CONFIG_DEFAULT_DEVICE_TREE="axs10x"
 CONFIG_BOOTDELAY=3
@@ -25,6 +25,7 @@
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_OHCI_GENERIC=y
 CONFIG_USB_STORAGE=y
 CONFIG_USE_PRIVATE_LIBGCC=y
diff --git a/configs/bayleybay_defconfig b/configs/bayleybay_defconfig
index 9f1d7fb..0a71bb8 100644
--- a/configs/bayleybay_defconfig
+++ b/configs/bayleybay_defconfig
@@ -2,6 +2,7 @@
 CONFIG_VENDOR_INTEL=y
 CONFIG_DEFAULT_DEVICE_TREE="bayleybay"
 CONFIG_TARGET_BAYLEYBAY=y
+CONFIG_INTERNAL_UART=y
 CONFIG_HAVE_INTEL_ME=y
 CONFIG_ENABLE_MRC_CACHE=y
 CONFIG_SMP=y
diff --git a/configs/bcm23550_w1d_defconfig b/configs/bcm23550_w1d_defconfig
index 0ef4a37..ca4feaf 100644
--- a/configs/bcm23550_w1d_defconfig
+++ b/configs/bcm23550_w1d_defconfig
@@ -2,6 +2,13 @@
 CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK=y
 CONFIG_TARGET_BCM23550_W1D=y
 CONFIG_HUSH_PARSER=y
+CONFIG_FASTBOOT=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_CMD_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x80000000
+CONFIG_FASTBOOT_BUF_SIZE=0x1d000000
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=0
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_ASKENV=y
@@ -17,6 +24,7 @@
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_BCM_UDC_OTG_PHY=y
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DWC2_OTG_PHY_BUS_WIDTH_8=y
 CONFIG_USB_GADGET_DOWNLOAD=y
diff --git a/configs/bcm28155_ap_defconfig b/configs/bcm28155_ap_defconfig
index 70eb44a..eb8aa35 100644
--- a/configs/bcm28155_ap_defconfig
+++ b/configs/bcm28155_ap_defconfig
@@ -3,6 +3,13 @@
 CONFIG_TARGET_BCM28155_AP=y
 CONFIG_HUSH_PARSER=y
 # CONFIG_AUTOBOOT is not set
+CONFIG_FASTBOOT=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_CMD_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x80000000
+CONFIG_FASTBOOT_BUF_SIZE=0x7ff00000
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=0
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_ASKENV=y
@@ -18,6 +25,7 @@
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_BCM_UDC_OTG_PHY=y
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DWC2_OTG_PHY_BUS_WIDTH_8=y
 CONFIG_USB_GADGET_DOWNLOAD=y
diff --git a/configs/chromebook_jerry_defconfig b/configs/chromebook_jerry_defconfig
index d5bc515..fd5314a 100644
--- a/configs/chromebook_jerry_defconfig
+++ b/configs/chromebook_jerry_defconfig
@@ -53,7 +53,7 @@
 CONFIG_PINCTRL=y
 CONFIG_SPL_PINCTRL=y
 # CONFIG_SPL_PINCTRL_FULL is not set
-CONFIG_ROCKCHIP_PINCTRL=y
+CONFIG_ROCKCHIP_RK3288_PINCTRL=y
 CONFIG_DM_PMIC=y
 # CONFIG_SPL_PMIC_CHILDREN is not set
 CONFIG_PMIC_RK808=y
diff --git a/configs/colibri_imx7_defconfig b/configs/colibri_imx7_defconfig
new file mode 100644
index 0000000..50c1201
--- /dev/null
+++ b/configs/colibri_imx7_defconfig
@@ -0,0 +1,40 @@
+CONFIG_ARM=y
+CONFIG_ARCH_MX7=y
+CONFIG_TARGET_COLIBRI_IMX7=y
+CONFIG_IMX_RDC=y
+CONFIG_IMX_BOOTAUX=y
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/toradex/colibri_imx7/imximage.cfg,MX7D"
+CONFIG_BOOTDELAY=1
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="Colibri iMX7 # "
+# CONFIG_CMD_BOOTD is not set
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_XIMG is not set
+CONFIG_CMD_ASKENV=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_NAND=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_DFU=y
+CONFIG_CMD_USB_MASS_STORAGE=y
+# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_GADGET=y
+CONFIG_CI_UDC=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_G_DNL_MANUFACTURER="Toradex"
+CONFIG_G_DNL_VENDOR_NUM=0x1b67
+CONFIG_G_DNL_PRODUCT_NUM=0x4020
+CONFIG_OF_LIBFDT=y
diff --git a/configs/conga-qeval20-qa3-e3845-internal-uart_defconfig b/configs/conga-qeval20-qa3-e3845-internal-uart_defconfig
new file mode 100644
index 0000000..c0f5199
--- /dev/null
+++ b/configs/conga-qeval20-qa3-e3845-internal-uart_defconfig
@@ -0,0 +1,66 @@
+CONFIG_X86=y
+CONFIG_DM_I2C=y
+CONFIG_VENDOR_CONGATEC=y
+CONFIG_TARGET_CONGA_QEVAL20_QA3_E3845=y
+CONFIG_DEFAULT_DEVICE_TREE="conga-qeval20-qa3-e3845"
+CONFIG_INTERNAL_UART=y
+CONFIG_HAVE_INTEL_ME=y
+CONFIG_ENABLE_MRC_CACHE=y
+CONFIG_SMP=y
+CONFIG_HAVE_VGA_BIOS=y
+CONFIG_GENERATE_PIRQ_TABLE=y
+CONFIG_GENERATE_MP_TABLE=y
+CONFIG_GENERATE_ACPI_TABLE=y
+CONFIG_SEABIOS=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_BOOTSTAGE=y
+CONFIG_BOOTSTAGE_REPORT=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_CPU=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_GPIO=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_PING=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_BOOTSTAGE=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_OF_CONTROL=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CPU=y
+CONFIG_SYS_I2C_INTEL=y
+CONFIG_WINBOND_W83627=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_ETH=y
+CONFIG_E1000=y
+CONFIG_DM_PCI=y
+CONFIG_DM_RTC=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0x3f8
+CONFIG_DEBUG_UART_CLOCK=1843200
+CONFIG_SYS_NS16550=y
+CONFIG_ICH_SPI=y
+CONFIG_TIMER=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_VIDEO_VESA=y
+CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
+CONFIG_FRAMEBUFFER_VESA_MODE_114=y
+CONFIG_USE_PRIVATE_LIBGCC=y
diff --git a/configs/conga-qeval20-qa3-e3845_defconfig b/configs/conga-qeval20-qa3-e3845_defconfig
index 64fd7c9..4636322 100644
--- a/configs/conga-qeval20-qa3-e3845_defconfig
+++ b/configs/conga-qeval20-qa3-e3845_defconfig
@@ -1,4 +1,5 @@
 CONFIG_X86=y
+CONFIG_DM_I2C=y
 CONFIG_VENDOR_CONGATEC=y
 CONFIG_TARGET_CONGA_QEVAL20_QA3_E3845=y
 CONFIG_DEFAULT_DEVICE_TREE="conga-qeval20-qa3-e3845"
@@ -21,6 +22,7 @@
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_I2C=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_SETEXPR is not set
@@ -38,6 +40,7 @@
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_CPU=y
+CONFIG_SYS_I2C_INTEL=y
 CONFIG_WINBOND_W83627=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_GIGADEVICE=y
diff --git a/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig b/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig
index aff6328..70a051a 100644
--- a/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig
+++ b/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig
@@ -1,11 +1,12 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_CONTROLCENTERD=y
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="36BIT,SDCARD,DEVELOP"
+CONFIG_SYS_EXTRA_OPTIONS="SDCARD,DEVELOP"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/controlcenterd_36BIT_SDCARD_defconfig b/configs/controlcenterd_36BIT_SDCARD_defconfig
index 74b67f7..fe7b463 100644
--- a/configs/controlcenterd_36BIT_SDCARD_defconfig
+++ b/configs/controlcenterd_36BIT_SDCARD_defconfig
@@ -1,11 +1,12 @@
 CONFIG_PPC=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_CONTROLCENTERD=y
+CONFIG_PHYS_64BIT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
-CONFIG_SYS_EXTRA_OPTIONS="36BIT,SDCARD"
+CONFIG_SYS_EXTRA_OPTIONS="SDCARD"
 CONFIG_BOOTDELAY=10
 CONFIG_HUSH_PARSER=y
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/da850evm_defconfig b/configs/da850evm_defconfig
index 0e281a5..40ab975 100644
--- a/configs/da850evm_defconfig
+++ b/configs/da850evm_defconfig
@@ -5,6 +5,7 @@
 CONFIG_SYS_EXTRA_OPTIONS="MAC_ADDR_IN_SPIFLASH"
 CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTZ=y
 CONFIG_SYS_PROMPT="U-Boot > "
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_ASKENV=y
diff --git a/configs/dfi-bt700-q7x-151_defconfig b/configs/dfi-bt700-q7x-151_defconfig
new file mode 100644
index 0000000..6f00004
--- /dev/null
+++ b/configs/dfi-bt700-q7x-151_defconfig
@@ -0,0 +1,63 @@
+CONFIG_X86=y
+CONFIG_DM_I2C=y
+CONFIG_VENDOR_DFI=y
+CONFIG_DEFAULT_DEVICE_TREE="dfi-bt700-q7x-151"
+CONFIG_TARGET_DFI_BT700=y
+CONFIG_HAVE_INTEL_ME=y
+CONFIG_ENABLE_MRC_CACHE=y
+CONFIG_SMP=y
+CONFIG_HAVE_VGA_BIOS=y
+CONFIG_GENERATE_PIRQ_TABLE=y
+CONFIG_GENERATE_MP_TABLE=y
+CONFIG_GENERATE_ACPI_TABLE=y
+CONFIG_SEABIOS=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_BOOTSTAGE=y
+CONFIG_BOOTSTAGE_REPORT=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_CPU=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_GPIO=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_PING=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_BOOTSTAGE=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_OF_CONTROL=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CPU=y
+CONFIG_NUVOTON_NCT6102D=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_ETH=y
+CONFIG_E1000=y
+CONFIG_DM_PCI=y
+CONFIG_DM_RTC=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0x3f8
+CONFIG_DEBUG_UART_CLOCK=1843200
+CONFIG_SYS_NS16550=y
+CONFIG_ICH_SPI=y
+CONFIG_TIMER=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_VIDEO_VESA=y
+CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
+CONFIG_FRAMEBUFFER_VESA_MODE_114=y
+CONFIG_USE_PRIVATE_LIBGCC=y
diff --git a/configs/dra7xx_evm_defconfig b/configs/dra7xx_evm_defconfig
index 756af63..956b83e 100644
--- a/configs/dra7xx_evm_defconfig
+++ b/configs/dra7xx_evm_defconfig
@@ -57,3 +57,9 @@
 CONFIG_SPL_OF_LIBFDT=y
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_OF_LIST="dra7-evm dra72-evm"
+CONFIG_DM_I2C=y
+CONFIG_PCF8575_GPIO=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_DM_ETH=y
diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig
index 6933ab5..ae08e6d 100644
--- a/configs/dra7xx_hs_evm_defconfig
+++ b/configs/dra7xx_hs_evm_defconfig
@@ -58,4 +58,10 @@
 CONFIG_FIT=y
 CONFIG_SPL_OF_LIBFDT=y
 CONFIG_SPL_LOAD_FIT=y
+CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y
 CONFIG_OF_LIST="dra7-evm dra72-evm"
+CONFIG_DM_I2C=y
+CONFIG_PCF8575_GPIO=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_CMD_REGULATOR=y
diff --git a/configs/dragonboard410c_defconfig b/configs/dragonboard410c_defconfig
index 37c5ea77..ad2e8b8 100644
--- a/configs/dragonboard410c_defconfig
+++ b/configs/dragonboard410c_defconfig
@@ -18,6 +18,7 @@
 CONFIG_CMD_EXT4=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_BLK=y
 CONFIG_CLK=y
 CONFIG_MSM_GPIO=y
 CONFIG_PM8916_GPIO=y
@@ -25,6 +26,7 @@
 CONFIG_LED_GPIO=y
 CONFIG_SYSRESET=y
 CONFIG_DM_MMC=y
+CONFIG_DM_MMC_OPS=y
 CONFIG_MSM_SDHCI=y
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_PM8916=y
diff --git a/configs/evb-rk3036_defconfig b/configs/evb-rk3036_defconfig
index 9894fff..2d5e5e0 100644
--- a/configs/evb-rk3036_defconfig
+++ b/configs/evb-rk3036_defconfig
@@ -32,7 +32,7 @@
 CONFIG_DM_MMC=y
 CONFIG_ROCKCHIP_DWMMC=y
 CONFIG_PINCTRL=y
-CONFIG_ROCKCHIP_3036_PINCTRL=y
+CONFIG_ROCKCHIP_RK3036_PINCTRL=y
 CONFIG_RAM=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 CONFIG_DEBUG_UART=y
diff --git a/configs/evb-rk3288_defconfig b/configs/evb-rk3288_defconfig
new file mode 100644
index 0000000..93be4a5
--- /dev/null
+++ b/configs/evb-rk3288_defconfig
@@ -0,0 +1,67 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ROCKCHIP_RK3288=y
+CONFIG_TARGET_EVB_RK3288=y
+CONFIG_SPL_STACK_R_ADDR=0x80000
+CONFIG_DEFAULT_DEVICE_TREE="rk3288-evb"
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_GPIO=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_SYSRESET=y
+CONFIG_DM_MMC=y
+CONFIG_ROCKCHIP_DWMMC=y
+CONFIG_PINCTRL=y
+# CONFIG_PINCTRL_FULL is not set
+CONFIG_SPL_PINCTRL=y
+# CONFIG_SPL_PINCTRL_FULL is not set
+CONFIG_ROCKCHIP_RK3288_PINCTRL=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_ACT8846=y
+CONFIG_DM_REGULATOR=y
+CONFIG_REGULATOR_ACT8846=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_PWM=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xff690000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
+CONFIG_USE_PRIVATE_LIBGCC=y
+CONFIG_USE_TINY_PRINTF=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_ERRNO_STR=y
diff --git a/configs/evb-rk3399_defconfig b/configs/evb-rk3399_defconfig
new file mode 100644
index 0000000..cd06cae
--- /dev/null
+++ b/configs/evb-rk3399_defconfig
@@ -0,0 +1,34 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_ROCKCHIP_RK3399=y
+CONFIG_TARGET_EVB_RK3399=y
+CONFIG_DEFAULT_DEVICE_TREE="rk3399-evb"
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TIME=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CLK=y
+CONFIG_FIT=y
+CONFIG_SYSRESET=y
+CONFIG_DM_MMC=y
+CONFIG_ROCKCHIP_DWMMC=y
+CONFIG_ROCKCHIP_SDHCI=y
+CONFIG_PINCTRL=y
+CONFIG_RAM=y
+CONFIG_SYS_NS16550=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xFF1A0000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_USE_TINY_PRINTF=y
+CONFIG_ERRNO_STR=y
diff --git a/configs/fennec-rk3288_defconfig b/configs/fennec-rk3288_defconfig
new file mode 100644
index 0000000..bcd6ebf
--- /dev/null
+++ b/configs/fennec-rk3288_defconfig
@@ -0,0 +1,66 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ROCKCHIP_RK3288=y
+CONFIG_TARGET_FENNEC_RK3288=y
+CONFIG_SPL_STACK_R_ADDR=0x80000
+CONFIG_DEFAULT_DEVICE_TREE="rk3288-fennec"
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_GPIO=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_SYSRESET=y
+CONFIG_DM_MMC=y
+CONFIG_ROCKCHIP_DWMMC=y
+CONFIG_PINCTRL=y
+# CONFIG_PINCTRL_FULL is not set
+CONFIG_SPL_PINCTRL=y
+# CONFIG_SPL_PINCTRL_FULL is not set
+CONFIG_ROCKCHIP_RK3288_PINCTRL=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_RK808=y
+CONFIG_DM_REGULATOR=y
+CONFIG_REGULATOR_RK808=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_PWM=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xff690000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
+CONFIG_USE_PRIVATE_LIBGCC=y
+CONFIG_USE_TINY_PRINTF=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_ERRNO_STR=y
+# CONFIG_SPL_SIMPLE_BUS is not set
diff --git a/configs/firefly-rk3288_defconfig b/configs/firefly-rk3288_defconfig
index 4af9120..4122000 100644
--- a/configs/firefly-rk3288_defconfig
+++ b/configs/firefly-rk3288_defconfig
@@ -46,7 +46,7 @@
 CONFIG_PINCTRL=y
 CONFIG_SPL_PINCTRL=y
 # CONFIG_SPL_PINCTRL_FULL is not set
-CONFIG_ROCKCHIP_PINCTRL=y
+CONFIG_ROCKCHIP_RK3288_PINCTRL=y
 CONFIG_DM_PMIC=y
 # CONFIG_SPL_PMIC_CHILDREN is not set
 CONFIG_PMIC_ACT8846=y
@@ -69,3 +69,6 @@
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
+CONFIG_SPL_OF_PLATDATA=y
+# CONFIG_SPL_OF_LIBFDT is not set
+CONFIG_ROCKCHIP_SERIAL=y
diff --git a/configs/igep0020_defconfig b/configs/igep0020_defconfig
index 66dd93f..649dd47 100644
--- a/configs/igep0020_defconfig
+++ b/configs/igep0020_defconfig
@@ -2,7 +2,8 @@
 CONFIG_OMAP34XX=y
 CONFIG_TARGET_OMAP3_IGEP00X0=y
 CONFIG_SPL=y
-CONFIG_SYS_EXTRA_OPTIONS="MACH_TYPE=MACH_TYPE_IGEP0020,BOOT_ONENAND"
+CONFIG_SYS_EXTRA_OPTIONS="MACH_TYPE=MACH_TYPE_IGEP0020"
+CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
@@ -24,4 +25,5 @@
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SYS_NS16550=y
+CONFIG_USE_TINY_PRINTF=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/igep0020_nand_defconfig b/configs/igep0020_nand_defconfig
deleted file mode 100644
index 7535d10..0000000
--- a/configs/igep0020_nand_defconfig
+++ /dev/null
@@ -1,27 +0,0 @@
-CONFIG_ARM=y
-CONFIG_OMAP34XX=y
-CONFIG_TARGET_OMAP3_IGEP00X0=y
-CONFIG_SPL=y
-CONFIG_SYS_EXTRA_OPTIONS="MACH_TYPE=MACH_TYPE_IGEP0020,BOOT_NAND"
-CONFIG_HUSH_PARSER=y
-CONFIG_CMD_BOOTZ=y
-# CONFIG_CMD_IMLS is not set
-CONFIG_CMD_ASKENV=y
-# CONFIG_CMD_FLASH is not set
-CONFIG_CMD_MMC=y
-CONFIG_CMD_SPI=y
-CONFIG_CMD_I2C=y
-CONFIG_CMD_GPIO=y
-# CONFIG_CMD_SETEXPR is not set
-CONFIG_CMD_DHCP=y
-CONFIG_CMD_MII=y
-CONFIG_CMD_PING=y
-CONFIG_CMD_CACHE=y
-CONFIG_CMD_EXT2=y
-CONFIG_CMD_EXT4=y
-CONFIG_CMD_EXT4_WRITE=y
-CONFIG_CMD_FAT=y
-CONFIG_CMD_FS_GENERIC=y
-CONFIG_NET_RANDOM_ETHADDR=y
-CONFIG_SYS_NS16550=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/k2e_evm_defconfig b/configs/k2e_evm_defconfig
index 9fcdfe9..04c52f0 100644
--- a/configs/k2e_evm_defconfig
+++ b/configs/k2e_evm_defconfig
@@ -28,6 +28,8 @@
 CONFIG_OF_CONTROL=y
 CONFIG_DM=y
 CONFIG_TI_AEMIF=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_DM_ETH=y
@@ -35,3 +37,5 @@
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
+CONFIG_LIB_RAND=y
+CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/k2g_evm_defconfig b/configs/k2g_evm_defconfig
index 8efa58c..825de72 100644
--- a/configs/k2g_evm_defconfig
+++ b/configs/k2g_evm_defconfig
@@ -27,11 +27,16 @@
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_OF_CONTROL=y
 CONFIG_DM=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_DM_ETH=y
+CONFIG_DM_MMC=y
 CONFIG_REMOTEPROC_TI_POWER=y
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_BAR=y
diff --git a/configs/k2hk_evm_defconfig b/configs/k2hk_evm_defconfig
index 278eaf3..c050f07 100644
--- a/configs/k2hk_evm_defconfig
+++ b/configs/k2hk_evm_defconfig
@@ -28,6 +28,8 @@
 CONFIG_OF_CONTROL=y
 CONFIG_DM=y
 CONFIG_TI_AEMIF=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_DM_ETH=y
@@ -35,3 +37,5 @@
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
+CONFIG_LIB_RAND=y
+CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/k2l_evm_defconfig b/configs/k2l_evm_defconfig
index 8417e0a..e1386f7 100644
--- a/configs/k2l_evm_defconfig
+++ b/configs/k2l_evm_defconfig
@@ -28,6 +28,8 @@
 CONFIG_OF_CONTROL=y
 CONFIG_DM=y
 CONFIG_TI_AEMIF=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_DM_ETH=y
@@ -35,3 +37,5 @@
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
+CONFIG_LIB_RAND=y
+CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/kylin-rk3036_defconfig b/configs/kylin-rk3036_defconfig
index 0ff6c6b..51196aa 100644
--- a/configs/kylin-rk3036_defconfig
+++ b/configs/kylin-rk3036_defconfig
@@ -32,7 +32,7 @@
 CONFIG_DM_MMC=y
 CONFIG_ROCKCHIP_DWMMC=y
 CONFIG_PINCTRL=y
-CONFIG_ROCKCHIP_3036_PINCTRL=y
+CONFIG_ROCKCHIP_RK3036_PINCTRL=y
 CONFIG_RAM=y
 CONFIG_USE_PRIVATE_LIBGCC=y
 CONFIG_CMD_DHRYSTONE=y
diff --git a/configs/ls1021aqds_ddr4_nor_defconfig b/configs/ls1021aqds_ddr4_nor_defconfig
index 6012d49..ffaf6fd 100644
--- a/configs/ls1021aqds_ddr4_nor_defconfig
+++ b/configs/ls1021aqds_ddr4_nor_defconfig
@@ -30,3 +30,4 @@
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
+CONFIG_DM_USB=y
diff --git a/configs/ls1021aqds_ddr4_nor_lpuart_defconfig b/configs/ls1021aqds_ddr4_nor_lpuart_defconfig
index 685f1da..a7c3253 100644
--- a/configs/ls1021aqds_ddr4_nor_lpuart_defconfig
+++ b/configs/ls1021aqds_ddr4_nor_lpuart_defconfig
@@ -30,3 +30,4 @@
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
+CONFIG_DM_USB=y
diff --git a/configs/ls1021aqds_nor_defconfig b/configs/ls1021aqds_nor_defconfig
index 6748546..7a82c67 100644
--- a/configs/ls1021aqds_nor_defconfig
+++ b/configs/ls1021aqds_nor_defconfig
@@ -29,3 +29,4 @@
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
+CONFIG_DM_USB=y
diff --git a/configs/ls1021aqds_nor_lpuart_defconfig b/configs/ls1021aqds_nor_lpuart_defconfig
index 81035c9..30c65ca 100644
--- a/configs/ls1021aqds_nor_lpuart_defconfig
+++ b/configs/ls1021aqds_nor_lpuart_defconfig
@@ -30,3 +30,4 @@
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
+CONFIG_DM_USB=y
diff --git a/configs/ls1021atwr_sdcard_ifc_SECURE_BOOT_defconfig b/configs/ls1021atwr_sdcard_ifc_SECURE_BOOT_defconfig
new file mode 100644
index 0000000..c735d6d
--- /dev/null
+++ b/configs/ls1021atwr_sdcard_ifc_SECURE_BOOT_defconfig
@@ -0,0 +1,31 @@
+CONFIG_ARM=y
+CONFIG_TARGET_LS1021ATWR=y
+CONFIG_SPL=y
+CONFIG_OF_BOARD_SETUP=y
+CONFIG_OF_STDOUT_VIA_ALIAS=y
+CONFIG_SYS_EXTRA_OPTIONS="RAMBOOT_PBL,SPL_FSL_PBL,SD_BOOT,SECURE_BOOT"
+CONFIG_BOOTDELAY=0
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_GREPENV=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_FAT=y
+CONFIG_NETDEVICES=y
+CONFIG_E1000=y
+CONFIG_SYS_NS16550=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
+CONFIG_OF_LIBFDT=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_RSA=y
+CONFIG_DM=y
diff --git a/configs/microblaze-generic_defconfig b/configs/microblaze-generic_defconfig
index a66cd3b..c184923 100644
--- a/configs/microblaze-generic_defconfig
+++ b/configs/microblaze-generic_defconfig
@@ -1,6 +1,4 @@
 CONFIG_MICROBLAZE=y
-CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_DM=y
 CONFIG_TARGET_MICROBLAZE_GENERIC=y
 CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1
 CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1
@@ -9,6 +7,7 @@
 CONFIG_SYS_TEXT_BASE=0x29000000
 CONFIG_DEFAULT_DEVICE_TREE="microblaze-generic"
 CONFIG_SPL=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_BOOTDELAY=-1
@@ -24,6 +23,7 @@
 CONFIG_SPL_OF_CONTROL=y
 CONFIG_OF_EMBED=y
 CONFIG_NETCONSOLE=y
+CONFIG_SPL_DM=y
 CONFIG_DM_ETH=y
 CONFIG_XILINX_AXIEMAC=y
 CONFIG_XILINX_EMACLITE=y
diff --git a/configs/miniarm-rk3288_defconfig b/configs/miniarm-rk3288_defconfig
new file mode 100644
index 0000000..33a4a56
--- /dev/null
+++ b/configs/miniarm-rk3288_defconfig
@@ -0,0 +1,65 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ROCKCHIP_RK3288=y
+CONFIG_TARGET_MINIARM_RK3288=y
+CONFIG_SPL_STACK_R_ADDR=0x80000
+CONFIG_DEFAULT_DEVICE_TREE="rk3288-miniarm"
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_GPIO=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+# CONFIG_SPL_SIMPLE_BUS is not set
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_SYSRESET=y
+CONFIG_DM_MMC=y
+CONFIG_ROCKCHIP_DWMMC=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+# CONFIG_SPL_PINCTRL_FULL is not set
+CONFIG_ROCKCHIP_RK3288_PINCTRL=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_RK808=y
+CONFIG_DM_REGULATOR=y
+CONFIG_REGULATOR_RK808=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_PWM=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xff690000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
+CONFIG_USE_PRIVATE_LIBGCC=y
+CONFIG_USE_TINY_PRINTF=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_ERRNO_STR=y
diff --git a/configs/minnowmax_defconfig b/configs/minnowmax_defconfig
index 28b837d..ba2b7dc 100644
--- a/configs/minnowmax_defconfig
+++ b/configs/minnowmax_defconfig
@@ -2,6 +2,7 @@
 CONFIG_VENDOR_INTEL=y
 CONFIG_DEFAULT_DEVICE_TREE="minnowmax"
 CONFIG_TARGET_MINNOWMAX=y
+CONFIG_INTERNAL_UART=y
 CONFIG_HAVE_INTEL_ME=y
 CONFIG_ENABLE_MRC_CACHE=y
 CONFIG_SMP=y
diff --git a/configs/mx7dsabresd_defconfig b/configs/mx7dsabresd_defconfig
index 09716a7f..b3a708e 100644
--- a/configs/mx7dsabresd_defconfig
+++ b/configs/mx7dsabresd_defconfig
@@ -1,6 +1,7 @@
 CONFIG_ARM=y
 CONFIG_ARCH_MX7=y
 CONFIG_TARGET_MX7DSABRESD=y
+# CONFIG_ARMV7_VIRT is not set
 CONFIG_IMX_RDC=y
 CONFIG_IMX_BOOTAUX=y
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx7dsabresd/imximage.cfg"
@@ -29,6 +30,8 @@
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_MXC_USB_OTG_HACTIVE=y
 CONFIG_USB_GADGET=y
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
diff --git a/configs/mx7dsabresd_secure_defconfig b/configs/mx7dsabresd_secure_defconfig
new file mode 100644
index 0000000..aa92a38
--- /dev/null
+++ b/configs/mx7dsabresd_secure_defconfig
@@ -0,0 +1,41 @@
+CONFIG_ARM=y
+CONFIG_ARCH_MX7=y
+CONFIG_TARGET_MX7DSABRESD=y
+CONFIG_IMX_RDC=y
+CONFIG_IMX_BOOTAUX=y
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx7dsabresd/imximage.cfg"
+CONFIG_BOOTDELAY=3
+CONFIG_HUSH_PARSER=y
+# CONFIG_CMD_BOOTD is not set
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_EXPORTENV is not set
+# CONFIG_CMD_IMPORTENV is not set
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_DFU=y
+CONFIG_CMD_USB_MASS_STORAGE=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_MXC_USB_OTG_HACTIVE=y
+CONFIG_USB_GADGET=y
+CONFIG_CI_UDC=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_G_DNL_MANUFACTURER="FSL"
+CONFIG_G_DNL_VENDOR_NUM=0x0525
+CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
+CONFIG_OF_LIBFDT=y
+CONFIG_ARMV7_BOOT_SEC_DEFAULT=y
diff --git a/configs/arcangel4-be_defconfig b/configs/nsim_700_defconfig
similarity index 75%
copy from configs/arcangel4-be_defconfig
copy to configs/nsim_700_defconfig
index c0c2e4b..202f77c 100644
--- a/configs/arcangel4-be_defconfig
+++ b/configs/nsim_700_defconfig
@@ -1,11 +1,11 @@
 CONFIG_ARC=y
-CONFIG_CPU_BIG_ENDIAN=y
-CONFIG_TARGET_ARCANGEL4=y
-CONFIG_DM_SERIAL=y
+CONFIG_TARGET_NSIM=y
 CONFIG_SYS_CLK_FREQ=70000000
+CONFIG_DM_SERIAL=y
 CONFIG_SYS_TEXT_BASE=0x81000000
-CONFIG_DEFAULT_DEVICE_TREE="arcangel4"
+CONFIG_DEFAULT_DEVICE_TREE="nsim"
 CONFIG_BOOTDELAY=3
+CONFIG_SYS_PROMPT="nsim# "
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
diff --git a/configs/arcangel4-be_defconfig b/configs/nsim_700be_defconfig
similarity index 78%
rename from configs/arcangel4-be_defconfig
rename to configs/nsim_700be_defconfig
index c0c2e4b..b7f7924 100644
--- a/configs/arcangel4-be_defconfig
+++ b/configs/nsim_700be_defconfig
@@ -1,11 +1,12 @@
 CONFIG_ARC=y
 CONFIG_CPU_BIG_ENDIAN=y
-CONFIG_TARGET_ARCANGEL4=y
-CONFIG_DM_SERIAL=y
+CONFIG_TARGET_NSIM=y
 CONFIG_SYS_CLK_FREQ=70000000
+CONFIG_DM_SERIAL=y
 CONFIG_SYS_TEXT_BASE=0x81000000
-CONFIG_DEFAULT_DEVICE_TREE="arcangel4"
+CONFIG_DEFAULT_DEVICE_TREE="nsim"
 CONFIG_BOOTDELAY=3
+CONFIG_SYS_PROMPT="nsim# "
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
diff --git a/configs/arcangel4_defconfig b/configs/nsim_hs38_defconfig
similarity index 73%
rename from configs/arcangel4_defconfig
rename to configs/nsim_hs38_defconfig
index efa55d0..6b448ef 100644
--- a/configs/arcangel4_defconfig
+++ b/configs/nsim_hs38_defconfig
@@ -1,11 +1,12 @@
 CONFIG_ARC=y
-CONFIG_TARGET_ARCANGEL4=y
-CONFIG_DM_SERIAL=y
+CONFIG_ISA_ARCV2=y
+CONFIG_TARGET_NSIM=y
 CONFIG_SYS_CLK_FREQ=70000000
+CONFIG_DM_SERIAL=y
 CONFIG_SYS_TEXT_BASE=0x81000000
-CONFIG_DEFAULT_DEVICE_TREE="arcangel4"
+CONFIG_DEFAULT_DEVICE_TREE="nsim"
 CONFIG_BOOTDELAY=3
-CONFIG_SYS_PROMPT="arcangel4# "
+CONFIG_SYS_PROMPT="nsim# "
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
diff --git a/configs/arcangel4-be_defconfig b/configs/nsim_hs38be_defconfig
similarity index 75%
copy from configs/arcangel4-be_defconfig
copy to configs/nsim_hs38be_defconfig
index c0c2e4b..3e1c599 100644
--- a/configs/arcangel4-be_defconfig
+++ b/configs/nsim_hs38be_defconfig
@@ -1,11 +1,13 @@
 CONFIG_ARC=y
+CONFIG_ISA_ARCV2=y
 CONFIG_CPU_BIG_ENDIAN=y
-CONFIG_TARGET_ARCANGEL4=y
-CONFIG_DM_SERIAL=y
+CONFIG_TARGET_NSIM=y
 CONFIG_SYS_CLK_FREQ=70000000
+CONFIG_DM_SERIAL=y
 CONFIG_SYS_TEXT_BASE=0x81000000
-CONFIG_DEFAULT_DEVICE_TREE="arcangel4"
+CONFIG_DEFAULT_DEVICE_TREE="nsim"
 CONFIG_BOOTDELAY=3
+CONFIG_SYS_PROMPT="nsim# "
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
diff --git a/configs/omap3_evm_quick_mmc_defconfig b/configs/omap3_evm_quick_mmc_defconfig
deleted file mode 100644
index ebdc105..0000000
--- a/configs/omap3_evm_quick_mmc_defconfig
+++ /dev/null
@@ -1,30 +0,0 @@
-CONFIG_ARM=y
-CONFIG_OMAP34XX=y
-CONFIG_TARGET_OMAP3_EVM_QUICK_MMC=y
-CONFIG_SPL=y
-CONFIG_BOOTDELAY=-2
-CONFIG_SYS_PROMPT="OMAP3_EVM # "
-# CONFIG_CMD_BDI is not set
-# CONFIG_CMD_CONSOLE is not set
-# CONFIG_CMD_BOOTD is not set
-# CONFIG_CMD_RUN is not set
-# CONFIG_CMD_IMI is not set
-# CONFIG_CMD_IMLS is not set
-# CONFIG_CMD_XIMG is not set
-# CONFIG_CMD_EDITENV is not set
-# CONFIG_CMD_SAVEENV is not set
-# CONFIG_CMD_ENV_EXISTS is not set
-# CONFIG_CMD_MEMORY is not set
-# CONFIG_CMD_LOADB is not set
-# CONFIG_CMD_LOADS is not set
-# CONFIG_CMD_FLASH is not set
-CONFIG_CMD_MMC=y
-# CONFIG_CMD_FPGA is not set
-# CONFIG_CMD_ECHO is not set
-# CONFIG_CMD_ITEST is not set
-# CONFIG_CMD_SOURCE is not set
-# CONFIG_CMD_SETEXPR is not set
-# CONFIG_CMD_NFS is not set
-# CONFIG_CMD_MISC is not set
-CONFIG_CMD_FAT=y
-CONFIG_SYS_NS16550=y
diff --git a/configs/omap3_evm_quick_nand_defconfig b/configs/omap3_evm_quick_nand_defconfig
deleted file mode 100644
index 52b08b8..0000000
--- a/configs/omap3_evm_quick_nand_defconfig
+++ /dev/null
@@ -1,28 +0,0 @@
-CONFIG_ARM=y
-CONFIG_OMAP34XX=y
-CONFIG_TARGET_OMAP3_EVM_QUICK_NAND=y
-CONFIG_SPL=y
-CONFIG_BOOTDELAY=-2
-CONFIG_SYS_PROMPT="OMAP3_EVM # "
-# CONFIG_CMD_BDI is not set
-# CONFIG_CMD_CONSOLE is not set
-# CONFIG_CMD_BOOTD is not set
-# CONFIG_CMD_RUN is not set
-# CONFIG_CMD_IMI is not set
-# CONFIG_CMD_IMLS is not set
-# CONFIG_CMD_XIMG is not set
-# CONFIG_CMD_EDITENV is not set
-# CONFIG_CMD_SAVEENV is not set
-# CONFIG_CMD_ENV_EXISTS is not set
-# CONFIG_CMD_MEMORY is not set
-# CONFIG_CMD_LOADB is not set
-# CONFIG_CMD_LOADS is not set
-# CONFIG_CMD_FLASH is not set
-# CONFIG_CMD_FPGA is not set
-# CONFIG_CMD_ECHO is not set
-# CONFIG_CMD_ITEST is not set
-# CONFIG_CMD_SOURCE is not set
-# CONFIG_CMD_SETEXPR is not set
-# CONFIG_CMD_NFS is not set
-# CONFIG_CMD_MISC is not set
-CONFIG_SYS_NS16550=y
diff --git a/configs/openrisc-generic_defconfig b/configs/openrisc-generic_defconfig
index 14923c0..5bc81cc 100644
--- a/configs/openrisc-generic_defconfig
+++ b/configs/openrisc-generic_defconfig
@@ -6,5 +6,7 @@
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
+CONFIG_NETDEVICES=y
+CONFIG_ETHOC=y
 CONFIG_SYS_NS16550=y
 # CONFIG_AUTOBOOT is not set
diff --git a/configs/orangepi_lite_defconfig b/configs/orangepi_lite_defconfig
new file mode 100644
index 0000000..417e4f6
--- /dev/null
+++ b/configs/orangepi_lite_defconfig
@@ -0,0 +1,15 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_MACH_SUN8I_H3=y
+CONFIG_DRAM_CLK=672
+CONFIG_DRAM_ZQ=3881979
+CONFIG_DRAM_ODT_EN=y
+CONFIG_MMC0_CD_PIN="PF6"
+# CONFIG_VIDEO is not set
+CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-lite"
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+CONFIG_USB_EHCI_HCD=y
diff --git a/configs/orangepi_one_defconfig b/configs/orangepi_one_defconfig
index be8afca..81299e6 100644
--- a/configs/orangepi_one_defconfig
+++ b/configs/orangepi_one_defconfig
@@ -13,3 +13,4 @@
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_FPGA is not set
 CONFIG_USB_EHCI_HCD=y
+CONFIG_SUN8I_EMAC=y
diff --git a/configs/orangepi_pc_defconfig b/configs/orangepi_pc_defconfig
index 7eaa795..2281aed 100644
--- a/configs/orangepi_pc_defconfig
+++ b/configs/orangepi_pc_defconfig
@@ -4,6 +4,7 @@
 CONFIG_DRAM_CLK=624
 CONFIG_DRAM_ZQ=3881979
 CONFIG_DRAM_ODT_EN=y
+CONFIG_MMC0_CD_PIN="PF6"
 # CONFIG_VIDEO is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-pc"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
@@ -13,3 +14,4 @@
 # CONFIG_CMD_FPGA is not set
 CONFIG_SY8106A_POWER=y
 CONFIG_USB_EHCI_HCD=y
+CONFIG_SUN8I_EMAC=y
diff --git a/configs/orangepi_pc_plus_defconfig b/configs/orangepi_pc_plus_defconfig
new file mode 100644
index 0000000..3ec6dac
--- /dev/null
+++ b/configs/orangepi_pc_plus_defconfig
@@ -0,0 +1,18 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_MACH_SUN8I_H3=y
+CONFIG_DRAM_CLK=624
+CONFIG_DRAM_ZQ=3881979
+CONFIG_DRAM_ODT_EN=y
+CONFIG_MMC0_CD_PIN="PF6"
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+# CONFIG_VIDEO is not set
+CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-pc-plus"
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+CONFIG_SY8106A_POWER=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_SUN8I_EMAC=y
diff --git a/configs/p2771-0000_defconfig b/configs/p2771-0000-a02_defconfig
similarity index 72%
copy from configs/p2771-0000_defconfig
copy to configs/p2771-0000-a02_defconfig
index 9f2c418..5ce369c 100644
--- a/configs/p2771-0000_defconfig
+++ b/configs/p2771-0000-a02_defconfig
@@ -2,10 +2,10 @@
 CONFIG_TEGRA=y
 CONFIG_TEGRA186=y
 CONFIG_TARGET_P2771_0000=y
-CONFIG_DEFAULT_DEVICE_TREE="tegra186-p2771-0000"
+CONFIG_DEFAULT_DEVICE_TREE="tegra186-p2771-0000-a02"
 CONFIG_OF_SYSTEM_SETUP=y
 CONFIG_HUSH_PARSER=y
-CONFIG_SYS_PROMPT="Tegra186 (P2771-0000) # "
+CONFIG_SYS_PROMPT="Tegra186 (P2771-0000 A02) # "
 # CONFIG_CMD_IMI is not set
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
@@ -26,6 +26,12 @@
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_RTL8169=y
+CONFIG_E1000=y
+CONFIG_PCI_TEGRA=y
+CONFIG_TEGRA186_BPMP_I2C=y
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_TEGRA186_POWER_DOMAIN=y
diff --git a/configs/p2771-0000_defconfig b/configs/p2771-0000-b00_defconfig
similarity index 72%
rename from configs/p2771-0000_defconfig
rename to configs/p2771-0000-b00_defconfig
index 9f2c418..27393f3 100644
--- a/configs/p2771-0000_defconfig
+++ b/configs/p2771-0000-b00_defconfig
@@ -2,10 +2,10 @@
 CONFIG_TEGRA=y
 CONFIG_TEGRA186=y
 CONFIG_TARGET_P2771_0000=y
-CONFIG_DEFAULT_DEVICE_TREE="tegra186-p2771-0000"
+CONFIG_DEFAULT_DEVICE_TREE="tegra186-p2771-0000-b00"
 CONFIG_OF_SYSTEM_SETUP=y
 CONFIG_HUSH_PARSER=y
-CONFIG_SYS_PROMPT="Tegra186 (P2771-0000) # "
+CONFIG_SYS_PROMPT="Tegra186 (P2771-0000 B00) # "
 # CONFIG_CMD_IMI is not set
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
@@ -26,6 +26,12 @@
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_RTL8169=y
+CONFIG_E1000=y
+CONFIG_PCI_TEGRA=y
+CONFIG_TEGRA186_BPMP_I2C=y
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_TEGRA186_POWER_DOMAIN=y
diff --git a/configs/pcm058_defconfig b/configs/pcm058_defconfig
new file mode 100644
index 0000000..1576745
--- /dev/null
+++ b/configs/pcm058_defconfig
@@ -0,0 +1,34 @@
+CONFIG_ARM=y
+CONFIG_ARCH_MX6=y
+CONFIG_TARGET_PCM058=y
+CONFIG_SPL=y
+CONFIG_BOOTDELAY=3
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,MX6Q"
+CONFIG_HUSH_PARSER=y
+CONFIG_MTD=y
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_MTDPARTS=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_USB=n
+CONFIG_CMD_DFU=n
+CONFIG_CMD_USB_MASS_STORAGE=n
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_FIT=y
+CONFIG_DM=y
+CONFIG_DM_THERMAL=y
+CONFIG_OF_LIBFDT=y
diff --git a/configs/pico-imx6ul_defconfig b/configs/pico-imx6ul_defconfig
index ab9c9f1..e202159 100644
--- a/configs/pico-imx6ul_defconfig
+++ b/configs/pico-imx6ul_defconfig
@@ -10,6 +10,7 @@
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_MMC=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_DFU=y
 CONFIG_CMD_USB_MASS_STORAGE=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_DHCP=y
@@ -21,4 +22,11 @@
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_USB=y
+CONFIG_USB_GADGET=y
+CONFIG_CI_UDC=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_G_DNL_MANUFACTURER="FSL"
+CONFIG_G_DNL_VENDOR_NUM=0x0525
+CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_OF_LIBFDT=y
diff --git a/configs/pine64_plus_defconfig b/configs/pine64_plus_defconfig
index 0bf79bf..5c97de1 100644
--- a/configs/pine64_plus_defconfig
+++ b/configs/pine64_plus_defconfig
@@ -10,3 +10,4 @@
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_FPGA is not set
 CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK=y
+CONFIG_SUN8I_EMAC=y
diff --git a/configs/popmetal-rk3288_defconfig b/configs/popmetal-rk3288_defconfig
new file mode 100644
index 0000000..653bfed
--- /dev/null
+++ b/configs/popmetal-rk3288_defconfig
@@ -0,0 +1,65 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ROCKCHIP_RK3288=y
+CONFIG_TARGET_POPMETAL_RK3288=y
+CONFIG_SPL_STACK_R_ADDR=0x80000
+CONFIG_DEFAULT_DEVICE_TREE="rk3288-popmetal"
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_GPIO=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+# CONFIG_SPL_SIMPLE_BUS is not set
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_SYSRESET=y
+CONFIG_DM_MMC=y
+CONFIG_ROCKCHIP_DWMMC=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+# CONFIG_SPL_PINCTRL_FULL is not set
+CONFIG_ROCKCHIP_RK3288_PINCTRL=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_RK808=y
+CONFIG_DM_REGULATOR=y
+CONFIG_REGULATOR_RK808=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_PWM=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xff690000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
+CONFIG_USE_PRIVATE_LIBGCC=y
+CONFIG_USE_TINY_PRINTF=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_ERRNO_STR=y
diff --git a/configs/rock2_defconfig b/configs/rock2_defconfig
index 3e16b80..3b6d7d9 100644
--- a/configs/rock2_defconfig
+++ b/configs/rock2_defconfig
@@ -44,7 +44,7 @@
 CONFIG_PINCTRL=y
 CONFIG_SPL_PINCTRL=y
 # CONFIG_SPL_PINCTRL_FULL is not set
-CONFIG_ROCKCHIP_PINCTRL=y
+CONFIG_ROCKCHIP_RK3288_PINCTRL=y
 CONFIG_DM_PMIC=y
 # CONFIG_SPL_PMIC_CHILDREN is not set
 CONFIG_PMIC_ACT8846=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 94253a6..887d83a 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -1,5 +1,4 @@
 CONFIG_SYS_MALLOC_F_LEN=0x2000
-CONFIG_BLK=y
 CONFIG_MMC=y
 CONFIG_PCI=y
 CONFIG_DEFAULT_DEVICE_TREE="sandbox"
@@ -71,6 +70,7 @@
 CONFIG_DEBUG_DEVRES=y
 CONFIG_ADC=y
 CONFIG_ADC_SANDBOX=y
+CONFIG_BLK=y
 CONFIG_CLK=y
 CONFIG_CPU=y
 CONFIG_DM_DEMO=y
@@ -101,7 +101,8 @@
 CONFIG_PWRSEQ=y
 CONFIG_SPL_PWRSEQ=y
 CONFIG_SYSRESET=y
-CONFIG_DM_MMC=y
+CONFIG_I2C_EEPROM=y
+CONFIG_DM_MMC_OPS=y
 CONFIG_SANDBOX_MMC=y
 CONFIG_SPI_FLASH_SANDBOX=y
 CONFIG_SPI_FLASH=y
@@ -119,8 +120,8 @@
 CONFIG_PCI_SANDBOX=y
 CONFIG_PINCTRL=y
 CONFIG_PINCONF=y
-CONFIG_ROCKCHIP_PINCTRL=y
-CONFIG_ROCKCHIP_3036_PINCTRL=y
+CONFIG_ROCKCHIP_RK3288_PINCTRL=y
+CONFIG_ROCKCHIP_RK3036_PINCTRL=y
 CONFIG_PINCTRL_SANDBOX=y
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_ACT8846=y
@@ -175,3 +176,5 @@
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
 CONFIG_UT_ENV=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_SANDBOX_POWER_DOMAIN=y
diff --git a/configs/sandbox_noblk_defconfig b/configs/sandbox_noblk_defconfig
index 60c7339..503845b 100644
--- a/configs/sandbox_noblk_defconfig
+++ b/configs/sandbox_noblk_defconfig
@@ -112,8 +112,8 @@
 CONFIG_PCI_SANDBOX=y
 CONFIG_PINCTRL=y
 CONFIG_PINCONF=y
-CONFIG_ROCKCHIP_PINCTRL=y
-CONFIG_ROCKCHIP_3036_PINCTRL=y
+CONFIG_ROCKCHIP_RK3288_PINCTRL=y
+CONFIG_ROCKCHIP_RK3036_PINCTRL=y
 CONFIG_PINCTRL_SANDBOX=y
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_ACT8846=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
new file mode 100644
index 0000000..0f6dda8
--- /dev/null
+++ b/configs/sandbox_spl_defconfig
@@ -0,0 +1,183 @@
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_MMC=y
+CONFIG_SANDBOX_SPL=y
+CONFIG_PCI=y
+CONFIG_DEFAULT_DEVICE_TREE="sandbox"
+CONFIG_I8042_KEYB=y
+CONFIG_SPL=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_BOOTSTAGE=y
+CONFIG_BOOTSTAGE_REPORT=y
+CONFIG_BOOTSTAGE_USER_COUNT=0x20
+CONFIG_BOOTSTAGE_FDT=y
+CONFIG_BOOTSTAGE_STASH=y
+CONFIG_BOOTSTAGE_STASH_ADDR=0x0
+CONFIG_BOOTSTAGE_STASH_SIZE=0x4096
+CONFIG_CONSOLE_RECORD=y
+CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_CPU=y
+CONFIG_CMD_LICENSE=y
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_ASKENV=y
+CONFIG_CMD_GREPENV=y
+CONFIG_LOOPW=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_MX_CYCLIC=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_DEMO=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_REMOTEPROC=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_TFTPSRV=y
+CONFIG_CMD_RARP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CDP=y
+CONFIG_CMD_SNTP=y
+CONFIG_CMD_DNS=y
+CONFIG_CMD_LINK_LOCAL=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_TIMER=y
+CONFIG_CMD_SOUND=y
+CONFIG_CMD_QFW=y
+CONFIG_CMD_BOOTSTAGE=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_TPM=y
+CONFIG_CMD_TPM_TEST=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_HOSTFILE=y
+CONFIG_SPL_OF_PLATDATA=y
+CONFIG_NETCONSOLE=y
+CONFIG_SPL_DM=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_DEVRES=y
+CONFIG_DEBUG_DEVRES=y
+# CONFIG_SPL_SIMPLE_BUS is not set
+CONFIG_ADC=y
+CONFIG_ADC_SANDBOX=y
+CONFIG_BLK=y
+CONFIG_CLK=y
+CONFIG_CPU=y
+CONFIG_DM_DEMO=y
+CONFIG_DM_DEMO_SIMPLE=y
+CONFIG_DM_DEMO_SHAPE=y
+CONFIG_PM8916_GPIO=y
+CONFIG_SANDBOX_GPIO=y
+CONFIG_DM_I2C_COMPAT=y
+CONFIG_I2C_CROS_EC_TUNNEL=y
+CONFIG_I2C_CROS_EC_LDO=y
+CONFIG_DM_I2C_GPIO=y
+CONFIG_SYS_I2C_SANDBOX=y
+CONFIG_I2C_MUX=y
+CONFIG_SPL_I2C_MUX=y
+CONFIG_I2C_ARB_GPIO_CHALLENGE=y
+CONFIG_CROS_EC_KEYB=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_DM_MAILBOX=y
+CONFIG_SANDBOX_MBOX=y
+CONFIG_MISC=y
+CONFIG_CMD_CROS_EC=y
+CONFIG_CROS_EC=y
+CONFIG_CROS_EC_I2C=y
+CONFIG_CROS_EC_LPC=y
+CONFIG_CROS_EC_SANDBOX=y
+CONFIG_CROS_EC_SPI=y
+CONFIG_PWRSEQ=y
+CONFIG_SPL_PWRSEQ=y
+CONFIG_SYSRESET=y
+CONFIG_DM_MMC_OPS=y
+CONFIG_SANDBOX_MMC=y
+CONFIG_SPI_FLASH_SANDBOX=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_ATMEL=y
+CONFIG_SPI_FLASH_EON=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_SST=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_ETH=y
+CONFIG_DM_PCI=y
+CONFIG_DM_PCI_COMPAT=y
+CONFIG_PCI_SANDBOX=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_ROCKCHIP_PINCTRL=y
+CONFIG_ROCKCHIP_3036_PINCTRL=y
+CONFIG_PINCTRL_SANDBOX=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_ACT8846=y
+CONFIG_DM_PMIC_PFUZE100=y
+CONFIG_DM_PMIC_MAX77686=y
+CONFIG_PMIC_PM8916=y
+CONFIG_PMIC_RK808=y
+CONFIG_PMIC_S2MPS11=y
+CONFIG_DM_PMIC_SANDBOX=y
+CONFIG_PMIC_S5M8767=y
+CONFIG_PMIC_TPS65090=y
+CONFIG_DM_REGULATOR=y
+CONFIG_REGULATOR_ACT8846=y
+CONFIG_DM_REGULATOR_PFUZE100=y
+CONFIG_DM_REGULATOR_MAX77686=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_REGULATOR_RK808=y
+CONFIG_REGULATOR_S5M8767=y
+CONFIG_DM_REGULATOR_SANDBOX=y
+CONFIG_REGULATOR_TPS65090=y
+CONFIG_RAM=y
+CONFIG_REMOTEPROC_SANDBOX=y
+CONFIG_DM_RESET=y
+CONFIG_SANDBOX_RESET=y
+CONFIG_DM_RTC=y
+CONFIG_SANDBOX_SERIAL=y
+CONFIG_SOUND=y
+CONFIG_SOUND_SANDBOX=y
+CONFIG_SANDBOX_SPI=y
+CONFIG_SPMI=y
+CONFIG_SPMI_SANDBOX=y
+CONFIG_TIMER=y
+CONFIG_TIMER_EARLY=y
+CONFIG_SANDBOX_TIMER=y
+CONFIG_TPM_TIS_SANDBOX=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EMUL=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_KEYBOARD=y
+CONFIG_SYS_USB_EVENT_POLL=y
+CONFIG_DM_VIDEO=y
+CONFIG_CONSOLE_ROTATION=y
+CONFIG_CONSOLE_TRUETYPE=y
+CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y
+CONFIG_VIDEO_SANDBOX_SDL=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_TPM=y
+CONFIG_LZ4=y
+CONFIG_ERRNO_STR=y
+CONFIG_UNIT_TEST=y
+CONFIG_UT_TIME=y
+CONFIG_UT_DM=y
+CONFIG_UT_ENV=y
diff --git a/configs/socfpga_arria5_defconfig b/configs/socfpga_arria5_defconfig
index 2478ae5..1bec969 100644
--- a/configs/socfpga_arria5_defconfig
+++ b/configs/socfpga_arria5_defconfig
@@ -10,7 +10,6 @@
 CONFIG_SPL=y
 CONFIG_SPL_STACK_R=y
 CONFIG_FIT=y
-CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/socfpga_cyclone5_defconfig b/configs/socfpga_cyclone5_defconfig
index 1619b86..0437cbe 100644
--- a/configs/socfpga_cyclone5_defconfig
+++ b/configs/socfpga_cyclone5_defconfig
@@ -10,7 +10,6 @@
 CONFIG_SPL=y
 CONFIG_SPL_STACK_R=y
 CONFIG_FIT=y
-CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/socfpga_de0_nano_soc_defconfig b/configs/socfpga_de0_nano_soc_defconfig
index 43d939b..7c05e6a 100644
--- a/configs/socfpga_de0_nano_soc_defconfig
+++ b/configs/socfpga_de0_nano_soc_defconfig
@@ -10,7 +10,6 @@
 CONFIG_SPL=y
 CONFIG_SPL_STACK_R=y
 CONFIG_FIT=y
-CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/socfpga_is1_defconfig b/configs/socfpga_is1_defconfig
index 658770b..58661c0 100644
--- a/configs/socfpga_is1_defconfig
+++ b/configs/socfpga_is1_defconfig
@@ -9,7 +9,6 @@
 CONFIG_SPL=y
 CONFIG_SPL_STACK_R=y
 CONFIG_FIT=y
-CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/socfpga_mcvevk_defconfig b/configs/socfpga_mcvevk_defconfig
index c5c662b..517a6de 100644
--- a/configs/socfpga_mcvevk_defconfig
+++ b/configs/socfpga_mcvevk_defconfig
@@ -10,7 +10,6 @@
 CONFIG_SPL=y
 CONFIG_SPL_STACK_R=y
 CONFIG_FIT=y
-CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/socfpga_sockit_defconfig b/configs/socfpga_sockit_defconfig
index 1c4a40d..9bd3331 100644
--- a/configs/socfpga_sockit_defconfig
+++ b/configs/socfpga_sockit_defconfig
@@ -10,7 +10,6 @@
 CONFIG_SPL=y
 CONFIG_SPL_STACK_R=y
 CONFIG_FIT=y
-CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/socfpga_socrates_defconfig b/configs/socfpga_socrates_defconfig
index e34d13e..5347032 100644
--- a/configs/socfpga_socrates_defconfig
+++ b/configs/socfpga_socrates_defconfig
@@ -10,7 +10,6 @@
 CONFIG_SPL=y
 CONFIG_SPL_STACK_R=y
 CONFIG_FIT=y
-CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/socfpga_sr1500_defconfig b/configs/socfpga_sr1500_defconfig
index d1cfbcd..81a3fc1 100644
--- a/configs/socfpga_sr1500_defconfig
+++ b/configs/socfpga_sr1500_defconfig
@@ -10,7 +10,6 @@
 CONFIG_SPL=y
 CONFIG_SPL_STACK_R=y
 CONFIG_FIT=y
-CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/som-db5800-som-6867_defconfig b/configs/som-db5800-som-6867_defconfig
new file mode 100644
index 0000000..30e093b
--- /dev/null
+++ b/configs/som-db5800-som-6867_defconfig
@@ -0,0 +1,61 @@
+CONFIG_X86=y
+CONFIG_VENDOR_ADVANTECH=y
+CONFIG_DEFAULT_DEVICE_TREE="baytrail_som-db5800-som-6867"
+CONFIG_TARGET_SOM_DB5800_SOM_6867=y
+CONFIG_HAVE_INTEL_ME=y
+CONFIG_ENABLE_MRC_CACHE=y
+CONFIG_SMP=y
+CONFIG_HAVE_VGA_BIOS=y
+CONFIG_GENERATE_PIRQ_TABLE=y
+CONFIG_GENERATE_MP_TABLE=y
+CONFIG_GENERATE_ACPI_TABLE=y
+CONFIG_SEABIOS=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_BOOTSTAGE=y
+CONFIG_BOOTSTAGE_REPORT=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_CPU=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_MMC is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_GPIO=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_PING=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_BOOTSTAGE=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_OF_CONTROL=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CPU=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_ETH=y
+CONFIG_E1000=y
+CONFIG_DM_PCI=y
+CONFIG_DM_RTC=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0x3f8
+CONFIG_DEBUG_UART_CLOCK=1843200
+CONFIG_SYS_NS16550=y
+CONFIG_ICH_SPI=y
+CONFIG_TIMER=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_VIDEO_VESA=y
+CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
+CONFIG_FRAMEBUFFER_VESA_MODE_11A=y
+CONFIG_USE_PRIVATE_LIBGCC=y
diff --git a/configs/theadorable-x86-dfi-bt700_defconfig b/configs/theadorable-x86-dfi-bt700_defconfig
new file mode 100644
index 0000000..3aba157
--- /dev/null
+++ b/configs/theadorable-x86-dfi-bt700_defconfig
@@ -0,0 +1,60 @@
+CONFIG_X86=y
+CONFIG_DM_I2C=y
+CONFIG_VENDOR_DFI=y
+CONFIG_DEFAULT_DEVICE_TREE="theadorable-x86-dfi-bt700"
+CONFIG_TARGET_DFI_BT700=y
+CONFIG_HAVE_INTEL_ME=y
+CONFIG_ENABLE_MRC_CACHE=y
+CONFIG_SMP=y
+CONFIG_HAVE_VGA_BIOS=y
+CONFIG_GENERATE_PIRQ_TABLE=y
+CONFIG_GENERATE_MP_TABLE=y
+CONFIG_GENERATE_ACPI_TABLE=y
+CONFIG_SEABIOS=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_BOOTSTAGE=y
+CONFIG_BOOTSTAGE_REPORT=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_CPU=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_GPIO=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_PING=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_BOOTSTAGE=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_OF_CONTROL=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CPU=y
+CONFIG_NUVOTON_NCT6102D=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_ETH=y
+CONFIG_E1000=y
+CONFIG_DM_PCI=y
+CONFIG_DM_RTC=y
+CONFIG_SYS_NS16550=y
+CONFIG_ICH_SPI=y
+CONFIG_TIMER=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_VIDEO_VESA=y
+CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
+CONFIG_FRAMEBUFFER_VESA_MODE_114=y
+CONFIG_USE_PRIVATE_LIBGCC=y
diff --git a/configs/thunderx_88xx_defconfig b/configs/thunderx_88xx_defconfig
index 4a8655f..28797f9 100644
--- a/configs/thunderx_88xx_defconfig
+++ b/configs/thunderx_88xx_defconfig
@@ -2,7 +2,6 @@
 CONFIG_TARGET_THUNDERX_88XX=y
 CONFIG_DM_SERIAL=y
 CONFIG_DEFAULT_DEVICE_TREE="thunderx-88xx"
-CONFIG_SYS_EXTRA_OPTIONS="ARM64"
 CONFIG_BOOTDELAY=5
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ThunderX_88XX> "
diff --git a/configs/uniphier_ld11_defconfig b/configs/uniphier_ld11_defconfig
index ffcac79..57b9c07 100644
--- a/configs/uniphier_ld11_defconfig
+++ b/configs/uniphier_ld11_defconfig
@@ -21,6 +21,8 @@
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_OF_TRANSLATE=y
 CONFIG_GPIO_UNIPHIER=y
+CONFIG_MISC=y
+CONFIG_I2C_EEPROM=y
 CONFIG_PINCTRL=y
 CONFIG_SPL_PINCTRL=y
 CONFIG_UNIPHIER_SERIAL=y
diff --git a/configs/uniphier_ld20_defconfig b/configs/uniphier_ld20_defconfig
index cbc65dd..e6aa525 100644
--- a/configs/uniphier_ld20_defconfig
+++ b/configs/uniphier_ld20_defconfig
@@ -21,6 +21,8 @@
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_OF_TRANSLATE=y
 CONFIG_GPIO_UNIPHIER=y
+CONFIG_MISC=y
+CONFIG_I2C_EEPROM=y
 CONFIG_MMC_UNIPHIER=y
 CONFIG_PINCTRL=y
 CONFIG_SPL_PINCTRL=y
diff --git a/configs/uniphier_ld4_sld8_defconfig b/configs/uniphier_ld4_sld8_defconfig
index 22615a6..47b577a 100644
--- a/configs/uniphier_ld4_sld8_defconfig
+++ b/configs/uniphier_ld4_sld8_defconfig
@@ -22,6 +22,8 @@
 CONFIG_CMD_FAT=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_GPIO_UNIPHIER=y
+CONFIG_MISC=y
+CONFIG_I2C_EEPROM=y
 CONFIG_MMC_UNIPHIER=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
diff --git a/configs/uniphier_pro4_defconfig b/configs/uniphier_pro4_defconfig
index 18f4caf..e156ec5 100644
--- a/configs/uniphier_pro4_defconfig
+++ b/configs/uniphier_pro4_defconfig
@@ -21,6 +21,8 @@
 CONFIG_CMD_FAT=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_GPIO_UNIPHIER=y
+CONFIG_MISC=y
+CONFIG_I2C_EEPROM=y
 CONFIG_MMC_UNIPHIER=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
diff --git a/configs/uniphier_pxs2_ld6b_defconfig b/configs/uniphier_pxs2_ld6b_defconfig
index cf6d3e4..f943516 100644
--- a/configs/uniphier_pxs2_ld6b_defconfig
+++ b/configs/uniphier_pxs2_ld6b_defconfig
@@ -22,6 +22,8 @@
 CONFIG_CMD_FAT=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_GPIO_UNIPHIER=y
+CONFIG_MISC=y
+CONFIG_I2C_EEPROM=y
 CONFIG_MMC_UNIPHIER=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
diff --git a/configs/uniphier_sld3_defconfig b/configs/uniphier_sld3_defconfig
index 0965019..598cde2 100644
--- a/configs/uniphier_sld3_defconfig
+++ b/configs/uniphier_sld3_defconfig
@@ -21,6 +21,8 @@
 CONFIG_CMD_FAT=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_GPIO_UNIPHIER=y
+CONFIG_MISC=y
+CONFIG_I2C_EEPROM=y
 CONFIG_MMC_UNIPHIER=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
diff --git a/configs/warp7_defconfig b/configs/warp7_defconfig
index 102b5b1..617e0a0 100644
--- a/configs/warp7_defconfig
+++ b/configs/warp7_defconfig
@@ -1,10 +1,10 @@
 CONFIG_ARM=y
 CONFIG_ARCH_MX7=y
 CONFIG_TARGET_WARP7=y
+# CONFIG_ARMV7_VIRT is not set
 CONFIG_IMX_RDC=y
 CONFIG_IMX_BOOTAUX=y
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/warp7/imximage.cfg"
-CONFIG_BOOTDELAY=1
 CONFIG_HUSH_PARSER=y
 # CONFIG_CMD_BOOTD is not set
 CONFIG_CMD_BOOTZ=y
@@ -23,4 +23,13 @@
 CONFIG_CMD_EXT4=y
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
+CONFIG_USB=y
+CONFIG_USB_GADGET=y
+CONFIG_CI_UDC=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_G_DNL_MANUFACTURER="FSL"
+CONFIG_G_DNL_VENDOR_NUM=0x0525
+CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
+CONFIG_USB_EHCI_HCD=y
+CONFIG_MXC_USB_OTG_HACTIVE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/xilinx_zynqmp_ep_defconfig b/configs/xilinx_zynqmp_ep_defconfig
index 7325f19..c975c14 100644
--- a/configs/xilinx_zynqmp_ep_defconfig
+++ b/configs/xilinx_zynqmp_ep_defconfig
@@ -2,15 +2,15 @@
 CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_ep"
 CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_MALLOC_F_LEN=0x8000
-CONFIG_DM_I2C=y
-CONFIG_DM_GPIO=y
 CONFIG_ZYNQMP_USB=y
+CONFIG_DM_GPIO=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-ep108"
+CONFIG_SPL=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
-CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_CONSOLE is not set
@@ -41,12 +41,16 @@
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_SPL_OF_CONTROL=y
 CONFIG_OF_EMBED=y
 CONFIG_NET_RANDOM_ETHADDR=y
-CONFIG_CLK=y
-CONFIG_SPL_CLK=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_BLK=y
+CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_CADENCE=y
 CONFIG_DM_MMC=y
+CONFIG_DM_MMC_OPS=y
 CONFIG_ZYNQ_SDHCI=y
 CONFIG_NAND_ARASAN=y
 CONFIG_SPI_FLASH=y
@@ -63,6 +67,7 @@
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GADGET=y
+CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_G_DNL_MANUFACTURER="Xilinx"
diff --git a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
index 91af8ce..52eb8c9 100644
--- a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
@@ -2,15 +2,15 @@
 CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zc1751_xm015_dc1"
 CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_MALLOC_F_LEN=0x8000
-CONFIG_DM_I2C=y
-CONFIG_DM_GPIO=y
 CONFIG_ZYNQMP_USB=y
+CONFIG_DM_GPIO=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm015-dc1"
+CONFIG_SPL=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
-CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_IMLS is not set
@@ -32,12 +32,16 @@
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_SPL_OF_CONTROL=y
 CONFIG_OF_EMBED=y
 CONFIG_NET_RANDOM_ETHADDR=y
-CONFIG_CLK=y
-CONFIG_SPL_CLK=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_BLK=y
+CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_CADENCE=y
 CONFIG_DM_MMC=y
+CONFIG_DM_MMC_OPS=y
 CONFIG_ZYNQ_SDHCI=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
@@ -58,6 +62,7 @@
 CONFIG_USB_DWC3_GADGET=y
 CONFIG_USB_ULPI_VIEWPORT=y
 CONFIG_USB_ULPI=y
+CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_G_DNL_MANUFACTURER="Xilinx"
diff --git a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
index 3e73312..928806b 100644
--- a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
@@ -2,15 +2,15 @@
 CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zc1751_xm016_dc2"
 CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_MALLOC_F_LEN=0x8000
-CONFIG_DM_I2C=y
-CONFIG_DM_GPIO=y
 CONFIG_ZYNQMP_USB=y
+CONFIG_DM_GPIO=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm016-dc2"
+CONFIG_SPL=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
-CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_IMLS is not set
@@ -32,12 +32,16 @@
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_SPL_OF_CONTROL=y
 CONFIG_OF_EMBED=y
 CONFIG_NET_RANDOM_ETHADDR=y
-CONFIG_CLK=y
-CONFIG_SPL_CLK=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_BLK=y
+CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_CADENCE=y
 CONFIG_DM_MMC=y
+CONFIG_DM_MMC_OPS=y
 CONFIG_NAND_ARASAN=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
@@ -56,6 +60,7 @@
 CONFIG_USB_DWC3_GADGET=y
 CONFIG_USB_ULPI_VIEWPORT=y
 CONFIG_USB_ULPI=y
+CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_G_DNL_MANUFACTURER="Xilinx"
diff --git a/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig b/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig
index 2805219..6a648da 100644
--- a/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig
@@ -2,14 +2,14 @@
 CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zc1751_xm018_dc4"
 CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_MALLOC_F_LEN=0x8000
-CONFIG_DM_I2C=y
 CONFIG_DM_GPIO=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm018-dc4"
+CONFIG_SPL=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
-CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_IMLS is not set
@@ -28,12 +28,16 @@
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_SPL_OF_CONTROL=y
 CONFIG_OF_EMBED=y
 CONFIG_NET_RANDOM_ETHADDR=y
-CONFIG_CLK=y
-CONFIG_SPL_CLK=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_BLK=y
+CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_CADENCE=y
 CONFIG_DM_MMC=y
+CONFIG_DM_MMC_OPS=y
 CONFIG_ZYNQ_SDHCI=y
 CONFIG_DM_ETH=y
 CONFIG_ZYNQ_GEM=y
diff --git a/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig b/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig
index 32bea4b..c6521e8 100644
--- a/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig
@@ -2,14 +2,14 @@
 CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zc1751_xm019_dc5"
 CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_MALLOC_F_LEN=0x8000
-CONFIG_DM_I2C=y
 CONFIG_DM_GPIO=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm019-dc5"
+CONFIG_SPL=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
-CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_IMLS is not set
@@ -28,11 +28,15 @@
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_SPL_OF_CONTROL=y
 CONFIG_OF_EMBED=y
-CONFIG_CLK=y
-CONFIG_SPL_CLK=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_BLK=y
+CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_CADENCE=y
 CONFIG_DM_MMC=y
+CONFIG_DM_MMC_OPS=y
 CONFIG_ZYNQ_SDHCI=y
 CONFIG_DM_ETH=y
 CONFIG_EFI_LOADER_BOUNCE_BUFFER=y
diff --git a/configs/xilinx_zynqmp_zcu102_defconfig b/configs/xilinx_zynqmp_zcu102_defconfig
index d7eb8c2..f0378fe 100644
--- a/configs/xilinx_zynqmp_zcu102_defconfig
+++ b/configs/xilinx_zynqmp_zcu102_defconfig
@@ -2,14 +2,15 @@
 CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zcu102"
 CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_MALLOC_F_LEN=0x8000
-CONFIG_DM_GPIO=y
 CONFIG_ZYNQMP_USB=y
+CONFIG_DM_GPIO=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102"
+CONFIG_SPL=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
-CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_IMLS is not set
@@ -31,11 +32,14 @@
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_SPL_OF_CONTROL=y
 CONFIG_OF_EMBED=y
 CONFIG_NET_RANDOM_ETHADDR=y
-CONFIG_CLK=y
-CONFIG_SPL_CLK=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_BLK=y
 CONFIG_DM_MMC=y
+CONFIG_DM_MMC_OPS=y
 CONFIG_ZYNQ_SDHCI=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
@@ -56,6 +60,7 @@
 CONFIG_USB_DWC3_GADGET=y
 CONFIG_USB_ULPI_VIEWPORT=y
 CONFIG_USB_ULPI=y
+CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_G_DNL_MANUFACTURER="Xilinx"
diff --git a/configs/xilinx_zynqmp_zcu102_revB_defconfig b/configs/xilinx_zynqmp_zcu102_revB_defconfig
index 80a59ef..cb810cf 100644
--- a/configs/xilinx_zynqmp_zcu102_revB_defconfig
+++ b/configs/xilinx_zynqmp_zcu102_revB_defconfig
@@ -2,14 +2,15 @@
 CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zcu102"
 CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_MALLOC_F_LEN=0x8000
-CONFIG_DM_GPIO=y
 CONFIG_ZYNQMP_USB=y
+CONFIG_DM_GPIO=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102-revB"
+CONFIG_SPL=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
-CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_IMLS is not set
@@ -31,11 +32,14 @@
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_SPL_OF_CONTROL=y
 CONFIG_OF_EMBED=y
 CONFIG_NET_RANDOM_ETHADDR=y
-CONFIG_CLK=y
-CONFIG_SPL_CLK=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_BLK=y
 CONFIG_DM_MMC=y
+CONFIG_DM_MMC_OPS=y
 CONFIG_ZYNQ_SDHCI=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
@@ -56,6 +60,7 @@
 CONFIG_USB_DWC3_GADGET=y
 CONFIG_USB_ULPI_VIEWPORT=y
 CONFIG_USB_ULPI=y
+CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_G_DNL_MANUFACTURER="Xilinx"
diff --git a/configs/xtfpga_defconfig b/configs/xtfpga_defconfig
new file mode 100644
index 0000000..535850c
--- /dev/null
+++ b/configs/xtfpga_defconfig
@@ -0,0 +1,22 @@
+CONFIG_XTENSA=y
+CONFIG_SYS_CPU="dc233c"
+CONFIG_XTFPGA_KC705=y
+CONFIG_BOOTDELAY=10
+CONFIG_SYS_PROMPT="U-Boot> "
+CONFIG_AUTOBOOT_KEYED=y
+CONFIG_AUTOBOOT_PROMPT="Autobooting in %d seconds, press <SPACE> to stop\n"
+CONFIG_AUTOBOOT_STOP_STR=" "
+CONFIG_CMD_ASKENV=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_PING=y
+CONFIG_DM=y
+# CONFIG_DM_WARN is not set
+# CONFIG_DM_DEVICE_REMOVE is not set
+# CONFIG_DM_STDIO is not set
+# CONFIG_DM_SEQ_ALIAS is not set
+CONFIG_SYSRESET=y
+CONFIG_DM_ETH=y
+CONFIG_PHYLIB=y
+CONFIG_ETHOC=y
+CONFIG_SYS_NS16550=y
+CONFIG_OF_LIBFDT=y
diff --git a/configs/zc5202_defconfig b/configs/zc5202_defconfig
new file mode 100644
index 0000000..2ebeec0
--- /dev/null
+++ b/configs/zc5202_defconfig
@@ -0,0 +1,22 @@
+CONFIG_ARM=y
+CONFIG_ARCH_MX6=y
+CONFIG_TARGET_ZC5202=y
+CONFIG_SPL=y
+CONFIG_BOOTDELAY=3
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,MX6Q"
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_OF_LIBFDT=y
diff --git a/configs/zc5601_defconfig b/configs/zc5601_defconfig
new file mode 100644
index 0000000..a52ae6f
--- /dev/null
+++ b/configs/zc5601_defconfig
@@ -0,0 +1,22 @@
+CONFIG_ARM=y
+CONFIG_ARCH_MX6=y
+CONFIG_TARGET_ZC5601=y
+CONFIG_SPL=y
+CONFIG_BOOTDELAY=3
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,MX6Q"
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_OF_LIBFDT=y
diff --git a/configs/zynq_microzed_defconfig b/configs/zynq_microzed_defconfig
index d88c61b..3bb090a 100644
--- a/configs/zynq_microzed_defconfig
+++ b/configs/zynq_microzed_defconfig
@@ -1,12 +1,11 @@
 CONFIG_ARM=y
-CONFIG_SYS_CONFIG_NAME="zynq_microzed"
 CONFIG_ARCH_ZYNQ=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-microzed"
 CONFIG_SPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_FIT_SIGNATURE=y
-CONFIG_BOOTDELAY=3
+CONFIG_SYS_NO_FLASH=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="Zynq> "
 # CONFIG_CMD_IMLS is not set
@@ -38,8 +37,10 @@
 CONFIG_ZYNQ_GEM=y
 CONFIG_ZYNQ_QSPI=y
 CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_ULPI_VIEWPORT=y
 CONFIG_USB_ULPI=y
+CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
diff --git a/configs/zynq_picozed_defconfig b/configs/zynq_picozed_defconfig
index aeb1270..5416141 100644
--- a/configs/zynq_picozed_defconfig
+++ b/configs/zynq_picozed_defconfig
@@ -1,9 +1,8 @@
 CONFIG_ARM=y
-CONFIG_SYS_CONFIG_NAME="zynq_picozed"
 CONFIG_ARCH_ZYNQ=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-picozed"
 CONFIG_SPL=y
-CONFIG_BOOTDELAY=3
+CONFIG_SYS_NO_FLASH=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="Zynq> "
 # CONFIG_CMD_IMLS is not set
@@ -28,8 +27,10 @@
 CONFIG_ZYNQ_SDHCI=y
 CONFIG_ZYNQ_GEM=y
 CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_ULPI_VIEWPORT=y
 CONFIG_USB_ULPI=y
+CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
diff --git a/configs/zynq_zc702_defconfig b/configs/zynq_zc702_defconfig
index d68ed0e..817ccc1 100644
--- a/configs/zynq_zc702_defconfig
+++ b/configs/zynq_zc702_defconfig
@@ -6,7 +6,7 @@
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_FIT_SIGNATURE=y
-CONFIG_BOOTDELAY=3
+CONFIG_SYS_NO_FLASH=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="Zynq> "
 # CONFIG_CMD_IMLS is not set
@@ -43,8 +43,10 @@
 CONFIG_DEBUG_UART_CLOCK=50000000
 CONFIG_ZYNQ_QSPI=y
 CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_ULPI_VIEWPORT=y
 CONFIG_USB_ULPI=y
+CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
diff --git a/configs/zynq_zc706_defconfig b/configs/zynq_zc706_defconfig
index 8bd9230..d9c1d64 100644
--- a/configs/zynq_zc706_defconfig
+++ b/configs/zynq_zc706_defconfig
@@ -6,7 +6,7 @@
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_FIT_SIGNATURE=y
-CONFIG_BOOTDELAY=3
+CONFIG_SYS_NO_FLASH=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="Zynq> "
 # CONFIG_CMD_IMLS is not set
@@ -39,8 +39,10 @@
 CONFIG_ZYNQ_GEM=y
 CONFIG_ZYNQ_QSPI=y
 CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_ULPI_VIEWPORT=y
 CONFIG_USB_ULPI=y
+CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
diff --git a/configs/zynq_zc770_xm010_defconfig b/configs/zynq_zc770_xm010_defconfig
index 81f16ec..9664b92 100644
--- a/configs/zynq_zc770_xm010_defconfig
+++ b/configs/zynq_zc770_xm010_defconfig
@@ -1,5 +1,4 @@
 CONFIG_ARM=y
-CONFIG_SYS_CONFIG_NAME="zynq_zc770"
 CONFIG_ARCH_ZYNQ=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm010"
 CONFIG_SPL=y
@@ -7,7 +6,7 @@
 CONFIG_FIT_VERBOSE=y
 CONFIG_FIT_SIGNATURE=y
 CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM010"
-CONFIG_BOOTDELAY=3
+CONFIG_SYS_NO_FLASH=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="Zynq> "
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/zynq_zc770_xm011_defconfig b/configs/zynq_zc770_xm011_defconfig
index 271fcfd..98a348e 100644
--- a/configs/zynq_zc770_xm011_defconfig
+++ b/configs/zynq_zc770_xm011_defconfig
@@ -1,5 +1,4 @@
 CONFIG_ARM=y
-CONFIG_SYS_CONFIG_NAME="zynq_zc770"
 CONFIG_ARCH_ZYNQ=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm011"
 CONFIG_SPL=y
@@ -7,7 +6,7 @@
 CONFIG_FIT_VERBOSE=y
 CONFIG_FIT_SIGNATURE=y
 CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM011"
-CONFIG_BOOTDELAY=3
+CONFIG_SYS_NO_FLASH=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="Zynq> "
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/zynq_zc770_xm012_defconfig b/configs/zynq_zc770_xm012_defconfig
index a9ea971..00e2e6f 100644
--- a/configs/zynq_zc770_xm012_defconfig
+++ b/configs/zynq_zc770_xm012_defconfig
@@ -1,5 +1,4 @@
 CONFIG_ARM=y
-CONFIG_SYS_CONFIG_NAME="zynq_zc770"
 CONFIG_ARCH_ZYNQ=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm012"
 CONFIG_SPL=y
@@ -7,7 +6,6 @@
 CONFIG_FIT_VERBOSE=y
 CONFIG_FIT_SIGNATURE=y
 CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM012"
-CONFIG_BOOTDELAY=3
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="Zynq> "
 CONFIG_CMD_GPIO=y
diff --git a/configs/zynq_zc770_xm013_defconfig b/configs/zynq_zc770_xm013_defconfig
index 56062b1..1b78fdf 100644
--- a/configs/zynq_zc770_xm013_defconfig
+++ b/configs/zynq_zc770_xm013_defconfig
@@ -1,5 +1,4 @@
 CONFIG_ARM=y
-CONFIG_SYS_CONFIG_NAME="zynq_zc770"
 CONFIG_ARCH_ZYNQ=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm013"
 CONFIG_SPL=y
@@ -7,7 +6,7 @@
 CONFIG_FIT_VERBOSE=y
 CONFIG_FIT_SIGNATURE=y
 CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM013"
-CONFIG_BOOTDELAY=3
+CONFIG_SYS_NO_FLASH=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="Zynq> "
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/zynq_zed_defconfig b/configs/zynq_zed_defconfig
index c70b860..22d3419 100644
--- a/configs/zynq_zed_defconfig
+++ b/configs/zynq_zed_defconfig
@@ -1,12 +1,11 @@
 CONFIG_ARM=y
-CONFIG_SYS_CONFIG_NAME="zynq_zed"
 CONFIG_ARCH_ZYNQ=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zed"
 CONFIG_SPL=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_FIT_SIGNATURE=y
-CONFIG_BOOTDELAY=3
+CONFIG_SYS_NO_FLASH=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="Zynq> "
 # CONFIG_CMD_IMLS is not set
@@ -38,8 +37,10 @@
 CONFIG_ZYNQ_GEM=y
 CONFIG_ZYNQ_QSPI=y
 CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_ULPI_VIEWPORT=y
 CONFIG_USB_ULPI=y
+CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
diff --git a/configs/zynq_zybo_defconfig b/configs/zynq_zybo_defconfig
index 624545e..4b85cdb 100644
--- a/configs/zynq_zybo_defconfig
+++ b/configs/zynq_zybo_defconfig
@@ -6,7 +6,7 @@
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_FIT_SIGNATURE=y
-CONFIG_BOOTDELAY=3
+CONFIG_SYS_NO_FLASH=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="Zynq> "
 # CONFIG_CMD_IMLS is not set
@@ -41,8 +41,10 @@
 CONFIG_DEBUG_UART_CLOCK=50000000
 CONFIG_ZYNQ_QSPI=y
 CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_ULPI_VIEWPORT=y
 CONFIG_USB_ULPI=y
+CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
diff --git a/disk/part_efi.c b/disk/part_efi.c
index 0af1e92..8d67c09 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -655,6 +655,10 @@
 		      (unsigned long long)partitions[i].size);
 
 		if (le64_to_cpu(gpt_part_size) != partitions[i].size) {
+			/* We do not check the extend partition size */
+			if ((i == parts - 1) && (partitions[i].size == 0))
+				continue;
+
 			error("Partition %s size: %llu does not match %llu!\n",
 			      efi_str, (unsigned long long)gpt_part_size,
 			      (unsigned long long)partitions[i].size);
@@ -886,9 +890,10 @@
 	count = le32_to_cpu(pgpt_head->num_partition_entries) *
 		le32_to_cpu(pgpt_head->sizeof_partition_entry);
 
-	debug("%s: count = %u * %u = %zu\n", __func__,
+	debug("%s: count = %u * %u = %lu\n", __func__,
 	      (u32) le32_to_cpu(pgpt_head->num_partition_entries),
-	      (u32) le32_to_cpu(pgpt_head->sizeof_partition_entry), count);
+	      (u32) le32_to_cpu(pgpt_head->sizeof_partition_entry),
+	      (ulong)count);
 
 	/* Allocate memory for PTE, remember to FREE */
 	if (count != 0) {
@@ -897,9 +902,8 @@
 	}
 
 	if (count == 0 || pte == NULL) {
-		printf("%s: ERROR: Can't allocate 0x%zX "
-		       "bytes for GPT Entries\n",
-			__func__, count);
+		printf("%s: ERROR: Can't allocate %#lX bytes for GPT Entries\n",
+		       __func__, (ulong)count);
 		return NULL;
 	}
 
diff --git a/disk/part_iso.c b/disk/part_iso.c
index 9f5c50c..f9a741d 100644
--- a/disk/part_iso.c
+++ b/disk/part_iso.c
@@ -233,13 +233,13 @@
 	disk_partition_t info;
 	int i;
 
-	if (part_get_info_iso_verb(dev_desc, 0, &info, 0) == -1) {
+	if (part_get_info_iso_verb(dev_desc, 1, &info, 0) == -1) {
 		printf("** No boot partition found on device %d **\n",
 		       dev_desc->devnum);
 		return;
 	}
 	printf("Part   Start     Sect x Size Type\n");
-	i=0;
+	i=1;
 	do {
 		printf(" %2d " LBAFU " " LBAFU " %6ld %.32s\n",
 		       i, info.start, info.size, info.blksz, info.type);
diff --git a/doc/README.fec_mxc b/doc/README.fec_mxc
index ed7e47d..9ca6ac2 100644
--- a/doc/README.fec_mxc
+++ b/doc/README.fec_mxc
@@ -27,6 +27,11 @@
 	Optional, selects the exact phy address that should be connected
 	and function fecmxc_initialize will try to initialize it.
 
+CONFIG_FEC_FIXED_SPEED
+	Optional, selects a fixed speed on the MAC interface without asking some
+	phy. This is usefull if there is a direct MAC <-> MAC connection, for
+	example if the CPU is connected directly via the RGMII interface to a
+	ethernet-switch.
 
 Reading the ethaddr from the SoC eFuses:
 if CONFIG_FEC_MXC is defined and the U-Boot environment does not contain the
diff --git a/doc/README.gpt b/doc/README.gpt
index a6f6de6..3fcd835 100644
--- a/doc/README.gpt
+++ b/doc/README.gpt
@@ -165,7 +165,7 @@
    The fields 'name' and 'size' are mandatory for every partition.
    The field 'start' is optional.
 
-   If field 'size' of the last partition is 0, the partiton is extended
+   If field 'size' of the last partition is 0, the partition is extended
    up to the end of the device.
 
    The fields 'uuid' and 'uuid_disk' are optional if CONFIG_RANDOM_UUID is
diff --git a/doc/README.rockchip b/doc/README.rockchip
index e0572c8..69b926c 100644
--- a/doc/README.rockchip
+++ b/doc/README.rockchip
@@ -36,11 +36,15 @@
 Building
 ========
 
-At present three RK3288 boards are supported:
+At present seven RK3288 boards are supported:
 
+   - EVB RK3288 - use evb-rk3288 configuration
+   - Fennec RK3288 - use fennec-rk3288 configuration
    - Firefly RK3288 - use firefly-rk3288 configuration
-   - Radxa Rock 2 - use rock2 configuration
    - Hisense Chromebook - use chromebook_jerry configuration
+   - Miniarm RK3288 - use miniarm-rk3288 configuration
+   - PopMetal RK3288 - use popmetal-rk3288 configuration
+   - Radxa Rock 2 - use rock2 configuration
 
 Two RK3036 board are supported:
 
@@ -119,6 +123,20 @@
    Hit any key to stop autoboot:  0
    =>
 
+The rockchip bootrom can load and boot an initial spl, then continue to
+load a second-level bootloader(ie. U-BOOT) as soon as it returns to bootrom.
+Therefore RK3288 has another loading sequence like RK3036. The option of
+U-Boot is controlled with this setting in U-Boot:
+
+	#define CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+
+You can create the image via the following operations:
+
+   ./firefly-rk3288/tools/mkimage -n rk3288 -T rksd -d \
+	firefly-rk3288/spl/u-boot-spl-dtb.bin out && \
+   cat firefly-rk3288/u-boot-dtb.bin >> out && \
+   sudo dd if=out of=/dev/sdc seek=64
+
 If you have an HDMI cable attached you should see a video console.
 
 For evb_rk3036 board:
@@ -129,6 +147,32 @@
 Note: rk3036 SDMMC and debug uart use the same iomux, so if you boot from SD, the
       debug uart must be disabled
 
+Using fastboot on rk3288
+========================
+- Define GPT partition layout like kylin_rk3036(see include/configs/kylin_rk3036.h)
+- Write GPT partition layout to mmc device which fastboot want to use it to
+store the image
+
+        => gpt write mmc 1 $partitions
+
+- Invoke fastboot command to prepare
+
+        => fastboot 1
+
+- Start fastboot request on PC
+
+        fastboot -i 0x2207 flash loader evb-rk3288/spl/u-boot-spl-dtb.bin
+
+You should see something like:
+
+        => fastboot 1
+        WARNING: unknown variable: partition-type:loader
+        Starting download of 357796 bytes
+        ..
+        downloading of 357796 bytes finished
+        Flashing Raw Image
+        ........ wrote 357888 bytes to 'loader'
+
 Booting from SPI
 ================
 
diff --git a/doc/README.scrapyard b/doc/README.scrapyard
index b7cf62d..200f670 100644
--- a/doc/README.scrapyard
+++ b/doc/README.scrapyard
@@ -3,7 +3,7 @@
 negligence in combination with ordinary bitrot.  Sometimes this goes
 by unnoticed, but often build errors will result.  If nobody cares any
 more to resolve such problems, then the code is really dead and will
-be removed from the U-Boot source tree.  The remainders rest in piece
+be removed from the U-Boot source tree.  The remainders rest in peace
 in the imperishable depths of the git history.  This document tries to
 maintain a list of such former fellows, so archaeologists can check
 easily if there is something they might want to dig for...
diff --git a/doc/README.sha1 b/doc/README.sha1
index f6cca40..f178f37 100644
--- a/doc/README.sha1
+++ b/doc/README.sha1
@@ -51,7 +51,8 @@
 
 Now you have a U-Boot-Image for the pcs440ep board with the correct SHA1 sum.
 
-If you do a "./MAKEALL pcs440ep" or a "make all" to get the U-Boot image,
-the correct SHA1 sum will be automagically included in the U-Boot image.
+If you do a "buildman -k pcs440ep" or a "make all" to get the U-Boot image,
+which will be found in ../current/ipam390/ - the correct SHA1 sum will be
+automagically included in the U-Boot image.
 
 Heiko Schocher, 11 Jul 2007
diff --git a/doc/README.ti-secure b/doc/README.ti-secure
index 7fc9b9b..54c996d 100644
--- a/doc/README.ti-secure
+++ b/doc/README.ti-secure
@@ -19,69 +19,80 @@
 package is viewable and downloadable. Contact TI, either online or by way
 of a local TI representative, to request access.
 
-When CONFIG_TI_SECURE_DEVICE is set, the U-Boot SPL build process requires
-the presence and use of these tools in order to create a viable boot image.
-The build process will look for the environment variable TI_SECURE_DEV_PKG,
-which should be the path of the installed SECDEV package. If the
-TI_SECURE_DEV_PKG variable is not defined or if it is defined but doesn't
-point to a valid SECDEV package, a warning is issued during the build to
-indicate that a final secure bootable image was not created.
+Booting of U-Boot SPL
+=====================
 
-Within the SECDEV package exists an image creation script:
+	When CONFIG_TI_SECURE_DEVICE is set, the U-Boot SPL build process
+	requires the presence and use of these tools in order to create a
+	viable boot image. The build process will look for the environment
+	variable TI_SECURE_DEV_PKG, which should be the path of the installed
+	SECDEV package. If the TI_SECURE_DEV_PKG variable is not defined or
+	if it is defined but doesn't point to a valid SECDEV package, a
+	warning is issued during the build to indicate that a final secure
+	bootable image was not created.
 
-${TI_SECURE_DEV_PKG}/scripts/create-boot-image.sh
+	Within the SECDEV package exists an image creation script:
 
-This is called as part of the SPL/u-boot build process. As the secure boot
-image formats and requirements differ between secure SOC from TI, the
-purpose of this script is to abstract these details as much as possible.
+	${TI_SECURE_DEV_PKG}/scripts/create-boot-image.sh
 
-The script is basically the only required interface to the TI SECDEV package
-for secure TI devices.
+	This is called as part of the SPL/u-boot build process. As the secure
+	boot image formats and requirements differ between secure SOC from TI,
+	the purpose of this script is to abstract these details as much as
+	possible.
 
-Invoking the script for AM43xx Secure Devices
-=============================================
+	The script is basically the only required interface to the TI SECDEV
+	package for creating a bootable SPL image for secure TI devices.
 
-create-boot-image.sh <IMAGE_FLAG> <INPUT_FILE> <OUTPUT_FILE> <SPL_LOAD_ADDR>
+	Invoking the script for AM43xx Secure Devices
+	=============================================
 
-<IMAGE_FLAG> is a value that specifies the type of the image to generate OR
-the action the image generation tool will take. Valid values are:
-	SPI_X-LOADER - Generates an image for SPI flash (byte swapped)
-	XIP_X-LOADER - Generates a single stage u-boot for NOR/QSPI XiP
-	ISSW - Generates an image for all other boot modes
+	create-boot-image.sh \
+		<IMAGE_FLAG> <INPUT_FILE> <OUTPUT_FILE> <SPL_LOAD_ADDR>
 
-<INPUT_FILE> is the full path and filename of the public world boot loader
-binary file (depending on the boot media, this is usually either
-u-boot-spl.bin or u-boot.bin).
+	<IMAGE_FLAG> is a value that specifies the type of the image to
+	generate OR the action the image generation tool will take. Valid
+	values are:
+		SPI_X-LOADER - Generates an image for SPI flash (byte
+			swapped)
+		XIP_X-LOADER - Generates a single stage u-boot for
+			NOR/QSPI XiP
+		ISSW - Generates an image for all other boot modes
 
-<OUTPUT_FILE> is the full path and filename of the final secure image. The
-output binary images should be used in place of the standard non-secure
-binary images (see the platform-specific user's guides and releases notes
-for how the non-secure images are typically used)
+	<INPUT_FILE> is the full path and filename of the public world boot
+	loaderbinary file (depending on the boot media, this is usually
+	either u-boot-spl.bin or u-boot.bin).
+
+	<OUTPUT_FILE> is the full path and filename of the final secure
+	image. The output binary images should be used in place of the standard
+	non-secure binary images (see the platform-specific user's guides and
+	releases notes for how the non-secure images are typically used)
 	u-boot-spl_HS_SPI_X-LOADER - byte swapped boot image for SPI flash
 	u-boot_HS_XIP_X-LOADER - boot image for NOR or QSPI flash
 	u-boot-spl_HS_ISSW - boot image for all other boot media
 
-<SPL_LOAD_ADDR> is the address at which SOC ROM should load the <INPUT_FILE>
+	<SPL_LOAD_ADDR> is the address at which SOC ROM should load the
+	<INPUT_FILE>
 
-Invoking the script for DRA7xx/AM57xx Secure Devices
-====================================================
+	Invoking the script for DRA7xx/AM57xx Secure Devices
+	====================================================
 
-create-boot-image.sh <IMAGE_TYPE> <INPUT_FILE> <OUTPUT_FILE>
+	create-boot-image.sh <IMAGE_TYPE> <INPUT_FILE> <OUTPUT_FILE>
 
-<IMAGE_TYPE> is a value that specifies the type of the image to generate OR
-the action the image generation tool will take. Valid values are:
-	X-LOADER - Generates an image for NOR or QSPI boot modes
-	MLO - Generates an image for SD/MMC/eMMC boot modes
-	ULO - Generates an image for USB/UART peripheral boot modes
-	Note: ULO is not yet used by the u-boot build process
+	<IMAGE_TYPE> is a value that specifies the type of the image to
+	generate OR the action the image generation tool will take. Valid
+	values are:
+		X-LOADER - Generates an image for NOR or QSPI boot modes
+		MLO - Generates an image for SD/MMC/eMMC boot modes
+		ULO - Generates an image for USB/UART peripheral boot modes
+		Note: ULO is not yet used by the u-boot build process
 
-<INPUT_FILE> is the full path and filename of the public world boot loader
-binary file (for this platform, this is always u-boot-spl.bin).
+	<INPUT_FILE> is the full path and filename of the public world boot
+	loader binary file (for this platform, this is always u-boot-spl.bin).
 
-<OUTPUT_FILE> is the full path and filename of the final secure image. The
-output binary images should be used in place of the standard non-secure
-binary images (see the platform-specific user's guides and releases notes
-for how the non-secure images are typically used)
+	<OUTPUT_FILE> is the full path and filename of the final secure image.
+	The output binary images should be used in place of the standard
+	non-secure binary images (see the platform-specific user's guides
+	and releases notes for how the non-secure images are typically used)
 	u-boot-spl_HS_MLO - boot image for SD/MMC/eMMC. This image is
 		copied to a file named MLO, which is the name that
 		the device ROM bootloader requires for loading from
@@ -89,3 +100,61 @@
 		non-secure devices)
 	u-boot-spl_HS_X-LOADER - boot image for all other flash memories
 		including QSPI and NOR flash
+
+Booting of Primary U-Boot (u-boot.img)
+======================================
+
+	The SPL image is responsible for loading the next stage boot loader,
+	which is the main u-boot image. For secure TI devices, the SPL will
+	be authenticated, as described above, as part of the particular
+	device's ROM boot process. In order to continue the secure boot
+	process, the authenticated SPL must authenticate the main u-boot
+	image that it loads.
+
+	The configurations for secure TI platforms are written to make the boot
+	process use the FIT image format for the u-boot.img (CONFIG_SPL_FRAMEWORK
+	and CONFIG_SPL_LOAD_FIT). With these configurations the binary
+	components that the SPL loads include a specific DTB image and u-boot
+	image. These DTB image may be one of many available to the boot
+	process. In order to secure these components so that they can be
+	authenticated by the SPL as they are loaded from the FIT image,	the
+	build procedure for secure TI devices will secure these images before
+	they are integrated into the FIT image. When those images are extracted
+	from the FIT image at boot time, they are post-processed to verify that
+	they are still secure. The outlined security-related SPL post-processing
+	is enabled through the CONFIG_SPL_FIT_IMAGE_POST_PROCESS option which
+	must be enabled for the secure boot scheme to work. In order to allow
+	verifying proper operation of the secure boot chain in case of successful
+	authentication messages like "Authentication passed: CERT_U-BOOT-NOD" are
+	output by the SPL to the console for each blob that got extracted from the
+	FIT image. Note that the last part of this log message is the (truncated)
+	name of the signing certificate embedded into the blob that got processed.
+
+	The exact details of the how the images are secured is handled by the
+	SECDEV package. Within the SECDEV package exists a script to process
+	an input binary image:
+
+	${TI_SECURE_DEV_PKG}/scripts/secure-binary-image.sh
+
+	This is called as part of the u-boot build process. As the secure
+	image formats and requirements can differ between the various secure
+	SOCs from TI, this script in the SECDEV package abstracts these
+	details. This script is essentially the only required interface to the
+	TI SECDEV package for creating a u-boot.img image for secure TI
+	devices.
+
+	The SPL/u-boot code contains calls to dedicated secure ROM functions
+	to perform the validation on the secured images. The details of the
+	interface to those functions is shown in the code. The summary
+	is that they are accessed by invoking an ARM secure monitor call to
+	the device's secure ROM (fixed read-only-memory that is secure and
+	only accessible when the ARM core is operating in the secure mode).
+
+	Invoking the secure-binary-image script for Secure Devices
+	==========================================================
+
+	secure-binary-image.sh <INPUT_FILE> <OUTPUT_FILE>
+
+	<INPUT_FILE> is the full path and filename of the input binary image
+
+	<OUTPUT_FILE> is the full path and filename of the output secure image.
diff --git a/doc/README.ubispl b/doc/README.ubispl
new file mode 100644
index 0000000..ff008bc
--- /dev/null
+++ b/doc/README.ubispl
@@ -0,0 +1,141 @@
+Lightweight UBI and UBI fastmap support
+
+# Copyright (C) Thomas Gleixner <tglx@linutronix.de>
+#
+# SPDX-License-Identifier: GPL 2.0+ BSD-3-Clause
+
+Scans the UBI information and loads the requested static volumes into
+memory.
+
+Configuration Options:
+
+   CONFIG_SPL_UBI
+     Enables the SPL UBI support
+
+   CONFIG_SPL_UBI_MAX_VOL_LEBS
+     The maximum number of logical eraseblocks which a static volume
+     to load can contain. Used for sizing the scan data structure
+
+   CONFIG_SPL_UBI_MAX_PEB_SIZE
+     The maximum physical erase block size. Either a compile time
+     constant or runtime detection. Used for sizing the scan data
+     structure
+
+   CONFIG_SPL_UBI_MAX_PEBS
+     The maximum physical erase block count. Either a compile time
+     constant or runtime detection. Used for sizing the scan data
+     structure
+
+   CONFIG_SPL_UBI_VOL_IDS
+     The maximum volume ids which can be loaded. Used for sizing the
+     scan data structure.
+
+Usage notes:
+
+In the board config file define for example:
+
+#define CONFIG_SPL_UBI
+#define CONFIG_SPL_UBI_MAX_VOL_LEBS	256
+#define CONFIG_SPL_UBI_MAX_PEB_SIZE	(256*1024)
+#define CONFIG_SPL_UBI_MAX_PEBS		4096
+#define CONFIG_SPL_UBI_VOL_IDS		8
+
+The size requirement is roughly as follows:
+
+    2k for the basic data structure
+  + CONFIG_SPL_UBI_VOL_IDS * CONFIG_SPL_UBI_MAX_VOL_LEBS * 8
+  + CONFIG_SPL_UBI_MAX_PEBS * 64
+  + CONFIG_SPL_UBI_MAX_PEB_SIZE * UBI_FM_MAX_BLOCKS
+
+The last one is big, but I really don't care in that stage. Real world
+implementations only use the first couple of blocks, but the code
+handles up to UBI_FM_MAX_BLOCKS.
+
+Given the above configuration example the requirement is about 5M
+which is usually not a problem to reserve in the RAM along with the
+other areas like the kernel/dts load address.
+
+So something like this will do the trick:
+
+#define SPL_FINFO_ADDR			0x80800000
+#define SPL_DTB_LOAD_ADDR		0x81800000
+#define SPL_KERNEL_LOAD_ADDR		0x82000000
+
+In the board file, implement the following:
+
+static struct ubispl_load myvolumes[] = {
+	{
+		.vol_id		= 0,	/* kernel volume */
+		.load_addr	= (void *)SPL_KERNEL_LOAD_ADDR,
+	},
+	{
+		.vol_id		= 1,	/* DT blob */
+		.load_addr	= (void *)SPL_DTB_LOAD_ADDR,
+	}
+};
+
+int spl_start_uboot(void)
+{
+	struct ubispl_info info;
+
+	info.ubi = (struct ubi_scan_info *) SPL_FINFO_ADDR;
+	info.fastmap = 1;
+	info.read = nand_spl_read_flash;
+
+#if COMPILE_TIME_DEFINED
+	/*
+	 * MY_NAND_NR_SPL_PEBS is the number of physical erase blocks
+	 * in the FLASH which are reserved for the SPL. Think about
+	 * mtd partitions:
+	 *
+	 * part_spl { .start = 0, .end = 4 }
+	 * part_ubi { .start = 4, .end = NR_PEBS }
+	 */
+	info.peb_offset = MY_NAND_NR_SPL_PEBS;
+	info.peb_size = CONFIG_SYS_NAND_BLOCK_SIZE;
+	info.vid_offset = MY_NAND_UBI_VID_OFFS;
+	info.leb_start = MY_NAND_UBI_DATA_OFFS;
+	info.peb_count = MY_NAND_UBI_NUM_PEBS;
+#else
+	get_flash_info(&flash_info);
+	info.peb_offset = MY_NAND_NR_SPL_PEBS;
+	info.peb_size = flash_info.peb_size;
+
+	/*
+	 * The VID and Data offset depend on the capability of the
+	 * FLASH chip to do subpage writes.
+	 *
+	 * If the flash chip supports subpage writes, then the VID
+	 * header starts at the second subpage. So for 2k pages size
+	 * with 4 subpages the VID offset is 512. The DATA offset is 2k.
+	 *
+	 * If the flash chip does not support subpage writes then the
+	 * VID offset is FLASH_PAGE_SIZE and the DATA offset
+	 * 2 * FLASH_PAGE_SIZE
+	 */
+	info.vid_offset = flash_info.vid_offset;
+	info.leb_start = flash_info.data_offset;
+
+	/*
+	 * The flash reports the total number of erase blocks, so
+	 * we need to subtract the number of blocks which are reserved
+	 * for the SPL itself and not managed by UBI.
+	 */
+	info.peb_count = flash_info.peb_count - MY_NAND_NR_SPL_PEBS;
+#endif
+
+	ret = ubispl_load_volumes(&info, myvolumes, ARRAY_SIZE(myvolumes);
+
+	....
+
+}
+
+Note: you can load any payload that way. You can even load u-boot from
+UBI, so the only non UBI managed FLASH area is the one which is
+reserved for the SPL itself and read from the SoC ROM.
+
+And you can do fallback scenarios:
+
+    if (ubispl_load_volumes(&info, volumes0, ARRAY_SIZE(volumes0)))
+        if (ubispl_load_volumes(&info, volumes1, ARRAY_SIZE(volumes1)))
+	    ubispl_load_volumes(&info, vol_uboot, ARRAY_SIZE(vol_uboot));
diff --git a/doc/README.x86 b/doc/README.x86
index a548b54..ba5bb99 100644
--- a/doc/README.x86
+++ b/doc/README.x86
@@ -314,6 +314,10 @@
 
 Overall ROM image size is controlled by CONFIG_ROM_SIZE.
 
+Note that the debug version of the FSP is bigger in size. If this version
+is used, CONFIG_FSP_ADDR needs to be configured to 0xfffb0000 instead of
+the default value 0xfffc0000.
+
 ---
 
 Intel Galileo instructions for bare mode:
@@ -1020,8 +1024,6 @@
  * S3 (Suspend to RAM), S4 (Suspend to Disk).
 
 Features that are optional:
- * ACPI global NVS support. We may need it to simplify ASL code logic if
-   utilizing NVS variables. Most likely we will need this sooner or later.
  * Dynamic AML bytecodes insertion at run-time. We may need this to support
    SSDT table generation and DSDT fix up.
  * SMI support. Since U-Boot is a modern bootloader, we don't want to bring
@@ -1037,10 +1039,39 @@
 For other platform boards, ACPI support status can be checked by examining their
 board defconfig files to see if CONFIG_GENERATE_ACPI_TABLE is set to y.
 
+EFI Support
+-----------
+U-Boot supports booting as a 32-bit or 64-bit EFI payload, e.g. with UEFI.
+This is enabled with CONFIG_EFI_STUB. U-Boot can also run as an EFI
+application, with CONFIG_EFI_APP. The CONFIG_EFI_LOADER option, where U-Booot
+provides an EFI environment to the kernel (i.e. replaces UEFI completely but
+provides the same EFI run-time services) is not currently supported on x86.
+
+See README.efi for details of EFI support in U-Boot.
+
+64-bit Support
+--------------
+U-Boot supports booting a 64-bit kernel directly and is able to change to
+64-bit mode to do so. It also supports (with CONFIG_EFI_STUB) booting from
+both 32-bit and 64-bit UEFI. However, U-Boot itself is currently always built
+in 32-bit mode. Some access to the full memory range is provided with
+arch_phys_memset().
+
+The development work to make U-Boot itself run in 64-bit mode has not yet
+been attempted. The best approach would likely be to build a 32-bit SPL
+image for U-Boot, with CONFIG_SPL_BUILD. This could then handle the early CPU
+init in 16-bit and 32-bit mode, running the FSP and any other binaries that
+are needed. Then it could change to 64-bit model and jump to U-Boot proper.
+
+Given U-Boot's extensive 64-bit support this has not been a high priority,
+but it would be a nice addition.
+
 TODO List
 ---------
 - Audio
 - Chrome OS verified boot
+- Support for CONFIG_EFI_LOADER
+- Building U-Boot to run in 64-bit mode
 
 References
 ----------
diff --git a/doc/README.xtensa b/doc/README.xtensa
new file mode 100644
index 0000000..4068582
--- /dev/null
+++ b/doc/README.xtensa
@@ -0,0 +1,97 @@
+U-Boot for the Xtensa Architecture
+==================================
+
+Xtensa Architecture and Diamond Cores
+-------------------------------------
+
+Xtensa is a configurable processor architecture from Tensilica, Inc.
+Diamond Cores are pre-configured instances available for license and
+SoC cores in the same manner as ARM, MIPS, etc.
+
+Xtensa licensees create their own Xtensa cores with selected features
+and custom instructions, registers and co-processors. The custom core
+is configured with Tensilica tools and built with Tensilica's Xtensa
+Processor Generator.
+
+There are an effectively infinite number of CPUs in the Xtensa
+architecture family. It is, however, not feasible to support individual
+Xtensa CPUs in U-Boot. Therefore, there is only a single 'xtensa' CPU
+in the cpu tree of U-Boot.
+
+In the same manner as the Linux port to Xtensa, U-Boot adapts to an
+individual Xtensa core configuration using a set of macros provided with
+the particular core. This is part of what is known as the hardware
+abstraction layer (HAL). For the purpose of U-Boot, the HAL consists only
+of a few header files. These provide CPP macros that customize sources,
+Makefiles, and the linker script.
+
+
+Adding support for an additional processor configuration
+--------------------------------------------------------
+
+The header files for one particular processor configuration are inside
+a variant-specific directory located in the arch/xtensa/include/asm
+directory. The name of that directory starts with 'arch-' followed by
+the name for the processor configuration, for example, arch-dc233c for
+the Diamond DC233 processor.
+
+    core.h	Definitions for the core itself.
+
+The following files are part of the overlay but not used by U-Boot.
+
+    tie.h	Co-processors and custom extensions defined
+		in the Tensilica Instruction Extension (TIE)
+		language.
+    tie-asm.h	Assembly macros to access custom-defined registers
+		and states.
+
+
+Global Data Pointer, Exported Function Stubs, and the ABI
+---------------------------------------------------------
+
+To support standalone applications launched with the "go" command,
+U-Boot provides a jump table of entrypoints to exported functions
+(grep for EXPORT_FUNC). The implementation for Xtensa depends on
+which ABI (or function calling convention) is used.
+
+Windowed ABI presents unique difficulties with the approach based on
+keeping global data pointer in dedicated register. Because the register
+window rotates during a call, there is no register that is constantly
+available for the gd pointer. Therefore, on xtensa gd is a simple
+global variable. Another difficulty arises from the requirement to have
+an 'entry' at the beginning of a function, which rotates the register
+file and reserves a stack frame. This is an integral part of the
+windowed ABI implemented in hardware. It makes using a jump table to an
+arbitrary (separately compiled) function a bit tricky. Use of a simple
+wrapper is also very tedious due to the need to move all possible
+register arguments and adjust the stack to handle arguments that cannot
+be passed in registers. The most efficient approach is to have the jump
+table perform the 'entry' so as to pretend it's the start of the real
+function. This requires decoding the target function's 'entry'
+instruction to determine the stack frame size, and adjusting the stack
+pointer accordingly, then jumping into the target function just after
+the 'entry'. Decoding depends on the processor's endianness so uses the
+HAL. The implementation (12 instructions) is in examples/stubs.c.
+
+
+Access to Invalid Memory Addresses
+----------------------------------
+
+U-Boot does not check if memory addresses given as arguments to commands
+such as "md" are valid. There are two possible types of invalid
+addresses: an area of physical address space may not be mapped to RAM
+or peripherals, or in the presence of MMU an area of virtual address
+space may not be mapped to physical addresses.
+
+Accessing first type of invalid addresses may result in hardware lockup,
+reading of meaningless data, written data being ignored or an exception,
+depending on the CPU wiring to the system. Accessing second type of
+invalid addresses always ends with an exception.
+
+U-Boot for Xtensa provides a special memory exception handler that
+reports such access attempts and resets the board.
+
+
+------------------------------------------------------------------------------
+Chris Zankel
+Ross Morley
diff --git a/doc/SPL/README.spl-secure-boot b/doc/SPL/README.spl-secure-boot
new file mode 100644
index 0000000..f2f8d78
--- /dev/null
+++ b/doc/SPL/README.spl-secure-boot
@@ -0,0 +1,18 @@
+Overview of SPL verified boot on powerpc/mpc85xx & arm/layerscape platforms
+===========================================================================
+
+Introduction
+------------
+
+This document provides an overview of how SPL verified boot works on powerpc/
+mpc85xx & arm/layerscape platforms.
+
+Methodology
+-----------
+
+The SPL image is responsible for loading the next stage boot loader, which is
+the main u-boot image. For secure boot process on these platforms ROM verifies
+SPL image, so to continue chain of trust SPL image verifies U-boot image using
+spl_validate_uboot(). This function uses QorIQ Trust Architecture header
+(appended to U-boot image) to validate the U-boot binary just before passing
+control to it.
diff --git a/doc/device-tree-bindings/firmware/nvidia,tegra186-bpmp.txt b/doc/device-tree-bindings/firmware/nvidia,tegra186-bpmp.txt
new file mode 100644
index 0000000..447252e
--- /dev/null
+++ b/doc/device-tree-bindings/firmware/nvidia,tegra186-bpmp.txt
@@ -0,0 +1,104 @@
+NVIDIA Tegra Boot and Power Management Processor (BPMP)
+
+The BPMP is a specific processor in Tegra chip, which is designed for
+booting process handling and offloading the power management, clock
+management, and reset control tasks from the CPU. The binding document
+defines the resources that would be used by the BPMP firmware driver,
+which can create the interprocessor communication (IPC) between the CPU
+and BPMP.
+
+Required properties:
+- name : Should be bpmp
+- compatible
+    Array of strings
+    One of:
+    - "nvidia,tegra186-bpmp"
+- mboxes : The phandle of mailbox controller and the mailbox specifier.
+- shmem : List of the phandle of the TX and RX shared memory area that
+	  the IPC between CPU and BPMP is based on.
+- #clock-cells : Should be 1.
+- #power-domain-cells : Should be 1.
+- #reset-cells : Should be 1.
+
+This node is a mailbox consumer. See the following files for details of
+the mailbox subsystem, and the specifiers implemented by the relevant
+provider(s):
+
+- .../mailbox/mailbox.txt
+- .../mailbox/nvidia,tegra186-hsp.txt
+
+This node is a clock, power domain, and reset provider. See the following
+files for general documentation of those features, and the specifiers
+implemented by this node:
+
+- .../clock/clock-bindings.txt
+- <dt-bindings/clock/tegra186-clock.h>
+- ../power/power_domain.txt
+- <dt-bindings/power/tegra186-powergate.h>
+- .../reset/reset.txt
+- <dt-bindings/reset/tegra186-reset.h>
+
+The BPMP implements some services which must be represented by separate nodes.
+For example, it can provide access to certain I2C controllers, and the I2C
+bindings represent each I2C controller as a device tree node. Such nodes should
+be nested directly inside the main BPMP node.
+
+Software can determine whether a child node of the BPMP node represents a device
+by checking for a compatible property. Any node with a compatible property
+represents a device that can be instantiated. Nodes without a compatible
+property may be used to provide configuration information regarding the BPMP
+itself, although no such configuration nodes are currently defined by this
+binding.
+
+The BPMP firmware defines no single global name-/numbering-space for such
+services. Put another way, the numbering scheme for I2C buses is distinct from
+the numbering scheme for any other service the BPMP may provide (e.g. a future
+hypothetical SPI bus service). As such, child device nodes will have no reg
+property, and the BPMP node will have no #address-cells or #size-cells property.
+
+The shared memory bindings for BPMP
+-----------------------------------
+
+The shared memory area for the IPC TX and RX between CPU and BPMP are
+predefined and work on top of sysram, which is an SRAM inside the chip.
+
+See ".../sram/sram.txt" for the bindings.
+
+Example:
+
+hsp_top0: hsp@03c00000 {
+	...
+	#mbox-cells = <2>;
+};
+
+sysram@30000000 {
+	compatible = "nvidia,tegra186-sysram", "mmio-sram";
+	reg = <0x0 0x30000000 0x0 0x50000>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+	ranges = <0 0x0 0x0 0x30000000 0x0 0x50000>;
+
+	cpu_bpmp_tx: bpmp_shmem@4e000 {
+		compatible = "nvidia,tegra186-bpmp-shmem";
+		reg = <0x0 0x4e000 0x0 0x1000>;
+	};
+
+	cpu_bpmp_rx: bpmp_shmem@4f000 {
+		compatible = "nvidia,tegra186-bpmp-shmem";
+		reg = <0x0 0x4f000 0x0 0x1000>;
+	};
+};
+
+bpmp {
+	compatible = "nvidia,tegra186-bpmp";
+	mboxes = <&hsp_top0 HSP_MBOX_TYPE_DB HSP_DB_MASTER_BPMP>;
+	shmem = <&cpu_bpmp_tx &cpu_bpmp_rx>;
+	#clock-cells = <1>;
+	#power-domain-cells = <1>;
+	#reset-cells = <1>;
+
+	i2c {
+		compatible = "...";
+		...
+	};
+};
diff --git a/doc/device-tree-bindings/gpio/gpio-pcf857x.txt b/doc/device-tree-bindings/gpio/gpio-pcf857x.txt
new file mode 100644
index 0000000..ada4e29
--- /dev/null
+++ b/doc/device-tree-bindings/gpio/gpio-pcf857x.txt
@@ -0,0 +1,71 @@
+* PCF857x-compatible I/O expanders
+
+The PCF857x-compatible chips have "quasi-bidirectional" I/O lines that can be
+driven high by a pull-up current source or driven low to ground. This combines
+the direction and output level into a single bit per line, which can't be read
+back. We can't actually know at initialization time whether a line is configured
+(a) as output and driving the signal low/high, or (b) as input and reporting a
+low/high value, without knowing the last value written since the chip came out
+of reset (if any). The only reliable solution for setting up line direction is
+thus to do it explicitly.
+
+Required Properties:
+
+  - compatible: should be one of the following.
+    - "maxim,max7328": For the Maxim MAX7378
+    - "maxim,max7329": For the Maxim MAX7329
+    - "nxp,pca8574": For the NXP PCA8574
+    - "nxp,pca8575": For the NXP PCA8575
+    - "nxp,pca9670": For the NXP PCA9670
+    - "nxp,pca9671": For the NXP PCA9671
+    - "nxp,pca9672": For the NXP PCA9672
+    - "nxp,pca9673": For the NXP PCA9673
+    - "nxp,pca9674": For the NXP PCA9674
+    - "nxp,pca9675": For the NXP PCA9675
+    - "nxp,pcf8574": For the NXP PCF8574
+    - "nxp,pcf8574a": For the NXP PCF8574A
+    - "nxp,pcf8575": For the NXP PCF8575
+    - "ti,tca9554": For the TI TCA9554
+
+  - reg: I2C slave address.
+
+  - gpio-controller: Marks the device node as a gpio controller.
+  - #gpio-cells: Should be 2. The first cell is the GPIO number and the second
+    cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>. Only the
+    GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported.
+
+Optional Properties:
+
+  - lines-initial-states: Bitmask that specifies the initial state of each
+  line. When a bit is set to zero, the corresponding line will be initialized to
+  the input (pulled-up) state. When the  bit is set to one, the line will be
+  initialized the low-level output state. If the property is not specified
+  all lines will be initialized to the input state.
+
+  The I/O expander can detect input state changes, and thus optionally act as
+  an interrupt controller. When the expander interrupt line is connected all the
+  following properties must be set. For more information please see the
+  interrupt controller device tree bindings documentation available at
+  Documentation/devicetree/bindings/interrupt-controller/interrupts.txt.
+
+  - interrupt-controller: Identifies the node as an interrupt controller.
+  - #interrupt-cells: Number of cells to encode an interrupt source, shall be 2.
+  - interrupt-parent: phandle of the parent interrupt controller.
+  - interrupts: Interrupt specifier for the controllers interrupt.
+
+
+Please refer to gpio.txt in this directory for details of the common GPIO
+bindings used by client devices.
+
+Example: PCF8575 I/O expander node
+
+	pcf8575: gpio@20 {
+		compatible = "nxp,pcf8575";
+		reg = <0x20>;
+		interrupt-parent = <&irqpin2>;
+		interrupts = <3 0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
diff --git a/doc/device-tree-bindings/i2c/i2c-at91.txt b/doc/device-tree-bindings/i2c/i2c-at91.txt
new file mode 100644
index 0000000..2065b73
--- /dev/null
+++ b/doc/device-tree-bindings/i2c/i2c-at91.txt
@@ -0,0 +1,26 @@
+I2C for Atmel platforms
+
+Required properties :
+- compatible : Must be "atmel,at91rm9200-i2c", "atmel,at91sam9261-i2c",
+     "atmel,at91sam9260-i2c", "atmel,at91sam9g20-i2c", "atmel,at91sam9g10-i2c",
+     "atmel,at91sam9x5-i2c", "atmel,sama5d4-i2c" or "atmel,sama5d2-i2c".
+- reg: physical base address of the controller and length of memory mapped
+     region.
+- #address-cells = <1>;
+- #size-cells = <0>;
+- clocks: phandles to input clocks.
+
+Optional properties:
+- clock-frequency: Desired I2C bus frequency in Hz, default value is 100000.
+- Child nodes conforming to i2c bus binding.
+
+Examples :
+
+i2c0: i2c@f8028000 {
+	compatible = "atmel,sama5d2-i2c";
+	reg = <0xf8028000 0x100>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	clocks = <&twi0_clk>;
+	clock-frequency = <100000>;
+};
diff --git a/doc/device-tree-bindings/i2c/nvidia,tegra186-bpmp-i2c.txt b/doc/device-tree-bindings/i2c/nvidia,tegra186-bpmp-i2c.txt
new file mode 100644
index 0000000..ab240e1
--- /dev/null
+++ b/doc/device-tree-bindings/i2c/nvidia,tegra186-bpmp-i2c.txt
@@ -0,0 +1,42 @@
+NVIDIA Tegra186 BPMP I2C controller
+
+In Tegra186, the BPMP (Boot and Power Management Processor) owns certain HW
+devices, such as the I2C controller for the power management I2C bus. Software
+running on other CPUs must perform IPC to the BPMP in order to execute
+transactions on that I2C bus. This binding describes an I2C bus that is
+accessed in such a fashion.
+
+The BPMP I2C node must be located directly inside the main BPMP node. See
+../firmware/nvidia,tegra186-bpmp.txt for details of the BPMP binding.
+
+This node represents an I2C controller. See ../i2c/i2c.txt for details of the
+core I2C binding.
+
+Required properties:
+- compatible:
+    Array of strings.
+    One of:
+    - "nvidia,tegra186-bpmp-i2c".
+- #address-cells: Address cells for I2C device address.
+    Single-cell integer.
+    Must be <1>.
+- #size-cells:
+    Single-cell integer.
+    Must be <0>.
+- nvidia,bpmp-bus-id:
+    Single-cell integer.
+    Indicates the I2C bus number this DT node represent, as defined by the
+    BPMP firmware.
+
+Example:
+
+bpmp {
+	...
+
+	i2c {
+		compatible = "nvidia,tegra186-bpmp-i2c";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		nvidia,bpmp-bus-id = <5>;
+	};
+};
diff --git a/doc/device-tree-bindings/mailbox/nvidia,tegra186-hsp.txt b/doc/device-tree-bindings/mailbox/nvidia,tegra186-hsp.txt
new file mode 100644
index 0000000..a915238
--- /dev/null
+++ b/doc/device-tree-bindings/mailbox/nvidia,tegra186-hsp.txt
@@ -0,0 +1,52 @@
+NVIDIA Tegra Hardware Synchronization Primitives (HSP)
+
+The HSP modules are used for the processors to share resources and communicate
+together. It provides a set of hardware synchronization primitives for
+interprocessor communication. So the interprocessor communication (IPC)
+protocols can use hardware synchronization primitives, when operating between
+two processors not in an SMP relationship.
+
+The features that HSP supported are shared mailboxes, shared semaphores,
+arbitrated semaphores and doorbells.
+
+Required properties:
+- name : Should be hsp
+- compatible
+    Array of strings.
+    one of:
+    - "nvidia,tegra186-hsp"
+- reg : Offset and length of the register set for the device.
+- interrupt-names
+    Array of strings.
+    Contains a list of names for the interrupts described by the interrupt
+    property. May contain the following entries, in any order:
+    - "doorbell"
+    Users of this binding MUST look up entries in the interrupt property
+    by name, using this interrupt-names property to do so.
+- interrupts
+    Array of interrupt specifiers.
+    Must contain one entry per entry in the interrupt-names property,
+    in a matching order.
+- #mbox-cells : Should be 2.
+
+The mbox specifier of the "mboxes" property in the client node should
+contain two data. The first one should be the HSP type and the second
+one should be the ID that the client is going to use. Those information
+can be found in the following file.
+
+- <dt-bindings/mailbox/tegra186-hsp.h>.
+
+Example:
+
+hsp_top0: hsp@3c00000 {
+	compatible = "nvidia,tegra186-hsp";
+	reg = <0x0 0x03c00000 0x0 0xa0000>;
+	interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+	interrupt-names = "doorbell";
+	#mbox-cells = <2>;
+};
+
+client {
+	...
+	mboxes = <&hsp_top0 HSP_MBOX_TYPE_DB HSP_DB_MASTER_XXX>;
+};
diff --git a/doc/device-tree-bindings/pinctrl/atmel,at91-pio4-pinctrl.txt b/doc/device-tree-bindings/pinctrl/atmel,at91-pio4-pinctrl.txt
new file mode 100644
index 0000000..a1b5596
--- /dev/null
+++ b/doc/device-tree-bindings/pinctrl/atmel,at91-pio4-pinctrl.txt
@@ -0,0 +1,66 @@
+* Atmel PIO4 Controller
+
+The Atmel PIO4 controller is used to select the function of a pin and to
+configure it.
+
+Required properties:
+- compatible: "atmel,sama5d2-pinctrl".
+- reg: base address and length of the PIO controller.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices.
+
+Subnode format
+Each node (or subnode) will list the pins it needs and how to configured these
+pins.
+
+	node {
+		pinmux = <PIN_NUMBER_PINMUX>;
+		GENERIC_PINCONFIG;
+	};
+
+Required properties:
+- pinmux: integer array. Each integer represents a pin number plus mux and
+ioset settings. Use the macros from boot/dts/<soc>-pinfunc.h file to get the
+right representation of the pin.
+
+Optional properties:
+- GENERIC_PINCONFIG: generic pinconfig options to use, bias-disable,
+bias-pull-down, bias-pull-up, drive-open-drain, input-schmitt-enable,
+input-debounce.
+
+Example:
+
+#include <sama5d2-pinfunc.h>
+
+...
+{
+	spi0: spi@f8000000 {
+		cs-gpios = <&pioA 17 0>, <0>, <0>, <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_spi0_default>;
+		status = "okay";
+
+		spi_flash@0 {
+			compatible = "spi-flash";
+			reg = <0>;
+			spi-max-frequency = <50000000>;
+		};
+	};
+
+	...
+
+	pioA: pinctrl@fc038000 {
+		compatible = "atmel,sama5d2-pinctrl";
+		reg = <0xfc038000 0x600>;
+
+		pinctrl_spi0_default: spi0_default {
+			pinmux = <PIN_PA14__SPI0_SPCK>,
+				 <PIN_PA15__SPI0_MOSI>,
+				 <PIN_PA16__SPI0_MISO>;
+			bias-disable;
+		};
+		...
+	};
+};
+...
diff --git a/doc/device-tree-bindings/serial/sh.txt b/doc/device-tree-bindings/serial/sh.txt
new file mode 100644
index 0000000..99634a5
--- /dev/null
+++ b/doc/device-tree-bindings/serial/sh.txt
@@ -0,0 +1,6 @@
+* Renesas SCI serial interface
+
+Required properties:
+- compatible: must be "renesas,scif", "renesas,scifa" or "renesas,sci"
+- reg: exactly one register range with length
+- clock: input clock frequency for the SCI unit
diff --git a/doc/driver-model/of-plat.txt b/doc/driver-model/of-plat.txt
new file mode 100644
index 0000000..86e5e25
--- /dev/null
+++ b/doc/driver-model/of-plat.txt
@@ -0,0 +1,310 @@
+Driver Model Compiled-in Device Tree / Platform Data
+====================================================
+
+
+Introduction
+------------
+
+Device tree is the standard configuration method in U-Boot. It is used to
+define what devices are in the system and provide configuration information
+to these devices.
+
+The overhead of adding device tree access to U-Boot is fairly modest,
+approximately 3KB on Thumb 2 (plus the size of the DT itself). This means
+that in most cases it is best to use device tree for configuration.
+
+However there are some very constrained environments where U-Boot needs to
+work. These include SPL with severe memory limitations. For example, some
+SoCs require a 16KB SPL image which must include a full MMC stack. In this
+case the overhead of device tree access may be too great.
+
+It is possible to create platform data manually by defining C structures
+for it, and reference that data in a U_BOOT_DEVICE() declaration. This
+bypasses the use of device tree completely, effectively creating a parallel
+configuration mechanism. But it is an available option for SPL.
+
+As an alternative, a new 'of-platdata' feature is provided. This converts the
+device tree contents into C code which can be compiled into the SPL binary.
+This saves the 3KB of code overhead and perhaps a few hundred more bytes due
+to more efficient storage of the data.
+
+Note: Quite a bit of thought has gone into the design of this feature.
+However it still has many rough edges and comments and suggestions are
+strongly encouraged! Quite possibly there is a much better approach.
+
+
+Caveats
+-------
+
+There are many problems with this features. It should only be used when
+strictly necessary. Notable problems include:
+
+   - Device tree does not describe data types. But the C code must define a
+        type for each property. These are guessed using heuristics which
+        are wrong in several fairly common cases. For example an 8-byte value
+        is considered to be a 2-item integer array, and is byte-swapped. A
+        boolean value that is not present means 'false', but cannot be
+        included in the structures since there is generally no mention of it
+        in the device tree file.
+
+   - Naming of nodes and properties is automatic. This means that they follow
+        the naming in the device tree, which may result in C identifiers that
+        look a bit strange.
+
+   - It is not possible to find a value given a property name. Code must use
+        the associated C member variable directly in the code. This makes
+        the code less robust in the face of device-tree changes. It also
+        makes it very unlikely that your driver code will be useful for more
+        than one SoC. Even if the code is common, each SoC will end up with
+        a different C struct name, and a likely a different format for the
+        platform data.
+
+   - The platform data is provided to drivers as a C structure. The driver
+        must use the same structure to access the data. Since a driver
+        normally also supports device tree it must use #ifdef to separate
+        out this code, since the structures are only available in SPL.
+
+
+How it works
+------------
+
+The feature is enabled by CONFIG SPL_OF_PLATDATA. This is only available
+in SPL and should be tested with:
+
+        #if CONFIG_IS_ENABLED(SPL_OF_PLATDATA)
+
+A new tool called 'dtoc' converts a device tree file either into a set of
+struct declarations, one for each compatible node, or a set of
+U_BOOT_DEVICE() declarations along with the actual platform data for each
+device. As an example, consider this MMC node:
+
+        sdmmc: dwmmc@ff0c0000 {
+                compatible = "rockchip,rk3288-dw-mshc";
+                clock-freq-min-max = <400000 150000000>;
+                clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
+                         <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
+                clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+                fifo-depth = <0x100>;
+                interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+                reg = <0xff0c0000 0x4000>;
+                bus-width = <4>;
+                cap-mmc-highspeed;
+                cap-sd-highspeed;
+                card-detect-delay = <200>;
+                disable-wp;
+                num-slots = <1>;
+                pinctrl-names = "default";
+                pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>;
+                vmmc-supply = <&vcc_sd>;
+                status = "okay";
+                u-boot,dm-pre-reloc;
+        };
+
+
+Some of these properties are dropped by U-Boot under control of the
+CONFIG_OF_SPL_REMOVE_PROPS option. The rest are processed. This will produce
+the following C struct declaration:
+
+struct dtd_rockchip_rk3288_dw_mshc {
+        fdt32_t         bus_width;
+        bool            cap_mmc_highspeed;
+        bool            cap_sd_highspeed;
+        fdt32_t         card_detect_delay;
+        fdt32_t         clock_freq_min_max[2];
+        struct phandle_2_cell clocks[4];
+        bool            disable_wp;
+        fdt32_t         fifo_depth;
+        fdt32_t         interrupts[3];
+        fdt32_t         num_slots;
+        fdt32_t         reg[2];
+        fdt32_t         vmmc_supply;
+};
+
+and the following device declaration:
+
+static struct dtd_rockchip_rk3288_dw_mshc dtv_dwmmc_at_ff0c0000 = {
+        .fifo_depth             = 0x100,
+        .cap_sd_highspeed       = true,
+        .interrupts             = {0x0, 0x20, 0x4},
+        .clock_freq_min_max     = {0x61a80, 0x8f0d180},
+        .vmmc_supply            = 0xb,
+        .num_slots              = 0x1,
+        .clocks                 = {{&dtv_clock_controller_at_ff760000, 456},
+                                   {&dtv_clock_controller_at_ff760000, 68},
+                                   {&dtv_clock_controller_at_ff760000, 114},
+                                   {&dtv_clock_controller_at_ff760000, 118}},
+        .cap_mmc_highspeed      = true,
+        .disable_wp             = true,
+        .bus_width              = 0x4,
+        .u_boot_dm_pre_reloc    = true,
+        .reg                    = {0xff0c0000, 0x4000},
+        .card_detect_delay      = 0xc8,
+};
+U_BOOT_DEVICE(dwmmc_at_ff0c0000) = {
+        .name           = "rockchip_rk3288_dw_mshc",
+        .platdata       = &dtv_dwmmc_at_ff0c0000,
+        .platdata_size  = sizeof(dtv_dwmmc_at_ff0c0000),
+};
+
+The device is then instantiated at run-time and the platform data can be
+accessed using:
+
+        struct udevice *dev;
+        struct dtd_rockchip_rk3288_dw_mshc *plat = dev_get_platdata(dev);
+
+This avoids the code overhead of converting the device tree data to
+platform data in the driver. The ofdata_to_platdata() method should
+therefore do nothing in such a driver.
+
+
+Converting of-platdata to a useful form
+---------------------------------------
+
+Of course it would be possible use the of-platdata directly in your driver
+whenever configuration information is required. However this meands that the
+driver will not be able to support device tree, since the of-platdata
+structure is not available when device tree is used. It would make no sense
+to use this structure if device tree were available, since the structure has
+all the limitations metioned in caveats above.
+
+Therefore it is recommended that the of-platdata structure should be used
+only in the probe() method of your driver. It cannot be used in the
+ofdata_to_platdata() method since this is not called when platform data is
+already present.
+
+
+How to structure your driver
+----------------------------
+
+Drivers should always support device tree as an option. The of-platdata
+feature is intended as a add-on to existing drivers.
+
+Your driver should convert the platdata struct in its probe() method. The
+existing device tree decoding logic should be kept in the
+ofdata_to_platdata() method and wrapped with #if.
+
+For example:
+
+    #include <dt-structs.h>
+
+    struct mmc_platdata {
+    #if CONFIG_IS_ENABLED(SPL_OF_PLATDATA)
+            /* Put this first since driver model will copy the data here */
+            struct dtd_mmc dtplat;
+    #endif
+            /*
+             * Other fields can go here, to be filled in by decoding from
+             * the device tree (or the C structures when of-platdata is used).
+             */
+            int fifo_depth;
+    };
+
+    static int mmc_ofdata_to_platdata(struct udevice *dev)
+    {
+    #if !CONFIG_IS_ENABLED(SPL_OF_PLATDATA)
+            /* Decode the device tree data */
+            struct mmc_platdata *plat = dev_get_platdata(dev);
+            const void *blob = gd->fdt_blob;
+            int node = dev->of_offset;
+
+            plat->fifo_depth = fdtdec_get_int(blob, node, "fifo-depth", 0);
+    #endif
+
+            return 0;
+    }
+
+    static int mmc_probe(struct udevice *dev)
+    {
+            struct mmc_platdata *plat = dev_get_platdata(dev);
+
+    #if CONFIG_IS_ENABLED(SPL_OF_PLATDATA)
+            /* Decode the of-platdata from the C structures */
+            struct dtd_mmc *dtplat = &plat->dtplat;
+
+            plat->fifo_depth = dtplat->fifo_depth;
+    #endif
+            /* Set up the device from the plat data */
+            writel(plat->fifo_depth, ...)
+    }
+
+    static const struct udevice_id mmc_ids[] = {
+            { .compatible = "vendor,mmc" },
+            { }
+    };
+
+    U_BOOT_DRIVER(mmc_drv) = {
+            .name           = "mmc",
+            .id             = UCLASS_MMC,
+            .of_match       = mmc_ids,
+            .ofdata_to_platdata = mmc_ofdata_to_platdata,
+            .probe          = mmc_probe,
+            .priv_auto_alloc_size = sizeof(struct mmc_priv),
+            .platdata_auto_alloc_size = sizeof(struct mmc_platdata),
+    };
+
+
+In the case where SPL_OF_PLATDATA is enabled, platdata_auto_alloc_size is
+still used to allocate space for the platform data. This is different from
+the normal behaviour and is triggered by the use of of-platdata (strictly
+speaking it is a non-zero platdata_size which triggers this).
+
+The of-platdata struct contents is copied from the C structure data to the
+start of the newly allocated area. In the case where device tree is used,
+the platform data is allocated, and starts zeroed. In this case the
+ofdata_to_platdata() method should still set up the platform data (and the
+of-platdata struct will not be present).
+
+SPL must use either of-platdata or device tree. Drivers cannot use both at
+the same time, but they must support device tree. Supporting of-platdata is
+optional.
+
+The device tree becomes in accessible when CONFIG_SPL_OF_PLATDATA is enabled,
+since the device-tree access code is not compiled in. A corollary is that
+a board can only move to using of-platdata if all the drivers it uses support
+it. There would be little point in having some drivers require the device
+tree data, since then libfdt would still be needed for those drivers and
+there would be no code-size benefit.
+
+Internals
+---------
+
+The dt-structs.h file includes the generated file
+(include/generated//dt-structs.h) if CONFIG_SPL_OF_PLATDATA is enabled.
+Otherwise (such as in U-Boot proper) these structs are not available. This
+prevents them being used inadvertently. All usage must be bracketed with
+#if CONFIG_IS_ENABLED(SPL_OF_PLATDATA).
+
+The dt-platdata.c file contains the device declarations and is is built in
+spl/dt-platdata.c.
+
+Some phandles (thsoe that are recognised as such) are converted into
+points to platform data. This pointer can potentially be used to access the
+referenced device (by searching for the pointer value). This feature is not
+yet implemented, however.
+
+The beginnings of a libfdt Python module are provided. So far this only
+implements a subset of the features.
+
+The 'swig' tool is needed to build the libfdt Python module. If this is not
+found then the Python model is not used and a fallback is used instead, which
+makes use of fdtget.
+
+
+Credits
+-------
+
+This is an implementation of an idea by Tom Rini <trini@konsulko.com>.
+
+
+Future work
+-----------
+- Consider programmatically reading binding files instead of device tree
+     contents
+- Complete the phandle feature
+- Move to using a full Python libfdt module
+
+--
+Simon Glass <sjg@chromium.org>
+Google, Inc
+6/6/16
+Updated Independence Day 2016
diff --git a/doc/feature-removal-schedule.txt b/doc/feature-removal-schedule.txt
index 4ed30df..b5a70da 100644
--- a/doc/feature-removal-schedule.txt
+++ b/doc/feature-removal-schedule.txt
@@ -12,7 +12,7 @@
 
 Why:	As the 'mtest' command is no longer default, a number of platforms
 	have not opted to turn the command back on and thus provide unused
-	defines (which are likely to be propogated to new platforms from
+	defines (which are likely to be propagated to new platforms from
 	copy/paste).  Remove these defines when unused.
 
 Who:	Tom Rini <trini@ti.com>
diff --git a/doc/git-mailrc b/doc/git-mailrc
index 1d6f4fc..a14629c 100644
--- a/doc/git-mailrc
+++ b/doc/git-mailrc
@@ -23,6 +23,7 @@
 alias hs             Heiko Schocher <hs@denx.de>
 alias ijc            Ian Campbell <ijc+uboot@hellion.org.uk>
 alias iwamatsu       Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+alias jaehoon        Jaehoon Chung <jh80.chung@samsung.com>
 alias jagan          Jagan Teki <jteki@openedev.com>
 alias jasonjin       Jason Jin <jason.jin@freescale.com>
 alias jhersh         Joe Hershberger <joe.hershberger@ni.com>
@@ -35,7 +36,6 @@
 alias masahiro       Masahiro Yamada <yamada.masahiro@socionext.com>
 alias mateusz        Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
 alias monstr         Michal Simek <monstr@monstr.eu>
-alias panto          Pantelis Antoniou <panto@antoniou-consulting.com>
 alias prafulla       Prafulla Wadaskar <prafulla@marvell.com>
 alias bobenstein     Przemyslaw Marczak <p.marczak@samsung.com>
 alias prom           Minkyu Kang <mk7.kang@samsung.com>
@@ -76,7 +76,7 @@
 alias ti             uboot, trini
 alias uniphier       uboot, masahiro
 alias zynq           uboot, monstr
-
+alias rockchip       uboot, sjg, Lin huang <hl@rock-chips.com>
 alias avr32          uboot, abiessmann
 
 alias bfin           uboot, vapier, sonic
@@ -124,7 +124,7 @@
 alias fdt            uboot, sjg
 alias i2c            uboot, hs
 alias kconfig        uboot, masahiro
-alias mmc            uboot, panto
+alias mmc            uboot, jaehoon
 alias nand           uboot, scottwood
 alias net            uboot, jhersh
 alias phy            uboot, jhersh
diff --git a/doc/uImage.FIT/kernel.its b/doc/uImage.FIT/kernel.its
index e668c3f..0aaf47e 100644
--- a/doc/uImage.FIT/kernel.its
+++ b/doc/uImage.FIT/kernel.its
@@ -85,3 +85,7 @@
 		};
 	};
 };
+
+Note: the above assumes a 32-bit kernel. To directly boot a 64-bit kernel,
+change both arch values to "x86_64". U-Boot will then change to 64-bit mode
+before booting the kernel (see boot_linux_kernel()).
diff --git a/doc/uImage.FIT/x86-fit-boot.txt b/doc/uImage.FIT/x86-fit-boot.txt
index 61c10ff..02238f9 100644
--- a/doc/uImage.FIT/x86-fit-boot.txt
+++ b/doc/uImage.FIT/x86-fit-boot.txt
@@ -63,9 +63,8 @@
 Build the kernel
 ----------------
 
-Note: these instructions assume a 32-bit kernel. U-Boot does not currently
-support booting a 64-bit kernel as it has no way of going into 64-bit mode on
-x86.
+Note: these instructions assume a 32-bit kernel. U-Boot also supports directly
+booting a 64-bit kernel by jumping into 64-bit mode first (see below).
 
 You can build the kernel as normal with 'make'. This will create a file called
 'vmlinux'. This is a standard ELF file and you can look at it if you like:
@@ -168,8 +167,9 @@
 ------------
 
 To create a FIT you will need a source file describing what should go in the
-FIT. See kernel.its for an example for x86. Put this into a file called
-image.its.
+FIT. See kernel.its for an example for x86 and also instructions on setting
+the 'arch' value for booting 64-bit kernels if desired. Put this into a file
+called image.its.
 
 Note that setup is loaded to the special address of 0x90000 (a special address
 you just have to know) and the kernel is loaded to 0x01000000 (the address you
@@ -263,10 +263,6 @@
 the kernel including the setup.bin format. This is handled in U-Boot in
 arch/x86/lib/zimage.c and arch/x86/lib/bootm.c.
 
-The procedure for entering 64-bit mode on x86 seems to be described here:
-
-   http://wiki.osdev.org/64-bit_Higher_Half_Kernel_with_GRUB_2
-
 Various files in the same directory as this file describe the FIT format.
 
 
diff --git a/drivers/Kconfig b/drivers/Kconfig
index f6003a0..4f84469 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -68,6 +68,8 @@
 
 source "drivers/spmi/Kconfig"
 
+source "drivers/sysreset/Kconfig"
+
 source "drivers/thermal/Kconfig"
 
 source "drivers/timer/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 1723958..7861d34 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -19,14 +19,15 @@
 obj-$(CONFIG_ARMADA_XP) += ddr/marvell/axp/
 obj-$(CONFIG_ALTERA_SDRAM) += ddr/altera/
 obj-$(CONFIG_SPL_SERIAL_SUPPORT) += serial/
-obj-$(CONFIG_SPL_SPI_FLASH_SUPPORT) += mtd/spi/
 obj-$(CONFIG_SPL_SPI_SUPPORT) += spi/
 obj-$(CONFIG_SPL_POWER_SUPPORT) += power/ power/pmic/
 obj-$(CONFIG_SPL_POWER_SUPPORT) += power/regulator/
+obj-$(CONFIG_SPL_DRIVERS_MISC_SUPPORT) += misc/ sysreset/
 obj-$(CONFIG_SPL_MTD_SUPPORT) += mtd/
 obj-$(CONFIG_SPL_NAND_SUPPORT) += mtd/nand/
-obj-$(CONFIG_SPL_DRIVERS_MISC_SUPPORT) += misc/
 obj-$(CONFIG_SPL_ONENAND_SUPPORT) += mtd/onenand/
+obj-$(CONFIG_SPL_SPI_FLASH_SUPPORT) += mtd/spi/
+obj-$(CONFIG_SPL_UBI) += mtd/ubispl/
 obj-$(CONFIG_SPL_DMA_SUPPORT) += dma/
 obj-$(CONFIG_SPL_ETH_SUPPORT) += net/
 obj-$(CONFIG_SPL_ETH_SUPPORT) += net/phy/
@@ -58,6 +59,7 @@
 obj-y += rtc/
 obj-y += sound/
 obj-y += spmi/
+obj-y += sysreset/
 obj-y += timer/
 obj-y += tpm/
 obj-y += twserial/
diff --git a/drivers/bios_emulator/x86emu/sys.c b/drivers/bios_emulator/x86emu/sys.c
index 0ba9c0c..c2db121 100644
--- a/drivers/bios_emulator/x86emu/sys.c
+++ b/drivers/bios_emulator/x86emu/sys.c
@@ -35,7 +35,7 @@
 * Description:  This file includes subroutines which are related to
 *               programmed I/O and memory access. Included in this module
 *               are default functions that do nothing. For real uses these
-*               functions will have to be overriden by the user library.
+*               functions will have to be overridden by the user library.
 *
 ****************************************************************************/
 
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 6eee8eb..8f3b96a 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -20,7 +20,9 @@
 	  setting up clocks within SPL, and allows the same drivers to be
 	  used as U-Boot proper.
 
+source "drivers/clk/tegra/Kconfig"
 source "drivers/clk/uniphier/Kconfig"
 source "drivers/clk/exynos/Kconfig"
+source "drivers/clk/at91/Kconfig"
 
 endmenu
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index f7a8891..778d748 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -6,10 +6,12 @@
 #
 
 obj-$(CONFIG_CLK) += clk-uclass.o clk_fixed_rate.o
-obj-$(CONFIG_ROCKCHIP_RK3036) += clk_rk3036.o
-obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
+obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
 obj-$(CONFIG_SANDBOX) += clk_sandbox.o
 obj-$(CONFIG_SANDBOX) += clk_sandbox_test.o
 obj-$(CONFIG_MACH_PIC32) += clk_pic32.o
+
+obj-y += tegra/
 obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
 obj-$(CONFIG_CLK_EXYNOS) += exynos/
+obj-$(CONFIG_CLK_AT91) += at91/
diff --git a/drivers/clk/at91/Kconfig b/drivers/clk/at91/Kconfig
new file mode 100644
index 0000000..10050d8
--- /dev/null
+++ b/drivers/clk/at91/Kconfig
@@ -0,0 +1,43 @@
+config CLK_AT91
+	bool "AT91 clock drivers"
+	depends on CLK
+	help
+	  This option is used to enable the AT91 clock driver.
+	  The driver supports the AT91 clock generator, including
+	  the oscillators and PLLs, such as main clock, slow clock,
+	  PLLA, UTMI PLL. Clocks can also be a source clock of other
+	  clocks a tree structure, such as master clock, usb device
+	  clock, matrix clock and generic clock.
+	  Devices can use a common clock API to request a particular
+	  clock, enable it and get its rate.
+
+config AT91_UTMI
+	bool "Support UTMI PLL Clock"
+	depends on CLK_AT91
+	help
+	  This option is used to enable the AT91 UTMI PLL clock
+	  driver. It is the clock provider of USB, and UPLLCK is the
+	  output of 480 MHz UTMI PLL, The souce clock of the UTMI
+	  PLL is the main clock, so the main clock must select the
+	  fast crystal oscillator to meet the frequency accuracy
+	  required by USB.
+
+config AT91_H32MX
+	bool "Support H32MX 32-bit Matrix Clock"
+	depends on CLK_AT91
+	help
+	  This option is used to enable the AT91 H32MX matrixes
+	  clock driver. There are H64MX and H32MX matrixes clocks,
+	  H64MX 64-bit matrix clocks are MCK. The H32MX 32-bit
+	  matrix clock is to be configured as MCK if MCK does not
+	  exceed 83 MHz, else it is to be configured as MCK/2.
+
+config AT91_GENERIC_CLK
+	bool "Support Generic Clock"
+	depends on CLK_AT91
+	help
+	  This option is used to enable the AT91 generic clock
+	  driver. Some peripherals may need a second clock source
+	  that may be different from the system clock. This second
+	  clock is the generic clock (GCLK) and is managed by
+	  the PMC via PMC_PCR register.
diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile
new file mode 100644
index 0000000..fbe3cb6
--- /dev/null
+++ b/drivers/clk/at91/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for at91 specific clk
+#
+
+obj-y += pmc.o sckc.o
+obj-y += clk-slow.o clk-main.o clk-plla.o clk-master.o
+obj-y += clk-system.o clk-peripheral.o
+
+obj-$(CONFIG_AT91_UTMI)		+= clk-utmi.o
+obj-$(CONFIG_AT91_H32MX)	+= clk-h32mx.o
+obj-$(CONFIG_AT91_GENERIC_CLK)	+= clk-generated.o
diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c
new file mode 100644
index 0000000..f6164cc
--- /dev/null
+++ b/drivers/clk/at91/clk-generated.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016 Atmel Corporation
+ *               Wenyou.Yang <wenyou.yang@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+#include <linux/io.h>
+#include <mach/at91_pmc.h>
+#include "pmc.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define GENERATED_SOURCE_MAX	6
+#define GENERATED_MAX_DIV	255
+
+struct generated_clk_priv {
+	u32 num_parents;
+};
+
+static ulong generated_clk_get_rate(struct clk *clk)
+{
+	struct pmc_platdata *plat = dev_get_platdata(clk->dev);
+	struct at91_pmc *pmc = plat->reg_base;
+	struct clk parent;
+	u32 tmp, gckdiv;
+	u8 parent_id;
+	int ret;
+
+	writel(clk->id & AT91_PMC_PCR_PID_MASK, &pmc->pcr);
+	tmp = readl(&pmc->pcr);
+	parent_id = (tmp >> AT91_PMC_PCR_GCKCSS_OFFSET) &
+		    AT91_PMC_PCR_GCKCSS_MASK;
+	gckdiv = (tmp >> AT91_PMC_PCR_GCKDIV_OFFSET) & AT91_PMC_PCR_GCKDIV_MASK;
+
+	ret = clk_get_by_index(clk->dev, parent_id, &parent);
+	if (ret)
+		return 0;
+
+	return clk_get_rate(&parent) / (gckdiv + 1);
+}
+
+static ulong generated_clk_set_rate(struct clk *clk, ulong rate)
+{
+	struct pmc_platdata *plat = dev_get_platdata(clk->dev);
+	struct at91_pmc *pmc = plat->reg_base;
+	struct generated_clk_priv *priv = dev_get_priv(clk->dev);
+	struct clk parent, best_parent;
+	ulong tmp_rate, best_rate = rate, parent_rate;
+	int tmp_diff, best_diff = -1;
+	u32 div, best_div = 0;
+	u8 best_parent_id = 0;
+	u8 i;
+	u32 tmp;
+	int ret;
+
+	for (i = 0; i < priv->num_parents; i++) {
+		ret = clk_get_by_index(clk->dev, i, &parent);
+		if (ret)
+			return ret;
+
+		parent_rate = clk_get_rate(&parent);
+		if (IS_ERR_VALUE(parent_rate))
+			return parent_rate;
+
+		for (div = 1; div < GENERATED_MAX_DIV + 2; div++) {
+			tmp_rate = DIV_ROUND_CLOSEST(parent_rate, div);
+			if (rate < tmp_rate)
+				continue;
+			tmp_diff = rate - tmp_rate;
+
+			if (best_diff < 0 || best_diff > tmp_diff) {
+				best_rate = tmp_rate;
+				best_diff = tmp_diff;
+
+				best_div = div - 1;
+				best_parent = parent;
+				best_parent_id = i;
+			}
+
+			if (!best_diff || tmp_rate < rate)
+				break;
+		}
+
+		if (!best_diff)
+			break;
+	}
+
+	debug("GCK: best parent: %s, best_rate = %ld, best_div = %d\n",
+	      best_parent.dev->name, best_rate, best_div);
+
+	ret = clk_enable(&best_parent);
+	if (ret)
+		return ret;
+
+	writel(clk->id & AT91_PMC_PCR_PID_MASK, &pmc->pcr);
+	tmp = readl(&pmc->pcr);
+	tmp &= ~(AT91_PMC_PCR_GCKDIV | AT91_PMC_PCR_GCKCSS);
+	tmp |= AT91_PMC_PCR_GCKCSS_(best_parent_id) |
+	       AT91_PMC_PCR_CMD_WRITE |
+	       AT91_PMC_PCR_GCKDIV_(best_div) |
+	       AT91_PMC_PCR_GCKEN;
+	writel(tmp, &pmc->pcr);
+
+	while (!(readl(&pmc->sr) & AT91_PMC_GCKRDY))
+		;
+
+	return 0;
+}
+
+static struct clk_ops generated_clk_ops = {
+	.get_rate = generated_clk_get_rate,
+	.set_rate = generated_clk_set_rate,
+};
+
+static int generated_clk_ofdata_to_platdata(struct udevice *dev)
+{
+	struct generated_clk_priv *priv = dev_get_priv(dev);
+	u32 cells[GENERATED_SOURCE_MAX];
+	u32 num_parents;
+
+	num_parents = fdtdec_get_int_array_count(gd->fdt_blob, dev->of_offset,
+						 "clocks", cells,
+						 GENERATED_SOURCE_MAX);
+
+	if (!num_parents)
+		return -1;
+
+	priv->num_parents = num_parents;
+
+	return 0;
+}
+
+static int generated_clk_bind(struct udevice *dev)
+{
+	return at91_pmc_clk_node_bind(dev);
+}
+
+static int generated_clk_probe(struct udevice *dev)
+{
+	return at91_pmc_core_probe(dev);
+}
+
+static const struct udevice_id generated_clk_match[] = {
+	{ .compatible = "atmel,sama5d2-clk-generated" },
+	{}
+};
+
+U_BOOT_DRIVER(generated_clk) = {
+	.name = "generated-clk",
+	.id = UCLASS_CLK,
+	.of_match = generated_clk_match,
+	.bind = generated_clk_bind,
+	.probe = generated_clk_probe,
+	.ofdata_to_platdata = generated_clk_ofdata_to_platdata,
+	.priv_auto_alloc_size = sizeof(struct generated_clk_priv),
+	.platdata_auto_alloc_size = sizeof(struct pmc_platdata),
+	.ops = &generated_clk_ops,
+};
diff --git a/drivers/clk/at91/clk-h32mx.c b/drivers/clk/at91/clk-h32mx.c
new file mode 100644
index 0000000..1a304ba
--- /dev/null
+++ b/drivers/clk/at91/clk-h32mx.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 Atmel Corporation
+ *               Wenyou.Yang <wenyou.yang@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+#include <dm/util.h>
+#include <linux/io.h>
+#include <mach/at91_pmc.h>
+#include "pmc.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define H32MX_MAX_FREQ	90000000
+
+static ulong sama5d4_h32mx_clk_get_rate(struct clk *clk)
+{
+	struct pmc_platdata *plat = dev_get_platdata(clk->dev);
+	struct at91_pmc *pmc = plat->reg_base;
+	ulong rate = gd->arch.mck_rate_hz;
+
+	if (readl(&pmc->mckr) & AT91_PMC_MCKR_H32MXDIV)
+		rate /= 2;
+
+	if (rate > H32MX_MAX_FREQ)
+		dm_warn("H32MX clock is too fast\n");
+
+	return rate;
+}
+
+static struct clk_ops sama5d4_h32mx_clk_ops = {
+	.get_rate = sama5d4_h32mx_clk_get_rate,
+};
+
+static int sama5d4_h32mx_clk_probe(struct udevice *dev)
+{
+	return at91_pmc_core_probe(dev);
+}
+
+static const struct udevice_id sama5d4_h32mx_clk_match[] = {
+	{ .compatible = "atmel,sama5d4-clk-h32mx" },
+	{}
+};
+
+U_BOOT_DRIVER(sama5d4_h32mx_clk) = {
+	.name = "sama5d4-h32mx-clk",
+	.id = UCLASS_CLK,
+	.of_match = sama5d4_h32mx_clk_match,
+	.probe = sama5d4_h32mx_clk_probe,
+	.platdata_auto_alloc_size = sizeof(struct pmc_platdata),
+	.ops = &sama5d4_h32mx_clk_ops,
+};
diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c
new file mode 100644
index 0000000..252d076
--- /dev/null
+++ b/drivers/clk/at91/clk-main.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 Atmel Corporation
+ *               Wenyou.Yang <wenyou.yang@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+#include <linux/io.h>
+#include <mach/at91_pmc.h>
+#include "pmc.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int main_osc_clk_enable(struct clk *clk)
+{
+	struct pmc_platdata *plat = dev_get_platdata(clk->dev);
+	struct at91_pmc *pmc = plat->reg_base;
+
+	if (readl(&pmc->sr) & AT91_PMC_MOSCSELS)
+		return 0;
+
+	return -EINVAL;
+}
+
+static ulong main_osc_clk_get_rate(struct clk *clk)
+{
+	return gd->arch.main_clk_rate_hz;
+}
+
+static struct clk_ops main_osc_clk_ops = {
+	.enable = main_osc_clk_enable,
+	.get_rate = main_osc_clk_get_rate,
+};
+
+static int main_osc_clk_probe(struct udevice *dev)
+{
+	return at91_pmc_core_probe(dev);
+}
+
+static const struct udevice_id main_osc_clk_match[] = {
+	{ .compatible = "atmel,at91sam9x5-clk-main" },
+	{}
+};
+
+U_BOOT_DRIVER(at91sam9x5_main_osc_clk) = {
+	.name = "at91sam9x5-main-osc-clk",
+	.id = UCLASS_CLK,
+	.of_match = main_osc_clk_match,
+	.probe = main_osc_clk_probe,
+	.platdata_auto_alloc_size = sizeof(struct pmc_platdata),
+	.ops = &main_osc_clk_ops,
+};
diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c
new file mode 100644
index 0000000..284b248
--- /dev/null
+++ b/drivers/clk/at91/clk-master.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 Atmel Corporation
+ *               Wenyou.Yang <wenyou.yang@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static ulong at91_master_clk_get_rate(struct clk *clk)
+{
+	return gd->arch.mck_rate_hz;
+}
+
+static struct clk_ops at91_master_clk_ops = {
+	.get_rate = at91_master_clk_get_rate,
+};
+
+static const struct udevice_id at91_master_clk_match[] = {
+	{ .compatible = "atmel,at91sam9x5-clk-master" },
+	{}
+};
+
+U_BOOT_DRIVER(at91_master_clk) = {
+	.name = "at91-master-clk",
+	.id = UCLASS_CLK,
+	.of_match = at91_master_clk_match,
+	.ops = &at91_master_clk_ops,
+};
diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c
new file mode 100644
index 0000000..16688e9
--- /dev/null
+++ b/drivers/clk/at91/clk-peripheral.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 Atmel Corporation
+ *               Wenyou.Yang <wenyou.yang@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+#include <linux/io.h>
+#include <mach/at91_pmc.h>
+#include "pmc.h"
+
+#define PERIPHERAL_ID_MIN	2
+#define PERIPHERAL_ID_MAX	31
+#define PERIPHERAL_MASK(id)	(1 << ((id) & PERIPHERAL_ID_MAX))
+
+static int sam9x5_periph_clk_enable(struct clk *clk)
+{
+	struct pmc_platdata *plat = dev_get_platdata(clk->dev);
+	struct at91_pmc *pmc = plat->reg_base;
+
+	if (clk->id < PERIPHERAL_ID_MIN)
+		return -1;
+
+	writel(clk->id & AT91_PMC_PCR_PID_MASK, &pmc->pcr);
+	setbits_le32(&pmc->pcr, AT91_PMC_PCR_CMD_WRITE | AT91_PMC_PCR_EN);
+
+	return 0;
+}
+
+static struct clk_ops sam9x5_periph_clk_ops = {
+	.enable = sam9x5_periph_clk_enable,
+};
+
+static int sam9x5_periph_clk_bind(struct udevice *dev)
+{
+	return at91_pmc_clk_node_bind(dev);
+}
+
+static int sam9x5_periph_clk_probe(struct udevice *dev)
+{
+	return at91_pmc_core_probe(dev);
+}
+
+static const struct udevice_id sam9x5_periph_clk_match[] = {
+	{ .compatible = "atmel,at91sam9x5-clk-peripheral" },
+	{}
+};
+
+U_BOOT_DRIVER(sam9x5_periph_clk) = {
+	.name = "sam9x5-periph-clk",
+	.id = UCLASS_CLK,
+	.of_match = sam9x5_periph_clk_match,
+	.bind = sam9x5_periph_clk_bind,
+	.probe = sam9x5_periph_clk_probe,
+	.platdata_auto_alloc_size = sizeof(struct pmc_platdata),
+	.ops = &sam9x5_periph_clk_ops,
+};
diff --git a/drivers/clk/at91/clk-plla.c b/drivers/clk/at91/clk-plla.c
new file mode 100644
index 0000000..2a71399
--- /dev/null
+++ b/drivers/clk/at91/clk-plla.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 Atmel Corporation
+ *               Wenyou.Yang <wenyou.yang@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+#include <linux/io.h>
+#include <mach/at91_pmc.h>
+#include "pmc.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int plla_clk_enable(struct clk *clk)
+{
+	struct pmc_platdata *plat = dev_get_platdata(clk->dev);
+	struct at91_pmc *pmc = plat->reg_base;
+
+	if (readl(&pmc->sr) & AT91_PMC_LOCKA)
+		return 0;
+
+	return -EINVAL;
+}
+
+static ulong plla_clk_get_rate(struct clk *clk)
+{
+	return gd->arch.plla_rate_hz;
+}
+
+static struct clk_ops plla_clk_ops = {
+	.enable = plla_clk_enable,
+	.get_rate = plla_clk_get_rate,
+};
+
+static int plla_clk_probe(struct udevice *dev)
+{
+	return at91_pmc_core_probe(dev);
+}
+
+static const struct udevice_id plla_clk_match[] = {
+	{ .compatible = "atmel,sama5d3-clk-pll" },
+	{}
+};
+
+U_BOOT_DRIVER(at91_plla_clk) = {
+	.name = "at91-plla-clk",
+	.id = UCLASS_CLK,
+	.of_match = plla_clk_match,
+	.probe = plla_clk_probe,
+	.platdata_auto_alloc_size = sizeof(struct pmc_platdata),
+	.ops = &plla_clk_ops,
+};
diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c
new file mode 100644
index 0000000..f7666b4
--- /dev/null
+++ b/drivers/clk/at91/clk-slow.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 Atmel Corporation
+ *               Wenyou.Yang <wenyou.yang@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+
+static int at91_slow_clk_enable(struct clk *clk)
+{
+	return 0;
+}
+
+static ulong at91_slow_clk_get_rate(struct clk *clk)
+{
+	return CONFIG_SYS_AT91_SLOW_CLOCK;
+}
+
+static struct clk_ops at91_slow_clk_ops = {
+	.enable = at91_slow_clk_enable,
+	.get_rate = at91_slow_clk_get_rate,
+};
+
+static const struct udevice_id at91_slow_clk_match[] = {
+	{ .compatible = "atmel,at91sam9x5-clk-slow" },
+	{}
+};
+
+U_BOOT_DRIVER(at91_slow_clk) = {
+	.name = "at91-slow-clk",
+	.id = UCLASS_CLK,
+	.of_match = at91_slow_clk_match,
+	.ops = &at91_slow_clk_ops,
+};
diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c
new file mode 100644
index 0000000..fa80bad
--- /dev/null
+++ b/drivers/clk/at91/clk-system.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 Atmel Corporation
+ *               Wenyou.Yang <wenyou.yang@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+#include <linux/io.h>
+#include <mach/at91_pmc.h>
+#include "pmc.h"
+
+#define SYSTEM_MAX_ID		31
+
+static inline int is_pck(int id)
+{
+	return (id >= 8) && (id <= 15);
+}
+
+static int at91_system_clk_enable(struct clk *clk)
+{
+	struct pmc_platdata *plat = dev_get_platdata(clk->dev);
+	struct at91_pmc *pmc = plat->reg_base;
+	u32 mask;
+
+	if (clk->id > SYSTEM_MAX_ID)
+		return -EINVAL;
+
+	mask = BIT(clk->id);
+
+	writel(mask, &pmc->scer);
+
+	/**
+	 * For the programmable clocks the Ready status in the PMC
+	 * status register should be checked after enabling.
+	 * For other clocks this is unnecessary.
+	 */
+	if (!is_pck(clk->id))
+		return 0;
+
+	while (!(readl(&pmc->sr) & mask))
+		;
+
+	return 0;
+}
+
+static struct clk_ops at91_system_clk_ops = {
+	.enable = at91_system_clk_enable,
+};
+
+static int at91_system_clk_bind(struct udevice *dev)
+{
+	return at91_pmc_clk_node_bind(dev);
+}
+
+static int at91_system_clk_probe(struct udevice *dev)
+{
+	return at91_pmc_core_probe(dev);
+}
+
+static const struct udevice_id at91_system_clk_match[] = {
+	{ .compatible = "atmel,at91rm9200-clk-system" },
+	{}
+};
+
+U_BOOT_DRIVER(at91_system_clk) = {
+	.name = "at91-system-clk",
+	.id = UCLASS_CLK,
+	.of_match = at91_system_clk_match,
+	.bind = at91_system_clk_bind,
+	.probe = at91_system_clk_probe,
+	.platdata_auto_alloc_size = sizeof(struct pmc_platdata),
+	.ops = &at91_system_clk_ops,
+};
diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c
new file mode 100644
index 0000000..369a687
--- /dev/null
+++ b/drivers/clk/at91/clk-utmi.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2016 Atmel Corporation
+ *               Wenyou.Yang <wenyou.yang@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+#include <linux/io.h>
+#include <mach/at91_pmc.h>
+#include "pmc.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define UTMI_FIXED_MUL		40
+
+static int utmi_clk_enable(struct clk *clk)
+{
+	struct pmc_platdata *plat = dev_get_platdata(clk->dev);
+	struct at91_pmc *pmc = plat->reg_base;
+	u32 tmp;
+
+	if (readl(&pmc->sr) & AT91_PMC_LOCKU)
+		return 0;
+
+	tmp = readl(&pmc->uckr);
+	tmp |= AT91_PMC_UPLLEN |
+	       AT91_PMC_UPLLCOUNT |
+	       AT91_PMC_BIASEN;
+	writel(tmp, &pmc->uckr);
+
+	while (!(readl(&pmc->sr) & AT91_PMC_LOCKU))
+		;
+
+	return 0;
+}
+
+static ulong utmi_clk_get_rate(struct clk *clk)
+{
+	return gd->arch.main_clk_rate_hz * UTMI_FIXED_MUL;
+}
+
+static struct clk_ops utmi_clk_ops = {
+	.enable = utmi_clk_enable,
+	.get_rate = utmi_clk_get_rate,
+};
+
+static int utmi_clk_probe(struct udevice *dev)
+{
+	return at91_pmc_core_probe(dev);
+}
+
+static const struct udevice_id utmi_clk_match[] = {
+	{ .compatible = "atmel,at91sam9x5-clk-utmi" },
+	{}
+};
+
+U_BOOT_DRIVER(at91sam9x5_utmi_clk) = {
+	.name = "at91sam9x5-utmi-clk",
+	.id = UCLASS_CLK,
+	.of_match = utmi_clk_match,
+	.probe = utmi_clk_probe,
+	.platdata_auto_alloc_size = sizeof(struct pmc_platdata),
+	.ops = &utmi_clk_ops,
+};
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
new file mode 100644
index 0000000..a08d7e8
--- /dev/null
+++ b/drivers/clk/at91/pmc.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 Atmel Corporation
+ *               Wenyou.Yang <wenyou.yang@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+#include "pmc.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int at91_pmc_bind(struct udevice *dev)
+{
+	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}
+
+static const struct udevice_id at91_pmc_match[] = {
+	{ .compatible = "atmel,sama5d2-pmc" },
+	{}
+};
+
+U_BOOT_DRIVER(at91_pmc) = {
+	.name = "at91-pmc-core",
+	.id = UCLASS_CLK,
+	.of_match = at91_pmc_match,
+	.bind = at91_pmc_bind,
+};
+
+int at91_pmc_core_probe(struct udevice *dev)
+{
+	struct pmc_platdata *plat = dev_get_platdata(dev);
+
+	dev = dev_get_parent(dev);
+
+	plat->reg_base = (struct at91_pmc *)dev_get_addr_ptr(dev);
+
+	return 0;
+}
+
+int at91_pmc_clk_node_bind(struct udevice *dev)
+{
+	const void *fdt = gd->fdt_blob;
+	int offset = dev->of_offset;
+	const char *name;
+	int ret;
+
+	for (offset = fdt_first_subnode(fdt, offset);
+	     offset > 0;
+	     offset = fdt_next_subnode(fdt, offset)) {
+		name = fdt_get_name(fdt, offset, NULL);
+		if (!name)
+			return -EINVAL;
+
+		ret = device_bind_driver_to_node(dev, "clk", name,
+						 offset, NULL);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+U_BOOT_DRIVER(clk_generic) = {
+	.id	= UCLASS_CLK,
+	.name	= "clk",
+};
diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
new file mode 100644
index 0000000..5444c84
--- /dev/null
+++ b/drivers/clk/at91/pmc.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2016 Atmel Corporation
+ *               Wenyou.Yang <wenyou.yang@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __AT91_PMC_H__
+#define __AT91_PMC_H__
+
+struct pmc_platdata {
+	struct at91_pmc *reg_base;
+};
+
+int at91_pmc_core_probe(struct udevice *dev);
+int at91_pmc_clk_node_bind(struct udevice *dev);
+
+#endif
diff --git a/drivers/clk/at91/sckc.c b/drivers/clk/at91/sckc.c
new file mode 100644
index 0000000..b207611
--- /dev/null
+++ b/drivers/clk/at91/sckc.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 Atmel Corporation
+ *               Wenyou.Yang <wenyou.yang@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+#include <dm/root.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int at91_sckc_clk_bind(struct udevice *dev)
+{
+	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}
+
+static const struct udevice_id at91_sckc_clk_match[] = {
+	{ .compatible = "atmel,at91sam9x5-sckc" },
+	{}
+};
+
+U_BOOT_DRIVER(at91_sckc_clk) = {
+	.name = "at91_sckc_clk",
+	.id = UCLASS_CLK,
+	.of_match = at91_sckc_clk_match,
+	.bind = at91_sckc_clk_bind,
+};
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 6e4d672..4d78e3f 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -10,6 +10,7 @@
 #include <clk.h>
 #include <clk-uclass.h>
 #include <dm.h>
+#include <dt-structs.h>
 #include <errno.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -20,31 +21,22 @@
 }
 
 #if CONFIG_IS_ENABLED(OF_CONTROL)
-#ifdef CONFIG_SPL_BUILD
-int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
+# if CONFIG_IS_ENABLED(OF_PLATDATA)
+int clk_get_by_index_platdata(struct udevice *dev, int index,
+			      struct phandle_2_cell *cells, struct clk *clk)
 {
 	int ret;
-	u32 cell[2];
 
 	if (index != 0)
 		return -ENOSYS;
-	assert(clk);
 	ret = uclass_get_device(UCLASS_CLK, 0, &clk->dev);
 	if (ret)
 		return ret;
-	ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clocks",
-				   cell, 2);
-	if (ret)
-		return ret;
-	clk->id = cell[1];
-	return 0;
-}
+	clk->id = cells[0].id;
 
-int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
-{
-	return -ENOSYS;
+	return 0;
 }
-#else
+# else
 static int clk_of_xlate_default(struct clk *clk,
 				struct fdtdec_phandle_args *args)
 {
@@ -101,6 +93,7 @@
 
 	return clk_request(dev_clk, clk);
 }
+# endif /* OF_PLATDATA */
 
 int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
 {
@@ -117,8 +110,7 @@
 
 	return clk_get_by_index(dev, index, clk);
 }
-#endif
-#endif
+#endif /* OF_CONTROL */
 
 int clk_request(struct udevice *dev, struct clk *clk)
 {
diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c
index 797e537..9c4d2b3 100644
--- a/drivers/clk/clk_fixed_rate.c
+++ b/drivers/clk/clk_fixed_rate.c
@@ -30,9 +30,11 @@
 
 static int clk_fixed_rate_ofdata_to_platdata(struct udevice *dev)
 {
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	to_clk_fixed_rate(dev)->fixed_rate =
 				fdtdec_get_int(gd->fdt_blob, dev->of_offset,
 					       "clock-frequency", 0);
+#endif
 
 	return 0;
 }
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
new file mode 100644
index 0000000..1f8e417
--- /dev/null
+++ b/drivers/clk/rockchip/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright (c) 2016 Google, Inc
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+obj-$(CONFIG_ROCKCHIP_RK3036) += clk_rk3036.o
+obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
+obj-$(CONFIG_ROCKCHIP_RK3399) += clk_rk3399.o
diff --git a/drivers/clk/clk_rk3036.c b/drivers/clk/rockchip/clk_rk3036.c
similarity index 97%
rename from drivers/clk/clk_rk3036.c
rename to drivers/clk/rockchip/clk_rk3036.c
index 6202c9d..8899b0c 100644
--- a/drivers/clk/clk_rk3036.c
+++ b/drivers/clk/rockchip/clk_rk3036.c
@@ -15,6 +15,7 @@
 #include <asm/arch/hardware.h>
 #include <dm/lists.h>
 #include <dt-bindings/clock/rk3036-cru.h>
+#include <linux/log2.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -48,11 +49,6 @@
 static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 3, 1);
 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2, 1);
 
-static inline unsigned int log2(unsigned int value)
-{
-	return fls(value) - 1;
-}
-
 void *rockchip_get_cru(void)
 {
 	struct udevice *dev;
@@ -177,11 +173,11 @@
 	aclk_div = GPLL_HZ / PERI_ACLK_HZ - 1;
 	assert((aclk_div + 1) * PERI_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
 
-	hclk_div = log2(PERI_ACLK_HZ / PERI_HCLK_HZ);
+	hclk_div = ilog2(PERI_ACLK_HZ / PERI_HCLK_HZ);
 	assert((1 << hclk_div) * PERI_HCLK_HZ ==
 		PERI_ACLK_HZ && (pclk_div < 0x4));
 
-	pclk_div = log2(PERI_ACLK_HZ / PERI_PCLK_HZ);
+	pclk_div = ilog2(PERI_ACLK_HZ / PERI_PCLK_HZ);
 	assert((1 << pclk_div) * PERI_PCLK_HZ ==
 		PERI_ACLK_HZ && pclk_div < 0x8);
 
diff --git a/drivers/clk/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c
similarity index 95%
rename from drivers/clk/clk_rk3288.c
rename to drivers/clk/rockchip/clk_rk3288.c
index 2285453..c07203d 100644
--- a/drivers/clk/clk_rk3288.c
+++ b/drivers/clk/rockchip/clk_rk3288.c
@@ -7,7 +7,9 @@
 #include <common.h>
 #include <clk-uclass.h>
 #include <dm.h>
+#include <dt-structs.h>
 #include <errno.h>
+#include <mapmem.h>
 #include <syscon.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
@@ -18,9 +20,16 @@
 #include <dm/device-internal.h>
 #include <dm/lists.h>
 #include <dm/uclass-internal.h>
+#include <linux/log2.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+struct rk3288_clk_plat {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_rockchip_rk3288_cru dtd;
+#endif
+};
+
 struct rk3288_clk_priv {
 	struct rk3288_grf *grf;
 	struct rk3288_cru *cru;
@@ -39,7 +48,7 @@
 	OUTPUT_MAX_HZ	= 2200U * 1000000,
 	OUTPUT_MIN_HZ	= 27500000,
 	FREF_MAX_HZ	= 2200U * 1000000,
-	FREF_MIN_HZ	= 269 * 1000000,
+	FREF_MIN_HZ	= 269 * 1000,
 };
 
 enum {
@@ -137,7 +146,7 @@
 	struct udevice *dev;
 	int ret;
 
-	ret = uclass_get_device(UCLASS_CLK, 0, &dev);
+	ret = rockchip_get_clk(&dev);
 	if (ret)
 		return ERR_PTR(ret);
 
@@ -178,11 +187,6 @@
 	return 0;
 }
 
-static inline unsigned int log2(unsigned int value)
-{
-	return fls(value) - 1;
-}
-
 static int rkclk_configure_ddr(struct rk3288_cru *cru, struct rk3288_grf *grf,
 			       unsigned int hz)
 {
@@ -413,11 +417,11 @@
 	aclk_div = GPLL_HZ / PERI_ACLK_HZ - 1;
 	assert((aclk_div + 1) * PERI_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
 
-	hclk_div = log2(PERI_ACLK_HZ / PERI_HCLK_HZ);
+	hclk_div = ilog2(PERI_ACLK_HZ / PERI_HCLK_HZ);
 	assert((1 << hclk_div) * PERI_HCLK_HZ ==
 		PERI_ACLK_HZ && (hclk_div < 0x4));
 
-	pclk_div = log2(PERI_ACLK_HZ / PERI_PCLK_HZ);
+	pclk_div = ilog2(PERI_ACLK_HZ / PERI_PCLK_HZ);
 	assert((1 << pclk_div) * PERI_PCLK_HZ ==
 		PERI_ACLK_HZ && (pclk_div < 0x4));
 
@@ -439,7 +443,7 @@
 }
 #endif
 
-void rkclk_configure_cpu(struct rk3288_cru *cru, struct rk3288_grf *grf)
+void rk3288_clk_configure_cpu(struct rk3288_cru *cru, struct rk3288_grf *grf)
 {
 	/* pll enter slow-mode */
 	rk_clrsetreg(&cru->cru_mode_con,
@@ -783,13 +787,30 @@
 	.set_rate	= rk3288_clk_set_rate,
 };
 
-static int rk3288_clk_probe(struct udevice *dev)
+static int rk3288_clk_ofdata_to_platdata(struct udevice *dev)
 {
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	struct rk3288_clk_priv *priv = dev_get_priv(dev);
 
 	priv->cru = (struct rk3288_cru *)dev_get_addr(dev);
+#endif
+
+	return 0;
+}
+
+static int rk3288_clk_probe(struct udevice *dev)
+{
+	struct rk3288_clk_priv *priv = dev_get_priv(dev);
+
 	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	if (IS_ERR(priv->grf))
+		return PTR_ERR(priv->grf);
 #ifdef CONFIG_SPL_BUILD
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct rk3288_clk_plat *plat = dev_get_platdata(dev);
+
+	priv->cru = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]);
+#endif
 	rkclk_init(priv->cru, priv->grf);
 #endif
 
@@ -813,12 +834,14 @@
 	{ }
 };
 
-U_BOOT_DRIVER(clk_rk3288) = {
-	.name		= "clk_rk3288",
+U_BOOT_DRIVER(rockchip_rk3288_cru) = {
+	.name		= "rockchip_rk3288_cru",
 	.id		= UCLASS_CLK,
 	.of_match	= rk3288_clk_ids,
 	.priv_auto_alloc_size = sizeof(struct rk3288_clk_priv),
+	.platdata_auto_alloc_size = sizeof(struct rk3288_clk_plat),
 	.ops		= &rk3288_clk_ops,
 	.bind		= rk3288_clk_bind,
+	.ofdata_to_platdata	= rk3288_clk_ofdata_to_platdata,
 	.probe		= rk3288_clk_probe,
 };
diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c
new file mode 100644
index 0000000..0b4ea82
--- /dev/null
+++ b/drivers/clk/rockchip/clk_rk3399.c
@@ -0,0 +1,832 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk3399.h>
+#include <asm/arch/hardware.h>
+#include <dm/lists.h>
+#include <dt-bindings/clock/rk3399-cru.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct rk3399_clk_priv {
+	struct rk3399_cru *cru;
+	ulong rate;
+};
+
+struct pll_div {
+	u32 refdiv;
+	u32 fbdiv;
+	u32 postdiv1;
+	u32 postdiv2;
+	u32 frac;
+};
+
+#define RATE_TO_DIV(input_rate, output_rate) \
+	((input_rate) / (output_rate) - 1);
+#define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
+
+#define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\
+	.refdiv = _refdiv,\
+	.fbdiv = (u32)((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ),\
+	.postdiv1 = _postdiv1, .postdiv2 = _postdiv2};
+
+static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2, 1);
+static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2, 2);
+static const struct pll_div ppll_init_cfg = PLL_DIVISORS(PPLL_HZ, 2, 2, 1);
+
+static const struct pll_div apll_l_1600_cfg = PLL_DIVISORS(1600*MHz, 3, 1, 1);
+static const struct pll_div apll_l_600_cfg = PLL_DIVISORS(600*MHz, 1, 2, 1);
+
+static const struct pll_div *apll_l_cfgs[] = {
+	[APLL_L_1600_MHZ] = &apll_l_1600_cfg,
+	[APLL_L_600_MHZ] = &apll_l_600_cfg,
+};
+
+enum {
+	/* PLL_CON0 */
+	PLL_FBDIV_MASK			= 0xfff,
+	PLL_FBDIV_SHIFT			= 0,
+
+	/* PLL_CON1 */
+	PLL_POSTDIV2_SHIFT		= 12,
+	PLL_POSTDIV2_MASK		= 0x7 << PLL_POSTDIV2_SHIFT,
+	PLL_POSTDIV1_SHIFT		= 8,
+	PLL_POSTDIV1_MASK		= 0x7 << PLL_POSTDIV1_SHIFT,
+	PLL_REFDIV_MASK			= 0x3f,
+	PLL_REFDIV_SHIFT		= 0,
+
+	/* PLL_CON2 */
+	PLL_LOCK_STATUS_SHIFT		= 31,
+	PLL_LOCK_STATUS_MASK		= 1 << PLL_LOCK_STATUS_SHIFT,
+	PLL_FRACDIV_MASK		= 0xffffff,
+	PLL_FRACDIV_SHIFT		= 0,
+
+	/* PLL_CON3 */
+	PLL_MODE_SHIFT			= 8,
+	PLL_MODE_MASK			= 3 << PLL_MODE_SHIFT,
+	PLL_MODE_SLOW			= 0,
+	PLL_MODE_NORM,
+	PLL_MODE_DEEP,
+	PLL_DSMPD_SHIFT			= 3,
+	PLL_DSMPD_MASK			= 1 << PLL_DSMPD_SHIFT,
+	PLL_INTEGER_MODE		= 1,
+
+	/* PMUCRU_CLKSEL_CON0 */
+	PMU_PCLK_DIV_CON_MASK		= 0x1f,
+	PMU_PCLK_DIV_CON_SHIFT		= 0,
+
+	/* PMUCRU_CLKSEL_CON1 */
+	SPI3_PLL_SEL_SHIFT		= 7,
+	SPI3_PLL_SEL_MASK		= 1 << SPI3_PLL_SEL_SHIFT,
+	SPI3_PLL_SEL_24M		= 0,
+	SPI3_PLL_SEL_PPLL		= 1,
+	SPI3_DIV_CON_SHIFT		= 0x0,
+	SPI3_DIV_CON_MASK		= 0x7f,
+
+	/* PMUCRU_CLKSEL_CON2 */
+	I2C_DIV_CON_MASK		= 0x7f,
+	I2C8_DIV_CON_SHIFT		= 8,
+	I2C0_DIV_CON_SHIFT		= 0,
+
+	/* PMUCRU_CLKSEL_CON3 */
+	I2C4_DIV_CON_SHIFT		= 0,
+
+	/* CLKSEL_CON0 */
+	ACLKM_CORE_L_DIV_CON_SHIFT	= 8,
+	ACLKM_CORE_L_DIV_CON_MASK	= 0x1f << ACLKM_CORE_L_DIV_CON_SHIFT,
+	CLK_CORE_L_PLL_SEL_SHIFT	= 6,
+	CLK_CORE_L_PLL_SEL_MASK		= 3 << CLK_CORE_L_PLL_SEL_SHIFT,
+	CLK_CORE_L_PLL_SEL_ALPLL	= 0x0,
+	CLK_CORE_L_PLL_SEL_ABPLL	= 0x1,
+	CLK_CORE_L_PLL_SEL_DPLL		= 0x10,
+	CLK_CORE_L_PLL_SEL_GPLL		= 0x11,
+	CLK_CORE_L_DIV_MASK		= 0x1f,
+	CLK_CORE_L_DIV_SHIFT		= 0,
+
+	/* CLKSEL_CON1 */
+	PCLK_DBG_L_DIV_SHIFT		= 0x8,
+	PCLK_DBG_L_DIV_MASK		= 0x1f << PCLK_DBG_L_DIV_SHIFT,
+	ATCLK_CORE_L_DIV_SHIFT		= 0,
+	ATCLK_CORE_L_DIV_MASK		= 0x1f << ATCLK_CORE_L_DIV_SHIFT,
+
+	/* CLKSEL_CON14 */
+	PCLK_PERIHP_DIV_CON_SHIFT	= 12,
+	PCLK_PERIHP_DIV_CON_MASK	= 0x7 << PCLK_PERIHP_DIV_CON_SHIFT,
+	HCLK_PERIHP_DIV_CON_SHIFT	= 8,
+	HCLK_PERIHP_DIV_CON_MASK	= 3 << HCLK_PERIHP_DIV_CON_SHIFT,
+	ACLK_PERIHP_PLL_SEL_SHIFT	= 7,
+	ACLK_PERIHP_PLL_SEL_MASK	= 1 << ACLK_PERIHP_PLL_SEL_SHIFT,
+	ACLK_PERIHP_PLL_SEL_CPLL	= 0,
+	ACLK_PERIHP_PLL_SEL_GPLL	= 1,
+	ACLK_PERIHP_DIV_CON_SHIFT	= 0,
+	ACLK_PERIHP_DIV_CON_MASK	= 0x1f,
+
+	/* CLKSEL_CON21 */
+	ACLK_EMMC_PLL_SEL_SHIFT         = 7,
+	ACLK_EMMC_PLL_SEL_MASK          = 0x1 << ACLK_EMMC_PLL_SEL_SHIFT,
+	ACLK_EMMC_PLL_SEL_GPLL          = 0x1,
+	ACLK_EMMC_DIV_CON_SHIFT         = 0,
+	ACLK_EMMC_DIV_CON_MASK          = 0x1f,
+
+	/* CLKSEL_CON22 */
+	CLK_EMMC_PLL_SHIFT              = 8,
+	CLK_EMMC_PLL_MASK               = 0x7 << CLK_EMMC_PLL_SHIFT,
+	CLK_EMMC_PLL_SEL_GPLL           = 0x1,
+	CLK_EMMC_PLL_SEL_24M            = 0x5,
+	CLK_EMMC_DIV_CON_SHIFT          = 0,
+	CLK_EMMC_DIV_CON_MASK           = 0x7f << CLK_EMMC_DIV_CON_SHIFT,
+
+	/* CLKSEL_CON23 */
+	PCLK_PERILP0_DIV_CON_SHIFT	= 12,
+	PCLK_PERILP0_DIV_CON_MASK	= 0x7 << PCLK_PERILP0_DIV_CON_SHIFT,
+	HCLK_PERILP0_DIV_CON_SHIFT	= 8,
+	HCLK_PERILP0_DIV_CON_MASK	= 3 << HCLK_PERILP0_DIV_CON_SHIFT,
+	ACLK_PERILP0_PLL_SEL_SHIFT	= 7,
+	ACLK_PERILP0_PLL_SEL_MASK	= 1 << ACLK_PERILP0_PLL_SEL_SHIFT,
+	ACLK_PERILP0_PLL_SEL_CPLL	= 0,
+	ACLK_PERILP0_PLL_SEL_GPLL	= 1,
+	ACLK_PERILP0_DIV_CON_SHIFT	= 0,
+	ACLK_PERILP0_DIV_CON_MASK	= 0x1f,
+
+	/* CLKSEL_CON25 */
+	PCLK_PERILP1_DIV_CON_SHIFT	= 8,
+	PCLK_PERILP1_DIV_CON_MASK	= 0x7 << PCLK_PERILP1_DIV_CON_SHIFT,
+	HCLK_PERILP1_PLL_SEL_SHIFT	= 7,
+	HCLK_PERILP1_PLL_SEL_MASK	= 1 << HCLK_PERILP1_PLL_SEL_SHIFT,
+	HCLK_PERILP1_PLL_SEL_CPLL	= 0,
+	HCLK_PERILP1_PLL_SEL_GPLL	= 1,
+	HCLK_PERILP1_DIV_CON_SHIFT	= 0,
+	HCLK_PERILP1_DIV_CON_MASK	= 0x1f,
+
+	/* CLKSEL_CON26 */
+	CLK_SARADC_DIV_CON_SHIFT	= 8,
+	CLK_SARADC_DIV_CON_MASK		= 0xff << CLK_SARADC_DIV_CON_SHIFT,
+
+	/* CLKSEL_CON27 */
+	CLK_TSADC_SEL_X24M		= 0x0,
+	CLK_TSADC_SEL_SHIFT		= 15,
+	CLK_TSADC_SEL_MASK		= 1 << CLK_TSADC_SEL_SHIFT,
+	CLK_TSADC_DIV_CON_SHIFT		= 0,
+	CLK_TSADC_DIV_CON_MASK		= 0x3ff,
+
+	/* CLKSEL_CON47 & CLKSEL_CON48 */
+	ACLK_VOP_PLL_SEL_SHIFT		= 6,
+	ACLK_VOP_PLL_SEL_MASK		= 0x3 << ACLK_VOP_PLL_SEL_SHIFT,
+	ACLK_VOP_PLL_SEL_CPLL		= 0x1,
+	ACLK_VOP_DIV_CON_SHIFT		= 0,
+	ACLK_VOP_DIV_CON_MASK		= 0x1f << ACLK_VOP_DIV_CON_SHIFT,
+
+	/* CLKSEL_CON49 & CLKSEL_CON50 */
+	DCLK_VOP_DCLK_SEL_SHIFT         = 11,
+	DCLK_VOP_DCLK_SEL_MASK          = 1 << DCLK_VOP_DCLK_SEL_SHIFT,
+	DCLK_VOP_DCLK_SEL_DIVOUT        = 0,
+	DCLK_VOP_PLL_SEL_SHIFT          = 8,
+	DCLK_VOP_PLL_SEL_MASK           = 3 << DCLK_VOP_PLL_SEL_SHIFT,
+	DCLK_VOP_PLL_SEL_VPLL           = 0,
+	DCLK_VOP_DIV_CON_MASK           = 0xff,
+	DCLK_VOP_DIV_CON_SHIFT          = 0,
+
+	/* CLKSEL_CON58 */
+	CLK_SPI_PLL_SEL_MASK		= 1,
+	CLK_SPI_PLL_SEL_CPLL		= 0,
+	CLK_SPI_PLL_SEL_GPLL		= 1,
+	CLK_SPI_PLL_DIV_CON_MASK	= 0x7f,
+	CLK_SPI5_PLL_DIV_CON_SHIFT	= 8,
+	CLK_SPI5_PLL_SEL_SHIFT		= 15,
+
+	/* CLKSEL_CON59 */
+	CLK_SPI1_PLL_SEL_SHIFT		= 15,
+	CLK_SPI1_PLL_DIV_CON_SHIFT	= 8,
+	CLK_SPI0_PLL_SEL_SHIFT		= 7,
+	CLK_SPI0_PLL_DIV_CON_SHIFT	= 0,
+
+	/* CLKSEL_CON60 */
+	CLK_SPI4_PLL_SEL_SHIFT		= 15,
+	CLK_SPI4_PLL_DIV_CON_SHIFT	= 8,
+	CLK_SPI2_PLL_SEL_SHIFT		= 7,
+	CLK_SPI2_PLL_DIV_CON_SHIFT	= 0,
+
+	/* CLKSEL_CON61 */
+	CLK_I2C_PLL_SEL_MASK		= 1,
+	CLK_I2C_PLL_SEL_CPLL		= 0,
+	CLK_I2C_PLL_SEL_GPLL		= 1,
+	CLK_I2C5_PLL_SEL_SHIFT		= 15,
+	CLK_I2C5_DIV_CON_SHIFT		= 8,
+	CLK_I2C1_PLL_SEL_SHIFT		= 7,
+	CLK_I2C1_DIV_CON_SHIFT		= 0,
+
+	/* CLKSEL_CON62 */
+	CLK_I2C6_PLL_SEL_SHIFT		= 15,
+	CLK_I2C6_DIV_CON_SHIFT		= 8,
+	CLK_I2C2_PLL_SEL_SHIFT		= 7,
+	CLK_I2C2_DIV_CON_SHIFT		= 0,
+
+	/* CLKSEL_CON63 */
+	CLK_I2C7_PLL_SEL_SHIFT		= 15,
+	CLK_I2C7_DIV_CON_SHIFT		= 8,
+	CLK_I2C3_PLL_SEL_SHIFT		= 7,
+	CLK_I2C3_DIV_CON_SHIFT		= 0,
+
+	/* CRU_SOFTRST_CON4 */
+	RESETN_DDR0_REQ_SHIFT		= 8,
+	RESETN_DDR0_REQ_MASK		= 1 << RESETN_DDR0_REQ_SHIFT,
+	RESETN_DDRPHY0_REQ_SHIFT	= 9,
+	RESETN_DDRPHY0_REQ_MASK		= 1 << RESETN_DDRPHY0_REQ_SHIFT,
+	RESETN_DDR1_REQ_SHIFT		= 12,
+	RESETN_DDR1_REQ_MASK		= 1 << RESETN_DDR1_REQ_SHIFT,
+	RESETN_DDRPHY1_REQ_SHIFT	= 13,
+	RESETN_DDRPHY1_REQ_MASK		= 1 << RESETN_DDRPHY1_REQ_SHIFT,
+};
+
+#define VCO_MAX_KHZ	(3200 * (MHz / KHz))
+#define VCO_MIN_KHZ	(800 * (MHz / KHz))
+#define OUTPUT_MAX_KHZ	(3200 * (MHz / KHz))
+#define OUTPUT_MIN_KHZ	(16 * (MHz / KHz))
+
+/*
+ *  the div restructions of pll in integer mode, these are defined in
+ *  * CRU_*PLL_CON0 or PMUCRU_*PLL_CON0
+ */
+#define PLL_DIV_MIN	16
+#define PLL_DIV_MAX	3200
+
+/*
+ * How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
+ * Formulas also embedded within the Fractional PLL Verilog model:
+ * If DSMPD = 1 (DSM is disabled, "integer mode")
+ * FOUTVCO = FREF / REFDIV * FBDIV
+ * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
+ * Where:
+ * FOUTVCO = Fractional PLL non-divided output frequency
+ * FOUTPOSTDIV = Fractional PLL divided output frequency
+ *               (output of second post divider)
+ * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
+ * REFDIV = Fractional PLL input reference clock divider
+ * FBDIV = Integer value programmed into feedback divide
+ *
+ */
+static void rkclk_set_pll(u32 *pll_con, const struct pll_div *div)
+{
+	/* All 8 PLLs have same VCO and output frequency range restrictions. */
+	u32 vco_khz = OSC_HZ / 1000 * div->fbdiv / div->refdiv;
+	u32 output_khz = vco_khz / div->postdiv1 / div->postdiv2;
+
+	debug("PLL at %p: fbdiv=%d, refdiv=%d, postdiv1=%d, "
+			   "postdiv2=%d, vco=%u khz, output=%u khz\n",
+			   pll_con, div->fbdiv, div->refdiv, div->postdiv1,
+			   div->postdiv2, vco_khz, output_khz);
+	assert(vco_khz >= VCO_MIN_KHZ && vco_khz <= VCO_MAX_KHZ &&
+	       output_khz >= OUTPUT_MIN_KHZ && output_khz <= OUTPUT_MAX_KHZ &&
+	       div->fbdiv >= PLL_DIV_MIN && div->fbdiv <= PLL_DIV_MAX);
+
+	/*
+	 * When power on or changing PLL setting,
+	 * we must force PLL into slow mode to ensure output stable clock.
+	 */
+	rk_clrsetreg(&pll_con[3], PLL_MODE_MASK,
+		     PLL_MODE_SLOW << PLL_MODE_SHIFT);
+
+	/* use integer mode */
+	rk_clrsetreg(&pll_con[3], PLL_DSMPD_MASK,
+		     PLL_INTEGER_MODE << PLL_DSMPD_SHIFT);
+
+	rk_clrsetreg(&pll_con[0], PLL_FBDIV_MASK,
+		     div->fbdiv << PLL_FBDIV_SHIFT);
+	rk_clrsetreg(&pll_con[1],
+		     PLL_POSTDIV2_MASK | PLL_POSTDIV1_MASK |
+		     PLL_REFDIV_MASK | PLL_REFDIV_SHIFT,
+		     (div->postdiv2 << PLL_POSTDIV2_SHIFT) |
+		     (div->postdiv1 << PLL_POSTDIV1_SHIFT) |
+		     (div->refdiv << PLL_REFDIV_SHIFT));
+
+	/* waiting for pll lock */
+	while (!(readl(&pll_con[2]) & (1 << PLL_LOCK_STATUS_SHIFT)))
+		udelay(1);
+
+	/* pll enter normal mode */
+	rk_clrsetreg(&pll_con[3], PLL_MODE_MASK,
+		     PLL_MODE_NORM << PLL_MODE_SHIFT);
+}
+
+static int pll_para_config(u32 freq_hz, struct pll_div *div)
+{
+	u32 ref_khz = OSC_HZ / KHz, refdiv, fbdiv = 0;
+	u32 postdiv1, postdiv2 = 1;
+	u32 fref_khz;
+	u32 diff_khz, best_diff_khz;
+	const u32 max_refdiv = 63, max_fbdiv = 3200, min_fbdiv = 16;
+	const u32 max_postdiv1 = 7, max_postdiv2 = 7;
+	u32 vco_khz;
+	u32 freq_khz = freq_hz / KHz;
+
+	if (!freq_hz) {
+		printf("%s: the frequency can't be 0 Hz\n", __func__);
+		return -1;
+	}
+
+	postdiv1 = DIV_ROUND_UP(VCO_MIN_KHZ, freq_khz);
+	if (postdiv1 > max_postdiv1) {
+		postdiv2 = DIV_ROUND_UP(postdiv1, max_postdiv1);
+		postdiv1 = DIV_ROUND_UP(postdiv1, postdiv2);
+	}
+
+	vco_khz = freq_khz * postdiv1 * postdiv2;
+
+	if (vco_khz < VCO_MIN_KHZ || vco_khz > VCO_MAX_KHZ ||
+	    postdiv2 > max_postdiv2) {
+		printf("%s: Cannot find out a supported VCO"
+		       " for Frequency (%uHz).\n", __func__, freq_hz);
+		return -1;
+	}
+
+	div->postdiv1 = postdiv1;
+	div->postdiv2 = postdiv2;
+
+	best_diff_khz = vco_khz;
+	for (refdiv = 1; refdiv < max_refdiv && best_diff_khz; refdiv++) {
+		fref_khz = ref_khz / refdiv;
+
+		fbdiv = vco_khz / fref_khz;
+		if ((fbdiv >= max_fbdiv) || (fbdiv <= min_fbdiv))
+			continue;
+		diff_khz = vco_khz - fbdiv * fref_khz;
+		if (fbdiv + 1 < max_fbdiv && diff_khz > fref_khz / 2) {
+			fbdiv++;
+			diff_khz = fref_khz - diff_khz;
+		}
+
+		if (diff_khz >= best_diff_khz)
+			continue;
+
+		best_diff_khz = diff_khz;
+		div->refdiv = refdiv;
+		div->fbdiv = fbdiv;
+	}
+
+	if (best_diff_khz > 4 * (MHz/KHz)) {
+		printf("%s: Failed to match output frequency %u, "
+		       "difference is %u Hz,exceed 4MHZ\n", __func__, freq_hz,
+		       best_diff_khz * KHz);
+		return -1;
+	}
+	return 0;
+}
+
+static void rkclk_init(struct rk3399_cru *cru)
+{
+	u32 aclk_div;
+	u32 hclk_div;
+	u32 pclk_div;
+
+	/*
+	 * some cru registers changed by bootrom, we'd better reset them to
+	 * reset/default values described in TRM to avoid confusion in kernel.
+	 * Please consider these three lines as a fix of bootrom bug.
+	 */
+	rk_clrsetreg(&cru->clksel_con[12], 0xffff, 0x4101);
+	rk_clrsetreg(&cru->clksel_con[19], 0xffff, 0x033f);
+	rk_clrsetreg(&cru->clksel_con[56], 0x0003, 0x0003);
+
+	/* configure gpll cpll */
+	rkclk_set_pll(&cru->gpll_con[0], &gpll_init_cfg);
+	rkclk_set_pll(&cru->cpll_con[0], &cpll_init_cfg);
+
+	/* configure perihp aclk, hclk, pclk */
+	aclk_div = GPLL_HZ / PERIHP_ACLK_HZ - 1;
+	assert((aclk_div + 1) * PERIHP_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
+
+	hclk_div = PERIHP_ACLK_HZ / PERIHP_HCLK_HZ - 1;
+	assert((hclk_div + 1) * PERIHP_HCLK_HZ ==
+	       PERIHP_ACLK_HZ && (hclk_div < 0x4));
+
+	pclk_div = PERIHP_ACLK_HZ / PERIHP_PCLK_HZ - 1;
+	assert((pclk_div + 1) * PERIHP_PCLK_HZ ==
+	       PERIHP_ACLK_HZ && (pclk_div < 0x7));
+
+	rk_clrsetreg(&cru->clksel_con[14],
+		     PCLK_PERIHP_DIV_CON_MASK | HCLK_PERIHP_DIV_CON_MASK |
+		     ACLK_PERIHP_PLL_SEL_MASK | ACLK_PERIHP_DIV_CON_MASK,
+		     pclk_div << PCLK_PERIHP_DIV_CON_SHIFT |
+		     hclk_div << HCLK_PERIHP_DIV_CON_SHIFT |
+		     ACLK_PERIHP_PLL_SEL_GPLL << ACLK_PERIHP_PLL_SEL_SHIFT |
+		     aclk_div << ACLK_PERIHP_DIV_CON_SHIFT);
+
+	/* configure perilp0 aclk, hclk, pclk */
+	aclk_div = GPLL_HZ / PERILP0_ACLK_HZ - 1;
+	assert((aclk_div + 1) * PERILP0_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
+
+	hclk_div = PERILP0_ACLK_HZ / PERILP0_HCLK_HZ - 1;
+	assert((hclk_div + 1) * PERILP0_HCLK_HZ ==
+	       PERILP0_ACLK_HZ && (hclk_div < 0x4));
+
+	pclk_div = PERILP0_ACLK_HZ / PERILP0_PCLK_HZ - 1;
+	assert((pclk_div + 1) * PERILP0_PCLK_HZ ==
+	       PERILP0_ACLK_HZ && (pclk_div < 0x7));
+
+	rk_clrsetreg(&cru->clksel_con[23],
+		     PCLK_PERILP0_DIV_CON_MASK | HCLK_PERILP0_DIV_CON_MASK |
+		     ACLK_PERILP0_PLL_SEL_MASK | ACLK_PERILP0_DIV_CON_MASK,
+		     pclk_div << PCLK_PERILP0_DIV_CON_SHIFT |
+		     hclk_div << HCLK_PERILP0_DIV_CON_SHIFT |
+		     ACLK_PERILP0_PLL_SEL_GPLL << ACLK_PERILP0_PLL_SEL_SHIFT |
+		     aclk_div << ACLK_PERILP0_DIV_CON_SHIFT);
+
+	/* perilp1 hclk select gpll as source */
+	hclk_div = GPLL_HZ / PERILP1_HCLK_HZ - 1;
+	assert((hclk_div + 1) * PERILP1_HCLK_HZ ==
+	       GPLL_HZ && (hclk_div < 0x1f));
+
+	pclk_div = PERILP1_HCLK_HZ / PERILP1_HCLK_HZ - 1;
+	assert((pclk_div + 1) * PERILP1_HCLK_HZ ==
+	       PERILP1_HCLK_HZ && (hclk_div < 0x7));
+
+	rk_clrsetreg(&cru->clksel_con[25],
+		     PCLK_PERILP1_DIV_CON_MASK | HCLK_PERILP1_DIV_CON_MASK |
+		     HCLK_PERILP1_PLL_SEL_MASK,
+		     pclk_div << PCLK_PERILP1_DIV_CON_SHIFT |
+		     hclk_div << HCLK_PERILP1_DIV_CON_SHIFT |
+		     HCLK_PERILP1_PLL_SEL_GPLL << HCLK_PERILP1_PLL_SEL_SHIFT);
+}
+
+void rk3399_configure_cpu(struct rk3399_cru *cru,
+			  enum apll_l_frequencies apll_l_freq)
+{
+	u32 aclkm_div;
+	u32 pclk_dbg_div;
+	u32 atclk_div;
+
+	rkclk_set_pll(&cru->apll_l_con[0], apll_l_cfgs[apll_l_freq]);
+
+	aclkm_div = APLL_HZ / ACLKM_CORE_HZ - 1;
+	assert((aclkm_div + 1) * ACLKM_CORE_HZ == APLL_HZ &&
+	       aclkm_div < 0x1f);
+
+	pclk_dbg_div = APLL_HZ / PCLK_DBG_HZ - 1;
+	assert((pclk_dbg_div + 1) * PCLK_DBG_HZ == APLL_HZ &&
+	       pclk_dbg_div < 0x1f);
+
+	atclk_div = APLL_HZ / ATCLK_CORE_HZ - 1;
+	assert((atclk_div + 1) * ATCLK_CORE_HZ == APLL_HZ &&
+	       atclk_div < 0x1f);
+
+	rk_clrsetreg(&cru->clksel_con[0],
+		     ACLKM_CORE_L_DIV_CON_MASK | CLK_CORE_L_PLL_SEL_MASK |
+		     CLK_CORE_L_DIV_MASK,
+		     aclkm_div << ACLKM_CORE_L_DIV_CON_SHIFT |
+		     CLK_CORE_L_PLL_SEL_ALPLL << CLK_CORE_L_PLL_SEL_SHIFT |
+		     0 << CLK_CORE_L_DIV_SHIFT);
+
+	rk_clrsetreg(&cru->clksel_con[1],
+		     PCLK_DBG_L_DIV_MASK | ATCLK_CORE_L_DIV_MASK,
+		     pclk_dbg_div << PCLK_DBG_L_DIV_SHIFT |
+		     atclk_div << ATCLK_CORE_L_DIV_SHIFT);
+}
+#define I2C_CLK_REG_MASK(bus) \
+			(I2C_DIV_CON_MASK << \
+			CLK_I2C ##bus## _DIV_CON_SHIFT | \
+			CLK_I2C_PLL_SEL_MASK << \
+			CLK_I2C ##bus## _PLL_SEL_SHIFT)
+
+#define I2C_CLK_REG_VALUE(bus, clk_div) \
+			      ((clk_div - 1) << \
+					CLK_I2C ##bus## _DIV_CON_SHIFT | \
+			      CLK_I2C_PLL_SEL_GPLL << \
+					CLK_I2C ##bus## _PLL_SEL_SHIFT)
+
+#define I2C_CLK_DIV_VALUE(con, bus) \
+			(con >> CLK_I2C ##bus## _DIV_CON_SHIFT) & \
+				I2C_DIV_CON_MASK;
+
+static ulong rk3399_i2c_get_clk(struct rk3399_cru *cru, ulong clk_id)
+{
+	u32 div, con;
+
+	switch (clk_id) {
+	case SCLK_I2C1:
+		con = readl(&cru->clksel_con[61]);
+		div = I2C_CLK_DIV_VALUE(con, 1);
+		break;
+	case SCLK_I2C2:
+		con = readl(&cru->clksel_con[62]);
+		div = I2C_CLK_DIV_VALUE(con, 2);
+		break;
+	case SCLK_I2C3:
+		con = readl(&cru->clksel_con[63]);
+		div = I2C_CLK_DIV_VALUE(con, 3);
+		break;
+	case SCLK_I2C5:
+		con = readl(&cru->clksel_con[61]);
+		div = I2C_CLK_DIV_VALUE(con, 5);
+		break;
+	case SCLK_I2C6:
+		con = readl(&cru->clksel_con[62]);
+		div = I2C_CLK_DIV_VALUE(con, 6);
+		break;
+	case SCLK_I2C7:
+		con = readl(&cru->clksel_con[63]);
+		div = I2C_CLK_DIV_VALUE(con, 7);
+		break;
+	default:
+		printf("do not support this i2c bus\n");
+		return -EINVAL;
+	}
+
+	return DIV_TO_RATE(GPLL_HZ, div);
+}
+
+static ulong rk3399_i2c_set_clk(struct rk3399_cru *cru, ulong clk_id, uint hz)
+{
+	int src_clk_div;
+
+	/* i2c0,4,8 src clock from ppll, i2c1,2,3,5,6,7 src clock from gpll*/
+	src_clk_div = GPLL_HZ / hz;
+	assert(src_clk_div - 1 < 127);
+
+	switch (clk_id) {
+	case SCLK_I2C1:
+		rk_clrsetreg(&cru->clksel_con[61], I2C_CLK_REG_MASK(1),
+			     I2C_CLK_REG_VALUE(1, src_clk_div));
+		break;
+	case SCLK_I2C2:
+		rk_clrsetreg(&cru->clksel_con[62], I2C_CLK_REG_MASK(2),
+			     I2C_CLK_REG_VALUE(2, src_clk_div));
+		break;
+	case SCLK_I2C3:
+		rk_clrsetreg(&cru->clksel_con[63], I2C_CLK_REG_MASK(3),
+			     I2C_CLK_REG_VALUE(3, src_clk_div));
+		break;
+	case SCLK_I2C5:
+		rk_clrsetreg(&cru->clksel_con[61], I2C_CLK_REG_MASK(5),
+			     I2C_CLK_REG_VALUE(5, src_clk_div));
+		break;
+	case SCLK_I2C6:
+		rk_clrsetreg(&cru->clksel_con[62], I2C_CLK_REG_MASK(6),
+			     I2C_CLK_REG_VALUE(6, src_clk_div));
+		break;
+	case SCLK_I2C7:
+		rk_clrsetreg(&cru->clksel_con[63], I2C_CLK_REG_MASK(7),
+			     I2C_CLK_REG_VALUE(7, src_clk_div));
+		break;
+	default:
+		printf("do not support this i2c bus\n");
+		return -EINVAL;
+	}
+
+	return DIV_TO_RATE(GPLL_HZ, src_clk_div);
+}
+
+static ulong rk3399_vop_set_clk(struct rk3399_cru *cru, ulong clk_id, u32 hz)
+{
+	struct pll_div vpll_config = {0};
+	int aclk_vop = 198*MHz;
+	void *aclkreg_addr, *dclkreg_addr;
+	u32 div;
+
+	switch (clk_id) {
+	case DCLK_VOP0:
+		aclkreg_addr = &cru->clksel_con[47];
+		dclkreg_addr = &cru->clksel_con[49];
+		break;
+	case DCLK_VOP1:
+		aclkreg_addr = &cru->clksel_con[48];
+		dclkreg_addr = &cru->clksel_con[50];
+		break;
+	default:
+		return -EINVAL;
+	}
+	/* vop aclk source clk: cpll */
+	div = CPLL_HZ / aclk_vop;
+	assert(div - 1 < 32);
+
+	rk_clrsetreg(aclkreg_addr,
+		     ACLK_VOP_PLL_SEL_MASK | ACLK_VOP_DIV_CON_MASK,
+		     ACLK_VOP_PLL_SEL_CPLL << ACLK_VOP_PLL_SEL_SHIFT |
+		     (div - 1) << ACLK_VOP_DIV_CON_SHIFT);
+
+	/* vop dclk source from vpll, and equals to vpll(means div == 1) */
+	if (pll_para_config(hz, &vpll_config))
+		return -1;
+
+	rkclk_set_pll(&cru->vpll_con[0], &vpll_config);
+
+	rk_clrsetreg(dclkreg_addr,
+		     DCLK_VOP_DCLK_SEL_MASK | DCLK_VOP_PLL_SEL_MASK|
+		     DCLK_VOP_DIV_CON_MASK,
+		     DCLK_VOP_DCLK_SEL_DIVOUT << DCLK_VOP_DCLK_SEL_SHIFT |
+		     DCLK_VOP_PLL_SEL_VPLL << DCLK_VOP_PLL_SEL_SHIFT |
+		     (1 - 1) << DCLK_VOP_DIV_CON_SHIFT);
+
+	return hz;
+}
+
+static ulong rk3399_mmc_get_clk(struct rk3399_cru *cru, uint clk_id)
+{
+	u32 div, con;
+
+	switch (clk_id) {
+	case SCLK_SDMMC:
+		con = readl(&cru->clksel_con[16]);
+		break;
+	case SCLK_EMMC:
+		con = readl(&cru->clksel_con[21]);
+		break;
+	default:
+		return -EINVAL;
+	}
+	div = (con & CLK_EMMC_DIV_CON_MASK) >> CLK_EMMC_DIV_CON_SHIFT;
+
+	if ((con & CLK_EMMC_PLL_MASK) >> CLK_EMMC_PLL_SHIFT
+			== CLK_EMMC_PLL_SEL_24M)
+		return DIV_TO_RATE(24*1024*1024, div);
+	else
+		return DIV_TO_RATE(GPLL_HZ, div);
+}
+
+static ulong rk3399_mmc_set_clk(struct rk3399_cru *cru,
+				ulong clk_id, ulong set_rate)
+{
+	int src_clk_div;
+	int aclk_emmc = 198*MHz;
+
+	switch (clk_id) {
+	case SCLK_SDMMC:
+		/* Select clk_sdmmc source from GPLL by default */
+		src_clk_div = GPLL_HZ / set_rate;
+
+		if (src_clk_div > 127) {
+			/* use 24MHz source for 400KHz clock */
+			src_clk_div = 24*1024*1024 / set_rate;
+			rk_clrsetreg(&cru->clksel_con[16],
+				     CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
+				     CLK_EMMC_PLL_SEL_24M << CLK_EMMC_PLL_SHIFT |
+				     (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
+		} else {
+			rk_clrsetreg(&cru->clksel_con[16],
+				     CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
+				     CLK_EMMC_PLL_SEL_GPLL << CLK_EMMC_PLL_SHIFT |
+				     (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
+		}
+		break;
+	case SCLK_EMMC:
+		/* Select aclk_emmc source from GPLL */
+		src_clk_div = GPLL_HZ / aclk_emmc;
+		assert(src_clk_div - 1 < 31);
+
+		rk_clrsetreg(&cru->clksel_con[21],
+			     ACLK_EMMC_PLL_SEL_MASK | ACLK_EMMC_DIV_CON_MASK,
+			     ACLK_EMMC_PLL_SEL_GPLL << ACLK_EMMC_PLL_SEL_SHIFT |
+			     (src_clk_div - 1) << ACLK_EMMC_DIV_CON_SHIFT);
+
+		/* Select clk_emmc source from GPLL too */
+		src_clk_div = GPLL_HZ / set_rate;
+		assert(src_clk_div - 1 < 127);
+
+		rk_clrsetreg(&cru->clksel_con[22],
+			     CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
+			     CLK_EMMC_PLL_SEL_GPLL << CLK_EMMC_PLL_SHIFT |
+			     (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return rk3399_mmc_get_clk(cru, clk_id);
+}
+
+static ulong rk3399_clk_get_rate(struct clk *clk)
+{
+	struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
+	ulong rate = 0;
+
+	switch (clk->id) {
+	case 0 ... 63:
+		return 0;
+	case SCLK_SDMMC:
+	case SCLK_EMMC:
+		rate = rk3399_mmc_get_clk(priv->cru, clk->id);
+		break;
+	case SCLK_I2C1:
+	case SCLK_I2C2:
+	case SCLK_I2C3:
+	case SCLK_I2C5:
+	case SCLK_I2C6:
+	case SCLK_I2C7:
+		rate = rk3399_i2c_get_clk(priv->cru, clk->id);
+		break;
+	case DCLK_VOP0:
+	case DCLK_VOP1:
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return rate;
+}
+
+static ulong rk3399_clk_set_rate(struct clk *clk, ulong rate)
+{
+	struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
+	ulong ret = 0;
+
+	switch (clk->id) {
+	case 0 ... 63:
+		return 0;
+	case SCLK_SDMMC:
+	case SCLK_EMMC:
+		ret = rk3399_mmc_set_clk(priv->cru, clk->id, rate);
+		break;
+	case SCLK_I2C1:
+	case SCLK_I2C2:
+	case SCLK_I2C3:
+	case SCLK_I2C5:
+	case SCLK_I2C6:
+	case SCLK_I2C7:
+		ret = rk3399_i2c_set_clk(priv->cru, clk->id, rate);
+		break;
+	case DCLK_VOP0:
+	case DCLK_VOP1:
+		rate = rk3399_vop_set_clk(priv->cru, clk->id, rate);
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return ret;
+}
+
+static struct clk_ops rk3399_clk_ops = {
+	.get_rate = rk3399_clk_get_rate,
+	.set_rate = rk3399_clk_set_rate,
+};
+
+void *rockchip_get_cru(void)
+{
+	struct udevice *dev;
+	fdt_addr_t *addr;
+	int ret;
+
+	ret = uclass_get_device_by_name(UCLASS_CLK, "clk_rk3399", &dev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	addr = dev_get_addr_ptr(dev);
+	if ((fdt_addr_t)addr == FDT_ADDR_T_NONE)
+		return ERR_PTR(-EINVAL);
+
+	return addr;
+}
+
+static int rk3399_clk_probe(struct udevice *dev)
+{
+	struct rk3399_clk_priv *priv = dev_get_priv(dev);
+
+	rkclk_init(priv->cru);
+
+	return 0;
+}
+
+static int rk3399_clk_ofdata_to_platdata(struct udevice *dev)
+{
+	struct rk3399_clk_priv *priv = dev_get_priv(dev);
+
+	priv->cru = (struct rk3399_cru *)dev_get_addr(dev);
+
+	return 0;
+}
+
+static int rk3399_clk_bind(struct udevice *dev)
+{
+	int ret;
+
+	/* The reset driver does not have a device node, so bind it here */
+	ret = device_bind_driver(gd->dm_root, "rk3399_sysreset", "reset", &dev);
+	if (ret)
+		printf("Warning: No RK3399 reset driver: ret=%d\n", ret);
+
+	return 0;
+}
+
+static const struct udevice_id rk3399_clk_ids[] = {
+	{ .compatible = "rockchip,rk3399-cru" },
+	{ }
+};
+
+U_BOOT_DRIVER(clk_rk3399) = {
+	.name		= "clk_rk3399",
+	.id		= UCLASS_CLK,
+	.of_match	= rk3399_clk_ids,
+	.priv_auto_alloc_size = sizeof(struct rk3399_clk_priv),
+	.ofdata_to_platdata = rk3399_clk_ofdata_to_platdata,
+	.ops		= &rk3399_clk_ops,
+	.bind		= rk3399_clk_bind,
+	.probe		= rk3399_clk_probe,
+};
diff --git a/drivers/clk/tegra/Kconfig b/drivers/clk/tegra/Kconfig
new file mode 100644
index 0000000..659fe02
--- /dev/null
+++ b/drivers/clk/tegra/Kconfig
@@ -0,0 +1,6 @@
+config TEGRA186_CLOCK
+	bool "Enable Tegra186 BPMP-based clock driver"
+	depends on TEGRA186_BPMP
+	help
+	  Enable support for manipulating Tegra's on-SoC clocks via IPC
+	  requests to the BPMP (Boot and Power Management Processor).
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
new file mode 100644
index 0000000..f32998c
--- /dev/null
+++ b/drivers/clk/tegra/Makefile
@@ -0,0 +1,5 @@
+# Copyright (c) 2016, NVIDIA CORPORATION.
+#
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_TEGRA186_CLOCK) += tegra186-clk.o
diff --git a/drivers/clk/tegra/tegra186-clk.c b/drivers/clk/tegra/tegra186-clk.c
new file mode 100644
index 0000000..075cb46
--- /dev/null
+++ b/drivers/clk/tegra/tegra186-clk.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <misc.h>
+#include <asm/arch-tegra/bpmp_abi.h>
+
+static ulong tegra186_clk_get_rate(struct clk *clk)
+{
+	struct mrq_clk_request req;
+	struct mrq_clk_response resp;
+	int ret;
+
+	debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
+	      clk->id);
+
+	req.cmd_and_id = (CMD_CLK_GET_RATE << 24) | clk->id;
+
+	ret = misc_call(clk->dev->parent, MRQ_CLK, &req, sizeof(req), &resp,
+			sizeof(resp));
+	if (ret < 0)
+		return ret;
+
+	return resp.clk_get_rate.rate;
+}
+
+static ulong tegra186_clk_set_rate(struct clk *clk, ulong rate)
+{
+	struct mrq_clk_request req;
+	struct mrq_clk_response resp;
+	int ret;
+
+	debug("%s(clk=%p, rate=%lu) (dev=%p, id=%lu)\n", __func__, clk, rate,
+	      clk->dev, clk->id);
+
+	req.cmd_and_id = (CMD_CLK_SET_RATE << 24) | clk->id;
+	req.clk_set_rate.rate = rate;
+
+	ret = misc_call(clk->dev->parent, MRQ_CLK, &req, sizeof(req), &resp,
+			sizeof(resp));
+	if (ret < 0)
+		return ret;
+
+	return resp.clk_set_rate.rate;
+}
+
+static int tegra186_clk_en_dis(struct clk *clk,
+			       enum mrq_reset_commands cmd)
+{
+	struct mrq_clk_request req;
+	struct mrq_clk_response resp;
+	int ret;
+
+	req.cmd_and_id = (cmd << 24) | clk->id;
+
+	ret = misc_call(clk->dev->parent, MRQ_CLK, &req, sizeof(req), &resp,
+			sizeof(resp));
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int tegra186_clk_enable(struct clk *clk)
+{
+	debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
+	      clk->id);
+
+	return tegra186_clk_en_dis(clk, CMD_CLK_ENABLE);
+}
+
+static int tegra186_clk_disable(struct clk *clk)
+{
+	debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
+	      clk->id);
+
+	return tegra186_clk_en_dis(clk, CMD_CLK_DISABLE);
+}
+
+static struct clk_ops tegra186_clk_ops = {
+	.get_rate = tegra186_clk_get_rate,
+	.set_rate = tegra186_clk_set_rate,
+	.enable = tegra186_clk_enable,
+	.disable = tegra186_clk_disable,
+};
+
+static int tegra186_clk_probe(struct udevice *dev)
+{
+	debug("%s(dev=%p)\n", __func__, dev);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(tegra186_clk) = {
+	.name		= "tegra186_clk",
+	.id		= UCLASS_CLK,
+	.probe		= tegra186_clk_probe,
+	.ops = &tegra186_clk_ops,
+};
diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c
index 2f5d4d8..a91924e 100644
--- a/drivers/clk/uniphier/clk-uniphier-core.c
+++ b/drivers/clk/uniphier/clk-uniphier-core.c
@@ -1,11 +1,11 @@
 /*
- * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #include <common.h>
-#include <mapmem.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
 #include <linux/sizes.h>
@@ -137,7 +137,7 @@
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
-	priv->base = map_sysmem(addr, SZ_4K);
+	priv->base = devm_ioremap(dev, addr, SZ_4K);
 	if (!priv->base)
 		return -ENOMEM;
 
@@ -145,12 +145,3 @@
 
 	return 0;
 }
-
-int uniphier_clk_remove(struct udevice *dev)
-{
-	struct uniphier_clk_priv *priv = dev_get_priv(dev);
-
-	unmap_sysmem(priv->base);
-
-	return 0;
-}
diff --git a/drivers/clk/uniphier/clk-uniphier-mio.c b/drivers/clk/uniphier/clk-uniphier-mio.c
index 2dd3fc0..2eea5eb 100644
--- a/drivers/clk/uniphier/clk-uniphier-mio.c
+++ b/drivers/clk/uniphier/clk-uniphier-mio.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -179,7 +180,6 @@
 	.id = UCLASS_CLK,
 	.of_match = uniphier_mio_clk_match,
 	.probe = uniphier_clk_probe,
-	.remove = uniphier_clk_remove,
 	.priv_auto_alloc_size = sizeof(struct uniphier_clk_priv),
 	.ops = &uniphier_clk_ops,
 };
diff --git a/drivers/clk/uniphier/clk-uniphier.h b/drivers/clk/uniphier/clk-uniphier.h
index 560b3f8..18aa888 100644
--- a/drivers/clk/uniphier/clk-uniphier.h
+++ b/drivers/clk/uniphier/clk-uniphier.h
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -52,6 +53,5 @@
 
 extern const struct clk_ops uniphier_clk_ops;
 int uniphier_clk_probe(struct udevice *dev);
-int uniphier_clk_remove(struct udevice *dev);
 
 #endif /* __CLK_UNIPHIER_H__ */
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index 0e56b23..a7f77b4 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -112,7 +112,7 @@
 
 	devres_release_all(dev);
 
-	if (dev->flags & DM_NAME_ALLOCED)
+	if (dev->flags & DM_FLAG_NAME_ALLOCED)
 		free((char *)dev->name);
 	free(dev);
 
diff --git a/drivers/core/device.c b/drivers/core/device.c
index eb75b17..b737f1c 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -10,6 +10,7 @@
  */
 
 #include <common.h>
+#include <asm/io.h>
 #include <fdtdec.h>
 #include <fdt_support.h>
 #include <malloc.h>
@@ -29,7 +30,7 @@
 static int device_bind_common(struct udevice *parent, const struct driver *drv,
 			      const char *name, void *platdata,
 			      ulong driver_data, int of_offset,
-			      struct udevice **devp)
+			      uint of_platdata_size, struct udevice **devp)
 {
 	struct udevice *dev;
 	struct uclass *uc;
@@ -83,12 +84,29 @@
 		}
 	}
 
-	if (!dev->platdata && drv->platdata_auto_alloc_size) {
-		dev->flags |= DM_FLAG_ALLOC_PDATA;
-		dev->platdata = calloc(1, drv->platdata_auto_alloc_size);
-		if (!dev->platdata) {
-			ret = -ENOMEM;
-			goto fail_alloc1;
+	if (drv->platdata_auto_alloc_size) {
+		bool alloc = !platdata;
+
+		if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
+			if (of_platdata_size) {
+				dev->flags |= DM_FLAG_OF_PLATDATA;
+				if (of_platdata_size <
+						drv->platdata_auto_alloc_size)
+					alloc = true;
+			}
+		}
+		if (alloc) {
+			dev->flags |= DM_FLAG_ALLOC_PDATA;
+			dev->platdata = calloc(1,
+					       drv->platdata_auto_alloc_size);
+			if (!dev->platdata) {
+				ret = -ENOMEM;
+				goto fail_alloc1;
+			}
+			if (CONFIG_IS_ENABLED(OF_PLATDATA) && platdata) {
+				memcpy(dev->platdata, platdata,
+				       of_platdata_size);
+			}
 		}
 	}
 
@@ -201,14 +219,14 @@
 				 struct udevice **devp)
 {
 	return device_bind_common(parent, drv, name, NULL, driver_data,
-				  of_offset, devp);
+				  of_offset, 0, devp);
 }
 
 int device_bind(struct udevice *parent, const struct driver *drv,
 		const char *name, void *platdata, int of_offset,
 		struct udevice **devp)
 {
-	return device_bind_common(parent, drv, name, platdata, 0, of_offset,
+	return device_bind_common(parent, drv, name, platdata, 0, of_offset, 0,
 				  devp);
 }
 
@@ -216,6 +234,7 @@
 			const struct driver_info *info, struct udevice **devp)
 {
 	struct driver *drv;
+	uint platdata_size = 0;
 
 	drv = lists_driver_lookup_name(info->name);
 	if (!drv)
@@ -223,8 +242,11 @@
 	if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC))
 		return -EPERM;
 
-	return device_bind(parent, drv, info->name, (void *)info->platdata,
-			   -1, devp);
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	platdata_size = info->platdata_size;
+#endif
+	return device_bind_common(parent, drv, info->name,
+			(void *)info->platdata, 0, -1, platdata_size, devp);
 }
 
 static void *alloc_priv(int size, uint flags)
@@ -607,7 +629,7 @@
 
 fdt_addr_t dev_get_addr_index(struct udevice *dev, int index)
 {
-#if CONFIG_IS_ENABLED(OF_CONTROL)
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
 	fdt_addr_t addr;
 
 	if (CONFIG_IS_ENABLED(OF_TRANSLATE)) {
@@ -649,7 +671,7 @@
 		addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
 							dev->parent->of_offset,
 							dev->of_offset, "reg",
-							index, NULL);
+							index, NULL, false);
 		if (CONFIG_IS_ENABLED(SIMPLE_BUS) && addr != FDT_ADDR_T_NONE) {
 			if (device_get_uclass_id(dev->parent) ==
 			    UCLASS_SIMPLE_BUS)
@@ -697,6 +719,16 @@
 	return (void *)(uintptr_t)dev_get_addr_index(dev, 0);
 }
 
+void *dev_map_physmem(struct udevice *dev, unsigned long size)
+{
+	fdt_addr_t addr = dev_get_addr(dev);
+
+	if (addr == FDT_ADDR_T_NONE)
+		return NULL;
+
+	return map_physmem(addr, size, MAP_NOCACHE);
+}
+
 bool device_has_children(struct udevice *dev)
 {
 	return !list_empty(&dev->child_head);
@@ -727,7 +759,7 @@
 
 void device_set_name_alloced(struct udevice *dev)
 {
-	dev->flags |= DM_NAME_ALLOCED;
+	dev->flags |= DM_FLAG_NAME_ALLOCED;
 }
 
 int device_set_name(struct udevice *dev, const char *name)
diff --git a/drivers/core/lists.c b/drivers/core/lists.c
index 0c27717..6a634e6 100644
--- a/drivers/core/lists.c
+++ b/drivers/core/lists.c
@@ -99,7 +99,7 @@
 	return 0;
 }
 
-#if CONFIG_IS_ENABLED(OF_CONTROL)
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
 /**
  * driver_check_compatible() - Check if a driver is compatible with this node
  *
diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index 519832f..0299ff0 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -15,6 +15,49 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static struct regmap *regmap_alloc_count(int count)
+{
+	struct regmap *map;
+
+	map = malloc(sizeof(struct regmap));
+	if (!map)
+		return NULL;
+	if (count <= 1) {
+		map->range = &map->base_range;
+	} else {
+		map->range = malloc(count * sizeof(struct regmap_range));
+		if (!map->range) {
+			free(map);
+			return NULL;
+		}
+	}
+	map->range_count = count;
+
+	return map;
+}
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+int regmap_init_mem_platdata(struct udevice *dev, u32 *reg, int count,
+			     struct regmap **mapp)
+{
+	struct regmap_range *range;
+	struct regmap *map;
+
+	map = regmap_alloc_count(count);
+	if (!map)
+		return -ENOMEM;
+
+	map->base = *reg;
+	for (range = map->range; count > 0; reg += 2, range++, count--) {
+		range->start = *reg;
+		range->size = reg[1];
+	}
+
+	*mapp = map;
+
+	return 0;
+}
+#else
 int regmap_init_mem(struct udevice *dev, struct regmap **mapp)
 {
 	const void *blob = gd->fdt_blob;
@@ -37,22 +80,11 @@
 	if (!cell || !count)
 		return -EINVAL;
 
-	map = malloc(sizeof(struct regmap));
+	map = regmap_alloc_count(count);
 	if (!map)
 		return -ENOMEM;
 
-	if (count <= 1) {
-		map->range = &map->base_range;
-	} else {
-		map->range = malloc(count * sizeof(struct regmap_range));
-		if (!map->range) {
-			free(map);
-			return -ENOMEM;
-		}
-	}
-
 	map->base = fdtdec_get_number(cell, addr_len);
-	map->range_count = count;
 
 	for (range = map->range; count > 0;
 	     count--, cell += both_len, range++) {
@@ -64,6 +96,7 @@
 
 	return 0;
 }
+#endif
 
 void *regmap_get_range(struct regmap *map, unsigned int range_num)
 {
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 95886ad..33dc9c0 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -188,7 +188,7 @@
 	return ret;
 }
 
-#if CONFIG_IS_ENABLED(OF_CONTROL)
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
 int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset,
 		     bool pre_reloc_only)
 {
@@ -218,6 +218,15 @@
 	return ret;
 }
 
+int dm_scan_fdt_dev(struct udevice *dev)
+{
+	if (dev->of_offset == -1)
+		return 0;
+
+	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset,
+				gd->flags & GD_FLG_RELOC ? false : true);
+}
+
 int dm_scan_fdt(const void *blob, bool pre_reloc_only)
 {
 	return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only);
@@ -244,7 +253,7 @@
 		return ret;
 	}
 
-	if (CONFIG_IS_ENABLED(OF_CONTROL)) {
+	if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
 		ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
 		if (ret) {
 			debug("dm_scan_fdt() failed: %d\n", ret);
diff --git a/drivers/core/simple-bus.c b/drivers/core/simple-bus.c
index 1a9c864..5c955da 100644
--- a/drivers/core/simple-bus.c
+++ b/drivers/core/simple-bus.c
@@ -6,7 +6,6 @@
 
 #include <common.h>
 #include <dm.h>
-#include <dm/root.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -41,7 +40,7 @@
 		plat->size = cell[2];
 	}
 
-	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+	return dm_scan_fdt_dev(dev);
 }
 
 UCLASS_DRIVER(simple_bus) = {
diff --git a/drivers/core/syscon-uclass.c b/drivers/core/syscon-uclass.c
index e03f46a..01bd968 100644
--- a/drivers/core/syscon-uclass.c
+++ b/drivers/core/syscon-uclass.c
@@ -29,7 +29,20 @@
 {
 	struct syscon_uc_info *priv = dev_get_uclass_priv(dev);
 
+	/*
+	 * With OF_PLATDATA we really have no way of knowing the format of
+	 * the device-specific platform data. So we assume that it starts with
+	 * a 'reg' member, and this holds a single address and size. Drivers
+	 * using OF_PLATDATA will need to ensure that this is true.
+	 */
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct syscon_base_platdata *plat = dev_get_platdata(dev);
+
+	return regmap_init_mem_platdata(dev, plat->reg, ARRAY_SIZE(plat->reg),
+					&priv->regmap);
+#else
 	return regmap_init_mem(dev, &priv->regmap);
+#endif
 }
 
 int syscon_get_by_driver_data(ulong driver_data, struct udevice **devp)
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 1141ce1..de602ae 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -311,6 +311,26 @@
 }
 #endif
 
+int uclass_get_device_by_driver(enum uclass_id id,
+				const struct driver *find_drv,
+				struct udevice **devp)
+{
+	struct udevice *dev;
+	struct uclass *uc;
+	int ret;
+
+	ret = uclass_get(id, &uc);
+	if (ret)
+		return ret;
+
+	list_for_each_entry(dev, &uc->dev_head, uclass_node) {
+		if (dev->driver == find_drv)
+			return uclass_get_device_tail(dev, 0, devp);
+	}
+
+	return -ENODEV;
+}
+
 int uclass_get_device_tail(struct udevice *dev, int ret,
 				  struct udevice **devp)
 {
diff --git a/drivers/crypto/fsl/desc.h b/drivers/crypto/fsl/desc.h
index 1ac3a09..081bce5 100644
--- a/drivers/crypto/fsl/desc.h
+++ b/drivers/crypto/fsl/desc.h
@@ -107,7 +107,7 @@
  */
 #define HDR_REVERSE		0x00000800
 
-/* Propogate DNR property to SharedDesc */
+/* Propagate DNR property to SharedDesc */
 #define HDR_PROP_DNR		0x00000800
 
 /* JobDesc/SharedDesc share property */
diff --git a/drivers/crypto/fsl/fsl_blob.c b/drivers/crypto/fsl/fsl_blob.c
index 8b25921..d24b8fc 100644
--- a/drivers/crypto/fsl/fsl_blob.c
+++ b/drivers/crypto/fsl/fsl_blob.c
@@ -18,7 +18,7 @@
 	int ret, i = 0;
 	u32 *desc;
 
-	printf("\nDecapsulating data to form blob\n");
+	printf("\nDecapsulating blob to get data\n");
 	desc = malloc(sizeof(int) * MAX_CAAM_DESCSIZE);
 	if (!desc) {
 		debug("Not enough memory for descriptor allocation\n");
@@ -27,12 +27,15 @@
 
 	inline_cnstr_jobdesc_blob_decap(desc, key_mod, src, dst, len);
 
+	debug("Descriptor dump:\n");
 	for (i = 0; i < 14; i++)
-		printf("%x\n", *(desc + i));
+		debug("Word[%d]: %08x\n", i, *(desc + i));
 	ret = run_descriptor_jr(desc);
 
 	if (ret)
 		printf("Error in Decapsulation %d\n", ret);
+	else
+		printf("Decapsulation Success\n");
 
 	free(desc);
 	return ret;
@@ -51,12 +54,16 @@
 	}
 
 	inline_cnstr_jobdesc_blob_encap(desc, key_mod, src, dst, len);
+
+	debug("Descriptor dump:\n");
 	for (i = 0; i < 14; i++)
-		printf("%x\n", *(desc + i));
+		debug("Word[%d]: %08x\n", i, *(desc + i));
 	ret = run_descriptor_jr(desc);
 
 	if (ret)
 		printf("Error in Encapsulation %d\n", ret);
+	else
+		printf("Encapsulation Success\n");
 
 	free(desc);
 	return ret;
diff --git a/drivers/crypto/fsl/fsl_rsa.c b/drivers/crypto/fsl/fsl_rsa.c
index cf1c4c1..5471504 100644
--- a/drivers/crypto/fsl/fsl_rsa.c
+++ b/drivers/crypto/fsl/fsl_rsa.c
@@ -53,6 +53,7 @@
 	.name	= "fsl_rsa_mod_exp",
 	.id	= UCLASS_MOD_EXP,
 	.ops	= &fsl_mod_exp_ops,
+	.flags  = DM_FLAG_PRE_RELOC,
 };
 
 U_BOOT_DEVICE(fsl_rsa) = {
diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c
index 510fa4e..4a8cc32 100644
--- a/drivers/crypto/fsl/jr.c
+++ b/drivers/crypto/fsl/jr.c
@@ -599,10 +599,27 @@
 	sec_out32(&sec->mcfgr, mcr);
 
 #ifdef CONFIG_FSL_CORENET
+#ifdef CONFIG_SPL_BUILD
+	/*
+	 * For SPL Build, Set the Liodns in SEC JR0 for
+	 * creating PAMU entries corresponding to these.
+	 * For normal build, these are set in set_liodns().
+	 */
+	liodn_ns = CONFIG_SPL_JR0_LIODN_NS & JRNSLIODN_MASK;
+	liodn_s = CONFIG_SPL_JR0_LIODN_S & JRSLIODN_MASK;
+
+	liodnr = sec_in32(&sec->jrliodnr[0].ls) &
+		 ~(JRNSLIODN_MASK | JRSLIODN_MASK);
+	liodnr = liodnr |
+		 (liodn_ns << JRNSLIODN_SHIFT) |
+		 (liodn_s << JRSLIODN_SHIFT);
+	sec_out32(&sec->jrliodnr[0].ls, liodnr);
+#else
 	liodnr = sec_in32(&sec->jrliodnr[0].ls);
 	liodn_ns = (liodnr & JRNSLIODN_MASK) >> JRNSLIODN_SHIFT;
 	liodn_s = (liodnr & JRSLIODN_MASK) >> JRSLIODN_SHIFT;
 #endif
+#endif
 
 	ret = jr_init(sec_idx);
 	if (ret < 0) {
diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c
index 1d5cec6..24fd366 100644
--- a/drivers/ddr/fsl/ctrl_regs.c
+++ b/drivers/ddr/fsl/ctrl_regs.c
@@ -709,7 +709,7 @@
 		| ((add_lat_mclk & 0xf) << 28)
 		| ((cpo & 0x1f) << 23)
 		| ((wr_lat & 0xf) << 19)
-		| ((wr_lat & 0x10) << 18)
+		| (((wr_lat & 0x10) >> 4) << 18)
 		| ((rd_to_pre & RD_TO_PRE_MASK) << RD_TO_PRE_SHIFT)
 		| ((wr_data_delay & WR_DATA_DELAY_MASK) << WR_DATA_DELAY_SHIFT)
 		| ((cke_pls & 0x7) << 6)
@@ -2212,7 +2212,7 @@
 		 * Write leveling start time
 		 * The value use for the DQS_ADJUST for the first sample
 		 * when write leveling is enabled. It probably needs to be
-		 * overriden per platform.
+		 * overridden per platform.
 		 */
 		wrlvl_start = 0x8;
 		/*
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
index 78724e4..926ccbd 100644
--- a/drivers/dfu/dfu_mmc.c
+++ b/drivers/dfu/dfu_mmc.c
@@ -49,7 +49,7 @@
 	}
 
 	if (dfu->data.mmc.hw_partition >= 0) {
-		part_num_bkp = mmc->block_dev.hwpart;
+		part_num_bkp = mmc_get_blk_desc(mmc)->hwpart;
 		ret = blk_select_hwpart_devnum(IF_TYPE_MMC,
 					       dfu->data.mmc.dev_num,
 					       dfu->data.mmc.hw_partition);
@@ -62,12 +62,11 @@
 	      dfu->data.mmc.dev_num, blk_start, blk_count, buf);
 	switch (op) {
 	case DFU_OP_READ:
-		n = mmc->block_dev.block_read(&mmc->block_dev, blk_start,
-					      blk_count, buf);
+		n = blk_dread(mmc_get_blk_desc(mmc), blk_start, blk_count, buf);
 		break;
 	case DFU_OP_WRITE:
-		n = mmc->block_dev.block_write(&mmc->block_dev, blk_start,
-					       blk_count, buf);
+		n = blk_dwrite(mmc_get_blk_desc(mmc), blk_start, blk_count,
+			       buf);
 		break;
 	default:
 		error("Operation not supported\n");
@@ -356,7 +355,7 @@
 
 	} else if (!strcmp(entity_type, "part")) {
 		disk_partition_t partinfo;
-		struct blk_desc *blk_dev = &mmc->block_dev;
+		struct blk_desc *blk_dev = mmc_get_blk_desc(mmc);
 		int mmcdev = second_arg;
 		int mmcpart = third_arg;
 
diff --git a/drivers/fpga/fpga.c b/drivers/fpga/fpga.c
index 7e2f3e1..e0fb1b4 100644
--- a/drivers/fpga/fpga.c
+++ b/drivers/fpga/fpga.c
@@ -31,7 +31,7 @@
 	else if (msg)
 		printf("No support for %s.\n", msg);
 	else
-		printf("No FPGA suport!\n");
+		printf("No FPGA support!\n");
 }
 
 
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 73b862d..8d9ab52 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -30,7 +30,7 @@
 
 config ATMEL_PIO4
 	bool "ATMEL PIO4 driver"
-	depends on DM
+	depends on DM_GPIO
 	default n
 	help
 	  Say yes here to support the Atmel PIO4 driver.
@@ -79,6 +79,13 @@
 	  Power and reset buttons are placed in "pm8916_key" bank and
           have gpio numbers 0 and 1 respectively.
 
+config PCF8575_GPIO
+	bool "PCF8575 I2C GPIO Expander driver"
+	depends on DM_GPIO && DM_I2C
+	help
+	 Support for PCF8575 I2C 16-bit GPIO expander. Most of these
+	 chips are from NXP and TI.
+
 config ROCKCHIP_GPIO
 	bool "Rockchip GPIO driver"
 	depends on DM_GPIO
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 792d191..8939226 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -56,4 +56,5 @@
 obj-$(CONFIG_PIC32_GPIO)	+= pic32_gpio.o
 obj-$(CONFIG_MVEBU_GPIO)	+= mvebu_gpio.o
 obj-$(CONFIG_MSM_GPIO)		+= msm_gpio.o
+obj-$(CONFIG_$(SPL_)PCF8575_GPIO)	+= pcf8575_gpio.o
 obj-$(CONFIG_PM8916_GPIO)	+= pm8916_gpio.o
diff --git a/drivers/gpio/atmel_pio4.c b/drivers/gpio/atmel_pio4.c
index d71f525..7adea88 100644
--- a/drivers/gpio/atmel_pio4.c
+++ b/drivers/gpio/atmel_pio4.c
@@ -7,45 +7,16 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
+#include <fdtdec.h>
+#include <dm/root.h>
 #include <asm/arch/hardware.h>
+#include <asm/gpio.h>
 #include <mach/gpio.h>
 #include <mach/atmel_pio4.h>
 
-#define ATMEL_PIO4_PINS_PER_BANK	32
-
-/*
- * Register Field Definitions
- */
-#define ATMEL_PIO4_CFGR_FUNC	(0x7 << 0)
-#define		ATMEL_PIO4_CFGR_FUNC_GPIO	(0x0 << 0)
-#define		ATMEL_PIO4_CFGR_FUNC_PERIPH_A	(0x1 << 0)
-#define		ATMEL_PIO4_CFGR_FUNC_PERIPH_B	(0x2 << 0)
-#define		ATMEL_PIO4_CFGR_FUNC_PERIPH_C	(0x3 << 0)
-#define		ATMEL_PIO4_CFGR_FUNC_PERIPH_D	(0x4 << 0)
-#define		ATMEL_PIO4_CFGR_FUNC_PERIPH_E	(0x5 << 0)
-#define		ATMEL_PIO4_CFGR_FUNC_PERIPH_F	(0x6 << 0)
-#define		ATMEL_PIO4_CFGR_FUNC_PERIPH_G	(0x7 << 0)
-#define ATMEL_PIO4_CFGR_DIR	(0x1 << 8)
-#define ATMEL_PIO4_CFGR_PUEN	(0x1 << 9)
-#define ATMEL_PIO4_CFGR_PDEN	(0x1 << 10)
-#define ATMEL_PIO4_CFGR_IFEN	(0x1 << 12)
-#define ATMEL_PIO4_CFGR_IFSCEN	(0x1 << 13)
-#define ATMEL_PIO4_CFGR_OPD	(0x1 << 14)
-#define ATMEL_PIO4_CFGR_SCHMITT	(0x1 << 15)
-#define ATMEL_PIO4_CFGR_DRVSTR	(0x3 << 16)
-#define		ATMEL_PIO4_CFGR_DRVSTR_LOW0	(0x0 << 16)
-#define		ATMEL_PIO4_CFGR_DRVSTR_LOW1	(0x1 << 16)
-#define		ATMEL_PIO4_CFGR_DRVSTR_MEDIUM	(0x2 << 16)
-#define		ATMEL_PIO4_CFGR_DRVSTR_HIGH	(0x3 << 16)
-#define ATMEL_PIO4_CFGR_EVTSEL	(0x7 << 24)
-#define		ATMEL_PIO4_CFGR_EVTSEL_FALLING	(0x0 << 24)
-#define		ATMEL_PIO4_CFGR_EVTSEL_RISING	(0x1 << 24)
-#define		ATMEL_PIO4_CFGR_EVTSEL_BOTH	(0x2 << 24)
-#define		ATMEL_PIO4_CFGR_EVTSEL_LOW	(0x3 << 24)
-#define		ATMEL_PIO4_CFGR_EVTSEL_HIGH	(0x4 << 24)
-#define ATMEL_PIO4_CFGR_PCFS	(0x1 << 29)
-#define ATMEL_PIO4_CFGR_ICFS	(0x1 << 30)
+DECLARE_GLOBAL_DATA_PTR;
 
 static struct atmel_pio4_port *atmel_pio4_port_base(u32 port)
 {
@@ -79,7 +50,7 @@
 	struct atmel_pio4_port *port_base;
 	u32 reg, mask;
 
-	if (pin >= ATMEL_PIO4_PINS_PER_BANK)
+	if (pin >= ATMEL_PIO_NPINS_PER_BANK)
 		return -ENODEV;
 
 	port_base = atmel_pio4_port_base(port);
@@ -88,7 +59,7 @@
 
 	mask = 1 << pin;
 	reg = func;
-	reg |= use_pullup ? ATMEL_PIO4_CFGR_PUEN : 0;
+	reg |= use_pullup ? ATMEL_PIO_PUEN_MASK : 0;
 
 	writel(mask, &port_base->mskr);
 	writel(reg, &port_base->cfgr);
@@ -99,56 +70,56 @@
 int atmel_pio4_set_gpio(u32 port, u32 pin, u32 use_pullup)
 {
 	return atmel_pio4_config_io_func(port, pin,
-					 ATMEL_PIO4_CFGR_FUNC_GPIO,
+					 ATMEL_PIO_CFGR_FUNC_GPIO,
 					 use_pullup);
 }
 
 int atmel_pio4_set_a_periph(u32 port, u32 pin, u32 use_pullup)
 {
 	return atmel_pio4_config_io_func(port, pin,
-					 ATMEL_PIO4_CFGR_FUNC_PERIPH_A,
+					 ATMEL_PIO_CFGR_FUNC_PERIPH_A,
 					 use_pullup);
 }
 
 int atmel_pio4_set_b_periph(u32 port, u32 pin, u32 use_pullup)
 {
 	return atmel_pio4_config_io_func(port, pin,
-					 ATMEL_PIO4_CFGR_FUNC_PERIPH_B,
+					 ATMEL_PIO_CFGR_FUNC_PERIPH_B,
 					 use_pullup);
 }
 
 int atmel_pio4_set_c_periph(u32 port, u32 pin, u32 use_pullup)
 {
 	return atmel_pio4_config_io_func(port, pin,
-					 ATMEL_PIO4_CFGR_FUNC_PERIPH_C,
+					 ATMEL_PIO_CFGR_FUNC_PERIPH_C,
 					 use_pullup);
 }
 
 int atmel_pio4_set_d_periph(u32 port, u32 pin, u32 use_pullup)
 {
 	return atmel_pio4_config_io_func(port, pin,
-					 ATMEL_PIO4_CFGR_FUNC_PERIPH_D,
+					 ATMEL_PIO_CFGR_FUNC_PERIPH_D,
 					 use_pullup);
 }
 
 int atmel_pio4_set_e_periph(u32 port, u32 pin, u32 use_pullup)
 {
 	return atmel_pio4_config_io_func(port, pin,
-					 ATMEL_PIO4_CFGR_FUNC_PERIPH_E,
+					 ATMEL_PIO_CFGR_FUNC_PERIPH_E,
 					 use_pullup);
 }
 
 int atmel_pio4_set_f_periph(u32 port, u32 pin, u32 use_pullup)
 {
 	return atmel_pio4_config_io_func(port, pin,
-					 ATMEL_PIO4_CFGR_FUNC_PERIPH_F,
+					 ATMEL_PIO_CFGR_FUNC_PERIPH_F,
 					 use_pullup);
 }
 
 int atmel_pio4_set_g_periph(u32 port, u32 pin, u32 use_pullup)
 {
 	return atmel_pio4_config_io_func(port, pin,
-					 ATMEL_PIO4_CFGR_FUNC_PERIPH_G,
+					 ATMEL_PIO_CFGR_FUNC_PERIPH_G,
 					 use_pullup);
 }
 
@@ -157,7 +128,7 @@
 	struct atmel_pio4_port *port_base;
 	u32 reg, mask;
 
-	if (pin >= ATMEL_PIO4_PINS_PER_BANK)
+	if (pin >= ATMEL_PIO_NPINS_PER_BANK)
 		return -ENODEV;
 
 	port_base = atmel_pio4_port_base(port);
@@ -165,7 +136,7 @@
 		return -ENODEV;
 
 	mask = 0x01 << pin;
-	reg = ATMEL_PIO4_CFGR_FUNC_GPIO | ATMEL_PIO4_CFGR_DIR;
+	reg = ATMEL_PIO_CFGR_FUNC_GPIO | ATMEL_PIO_DIR_MASK;
 
 	writel(mask, &port_base->mskr);
 	writel(reg, &port_base->cfgr);
@@ -183,7 +154,7 @@
 	struct atmel_pio4_port *port_base;
 	u32 reg, mask;
 
-	if (pin >= ATMEL_PIO4_PINS_PER_BANK)
+	if (pin >= ATMEL_PIO_NPINS_PER_BANK)
 		return -ENODEV;
 
 	port_base = atmel_pio4_port_base(port);
@@ -191,7 +162,7 @@
 		return -ENODEV;
 
 	mask = 0x01 << pin;
-	reg = ATMEL_PIO4_CFGR_FUNC_GPIO;
+	reg = ATMEL_PIO_CFGR_FUNC_GPIO;
 
 	writel(mask, &port_base->mskr);
 	writel(reg, &port_base->cfgr);
@@ -200,15 +171,37 @@
 }
 
 #ifdef CONFIG_DM_GPIO
+
+struct atmel_pioctrl_data {
+	u32 nbanks;
+};
+
+struct atmel_pio4_platdata {
+	struct atmel_pio4_port *reg_base;
+};
+
+static struct atmel_pio4_port *atmel_pio4_bank_base(struct udevice *dev,
+						    u32 bank)
+{
+	struct atmel_pio4_platdata *plat = dev_get_platdata(dev);
+	struct atmel_pio4_port *port_base =
+			(struct atmel_pio4_port *)((u32)plat->reg_base +
+			ATMEL_PIO_BANK_OFFSET * bank);
+
+	return port_base;
+}
+
 static int atmel_pio4_direction_input(struct udevice *dev, unsigned offset)
 {
-	struct at91_port_platdata *plat = dev_get_platdata(dev);
-	struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr;
-	u32 mask = 0x01 << offset;
-	u32 reg = ATMEL_PIO4_CFGR_FUNC_GPIO;
+	u32 bank = ATMEL_PIO_BANK(offset);
+	u32 line = ATMEL_PIO_LINE(offset);
+	struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
+	u32 mask = BIT(line);
 
 	writel(mask, &port_base->mskr);
-	writel(reg, &port_base->cfgr);
+
+	clrbits_le32(&port_base->cfgr,
+		     ATMEL_PIO_CFGR_FUNC_MASK | ATMEL_PIO_DIR_MASK);
 
 	return 0;
 }
@@ -216,13 +209,15 @@
 static int atmel_pio4_direction_output(struct udevice *dev,
 				       unsigned offset, int value)
 {
-	struct at91_port_platdata *plat = dev_get_platdata(dev);
-	struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr;
-	u32 mask = 0x01 << offset;
-	u32 reg = ATMEL_PIO4_CFGR_FUNC_GPIO | ATMEL_PIO4_CFGR_DIR;
+	u32 bank = ATMEL_PIO_BANK(offset);
+	u32 line = ATMEL_PIO_LINE(offset);
+	struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
+	u32 mask = BIT(line);
 
 	writel(mask, &port_base->mskr);
-	writel(reg, &port_base->cfgr);
+
+	clrsetbits_le32(&port_base->cfgr,
+			ATMEL_PIO_CFGR_FUNC_MASK, ATMEL_PIO_DIR_MASK);
 
 	if (value)
 		writel(mask, &port_base->sodr);
@@ -234,9 +229,10 @@
 
 static int atmel_pio4_get_value(struct udevice *dev, unsigned offset)
 {
-	struct at91_port_platdata *plat = dev_get_platdata(dev);
-	struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr;
-	u32 mask = 0x01 << offset;
+	u32 bank = ATMEL_PIO_BANK(offset);
+	u32 line = ATMEL_PIO_LINE(offset);
+	struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
+	u32 mask = BIT(line);
 
 	return (readl(&port_base->pdsr) & mask) ? 1 : 0;
 }
@@ -244,9 +240,10 @@
 static int atmel_pio4_set_value(struct udevice *dev,
 				unsigned offset, int value)
 {
-	struct at91_port_platdata *plat = dev_get_platdata(dev);
-	struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr;
-	u32 mask = 0x01 << offset;
+	u32 bank = ATMEL_PIO_BANK(offset);
+	u32 line = ATMEL_PIO_LINE(offset);
+	struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
+	u32 mask = BIT(line);
 
 	if (value)
 		writel(mask, &port_base->sodr);
@@ -258,14 +255,15 @@
 
 static int atmel_pio4_get_function(struct udevice *dev, unsigned offset)
 {
-	struct at91_port_platdata *plat = dev_get_platdata(dev);
-	struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr;
-	u32 mask = 0x01 << offset;
+	u32 bank = ATMEL_PIO_BANK(offset);
+	u32 line = ATMEL_PIO_LINE(offset);
+	struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
+	u32 mask = BIT(line);
 
 	writel(mask, &port_base->mskr);
 
 	return (readl(&port_base->cfgr) &
-		ATMEL_PIO4_CFGR_DIR) ? GPIOF_OUTPUT : GPIOF_INPUT;
+		ATMEL_PIO_DIR_MASK) ? GPIOF_OUTPUT : GPIOF_INPUT;
 }
 
 static const struct dm_gpio_ops atmel_pio4_ops = {
@@ -276,21 +274,82 @@
 	.get_function		= atmel_pio4_get_function,
 };
 
+static int atmel_pio4_bind(struct udevice *dev)
+{
+	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}
+
 static int atmel_pio4_probe(struct udevice *dev)
 {
-	struct at91_port_platdata *plat = dev_get_platdata(dev);
+	struct atmel_pio4_platdata *plat = dev_get_platdata(dev);
 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct atmel_pioctrl_data *pioctrl_data;
+	struct udevice *dev_clk;
+	struct clk clk;
+	fdt_addr_t addr_base;
+	u32 nbanks;
+	int periph;
+	int ret;
+
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret)
+		return ret;
+
+	periph = fdtdec_get_uint(gd->fdt_blob, clk.dev->of_offset, "reg", -1);
+	if (periph < 0)
+		return -EINVAL;
+
+	dev_clk = dev_get_parent(clk.dev);
+	ret = clk_request(dev_clk, &clk);
+	if (ret)
+		return ret;
 
-	uc_priv->bank_name = plat->bank_name;
-	uc_priv->gpio_count = ATMEL_PIO4_PINS_PER_BANK;
+	clk.id = periph;
+	ret = clk_enable(&clk);
+	if (ret)
+		return ret;
+
+	clk_free(&clk);
+
+	addr_base = dev_get_addr(dev);
+	if (addr_base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	plat->reg_base = (struct atmel_pio4_port *)addr_base;
+
+	pioctrl_data = (struct atmel_pioctrl_data *)dev_get_driver_data(dev);
+	nbanks = pioctrl_data->nbanks;
+
+	uc_priv->bank_name = fdt_get_name(gd->fdt_blob, dev->of_offset, NULL);
+	uc_priv->gpio_count = nbanks * ATMEL_PIO_NPINS_PER_BANK;
 
 	return 0;
 }
 
+/*
+ * The number of banks can be different from a SoC to another one.
+ * We can have up to 16 banks.
+ */
+static const struct atmel_pioctrl_data atmel_sama5d2_pioctrl_data = {
+	.nbanks	= 4,
+};
+
+static const struct udevice_id atmel_pio4_ids[] = {
+	{
+		.compatible = "atmel,sama5d2-gpio",
+		.data = (ulong)&atmel_sama5d2_pioctrl_data,
+	},
+	{}
+};
+
 U_BOOT_DRIVER(gpio_atmel_pio4) = {
 	.name	= "gpio_atmel_pio4",
 	.id	= UCLASS_GPIO,
 	.ops	= &atmel_pio4_ops,
 	.probe	= atmel_pio4_probe,
+	.bind	= atmel_pio4_bind,
+	.of_match = atmel_pio4_ids,
+	.platdata_auto_alloc_size = sizeof(struct atmel_pio4_platdata),
 };
+
 #endif
diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c
index bde51ea..afb27a3 100644
--- a/drivers/gpio/gpio-uniphier.c
+++ b/drivers/gpio/gpio-uniphier.c
@@ -1,12 +1,12 @@
 /*
- * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #include <common.h>
 #include <dm/device.h>
-#include <mapmem.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
 #include <linux/sizes.h>
@@ -99,7 +99,7 @@
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
-	priv->base = map_sysmem(addr, SZ_8);
+	priv->base = devm_ioremap(dev, addr, SZ_8);
 	if (!priv->base)
 		return -ENOMEM;
 
@@ -119,15 +119,6 @@
 	return 0;
 }
 
-static int uniphier_gpio_remove(struct udevice *dev)
-{
-	struct uniphier_gpio_priv *priv = dev_get_priv(dev);
-
-	unmap_sysmem(priv->base);
-
-	return 0;
-}
-
 /* .data = the number of GPIO banks */
 static const struct udevice_id uniphier_gpio_match[] = {
 	{ .compatible = "socionext,uniphier-gpio" },
@@ -139,7 +130,6 @@
 	.id	= UCLASS_GPIO,
 	.of_match = uniphier_gpio_match,
 	.probe	= uniphier_gpio_probe,
-	.remove	= uniphier_gpio_remove,
 	.priv_auto_alloc_size = sizeof(struct uniphier_gpio_priv),
 	.ops	= &uniphier_gpio_ops,
 };
diff --git a/drivers/gpio/mpc85xx_gpio.c b/drivers/gpio/mpc85xx_gpio.c
index 04773e2..168c696 100644
--- a/drivers/gpio/mpc85xx_gpio.c
+++ b/drivers/gpio/mpc85xx_gpio.c
@@ -163,23 +163,41 @@
 	return dir ? GPIOF_OUTPUT : GPIOF_INPUT;
 }
 
+#if CONFIG_IS_ENABLED(OF_CONTROL)
 static int mpc85xx_gpio_ofdata_to_platdata(struct udevice *dev) {
-	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+	struct mpc85xx_gpio_plat *plat = dev_get_platdata(dev);
 	fdt_addr_t addr;
 	fdt_size_t size;
 
 	addr = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, dev->of_offset,
-						  "reg", 0, &size);
+						  "reg", 0, &size, false);
 
-	data->addr = addr;
-	data->base = map_sysmem(CONFIG_SYS_IMMR + addr, size);
+	plat->addr = addr;
+	plat->size = size;
+	plat->ngpios = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+						  "ngpios", 32);
 
-	if (!data->base)
+	return 0;
+}
+#endif
+
+static int mpc85xx_gpio_platdata_to_priv(struct udevice *dev)
+{
+	struct mpc85xx_gpio_data *priv = dev_get_priv(dev);
+	struct mpc85xx_gpio_plat *plat = dev_get_platdata(dev);
+	unsigned long size = plat->size;
+
+	if (size == 0)
+		size = 0x100;
+
+	priv->addr = plat->addr;
+	priv->base = map_sysmem(CONFIG_SYS_IMMR + plat->addr, size);
+
+	if (!priv->base)
 		return -ENOMEM;
 
-	data->gpio_count = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
-					  "ngpios", 32);
-	data->dat_shadow = 0;
+	priv->gpio_count = plat->ngpios;
+	priv->dat_shadow = 0;
 
 	return 0;
 }
@@ -190,6 +208,8 @@
 	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
 	char name[32], *str;
 
+	mpc85xx_gpio_platdata_to_priv(dev);
+
 	snprintf(name, sizeof(name), "MPC@%lx_", data->addr);
 	str = strdup(name);
 
@@ -221,8 +241,11 @@
 	.name	= "gpio_mpc85xx",
 	.id	= UCLASS_GPIO,
 	.ops	= &gpio_mpc85xx_ops,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
 	.ofdata_to_platdata = mpc85xx_gpio_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct mpc85xx_gpio_plat),
 	.of_match = mpc85xx_gpio_ids,
+#endif
 	.probe	= mpc85xx_gpio_probe,
 	.priv_auto_alloc_size = sizeof(struct mpc85xx_gpio_data),
 };
diff --git a/drivers/gpio/pcf8575_gpio.c b/drivers/gpio/pcf8575_gpio.c
new file mode 100644
index 0000000..2bda0ff
--- /dev/null
+++ b/drivers/gpio/pcf8575_gpio.c
@@ -0,0 +1,180 @@
+/*
+ * PCF8575 I2C GPIO EXPANDER DRIVER
+ *
+ * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Vignesh R <vigneshr@ti.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ *
+ *
+ * Driver for TI PCF-8575 16-bit I2C gpio expander. Based on
+ * gpio-pcf857x Linux Kernel(v4.7) driver.
+ *
+ * Copyright (C) 2007 David Brownell
+ *
+ */
+
+/*
+ * NOTE: The driver and devicetree bindings are borrowed from Linux
+ * Kernel, but driver does not support all PCF857x devices. It currently
+ * supports PCF8575 16-bit expander by TI and NXP.
+ *
+ * TODO(vigneshr@ti.com):
+ * Support 8 bit PCF857x compatible expanders.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+#include <asm-generic/gpio.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct pcf8575_chip {
+	int gpio_count;		/* No. GPIOs supported by the chip */
+
+	/* NOTE:  these chips have strange "quasi-bidirectional" I/O pins.
+	 * We can't actually know whether a pin is configured (a) as output
+	 * and driving the signal low, or (b) as input and reporting a low
+	 * value ... without knowing the last value written since the chip
+	 * came out of reset (if any).  We can't read the latched output.
+	 * In short, the only reliable solution for setting up pin direction
+	 * is to do it explicitly.
+	 *
+	 * Using "out" avoids that trouble.  When left initialized to zero,
+	 * our software copy of the "latch" then matches the chip's all-ones
+	 * reset state.  Otherwise it flags pins to be driven low.
+	 */
+	unsigned int out;	/* software latch */
+	const char *bank_name;	/* Name of the expander bank */
+};
+
+/* Read/Write to 16-bit I/O expander */
+
+static int pcf8575_i2c_write_le16(struct udevice *dev, unsigned int word)
+{
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
+	u8 buf[2] = { word & 0xff, word >> 8, };
+	int ret;
+
+	ret = dm_i2c_write(dev, 0, buf, 2);
+	if (ret)
+		printf("%s i2c write failed to addr %x\n", __func__,
+		       chip->chip_addr);
+
+	return ret;
+}
+
+static int pcf8575_i2c_read_le16(struct udevice *dev)
+{
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
+	u8 buf[2];
+	int ret;
+
+	ret = dm_i2c_read(dev, 0, buf, 2);
+	if (ret) {
+		printf("%s i2c read failed from addr %x\n", __func__,
+		       chip->chip_addr);
+		return ret;
+	}
+
+	return (buf[1] << 8) | buf[0];
+}
+
+static int pcf8575_direction_input(struct udevice *dev, unsigned offset)
+{
+	struct pcf8575_chip *plat = dev_get_platdata(dev);
+	int status;
+
+	plat->out |= BIT(offset);
+	status = pcf8575_i2c_write_le16(dev, plat->out);
+
+	return status;
+}
+
+static int pcf8575_direction_output(struct udevice *dev,
+				    unsigned int offset, int value)
+{
+	struct pcf8575_chip *plat = dev_get_platdata(dev);
+	int ret;
+
+	if (value)
+		plat->out |= BIT(offset);
+	else
+		plat->out &= ~BIT(offset);
+
+	ret = pcf8575_i2c_write_le16(dev, plat->out);
+
+	return ret;
+}
+
+static int pcf8575_get_value(struct udevice *dev, unsigned int offset)
+{
+	int             value;
+
+	value = pcf8575_i2c_read_le16(dev);
+
+	return (value < 0) ? value : ((value & BIT(offset)) >> offset);
+}
+
+static int pcf8575_set_value(struct udevice *dev, unsigned int offset,
+			     int value)
+{
+	return pcf8575_direction_output(dev, offset, value);
+}
+
+static int pcf8575_ofdata_platdata(struct udevice *dev)
+{
+	struct pcf8575_chip *plat = dev_get_platdata(dev);
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	int n_latch;
+
+	uc_priv->gpio_count = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+					     "gpio-count", 16);
+	uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev->of_offset,
+					 "gpio-bank-name", NULL);
+	if (!uc_priv->bank_name)
+		uc_priv->bank_name = fdt_get_name(gd->fdt_blob,
+						  dev->of_offset, NULL);
+
+	n_latch = fdtdec_get_uint(gd->fdt_blob, dev->of_offset,
+				  "lines-initial-states", 0);
+	plat->out = ~n_latch;
+
+	return 0;
+}
+
+static int pcf8575_gpio_probe(struct udevice  *dev)
+{
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	debug("%s GPIO controller with %d gpios probed\n",
+	      uc_priv->bank_name, uc_priv->gpio_count);
+
+	return 0;
+}
+
+static const struct dm_gpio_ops pcf8575_gpio_ops = {
+	.direction_input	= pcf8575_direction_input,
+	.direction_output	= pcf8575_direction_output,
+	.get_value		= pcf8575_get_value,
+	.set_value		= pcf8575_set_value,
+};
+
+static const struct udevice_id pcf8575_gpio_ids[] = {
+	{ .compatible = "nxp,pcf8575" },
+	{ .compatible = "ti,pcf8575" },
+	{ }
+};
+
+U_BOOT_DRIVER(gpio_pcf8575) = {
+	.name	= "gpio_pcf8575",
+	.id	= UCLASS_GPIO,
+	.ops	= &pcf8575_gpio_ops,
+	.of_match = pcf8575_gpio_ids,
+	.ofdata_to_platdata = pcf8575_ofdata_platdata,
+	.probe	= pcf8575_gpio_probe,
+	.platdata_auto_alloc_size = sizeof(struct pcf8575_chip),
+};
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index 94abbeb..e8accaa 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -19,6 +19,7 @@
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <dm/device-internal.h>
+#include <dt-bindings/gpio/gpio.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -215,12 +216,27 @@
 		return GPIOF_FUNC;
 }
 
+static int sunxi_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
+			    struct fdtdec_phandle_args *args)
+{
+	int ret;
+
+	ret = device_get_child(dev, args->args[0], &desc->dev);
+	if (ret)
+		return ret;
+	desc->offset = args->args[1];
+	desc->flags = args->args[2] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
+
+	return 0;
+}
+
 static const struct dm_gpio_ops gpio_sunxi_ops = {
 	.direction_input	= sunxi_gpio_direction_input,
 	.direction_output	= sunxi_gpio_direction_output,
 	.get_value		= sunxi_gpio_get_value,
 	.set_value		= sunxi_gpio_set_value,
 	.get_function		= sunxi_gpio_get_function,
+	.xlate			= sunxi_gpio_xlate,
 };
 
 /**
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 6e22bba..1537b67 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -58,6 +58,16 @@
 	  bindings are supported.
 	  Binding info: doc/device-tree-bindings/i2c/i2c-gpio.txt
 
+config SYS_I2C_AT91
+	bool "Atmel I2C driver"
+	depends on DM_I2C && ARCH_AT91
+	help
+	  Add support for the Atmel I2C driver. A serious problem is that there
+	  is no documented way to issue repeated START conditions for more than
+	  two messages, as needed to support combined I2C messages. Use the
+	  i2c-gpio driver unless your system can cope with this limitation.
+	  Binding info: doc/device-tree-bindings/i2c/i2c-at91.txt
+
 config SYS_I2C_FSL
        bool "Freescale I2C bus driver"
        depends on DM_I2C
@@ -154,6 +164,23 @@
 	  Support for UniPhier FIFO-builtin I2C controller driver.
 	  This I2C controller is used on PH1-Pro4 or newer UniPhier SoCs.
 
+config SYS_I2C_MVTWSI
+	bool "Marvell I2C driver"
+	depends on DM_I2C
+	help
+	  Support for Marvell I2C controllers as used on the orion5x and
+	  kirkwood SoC families.
+
+config TEGRA186_BPMP_I2C
+	bool "Enable Tegra186 BPMP-based I2C driver"
+	depends on TEGRA186_BPMP
+	help
+	  Support for Tegra I2C controllers managed by the BPMP (Boot and
+	  Power Management Processor). On Tegra186, some I2C controllers are
+	  directly controlled by the main CPU, whereas others are controlled
+	  by the BPMP, and can only be accessed by the main CPU via IPC
+	  requests to the BPMP. This driver covers the latter case.
+
 source "drivers/i2c/muxes/Kconfig"
 
 endmenu
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 167424d..2987081 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -16,6 +16,7 @@
 obj-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
 obj-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
 obj-$(CONFIG_SYS_I2C) += i2c_core.o
+obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
 obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
 obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
@@ -41,5 +42,6 @@
 obj-$(CONFIG_SYS_I2C_UNIPHIER) += i2c-uniphier.o
 obj-$(CONFIG_SYS_I2C_UNIPHIER_F) += i2c-uniphier-f.o
 obj-$(CONFIG_SYS_I2C_ZYNQ) += zynq_i2c.o
+obj-$(CONFIG_TEGRA186_BPMP_I2C) += tegra186_bpmp_i2c.o
 
 obj-$(CONFIG_I2C_MUX) += muxes/
diff --git a/drivers/i2c/at91_i2c.c b/drivers/i2c/at91_i2c.c
new file mode 100644
index 0000000..8e9c3ad
--- /dev/null
+++ b/drivers/i2c/at91_i2c.c
@@ -0,0 +1,338 @@
+/*
+ * Atmel I2C driver.
+ *
+ * (C) Copyright 2016 Songjun Wu <songjun.wu@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/io.h>
+#include <common.h>
+#include <clk_client.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <linux/bitops.h>
+#include <mach/clk.h>
+
+#include "at91_i2c.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define I2C_TIMEOUT_MS	100
+
+static int at91_wait_for_xfer(struct at91_i2c_bus *bus, u32 status)
+{
+	struct at91_i2c_regs *reg = bus->regs;
+	ulong start_time = get_timer(0);
+	u32 sr;
+
+	bus->status = 0;
+
+	do {
+		sr = readl(&reg->sr);
+		bus->status |= sr;
+
+		if (sr & TWI_SR_NACK)
+			return -EREMOTEIO;
+		else if (sr & status)
+			return 0;
+	} while (get_timer(start_time) < I2C_TIMEOUT_MS);
+
+	return -ETIMEDOUT;
+}
+
+static int at91_i2c_xfer_msg(struct at91_i2c_bus *bus, struct i2c_msg *msg)
+{
+	struct at91_i2c_regs *reg = bus->regs;
+	bool is_read = msg->flags & I2C_M_RD;
+	u32 i;
+	int ret = 0;
+
+	readl(&reg->sr);
+	if (is_read) {
+		writel(TWI_CR_START, &reg->cr);
+
+		for (i = 0; !ret && i < (msg->len - 1); i++) {
+			ret = at91_wait_for_xfer(bus, TWI_SR_RXRDY);
+			msg->buf[i] = readl(&reg->rhr);
+		}
+
+		if (ret)
+			goto error;
+
+		writel(TWI_CR_STOP, &reg->cr);
+
+		ret = at91_wait_for_xfer(bus, TWI_SR_RXRDY);
+		if (ret)
+			goto error;
+
+		msg->buf[i] = readl(&reg->rhr);
+
+	} else {
+		writel(msg->buf[0], &reg->thr);
+		for (i = 1; !ret && (i < msg->len); i++) {
+			writel(msg->buf[i], &reg->thr);
+			ret = at91_wait_for_xfer(bus, TWI_SR_TXRDY);
+		}
+
+		if (ret)
+			goto error;
+
+		writel(TWI_CR_STOP, &reg->cr);
+	}
+
+	if (!ret)
+		ret = at91_wait_for_xfer(bus, TWI_SR_TXCOMP);
+
+	if (ret)
+		goto error;
+
+	if (bus->status & (TWI_SR_OVRE | TWI_SR_UNRE | TWI_SR_LOCK)) {
+		ret = -EIO;
+		goto error;
+	}
+
+	return 0;
+
+error:
+	if (bus->status & TWI_SR_LOCK)
+		writel(TWI_CR_LOCKCLR, &reg->cr);
+
+	return ret;
+}
+
+static int at91_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
+{
+	struct at91_i2c_bus *bus = dev_get_priv(dev);
+	struct at91_i2c_regs *reg = bus->regs;
+	struct i2c_msg *m_start = msg;
+	bool is_read;
+	u32 int_addr_flag = 0;
+	int ret = 0;
+
+	if (nmsgs == 2) {
+		int internal_address = 0;
+		int i;
+
+		/* 1st msg is put into the internal address, start with 2nd */
+		m_start = &msg[1];
+
+		/* the max length of internal address is 3 bytes */
+		if (msg->len > 3)
+			return -EFAULT;
+
+		for (i = 0; i < msg->len; ++i) {
+			const unsigned addr = msg->buf[msg->len - 1 - i];
+
+			internal_address |= addr << (8 * i);
+			int_addr_flag += TWI_MMR_IADRSZ_1;
+		}
+
+		writel(internal_address, &reg->iadr);
+	}
+
+	is_read = m_start->flags & I2C_M_RD;
+
+	writel((m_start->addr << 16) | int_addr_flag |
+	       (is_read ? TWI_MMR_MREAD : 0), &reg->mmr);
+
+	ret = at91_i2c_xfer_msg(bus, m_start);
+
+	return ret;
+}
+
+/*
+ * Calculate symmetric clock as stated in datasheet:
+ * twi_clk = F_MAIN / (2 * (cdiv * (1 << ckdiv) + offset))
+ */
+static void at91_calc_i2c_clock(struct udevice *dev, int i2c_clk)
+{
+	struct at91_i2c_bus *bus = dev_get_priv(dev);
+	const struct at91_i2c_pdata *pdata = bus->pdata;
+	int offset = pdata->clk_offset;
+	int max_ckdiv = pdata->clk_max_div;
+	int ckdiv, cdiv, div;
+	unsigned long src_rate;
+
+	src_rate = bus->bus_clk_rate;
+
+	div = max(0, (int)DIV_ROUND_UP(src_rate, 2 * i2c_clk) - offset);
+	ckdiv = fls(div >> 8);
+	cdiv = div >> ckdiv;
+
+	if (ckdiv > max_ckdiv) {
+		ckdiv = max_ckdiv;
+		cdiv = 255;
+	}
+
+	bus->speed = DIV_ROUND_UP(src_rate,
+				  (cdiv * (1 << ckdiv) + offset) * 2);
+
+	bus->cwgr_val = (ckdiv << 16) | (cdiv << 8) | cdiv;
+}
+
+static int at91_i2c_enable_clk(struct udevice *dev)
+{
+	struct at91_i2c_bus *bus = dev_get_priv(dev);
+	struct udevice *dev_clk;
+	struct clk clk;
+	ulong clk_rate;
+	int periph;
+	int ret;
+
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret)
+		return -EINVAL;
+
+	periph = fdtdec_get_uint(gd->fdt_blob, clk.dev->of_offset, "reg", -1);
+	if (periph < 0)
+		return -EINVAL;
+
+	dev_clk = dev_get_parent(clk.dev);
+	ret = clk_request(dev_clk, &clk);
+	if (ret)
+		return ret;
+
+	clk.id = periph;
+	ret = clk_enable(&clk);
+	if (ret)
+		return ret;
+
+	ret = clk_get_by_index(dev_clk, 0, &clk);
+	if (ret)
+		return ret;
+
+	clk_rate = clk_get_rate(&clk);
+	if (!clk_rate)
+		return -ENODEV;
+
+	bus->bus_clk_rate = clk_rate;
+
+	clk_free(&clk);
+
+	return 0;
+}
+
+static int at91_i2c_probe(struct udevice *dev, uint chip, uint chip_flags)
+{
+	struct at91_i2c_bus *bus = dev_get_priv(dev);
+	struct at91_i2c_regs *reg = bus->regs;
+	int ret;
+
+	ret = at91_i2c_enable_clk(dev);
+	if (ret)
+		return ret;
+
+	writel(TWI_CR_SWRST, &reg->cr);
+
+	at91_calc_i2c_clock(dev, bus->clock_frequency);
+
+	writel(bus->cwgr_val, &reg->cwgr);
+	writel(TWI_CR_MSEN, &reg->cr);
+	writel(TWI_CR_SVDIS, &reg->cr);
+
+	return 0;
+}
+
+static int at91_i2c_set_bus_speed(struct udevice *dev, unsigned int speed)
+{
+	struct at91_i2c_bus *bus = dev_get_priv(dev);
+
+	at91_calc_i2c_clock(dev, speed);
+
+	writel(bus->cwgr_val, &bus->regs->cwgr);
+
+	return 0;
+}
+
+int at91_i2c_get_bus_speed(struct udevice *dev)
+{
+	struct at91_i2c_bus *bus = dev_get_priv(dev);
+
+	return bus->speed;
+}
+
+static int at91_i2c_ofdata_to_platdata(struct udevice *dev)
+{
+	const void *blob = gd->fdt_blob;
+	struct at91_i2c_bus *bus = dev_get_priv(dev);
+	int node = dev->of_offset;
+
+	bus->regs = (struct at91_i2c_regs *)dev_get_addr(dev);
+	bus->pdata = (struct at91_i2c_pdata *)dev_get_driver_data(dev);
+	bus->clock_frequency = fdtdec_get_int(blob, node,
+					      "clock-frequency", 100000);
+
+	return 0;
+}
+
+static const struct dm_i2c_ops at91_i2c_ops = {
+	.xfer		= at91_i2c_xfer,
+	.probe_chip	= at91_i2c_probe,
+	.set_bus_speed	= at91_i2c_set_bus_speed,
+	.get_bus_speed	= at91_i2c_get_bus_speed,
+};
+
+static const struct at91_i2c_pdata at91rm9200_config = {
+	.clk_max_div = 5,
+	.clk_offset = 3,
+};
+
+static const struct at91_i2c_pdata at91sam9261_config = {
+	.clk_max_div = 5,
+	.clk_offset = 4,
+};
+
+static const struct at91_i2c_pdata at91sam9260_config = {
+	.clk_max_div = 7,
+	.clk_offset = 4,
+};
+
+static const struct at91_i2c_pdata at91sam9g20_config = {
+	.clk_max_div = 7,
+	.clk_offset = 4,
+};
+
+static const struct at91_i2c_pdata at91sam9g10_config = {
+	.clk_max_div = 7,
+	.clk_offset = 4,
+};
+
+static const struct at91_i2c_pdata at91sam9x5_config = {
+	.clk_max_div = 7,
+	.clk_offset = 4,
+};
+
+static const struct at91_i2c_pdata sama5d4_config = {
+	.clk_max_div = 7,
+	.clk_offset = 4,
+};
+
+static const struct at91_i2c_pdata sama5d2_config = {
+	.clk_max_div = 7,
+	.clk_offset = 3,
+};
+
+static const struct udevice_id at91_i2c_ids[] = {
+{ .compatible = "atmel,at91rm9200-i2c", .data = (long)&at91rm9200_config },
+{ .compatible = "atmel,at91sam9260-i2c", .data = (long)&at91sam9260_config },
+{ .compatible = "atmel,at91sam9261-i2c", .data = (long)&at91sam9261_config },
+{ .compatible = "atmel,at91sam9g20-i2c", .data = (long)&at91sam9g20_config },
+{ .compatible = "atmel,at91sam9g10-i2c", .data = (long)&at91sam9g10_config },
+{ .compatible = "atmel,at91sam9x5-i2c", .data = (long)&at91sam9x5_config },
+{ .compatible = "atmel,sama5d4-i2c", .data = (long)&sama5d4_config },
+{ .compatible = "atmel,sama5d2-i2c", .data = (long)&sama5d2_config },
+{ }
+};
+
+U_BOOT_DRIVER(i2c_at91) = {
+	.name	= "i2c_at91",
+	.id	= UCLASS_I2C,
+	.of_match = at91_i2c_ids,
+	.ofdata_to_platdata = at91_i2c_ofdata_to_platdata,
+	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
+	.priv_auto_alloc_size = sizeof(struct at91_i2c_bus),
+	.ops	= &at91_i2c_ops,
+};
diff --git a/drivers/i2c/at91_i2c.h b/drivers/i2c/at91_i2c.h
new file mode 100644
index 0000000..87f02bf
--- /dev/null
+++ b/drivers/i2c/at91_i2c.h
@@ -0,0 +1,77 @@
+#ifndef _AT91_I2C_H
+#define _AT91_I2C_H
+
+#define	TWI_CR_START		BIT(0)	/* Send a Start Condition */
+#define	TWI_CR_MSEN		BIT(2)	/* Master Transfer Enable */
+#define	TWI_CR_STOP		BIT(1)	/* Send a Stop Condition */
+#define	TWI_CR_SVDIS		BIT(5)	/* Slave Transfer Disable */
+#define	TWI_CR_SWRST		BIT(7)	/* Software Reset */
+#define	TWI_CR_ACMEN		BIT(16) /* Alternative Command Mode Enable */
+#define	TWI_CR_ACMDIS		BIT(17) /* Alternative Command Mode Disable */
+#define	TWI_CR_LOCKCLR		BIT(26) /* Lock Clear */
+
+#define	TWI_MMR_MREAD		BIT(12) /* Master Read Direction */
+#define	TWI_MMR_IADRSZ_1	BIT(8)	/* Internal Device Address Size */
+
+#define	TWI_SR_TXCOMP		BIT(0)	/* Transmission Complete */
+#define	TWI_SR_RXRDY		BIT(1)	/* Receive Holding Register Ready */
+#define	TWI_SR_TXRDY		BIT(2)	/* Transmit Holding Register Ready */
+#define	TWI_SR_OVRE		BIT(6)	/* Overrun Error */
+#define	TWI_SR_UNRE		BIT(7)	/* Underrun Error */
+#define	TWI_SR_NACK		BIT(8)	/* Not Acknowledged */
+#define	TWI_SR_LOCK		BIT(23) /* TWI Lock due to Frame Errors */
+
+#define	TWI_ACR_DATAL(len)	((len) & 0xff)
+#define	TWI_ACR_DIR_READ	BIT(8)
+
+#define	TWI_CWGR_HOLD_MAX	0x1f
+#define	TWI_CWGR_HOLD(x)	(((x) & TWI_CWGR_HOLD_MAX) << 24)
+
+struct at91_i2c_regs {
+	u32 cr;
+	u32 mmr;
+	u32 smr;
+	u32 iadr;
+	u32 cwgr;
+	u32 rev_0[3];
+	u32 sr;
+	u32 ier;
+	u32 idr;
+	u32 imr;
+	u32 rhr;
+	u32 thr;
+	u32 smbtr;
+	u32 rev_1;
+	u32 acr;
+	u32 filtr;
+	u32 rev_2;
+	u32 swmr;
+	u32 fmr;
+	u32 flr;
+	u32 rev_3;
+	u32 fsr;
+	u32 fier;
+	u32 fidr;
+	u32 fimr;
+	u32 rev_4[29];
+	u32 wpmr;
+	u32 wpsr;
+	u32 rev_5[6];
+};
+
+struct at91_i2c_pdata {
+	unsigned clk_max_div;
+	unsigned clk_offset;
+};
+
+struct at91_i2c_bus {
+	struct at91_i2c_regs *regs;
+	u32 status;
+	ulong bus_clk_rate;
+	u32 clock_frequency;
+	u32 speed;
+	u32 cwgr_val;
+	const struct at91_i2c_pdata *pdata;
+};
+
+#endif
diff --git a/drivers/i2c/cros_ec_ldo.c b/drivers/i2c/cros_ec_ldo.c
index b817c61..a4cd660 100644
--- a/drivers/i2c/cros_ec_ldo.c
+++ b/drivers/i2c/cros_ec_ldo.c
@@ -72,6 +72,5 @@
 	.name	= "cros_ec_ldo_tunnel",
 	.id	= UCLASS_I2C,
 	.of_match = cros_ec_i2c_ids,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
 	.ops	= &cros_ec_i2c_ops,
 };
diff --git a/drivers/i2c/cros_ec_tunnel.c b/drivers/i2c/cros_ec_tunnel.c
index 7ab1fd8..e2c6e44 100644
--- a/drivers/i2c/cros_ec_tunnel.c
+++ b/drivers/i2c/cros_ec_tunnel.c
@@ -36,6 +36,5 @@
 	.name	= "cros_ec_tunnel",
 	.id	= UCLASS_I2C,
 	.of_match = cros_ec_i2c_ids,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
 	.ops	= &cros_ec_i2c_ops,
 };
diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c
index b8cc647..c3f826d 100644
--- a/drivers/i2c/fsl_i2c.c
+++ b/drivers/i2c/fsl_i2c.c
@@ -583,12 +583,11 @@
 static int fsl_i2c_ofdata_to_platdata(struct udevice *bus)
 {
 	struct fsl_i2c_dev *dev = dev_get_priv(bus);
-	u64 reg;
-	u32 addr, size;
+	fdt_addr_t addr;
+	fdt_size_t size;
 
-	reg = fdtdec_get_addr(gd->fdt_blob, bus->of_offset, "reg");
-	addr = reg >> 32;
-	size = reg & 0xFFFFFFFF;
+	addr = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, bus->of_offset,
+						  "reg", 0, &size, false);
 
 	dev->base = map_sysmem(CONFIG_SYS_IMMR + addr, size);
 
diff --git a/drivers/i2c/i2c-uclass-compat.c b/drivers/i2c/i2c-uclass-compat.c
index 5606d1f..de78db6 100644
--- a/drivers/i2c/i2c-uclass-compat.c
+++ b/drivers/i2c/i2c-uclass-compat.c
@@ -9,7 +9,7 @@
 #include <errno.h>
 #include <i2c.h>
 
-static int cur_busnum;
+static int cur_busnum __attribute__((section(".data")));
 
 static int i2c_compat_get_device(uint chip_addr, int alen,
 				 struct udevice **devp)
diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c
index 50b99ea..dbd3789 100644
--- a/drivers/i2c/i2c-uclass.c
+++ b/drivers/i2c/i2c-uclass.c
@@ -12,7 +12,6 @@
 #include <malloc.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
-#include <dm/root.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -467,6 +466,7 @@
 	return ops->deblock(bus);
 }
 
+#if CONFIG_IS_ENABLED(OF_CONTROL)
 int i2c_chip_ofdata_to_platdata(const void *blob, int node,
 				struct dm_i2c_chip *chip)
 {
@@ -482,38 +482,43 @@
 
 	return 0;
 }
+#endif
 
 static int i2c_post_probe(struct udevice *dev)
 {
+#if CONFIG_IS_ENABLED(OF_CONTROL)
 	struct dm_i2c_bus *i2c = dev_get_uclass_priv(dev);
 
 	i2c->speed_hz = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
 				     "clock-frequency", 100000);
 
 	return dm_i2c_set_bus_speed(dev, i2c->speed_hz);
-}
-
-static int i2c_post_bind(struct udevice *dev)
-{
-	/* Scan the bus for devices */
-	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+#else
+	return 0;
+#endif
 }
 
 static int i2c_child_post_bind(struct udevice *dev)
 {
+#if CONFIG_IS_ENABLED(OF_CONTROL)
 	struct dm_i2c_chip *plat = dev_get_parent_platdata(dev);
 
 	if (dev->of_offset == -1)
 		return 0;
 
 	return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, plat);
+#else
+	return 0;
+#endif
 }
 
 UCLASS_DRIVER(i2c) = {
 	.id		= UCLASS_I2C,
 	.name		= "i2c",
 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
-	.post_bind	= i2c_post_bind,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	.post_bind	= dm_scan_fdt_dev,
+#endif
 	.post_probe	= i2c_post_probe,
 	.per_device_auto_alloc_size = sizeof(struct dm_i2c_bus),
 	.per_child_platdata_auto_alloc_size = sizeof(struct dm_i2c_chip),
diff --git a/drivers/i2c/i2c-uniphier-f.c b/drivers/i2c/i2c-uniphier-f.c
index aebdcfc..a56e058 100644
--- a/drivers/i2c/i2c-uniphier-f.c
+++ b/drivers/i2c/i2c-uniphier-f.c
@@ -1,5 +1,7 @@
 /*
- * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2014      Panasonic Corporation
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -13,7 +15,6 @@
 #include <dm/root.h>
 #include <i2c.h>
 #include <fdtdec.h>
-#include <mapmem.h>
 
 struct uniphier_fi2c_regs {
 	u32 cr;				/* control register */
@@ -118,7 +119,7 @@
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
-	priv->regs = map_sysmem(addr, SZ_128);
+	priv->regs = devm_ioremap(dev, addr, SZ_128);
 	if (!priv->regs)
 		return -ENOMEM;
 
@@ -134,15 +135,6 @@
 	return 0;
 }
 
-static int uniphier_fi2c_remove(struct udevice *dev)
-{
-	struct uniphier_fi2c_dev *priv = dev_get_priv(dev);
-
-	unmap_sysmem(priv->regs);
-
-	return 0;
-}
-
 static int wait_for_irq(struct uniphier_fi2c_dev *dev, u32 flags,
 			bool *stop)
 {
@@ -359,7 +351,6 @@
 	.id = UCLASS_I2C,
 	.of_match = uniphier_fi2c_of_match,
 	.probe = uniphier_fi2c_probe,
-	.remove = uniphier_fi2c_remove,
 	.priv_auto_alloc_size = sizeof(struct uniphier_fi2c_dev),
 	.ops = &uniphier_fi2c_ops,
 };
diff --git a/drivers/i2c/i2c-uniphier.c b/drivers/i2c/i2c-uniphier.c
index f8221da..39a3ebd 100644
--- a/drivers/i2c/i2c-uniphier.c
+++ b/drivers/i2c/i2c-uniphier.c
@@ -1,5 +1,7 @@
 /*
- * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2014      Panasonic Corporation
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -13,7 +15,6 @@
 #include <dm/root.h>
 #include <i2c.h>
 #include <fdtdec.h>
-#include <mapmem.h>
 
 struct uniphier_i2c_regs {
 	u32 dtrm;			/* data transmission */
@@ -53,7 +54,7 @@
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
-	priv->regs = map_sysmem(addr, SZ_64);
+	priv->regs = devm_ioremap(dev, addr, SZ_64);
 	if (!priv->regs)
 		return -ENOMEM;
 
@@ -65,15 +66,6 @@
 	return 0;
 }
 
-static int uniphier_i2c_remove(struct udevice *dev)
-{
-	struct uniphier_i2c_dev *priv = dev_get_priv(dev);
-
-	unmap_sysmem(priv->regs);
-
-	return 0;
-}
-
 static int send_and_recv_byte(struct uniphier_i2c_dev *dev, u32 dtrm)
 {
 	writel(dtrm, &dev->regs->dtrm);
@@ -220,7 +212,6 @@
 	.id = UCLASS_I2C,
 	.of_match = uniphier_i2c_of_match,
 	.probe = uniphier_i2c_probe,
-	.remove = uniphier_i2c_remove,
 	.priv_auto_alloc_size = sizeof(struct uniphier_i2c_dev),
 	.ops = &uniphier_i2c_ops,
 };
diff --git a/drivers/i2c/intel_i2c.c b/drivers/i2c/intel_i2c.c
index 3d777ff..a0182dc 100644
--- a/drivers/i2c/intel_i2c.c
+++ b/drivers/i2c/intel_i2c.c
@@ -2,54 +2,290 @@
  * Copyright (c) 2015 Google, Inc
  * Written by Simon Glass <sjg@chromium.org>
  *
+ * SMBus block read/write support added by Stefan Roese:
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
  * SPDX-License-Identifier:     GPL-2.0+
  */
 
 #include <common.h>
 #include <dm.h>
 #include <i2c.h>
+#include <pci.h>
 #include <asm/io.h>
-#include <asm/arch/pch.h>
 
-int intel_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
+/* PCI Configuration Space (D31:F3): SMBus */
+#define SMB_BASE		0x20
+#define HOSTC			0x40
+#define  HST_EN			(1 << 0)
+#define SMB_RCV_SLVA		0x09
+
+/* SMBus I/O bits. */
+#define SMBHSTSTAT		0x0
+#define SMBHSTCTL		0x2
+#define SMBHSTCMD		0x3
+#define SMBXMITADD		0x4
+#define SMBHSTDAT0		0x5
+#define SMBHSTDAT1		0x6
+#define SMBBLKDAT		0x7
+#define SMBTRNSADD		0x9
+#define SMBSLVDATA		0xa
+#define SMBAUXCTL		0xd
+#define SMLINK_PIN_CTL		0xe
+#define SMBUS_PIN_CTL		0xf
+
+/* I801 Hosts Status register bits */
+#define SMBHSTSTS_BYTE_DONE	0x80
+#define SMBHSTSTS_INUSE_STS	0x40
+#define SMBHSTSTS_SMBALERT_STS	0x20
+#define SMBHSTSTS_FAILED	0x10
+#define SMBHSTSTS_BUS_ERR	0x08
+#define SMBHSTSTS_DEV_ERR	0x04
+#define SMBHSTSTS_INTR		0x02
+#define SMBHSTSTS_HOST_BUSY	0x01
+
+/* I801 Host Control register bits */
+#define SMBHSTCNT_INTREN	0x01
+#define SMBHSTCNT_KILL		0x02
+#define SMBHSTCNT_LAST_BYTE	0x20
+#define SMBHSTCNT_START		0x40
+#define SMBHSTCNT_PEC_EN	0x80	/* ICH3 and later */
+
+/* Auxiliary control register bits, ICH4+ only */
+#define SMBAUXCTL_CRC		1
+#define SMBAUXCTL_E32B		2
+
+#define SMBUS_TIMEOUT	100	/* 100 ms */
+
+struct intel_i2c {
+	u32 base;
+	int running;
+};
+
+static int smbus_wait_until_ready(u32 base)
 {
-	return -ENOSYS;
+	unsigned long ts;
+	u8 byte;
+
+	ts = get_timer(0);
+	do {
+		byte = inb(base + SMBHSTSTAT);
+		if (!(byte & 1))
+			return 0;
+	} while (get_timer(ts) < SMBUS_TIMEOUT);
+
+	return -ETIMEDOUT;
 }
 
-int intel_i2c_probe_chip(struct udevice *bus, uint chip_addr, uint chip_flags)
+static int smbus_wait_until_done(u32 base)
 {
-	return -ENOSYS;
+	unsigned long ts;
+	u8 byte;
+
+	ts = get_timer(0);
+	do {
+		byte = inb(base + SMBHSTSTAT);
+		if (!((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0))
+			return 0;
+	} while (get_timer(ts) < SMBUS_TIMEOUT);
+
+	return -ETIMEDOUT;
 }
 
-int intel_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+static int smbus_block_read(u32 base, u8 dev, u8 *buffer,
+			    int offset, int len)
 {
+	u8 buf_temp[32];
+	int count;
+	int i;
+
+	debug("%s (%d): dev=0x%x offs=0x%x len=0x%x\n",
+	      __func__, __LINE__, dev, offset, len);
+	if (smbus_wait_until_ready(base) < 0)
+		return -ETIMEDOUT;
+
+	/* Setup transaction */
+
+	/* Reset the data buffer index */
+	inb(base + SMBHSTCTL);
+
+	/* Set the device I'm talking too */
+	outb(((dev & 0x7f) << 1) | 1, base + SMBXMITADD);
+	/* Set the command/address... */
+	outb(offset & 0xff, base + SMBHSTCMD);
+	/* Set up for a block read */
+	outb((inb(base + SMBHSTCTL) & (~(0x7) << 2)) | (0x5 << 2),
+	     (base + SMBHSTCTL));
+	/* Clear any lingering errors, so the transaction will run */
+	outb(inb(base + SMBHSTSTAT), base + SMBHSTSTAT);
+
+	/* Start the command */
+	outb((inb(base + SMBHSTCTL) | SMBHSTCNT_START), base + SMBHSTCTL);
+
+	/* Poll for transaction completion */
+	if (smbus_wait_until_done(base) < 0) {
+		printf("SMBUS read transaction timeout (dev=0x%x)\n", dev);
+		return -ETIMEDOUT;
+	}
+
+	count = inb(base + SMBHSTDAT0);
+	debug("%s (%d): count=%d (len=%d)\n", __func__, __LINE__, count, len);
+	if (count == 0) {
+		debug("ERROR: len=0 on read\n");
+		return -EIO;
+	}
+
+	if (count < len) {
+		debug("ERROR: too few bytes read\n");
+		return -EIO;
+	}
+
+	if (count > 32) {
+		debug("ERROR: count=%d too high\n", count);
+		return -EIO;
+	}
+
+	/* Read all available bytes from buffer */
+	for (i = 0; i < count; i++)
+		buf_temp[i] = inb(base + SMBBLKDAT);
+
+	memcpy(buffer, buf_temp, len);
+
+	/* Return results of transaction */
+	if (!(inb(base + SMBHSTSTAT) & SMBHSTSTS_INTR))
+		return -EIO;
+
 	return 0;
 }
 
-static int intel_i2c_probe(struct udevice *dev)
+static int smbus_block_write(u32 base, u8 dev, u8 *buffer,
+			     int offset, int len)
+{
+	int i;
+
+	debug("%s (%d): dev=0x%x offs=0x%x len=0x%x\n",
+	      __func__, __LINE__, dev, offset, len);
+	if (smbus_wait_until_ready(base) < 0)
+		return -ETIMEDOUT;
+
+	/* Setup transaction */
+	/* Set the device I'm talking too */
+	outb(((dev & 0x7f) << 1) & ~0x01, base + SMBXMITADD);
+	/* Set the command/address... */
+	outb(offset, base + SMBHSTCMD);
+	/* Set up for a block write */
+	outb((inb(base + SMBHSTCTL) & (~(0x7) << 2)) | (0x5 << 2),
+	     (base + SMBHSTCTL));
+	/* Clear any lingering errors, so the transaction will run */
+	outb(inb(base + SMBHSTSTAT), base + SMBHSTSTAT);
+
+	/* Write count in DAT0 register */
+	outb(len, base + SMBHSTDAT0);
+
+	/* Write data bytes... */
+	for (i = 0; i < len; i++)
+		outb(*buffer++, base + SMBBLKDAT);
+
+	/* Start the command */
+	outb((inb(base + SMBHSTCTL) | SMBHSTCNT_START), base + SMBHSTCTL);
+
+	/* Poll for transaction completion */
+	if (smbus_wait_until_done(base) < 0) {
+		printf("SMBUS write transaction timeout (dev=0x%x)\n", dev);
+		return -ETIMEDOUT;
+	}
+
+	/* Return results of transaction */
+	if (!(inb(base + SMBHSTSTAT) & SMBHSTSTS_INTR))
+		return -EIO;
+
+	return 0;
+}
+
+static int intel_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
 {
+	struct intel_i2c *i2c = dev_get_priv(bus);
+	struct i2c_msg *dmsg, *omsg, dummy;
+
+	debug("i2c_xfer: %d messages\n", nmsgs);
+
+	memset(&dummy, 0, sizeof(struct i2c_msg));
+
 	/*
-	 * So far this is just setup code for ivybridge SMbus. When we have
-	 * a full I2C driver this may need to be moved, generalised or made
-	 * dependant on a particular compatible string.
-	 *
-	 * Set SMBus I/O base
+	 * We expect either two messages (one with an offset and one with the
+	 * actucal data) or one message (just data)
 	 */
-	dm_pci_write_config32(dev, SMB_BASE,
-			      SMBUS_IO_BASE | PCI_BASE_ADDRESS_SPACE_IO);
+	if (nmsgs > 2 || nmsgs == 0) {
+		debug("%s: Only one or two messages are supported", __func__);
+		return -EIO;
+	}
+
+	omsg = nmsgs == 1 ? &dummy : msg;
+	dmsg = nmsgs == 1 ? msg : msg + 1;
+
+	if (dmsg->flags & I2C_M_RD)
+		return smbus_block_read(i2c->base, dmsg->addr, &dmsg->buf[0],
+					omsg->buf[0], dmsg->len);
+	else
+		return smbus_block_write(i2c->base, dmsg->addr, &dmsg->buf[1],
+					 dmsg->buf[0], dmsg->len - 1);
+}
+
+static int intel_i2c_probe_chip(struct udevice *bus, uint chip_addr,
+				uint chip_flags)
+{
+	struct intel_i2c *i2c = dev_get_priv(bus);
+	u8 buf[4];
+
+	return smbus_block_read(i2c->base, chip_addr, buf, 0, 1);
+}
+
+static int intel_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+{
+	return 0;
+}
+
+static int intel_i2c_probe(struct udevice *dev)
+{
+	struct intel_i2c *priv = dev_get_priv(dev);
+	u32 base;
+
+	/* Save base address from PCI BAR */
+	priv->base = (u32)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4,
+					 PCI_REGION_IO);
+	base = priv->base;
 
 	/* Set SMBus enable. */
 	dm_pci_write_config8(dev, HOSTC, HST_EN);
 
-	/* Set SMBus I/O space enable. */
-	dm_pci_write_config16(dev, PCI_COMMAND, PCI_COMMAND_IO);
+	/* Disable interrupts */
+	outb(inb(base + SMBHSTCTL) & ~SMBHSTCNT_INTREN, base + SMBHSTCTL);
 
-	/* Disable interrupt generation. */
-	outb(0, SMBUS_IO_BASE + SMBHSTCTL);
+	/* Set 32-byte data buffer mode */
+	outb(inb(base + SMBAUXCTL) | SMBAUXCTL_E32B, base + SMBAUXCTL);
 
-	/* Clear any lingering errors, so transactions can run. */
-	outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
-	debug("SMBus controller enabled\n");
+	return 0;
+}
+
+static int intel_i2c_bind(struct udevice *dev)
+{
+	static int num_cards __attribute__ ((section(".data")));
+	char name[20];
+
+	/* Create a unique device name for PCI type devices */
+	if (device_is_on_pci_bus(dev)) {
+		/*
+		 * ToDo:
+		 * Setting req_seq in the driver is probably not recommended.
+		 * But without a DT alias the number is not configured. And
+		 * using this driver is impossible for PCIe I2C devices.
+		 * This can be removed, once a better (correct) way for this
+		 * is found and implemented.
+		 */
+		dev->req_seq = num_cards;
+		sprintf(name, "intel_i2c#%u", num_cards++);
+		device_set_name(dev, name);
+	}
 
 	return 0;
 }
@@ -69,7 +305,18 @@
 	.name	= "i2c_intel",
 	.id	= UCLASS_I2C,
 	.of_match = intel_i2c_ids,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
 	.ops	= &intel_i2c_ops,
+	.priv_auto_alloc_size = sizeof(struct intel_i2c),
+	.bind	= intel_i2c_bind,
 	.probe	= intel_i2c_probe,
 };
+
+static struct pci_device_id intel_smbus_pci_supported[] = {
+	/* Intel BayTrail SMBus on the PCI bus */
+	{ PCI_VDEVICE(INTEL, 0x0f12) },
+	/* Intel IvyBridge (Panther Point PCH) SMBus on the PCI bus */
+	{ PCI_VDEVICE(INTEL, 0x1e22) },
+	{},
+};
+
+U_BOOT_PCI_DEVICE(intel_i2c, intel_smbus_pci_supported);
diff --git a/drivers/i2c/muxes/i2c-mux-uclass.c b/drivers/i2c/muxes/i2c-mux-uclass.c
index 3f52bff..7a698b6 100644
--- a/drivers/i2c/muxes/i2c-mux-uclass.c
+++ b/drivers/i2c/muxes/i2c-mux-uclass.c
@@ -183,7 +183,6 @@
 U_BOOT_DRIVER(i2c_mux_bus) = {
 	.name		= "i2c_mux_bus_drv",
 	.id		= UCLASS_I2C,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
 	.ops	= &i2c_mux_bus_ops,
 };
 
diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c
index bf44432..ab7481a 100644
--- a/drivers/i2c/mvtwsi.c
+++ b/drivers/i2c/mvtwsi.c
@@ -12,12 +12,19 @@
 #include <i2c.h>
 #include <asm/errno.h>
 #include <asm/io.h>
+#include <linux/compat.h>
+#ifdef CONFIG_DM_I2C
+#include <dm.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
 
 /*
- * include a file that will provide CONFIG_I2C_MVTWSI_BASE*
- * and possibly other settings
+ * Include a file that will provide CONFIG_I2C_MVTWSI_BASE*, and possibly other
+ * settings
  */
 
+#ifndef CONFIG_DM_I2C
 #if defined(CONFIG_ORION5X)
 #include <asm/arch/orion5x.h>
 #elif (defined(CONFIG_KIRKWOOD) || defined(CONFIG_ARCH_MVEBU))
@@ -27,6 +34,7 @@
 #else
 #error Driver mvtwsi not supported by SoC or board
 #endif
+#endif /* CONFIG_DM_I2C */
 
 /*
  * TWSI register structure
@@ -51,8 +59,8 @@
 	u32 data;
 	u32 control;
 	union {
-		u32 status;	/* when reading */
-		u32 baudrate;	/* when writing */
+		u32 status;	/* When reading */
+		u32 baudrate;	/* When writing */
 	};
 	u32 xtnd_slave_addr;
 	u32 reserved[2];
@@ -61,20 +69,43 @@
 
 #endif
 
+#ifdef CONFIG_DM_I2C
+struct mvtwsi_i2c_dev {
+	/* TWSI Register base for the device */
+	struct mvtwsi_registers *base;
+	/* Number of the device (determined from cell-index property) */
+	int index;
+	/* The I2C slave address for the device */
+	u8 slaveadd;
+	/* The configured I2C speed in Hz */
+	uint speed;
+	/* The current length of a clock period (depending on speed) */
+	uint tick;
+};
+#endif /* CONFIG_DM_I2C */
+
 /*
- * Control register fields
+ * enum mvtwsi_ctrl_register_fields - Bit masks for flags in the control
+ * register
  */
-
-#define	MVTWSI_CONTROL_ACK	0x00000004
-#define	MVTWSI_CONTROL_IFLG	0x00000008
-#define	MVTWSI_CONTROL_STOP	0x00000010
-#define	MVTWSI_CONTROL_START	0x00000020
-#define	MVTWSI_CONTROL_TWSIEN	0x00000040
-#define	MVTWSI_CONTROL_INTEN	0x00000080
+enum mvtwsi_ctrl_register_fields {
+	/* Acknowledge bit */
+	MVTWSI_CONTROL_ACK	= 0x00000004,
+	/* Interrupt flag */
+	MVTWSI_CONTROL_IFLG	= 0x00000008,
+	/* Stop bit */
+	MVTWSI_CONTROL_STOP	= 0x00000010,
+	/* Start bit */
+	MVTWSI_CONTROL_START	= 0x00000020,
+	/* I2C enable */
+	MVTWSI_CONTROL_TWSIEN	= 0x00000040,
+	/* Interrupt enable */
+	MVTWSI_CONTROL_INTEN	= 0x00000080,
+};
 
 /*
- * On sun6i and newer IFLG is a write-clear bit which is cleared by writing 1,
- * on other platforms it is a normal r/w bit which is cleared by writing 0.
+ * On sun6i and newer, IFLG is a write-clear bit, which is cleared by writing 1;
+ * on other platforms, it is a normal r/w bit, which is cleared by writing 0.
  */
 
 #ifdef CONFIG_SUNXI_GEN_SUN6I
@@ -84,53 +115,95 @@
 #endif
 
 /*
- * Status register values -- only those expected in normal master
- * operation on non-10-bit-address devices; whatever status we don't
- * expect in nominal conditions (bus errors, arbitration losses,
- * missing ACKs...) we just pass back to the caller as an error
+ * enum mvstwsi_status_values - Possible values of I2C controller's status
+ * register
+ *
+ * Only those statuses expected in normal master operation on
+ * non-10-bit-address devices are specified.
+ *
+ * Every status that's unexpected during normal operation (bus errors,
+ * arbitration losses, missing ACKs...) is passed back to the caller as an error
  * code.
  */
+enum mvstwsi_status_values {
+	/* START condition transmitted */
+	MVTWSI_STATUS_START		= 0x08,
+	/* Repeated START condition transmitted */
+	MVTWSI_STATUS_REPEATED_START	= 0x10,
+	/* Address + write bit transmitted, ACK received */
+	MVTWSI_STATUS_ADDR_W_ACK	= 0x18,
+	/* Data transmitted, ACK received */
+	MVTWSI_STATUS_DATA_W_ACK	= 0x28,
+	/* Address + read bit transmitted, ACK received */
+	MVTWSI_STATUS_ADDR_R_ACK	= 0x40,
+	/* Address + read bit transmitted, ACK not received */
+	MVTWSI_STATUS_ADDR_R_NAK	= 0x48,
+	/* Data received, ACK transmitted */
+	MVTWSI_STATUS_DATA_R_ACK	= 0x50,
+	/* Data received, ACK not transmitted */
+	MVTWSI_STATUS_DATA_R_NAK	= 0x58,
+	/* No relevant status */
+	MVTWSI_STATUS_IDLE		= 0xF8,
+};
 
-#define	MVTWSI_STATUS_START		0x08
-#define	MVTWSI_STATUS_REPEATED_START	0x10
-#define	MVTWSI_STATUS_ADDR_W_ACK	0x18
-#define	MVTWSI_STATUS_DATA_W_ACK	0x28
-#define	MVTWSI_STATUS_ADDR_R_ACK	0x40
-#define	MVTWSI_STATUS_ADDR_R_NAK	0x48
-#define	MVTWSI_STATUS_DATA_R_ACK	0x50
-#define	MVTWSI_STATUS_DATA_R_NAK	0x58
-#define	MVTWSI_STATUS_IDLE		0xF8
+/*
+ * enum mvstwsi_ack_flags - Determine whether a read byte should be
+ * acknowledged or not.
+ */
+enum mvtwsi_ack_flags {
+	/* Send NAK after received byte */
+	MVTWSI_READ_NAK = 0,
+	/* Send ACK after received byte */
+	MVTWSI_READ_ACK = 1,
+};
 
 /*
- * MVTWSI controller base
+ * calc_tick() - Calculate the duration of a clock cycle from the I2C speed
+ *
+ * @speed:	The speed in Hz to calculate the clock cycle duration for.
+ * @return The duration of a clock cycle in ns.
  */
+inline uint calc_tick(uint speed)
+{
+	/* One tick = the duration of a period at the specified speed in ns (we
+	 * add 100 ns to be on the safe side) */
+	return (1000000000u / speed) + 100;
+}
 
+#ifndef CONFIG_DM_I2C
+
+/*
+ * twsi_get_base() - Get controller register base for specified adapter
+ *
+ * @adap:	Adapter to get the register base for.
+ * @return Register base for the specified adapter.
+ */
 static struct mvtwsi_registers *twsi_get_base(struct i2c_adapter *adap)
 {
 	switch (adap->hwadapnr) {
 #ifdef CONFIG_I2C_MVTWSI_BASE0
 	case 0:
-		return (struct mvtwsi_registers *) CONFIG_I2C_MVTWSI_BASE0;
+		return (struct mvtwsi_registers *)CONFIG_I2C_MVTWSI_BASE0;
 #endif
 #ifdef CONFIG_I2C_MVTWSI_BASE1
 	case 1:
-		return (struct mvtwsi_registers *) CONFIG_I2C_MVTWSI_BASE1;
+		return (struct mvtwsi_registers *)CONFIG_I2C_MVTWSI_BASE1;
 #endif
 #ifdef CONFIG_I2C_MVTWSI_BASE2
 	case 2:
-		return (struct mvtwsi_registers *) CONFIG_I2C_MVTWSI_BASE2;
+		return (struct mvtwsi_registers *)CONFIG_I2C_MVTWSI_BASE2;
 #endif
 #ifdef CONFIG_I2C_MVTWSI_BASE3
 	case 3:
-		return (struct mvtwsi_registers *) CONFIG_I2C_MVTWSI_BASE3;
+		return (struct mvtwsi_registers *)CONFIG_I2C_MVTWSI_BASE3;
 #endif
 #ifdef CONFIG_I2C_MVTWSI_BASE4
 	case 4:
-		return (struct mvtwsi_registers *) CONFIG_I2C_MVTWSI_BASE4;
+		return (struct mvtwsi_registers *)CONFIG_I2C_MVTWSI_BASE4;
 #endif
 #ifdef CONFIG_I2C_MVTWSI_BASE5
 	case 5:
-		return (struct mvtwsi_registers *) CONFIG_I2C_MVTWSI_BASE5;
+		return (struct mvtwsi_registers *)CONFIG_I2C_MVTWSI_BASE5;
 #endif
 	default:
 		printf("Missing mvtwsi controller %d base\n", adap->hwadapnr);
@@ -139,30 +212,48 @@
 
 	return NULL;
 }
+#endif
 
 /*
- * Returned statuses are 0 for success and nonzero otherwise.
- * Currently, cmd_i2c and cmd_eeprom do not interpret an error status.
- * Thus to ease debugging, the return status contains some debug info:
- * - bits 31..24 are error class: 1 is timeout, 2 is 'status mismatch'.
- * - bits 23..16 are the last value of the control register.
- * - bits 15..8 are the last value of the status register.
- * - bits 7..0 are the expected value of the status register.
+ * enum mvtwsi_error_class - types of I2C errors
  */
-
-#define MVTWSI_ERROR_WRONG_STATUS	0x01
-#define MVTWSI_ERROR_TIMEOUT		0x02
+enum mvtwsi_error_class {
+	/* The controller returned a different status than expected */
+	MVTWSI_ERROR_WRONG_STATUS       = 0x01,
+	/* The controller timed out */
+	MVTWSI_ERROR_TIMEOUT            = 0x02,
+};
 
-#define MVTWSI_ERROR(ec, lc, ls, es) (((ec << 24) & 0xFF000000) | \
-	((lc << 16) & 0x00FF0000) | ((ls<<8) & 0x0000FF00) | (es & 0xFF))
+/*
+ * mvtwsi_error() - Build I2C return code from error information
+ *
+ * For debugging purposes, this function packs some information of an occurred
+ * error into a return code. These error codes are returned from I2C API
+ * functions (i2c_{read,write}, dm_i2c_{read,write}, etc.).
+ *
+ * @ec:		The error class of the error (enum mvtwsi_error_class).
+ * @lc:		The last value of the control register.
+ * @ls:		The last value of the status register.
+ * @es:		The expected value of the status register.
+ * @return The generated error code.
+ */
+inline uint mvtwsi_error(uint ec, uint lc, uint ls, uint es)
+{
+	return ((ec << 24) & 0xFF000000)
+	       | ((lc << 16) & 0x00FF0000)
+	       | ((ls << 8) & 0x0000FF00)
+	       | (es & 0xFF);
+}
 
 /*
- * Wait for IFLG to raise, or return 'timeout'; then if status is as expected,
- * return 0 (ok) or return 'wrong status'.
+ * twsi_wait() - Wait for I2C bus interrupt flag and check status, or time out.
+ *
+ * @return Zero if status is as expected, or a non-zero code if either a time
+ *	   out occurred, or the status was not the expected one.
  */
-static int twsi_wait(struct i2c_adapter *adap, int expected_status)
+static int twsi_wait(struct mvtwsi_registers *twsi, int expected_status,
+		     uint tick)
 {
-	struct mvtwsi_registers *twsi = twsi_get_base(adap);
 	int control, status;
 	int timeout = 1000;
 
@@ -173,105 +264,140 @@
 			if (status == expected_status)
 				return 0;
 			else
-				return MVTWSI_ERROR(
+				return mvtwsi_error(
 					MVTWSI_ERROR_WRONG_STATUS,
 					control, status, expected_status);
 		}
-		udelay(10); /* one clock cycle at 100 kHz */
+		ndelay(tick); /* One clock cycle */
 	} while (timeout--);
 	status = readl(&twsi->status);
-	return MVTWSI_ERROR(
-		MVTWSI_ERROR_TIMEOUT, control, status, expected_status);
+	return mvtwsi_error(MVTWSI_ERROR_TIMEOUT, control, status,
+			    expected_status);
 }
 
 /*
- * Assert the START condition, either in a single I2C transaction
- * or inside back-to-back ones (repeated starts).
+ * twsi_start() - Assert a START condition on the bus.
+ *
+ * This function is used in both single I2C transactions and inside
+ * back-to-back transactions (repeated starts).
+ *
+ * @twsi:		The MVTWSI register structure to use.
+ * @expected_status:	The I2C bus status expected to be asserted after the
+ *			operation completion.
+ * @tick:		The duration of a clock cycle at the current I2C speed.
+ * @return Zero if status is as expected, or a non-zero code if either a time
+ *	   out occurred or the status was not the expected one.
  */
-static int twsi_start(struct i2c_adapter *adap, int expected_status, u8 *flags)
+static int twsi_start(struct mvtwsi_registers *twsi, int expected_status,
+		      uint tick)
 {
-	struct mvtwsi_registers *twsi = twsi_get_base(adap);
-
-	/* globally set TWSIEN in case it was not */
-	*flags |= MVTWSI_CONTROL_TWSIEN;
-	/* assert START */
-	writel(*flags | MVTWSI_CONTROL_START |
-				    MVTWSI_CONTROL_CLEAR_IFLG, &twsi->control);
-	/* wait for controller to process START */
-	return twsi_wait(adap, expected_status);
+	/* Assert START */
+	writel(MVTWSI_CONTROL_TWSIEN | MVTWSI_CONTROL_START |
+	       MVTWSI_CONTROL_CLEAR_IFLG, &twsi->control);
+	/* Wait for controller to process START */
+	return twsi_wait(twsi, expected_status, tick);
 }
 
 /*
- * Send a byte (i2c address or data).
+ * twsi_send() - Send a byte on the I2C bus.
+ *
+ * The byte may be part of an address byte or data.
+ *
+ * @twsi:		The MVTWSI register structure to use.
+ * @byte:		The byte to send.
+ * @expected_status:	The I2C bus status expected to be asserted after the
+ *			operation completion.
+ * @tick:		The duration of a clock cycle at the current I2C speed.
+ * @return Zero if status is as expected, or a non-zero code if either a time
+ *	   out occurred or the status was not the expected one.
  */
-static int twsi_send(struct i2c_adapter *adap, u8 byte, int expected_status,
-		     u8 *flags)
+static int twsi_send(struct mvtwsi_registers *twsi, u8 byte,
+		     int expected_status, uint tick)
 {
-	struct mvtwsi_registers *twsi = twsi_get_base(adap);
-
-	/* put byte in data register for sending */
+	/* Write byte to data register for sending */
 	writel(byte, &twsi->data);
-	/* clear any pending interrupt -- that'll cause sending */
-	writel(*flags | MVTWSI_CONTROL_CLEAR_IFLG, &twsi->control);
-	/* wait for controller to receive byte and check ACK */
-	return twsi_wait(adap, expected_status);
+	/* Clear any pending interrupt -- that will cause sending */
+	writel(MVTWSI_CONTROL_TWSIEN | MVTWSI_CONTROL_CLEAR_IFLG,
+	       &twsi->control);
+	/* Wait for controller to receive byte, and check ACK */
+	return twsi_wait(twsi, expected_status, tick);
 }
 
 /*
- * Receive a byte.
- * Global mvtwsi_control_flags variable says if we should ack or nak.
+ * twsi_recv() - Receive a byte on the I2C bus.
+ *
+ * The static variable mvtwsi_control_flags controls whether we ack or nak.
+ *
+ * @twsi:		The MVTWSI register structure to use.
+ * @byte:		The byte to send.
+ * @ack_flag:		Flag that determines whether the received byte should
+ *			be acknowledged by the controller or not (sent ACK/NAK).
+ * @tick:		The duration of a clock cycle at the current I2C speed.
+ * @return Zero if status is as expected, or a non-zero code if either a time
+ *	   out occurred or the status was not the expected one.
  */
-static int twsi_recv(struct i2c_adapter *adap, u8 *byte, u8 *flags)
+static int twsi_recv(struct mvtwsi_registers *twsi, u8 *byte, int ack_flag,
+		     uint tick)
 {
-	struct mvtwsi_registers *twsi = twsi_get_base(adap);
-	int expected_status, status;
+	int expected_status, status, control;
 
-	/* compute expected status based on ACK bit in global control flags */
-	if (*flags & MVTWSI_CONTROL_ACK)
-		expected_status = MVTWSI_STATUS_DATA_R_ACK;
-	else
-		expected_status = MVTWSI_STATUS_DATA_R_NAK;
-	/* acknowledge *previous state* and launch receive */
-	writel(*flags | MVTWSI_CONTROL_CLEAR_IFLG, &twsi->control);
-	/* wait for controller to receive byte and assert ACK or NAK */
-	status = twsi_wait(adap, expected_status);
-	/* if we did receive expected byte then store it */
+	/* Compute expected status based on passed ACK flag */
+	expected_status = ack_flag ? MVTWSI_STATUS_DATA_R_ACK :
+			  MVTWSI_STATUS_DATA_R_NAK;
+	/* Acknowledge *previous state*, and launch receive */
+	control = MVTWSI_CONTROL_TWSIEN;
+	control |= ack_flag == MVTWSI_READ_ACK ? MVTWSI_CONTROL_ACK : 0;
+	writel(control | MVTWSI_CONTROL_CLEAR_IFLG, &twsi->control);
+	/* Wait for controller to receive byte, and assert ACK or NAK */
+	status = twsi_wait(twsi, expected_status, tick);
+	/* If we did receive the expected byte, store it */
 	if (status == 0)
 		*byte = readl(&twsi->data);
-	/* return status */
 	return status;
 }
 
 /*
- * Assert the STOP condition.
- * This is also used to force the bus back in idle (SDA=SCL=1).
+ * twsi_stop() - Assert a STOP condition on the bus.
+ *
+ * This function is also used to force the bus back to idle state (SDA =
+ * SCL = 1).
+ *
+ * @twsi:	The MVTWSI register structure to use.
+ * @tick:	The duration of a clock cycle at the current I2C speed.
+ * @return Zero if the operation succeeded, or a non-zero code if a time out
+ *	   occurred.
  */
-static int twsi_stop(struct i2c_adapter *adap, int status)
+static int twsi_stop(struct mvtwsi_registers *twsi, uint tick)
 {
-	struct mvtwsi_registers *twsi = twsi_get_base(adap);
 	int control, stop_status;
+	int status = 0;
 	int timeout = 1000;
 
-	/* assert STOP */
+	/* Assert STOP */
 	control = MVTWSI_CONTROL_TWSIEN | MVTWSI_CONTROL_STOP;
 	writel(control | MVTWSI_CONTROL_CLEAR_IFLG, &twsi->control);
-	/* wait for IDLE; IFLG won't rise so twsi_wait() is no use. */
+	/* Wait for IDLE; IFLG won't rise, so we can't use twsi_wait() */
 	do {
 		stop_status = readl(&twsi->status);
 		if (stop_status == MVTWSI_STATUS_IDLE)
 			break;
-		udelay(10); /* one clock cycle at 100 kHz */
+		ndelay(tick); /* One clock cycle */
 	} while (timeout--);
 	control = readl(&twsi->control);
 	if (stop_status != MVTWSI_STATUS_IDLE)
-		if (status == 0)
-			status = MVTWSI_ERROR(
-				MVTWSI_ERROR_TIMEOUT,
-				control, status, MVTWSI_STATUS_IDLE);
+		status = mvtwsi_error(MVTWSI_ERROR_TIMEOUT,
+				      control, status, MVTWSI_STATUS_IDLE);
 	return status;
 }
 
-static unsigned int twsi_calc_freq(const int n, const int m)
+/*
+ * twsi_calc_freq() - Compute I2C frequency depending on m and n parameters.
+ *
+ * @n:		Parameter 'n' for the frequency calculation algorithm.
+ * @m:		Parameter 'm' for the frequency calculation algorithm.
+ * @return The I2C frequency corresponding to the passed m and n parameters.
+ */
+static uint twsi_calc_freq(const int n, const int m)
 {
 #ifdef CONFIG_SUNXI
 	return CONFIG_SYS_TCLK / (10 * (m + 1) * (1 << n));
@@ -281,176 +407,303 @@
 }
 
 /*
- * Reset controller.
- * Controller reset also resets the baud rate and slave address, so
- * they must be re-established afterwards.
+ * twsi_reset() - Reset the I2C controller.
+ *
+ * Resetting the controller also resets the baud rate and slave address, hence
+ * they must be re-established after the reset.
+ *
+ * @twsi:	The MVTWSI register structure to use.
  */
-static void twsi_reset(struct i2c_adapter *adap)
+static void twsi_reset(struct mvtwsi_registers *twsi)
 {
-	struct mvtwsi_registers *twsi = twsi_get_base(adap);
-
-	/* reset controller */
+	/* Reset controller */
 	writel(0, &twsi->soft_reset);
-	/* wait 2 ms -- this is what the Marvell LSP does */
+	/* Wait 2 ms -- this is what the Marvell LSP does */
 	udelay(20000);
 }
 
 /*
- * I2C init called by cmd_i2c when doing 'i2c reset'.
- * Sets baud to the highest possible value not exceeding requested one.
+ * __twsi_i2c_set_bus_speed() - Set the speed of the I2C controller.
+ *
+ * This function sets baud rate to the highest possible value that does not
+ * exceed the requested rate.
+ *
+ * @twsi:		The MVTWSI register structure to use.
+ * @requested_speed:	The desired frequency the controller should run at
+ *			in Hz.
+ * @return The actual frequency the controller was configured to.
  */
-static unsigned int twsi_i2c_set_bus_speed(struct i2c_adapter *adap,
-					   unsigned int requested_speed)
+static uint __twsi_i2c_set_bus_speed(struct mvtwsi_registers *twsi,
+				     uint requested_speed)
 {
-	struct mvtwsi_registers *twsi = twsi_get_base(adap);
-	unsigned int tmp_speed, highest_speed, n, m;
-	unsigned int baud = 0x44; /* baudrate at controller reset */
+	uint tmp_speed, highest_speed, n, m;
+	uint baud = 0x44; /* Baud rate after controller reset */
 
-	/* use actual speed to collect progressively higher values */
 	highest_speed = 0;
-	/* compute m, n setting for highest speed not above requested speed */
+	/* Successively try m, n combinations, and use the combination
+	 * resulting in the largest speed that's not above the requested
+	 * speed */
 	for (n = 0; n < 8; n++) {
 		for (m = 0; m < 16; m++) {
 			tmp_speed = twsi_calc_freq(n, m);
-			if ((tmp_speed <= requested_speed)
-			 && (tmp_speed > highest_speed)) {
+			if ((tmp_speed <= requested_speed) &&
+			    (tmp_speed > highest_speed)) {
 				highest_speed = tmp_speed;
 				baud = (m << 3) | n;
 			}
 		}
 	}
 	writel(baud, &twsi->baudrate);
-	return 0;
+
+	/* Wait for controller for one tick */
+#ifdef CONFIG_DM_I2C
+	ndelay(calc_tick(highest_speed));
+#else
+	ndelay(10000);
+#endif
+	return highest_speed;
 }
 
-static void twsi_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
+/*
+ * __twsi_i2c_init() - Initialize the I2C controller.
+ *
+ * @twsi:		The MVTWSI register structure to use.
+ * @speed:		The initial frequency the controller should run at
+ *			in Hz.
+ * @slaveadd:		The I2C address to be set for the I2C master.
+ * @actual_speed:	A output parameter that receives the actual frequency
+ *			in Hz the controller was set to by the function.
+ * @return Zero if the operation succeeded, or a non-zero code if a time out
+ *	   occurred.
+ */
+static void __twsi_i2c_init(struct mvtwsi_registers *twsi, int speed,
+			    int slaveadd, uint *actual_speed)
 {
-	struct mvtwsi_registers *twsi = twsi_get_base(adap);
-
-	/* reset controller */
-	twsi_reset(adap);
-	/* set speed */
-	twsi_i2c_set_bus_speed(adap, speed);
-	/* set slave address even though we don't use it */
+	/* Reset controller */
+	twsi_reset(twsi);
+	/* Set speed */
+	*actual_speed = __twsi_i2c_set_bus_speed(twsi, speed);
+	/* Set slave address; even though we don't use it */
 	writel(slaveadd, &twsi->slave_address);
 	writel(0, &twsi->xtnd_slave_addr);
-	/* assert STOP but don't care for the result */
-	(void) twsi_stop(adap, 0);
+	/* Assert STOP, but don't care for the result */
+#ifdef CONFIG_DM_I2C
+	(void) twsi_stop(twsi, calc_tick(*actual_speed));
+#else
+	(void) twsi_stop(twsi, 10000);
+#endif
 }
 
 /*
- * Begin I2C transaction with expected start status, at given address.
- * Common to i2c_probe, i2c_read and i2c_write.
- * Expected address status will derive from direction bit (bit 0) in addr.
+ * i2c_begin() - Start a I2C transaction.
+ *
+ * Begin a I2C transaction with a given expected start status and chip address.
+ * A START is asserted, and the address byte is sent to the I2C controller. The
+ * expected address status will be derived from the direction bit (bit 0) of
+ * the address byte.
+ *
+ * @twsi:			The MVTWSI register structure to use.
+ * @expected_start_status:	The I2C status the controller is expected to
+ *				assert after the address byte was sent.
+ * @addr:			The address byte to be sent.
+ * @tick:			The duration of a clock cycle at the current
+ *				I2C speed.
+ * @return Zero if the operation succeeded, or a non-zero code if a time out or
+ *	   unexpected I2C status occurred.
  */
-static int i2c_begin(struct i2c_adapter *adap, int expected_start_status,
-		     u8 addr, u8 *flags)
+static int i2c_begin(struct mvtwsi_registers *twsi, int expected_start_status,
+		     u8 addr, uint tick)
 {
 	int status, expected_addr_status;
 
-	/* compute expected address status from direction bit in addr */
-	if (addr & 1) /* reading */
+	/* Compute the expected address status from the direction bit in
+	 * the address byte */
+	if (addr & 1) /* Reading */
 		expected_addr_status = MVTWSI_STATUS_ADDR_R_ACK;
-	else /* writing */
+	else /* Writing */
 		expected_addr_status = MVTWSI_STATUS_ADDR_W_ACK;
-	/* assert START */
-	status = twsi_start(adap, expected_start_status, flags);
-	/* send out the address if the start went well */
+	/* Assert START */
+	status = twsi_start(twsi, expected_start_status, tick);
+	/* Send out the address if the start went well */
 	if (status == 0)
-		status = twsi_send(adap, addr, expected_addr_status,
-				   flags);
-	/* return ok or status of first failure to caller */
+		status = twsi_send(twsi, addr, expected_addr_status, tick);
+	/* Return 0, or the status of the first failure */
 	return status;
 }
 
 /*
- * I2C probe called by cmd_i2c when doing 'i2c probe'.
- * Begin read, nak data byte, end.
+ * __twsi_i2c_probe_chip() - Probe the given I2C chip address.
+ *
+ * This function begins a I2C read transaction, does a dummy read and NAKs; if
+ * the procedure succeeds, the chip is considered to be present.
+ *
+ * @twsi:	The MVTWSI register structure to use.
+ * @chip:	The chip address to probe.
+ * @tick:	The duration of a clock cycle at the current I2C speed.
+ * @return Zero if the operation succeeded, or a non-zero code if a time out or
+ *	   unexpected I2C status occurred.
  */
-static int twsi_i2c_probe(struct i2c_adapter *adap, uchar chip)
+static int __twsi_i2c_probe_chip(struct mvtwsi_registers *twsi, uchar chip,
+				 uint tick)
 {
 	u8 dummy_byte;
-	u8 flags = 0;
 	int status;
 
-	/* begin i2c read */
-	status = i2c_begin(adap, MVTWSI_STATUS_START, (chip << 1) | 1, &flags);
-	/* dummy read was accepted: receive byte but NAK it. */
+	/* Begin i2c read */
+	status = i2c_begin(twsi, MVTWSI_STATUS_START, (chip << 1) | 1, tick);
+	/* Dummy read was accepted: receive byte, but NAK it. */
 	if (status == 0)
-		status = twsi_recv(adap, &dummy_byte, &flags);
+		status = twsi_recv(twsi, &dummy_byte, MVTWSI_READ_NAK, tick);
 	/* Stop transaction */
-	twsi_stop(adap, 0);
-	/* return 0 or status of first failure */
+	twsi_stop(twsi, tick);
+	/* Return 0, or the status of the first failure */
 	return status;
 }
 
 /*
- * I2C read called by cmd_i2c when doing 'i2c read' and by cmd_eeprom.c
- * Begin write, send address byte(s), begin read, receive data bytes, end.
+ * __twsi_i2c_read() - Read data from a I2C chip.
+ *
+ * This function begins a I2C write transaction, and transmits the address
+ * bytes; then begins a I2C read transaction, and receives the data bytes.
+ *
+ * NOTE: Some devices want a stop right before the second start, while some
+ * will choke if it is there. Since deciding this is not yet supported in
+ * higher level APIs, we need to make a decision here, and for the moment that
+ * will be a repeated start without a preceding stop.
  *
- * NOTE: some EEPROMS want a stop right before the second start, while
- * some will choke if it is there. Deciding which we should do is eeprom
- * stuff, not i2c, but at the moment the APIs won't let us put it in
- * cmd_eeprom, so we have to choose here, and for the moment that'll be
- * a repeated start without a preceding stop.
+ * @twsi:	The MVTWSI register structure to use.
+ * @chip:	The chip address to read from.
+ * @addr:	The address bytes to send.
+ * @alen:	The length of the address bytes in bytes.
+ * @data:	The buffer to receive the data read from the chip (has to have
+ *		a size of at least 'length' bytes).
+ * @length:	The amount of data to be read from the chip in bytes.
+ * @tick:	The duration of a clock cycle at the current I2C speed.
+ * @return Zero if the operation succeeded, or a non-zero code if a time out or
+ *	   unexpected I2C status occurred.
  */
-static int twsi_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
-			int alen, uchar *data, int length)
+static int __twsi_i2c_read(struct mvtwsi_registers *twsi, uchar chip,
+			   u8 *addr, int alen, uchar *data, int length,
+			   uint tick)
 {
-	int status;
-	u8 flags = 0;
+	int status = 0;
+	int stop_status;
+	int expected_start = MVTWSI_STATUS_START;
 
-	/* begin i2c write to send the address bytes */
-	status = i2c_begin(adap, MVTWSI_STATUS_START, (chip << 1), &flags);
-	/* send addr bytes */
-	while ((status == 0) && alen--)
-		status = twsi_send(adap, addr >> (8*alen),
-			MVTWSI_STATUS_DATA_W_ACK, &flags);
-	/* begin i2c read to receive eeprom data bytes */
-	if (status == 0)
-		status = i2c_begin(adap, MVTWSI_STATUS_REPEATED_START,
-				   (chip << 1) | 1, &flags);
-	/* prepare ACK if at least one byte must be received */
-	if (length > 0)
-		flags |= MVTWSI_CONTROL_ACK;
-	/* now receive actual bytes */
-	while ((status == 0) && length--) {
-		/* reset NAK if we if no more to read now */
-		if (length == 0)
-			flags &= ~MVTWSI_CONTROL_ACK;
-		/* read current byte */
-		status = twsi_recv(adap, data++, &flags);
+	if (alen > 0) {
+		/* Begin i2c write to send the address bytes */
+		status = i2c_begin(twsi, expected_start, (chip << 1), tick);
+		/* Send address bytes */
+		while ((status == 0) && alen--)
+			status = twsi_send(twsi, *(addr++),
+					   MVTWSI_STATUS_DATA_W_ACK, tick);
+		/* Send repeated STARTs after the initial START */
+		expected_start = MVTWSI_STATUS_REPEATED_START;
 	}
+	/* Begin i2c read to receive data bytes */
+	if (status == 0)
+		status = i2c_begin(twsi, expected_start, (chip << 1) | 1, tick);
+	/* Receive actual data bytes; set NAK if we if we have nothing more to
+	 * read */
+	while ((status == 0) && length--)
+		status = twsi_recv(twsi, data++,
+				   length > 0 ?
+				   MVTWSI_READ_ACK : MVTWSI_READ_NAK, tick);
 	/* Stop transaction */
-	status = twsi_stop(adap, status);
-	/* return 0 or status of first failure */
-	return status;
+	stop_status = twsi_stop(twsi, tick);
+	/* Return 0, or the status of the first failure */
+	return status != 0 ? status : stop_status;
 }
 
 /*
- * I2C write called by cmd_i2c when doing 'i2c write' and by cmd_eeprom.c
- * Begin write, send address byte(s), send data bytes, end.
+ * __twsi_i2c_write() - Send data to a I2C chip.
+ *
+ * This function begins a I2C write transaction, and transmits the address
+ * bytes; then begins a new I2C write transaction, and sends the data bytes.
+ *
+ * @twsi:	The MVTWSI register structure to use.
+ * @chip:	The chip address to read from.
+ * @addr:	The address bytes to send.
+ * @alen:	The length of the address bytes in bytes.
+ * @data:	The buffer containing the data to be sent to the chip.
+ * @length:	The length of data to be sent to the chip in bytes.
+ * @tick:	The duration of a clock cycle at the current I2C speed.
+ * @return Zero if the operation succeeded, or a non-zero code if a time out or
+ *	   unexpected I2C status occurred.
  */
-static int twsi_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
-			int alen, uchar *data, int length)
+static int __twsi_i2c_write(struct mvtwsi_registers *twsi, uchar chip,
+			    u8 *addr, int alen, uchar *data, int length,
+			    uint tick)
 {
-	int status;
-	u8 flags = 0;
+	int status, stop_status;
 
-	/* begin i2c write to send the eeprom adress bytes then data bytes */
-	status = i2c_begin(adap, MVTWSI_STATUS_START, (chip << 1), &flags);
-	/* send addr bytes */
-	while ((status == 0) && alen--)
-		status = twsi_send(adap, addr >> (8*alen),
-			MVTWSI_STATUS_DATA_W_ACK, &flags);
-	/* send data bytes */
+	/* Begin i2c write to send first the address bytes, then the
+	 * data bytes */
+	status = i2c_begin(twsi, MVTWSI_STATUS_START, (chip << 1), tick);
+	/* Send address bytes */
+	while ((status == 0) && (alen-- > 0))
+		status = twsi_send(twsi, *(addr++), MVTWSI_STATUS_DATA_W_ACK,
+				   tick);
+	/* Send data bytes */
 	while ((status == 0) && (length-- > 0))
-		status = twsi_send(adap, *(data++), MVTWSI_STATUS_DATA_W_ACK,
-				   &flags);
+		status = twsi_send(twsi, *(data++), MVTWSI_STATUS_DATA_W_ACK,
+				   tick);
 	/* Stop transaction */
-	status = twsi_stop(adap, status);
-	/* return 0 or status of first failure */
-	return status;
+	stop_status = twsi_stop(twsi, tick);
+	/* Return 0, or the status of the first failure */
+	return status != 0 ? status : stop_status;
+}
+
+#ifndef CONFIG_DM_I2C
+static void twsi_i2c_init(struct i2c_adapter *adap, int speed,
+			  int slaveadd)
+{
+	struct mvtwsi_registers *twsi = twsi_get_base(adap);
+	__twsi_i2c_init(twsi, speed, slaveadd, NULL);
+}
+
+static uint twsi_i2c_set_bus_speed(struct i2c_adapter *adap,
+				   uint requested_speed)
+{
+	struct mvtwsi_registers *twsi = twsi_get_base(adap);
+	__twsi_i2c_set_bus_speed(twsi, requested_speed);
+	return 0;
+}
+
+static int twsi_i2c_probe(struct i2c_adapter *adap, uchar chip)
+{
+	struct mvtwsi_registers *twsi = twsi_get_base(adap);
+	return __twsi_i2c_probe_chip(twsi, chip, 10000);
+}
+
+static int twsi_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
+			 int alen, uchar *data, int length)
+{
+	struct mvtwsi_registers *twsi = twsi_get_base(adap);
+	u8 addr_bytes[4];
+
+	addr_bytes[0] = (addr >> 0) & 0xFF;
+	addr_bytes[1] = (addr >> 8) & 0xFF;
+	addr_bytes[2] = (addr >> 16) & 0xFF;
+	addr_bytes[3] = (addr >> 24) & 0xFF;
+
+	return __twsi_i2c_read(twsi, chip, addr_bytes, alen, data, length,
+			       10000);
+}
+
+static int twsi_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
+			  int alen, uchar *data, int length)
+{
+	struct mvtwsi_registers *twsi = twsi_get_base(adap);
+	u8 addr_bytes[4];
+
+	addr_bytes[0] = (addr >> 0) & 0xFF;
+	addr_bytes[1] = (addr >> 8) & 0xFF;
+	addr_bytes[2] = (addr >> 16) & 0xFF;
+	addr_bytes[3] = (addr >> 24) & 0xFF;
+
+	return __twsi_i2c_write(twsi, chip, addr_bytes, alen, data, length,
+				10000);
 }
 
 #ifdef CONFIG_I2C_MVTWSI_BASE0
@@ -494,3 +747,99 @@
 			 CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 5)
 
 #endif
+#else /* CONFIG_DM_I2C */
+
+static int mvtwsi_i2c_probe_chip(struct udevice *bus, u32 chip_addr,
+				 u32 chip_flags)
+{
+	struct mvtwsi_i2c_dev *dev = dev_get_priv(bus);
+	return __twsi_i2c_probe_chip(dev->base, chip_addr, dev->tick);
+}
+
+static int mvtwsi_i2c_set_bus_speed(struct udevice *bus, uint speed)
+{
+	struct mvtwsi_i2c_dev *dev = dev_get_priv(bus);
+
+	dev->speed = __twsi_i2c_set_bus_speed(dev->base, speed);
+	dev->tick = calc_tick(dev->speed);
+
+	return 0;
+}
+
+static int mvtwsi_i2c_ofdata_to_platdata(struct udevice *bus)
+{
+	struct mvtwsi_i2c_dev *dev = dev_get_priv(bus);
+
+	dev->base = dev_get_addr_ptr(bus);
+
+	if (!dev->base)
+		return -ENOMEM;
+
+	dev->index = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
+				    "cell-index", -1);
+	dev->slaveadd = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
+				       "u-boot,i2c-slave-addr", 0x0);
+	dev->speed = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
+				    "clock-frequency", 100000);
+	return 0;
+}
+
+static int mvtwsi_i2c_probe(struct udevice *bus)
+{
+	struct mvtwsi_i2c_dev *dev = dev_get_priv(bus);
+	uint actual_speed;
+
+	__twsi_i2c_init(dev->base, dev->speed, dev->slaveadd, &actual_speed);
+	dev->speed = actual_speed;
+	dev->tick = calc_tick(dev->speed);
+	return 0;
+}
+
+static int mvtwsi_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
+{
+	struct mvtwsi_i2c_dev *dev = dev_get_priv(bus);
+	struct i2c_msg *dmsg, *omsg, dummy;
+
+	memset(&dummy, 0, sizeof(struct i2c_msg));
+
+	/* We expect either two messages (one with an offset and one with the
+	 * actual data) or one message (just data or offset/data combined) */
+	if (nmsgs > 2 || nmsgs == 0) {
+		debug("%s: Only one or two messages are supported.", __func__);
+		return -1;
+	}
+
+	omsg = nmsgs == 1 ? &dummy : msg;
+	dmsg = nmsgs == 1 ? msg : msg + 1;
+
+	if (dmsg->flags & I2C_M_RD)
+		return __twsi_i2c_read(dev->base, dmsg->addr, omsg->buf,
+				       omsg->len, dmsg->buf, dmsg->len,
+				       dev->tick);
+	else
+		return __twsi_i2c_write(dev->base, dmsg->addr, omsg->buf,
+					omsg->len, dmsg->buf, dmsg->len,
+					dev->tick);
+}
+
+static const struct dm_i2c_ops mvtwsi_i2c_ops = {
+	.xfer		= mvtwsi_i2c_xfer,
+	.probe_chip	= mvtwsi_i2c_probe_chip,
+	.set_bus_speed	= mvtwsi_i2c_set_bus_speed,
+};
+
+static const struct udevice_id mvtwsi_i2c_ids[] = {
+	{ .compatible = "marvell,mv64xxx-i2c", },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(i2c_mvtwsi) = {
+	.name = "i2c_mvtwsi",
+	.id = UCLASS_I2C,
+	.of_match = mvtwsi_i2c_ids,
+	.probe = mvtwsi_i2c_probe,
+	.ofdata_to_platdata = mvtwsi_i2c_ofdata_to_platdata,
+	.priv_auto_alloc_size = sizeof(struct mvtwsi_i2c_dev),
+	.ops = &mvtwsi_i2c_ops,
+};
+#endif /* CONFIG_DM_I2C */
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index a7f3fb4..0006343 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -39,6 +39,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <i2c.h>
 
 #include <asm/arch/i2c.h>
@@ -53,10 +54,14 @@
 /* Absolutely safe for status update at 100 kHz I2C: */
 #define I2C_WAIT	200
 
-static int wait_for_bb(struct i2c_adapter *adap);
-static struct i2c *omap24_get_base(struct i2c_adapter *adap);
-static u16 wait_for_event(struct i2c_adapter *adap);
-static void flush_fifo(struct i2c_adapter *adap);
+struct omap_i2c {
+	struct udevice *clk;
+	struct i2c *regs;
+	unsigned int speed;
+	int waitdelay;
+	int clk_id;
+};
+
 static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed)
 {
 	unsigned int sampleclk, prescaler;
@@ -90,9 +95,96 @@
 	}
 	return -1;
 }
-static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed)
+
+/*
+ * Wait for the bus to be free by checking the Bus Busy (BB)
+ * bit to become clear
+ */
+static int wait_for_bb(struct i2c *i2c_base, int waitdelay)
 {
-	struct i2c *i2c_base = omap24_get_base(adap);
+	int timeout = I2C_TIMEOUT;
+	u16 stat;
+
+	writew(0xFFFF, &i2c_base->stat);	/* clear current interrupts...*/
+#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
+	while ((stat = readw(&i2c_base->stat) & I2C_STAT_BB) && timeout--) {
+#else
+	/* Read RAW status */
+	while ((stat = readw(&i2c_base->irqstatus_raw) &
+		I2C_STAT_BB) && timeout--) {
+#endif
+		writew(stat, &i2c_base->stat);
+		udelay(waitdelay);
+	}
+
+	if (timeout <= 0) {
+		printf("Timed out in wait_for_bb: status=%04x\n",
+		       stat);
+		return 1;
+	}
+	writew(0xFFFF, &i2c_base->stat);	 /* clear delayed stuff*/
+	return 0;
+}
+
+/*
+ * Wait for the I2C controller to complete current action
+ * and update status
+ */
+static u16 wait_for_event(struct i2c *i2c_base, int waitdelay)
+{
+	u16 status;
+	int timeout = I2C_TIMEOUT;
+
+	do {
+		udelay(waitdelay);
+#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
+		status = readw(&i2c_base->stat);
+#else
+		/* Read RAW status */
+		status = readw(&i2c_base->irqstatus_raw);
+#endif
+	} while (!(status &
+		   (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
+		    I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
+		    I2C_STAT_AL)) && timeout--);
+
+	if (timeout <= 0) {
+		printf("Timed out in wait_for_event: status=%04x\n",
+		       status);
+		/*
+		 * If status is still 0 here, probably the bus pads have
+		 * not been configured for I2C, and/or pull-ups are missing.
+		 */
+		printf("Check if pads/pull-ups of bus are properly configured\n");
+		writew(0xFFFF, &i2c_base->stat);
+		status = 0;
+	}
+
+	return status;
+}
+
+static void flush_fifo(struct i2c *i2c_base)
+{
+	u16 stat;
+
+	/*
+	 * note: if you try and read data when its not there or ready
+	 * you get a bus error
+	 */
+	while (1) {
+		stat = readw(&i2c_base->stat);
+		if (stat == I2C_STAT_RRDY) {
+			readb(&i2c_base->data);
+			writew(I2C_STAT_RRDY, &i2c_base->stat);
+			udelay(1000);
+		} else
+			break;
+	}
+}
+
+static int __omap24_i2c_setspeed(struct i2c *i2c_base, uint speed,
+				 int *waitdelay)
+{
 	int psc, fsscll = 0, fssclh = 0;
 	int hsscll = 0, hssclh = 0;
 	u32 scll = 0, sclh = 0;
@@ -142,8 +234,7 @@
 		}
 	}
 
-	adap->speed	= speed;
-	adap->waitdelay = (10000000 / speed) * 2; /* wait for 20 clkperiods */
+	*waitdelay = (10000000 / speed) * 2; /* wait for 20 clkperiods */
 	writew(0, &i2c_base->con);
 	writew(psc, &i2c_base->psc);
 	writew(scll, &i2c_base->scll);
@@ -154,9 +245,8 @@
 	return 0;
 }
 
-static void omap24_i2c_deblock(struct i2c_adapter *adap)
+static void omap24_i2c_deblock(struct i2c *i2c_base)
 {
-	struct i2c *i2c_base = omap24_get_base(adap);
 	int i;
 	u16 systest;
 	u16 orgsystest;
@@ -200,9 +290,9 @@
 	writew(orgsystest, &i2c_base->systest);
 }
 
-static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
+static void __omap24_i2c_init(struct i2c *i2c_base, int speed, int slaveadd,
+			      int *waitdelay)
 {
-	struct i2c *i2c_base = omap24_get_base(adap);
 	int timeout = I2C_TIMEOUT;
 	int deblock = 1;
 
@@ -224,7 +314,7 @@
 		udelay(1000);
 	}
 
-	if (0 != omap24_i2c_setspeed(adap, speed)) {
+	if (0 != __omap24_i2c_setspeed(i2c_base, speed, waitdelay)) {
 		printf("ERROR: failed to setup I2C bus-speed!\n");
 		return;
 	}
@@ -241,45 +331,24 @@
 	       I2C_IE_NACK_IE | I2C_IE_AL_IE, &i2c_base->ie);
 #endif
 	udelay(1000);
-	flush_fifo(adap);
+	flush_fifo(i2c_base);
 	writew(0xFFFF, &i2c_base->stat);
 
 	/* Handle possible failed I2C state */
-	if (wait_for_bb(adap))
+	if (wait_for_bb(i2c_base, *waitdelay))
 		if (deblock == 1) {
-			omap24_i2c_deblock(adap);
+			omap24_i2c_deblock(i2c_base);
 			deblock = 0;
 			goto retry;
 		}
 }
 
-static void flush_fifo(struct i2c_adapter *adap)
-{
-	struct i2c *i2c_base = omap24_get_base(adap);
-	u16 stat;
-
-	/*
-	 * note: if you try and read data when its not there or ready
-	 * you get a bus error
-	 */
-	while (1) {
-		stat = readw(&i2c_base->stat);
-		if (stat == I2C_STAT_RRDY) {
-			readb(&i2c_base->data);
-			writew(I2C_STAT_RRDY, &i2c_base->stat);
-			udelay(1000);
-		} else
-			break;
-	}
-}
-
 /*
  * i2c_probe: Use write access. Allows to identify addresses that are
  *            write-only (like the config register of dual-port EEPROMs)
  */
-static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip)
+static int __omap24_i2c_probe(struct i2c *i2c_base, int waitdelay, uchar chip)
 {
-	struct i2c *i2c_base = omap24_get_base(adap);
 	u16 status;
 	int res = 1; /* default = fail */
 
@@ -287,7 +356,7 @@
 		return res;
 
 	/* Wait until bus is free */
-	if (wait_for_bb(adap))
+	if (wait_for_bb(i2c_base, waitdelay))
 		return res;
 
 	/* No data transfer, slave addr only */
@@ -296,7 +365,7 @@
 	writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
 	       I2C_CON_STP, &i2c_base->con);
 
-	status = wait_for_event(adap);
+	status = wait_for_event(i2c_base, waitdelay);
 
 	if ((status & ~I2C_STAT_XRDY) == 0 || (status & I2C_STAT_AL)) {
 		/*
@@ -306,8 +375,8 @@
 		 * following 'if' section:
 		 */
 		if (status == I2C_STAT_XRDY)
-			printf("i2c_probe: pads on bus %d probably not configured (status=0x%x)\n",
-			       adap->hwadapnr, status);
+			printf("i2c_probe: pads on bus probably not configured (status=0x%x)\n",
+			       status);
 
 		goto pr_exit;
 	}
@@ -315,7 +384,7 @@
 	/* Check for ACK (!NAK) */
 	if (!(status & I2C_STAT_NACK)) {
 		res = 0;				/* Device found */
-		udelay(adap->waitdelay);/* Required by AM335X in SPL */
+		udelay(waitdelay);/* Required by AM335X in SPL */
 		/* Abort transfer (force idle state) */
 		writew(I2C_CON_MST | I2C_CON_TRX, &i2c_base->con); /* Reset */
 		udelay(1000);
@@ -323,7 +392,7 @@
 		       I2C_CON_STP, &i2c_base->con);		/* STP */
 	}
 pr_exit:
-	flush_fifo(adap);
+	flush_fifo(i2c_base);
 	writew(0xFFFF, &i2c_base->stat);
 	return res;
 }
@@ -341,10 +410,9 @@
  *           or that do not need a register address at all (such as some clock
  *           distributors).
  */
-static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
-			   int alen, uchar *buffer, int len)
+static int __omap24_i2c_read(struct i2c *i2c_base, int waitdelay, uchar chip,
+			     uint addr, int alen, uchar *buffer, int len)
 {
-	struct i2c *i2c_base = omap24_get_base(adap);
 	int i2c_error = 0;
 	u16 status;
 
@@ -389,7 +457,7 @@
 #endif
 
 	/* Wait until bus not busy */
-	if (wait_for_bb(adap))
+	if (wait_for_bb(i2c_base, waitdelay))
 		return 1;
 
 	/* Zero, one or two bytes reg address (offset) */
@@ -410,12 +478,12 @@
 #endif
 		/* Send register offset */
 		while (1) {
-			status = wait_for_event(adap);
+			status = wait_for_event(i2c_base, waitdelay);
 			/* Try to identify bus that is not padconf'd for I2C */
 			if (status == I2C_STAT_XRDY) {
 				i2c_error = 2;
-				printf("i2c_read (addr phase): pads on bus %d probably not configured (status=0x%x)\n",
-				       adap->hwadapnr, status);
+				printf("i2c_read (addr phase): pads on bus probably not configured (status=0x%x)\n",
+				       status);
 				goto rd_exit;
 			}
 			if (status == 0 || (status & I2C_STAT_NACK)) {
@@ -450,7 +518,7 @@
 
 	/* Receive data */
 	while (1) {
-		status = wait_for_event(adap);
+		status = wait_for_event(i2c_base, waitdelay);
 		/*
 		 * Try to identify bus that is not padconf'd for I2C. This
 		 * state could be left over from previous transactions if
@@ -458,8 +526,8 @@
 		 */
 		if (status == I2C_STAT_XRDY) {
 			i2c_error = 2;
-			printf("i2c_read (data phase): pads on bus %d probably not configured (status=0x%x)\n",
-			       adap->hwadapnr, status);
+			printf("i2c_read (data phase): pads on bus probably not configured (status=0x%x)\n",
+			       status);
 			goto rd_exit;
 		}
 		if (status == 0 || (status & I2C_STAT_NACK)) {
@@ -477,16 +545,15 @@
 	}
 
 rd_exit:
-	flush_fifo(adap);
+	flush_fifo(i2c_base);
 	writew(0xFFFF, &i2c_base->stat);
 	return i2c_error;
 }
 
 /* i2c_write: Address (reg offset) may be 0, 1 or 2 bytes long. */
-static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
-			    int alen, uchar *buffer, int len)
+static int __omap24_i2c_write(struct i2c *i2c_base, int waitdelay, uchar chip,
+			      uint addr, int alen, uchar *buffer, int len)
 {
-	struct i2c *i2c_base = omap24_get_base(adap);
 	int i;
 	u16 status;
 	int i2c_error = 0;
@@ -536,7 +603,7 @@
 #endif
 
 	/* Wait until bus not busy */
-	if (wait_for_bb(adap))
+	if (wait_for_bb(i2c_base, waitdelay))
 		return 1;
 
 	/* Start address phase - will write regoffset + len bytes data */
@@ -549,12 +616,12 @@
 
 	while (alen) {
 		/* Must write reg offset (one or two bytes) */
-		status = wait_for_event(adap);
+		status = wait_for_event(i2c_base, waitdelay);
 		/* Try to identify bus that is not padconf'd for I2C */
 		if (status == I2C_STAT_XRDY) {
 			i2c_error = 2;
-			printf("i2c_write: pads on bus %d probably not configured (status=0x%x)\n",
-			       adap->hwadapnr, status);
+			printf("i2c_write: pads on bus probably not configured (status=0x%x)\n",
+			       status);
 			goto wr_exit;
 		}
 		if (status == 0 || (status & I2C_STAT_NACK)) {
@@ -576,7 +643,7 @@
 	}
 	/* Address phase is over, now write data */
 	for (i = 0; i < len; i++) {
-		status = wait_for_event(adap);
+		status = wait_for_event(i2c_base, waitdelay);
 		if (status == 0 || (status & I2C_STAT_NACK)) {
 			i2c_error = 1;
 			printf("i2c_write: error waiting for data ACK (status=0x%x)\n",
@@ -598,87 +665,22 @@
 	 * transferred on the bus.
 	 */
 	do {
-		status = wait_for_event(adap);
+		status = wait_for_event(i2c_base, waitdelay);
 	} while (!(status & I2C_STAT_ARDY) && timeout--);
 	if (timeout <= 0)
 		printf("i2c_write: timed out writig last byte!\n");
 
 wr_exit:
-	flush_fifo(adap);
+	flush_fifo(i2c_base);
 	writew(0xFFFF, &i2c_base->stat);
 	return i2c_error;
 }
 
-/*
- * Wait for the bus to be free by checking the Bus Busy (BB)
- * bit to become clear
- */
-static int wait_for_bb(struct i2c_adapter *adap)
-{
-	struct i2c *i2c_base = omap24_get_base(adap);
-	int timeout = I2C_TIMEOUT;
-	u16 stat;
-
-	writew(0xFFFF, &i2c_base->stat);	/* clear current interrupts...*/
-#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
-	while ((stat = readw(&i2c_base->stat) & I2C_STAT_BB) && timeout--) {
-#else
-	/* Read RAW status */
-	while ((stat = readw(&i2c_base->irqstatus_raw) &
-		I2C_STAT_BB) && timeout--) {
-#endif
-		writew(stat, &i2c_base->stat);
-		udelay(adap->waitdelay);
-	}
-
-	if (timeout <= 0) {
-		printf("Timed out in wait_for_bb: status=%04x\n",
-		       stat);
-		return 1;
-	}
-	writew(0xFFFF, &i2c_base->stat);	 /* clear delayed stuff*/
-	return 0;
-}
-
+#ifndef CONFIG_DM_I2C
 /*
- * Wait for the I2C controller to complete current action
- * and update status
+ * The legacy I2C functions. These need to get removed once
+ * all users of this driver are converted to DM.
  */
-static u16 wait_for_event(struct i2c_adapter *adap)
-{
-	struct i2c *i2c_base = omap24_get_base(adap);
-	u16 status;
-	int timeout = I2C_TIMEOUT;
-
-	do {
-		udelay(adap->waitdelay);
-#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
-		status = readw(&i2c_base->stat);
-#else
-		/* Read RAW status */
-		status = readw(&i2c_base->irqstatus_raw);
-#endif
-	} while (!(status &
-		   (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
-		    I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
-		    I2C_STAT_AL)) && timeout--);
-
-	if (timeout <= 0) {
-		printf("Timed out in wait_for_event: status=%04x\n",
-		       status);
-		/*
-		 * If status is still 0 here, probably the bus pads have
-		 * not been configured for I2C, and/or pull-ups are missing.
-		 */
-		printf("Check if pads/pull-ups of bus %d are properly configured\n",
-		       adap->hwadapnr);
-		writew(0xFFFF, &i2c_base->stat);
-		status = 0;
-	}
-
-	return status;
-}
-
 static struct i2c *omap24_get_base(struct i2c_adapter *adap)
 {
 	switch (adap->hwadapnr) {
@@ -710,6 +712,56 @@
 	return NULL;
 }
 
+
+static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
+			   int alen, uchar *buffer, int len)
+{
+	struct i2c *i2c_base = omap24_get_base(adap);
+
+	return __omap24_i2c_read(i2c_base, adap->waitdelay, chip, addr,
+				 alen, buffer, len);
+}
+
+
+static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
+			    int alen, uchar *buffer, int len)
+{
+	struct i2c *i2c_base = omap24_get_base(adap);
+
+	return __omap24_i2c_write(i2c_base, adap->waitdelay, chip, addr,
+				  alen, buffer, len);
+}
+
+static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed)
+{
+	struct i2c *i2c_base = omap24_get_base(adap);
+	int ret;
+
+	ret = __omap24_i2c_setspeed(i2c_base, speed, &adap->waitdelay);
+	if (ret) {
+		error("%s: set i2c speed failed\n", __func__);
+		return ret;
+	}
+
+	adap->speed = speed;
+
+	return 0;
+}
+
+static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
+{
+	struct i2c *i2c_base = omap24_get_base(adap);
+
+	return __omap24_i2c_init(i2c_base, speed, slaveadd, &adap->waitdelay);
+}
+
+static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip)
+{
+	struct i2c *i2c_base = omap24_get_base(adap);
+
+	return __omap24_i2c_probe(i2c_base, adap->waitdelay, chip);
+}
+
 #if !defined(CONFIG_SYS_OMAP24_I2C_SPEED1)
 #define CONFIG_SYS_OMAP24_I2C_SPEED1 CONFIG_SYS_OMAP24_I2C_SPEED
 #endif
@@ -769,3 +821,92 @@
 #endif
 #endif
 #endif
+
+#else /* CONFIG_DM_I2C */
+
+static int omap_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
+{
+	struct omap_i2c *priv = dev_get_priv(bus);
+	int ret;
+
+	debug("i2c_xfer: %d messages\n", nmsgs);
+	for (; nmsgs > 0; nmsgs--, msg++) {
+		debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
+		if (msg->flags & I2C_M_RD) {
+			ret = __omap24_i2c_read(priv->regs, priv->waitdelay,
+						msg->addr, 0, 0, msg->buf,
+						msg->len);
+		} else {
+			ret = __omap24_i2c_write(priv->regs, priv->waitdelay,
+						 msg->addr, 0, 0, msg->buf,
+						 msg->len);
+		}
+		if (ret) {
+			debug("i2c_write: error sending\n");
+			return -EREMOTEIO;
+		}
+	}
+
+	return 0;
+}
+
+static int omap_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+{
+	struct omap_i2c *priv = dev_get_priv(bus);
+
+	priv->speed = speed;
+
+	return __omap24_i2c_setspeed(priv->regs, speed, &priv->waitdelay);
+}
+
+static int omap_i2c_probe_chip(struct udevice *bus, uint chip_addr,
+				     uint chip_flags)
+{
+	struct omap_i2c *priv = dev_get_priv(bus);
+
+	return __omap24_i2c_probe(priv->regs, priv->waitdelay, chip_addr);
+}
+
+static int omap_i2c_probe(struct udevice *bus)
+{
+	struct omap_i2c *priv = dev_get_priv(bus);
+
+	__omap24_i2c_init(priv->regs, priv->speed, 0, &priv->waitdelay);
+
+	return 0;
+}
+
+static int omap_i2c_ofdata_to_platdata(struct udevice *bus)
+{
+	struct omap_i2c *priv = dev_get_priv(bus);
+
+	priv->regs = map_physmem(dev_get_addr(bus), sizeof(void *),
+				 MAP_NOCACHE);
+	priv->speed = CONFIG_SYS_OMAP24_I2C_SPEED;
+
+	return 0;
+}
+
+static const struct dm_i2c_ops omap_i2c_ops = {
+	.xfer		= omap_i2c_xfer,
+	.probe_chip	= omap_i2c_probe_chip,
+	.set_bus_speed	= omap_i2c_set_bus_speed,
+};
+
+static const struct udevice_id omap_i2c_ids[] = {
+	{ .compatible = "ti,omap4-i2c" },
+	{ }
+};
+
+U_BOOT_DRIVER(i2c_omap) = {
+	.name	= "i2c_omap",
+	.id	= UCLASS_I2C,
+	.of_match = omap_i2c_ids,
+	.ofdata_to_platdata = omap_i2c_ofdata_to_platdata,
+	.probe	= omap_i2c_probe,
+	.priv_auto_alloc_size = sizeof(struct omap_i2c),
+	.ops	= &omap_i2c_ops,
+	.flags  = DM_FLAG_PRE_RELOC,
+};
+
+#endif /* CONFIG_DM_I2C */
diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
index dc9b661..eab49d0 100644
--- a/drivers/i2c/s3c24x0_i2c.c
+++ b/drivers/i2c/s3c24x0_i2c.c
@@ -1433,7 +1433,6 @@
 	.id	= UCLASS_I2C,
 	.of_match = s3c_i2c_ids,
 	.ofdata_to_platdata = s3c_i2c_ofdata_to_platdata,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
 	.priv_auto_alloc_size = sizeof(struct s3c24x0_i2c_bus),
 	.ops	= &s3c_i2c_ops,
 };
@@ -1458,7 +1457,6 @@
 	.id	= UCLASS_I2C,
 	.of_match = exynos_hs_i2c_ids,
 	.ofdata_to_platdata = s3c_i2c_ofdata_to_platdata,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
 	.priv_auto_alloc_size = sizeof(struct s3c24x0_i2c_bus),
 	.ops	= &exynos_hs_i2c_ops,
 };
diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c
index 2c84c41..4696a1a 100644
--- a/drivers/i2c/sandbox_i2c.c
+++ b/drivers/i2c/sandbox_i2c.c
@@ -14,7 +14,6 @@
 #include <asm/test.h>
 #include <dm/lists.h>
 #include <dm/device-internal.h>
-#include <dm/root.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -33,8 +32,7 @@
 	*opsp = NULL;
 	plat = dev_get_parent_platdata(dev);
 	if (!plat->emul) {
-		ret = dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset,
-				       false);
+		ret = dm_scan_fdt_dev(dev);
 		if (ret)
 			return ret;
 
diff --git a/drivers/i2c/tegra186_bpmp_i2c.c b/drivers/i2c/tegra186_bpmp_i2c.c
new file mode 100644
index 0000000..88e8413
--- /dev/null
+++ b/drivers/i2c/tegra186_bpmp_i2c.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+#include <misc.h>
+#include <asm/arch-tegra/bpmp_abi.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct tegra186_bpmp_i2c {
+	uint32_t bpmp_bus_id;
+};
+
+static inline void serialize_u16(uint8_t **p, uint16_t val)
+{
+	(*p)[0] = val & 0xff;
+	(*p)[1] = val >> 8;
+	(*p) += 2;
+}
+
+/* These just happen to have the same values as I2C_M_* and SERIALI2C_* */
+#define SUPPORTED_FLAGS \
+	(I2C_M_TEN | \
+	I2C_M_RD | \
+	I2C_M_STOP | \
+	I2C_M_NOSTART | \
+	I2C_M_REV_DIR_ADDR | \
+	I2C_M_IGNORE_NAK | \
+	I2C_M_NO_RD_ACK | \
+	I2C_M_RECV_LEN)
+
+static int tegra186_bpmp_i2c_xfer(struct udevice *dev, struct i2c_msg *msg,
+				  int nmsgs)
+{
+	struct tegra186_bpmp_i2c *priv = dev_get_priv(dev);
+	struct mrq_i2c_request req;
+	struct mrq_i2c_response resp;
+	uint8_t *p;
+	int left, i, ret;
+
+	req.cmd = CMD_I2C_XFER;
+	req.xfer.bus_id = priv->bpmp_bus_id;
+	p = &req.xfer.data_buf[0];
+	left = ARRAY_SIZE(req.xfer.data_buf);
+	for (i = 0; i < nmsgs; i++) {
+		int len = 6;
+		if (!(msg[i].flags & I2C_M_RD))
+			len += msg[i].len;
+		if ((len >= BIT(16)) || (len > left))
+			return -ENOSPC;
+
+		if (msg[i].flags & ~SUPPORTED_FLAGS)
+			return -EINVAL;
+
+		serialize_u16(&p, msg[i].addr);
+		serialize_u16(&p, msg[i].flags);
+		serialize_u16(&p, msg[i].len);
+		if (!(msg[i].flags & I2C_M_RD)) {
+			memcpy(p, msg[i].buf, msg[i].len);
+			p += msg[i].len;
+		}
+	}
+	req.xfer.data_size = p - &req.xfer.data_buf[0];
+
+	ret = misc_call(dev->parent, MRQ_I2C, &req, sizeof(req), &resp,
+			sizeof(resp));
+	if (ret < 0)
+		return ret;
+
+	p = &resp.xfer.data_buf[0];
+	left = resp.xfer.data_size;
+	if (left > ARRAY_SIZE(resp.xfer.data_buf))
+		return -EINVAL;
+	for (i = 0; i < nmsgs; i++) {
+		if (msg[i].flags & I2C_M_RD) {
+			memcpy(msg[i].buf, p, msg[i].len);
+			p += msg[i].len;
+		}
+	}
+
+	return 0;
+}
+
+static int tegra186_bpmp_i2c_probe(struct udevice *dev)
+{
+	struct tegra186_bpmp_i2c *priv = dev_get_priv(dev);
+	int ret;
+	struct fdtdec_phandle_args args;
+
+	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
+					     "nvidia,bpmp", NULL, 0, 0, &args);
+	if (ret < 0) {
+		debug("%s: fdtdec_parse_phandle_with_args() failed: %d\n",
+		      __func__, ret);
+		return ret;
+	}
+
+	priv->bpmp_bus_id = fdtdec_get_uint(gd->fdt_blob, dev->of_offset,
+					    "nvidia,bpmp-bus-id", U32_MAX);
+	if (priv->bpmp_bus_id == U32_MAX) {
+		debug("%s: could not parse nvidia,bpmp-bus-id\n", __func__);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static const struct dm_i2c_ops tegra186_bpmp_i2c_ops = {
+	.xfer = tegra186_bpmp_i2c_xfer,
+};
+
+static const struct udevice_id tegra186_bpmp_i2c_ids[] = {
+	{ .compatible = "nvidia,tegra186-bpmp-i2c" },
+	{ }
+};
+
+U_BOOT_DRIVER(i2c_gpio) = {
+	.name	= "tegra186_bpmp_i2c",
+	.id	= UCLASS_I2C,
+	.of_match = tegra186_bpmp_i2c_ids,
+	.probe	= tegra186_bpmp_i2c_probe,
+	.priv_auto_alloc_size = sizeof(struct tegra186_bpmp_i2c),
+	.ops	= &tegra186_bpmp_i2c_ops,
+};
diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c
index 2fa07f9..31ba263 100644
--- a/drivers/i2c/tegra_i2c.c
+++ b/drivers/i2c/tegra_i2c.c
@@ -12,13 +12,27 @@
 #include <fdtdec.h>
 #include <i2c.h>
 #include <asm/io.h>
+#ifdef CONFIG_TEGRA186
+#include <clk.h>
+#include <reset.h>
+#else
 #include <asm/arch/clock.h>
 #include <asm/arch/funcmux.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch-tegra/clk_rst.h>
+#endif
+#include <asm/arch/gpio.h>
 #include <asm/arch-tegra/tegra_i2c.h>
 
+/*
+ * FIXME: TODO: This driver contains a number of ifdef CONFIG_TEGRA186 that
+ * should not be present. These are needed because newer Tegra SoCs support
+ * only the standard clock/reset APIs, whereas older Tegra SoCs support only
+ * a custom Tegra-specific API. ASAP the older Tegra SoCs' code should be
+ * fixed to implement the standard APIs, and all drivers converted to solely
+ * use the new standard APIs, with no ifdefs.
+ */
+
 DECLARE_GLOBAL_DATA_PTR;
 
 enum i2c_type {
@@ -30,7 +44,12 @@
 /* Information about i2c controller */
 struct i2c_bus {
 	int			id;
+#ifdef CONFIG_TEGRA186
+	struct reset_ctl	reset_ctl;
+	struct clk		clk;
+#else
 	enum periph_id		periph_id;
+#endif
 	int			speed;
 	int			pinmux_config;
 	struct i2c_control	*control;
@@ -62,12 +81,41 @@
 static void i2c_reset_controller(struct i2c_bus *i2c_bus)
 {
 	/* Reset I2C controller. */
+#ifdef CONFIG_TEGRA186
+	reset_assert(&i2c_bus->reset_ctl);
+	udelay(1);
+	reset_deassert(&i2c_bus->reset_ctl);
+	udelay(1);
+#else
 	reset_periph(i2c_bus->periph_id, 1);
+#endif
 
 	/* re-program config register to packet mode */
 	set_packet_mode(i2c_bus);
 }
 
+#ifdef CONFIG_TEGRA186
+static int i2c_init_clock(struct i2c_bus *i2c_bus, unsigned rate)
+{
+	int ret;
+
+	ret = reset_assert(&i2c_bus->reset_ctl);
+	if (ret)
+		return ret;
+	ret = clk_enable(&i2c_bus->clk);
+	if (ret)
+		return ret;
+	ret = clk_set_rate(&i2c_bus->clk, rate);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+	ret = reset_deassert(&i2c_bus->reset_ctl);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+#endif
+
 static void i2c_init_controller(struct i2c_bus *i2c_bus)
 {
 	if (!i2c_bus->speed)
@@ -78,8 +126,12 @@
 	 * here, in section 23.3.1, but in fact we seem to need a factor of
 	 * 16 to get the right frequency.
 	 */
+#ifdef CONFIG_TEGRA186
+	i2c_init_clock(i2c_bus, i2c_bus->speed * 2 * 8);
+#else
 	clock_start_periph_pll(i2c_bus->periph_id, CLOCK_ID_PERIPH,
 		i2c_bus->speed * 2 * 8);
+#endif
 
 	if (i2c_bus->type == TYPE_114) {
 		/*
@@ -94,12 +146,17 @@
 		 * is running, we hang, and we need it for the new calc.
 		 */
 		int clk_div_stdfst_mode = readl(&i2c_bus->regs->clk_div) >> 16;
+		unsigned rate = CLK_MULT_STD_FAST_MODE *
+				(clk_div_stdfst_mode + 1) * i2c_bus->speed * 2;
 		debug("%s: CLK_DIV_STD_FAST_MODE setting = %d\n", __func__,
 			clk_div_stdfst_mode);
 
+#ifdef CONFIG_TEGRA186
+		i2c_init_clock(i2c_bus, rate);
+#else
 		clock_start_periph_pll(i2c_bus->periph_id, CLOCK_ID_PERIPH,
-			CLK_MULT_STD_FAST_MODE * (clk_div_stdfst_mode + 1) *
-			i2c_bus->speed * 2);
+				       rate);
+#endif
 	}
 
 	/* Reset I2C controller. */
@@ -112,7 +169,9 @@
 		setbits_le32(&dvc->ctrl3, DVC_CTRL_REG3_I2C_HW_SW_PROG_MASK);
 	}
 
+#ifndef CONFIG_TEGRA186
 	funcmux_select(i2c_bus->periph_id, i2c_bus->pinmux_config);
+#endif
 }
 
 static void send_packet_headers(
@@ -333,8 +392,12 @@
 static int tegra_i2c_probe(struct udevice *dev)
 {
 	struct i2c_bus *i2c_bus = dev_get_priv(dev);
+#ifdef CONFIG_TEGRA186
+	int ret;
+#else
 	const void *blob = gd->fdt_blob;
 	int node = dev->of_offset;
+#endif
 	bool is_dvc;
 
 	i2c_bus->id = dev->seq;
@@ -345,6 +408,18 @@
 	 * We don't have a binding for pinmux yet. Leave it out for now. So
 	 * far no one needs anything other than the default.
 	 */
+#ifdef CONFIG_TEGRA186
+	ret = reset_get_by_name(dev, "i2c", &i2c_bus->reset_ctl);
+	if (ret) {
+		error("reset_get_by_name() failed: %d\n", ret);
+		return ret;
+	}
+	ret = clk_get_by_name(dev, "i2c", &i2c_bus->clk);
+	if (ret) {
+		error("clk_get_by_name() failed: %d\n", ret);
+		return ret;
+	}
+#else
 	i2c_bus->pinmux_config = FUNCMUX_DEFAULT;
 	i2c_bus->periph_id = clock_decode_periph_id(blob, node);
 
@@ -359,6 +434,7 @@
 	 */
 	if (i2c_bus->periph_id == -1)
 		return -EINVAL;
+#endif
 
 	is_dvc = dev_get_driver_data(dev) == TYPE_DVC;
 	if (is_dvc) {
@@ -370,7 +446,12 @@
 	i2c_init_controller(i2c_bus);
 	debug("%s: controller bus %d at %p, periph_id %d, speed %d: ",
 	      is_dvc ? "dvc" : "i2c", dev->seq, i2c_bus->regs,
-	      i2c_bus->periph_id, i2c_bus->speed);
+#ifndef CONFIG_TEGRA186
+	      i2c_bus->periph_id,
+#else
+	      -1,
+#endif
+	      i2c_bus->speed);
 
 	return 0;
 }
diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c
index 5c781a5..3d0362d 100644
--- a/drivers/mailbox/tegra-hsp.c
+++ b/drivers/mailbox/tegra-hsp.c
@@ -8,7 +8,19 @@
 #include <asm/io.h>
 #include <dm.h>
 #include <mailbox-uclass.h>
-#include <dt-bindings/mailbox/tegra-hsp.h>
+#include <dt-bindings/mailbox/tegra186-hsp.h>
+
+#define TEGRA_HSP_INT_DIMENSIONING		0x380
+#define TEGRA_HSP_INT_DIMENSIONING_NSI_SHIFT	16
+#define TEGRA_HSP_INT_DIMENSIONING_NSI_MASK	0xf
+#define TEGRA_HSP_INT_DIMENSIONING_NDB_SHIFT	12
+#define TEGRA_HSP_INT_DIMENSIONING_NDB_MASK	0xf
+#define TEGRA_HSP_INT_DIMENSIONING_NAS_SHIFT	8
+#define TEGRA_HSP_INT_DIMENSIONING_NAS_MASK	0xf
+#define TEGRA_HSP_INT_DIMENSIONING_NSS_SHIFT	4
+#define TEGRA_HSP_INT_DIMENSIONING_NSS_MASK	0xf
+#define TEGRA_HSP_INT_DIMENSIONING_NSM_SHIFT	0
+#define TEGRA_HSP_INT_DIMENSIONING_NSM_MASK	0xf
 
 #define TEGRA_HSP_DB_REG_TRIGGER	0x0
 #define TEGRA_HSP_DB_REG_ENABLE		0x4
@@ -51,12 +63,27 @@
 static int tegra_hsp_db_id(ulong chan_id)
 {
 	switch (chan_id) {
-	case TEGRA_HSP_MASTER_BPMP:
+	case (HSP_MBOX_TYPE_DB << 16) | HSP_DB_MASTER_BPMP:
 		return TEGRA_HSP_DB_ID_BPMP;
 	default:
 		debug("Invalid channel ID\n");
 		return -EINVAL;
 	}
+}
+
+static int tegra_hsp_of_xlate(struct mbox_chan *chan,
+			      struct fdtdec_phandle_args *args)
+{
+	debug("%s(chan=%p)\n", __func__, chan);
+
+	if (args->args_count != 2) {
+		debug("Invaild args_count: %d\n", args->args_count);
+		return -EINVAL;
+	}
+
+	chan->id = (args->args[0] << 16) | args->args[1];
+
+	return 0;
 }
 
 static int tegra_hsp_request(struct mbox_chan *chan)
@@ -121,6 +148,7 @@
 static int tegra_hsp_probe(struct udevice *dev)
 {
 	struct tegra_hsp *thsp = dev_get_priv(dev);
+	u32 val;
 	int nr_sm, nr_ss, nr_as;
 
 	debug("%s(dev=%p)\n", __func__, dev);
@@ -129,12 +157,14 @@
 	if (thsp->regs == FDT_ADDR_T_NONE)
 		return -ENODEV;
 
-	nr_sm = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "nvidia,num-SM",
-			       0);
-	nr_ss = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "nvidia,num-SS",
-			       0);
-	nr_as = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "nvidia,num-AS",
-			       0);
+	val = readl(thsp->regs + TEGRA_HSP_INT_DIMENSIONING);
+	nr_sm = (val >> TEGRA_HSP_INT_DIMENSIONING_NSM_SHIFT) &
+		TEGRA_HSP_INT_DIMENSIONING_NSM_MASK;
+	nr_ss = (val >> TEGRA_HSP_INT_DIMENSIONING_NSS_SHIFT) &
+		TEGRA_HSP_INT_DIMENSIONING_NSS_MASK;
+	nr_as = (val >> TEGRA_HSP_INT_DIMENSIONING_NAS_SHIFT) &
+		TEGRA_HSP_INT_DIMENSIONING_NAS_MASK;
+
 	thsp->db_base = (1 + (nr_sm >> 1) + nr_ss + nr_as) << 16;
 
 	return 0;
@@ -146,6 +176,7 @@
 };
 
 struct mbox_ops tegra_hsp_mbox_ops = {
+	.of_xlate = tegra_hsp_of_xlate,
 	.request = tegra_hsp_request,
 	.free = tegra_hsp_free,
 	.send = tegra_hsp_send,
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 2373037..8990489 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -90,6 +90,14 @@
 	  Programmable memory pages that are stored on the some
 	  Freescale i.MX processors.
 
+config NUVOTON_NCT6102D
+	bool "Enable Nuvoton NCT6102D Super I/O driver"
+	help
+	  If you say Y here, you will get support for the Nuvoton
+	  NCT6102D Super I/O driver. This can be used to enable or
+	  disable the legacy UART, the watchdog or other devices
+	  in the Nuvoton Super IO chips on X86 platforms.
+
 config PWRSEQ
 	bool "Enable power-sequencing drivers"
 	depends on DM
@@ -121,14 +129,17 @@
 	help
 	  The I2C address of the PCA9551 LED controller.
 
-config SYSRESET
-	bool "Enable support for system reset drivers"
-	depends on DM
+config TEGRA186_BPMP
+	bool "Enable support for the Tegra186 BPMP driver"
+	depends on TEGRA186
 	help
-	  Enable system reset drivers which can be used to reset the CPU or
-	  board. Each driver can provide a reset method which will be called
-	  to effect a reset. The uclass will try all available drivers when
-	  reset_walk() is called.
+	  The Tegra BPMP (Boot and Power Management Processor) is a separate
+	  auxiliary CPU embedded into Tegra to perform power management work,
+	  and controls related features such as clocks, resets, power domains,
+	  PMIC I2C bus, etc. This driver provides the core low-level
+	  communication path by which feature-specific drivers (such as clock)
+	  can make requests to the BPMP. This driver is similar to an MFD
+	  driver in the Linux kernel.
 
 config WINBOND_W83627
 	bool "Enable Winbond Super I/O driver"
@@ -144,4 +155,9 @@
 	  Hidden option to enable QEMU fw_cfg interface. This will be selected by
 	  either CONFIG_CMD_QFW or CONFIG_GENERATE_ACPI_TABLE.
 
+config I2C_EEPROM
+	bool "Enable driver for generic I2C-attached EEPROMs"
+	depends on MISC
+	help
+	  Enable a generic driver for EEPROMs attached via I2C.
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 066639b..c0e5f03 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -24,23 +24,30 @@
 obj-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o
 obj-$(CONFIG_MXC_OCOTP) += mxc_ocotp.o
 obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o
+obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o
 obj-$(CONFIG_NS87308) += ns87308.o
 obj-$(CONFIG_PDSP188x) += pdsp188x.o
 obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
-obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o
 ifdef CONFIG_DM_I2C
+ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_SANDBOX) += i2c_eeprom_emul.o
 endif
+endif
 obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o
 obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o
 obj-$(CONFIG_STATUS_LED) += status_led.o
 obj-$(CONFIG_SANDBOX) += swap_case.o
+ifdef CONFIG_SPL_OF_PLATDATA
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_SANDBOX) += spltest_sandbox.o
+endif
+endif
 obj-$(CONFIG_SANDBOX) += syscon_sandbox.o
+obj-$(CONFIG_TEGRA186_BPMP) += tegra186_bpmp.o
 obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
 obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
 obj-$(CONFIG_FSL_SEC_MON) += fsl_sec_mon.o
 obj-$(CONFIG_PCA9551_LED) += pca9551_led.o
-obj-$(CONFIG_SYSRESET) += sysreset-uclass.o
 obj-$(CONFIG_FSL_DEVICE_DISABLE) += fsl_devdis.o
 obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o
 obj-$(CONFIG_QFW) += qfw.o
diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c
index e3229ef..aea8d61 100644
--- a/drivers/misc/cros_ec.c
+++ b/drivers/misc/cros_ec.c
@@ -26,7 +26,6 @@
 #include <asm/io.h>
 #include <asm-generic/gpio.h>
 #include <dm/device-internal.h>
-#include <dm/root.h>
 #include <dm/uclass-internal.h>
 
 #ifdef DEBUG_TRACE
@@ -1450,12 +1449,6 @@
 	return ret;
 }
 
-int cros_ec_post_bind(struct udevice *dev)
-{
-	/* Scan for available EC devices (e.g. I2C tunnel) */
-	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
-}
-
 U_BOOT_CMD(
 	crosec,	6,	1,	do_cros_ec,
 	"CROS-EC utility command",
@@ -1482,5 +1475,5 @@
 	.id		= UCLASS_CROS_EC,
 	.name		= "cros_ec",
 	.per_device_auto_alloc_size = sizeof(struct cros_ec_dev),
-	.post_bind	= cros_ec_post_bind,
+	.post_bind	= dm_scan_fdt_dev,
 };
diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c
index 98f19a6..c4fbca0 100644
--- a/drivers/misc/cros_ec_sandbox.c
+++ b/drivers/misc/cros_ec_sandbox.c
@@ -517,6 +517,7 @@
 	struct ec_state *ec = dev->priv;
 	struct cros_ec_dev *cdev = dev->uclass_priv;
 	const void *blob = gd->fdt_blob;
+	struct udevice *keyb_dev;
 	int node;
 	int err;
 
@@ -525,7 +526,15 @@
 	if (err)
 		return err;
 
-	node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC_KEYB);
+	node = -1;
+	for (device_find_first_child(dev, &keyb_dev);
+	     keyb_dev;
+	     device_find_next_child(&keyb_dev)) {
+		if (device_get_uclass_id(keyb_dev) == UCLASS_KEYBOARD) {
+			node = keyb_dev->of_offset;
+			break;
+		}
+	}
 	if (node < 0) {
 		debug("%s: No cros_ec keyboard found\n", __func__);
 	} else if (keyscan_read_fdt_matrix(ec, blob, node)) {
diff --git a/drivers/misc/i2c_eeprom.c b/drivers/misc/i2c_eeprom.c
index 814134a..c9f4174 100644
--- a/drivers/misc/i2c_eeprom.c
+++ b/drivers/misc/i2c_eeprom.c
@@ -13,7 +13,7 @@
 static int i2c_eeprom_read(struct udevice *dev, int offset, uint8_t *buf,
 			   int size)
 {
-	return -ENODEV;
+	return dm_i2c_read(dev, offset, buf, size);
 }
 
 static int i2c_eeprom_write(struct udevice *dev, int offset,
@@ -27,23 +27,46 @@
 	.write	= i2c_eeprom_write,
 };
 
+static int i2c_eeprom_std_ofdata_to_platdata(struct udevice *dev)
+{
+	struct i2c_eeprom *priv = dev_get_priv(dev);
+	u64 data = dev_get_driver_data(dev);
+
+	/* 6 bit -> page size of up to 2^63 (should be sufficient) */
+	priv->pagewidth = data & 0x3F;
+	priv->pagesize = (1 << priv->pagewidth);
+
+	return 0;
+}
+
 int i2c_eeprom_std_probe(struct udevice *dev)
 {
 	return 0;
 }
 
 static const struct udevice_id i2c_eeprom_std_ids[] = {
-	{ .compatible = "i2c-eeprom" },
+	{ .compatible = "i2c-eeprom", .data = 0 },
+	{ .compatible = "atmel,24c01a", .data = 3 },
+	{ .compatible = "atmel,24c02", .data = 3 },
+	{ .compatible = "atmel,24c04", .data = 4 },
+	{ .compatible = "atmel,24c08a", .data = 4 },
+	{ .compatible = "atmel,24c16a", .data = 4 },
+	{ .compatible = "atmel,24c32", .data = 5 },
+	{ .compatible = "atmel,24c64", .data = 5 },
+	{ .compatible = "atmel,24c128", .data = 6 },
+	{ .compatible = "atmel,24c256", .data = 6 },
+	{ .compatible = "atmel,24c512", .data = 6 },
 	{ }
 };
 
 U_BOOT_DRIVER(i2c_eeprom_std) = {
-	.name		= "i2c_eeprom",
-	.id		= UCLASS_I2C_EEPROM,
-	.of_match	= i2c_eeprom_std_ids,
-	.probe		= i2c_eeprom_std_probe,
-	.priv_auto_alloc_size = sizeof(struct i2c_eeprom),
-	.ops		= &i2c_eeprom_std_ops,
+	.name			= "i2c_eeprom",
+	.id			= UCLASS_I2C_EEPROM,
+	.of_match		= i2c_eeprom_std_ids,
+	.probe			= i2c_eeprom_std_probe,
+	.ofdata_to_platdata	= i2c_eeprom_std_ofdata_to_platdata,
+	.priv_auto_alloc_size	= sizeof(struct i2c_eeprom),
+	.ops			= &i2c_eeprom_std_ops,
 };
 
 UCLASS_DRIVER(i2c_eeprom) = {
diff --git a/drivers/misc/misc-uclass.c b/drivers/misc/misc-uclass.c
index 13a6ea5..d9eea3d 100644
--- a/drivers/misc/misc-uclass.c
+++ b/drivers/misc/misc-uclass.c
@@ -45,6 +45,17 @@
 	return ops->ioctl(dev, request, buf);
 }
 
+int misc_call(struct udevice *dev, int msgid, void *tx_msg, int tx_size,
+	      void *rx_msg, int rx_size)
+{
+	const struct misc_ops *ops = device_get_ops(dev);
+
+	if (!ops->call)
+		return -ENOSYS;
+
+	return ops->call(dev, msgid, tx_msg, tx_size, rx_msg, rx_size);
+}
+
 UCLASS_DRIVER(misc) = {
 	.id		= UCLASS_MISC,
 	.name		= "misc",
diff --git a/drivers/misc/nuvoton_nct6102d.c b/drivers/misc/nuvoton_nct6102d.c
new file mode 100644
index 0000000..ced70f1
--- /dev/null
+++ b/drivers/misc/nuvoton_nct6102d.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <nuvoton_nct6102d.h>
+#include <asm/io.h>
+#include <asm/pnp_def.h>
+
+static void superio_outb(int reg, int val)
+{
+	outb(reg, NCT_EFER);
+	outb(val, NCT_EFDR);
+}
+
+static inline int superio_inb(int reg)
+{
+	outb(reg, NCT_EFER);
+	return inb(NCT_EFDR);
+}
+
+static int superio_enter(void)
+{
+	outb(NCT_ENTRY_KEY, NCT_EFER); /* Enter extended function mode */
+	outb(NCT_ENTRY_KEY, NCT_EFER); /* Again according to manual */
+
+	return 0;
+}
+
+static void superio_select(int ld)
+{
+	superio_outb(NCT_LD_SELECT_REG, ld);
+}
+
+static void superio_exit(void)
+{
+	outb(NCT_EXIT_KEY, NCT_EFER); /* Leave extended function mode */
+}
+
+/*
+ * The Nuvoton NCT6102D starts per default after reset with both,
+ * the internal watchdog and the internal legacy UART enabled. This
+ * code provides a function to disable the watchdog.
+ */
+int nct6102d_wdt_disable(void)
+{
+	superio_enter();
+	/* Select logical device for WDT */
+	superio_select(NCT6102D_LD_WDT);
+	superio_outb(NCT6102D_WDT_TIMEOUT, 0x00);
+	superio_exit();
+
+	return 0;
+}
diff --git a/drivers/misc/spltest_sandbox.c b/drivers/misc/spltest_sandbox.c
new file mode 100644
index 0000000..1fef825
--- /dev/null
+++ b/drivers/misc/spltest_sandbox.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dt-structs.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int sandbox_spl_probe(struct udevice *dev)
+{
+	struct dtd_sandbox_spl_test *plat = dev_get_platdata(dev);
+	int i;
+
+	printf("of-platdata probe:\n");
+	printf("bool %d\n", plat->boolval);
+
+	printf("byte %02x\n", plat->byteval);
+	printf("bytearray");
+	for (i = 0; i < sizeof(plat->bytearray); i++)
+		printf(" %02x", plat->bytearray[i]);
+	printf("\n");
+
+	printf("int %d\n", plat->intval);
+	printf("intarray");
+	for (i = 0; i < ARRAY_SIZE(plat->intarray); i++)
+		printf(" %d", plat->intarray[i]);
+	printf("\n");
+
+	printf("longbytearray");
+	for (i = 0; i < sizeof(plat->longbytearray); i++)
+		printf(" %02x", plat->longbytearray[i]);
+	printf("\n");
+
+	printf("string %s\n", plat->stringval);
+	printf("stringarray");
+	for (i = 0; i < ARRAY_SIZE(plat->stringarray); i++)
+		printf(" \"%s\"", plat->stringarray[i]);
+	printf("\n");
+
+	return 0;
+}
+
+U_BOOT_DRIVER(sandbox_spl_test) = {
+	.name	= "sandbox_spl_test",
+	.id	= UCLASS_MISC,
+	.flags	= DM_FLAG_PRE_RELOC,
+	.probe	= sandbox_spl_probe,
+};
diff --git a/drivers/misc/tegra186_bpmp.c b/drivers/misc/tegra186_bpmp.c
new file mode 100644
index 0000000..f4ddbea3
--- /dev/null
+++ b/drivers/misc/tegra186_bpmp.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+#include <mailbox.h>
+#include <misc.h>
+#include <asm/arch-tegra/bpmp_abi.h>
+#include <asm/arch-tegra/ivc.h>
+
+#define BPMP_IVC_FRAME_COUNT 1
+#define BPMP_IVC_FRAME_SIZE 128
+
+#define BPMP_FLAG_DO_ACK	BIT(0)
+#define BPMP_FLAG_RING_DOORBELL	BIT(1)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct tegra186_bpmp {
+	struct mbox_chan mbox;
+	struct tegra_ivc ivc;
+};
+
+static int tegra186_bpmp_call(struct udevice *dev, int mrq, void *tx_msg,
+			      int tx_size, void *rx_msg, int rx_size)
+{
+	struct tegra186_bpmp *priv = dev_get_priv(dev);
+	int ret, err;
+	void *ivc_frame;
+	struct mrq_request *req;
+	struct mrq_response *resp;
+	ulong start_time;
+
+	debug("%s(dev=%p, mrq=%u, tx_msg=%p, tx_size=%d, rx_msg=%p, rx_size=%d) (priv=%p)\n",
+	      __func__, dev, mrq, tx_msg, tx_size, rx_msg, rx_size, priv);
+
+	if ((tx_size > BPMP_IVC_FRAME_SIZE) || (rx_size > BPMP_IVC_FRAME_SIZE))
+		return -EINVAL;
+
+	ret = tegra_ivc_write_get_next_frame(&priv->ivc, &ivc_frame);
+	if (ret) {
+		error("tegra_ivc_write_get_next_frame() failed: %d\n", ret);
+		return ret;
+	}
+
+	req = ivc_frame;
+	req->mrq = mrq;
+	req->flags = BPMP_FLAG_DO_ACK | BPMP_FLAG_RING_DOORBELL;
+	memcpy(req + 1, tx_msg, tx_size);
+
+	ret = tegra_ivc_write_advance(&priv->ivc);
+	if (ret) {
+		error("tegra_ivc_write_advance() failed: %d\n", ret);
+		return ret;
+	}
+
+	start_time = timer_get_us();
+	for (;;) {
+		ret = tegra_ivc_channel_notified(&priv->ivc);
+		if (ret) {
+			error("tegra_ivc_channel_notified() failed: %d\n", ret);
+			return ret;
+		}
+
+		ret = tegra_ivc_read_get_next_frame(&priv->ivc, &ivc_frame);
+		if (!ret)
+			break;
+
+		/* Timeout 20ms; roughly 10x current max observed duration */
+		if ((timer_get_us() - start_time) > 20 * 1000) {
+			error("tegra_ivc_read_get_next_frame() timed out (%d)\n",
+			      ret);
+			return -ETIMEDOUT;
+		}
+	}
+
+	resp = ivc_frame;
+	err = resp->err;
+	if (!err && rx_msg && rx_size)
+		memcpy(rx_msg, resp + 1, rx_size);
+
+	ret = tegra_ivc_read_advance(&priv->ivc);
+	if (ret) {
+		error("tegra_ivc_write_advance() failed: %d\n", ret);
+		return ret;
+	}
+
+	if (err) {
+		error("BPMP responded with error %d\n", err);
+		/* err isn't a U-Boot error code, so don't that */
+		return -EIO;
+	}
+
+	return rx_size;
+}
+
+/**
+ * The BPMP exposes multiple different services. We create a sub-device for
+ * each separate type of service, since each device must be of the appropriate
+ * UCLASS.
+ */
+static int tegra186_bpmp_bind(struct udevice *dev)
+{
+	int ret;
+	struct udevice *child;
+
+	debug("%s(dev=%p)\n", __func__, dev);
+
+	ret = device_bind_driver_to_node(dev, "tegra186_clk", "tegra186_clk",
+					 dev->of_offset, &child);
+	if (ret)
+		return ret;
+
+	ret = device_bind_driver_to_node(dev, "tegra186_reset",
+					 "tegra186_reset", dev->of_offset,
+					 &child);
+	if (ret)
+		return ret;
+
+	ret = device_bind_driver_to_node(dev, "tegra186_power_domain",
+					 "tegra186_power_domain",
+					 dev->of_offset, &child);
+	if (ret)
+		return ret;
+
+	ret = dm_scan_fdt_dev(dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static ulong tegra186_bpmp_get_shmem(struct udevice *dev, int index)
+{
+	int ret;
+	struct fdtdec_phandle_args args;
+	fdt_addr_t reg;
+
+	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
+					      "shmem", NULL, 0, index, &args);
+	if (ret < 0) {
+		error("fdtdec_parse_phandle_with_args() failed: %d\n", ret);
+		return ret;
+	}
+
+	reg = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, args.node,
+						 "reg", 0, NULL, true);
+	if (reg == FDT_ADDR_T_NONE) {
+		error("fdtdec_get_addr_size_auto_noparent() failed\n");
+		return -ENODEV;
+	}
+
+	return reg;
+}
+
+static void tegra186_bpmp_ivc_notify(struct tegra_ivc *ivc)
+{
+	struct tegra186_bpmp *priv =
+		container_of(ivc, struct tegra186_bpmp, ivc);
+	int ret;
+
+	ret = mbox_send(&priv->mbox, NULL);
+	if (ret)
+		error("mbox_send() failed: %d\n", ret);
+}
+
+static int tegra186_bpmp_probe(struct udevice *dev)
+{
+	struct tegra186_bpmp *priv = dev_get_priv(dev);
+	int ret;
+	ulong tx_base, rx_base, start_time;
+
+	debug("%s(dev=%p) (priv=%p)\n", __func__, dev, priv);
+
+	ret = mbox_get_by_index(dev, 0, &priv->mbox);
+	if (ret) {
+		error("mbox_get_by_index() failed: %d\n", ret);
+		return ret;
+	}
+
+	tx_base = tegra186_bpmp_get_shmem(dev, 0);
+	if (IS_ERR_VALUE(tx_base)) {
+		error("tegra186_bpmp_get_shmem failed for tx_base\n");
+		return tx_base;
+	}
+	rx_base = tegra186_bpmp_get_shmem(dev, 1);
+	if (IS_ERR_VALUE(rx_base)) {
+		error("tegra186_bpmp_get_shmem failed for rx_base\n");
+		return rx_base;
+	}
+	debug("shmem: rx=%lx, tx=%lx\n", rx_base, tx_base);
+
+	ret = tegra_ivc_init(&priv->ivc, rx_base, tx_base, BPMP_IVC_FRAME_COUNT,
+			     BPMP_IVC_FRAME_SIZE, tegra186_bpmp_ivc_notify);
+	if (ret) {
+		error("tegra_ivc_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	tegra_ivc_channel_reset(&priv->ivc);
+	start_time = timer_get_us();
+	for (;;) {
+		ret = tegra_ivc_channel_notified(&priv->ivc);
+		if (!ret)
+			break;
+
+		/* Timeout 100ms */
+		if ((timer_get_us() - start_time) > 100 * 1000) {
+			error("Initial IVC reset timed out (%d)\n", ret);
+			ret = -ETIMEDOUT;
+			goto err_free_mbox;
+		}
+	}
+
+	return 0;
+
+err_free_mbox:
+	mbox_free(&priv->mbox);
+
+	return ret;
+}
+
+static int tegra186_bpmp_remove(struct udevice *dev)
+{
+	struct tegra186_bpmp *priv = dev_get_priv(dev);
+
+	debug("%s(dev=%p) (priv=%p)\n", __func__, dev, priv);
+
+	mbox_free(&priv->mbox);
+
+	return 0;
+}
+
+static struct misc_ops tegra186_bpmp_ops = {
+	.call = tegra186_bpmp_call,
+};
+
+static const struct udevice_id tegra186_bpmp_ids[] = {
+	{ .compatible = "nvidia,tegra186-bpmp" },
+	{ }
+};
+
+U_BOOT_DRIVER(tegra186_bpmp) = {
+	.name		= "tegra186_bpmp",
+	.id		= UCLASS_MISC,
+	.of_match	= tegra186_bpmp_ids,
+	.bind		= tegra186_bpmp_bind,
+	.probe		= tegra186_bpmp_probe,
+	.remove		= tegra186_bpmp_remove,
+	.ops		= &tegra186_bpmp_ops,
+	.priv_auto_alloc_size = sizeof(struct tegra186_bpmp),
+};
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index c80efc3..3616dee 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -10,21 +10,40 @@
 	bool "Enable MMC controllers using Driver Model"
 	depends on DM
 	help
-	  This enables the MultiMediaCard (MMC) uclass which suports MMC and
+	  This enables the MultiMediaCard (MMC) uclass which supports MMC and
 	  Secure Digital I/O (SDIO) cards. Both removable (SD, micro-SD, etc.)
 	  and non-removable (e.g. eMMC chip) devices are supported. These
 	  appear as block devices in U-Boot and can support filesystems such
 	  as EXT4 and FAT.
 
+config DM_MMC_OPS
+	bool "Support MMC controller operations using Driver Model"
+	depends on DM_MMC
+	help
+	  Driver model provides a means of supporting device operations. This
+	  option moves MMC operations under the control of driver model. The
+	  option will be removed as soon as all DM_MMC drivers use it, as it
+	  will the only supported behaviour.
+
 config MSM_SDHCI
 	bool "Qualcomm SDHCI controller"
-	depends on DM_MMC
+	depends on DM_MMC && BLK && DM_MMC_OPS
 	help
 	  Enables support for SDHCI 2.0 controller present on some Qualcomm
           Snapdragon devices. This device is compatible with eMMC v4.5 and
           SD 3.0 specifications. Both SD and eMMC devices are supported.
 	  Card-detect gpios are not supported.
 
+config ATMEL_SDHCI
+	bool "Atmel SDHCI controller support"
+	depends on DM_MMC && BLK && DM_MMC_OPS && ARCH_AT91
+	help
+	  This enables support for the Atmel SDHCI controller, which supports
+	  the embedded MultiMedia Card (e.MMC) Specification V4.51, the SD
+	  Memory Card Specification V3.0, and the SDIO V3.0 specification.
+	  It is compliant with the SD Host Controller Standard V3.0
+	  specification.
+
 config ROCKCHIP_DWMMC
 	bool "Rockchip SD/MMC controller support"
 	depends on DM_MMC && OF_CONTROL
@@ -52,6 +71,12 @@
 	help
 	  Support for Arasan SDHCI host controller on Zynq/ZynqMP ARM SoCs platform
 
+config ROCKCHIP_SDHCI
+	bool "Arasan SDHCI controller for Rockchip support"
+	depends on DM_MMC && BLK && DM_MMC_OPS
+	help
+	  Support for Arasan SDHCI host controller on Rockchip ARM SoCs platform
+
 config MMC_UNIPHIER
 	bool "UniPhier SD/MMC Host Controller support"
 	depends on ARCH_UNIPHIER
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 3da4817..18351fb 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -25,6 +25,9 @@
 obj-$(CONFIG_FTSDC010) += ftsdc010_mci.o
 obj-$(CONFIG_FTSDC021) += ftsdc021_sdhci.o
 obj-$(CONFIG_GENERIC_MMC) += mmc.o
+ifdef CONFIG_SUPPORT_EMMC_BOOT
+obj-$(CONFIG_GENERIC_MMC) += mmc_boot.o
+endif
 obj-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o
 obj-$(CONFIG_KONA_SDHCI) += kona_sdhci.o
 obj-$(CONFIG_MMC_SPI) += mmc_spi.o
@@ -53,6 +56,7 @@
 obj-$(CONFIG_TEGRA_MMC) += tegra_mmc.o
 obj-$(CONFIG_MMC_UNIPHIER) += uniphier-sd.o
 obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o
+obj-$(CONFIG_ROCKCHIP_SDHCI) += rockchip_sdhci.o
 
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o
diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c
index 8f2694f..e64ac3c 100644
--- a/drivers/mmc/arm_pl180_mmci.c
+++ b/drivers/mmc/arm_pl180_mmci.c
@@ -37,7 +37,7 @@
 	writel(statusmask, &host->base->status_clear);
 	if (hoststatus & SDI_STA_CTIMEOUT) {
 		debug("CMD%d time out\n", cmd->cmdidx);
-		return TIMEOUT;
+		return -ETIMEDOUT;
 	} else if ((hoststatus & SDI_STA_CCRCFAIL) &&
 		   (cmd->resp_type & MMC_RSP_CRC)) {
 		printf("CMD%d CRC error\n", cmd->cmdidx);
diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c
index 24b68b6..dd6bd33 100644
--- a/drivers/mmc/atmel_sdhci.c
+++ b/drivers/mmc/atmel_sdhci.c
@@ -6,12 +6,15 @@
  */
 
 #include <common.h>
+#include <clk.h>
+#include <dm.h>
 #include <malloc.h>
 #include <sdhci.h>
 #include <asm/arch/clk.h>
 
 #define ATMEL_SDHC_MIN_FREQ	400000
 
+#ifndef CONFIG_DM_MMC
 int atmel_sdhci_init(void *regbase, u32 id)
 {
 	struct sdhci_host *host;
@@ -38,3 +41,123 @@
 
 	return 0;
 }
+
+#else
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct atmel_sdhci_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
+static int atmel_sdhci_get_clk(struct udevice *dev, int index, struct clk *clk)
+{
+	struct udevice *dev_clk;
+	int periph, ret;
+
+	ret = clk_get_by_index(dev, index, clk);
+	if (ret)
+		return ret;
+
+	periph = fdtdec_get_uint(gd->fdt_blob, clk->dev->of_offset, "reg", -1);
+	if (periph < 0)
+		return -EINVAL;
+
+	dev_clk = dev_get_parent(clk->dev);
+	ret = clk_request(dev_clk, clk);
+	if (ret)
+		return ret;
+
+	clk->id = periph;
+
+	return 0;
+}
+
+static int atmel_sdhci_probe(struct udevice *dev)
+{
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct atmel_sdhci_plat *plat = dev_get_platdata(dev);
+	struct sdhci_host *host = dev_get_priv(dev);
+	u32 max_clk;
+	u32 caps, caps_1;
+	u32 clk_base, clk_mul;
+	ulong gck_rate;
+	struct clk clk;
+	int ret;
+
+	ret = atmel_sdhci_get_clk(dev, 0, &clk);
+	if (ret)
+		return ret;
+
+	ret = clk_enable(&clk);
+	if (ret)
+		return ret;
+
+	host->name = dev->name;
+	host->ioaddr = (void *)dev_get_addr(dev);
+
+	host->quirks = 0;
+	host->bus_width	= fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+					 "bus-width", 4);
+
+	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+	clk_base = (caps & SDHCI_CLOCK_V3_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
+	caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+	clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >> SDHCI_CLOCK_MUL_SHIFT;
+	gck_rate = clk_base * 1000000 * (clk_mul + 1);
+
+	ret = atmel_sdhci_get_clk(dev, 1, &clk);
+	if (ret)
+		return ret;
+
+	ret = clk_set_rate(&clk, gck_rate);
+	if (ret)
+		return ret;
+
+	max_clk = clk_get_rate(&clk);
+	if (!max_clk)
+		return -EINVAL;
+
+	ret = sdhci_setup_cfg(&plat->cfg, host, max_clk, ATMEL_SDHC_MIN_FREQ);
+	if (ret)
+		return ret;
+
+	host->mmc = &plat->mmc;
+	host->mmc->dev = dev;
+	host->mmc->priv = host;
+	upriv->mmc = host->mmc;
+
+	clk_free(&clk);
+
+	return sdhci_probe(dev);
+}
+
+static int atmel_sdhci_bind(struct udevice *dev)
+{
+	struct atmel_sdhci_plat *plat = dev_get_platdata(dev);
+	int ret;
+
+	ret = sdhci_bind(dev, &plat->mmc, &plat->cfg);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct udevice_id atmel_sdhci_ids[] = {
+	{ .compatible = "atmel,sama5d2-sdhci" },
+	{ }
+};
+
+U_BOOT_DRIVER(atmel_sdhci_drv) = {
+	.name		= "atmel_sdhci",
+	.id		= UCLASS_MMC,
+	.of_match	= atmel_sdhci_ids,
+	.ops		= &sdhci_ops,
+	.bind		= atmel_sdhci_bind,
+	.probe		= atmel_sdhci_probe,
+	.priv_auto_alloc_size = sizeof(struct sdhci_host),
+	.platdata_auto_alloc_size = sizeof(struct atmel_sdhci_plat),
+};
+#endif
diff --git a/drivers/mmc/bfin_sdh.c b/drivers/mmc/bfin_sdh.c
index 9bdfbbc..0e493da 100644
--- a/drivers/mmc/bfin_sdh.c
+++ b/drivers/mmc/bfin_sdh.c
@@ -109,9 +109,9 @@
 	}
 
 	if (status & CMD_TIME_OUT)
-		ret = TIMEOUT;
+		ret = -ETIMEDOUT;
 	else if (status & CMD_CRC_FAIL && flags & MMC_RSP_CRC)
-		ret = COMM_ERR;
+		ret = -ECOMM;
 	else
 		ret = 0;
 
@@ -136,7 +136,7 @@
 
 	/* Don't support write yet. */
 	if (data->flags & MMC_DATA_WRITE)
-		return UNUSABLE_ERR;
+		return -EOPNOTSUPP;
 #ifndef RSI_BLKSZ
 	data_ctl |= ((ffs(data->blocksize) - 1) << 4);
 #else
@@ -194,10 +194,10 @@
 
 		if (status & DAT_TIME_OUT) {
 			bfin_write_SDH_STATUS_CLR(DAT_TIMEOUT_STAT);
-			ret |= TIMEOUT;
+			ret = -ETIMEDOUT;
 		} else if (status & (DAT_CRC_FAIL | RX_OVERRUN)) {
 			bfin_write_SDH_STATUS_CLR(DAT_CRC_FAIL_STAT | RX_OVERRUN_STAT);
-			ret |= COMM_ERR;
+			ret = -ECOMM;
 		} else
 			bfin_write_SDH_STATUS_CLR(DAT_BLK_END_STAT | DAT_END_STAT);
 
diff --git a/drivers/mmc/davinci_mmc.c b/drivers/mmc/davinci_mmc.c
index aae00e9..b495c75 100644
--- a/drivers/mmc/davinci_mmc.c
+++ b/drivers/mmc/davinci_mmc.c
@@ -9,6 +9,7 @@
 #include <config.h>
 #include <common.h>
 #include <command.h>
+#include <errno.h>
 #include <mmc.h>
 #include <part.h>
 #include <malloc.h>
@@ -66,7 +67,7 @@
 		udelay(100);
 
 	if (wdog == 0)
-		return COMM_ERR;
+		return -ECOMM;
 
 	return 0;
 }
@@ -80,7 +81,7 @@
 		udelay(10);
 
 	if (wdog == 0)
-		return COMM_ERR;
+		return -ECOMM;
 
 	return 0;
 }
@@ -99,7 +100,7 @@
 			return 0;
 		} else if (mmcstatus & st_error) {
 			if (mmcstatus & MMCST0_TOUTRS)
-				return TIMEOUT;
+				return -ETIMEDOUT;
 			printf("[ ST0 ERROR %x]\n", mmcstatus);
 			/*
 			 * Ignore CRC errors as some MMC cards fail to
@@ -107,7 +108,7 @@
 			 */
 			if (mmcstatus & MMCST0_CRCRS)
 				return 0;
-			return COMM_ERR;
+			return -ECOMM;
 		}
 		udelay(10);
 
@@ -116,7 +117,7 @@
 
 	printf("Status %x Timeout ST0:%x ST1:%x\n", st_ready, mmcstatus,
 			get_val(&regs->mmcst1));
-	return COMM_ERR;
+	return -ECOMM;
 }
 
 /*
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index af6e04a..afc674d 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -13,7 +13,6 @@
 #include <memalign.h>
 #include <mmc.h>
 #include <dwmmc.h>
-#include <asm-generic/errno.h>
 
 #define PAGE_SIZE 4096
 
@@ -120,12 +119,14 @@
 		}
 
 		if (host->fifo_mode && size) {
+			len = 0;
 			if (data->flags == MMC_DATA_READ) {
 				if ((dwmci_readl(host, DWMCI_RINTSTS) &
 				     DWMCI_INTMSK_RXDR)) {
 					len = dwmci_readl(host, DWMCI_STATUS);
 					len = (len >> DWMCI_FIFO_SHIFT) &
 						    DWMCI_FIFO_MASK;
+					len = min(size, len);
 					for (i = 0; i < len; i++)
 						*buf++ =
 						dwmci_readl(host, DWMCI_DATA);
@@ -139,6 +140,7 @@
 					len = fifo_depth - ((len >>
 						   DWMCI_FIFO_SHIFT) &
 						   DWMCI_FIFO_MASK);
+					len = min(size, len);
 					for (i = 0; i < len; i++)
 						dwmci_writel(host, DWMCI_DATA,
 							     *buf++);
@@ -159,7 +161,7 @@
 		if (get_timer(start) > timeout) {
 			debug("%s: Timeout waiting for data!\n",
 			      __func__);
-			ret = TIMEOUT;
+			ret = -ETIMEDOUT;
 			break;
 		}
 	}
@@ -181,14 +183,21 @@
 	return mode;
 }
 
+#ifdef CONFIG_DM_MMC_OPS
+static int dwmci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+		   struct mmc_data *data)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
 static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 		struct mmc_data *data)
 {
+#endif
 	struct dwmci_host *host = mmc->priv;
 	ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac,
 				 data ? DIV_ROUND_UP(data->blocks, 8) : 0);
 	int ret = 0, flags = 0, i;
-	unsigned int timeout = 100000;
+	unsigned int timeout = 500;
 	u32 retry = 100000;
 	u32 mask, ctrl;
 	ulong start = get_timer(0);
@@ -197,7 +206,7 @@
 	while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) {
 		if (get_timer(start) > timeout) {
 			debug("%s: Timeout on data busy\n", __func__);
-			return TIMEOUT;
+			return -ETIMEDOUT;
 		}
 	}
 
@@ -263,7 +272,7 @@
 
 	if (i == retry) {
 		debug("%s: Timeout.\n", __func__);
-		return TIMEOUT;
+		return -ETIMEDOUT;
 	}
 
 	if (mask & DWMCI_INTMSK_RTO) {
@@ -276,7 +285,7 @@
 		 * CMD8, please keep that in mind.
 		 */
 		debug("%s: Response Timeout.\n", __func__);
-		return TIMEOUT;
+		return -ETIMEDOUT;
 	} else if (mask & DWMCI_INTMSK_RE) {
 		debug("%s: Response Error.\n", __func__);
 		return -EIO;
@@ -373,8 +382,14 @@
 	return 0;
 }
 
+#ifdef CONFIG_DM_MMC_OPS
+static int dwmci_set_ios(struct udevice *dev)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
 static void dwmci_set_ios(struct mmc *mmc)
 {
+#endif
 	struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
 	u32 ctype, regs;
 
@@ -405,6 +420,9 @@
 
 	if (host->clksel)
 		host->clksel(host);
+#ifdef CONFIG_DM_MMC_OPS
+	return 0;
+#endif
 }
 
 static int dwmci_init(struct mmc *mmc)
@@ -448,17 +466,34 @@
 	return 0;
 }
 
+#ifdef CONFIG_DM_MMC_OPS
+int dwmci_probe(struct udevice *dev)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+	return dwmci_init(mmc);
+}
+
+const struct dm_mmc_ops dm_dwmci_ops = {
+	.send_cmd	= dwmci_send_cmd,
+	.set_ios	= dwmci_set_ios,
+};
+
+#else
 static const struct mmc_ops dwmci_ops = {
 	.send_cmd	= dwmci_send_cmd,
 	.set_ios	= dwmci_set_ios,
 	.init		= dwmci_init,
 };
+#endif
 
 void dwmci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth,
 		     uint caps, u32 max_clk, u32 min_clk)
 {
 	cfg->name = name;
+#ifndef CONFIG_DM_MMC_OPS
 	cfg->ops = &dwmci_ops;
+#endif
 	cfg->f_min = min_clk;
 	cfg->f_max = max_clk;
 
diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c
index 863bbb3..57271f1 100644
--- a/drivers/mmc/exynos_dw_mmc.c
+++ b/drivers/mmc/exynos_dw_mmc.c
@@ -10,12 +10,12 @@
 #include <fdtdec.h>
 #include <libfdt.h>
 #include <malloc.h>
+#include <errno.h>
 #include <asm/arch/dwmmc.h>
 #include <asm/arch/clk.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/power.h>
 #include <asm/gpio.h>
-#include <asm-generic/errno.h>
 
 #define	DWMMC_MAX_CH_NUM		4
 #define	DWMMC_MAX_FREQ			52000000
@@ -23,8 +23,21 @@
 #define	DWMMC_MMC0_SDR_TIMING_VAL	0x03030001
 #define	DWMMC_MMC2_SDR_TIMING_VAL	0x03020001
 
+#ifdef CONFIG_DM_MMC
+#include <dm.h>
+DECLARE_GLOBAL_DATA_PTR;
+
+struct exynos_mmc_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+#endif
+
 /* Exynos implmentation specific drver private data */
 struct dwmci_exynos_priv_data {
+#ifdef CONFIG_DM_MMC
+	struct dwmci_host host;
+#endif
 	u32 sdr_timing;
 };
 
@@ -80,11 +93,10 @@
 		exynos_dwmci_clksel(host);
 }
 
-static int exynos_dwmci_core_init(struct dwmci_host *host, int index)
+static int exynos_dwmci_core_init(struct dwmci_host *host)
 {
 	unsigned int div;
 	unsigned long freq, sclk;
-	struct dwmci_exynos_priv_data *priv = host->priv;
 
 	if (host->bus_hz)
 		freq = host->bus_hz;
@@ -92,10 +104,10 @@
 		freq = DWMMC_MAX_FREQ;
 
 	/* request mmc clock vlaue of 52MHz.  */
-	sclk = get_mmc_clk(index);
+	sclk = get_mmc_clk(host->dev_index);
 	div = DIV_ROUND_UP(sclk, freq);
 	/* set the clock divisor for mmc */
-	set_mmc_clk(index, div);
+	set_mmc_clk(host->dev_index, div);
 
 	host->name = "EXYNOS DWMMC";
 #ifdef CONFIG_EXYNOS5420
@@ -103,78 +115,35 @@
 #endif
 	host->board_init = exynos_dwmci_board_init;
 
-	if (!priv->sdr_timing) {
-		if (index == 0)
-			priv->sdr_timing = DWMMC_MMC0_SDR_TIMING_VAL;
-		else if (index == 2)
-			priv->sdr_timing = DWMMC_MMC2_SDR_TIMING_VAL;
-	}
-
 	host->caps = MMC_MODE_DDR_52MHz;
 	host->clksel = exynos_dwmci_clksel;
-	host->dev_index = index;
 	host->get_mmc_clk = exynos_dwmci_get_clk;
+
+#ifndef CONFIG_DM_MMC
 	/* Add the mmc channel to be registered with mmc core */
 	if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) {
-		printf("DWMMC%d registration failed\n", index);
+		printf("DWMMC%d registration failed\n", host->dev_index);
 		return -1;
 	}
-	return 0;
-}
-
-/*
- * This function adds the mmc channel to be registered with mmc core.
- * index -	mmc channel number.
- * regbase -	register base address of mmc channel specified in 'index'.
- * bus_width -	operating bus width of mmc channel specified in 'index'.
- * clksel -	value to be written into CLKSEL register in case of FDT.
- *		NULL in case od non-FDT.
- */
-int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel)
-{
-	struct dwmci_host *host = NULL;
-	struct dwmci_exynos_priv_data *priv;
-
-	host = malloc(sizeof(struct dwmci_host));
-	if (!host) {
-		error("dwmci_host malloc fail!\n");
-		return -ENOMEM;
-	}
-
-	priv = malloc(sizeof(struct dwmci_exynos_priv_data));
-	if (!priv) {
-		error("dwmci_exynos_priv_data malloc fail!\n");
-		return -ENOMEM;
-	}
-
-	host->ioaddr = (void *)regbase;
-	host->buswidth = bus_width;
-
-	if (clksel)
-		priv->sdr_timing = clksel;
-
-	host->priv = priv;
+#endif
 
-	return exynos_dwmci_core_init(host, index);
+	return 0;
 }
 
-#if CONFIG_IS_ENABLED(OF_CONTROL)
 static struct dwmci_host dwmci_host[DWMMC_MAX_CH_NUM];
 
 static int do_dwmci_init(struct dwmci_host *host)
 {
-	int index, flag, err;
-
-	index = host->dev_index;
+	int flag, err;
 
 	flag = host->buswidth == 8 ? PINMUX_FLAG_8BIT_MODE : PINMUX_FLAG_NONE;
 	err = exynos_pinmux_config(host->dev_id, flag);
 	if (err) {
-		printf("DWMMC%d not configure\n", index);
+		printf("DWMMC%d not configure\n", host->dev_index);
 		return err;
 	}
 
-	return exynos_dwmci_core_init(host, index);
+	return exynos_dwmci_core_init(host);
 }
 
 static int exynos_dwmci_get_config(const void *blob, int node,
@@ -197,13 +166,14 @@
 	if (host->dev_index == host->dev_id)
 		host->dev_index = host->dev_id - PERIPH_ID_SDMMC0;
 
-	/* Get the bus width from the device node */
-	host->buswidth = fdtdec_get_int(blob, node, "samsung,bus-width", 0);
-	if (host->buswidth <= 0) {
-		printf("DWMMC%d: Can't get bus-width\n", host->dev_index);
+	if (host->dev_index > 4) {
+		printf("DWMMC%d: Can't get the dev index\n", host->dev_index);
 		return -EINVAL;
 	}
 
+	/* Get the bus width from the device node (Default is 4bit buswidth) */
+	host->buswidth = fdtdec_get_int(blob, node, "samsung,bus-width", 4);
+
 	/* Set the base address from the device node */
 	base = fdtdec_get_addr(blob, node, "reg");
 	if (!base) {
@@ -265,15 +235,13 @@
 
 int exynos_dwmmc_init(const void *blob)
 {
-	int compat_id;
 	int node_list[DWMMC_MAX_CH_NUM];
 	int boot_dev_node;
 	int err = 0, count;
 
-	compat_id = COMPAT_SAMSUNG_EXYNOS_DWMMC;
-
 	count = fdtdec_find_aliases_for_id(blob, "mmc",
-				compat_id, node_list, DWMMC_MAX_CH_NUM);
+			COMPAT_SAMSUNG_EXYNOS_DWMMC, node_list,
+			DWMMC_MAX_CH_NUM);
 
 	/* For DWMMC always set boot device as mmc 0 */
 	if (count >= 3 && get_boot_mode() == BOOT_MODE_SD) {
@@ -286,4 +254,58 @@
 
 	return err;
 }
+
+#ifdef CONFIG_DM_MMC
+static int exynos_dwmmc_probe(struct udevice *dev)
+{
+	struct exynos_mmc_plat *plat = dev_get_platdata(dev);
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct dwmci_exynos_priv_data *priv = dev_get_priv(dev);
+	struct dwmci_host *host = &priv->host;
+	int err;
+
+	err = exynos_dwmci_get_config(gd->fdt_blob, dev->of_offset, host);
+	if (err)
+		return err;
+	err = do_dwmci_init(host);
+	if (err)
+		return err;
+
+	dwmci_setup_cfg(&plat->cfg, host->name, host->buswidth, host->caps,
+			DWMMC_MAX_FREQ, DWMMC_MIN_FREQ);
+	host->mmc = &plat->mmc;
+	host->mmc->priv = &priv->host;
+	host->priv = dev;
+	upriv->mmc = host->mmc;
+
+	return dwmci_probe(dev);
+}
+
+static int exynos_dwmmc_bind(struct udevice *dev)
+{
+	struct exynos_mmc_plat *plat = dev_get_platdata(dev);
+	int ret;
+
+	ret = dwmci_bind(dev, &plat->mmc, &plat->cfg);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct udevice_id exynos_dwmmc_ids[] = {
+	{ .compatible = "samsung,exynos4412-dw-mshc" },
+	{ }
+};
+
+U_BOOT_DRIVER(exynos_dwmmc_drv) = {
+	.name		= "exynos_dwmmc",
+	.id		= UCLASS_MMC,
+	.of_match	= exynos_dwmmc_ids,
+	.bind		= exynos_dwmmc_bind,
+	.ops		= &dm_dwmci_ops,
+	.probe		= exynos_dwmmc_probe,
+	.priv_auto_alloc_size	= sizeof(struct dwmci_exynos_priv_data),
+	.platdata_auto_alloc_size = sizeof(struct exynos_mmc_plat),
+};
 #endif
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index a865c7b..103b32e 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -12,11 +12,11 @@
 #include <config.h>
 #include <common.h>
 #include <command.h>
+#include <errno.h>
 #include <hwconfig.h>
 #include <mmc.h>
 #include <part.h>
 #include <malloc.h>
-#include <mmc.h>
 #include <fsl_esdhc.h>
 #include <fdt_support.h>
 #include <asm/io.h>
@@ -253,7 +253,7 @@
 			if ((esdhc_read32(&regs->prsstat) &
 			    PRSSTAT_WPSPL) == 0) {
 				printf("\nThe SD card is locked. Can not write to a locked card.\n\n");
-				return TIMEOUT;
+				return -ETIMEDOUT;
 			}
 		}
 
@@ -411,12 +411,12 @@
 	irqstat = esdhc_read32(&regs->irqstat);
 
 	if (irqstat & CMD_ERR) {
-		err = COMM_ERR;
+		err = -ECOMM;
 		goto out;
 	}
 
 	if (irqstat & IRQSTAT_CTOE) {
-		err = TIMEOUT;
+		err = -ETIMEDOUT;
 		goto out;
 	}
 
@@ -442,7 +442,7 @@
 
 		if (timeout <= 0) {
 			printf("Timeout waiting for DAT0 to go high!\n");
-			err = TIMEOUT;
+			err = -ETIMEDOUT;
 			goto out;
 		}
 	}
@@ -471,12 +471,12 @@
 			irqstat = esdhc_read32(&regs->irqstat);
 
 			if (irqstat & IRQSTAT_DTOE) {
-				err = TIMEOUT;
+				err = -ETIMEDOUT;
 				goto out;
 			}
 
 			if (irqstat & DATA_ERR) {
-				err = COMM_ERR;
+				err = -ECOMM;
 				goto out;
 			}
 		} while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE);
diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c
index a620678..c02740f 100644
--- a/drivers/mmc/ftsdc010_mci.c
+++ b/drivers/mmc/ftsdc010_mci.c
@@ -34,7 +34,7 @@
 {
 	struct ftsdc010_chip *chip = mmc->priv;
 	struct ftsdc010_mmc __iomem *regs = chip->regs;
-	int ret = TIMEOUT;
+	int ret = -ETIMEDOUT;
 	uint32_t ts, st;
 	uint32_t cmd   = FTSDC010_CMD_IDX(mmc_cmd->cmdidx);
 	uint32_t arg   = mmc_cmd->cmdarg;
@@ -126,7 +126,7 @@
 
 static int ftsdc010_wait(struct ftsdc010_mmc __iomem *regs, uint32_t mask)
 {
-	int ret = TIMEOUT;
+	int ret = -ETIMEDOUT;
 	uint32_t st, ts;
 
 	for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) {
@@ -151,7 +151,7 @@
 static int ftsdc010_request(struct mmc *mmc, struct mmc_cmd *cmd,
 	struct mmc_data *data)
 {
-	int ret = UNUSABLE_ERR;
+	int ret = -EOPNOTSUPP;
 	uint32_t len = 0;
 	struct ftsdc010_chip *chip = mmc->priv;
 	struct ftsdc010_mmc __iomem *regs = chip->regs;
@@ -279,7 +279,7 @@
 	uint32_t ts;
 
 	if (readl(&regs->status) & FTSDC010_STATUS_CARD_DETECT)
-		return NO_CARD_ERR;
+		return -ENOMEDIUM;
 
 	if (readl(&regs->status) & FTSDC010_STATUS_WRITE_PROT) {
 		printf("ftsdc010: write protected\n");
@@ -297,7 +297,7 @@
 	}
 	if (readl(&regs->cmd) & FTSDC010_CMD_SDC_RST) {
 		printf("ftsdc010: reset failed\n");
-		return UNUSABLE_ERR;
+		return -EOPNOTSUPP;
 	}
 
 	/* 2. enter low speed mode (400k card detection) */
diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
index 0474a15..69770df 100644
--- a/drivers/mmc/gen_atmel_mci.c
+++ b/drivers/mmc/gen_atmel_mci.c
@@ -213,7 +213,7 @@
 
 	if (!priv->initialized) {
 		puts ("MCI not initialized!\n");
-		return COMM_ERR;
+		return -ECOMM;
 	}
 
 	/* Figure out the transfer arguments */
@@ -238,10 +238,10 @@
 
 	if ((status & error_flags) & MMCI_BIT(RTOE)) {
 		dump_cmd(cmdr, cmd->cmdarg, status, "Command Time Out");
-		return TIMEOUT;
+		return -ETIMEDOUT;
 	} else if (status & error_flags) {
 		dump_cmd(cmdr, cmd->cmdarg, status, "Command Failed");
-		return COMM_ERR;
+		return -ECOMM;
 	}
 
 	/* Copy the response to the response buffer */
@@ -303,7 +303,7 @@
 			if (status) {
 				dump_cmd(cmdr, cmd->cmdarg, status,
 					"Data Transfer Failed");
-				return COMM_ERR;
+				return -ECOMM;
 			}
 		}
 
@@ -315,7 +315,7 @@
 			if (status & error_flags) {
 				dump_cmd(cmdr, cmd->cmdarg, status,
 					"DTIP Wait Failed");
-				return COMM_ERR;
+				return -ECOMM;
 			}
 			i++;
 		} while ((status & MMCI_BIT(DTIP)) && i < 10000);
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 1b967d9..425abb1 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -8,8 +8,76 @@
 #include <common.h>
 #include <mmc.h>
 #include <dm.h>
+#include <dm/device-internal.h>
 #include <dm/lists.h>
 #include <dm/root.h>
+#include "mmc_private.h"
+
+#ifdef CONFIG_DM_MMC_OPS
+int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+		    struct mmc_data *data)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+	struct dm_mmc_ops *ops = mmc_get_ops(dev);
+	int ret;
+
+	mmmc_trace_before_send(mmc, cmd);
+	if (ops->send_cmd)
+		ret = ops->send_cmd(dev, cmd, data);
+	else
+		ret = -ENOSYS;
+	mmmc_trace_after_send(mmc, cmd, ret);
+
+	return ret;
+}
+
+int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
+{
+	return dm_mmc_send_cmd(mmc->dev, cmd, data);
+}
+
+int dm_mmc_set_ios(struct udevice *dev)
+{
+	struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+	if (!ops->set_ios)
+		return -ENOSYS;
+	return ops->set_ios(dev);
+}
+
+int mmc_set_ios(struct mmc *mmc)
+{
+	return dm_mmc_set_ios(mmc->dev);
+}
+
+int dm_mmc_get_wp(struct udevice *dev)
+{
+	struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+	if (!ops->get_wp)
+		return -ENOSYS;
+	return ops->get_wp(dev);
+}
+
+int mmc_getwp(struct mmc *mmc)
+{
+	return dm_mmc_get_wp(mmc->dev);
+}
+
+int dm_mmc_get_cd(struct udevice *dev)
+{
+	struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+	if (!ops->get_cd)
+		return -ENOSYS;
+	return ops->get_cd(dev);
+}
+
+int mmc_getcd(struct mmc *mmc)
+{
+	return dm_mmc_get_cd(mmc->dev);
+}
+#endif
 
 struct mmc *mmc_get_mmc_dev(struct udevice *dev)
 {
@@ -43,18 +111,18 @@
 
 int get_mmc_num(void)
 {
-	return max(blk_find_max_devnum(IF_TYPE_MMC), 0);
+	return max((blk_find_max_devnum(IF_TYPE_MMC) + 1), 0);
 }
 
 int mmc_get_next_devnum(void)
 {
 	int ret;
 
-	ret = get_mmc_num();
+	ret = blk_find_max_devnum(IF_TYPE_MMC);
 	if (ret < 0)
 		return ret;
 
-	return ret + 1;
+	return ret;
 }
 
 struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
@@ -101,7 +169,7 @@
 
 	for (uclass_first_device(UCLASS_MMC, &dev);
 	     dev;
-	     uclass_next_device(&dev)) {
+	     uclass_next_device(&dev), first = false) {
 		struct mmc *m = mmc_get_mmc_dev(dev);
 
 		if (!first) {
@@ -125,6 +193,84 @@
 #else
 void print_mmc_devices(char separator) { }
 #endif
+
+int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
+{
+	struct blk_desc *bdesc;
+	struct udevice *bdev;
+	int ret;
+
+	ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC, -1, 512,
+				 0, &bdev);
+	if (ret) {
+		debug("Cannot create block device\n");
+		return ret;
+	}
+	bdesc = dev_get_uclass_platdata(bdev);
+	mmc->cfg = cfg;
+	mmc->priv = dev;
+
+	/* the following chunk was from mmc_register() */
+
+	/* Setup dsr related values */
+	mmc->dsr_imp = 0;
+	mmc->dsr = 0xffffffff;
+	/* Setup the universal parts of the block interface just once */
+	bdesc->removable = 1;
+
+	/* setup initial part type */
+	bdesc->part_type = cfg->part_type;
+	mmc->dev = dev;
+
+	return 0;
+}
+
+int mmc_unbind(struct udevice *dev)
+{
+	struct udevice *bdev;
+
+	device_find_first_child(dev, &bdev);
+	if (bdev) {
+		device_remove(bdev);
+		device_unbind(bdev);
+	}
+
+	return 0;
+}
+
+static int mmc_select_hwpart(struct udevice *bdev, int hwpart)
+{
+	struct udevice *mmc_dev = dev_get_parent(bdev);
+	struct mmc *mmc = mmc_get_mmc_dev(mmc_dev);
+	struct blk_desc *desc = dev_get_uclass_platdata(bdev);
+	int ret;
+
+	if (desc->hwpart == hwpart)
+		return 0;
+
+	if (mmc->part_config == MMCPART_NOAVAILABLE)
+		return -EMEDIUMTYPE;
+
+	ret = mmc_switch_part(mmc, hwpart);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct blk_ops mmc_blk_ops = {
+	.read	= mmc_bread,
+#ifndef CONFIG_SPL_BUILD
+	.write	= mmc_bwrite,
+#endif
+	.select_hwpart	= mmc_select_hwpart,
+};
+
+U_BOOT_DRIVER(mmc_blk) = {
+	.name		= "mmc_blk",
+	.id		= UCLASS_BLK,
+	.ops		= &mmc_blk_ops,
+};
 #endif /* CONFIG_BLK */
 
 U_BOOT_DRIVER(mmc) = {
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index aabfc71..43ea0bb 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -21,6 +21,7 @@
 #include <div64.h>
 #include "mmc_private.h"
 
+#ifndef CONFIG_DM_MMC_OPS
 __weak int board_mmc_getwp(struct mmc *mmc)
 {
 	return -1;
@@ -46,18 +47,20 @@
 {
 	return -1;
 }
+#endif
 
-int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
+#ifdef CONFIG_MMC_TRACE
+void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd)
 {
-	int ret;
+	printf("CMD_SEND:%d\n", cmd->cmdidx);
+	printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
+}
 
-#ifdef CONFIG_MMC_TRACE
+void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd, int ret)
+{
 	int i;
 	u8 *ptr;
 
-	printf("CMD_SEND:%d\n", cmd->cmdidx);
-	printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
-	ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
 	if (ret) {
 		printf("\t\tRET\t\t\t %d\n", ret);
 	} else {
@@ -103,19 +106,34 @@
 			break;
 		}
 	}
-#else
-	ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
+}
+
+void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd)
+{
+	int status;
+
+	status = (cmd->response[0] & MMC_STATUS_CURR_STATE) >> 9;
+	printf("CURR STATE:%d\n", status);
+}
 #endif
+
+#ifndef CONFIG_DM_MMC_OPS
+int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
+{
+	int ret;
+
+	mmmc_trace_before_send(mmc, cmd);
+	ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
+	mmmc_trace_after_send(mmc, cmd, ret);
+
 	return ret;
 }
+#endif
 
 int mmc_send_status(struct mmc *mmc, int timeout)
 {
 	struct mmc_cmd cmd;
 	int err, retries = 5;
-#ifdef CONFIG_MMC_TRACE
-	int status;
-#endif
 
 	cmd.cmdidx = MMC_CMD_SEND_STATUS;
 	cmd.resp_type = MMC_RSP_R1;
@@ -134,7 +152,7 @@
 				printf("Status Error: 0x%08X\n",
 					cmd.response[0]);
 #endif
-				return COMM_ERR;
+				return -ECOMM;
 			}
 		} else if (--retries < 0)
 			return err;
@@ -145,15 +163,12 @@
 		udelay(1000);
 	}
 
-#ifdef CONFIG_MMC_TRACE
-	status = (cmd.response[0] & MMC_STATUS_CURR_STATE) >> 9;
-	printf("CURR STATE:%d\n", status);
-#endif
+	mmc_trace_state(mmc, &cmd);
 	if (timeout <= 0) {
 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
 		printf("Timeout waiting card ready\n");
 #endif
-		return TIMEOUT;
+		return -ETIMEDOUT;
 	}
 
 	return 0;
@@ -215,11 +230,10 @@
 }
 
 #ifdef CONFIG_BLK
-static ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
-		       void *dst)
+ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *dst)
 #else
-static ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start,
-		       lbaint_t blkcnt, void *dst)
+ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
+		void *dst)
 #endif
 {
 #ifdef CONFIG_BLK
@@ -330,7 +344,7 @@
 			break;
 
 		if (timeout-- <= 0)
-			return UNUSABLE_ERR;
+			return -EOPNOTSUPP;
 
 		udelay(1000);
 	}
@@ -408,6 +422,9 @@
 
 	mmc->op_cond_pending = 0;
 	if (!(mmc->ocr & OCR_BUSY)) {
+		/* Some cards seem to need this */
+		mmc_go_idle(mmc);
+
 		start = get_timer(0);
 		while (1) {
 			err = mmc_send_op_cond_iter(mmc, 1);
@@ -416,7 +433,7 @@
 			if (mmc->ocr & OCR_BUSY)
 				break;
 			if (get_timer(start) > timeout)
-				return UNUSABLE_ERR;
+				return -EOPNOTSUPP;
 			udelay(100);
 		}
 	}
@@ -464,8 +481,7 @@
 	return err;
 }
 
-
-static int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
+int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
 {
 	struct mmc_cmd cmd;
 	int timeout = 1000;
@@ -566,7 +582,7 @@
 	return 0;
 }
 
-static int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
+int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
 {
 	int ret;
 
@@ -586,49 +602,6 @@
 	return ret;
 }
 
-#ifdef CONFIG_BLK
-static int mmc_select_hwpart(struct udevice *bdev, int hwpart)
-{
-	struct udevice *mmc_dev = dev_get_parent(bdev);
-	struct mmc *mmc = mmc_get_mmc_dev(mmc_dev);
-	struct blk_desc *desc = dev_get_uclass_platdata(bdev);
-	int ret;
-
-	if (desc->hwpart == hwpart)
-		return 0;
-
-	if (mmc->part_config == MMCPART_NOAVAILABLE)
-		return -EMEDIUMTYPE;
-
-	ret = mmc_switch_part(mmc, hwpart);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-#else
-static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart)
-{
-	struct mmc *mmc = find_mmc_device(desc->devnum);
-	int ret;
-
-	if (!mmc)
-		return -ENODEV;
-
-	if (mmc->block_dev.hwpart == hwpart)
-		return 0;
-
-	if (mmc->part_config == MMCPART_NOAVAILABLE)
-		return -EMEDIUMTYPE;
-
-	ret = mmc_switch_part(mmc, hwpart);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-#endif
-
 int mmc_hwpart_config(struct mmc *mmc,
 		      const struct mmc_hwpart_conf *conf,
 		      enum mmc_hwpart_conf_mode mode)
@@ -823,6 +796,7 @@
 	return 0;
 }
 
+#ifndef CONFIG_DM_MMC_OPS
 int mmc_getcd(struct mmc *mmc)
 {
 	int cd;
@@ -838,6 +812,7 @@
 
 	return cd;
 }
+#endif
 
 static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
 {
@@ -1001,11 +976,13 @@
 	80,
 };
 
+#ifndef CONFIG_DM_MMC_OPS
 static void mmc_set_ios(struct mmc *mmc)
 {
 	if (mmc->cfg->ops->set_ios)
 		mmc->cfg->ops->set_ios(mmc);
 }
+#endif
 
 void mmc_set_clock(struct mmc *mmc, uint clock)
 {
@@ -1455,7 +1432,7 @@
 				   &test_csd[EXT_CSD_SEC_CNT], 4) == 0)
 				break;
 			else
-				err = SWITCH_ERR;
+				err = -EBADMSG;
 		}
 
 		if (err)
@@ -1525,121 +1502,12 @@
 		return err;
 
 	if ((cmd.response[0] & 0xff) != 0xaa)
-		return UNUSABLE_ERR;
+		return -EOPNOTSUPP;
 	else
 		mmc->version = SD_VERSION_2;
 
 	return 0;
 }
-
-#ifdef CONFIG_BLK
-int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
-{
-	struct blk_desc *bdesc;
-	struct udevice *bdev;
-	int ret;
-
-	ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC, -1, 512,
-				 0, &bdev);
-	if (ret) {
-		debug("Cannot create block device\n");
-		return ret;
-	}
-	bdesc = dev_get_uclass_platdata(bdev);
-	mmc->cfg = cfg;
-	mmc->priv = dev;
-
-	/* the following chunk was from mmc_register() */
-
-	/* Setup dsr related values */
-	mmc->dsr_imp = 0;
-	mmc->dsr = 0xffffffff;
-	/* Setup the universal parts of the block interface just once */
-	bdesc->removable = 1;
-
-	/* setup initial part type */
-	bdesc->part_type = cfg->part_type;
-	mmc->dev = dev;
-
-	return 0;
-}
-
-int mmc_unbind(struct udevice *dev)
-{
-	struct udevice *bdev;
-
-	device_find_first_child(dev, &bdev);
-	if (bdev) {
-		device_remove(bdev);
-		device_unbind(bdev);
-	}
-
-	return 0;
-}
-
-#else
-struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
-{
-	struct blk_desc *bdesc;
-	struct mmc *mmc;
-
-	/* quick validation */
-	if (cfg == NULL || cfg->ops == NULL || cfg->ops->send_cmd == NULL ||
-			cfg->f_min == 0 || cfg->f_max == 0 || cfg->b_max == 0)
-		return NULL;
-
-	mmc = calloc(1, sizeof(*mmc));
-	if (mmc == NULL)
-		return NULL;
-
-	mmc->cfg = cfg;
-	mmc->priv = priv;
-
-	/* the following chunk was mmc_register() */
-
-	/* Setup dsr related values */
-	mmc->dsr_imp = 0;
-	mmc->dsr = 0xffffffff;
-	/* Setup the universal parts of the block interface just once */
-	bdesc = mmc_get_blk_desc(mmc);
-	bdesc->if_type = IF_TYPE_MMC;
-	bdesc->removable = 1;
-	bdesc->devnum = mmc_get_next_devnum();
-	bdesc->block_read = mmc_bread;
-	bdesc->block_write = mmc_bwrite;
-	bdesc->block_erase = mmc_berase;
-
-	/* setup initial part type */
-	bdesc->part_type = mmc->cfg->part_type;
-	mmc_list_add(mmc);
-
-	return mmc;
-}
-
-void mmc_destroy(struct mmc *mmc)
-{
-	/* only freeing memory for now */
-	free(mmc);
-}
-#endif
-
-#ifndef CONFIG_BLK
-static int mmc_get_dev(int dev, struct blk_desc **descp)
-{
-	struct mmc *mmc = find_mmc_device(dev);
-	int ret;
-
-	if (!mmc)
-		return -ENODEV;
-	ret = mmc_init(mmc);
-	if (ret)
-		return ret;
-
-	*descp = &mmc->block_dev;
-
-	return 0;
-}
-#endif
 
 /* board-specific MMC power initializations. */
 __weak void board_mmc_power_init(void)
@@ -1648,15 +1516,20 @@
 
 int mmc_start_init(struct mmc *mmc)
 {
+	bool no_card;
 	int err;
 
 	/* we pretend there's no card when init is NULL */
-	if (mmc_getcd(mmc) == 0 || mmc->cfg->ops->init == NULL) {
+	no_card = mmc_getcd(mmc) == 0;
+#ifndef CONFIG_DM_MMC_OPS
+	no_card = no_card || (mmc->cfg->ops->init == NULL);
+#endif
+	if (no_card) {
 		mmc->has_init = 0;
 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
 		printf("MMC: no card present\n");
 #endif
-		return NO_CARD_ERR;
+		return -ENOMEDIUM;
 	}
 
 	if (mmc->has_init)
@@ -1667,12 +1540,14 @@
 #endif
 	board_mmc_power_init();
 
+#ifdef CONFIG_DM_MMC_OPS
+	/* The device has already been probed ready for use */
+#else
 	/* made sure it's not NULL earlier */
 	err = mmc->cfg->ops->init(mmc);
-
 	if (err)
 		return err;
-
+#endif
 	mmc->ddr_mode = 0;
 	mmc_set_bus_width(mmc, 1);
 	mmc_set_clock(mmc, 1);
@@ -1693,14 +1568,14 @@
 	err = sd_send_op_cond(mmc);
 
 	/* If the command timed out, we check for an MMC card */
-	if (err == TIMEOUT) {
+	if (err == -ETIMEDOUT) {
 		err = mmc_send_op_cond(mmc);
 
 		if (err) {
 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
 			printf("Card did not respond to voltage select!\n");
 #endif
-			return UNUSABLE_ERR;
+			return -EOPNOTSUPP;
 		}
 	}
 
@@ -1839,148 +1714,3 @@
 	mmc_do_preinit();
 	return 0;
 }
-
-#ifdef CONFIG_SUPPORT_EMMC_BOOT
-/*
- * This function changes the size of boot partition and the size of rpmb
- * partition present on EMMC devices.
- *
- * Input Parameters:
- * struct *mmc: pointer for the mmc device strcuture
- * bootsize: size of boot partition
- * rpmbsize: size of rpmb partition
- *
- * Returns 0 on success.
- */
-
-int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
-				unsigned long rpmbsize)
-{
-	int err;
-	struct mmc_cmd cmd;
-
-	/* Only use this command for raw EMMC moviNAND. Enter backdoor mode */
-	cmd.cmdidx = MMC_CMD_RES_MAN;
-	cmd.resp_type = MMC_RSP_R1b;
-	cmd.cmdarg = MMC_CMD62_ARG1;
-
-	err = mmc_send_cmd(mmc, &cmd, NULL);
-	if (err) {
-		debug("mmc_boot_partition_size_change: Error1 = %d\n", err);
-		return err;
-	}
-
-	/* Boot partition changing mode */
-	cmd.cmdidx = MMC_CMD_RES_MAN;
-	cmd.resp_type = MMC_RSP_R1b;
-	cmd.cmdarg = MMC_CMD62_ARG2;
-
-	err = mmc_send_cmd(mmc, &cmd, NULL);
-	if (err) {
-		debug("mmc_boot_partition_size_change: Error2 = %d\n", err);
-		return err;
-	}
-	/* boot partition size is multiple of 128KB */
-	bootsize = (bootsize * 1024) / 128;
-
-	/* Arg: boot partition size */
-	cmd.cmdidx = MMC_CMD_RES_MAN;
-	cmd.resp_type = MMC_RSP_R1b;
-	cmd.cmdarg = bootsize;
-
-	err = mmc_send_cmd(mmc, &cmd, NULL);
-	if (err) {
-		debug("mmc_boot_partition_size_change: Error3 = %d\n", err);
-		return err;
-	}
-	/* RPMB partition size is multiple of 128KB */
-	rpmbsize = (rpmbsize * 1024) / 128;
-	/* Arg: RPMB partition size */
-	cmd.cmdidx = MMC_CMD_RES_MAN;
-	cmd.resp_type = MMC_RSP_R1b;
-	cmd.cmdarg = rpmbsize;
-
-	err = mmc_send_cmd(mmc, &cmd, NULL);
-	if (err) {
-		debug("mmc_boot_partition_size_change: Error4 = %d\n", err);
-		return err;
-	}
-	return 0;
-}
-
-/*
- * Modify EXT_CSD[177] which is BOOT_BUS_WIDTH
- * based on the passed in values for BOOT_BUS_WIDTH, RESET_BOOT_BUS_WIDTH
- * and BOOT_MODE.
- *
- * Returns 0 on success.
- */
-int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode)
-{
-	int err;
-
-	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_BUS_WIDTH,
-			 EXT_CSD_BOOT_BUS_WIDTH_MODE(mode) |
-			 EXT_CSD_BOOT_BUS_WIDTH_RESET(reset) |
-			 EXT_CSD_BOOT_BUS_WIDTH_WIDTH(width));
-
-	if (err)
-		return err;
-	return 0;
-}
-
-/*
- * Modify EXT_CSD[179] which is PARTITION_CONFIG (formerly BOOT_CONFIG)
- * based on the passed in values for BOOT_ACK, BOOT_PARTITION_ENABLE and
- * PARTITION_ACCESS.
- *
- * Returns 0 on success.
- */
-int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
-{
-	int err;
-
-	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
-			 EXT_CSD_BOOT_ACK(ack) |
-			 EXT_CSD_BOOT_PART_NUM(part_num) |
-			 EXT_CSD_PARTITION_ACCESS(access));
-
-	if (err)
-		return err;
-	return 0;
-}
-
-/*
- * Modify EXT_CSD[162] which is RST_n_FUNCTION based on the given value
- * for enable.  Note that this is a write-once field for non-zero values.
- *
- * Returns 0 on success.
- */
-int mmc_set_rst_n_function(struct mmc *mmc, u8 enable)
-{
-	return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_RST_N_FUNCTION,
-			  enable);
-}
-#endif
-
-#ifdef CONFIG_BLK
-static const struct blk_ops mmc_blk_ops = {
-	.read	= mmc_bread,
-	.write	= mmc_bwrite,
-	.select_hwpart	= mmc_select_hwpart,
-};
-
-U_BOOT_DRIVER(mmc_blk) = {
-	.name		= "mmc_blk",
-	.id		= UCLASS_BLK,
-	.ops		= &mmc_blk_ops,
-};
-#else
-U_BOOT_LEGACY_BLK(mmc) = {
-	.if_typename	= "mmc",
-	.if_type	= IF_TYPE_MMC,
-	.max_devs	= -1,
-	.get_dev	= mmc_get_dev,
-	.select_hwpart	= mmc_select_hwpartp,
-};
-#endif
diff --git a/drivers/mmc/mmc_boot.c b/drivers/mmc/mmc_boot.c
new file mode 100644
index 0000000..756a982
--- /dev/null
+++ b/drivers/mmc/mmc_boot.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2016 Google, Inc
+ * Written by Amar <amarendra.xt@samsung.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <mmc.h>
+#include "mmc_private.h"
+
+/*
+ * This function changes the size of boot partition and the size of rpmb
+ * partition present on EMMC devices.
+ *
+ * Input Parameters:
+ * struct *mmc: pointer for the mmc device strcuture
+ * bootsize: size of boot partition
+ * rpmbsize: size of rpmb partition
+ *
+ * Returns 0 on success.
+ */
+
+int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
+				unsigned long rpmbsize)
+{
+	int err;
+	struct mmc_cmd cmd;
+
+	/* Only use this command for raw EMMC moviNAND. Enter backdoor mode */
+	cmd.cmdidx = MMC_CMD_RES_MAN;
+	cmd.resp_type = MMC_RSP_R1b;
+	cmd.cmdarg = MMC_CMD62_ARG1;
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err) {
+		debug("mmc_boot_partition_size_change: Error1 = %d\n", err);
+		return err;
+	}
+
+	/* Boot partition changing mode */
+	cmd.cmdidx = MMC_CMD_RES_MAN;
+	cmd.resp_type = MMC_RSP_R1b;
+	cmd.cmdarg = MMC_CMD62_ARG2;
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err) {
+		debug("mmc_boot_partition_size_change: Error2 = %d\n", err);
+		return err;
+	}
+	/* boot partition size is multiple of 128KB */
+	bootsize = (bootsize * 1024) / 128;
+
+	/* Arg: boot partition size */
+	cmd.cmdidx = MMC_CMD_RES_MAN;
+	cmd.resp_type = MMC_RSP_R1b;
+	cmd.cmdarg = bootsize;
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err) {
+		debug("mmc_boot_partition_size_change: Error3 = %d\n", err);
+		return err;
+	}
+	/* RPMB partition size is multiple of 128KB */
+	rpmbsize = (rpmbsize * 1024) / 128;
+	/* Arg: RPMB partition size */
+	cmd.cmdidx = MMC_CMD_RES_MAN;
+	cmd.resp_type = MMC_RSP_R1b;
+	cmd.cmdarg = rpmbsize;
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err) {
+		debug("mmc_boot_partition_size_change: Error4 = %d\n", err);
+		return err;
+	}
+	return 0;
+}
+
+/*
+ * Modify EXT_CSD[177] which is BOOT_BUS_WIDTH
+ * based on the passed in values for BOOT_BUS_WIDTH, RESET_BOOT_BUS_WIDTH
+ * and BOOT_MODE.
+ *
+ * Returns 0 on success.
+ */
+int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode)
+{
+	int err;
+
+	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_BUS_WIDTH,
+			 EXT_CSD_BOOT_BUS_WIDTH_MODE(mode) |
+			 EXT_CSD_BOOT_BUS_WIDTH_RESET(reset) |
+			 EXT_CSD_BOOT_BUS_WIDTH_WIDTH(width));
+
+	if (err)
+		return err;
+	return 0;
+}
+
+/*
+ * Modify EXT_CSD[179] which is PARTITION_CONFIG (formerly BOOT_CONFIG)
+ * based on the passed in values for BOOT_ACK, BOOT_PARTITION_ENABLE and
+ * PARTITION_ACCESS.
+ *
+ * Returns 0 on success.
+ */
+int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
+{
+	int err;
+
+	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
+			 EXT_CSD_BOOT_ACK(ack) |
+			 EXT_CSD_BOOT_PART_NUM(part_num) |
+			 EXT_CSD_PARTITION_ACCESS(access));
+
+	if (err)
+		return err;
+	return 0;
+}
+
+/*
+ * Modify EXT_CSD[162] which is RST_n_FUNCTION based on the given value
+ * for enable.  Note that this is a write-once field for non-zero values.
+ *
+ * Returns 0 on success.
+ */
+int mmc_set_rst_n_function(struct mmc *mmc, u8 enable)
+{
+	return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_RST_N_FUNCTION,
+			  enable);
+}
diff --git a/drivers/mmc/mmc_legacy.c b/drivers/mmc/mmc_legacy.c
index 3ec649f..25361d1 100644
--- a/drivers/mmc/mmc_legacy.c
+++ b/drivers/mmc/mmc_legacy.c
@@ -6,7 +6,9 @@
  */
 
 #include <common.h>
+#include <malloc.h>
 #include <mmc.h>
+#include "mmc_private.h"
 
 static struct list_head mmc_devices;
 static int cur_dev_num = -1;
@@ -106,3 +108,97 @@
 #else
 void print_mmc_devices(char separator) { }
 #endif
+
+struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
+{
+	struct blk_desc *bdesc;
+	struct mmc *mmc;
+
+	/* quick validation */
+	if (cfg == NULL || cfg->f_min == 0 ||
+	    cfg->f_max == 0 || cfg->b_max == 0)
+		return NULL;
+
+#ifndef CONFIG_DM_MMC_OPS
+	if (cfg->ops == NULL || cfg->ops->send_cmd == NULL)
+		return NULL;
+#endif
+
+	mmc = calloc(1, sizeof(*mmc));
+	if (mmc == NULL)
+		return NULL;
+
+	mmc->cfg = cfg;
+	mmc->priv = priv;
+
+	/* the following chunk was mmc_register() */
+
+	/* Setup dsr related values */
+	mmc->dsr_imp = 0;
+	mmc->dsr = 0xffffffff;
+	/* Setup the universal parts of the block interface just once */
+	bdesc = mmc_get_blk_desc(mmc);
+	bdesc->if_type = IF_TYPE_MMC;
+	bdesc->removable = 1;
+	bdesc->devnum = mmc_get_next_devnum();
+	bdesc->block_read = mmc_bread;
+	bdesc->block_write = mmc_bwrite;
+	bdesc->block_erase = mmc_berase;
+
+	/* setup initial part type */
+	bdesc->part_type = mmc->cfg->part_type;
+	mmc_list_add(mmc);
+
+	return mmc;
+}
+
+void mmc_destroy(struct mmc *mmc)
+{
+	/* only freeing memory for now */
+	free(mmc);
+}
+
+static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart)
+{
+	struct mmc *mmc = find_mmc_device(desc->devnum);
+	int ret;
+
+	if (!mmc)
+		return -ENODEV;
+
+	if (mmc->block_dev.hwpart == hwpart)
+		return 0;
+
+	if (mmc->part_config == MMCPART_NOAVAILABLE)
+		return -EMEDIUMTYPE;
+
+	ret = mmc_switch_part(mmc, hwpart);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int mmc_get_dev(int dev, struct blk_desc **descp)
+{
+	struct mmc *mmc = find_mmc_device(dev);
+	int ret;
+
+	if (!mmc)
+		return -ENODEV;
+	ret = mmc_init(mmc);
+	if (ret)
+		return ret;
+
+	*descp = &mmc->block_dev;
+
+	return 0;
+}
+
+U_BOOT_LEGACY_BLK(mmc) = {
+	.if_typename	= "mmc",
+	.if_type	= IF_TYPE_MMC,
+	.max_devs	= -1,
+	.get_dev	= mmc_get_dev,
+	.select_hwpart	= mmc_select_hwpartp,
+};
diff --git a/drivers/mmc/mmc_private.h b/drivers/mmc/mmc_private.h
index 9f0d5c2..49ec022 100644
--- a/drivers/mmc/mmc_private.h
+++ b/drivers/mmc/mmc_private.h
@@ -20,6 +20,14 @@
 void mmc_adapter_card_type_ident(void);
 #endif
 
+#ifdef CONFIG_BLK
+ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
+		void *dst);
+#else
+ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
+		void *dst);
+#endif
+
 #ifndef CONFIG_SPL_BUILD
 
 unsigned long mmc_berase(struct blk_desc *block_dev, lbaint_t start,
@@ -65,6 +73,25 @@
 
 #endif /* CONFIG_SPL_BUILD */
 
+#ifdef CONFIG_MMC_TRACE
+void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd);
+void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd, int ret);
+void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd);
+#else
+static inline void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd)
+{
+}
+
+static inline void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd,
+					 int ret)
+{
+}
+
+static inline void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd)
+{
+}
+#endif
+
 /**
  * mmc_get_next_devnum() - Get the next available MMC device number
  *
@@ -89,4 +116,24 @@
  */
 void mmc_list_add(struct mmc *mmc);
 
+/**
+ * mmc_switch_part() - Switch to a new MMC hardware partition
+ *
+ * @mmc:	MMC device
+ * @part_num:	Hardware partition number
+ * @return 0 if OK, -ve on error
+ */
+int mmc_switch_part(struct mmc *mmc, unsigned int part_num);
+
+/**
+ * mmc_switch() - Issue and MMC switch mode command
+ *
+ * @mmc:	MMC device
+ * @set:	Unused
+ * @index:	Cmdarg index
+ * @value:	Cmdarg value
+ * @return 0 if OK, -ve on error
+ */
+int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value);
+
 #endif /* _MMC_PRIVATE_H_ */
diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c
index 7547e1a..2510117 100644
--- a/drivers/mmc/mmc_spi.c
+++ b/drivers/mmc/mmc_spi.c
@@ -5,6 +5,7 @@
  * Licensed under the GPL-2 or later.
  */
 #include <common.h>
+#include <errno.h>
 #include <malloc.h>
 #include <part.h>
 #include <mmc.h>
@@ -182,13 +183,13 @@
 	spi_cs_activate(spi);
 	r1 = mmc_spi_sendcmd(mmc, cmd->cmdidx, cmd->cmdarg);
 	if (r1 == 0xff) { /* no response */
-		ret = NO_CARD_ERR;
+		ret = -ENOMEDIUM;
 		goto done;
 	} else if (r1 & R1_SPI_COM_CRC) {
-		ret = COMM_ERR;
+		ret = -ECOMM;
 		goto done;
 	} else if (r1 & ~R1_SPI_IDLE) { /* other errors */
-		ret = TIMEOUT;
+		ret = -ETIMEDOUT;
 		goto done;
 	} else if (cmd->resp_type == MMC_RSP_R2) {
 		r1 = mmc_spi_readdata(mmc, cmd->response, 1, 16);
@@ -225,9 +226,9 @@
 				data->blocks, data->blocksize,
 				(cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK));
 		if (r1 & R1_SPI_COM_CRC)
-			ret = COMM_ERR;
+			ret = -ECOMM;
 		else if (r1) /* other errors */
-			ret = TIMEOUT;
+			ret = -ETIMEDOUT;
 	}
 done:
 	spi_cs_deactivate(spi);
diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c
index 96dcdbe..8d4399e 100644
--- a/drivers/mmc/msm_sdhci.c
+++ b/drivers/mmc/msm_sdhci.c
@@ -36,6 +36,11 @@
 /* Non standard (?) SDHCI register */
 #define SDHCI_VENDOR_SPEC_CAPABILITIES0  0x11c
 
+struct msm_sdhc_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
 struct msm_sdhc {
 	struct sdhci_host host;
 	void *base;
@@ -81,9 +86,12 @@
 
 static int msm_sdc_probe(struct udevice *dev)
 {
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct msm_sdhc_plat *plat = dev_get_platdata(dev);
 	struct msm_sdhc *prv = dev_get_priv(dev);
 	struct sdhci_host *host = &prv->host;
 	u32 core_version, core_minor, core_major;
+	u32 caps;
 	int ret;
 
 	host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B;
@@ -127,7 +135,7 @@
 	 * controller versions and must be explicitly enabled.
 	 */
 	if (core_major >= 1 && core_minor != 0x11 && core_minor != 0x12) {
-		u32 caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
+		caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
 		caps |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT;
 		writel(caps, host->ioaddr + SDHCI_VENDOR_SPEC_CAPABILITIES0);
 	}
@@ -135,13 +143,15 @@
 	/* Set host controller version */
 	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
 
-	/* automatically detect max and min speed */
-	ret =  add_sdhci(host, 0, 0);
+	ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
+	host->mmc = &plat->mmc;
 	if (ret)
 		return ret;
+	host->mmc->priv = &prv->host;
 	host->mmc->dev = dev;
+	upriv->mmc = host->mmc;
 
-	return 0;
+	return sdhci_probe(dev);
 }
 
 static int msm_sdc_remove(struct udevice *dev)
@@ -168,7 +178,8 @@
 	priv->base = (void *)fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
 							      parent->of_offset,
 							      dev->of_offset,
-							      "reg", 1, NULL);
+							      "reg", 1, NULL,
+							      false);
 	if (priv->base == (void *)FDT_ADDR_T_NONE ||
 	    host->ioaddr == (void *)FDT_ADDR_T_NONE)
 		return -EINVAL;
@@ -176,6 +187,18 @@
 	return 0;
 }
 
+static int msm_sdc_bind(struct udevice *dev)
+{
+	struct msm_sdhc_plat *plat = dev_get_platdata(dev);
+	int ret;
+
+	ret = sdhci_bind(dev, &plat->mmc, &plat->cfg);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static const struct udevice_id msm_mmc_ids[] = {
 	{ .compatible = "qcom,sdhci-msm-v4" },
 	{ }
@@ -186,7 +209,10 @@
 	.id		= UCLASS_MMC,
 	.of_match	= msm_mmc_ids,
 	.ofdata_to_platdata = msm_ofdata_to_platdata,
+	.ops		= &sdhci_ops,
+	.bind		= msm_sdc_bind,
 	.probe		= msm_sdc_probe,
 	.remove		= msm_sdc_remove,
 	.priv_auto_alloc_size = sizeof(struct msm_sdhc),
+	.platdata_auto_alloc_size = sizeof(struct msm_sdhc_plat),
 };
diff --git a/drivers/mmc/mvebu_mmc.c b/drivers/mmc/mvebu_mmc.c
index 056aef5..a2792ac 100644
--- a/drivers/mmc/mvebu_mmc.c
+++ b/drivers/mmc/mvebu_mmc.c
@@ -9,6 +9,7 @@
  */
 
 #include <common.h>
+#include <errno.h>
 #include <malloc.h>
 #include <part.h>
 #include <mmc.h>
@@ -172,15 +173,15 @@
 			    (SDIO_ERR_CMD_TIMEOUT | SDIO_ERR_DATA_TIMEOUT)) {
 				debug("%s: command READ timed out\n",
 				      DRIVER_NAME);
-				return TIMEOUT;
+				return -ETIMEDOUT;
 			}
 			debug("%s: command READ error\n", DRIVER_NAME);
-			return COMM_ERR;
+			return -ECOMM;
 		}
 
 		if ((get_timer(0) - start) > TIMEOUT_DELAY) {
 			debug("%s: command timed out\n", DRIVER_NAME);
-			return TIMEOUT;
+			return -ETIMEDOUT;
 		}
 	}
 
@@ -232,7 +233,7 @@
 
 	if (mvebu_mmc_read(SDIO_ERR_INTR_STATUS) &
 		(SDIO_ERR_CMD_TIMEOUT | SDIO_ERR_DATA_TIMEOUT))
-		return TIMEOUT;
+		return -ETIMEDOUT;
 
 	return 0;
 }
diff --git a/drivers/mmc/mxcmmc.c b/drivers/mmc/mxcmmc.c
index 561b204..8038f90 100644
--- a/drivers/mmc/mxcmmc.c
+++ b/drivers/mmc/mxcmmc.c
@@ -211,11 +211,11 @@
 		} else if (stat & STATUS_CRC_WRITE_ERR) {
 			u32 err_code = (stat >> 9) & 0x3;
 			if (err_code == 2) /* No CRC response */
-				data_error = TIMEOUT;
+				data_error = -ETIMEDOUT;
 			else
 				data_error = -EILSEQ;
 		} else if (stat & STATUS_TIME_OUT_READ) {
-			data_error = TIMEOUT;
+			data_error = -ETIMEDOUT;
 		} else {
 			data_error = -EIO;
 		}
@@ -238,7 +238,7 @@
 
 	if (stat & STATUS_TIME_OUT_RESP) {
 		printf("CMD TIMEOUT\n");
-		return TIMEOUT;
+		return -ETIMEDOUT;
 	} else if (stat & STATUS_RESP_CRC_ERR && cmd->resp_type & MMC_RSP_CRC) {
 		printf("cmd crc error\n");
 		return -EILSEQ;
diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c
index 9fa87d5..40f3eaa 100644
--- a/drivers/mmc/mxsmmc.c
+++ b/drivers/mmc/mxsmmc.c
@@ -84,7 +84,7 @@
 		}
 	}
 
-	return timeout ? 0 : COMM_ERR;
+	return timeout ? 0 : -ECOMM;
 }
 
 static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data)
@@ -120,7 +120,7 @@
 	mxs_dma_desc_append(dmach, priv->desc);
 	if (mxs_dma_go(dmach)) {
 		bounce_buffer_stop(&bbstate);
-		return COMM_ERR;
+		return -ECOMM;
 	}
 
 	bounce_buffer_stop(&bbstate);
@@ -158,13 +158,13 @@
 
 	if (!timeout) {
 		printf("MMC%d: Bus busy timeout!\n", mmc->block_dev.devnum);
-		return TIMEOUT;
+		return -ETIMEDOUT;
 	}
 
 	/* See if card is present */
 	if (!mxsmmc_cd(priv)) {
 		printf("MMC%d: No card detected!\n", mmc->block_dev.devnum);
-		return NO_CARD_ERR;
+		return -ENOMEDIUM;
 	}
 
 	/* Start building CTRL0 contents */
@@ -203,7 +203,7 @@
 			priv->mmc_is_wp(mmc->block_dev.devnum)) {
 			printf("MMC%d: Can not write a locked card!\n",
 				mmc->block_dev.devnum);
-			return UNUSABLE_ERR;
+			return -EOPNOTSUPP;
 		}
 
 		ctrl0 |= SSP_CTRL0_DATA_XFER;
@@ -244,21 +244,21 @@
 	if (!timeout) {
 		printf("MMC%d: Command %d busy\n",
 			mmc->block_dev.devnum, cmd->cmdidx);
-		return TIMEOUT;
+		return -ETIMEDOUT;
 	}
 
 	/* Check command timeout */
 	if (reg & SSP_STATUS_RESP_TIMEOUT) {
 		printf("MMC%d: Command %d timeout (status 0x%08x)\n",
 			mmc->block_dev.devnum, cmd->cmdidx, reg);
-		return TIMEOUT;
+		return -ETIMEDOUT;
 	}
 
 	/* Check command errors */
 	if (reg & (SSP_STATUS_RESP_CRC_ERR | SSP_STATUS_RESP_ERR)) {
 		printf("MMC%d: Command %d error (status 0x%08x)!\n",
 			mmc->block_dev.devnum, cmd->cmdidx, reg);
-		return COMM_ERR;
+		return -ECOMM;
 	}
 
 	/* Copy response to response buffer */
@@ -298,7 +298,7 @@
 		SSP_STATUS_FIFO_OVRFLW | SSP_STATUS_FIFO_UNDRFLW)) {
 		printf("MMC%d: Data error with command %d (status 0x%08x)!\n",
 			mmc->block_dev.devnum, cmd->cmdidx, reg);
-		return COMM_ERR;
+		return -ECOMM;
 	}
 
 	return 0;
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index d007b56..fceafe1 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -231,7 +231,7 @@
 	while ((readl(&mmc_base->sysstatus) & RESETDONE) == 0) {
 		if (get_timer(0) - start > MAX_RETRY_MS) {
 			printf("%s: timedout waiting for cc2!\n", __func__);
-			return TIMEOUT;
+			return -ETIMEDOUT;
 		}
 	}
 	writel(readl(&mmc_base->sysctl) | SOFTRESETALL, &mmc_base->sysctl);
@@ -240,7 +240,7 @@
 		if (get_timer(0) - start > MAX_RETRY_MS) {
 			printf("%s: timedout waiting for softresetall!\n",
 				__func__);
-			return TIMEOUT;
+			return -ETIMEDOUT;
 		}
 	}
 	writel(DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V0, &mmc_base->hctl);
@@ -262,7 +262,7 @@
 	while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) {
 		if (get_timer(0) - start > MAX_RETRY_MS) {
 			printf("%s: timedout waiting for ics!\n", __func__);
-			return TIMEOUT;
+			return -ETIMEDOUT;
 		}
 	}
 	writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl);
@@ -337,7 +337,7 @@
 		if (get_timer(0) - start > MAX_RETRY_MS) {
 			printf("%s: timedout waiting on cmd inhibit to clear\n",
 					__func__);
-			return TIMEOUT;
+			return -ETIMEDOUT;
 		}
 	}
 	writel(0xFFFFFFFF, &mmc_base->stat);
@@ -346,7 +346,7 @@
 		if (get_timer(0) - start > MAX_RETRY_MS) {
 			printf("%s: timedout waiting for STAT (%x) to clear\n",
 				__func__, readl(&mmc_base->stat));
-			return TIMEOUT;
+			return -ETIMEDOUT;
 		}
 	}
 	/*
@@ -410,13 +410,13 @@
 		mmc_stat = readl(&mmc_base->stat);
 		if (get_timer(0) - start > MAX_RETRY_MS) {
 			printf("%s : timeout: No status update\n", __func__);
-			return TIMEOUT;
+			return -ETIMEDOUT;
 		}
 	} while (!mmc_stat);
 
 	if ((mmc_stat & IE_CTO) != 0) {
 		mmc_reset_controller_fsm(mmc_base, SYSCTL_SRC);
-		return TIMEOUT;
+		return -ETIMEDOUT;
 	} else if ((mmc_stat & ERRI_MASK) != 0)
 		return -1;
 
@@ -464,7 +464,7 @@
 			if (get_timer(0) - start > MAX_RETRY_MS) {
 				printf("%s: timedout waiting for status!\n",
 						__func__);
-				return TIMEOUT;
+				return -ETIMEDOUT;
 			}
 		} while (mmc_stat == 0);
 
@@ -519,7 +519,7 @@
 			if (get_timer(0) - start > MAX_RETRY_MS) {
 				printf("%s: timedout waiting for status!\n",
 						__func__);
-				return TIMEOUT;
+				return -ETIMEDOUT;
 			}
 		} while (mmc_stat == 0);
 
@@ -801,7 +801,9 @@
 	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
 	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
+#ifdef OMAP_HSMMC_USE_GPIO
 	priv->cd_inverted = fdtdec_get_bool(fdt, node, "cd-inverted");
+#endif
 
 	return 0;
 }
diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c
index d41d60c..020a59b 100644
--- a/drivers/mmc/rockchip_dw_mmc.c
+++ b/drivers/mmc/rockchip_dw_mmc.c
@@ -7,8 +7,10 @@
 #include <common.h>
 #include <clk.h>
 #include <dm.h>
+#include <dt-structs.h>
 #include <dwmmc.h>
 #include <errno.h>
+#include <mapmem.h>
 #include <pwrseq.h>
 #include <syscon.h>
 #include <asm/gpio.h>
@@ -19,6 +21,9 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 struct rockchip_mmc_plat {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_rockchip_rk3288_dw_mshc dtplat;
+#endif
 	struct mmc_config cfg;
 	struct mmc mmc;
 };
@@ -26,6 +31,9 @@
 struct rockchip_dwmmc_priv {
 	struct clk clk;
 	struct dwmci_host host;
+	int fifo_depth;
+	bool fifo_mode;
+	u32 minmax[2];
 };
 
 static uint rockchip_dwmmc_get_mmc_clk(struct dwmci_host *host, uint freq)
@@ -45,6 +53,7 @@
 
 static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev)
 {
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
 	struct dwmci_host *host = &priv->host;
 
@@ -61,40 +70,54 @@
 	else
 		host->dev_index = 1;
 
+	priv->fifo_depth = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+				    "fifo-depth", 0);
+	if (priv->fifo_depth < 0)
+		return -EINVAL;
+	priv->fifo_mode = fdtdec_get_bool(gd->fdt_blob, dev->of_offset,
+					  "fifo-mode");
+	if (fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
+				 "clock-freq-min-max", priv->minmax, 2))
+		return -EINVAL;
+#endif
 	return 0;
 }
 
 static int rockchip_dwmmc_probe(struct udevice *dev)
 {
-#ifdef CONFIG_BLK
 	struct rockchip_mmc_plat *plat = dev_get_platdata(dev);
-#endif
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
 	struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
 	struct dwmci_host *host = &priv->host;
 	struct udevice *pwr_dev __maybe_unused;
-	u32 minmax[2];
 	int ret;
-	int fifo_depth;
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_rockchip_rk3288_dw_mshc *dtplat = &plat->dtplat;
+
+	host->name = dev->name;
+	host->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]);
+	host->buswidth = dtplat->bus_width;
+	host->get_mmc_clk = rockchip_dwmmc_get_mmc_clk;
+	host->priv = dev;
+	host->dev_index = 0;
+	priv->fifo_depth = dtplat->fifo_depth;
+	priv->fifo_mode = 0;
+	memcpy(priv->minmax, dtplat->clock_freq_min_max, sizeof(priv->minmax));
 
+	ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk);
+	if (ret < 0)
+		return ret;
+#else
 	ret = clk_get_by_index(dev, 0, &priv->clk);
 	if (ret < 0)
 		return ret;
-
-	if (fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
-				 "clock-freq-min-max", minmax, 2))
-		return -EINVAL;
-
-	fifo_depth = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
-				    "fifo-depth", 0);
-	if (fifo_depth < 0)
-		return -EINVAL;
-
+#endif
 	host->fifoth_val = MSIZE(0x2) |
-		RX_WMARK(fifo_depth / 2 - 1) | TX_WMARK(fifo_depth / 2);
+		RX_WMARK(priv->fifo_depth / 2 - 1) |
+		TX_WMARK(priv->fifo_depth / 2);
 
-	if (fdtdec_get_bool(gd->fdt_blob, dev->of_offset, "fifo-mode"))
-		host->fifo_mode = true;
+	host->fifo_mode = priv->fifo_mode;
 
 #ifdef CONFIG_PWRSEQ
 	/* Enable power if needed */
@@ -106,33 +129,24 @@
 			return ret;
 	}
 #endif
-#ifdef CONFIG_BLK
 	dwmci_setup_cfg(&plat->cfg, dev->name, host->buswidth, host->caps,
-			minmax[1], minmax[0]);
+			priv->minmax[1], priv->minmax[0]);
 	host->mmc = &plat->mmc;
-#else
-	ret = add_dwmci(host, minmax[1], minmax[0]);
-	if (ret)
-		return ret;
-
-#endif
 	host->mmc->priv = &priv->host;
 	host->mmc->dev = dev;
 	upriv->mmc = host->mmc;
 
-	return 0;
+	return dwmci_probe(dev);
 }
 
 static int rockchip_dwmmc_bind(struct udevice *dev)
 {
-#ifdef CONFIG_BLK
 	struct rockchip_mmc_plat *plat = dev_get_platdata(dev);
 	int ret;
 
 	ret = dwmci_bind(dev, &plat->mmc, &plat->cfg);
 	if (ret)
 		return ret;
-#endif
 
 	return 0;
 }
@@ -143,10 +157,11 @@
 };
 
 U_BOOT_DRIVER(rockchip_dwmmc_drv) = {
-	.name		= "rockchip_dwmmc",
+	.name		= "rockchip_rk3288_dw_mshc",
 	.id		= UCLASS_MMC,
 	.of_match	= rockchip_dwmmc_ids,
 	.ofdata_to_platdata = rockchip_dwmmc_ofdata_to_platdata,
+	.ops		= &dm_dwmci_ops,
 	.bind		= rockchip_dwmmc_bind,
 	.probe		= rockchip_dwmmc_probe,
 	.priv_auto_alloc_size = sizeof(struct rockchip_dwmmc_priv),
diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
new file mode 100644
index 0000000..624029b
--- /dev/null
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -0,0 +1,89 @@
+/*
+ * (C) Copyright 2016 Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * Rockchip SD Host Controller Interface
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <malloc.h>
+#include <sdhci.h>
+
+/* 400KHz is max freq for card ID etc. Use that as min */
+#define EMMC_MIN_FREQ	400000
+
+struct rockchip_sdhc_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
+struct rockchip_sdhc {
+	struct sdhci_host host;
+	void *base;
+};
+
+static int arasan_sdhci_probe(struct udevice *dev)
+{
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct rockchip_sdhc_plat *plat = dev_get_platdata(dev);
+	struct rockchip_sdhc *prv = dev_get_priv(dev);
+	struct sdhci_host *host = &prv->host;
+	int ret;
+
+	host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD;
+
+	ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ROCKCHIP_SDHCI_MAX_FREQ,
+			EMMC_MIN_FREQ);
+
+	host->mmc = &plat->mmc;
+	if (ret)
+		return ret;
+	host->mmc->priv = &prv->host;
+	host->mmc->dev = dev;
+	upriv->mmc = host->mmc;
+
+	return sdhci_probe(dev);
+}
+
+static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
+{
+	struct sdhci_host *host = dev_get_priv(dev);
+
+	host->name = dev->name;
+	host->ioaddr = dev_get_addr_ptr(dev);
+
+	return 0;
+}
+
+static int rockchip_sdhci_bind(struct udevice *dev)
+{
+	struct rockchip_sdhc_plat *plat = dev_get_platdata(dev);
+	int ret;
+
+	ret = sdhci_bind(dev, &plat->mmc, &plat->cfg);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct udevice_id arasan_sdhci_ids[] = {
+	{ .compatible = "arasan,sdhci-5.1" },
+	{ }
+};
+
+U_BOOT_DRIVER(arasan_sdhci_drv) = {
+	.name		= "arasan_sdhci",
+	.id		= UCLASS_MMC,
+	.of_match	= arasan_sdhci_ids,
+	.ofdata_to_platdata = arasan_sdhci_ofdata_to_platdata,
+	.ops		= &sdhci_ops,
+	.bind		= rockchip_sdhci_bind,
+	.probe		= arasan_sdhci_probe,
+	.priv_auto_alloc_size = sizeof(struct rockchip_sdhc),
+	.platdata_auto_alloc_size = sizeof(struct rockchip_sdhc_plat),
+};
diff --git a/drivers/mmc/s3c_sdi.c b/drivers/mmc/s3c_sdi.c
index 02d1138..1b8358a 100644
--- a/drivers/mmc/s3c_sdi.c
+++ b/drivers/mmc/s3c_sdi.c
@@ -133,7 +133,7 @@
 
 	if (!timeout) {
 		puts("S3C SDI: Command timed out!\n");
-		ret = TIMEOUT;
+		ret = -ETIMEDOUT;
 		goto error;
 	}
 
@@ -196,7 +196,7 @@
 
 	if (!timeout) {
 		puts("S3C SDI: Command timed out!\n");
-		ret = TIMEOUT;
+		ret = -ETIMEDOUT;
 		goto error;
 	}
 
diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c
index 44353c7..3bace21 100644
--- a/drivers/mmc/s5p_sdhci.c
+++ b/drivers/mmc/s5p_sdhci.c
@@ -68,7 +68,7 @@
 	host->name = S5P_NAME;
 
 	host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE |
-		SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_32BIT_DMA_ADDR |
+		SDHCI_QUIRK_32BIT_DMA_ADDR |
 		SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_USE_WIDE8;
 	host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
 	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c
index 7da059c..5f1333b 100644
--- a/drivers/mmc/sandbox_mmc.c
+++ b/drivers/mmc/sandbox_mmc.c
@@ -25,7 +25,7 @@
  * This emulate an SD card version 2. Single-block reads result in zero data.
  * Multiple-block reads return a test string.
  */
-static int sandbox_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 				struct mmc_data *data)
 {
 	switch (cmd->cmdidx) {
@@ -85,25 +85,20 @@
 	return 0;
 }
 
-static void sandbox_mmc_set_ios(struct mmc *mmc)
-{
-}
-
-static int sandbox_mmc_init(struct mmc *mmc)
+static int sandbox_mmc_set_ios(struct udevice *dev)
 {
 	return 0;
 }
 
-static int sandbox_mmc_getcd(struct mmc *mmc)
+static int sandbox_mmc_get_cd(struct udevice *dev)
 {
 	return 1;
 }
 
-static const struct mmc_ops sandbox_mmc_ops = {
+static const struct dm_mmc_ops sandbox_mmc_ops = {
 	.send_cmd = sandbox_mmc_send_cmd,
 	.set_ios = sandbox_mmc_set_ios,
-	.init = sandbox_mmc_init,
-	.getcd = sandbox_mmc_getcd,
+	.get_cd = sandbox_mmc_get_cd,
 };
 
 int sandbox_mmc_probe(struct udevice *dev)
@@ -120,7 +115,6 @@
 	int ret;
 
 	cfg->name = dev->name;
-	cfg->ops = &sandbox_mmc_ops;
 	cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_8BIT;
 	cfg->voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
 	cfg->f_min = 1000000;
@@ -150,6 +144,7 @@
 	.name		= "mmc_sandbox",
 	.id		= UCLASS_MMC,
 	.of_match	= sandbox_mmc_ids,
+	.ops		= &sandbox_mmc_ops,
 	.bind		= sandbox_mmc_bind,
 	.unbind		= sandbox_mmc_unbind,
 	.probe		= sandbox_mmc_probe,
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 604f18d..7ddb549 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -9,6 +9,7 @@
  */
 
 #include <common.h>
+#include <errno.h>
 #include <malloc.h>
 #include <mmc.h>
 #include <sdhci.h>
@@ -129,9 +130,17 @@
 #define CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT	100
 #define SDHCI_READ_STATUS_TIMEOUT		1000
 
+#ifdef CONFIG_DM_MMC_OPS
+static int sdhci_send_command(struct udevice *dev, struct mmc_cmd *cmd,
+			      struct mmc_data *data)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+#else
 static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
-		       struct mmc_data *data)
+			      struct mmc_data *data)
 {
+#endif
 	struct sdhci_host *host = mmc->priv;
 	unsigned int stat = 0;
 	int ret = 0;
@@ -161,7 +170,7 @@
 				       cmd_timeout);
 			} else {
 				puts("timeout.\n");
-				return COMM_ERR;
+				return -ECOMM;
 			}
 		}
 		time++;
@@ -175,7 +184,8 @@
 		flags = SDHCI_CMD_RESP_LONG;
 	else if (cmd->resp_type & MMC_RSP_BUSY) {
 		flags = SDHCI_CMD_RESP_SHORT_BUSY;
-		mask |= SDHCI_INT_DATA_END;
+		if (data)
+			mask |= SDHCI_INT_DATA_END;
 	} else
 		flags = SDHCI_CMD_RESP_SHORT;
 
@@ -243,17 +253,17 @@
 		stat = sdhci_readl(host, SDHCI_INT_STATUS);
 		if (stat & SDHCI_INT_ERROR)
 			break;
-	} while (((stat & mask) != mask) &&
-		 (get_timer(start) < SDHCI_READ_STATUS_TIMEOUT));
 
-	if (get_timer(start) >= SDHCI_READ_STATUS_TIMEOUT) {
-		if (host->quirks & SDHCI_QUIRK_BROKEN_R1B)
-			return 0;
-		else {
-			printf("%s: Timeout for status update!\n", __func__);
-			return TIMEOUT;
+		if (get_timer(start) >= SDHCI_READ_STATUS_TIMEOUT) {
+			if (host->quirks & SDHCI_QUIRK_BROKEN_R1B) {
+				return 0;
+			} else {
+				printf("%s: Timeout for status update!\n",
+				       __func__);
+				return -ETIMEDOUT;
+			}
 		}
-	}
+	} while ((stat & mask) != mask);
 
 	if ((stat & (SDHCI_INT_ERROR | mask)) == mask) {
 		sdhci_cmd_done(host, cmd);
@@ -279,9 +289,9 @@
 	sdhci_reset(host, SDHCI_RESET_CMD);
 	sdhci_reset(host, SDHCI_RESET_DATA);
 	if (stat & SDHCI_INT_TIMEOUT)
-		return TIMEOUT;
+		return -ETIMEDOUT;
 	else
-		return COMM_ERR;
+		return -ECOMM;
 }
 
 static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
@@ -304,7 +314,7 @@
 	}
 
 	reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-	reg &= ~SDHCI_CLOCK_CARD_EN;
+	reg &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_INT_EN);
 	sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
 
 	if (clock == 0)
@@ -389,8 +399,14 @@
 	sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
 }
 
+#ifdef CONFIG_DM_MMC_OPS
+static int sdhci_set_ios(struct udevice *dev)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
 static void sdhci_set_ios(struct mmc *mmc)
 {
+#endif
 	u32 ctrl;
 	struct sdhci_host *host = mmc->priv;
 
@@ -426,6 +442,9 @@
 		ctrl &= ~SDHCI_CTRL_HISPD;
 
 	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+#ifdef CONFIG_DM_MMC_OPS
+	return 0;
+#endif
 }
 
 static int sdhci_init(struct mmc *mmc)
@@ -472,80 +491,109 @@
 	return 0;
 }
 
+#ifdef CONFIG_DM_MMC_OPS
+int sdhci_probe(struct udevice *dev)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
 
+	return sdhci_init(mmc);
+}
+
+const struct dm_mmc_ops sdhci_ops = {
+	.send_cmd	= sdhci_send_command,
+	.set_ios	= sdhci_set_ios,
+};
+#else
 static const struct mmc_ops sdhci_ops = {
 	.send_cmd	= sdhci_send_command,
 	.set_ios	= sdhci_set_ios,
 	.init		= sdhci_init,
 };
+#endif
 
-int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
+int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
+		u32 max_clk, u32 min_clk)
 {
-	unsigned int caps;
-
-	host->cfg.name = host->name;
-	host->cfg.ops = &sdhci_ops;
+	u32 caps;
 
 	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
-#ifdef CONFIG_MMC_SDMA
-	if (!(caps & SDHCI_CAN_DO_SDMA)) {
-		printf("%s: Your controller doesn't support SDMA!!\n",
-		       __func__);
-		return -1;
-	}
-#endif
+	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
 
+	cfg->name = host->name;
+#ifndef CONFIG_DM_MMC_OPS
+	cfg->ops = &sdhci_ops;
+#endif
 	if (max_clk)
-		host->cfg.f_max = max_clk;
+		cfg->f_max = max_clk;
 	else {
 		if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
-			host->cfg.f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK)
-				>> SDHCI_CLOCK_BASE_SHIFT;
+			cfg->f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK) >>
+				SDHCI_CLOCK_BASE_SHIFT;
 		else
-			host->cfg.f_max = (caps & SDHCI_CLOCK_BASE_MASK)
-				>> SDHCI_CLOCK_BASE_SHIFT;
-		host->cfg.f_max *= 1000000;
-	}
-	if (host->cfg.f_max == 0) {
-		printf("%s: Hardware doesn't specify base clock frequency\n",
-		       __func__);
-		return -1;
+			cfg->f_max = (caps & SDHCI_CLOCK_BASE_MASK) >>
+				SDHCI_CLOCK_BASE_SHIFT;
+		cfg->f_max *= 1000000;
 	}
+	if (cfg->f_max == 0)
+		return -EINVAL;
 	if (min_clk)
-		host->cfg.f_min = min_clk;
+		cfg->f_min = min_clk;
 	else {
 		if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
-			host->cfg.f_min = host->cfg.f_max /
-				SDHCI_MAX_DIV_SPEC_300;
+			cfg->f_min = cfg->f_max / SDHCI_MAX_DIV_SPEC_300;
 		else
-			host->cfg.f_min = host->cfg.f_max /
-				SDHCI_MAX_DIV_SPEC_200;
+			cfg->f_min = cfg->f_max / SDHCI_MAX_DIV_SPEC_200;
 	}
-
-	host->cfg.voltages = 0;
+	cfg->voltages = 0;
 	if (caps & SDHCI_CAN_VDD_330)
-		host->cfg.voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
+		cfg->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
 	if (caps & SDHCI_CAN_VDD_300)
-		host->cfg.voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
+		cfg->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
 	if (caps & SDHCI_CAN_VDD_180)
-		host->cfg.voltages |= MMC_VDD_165_195;
-
-	if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
-		host->cfg.voltages |= host->voltages;
+		cfg->voltages |= MMC_VDD_165_195;
 
-	host->cfg.host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
+	cfg->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
 	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
 		if (caps & SDHCI_CAN_DO_8BIT)
-			host->cfg.host_caps |= MMC_MODE_8BIT;
+			cfg->host_caps |= MMC_MODE_8BIT;
 	}
 
-	if (host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)
-		host->cfg.host_caps &= ~(MMC_MODE_HS | MMC_MODE_HS_52MHz);
-
 	if (host->host_caps)
-		host->cfg.host_caps |= host->host_caps;
+		cfg->host_caps |= host->host_caps;
+
+
+	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
-	host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+	return 0;
+}
+
+#ifdef CONFIG_BLK
+int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg)
+{
+	return mmc_bind(dev, mmc, cfg);
+}
+#else
+int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
+{
+#ifdef CONFIG_MMC_SDMA
+	unsigned int caps;
+
+	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+	if (!(caps & SDHCI_CAN_DO_SDMA)) {
+		printf("%s: Your controller doesn't support SDMA!!\n",
+		       __func__);
+		return -1;
+	}
+#endif
+
+	if (sdhci_setup_cfg(&host->cfg, host, max_clk, min_clk)) {
+		printf("%s: Hardware doesn't specify base clock frequency\n",
+		       __func__);
+		return -EINVAL;
+	}
+
+	if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
+		host->cfg.voltages |= host->voltages;
 
 	sdhci_reset(host, SDHCI_RESET_ALL);
 
@@ -557,3 +605,4 @@
 
 	return 0;
 }
+#endif
diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c
index 001bf18..bc4b344 100644
--- a/drivers/mmc/sh_mmcif.c
+++ b/drivers/mmc/sh_mmcif.c
@@ -168,7 +168,7 @@
 	if (state2 & STS2_CRC_ERR)
 		ret = -EILSEQ;
 	else if (state2 & STS2_TIMEOUT_ERR)
-		ret = TIMEOUT;
+		ret = -ETIMEDOUT;
 	else
 		ret = -EILSEQ;
 	return ret;
@@ -483,7 +483,7 @@
 		case MMC_CMD_ALL_SEND_CID:
 		case MMC_CMD_SELECT_CARD:
 		case MMC_CMD_APP_CMD:
-			ret = TIMEOUT;
+			ret = -ETIMEDOUT;
 			break;
 		default:
 			printf(DRIVER_NAME": Cmd(d'%d) err\n", cmd->cmdidx);
@@ -520,14 +520,14 @@
 
 	switch (cmd->cmdidx) {
 	case MMC_CMD_APP_CMD:
-		return TIMEOUT;
+		return -ETIMEDOUT;
 	case MMC_CMD_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */
 		if (data)
 			/* ext_csd */
 			break;
 		else
 			/* send_if_cond cmd (not support) */
-			return TIMEOUT;
+			return -ETIMEDOUT;
 	default:
 		break;
 	}
diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c
index e9d99a2..ea82e2b 100644
--- a/drivers/mmc/sh_sdhi.c
+++ b/drivers/mmc/sh_sdhi.c
@@ -232,7 +232,7 @@
 	e_state2 = sh_sdhi_readw(host, SDHI_ERR_STS2);
 	if (e_state2 & ERR_STS2_SYS_ERROR) {
 		if (e_state2 & ERR_STS2_RES_STOP_TIMEOUT)
-			ret = TIMEOUT;
+			ret = -ETIMEDOUT;
 		else
 			ret = -EILSEQ;
 		debug("%s: ERR_STS2 = %04x\n",
@@ -246,7 +246,7 @@
 	if (e_state1 & ERR_STS1_CRC_ERROR || e_state1 & ERR_STS1_CMD_ERROR)
 		ret = -EILSEQ;
 	else
-		ret = TIMEOUT;
+		ret = -ETIMEDOUT;
 
 	debug("%s: ERR_STS1 = %04x\n",
 	      DRIVER_NAME, sh_sdhi_readw(host, SDHI_ERR_STS1));
@@ -567,7 +567,7 @@
 		case MMC_CMD_SELECT_CARD:
 		case SD_CMD_SEND_IF_COND:
 		case MMC_CMD_APP_CMD:
-			ret = TIMEOUT;
+			ret = -ETIMEDOUT;
 			break;
 		default:
 			debug(DRIVER_NAME": Cmd(d'%d) err\n", opc);
diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c
index 6a0e971..8a96302 100644
--- a/drivers/mmc/socfpga_dw_mmc.c
+++ b/drivers/mmc/socfpga_dw_mmc.c
@@ -22,6 +22,11 @@
 static const struct socfpga_system_manager *system_manager_base =
 		(void *)SOCFPGA_SYSMGR_ADDRESS;
 
+struct socfpga_dwmci_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
 /* socfpga implmentation specific driver private data */
 struct dwmci_socfpga_priv_data {
 	struct dwmci_host	host;
@@ -98,21 +103,45 @@
 
 static int socfpga_dwmmc_probe(struct udevice *dev)
 {
+#ifdef CONFIG_BLK
+	struct socfpga_dwmci_plat *plat = dev_get_platdata(dev);
+#endif
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
 	struct dwmci_socfpga_priv_data *priv = dev_get_priv(dev);
 	struct dwmci_host *host = &priv->host;
+
+#ifdef CONFIG_BLK
+	dwmci_setup_cfg(&plat->cfg, dev->name, host->buswidth, host->caps,
+			host->bus_hz, 400000);
+	host->mmc = &plat->mmc;
+#else
 	int ret;
 
 	ret = add_dwmci(host, host->bus_hz, 400000);
 	if (ret)
 		return ret;
-
+#endif
+	host->mmc->priv = &priv->host;
 	upriv->mmc = host->mmc;
 	host->mmc->dev = dev;
 
 	return 0;
 }
 
+static int socfpga_dwmmc_bind(struct udevice *dev)
+{
+#ifdef CONFIG_BLK
+	struct socfpga_dwmci_plat *plat = dev_get_platdata(dev);
+	int ret;
+
+	ret = dwmci_bind(dev, &plat->mmc, &plat->cfg);
+	if (ret)
+		return ret;
+#endif
+
+	return 0;
+}
+
 static const struct udevice_id socfpga_dwmmc_ids[] = {
 	{ .compatible = "altr,socfpga-dw-mshc" },
 	{ }
@@ -123,6 +152,7 @@
 	.id		= UCLASS_MMC,
 	.of_match	= socfpga_dwmmc_ids,
 	.ofdata_to_platdata = socfpga_dwmmc_ofdata_to_platdata,
+	.bind		= socfpga_dwmmc_bind,
 	.probe		= socfpga_dwmmc_probe,
 	.priv_auto_alloc_size = sizeof(struct dwmci_socfpga_priv_data),
 };
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index ce2dc4a..6953acc 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -269,18 +269,18 @@
 	unsigned i;
 	unsigned *buff = (unsigned int *)(reading ? data->dest : data->src);
 	unsigned byte_cnt = data->blocksize * data->blocks;
-	unsigned timeout_msecs = byte_cnt >> 8;
-	if (timeout_msecs < 2000)
-		timeout_msecs = 2000;
+	unsigned timeout_usecs = (byte_cnt >> 8) * 1000;
+	if (timeout_usecs < 2000000)
+		timeout_usecs = 2000000;
 
 	/* Always read / write data through the CPU */
 	setbits_le32(&mmchost->reg->gctrl, SUNXI_MMC_GCTRL_ACCESS_BY_AHB);
 
 	for (i = 0; i < (byte_cnt >> 2); i++) {
 		while (readl(&mmchost->reg->status) & status_bit) {
-			if (!timeout_msecs--)
+			if (!timeout_usecs--)
 				return -1;
-			udelay(1000);
+			udelay(1);
 		}
 
 		if (reading)
@@ -304,7 +304,7 @@
 		    (status & SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT)) {
 			debug("%s timeout %x\n", what,
 			      status & SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT);
-			return TIMEOUT;
+			return -ETIMEDOUT;
 		}
 		udelay(1000);
 	} while (!(status & done_bit));
@@ -375,7 +375,7 @@
 		if (ret) {
 			error = readl(&mmchost->reg->rint) & \
 				SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT;
-			error = TIMEOUT;
+			error = -ETIMEDOUT;
 			goto out;
 		}
 	}
@@ -402,7 +402,7 @@
 			status = readl(&mmchost->reg->status);
 			if (!timeout_msecs--) {
 				debug("busy timeout\n");
-				error = TIMEOUT;
+				error = -ETIMEDOUT;
 				goto out;
 			}
 			udelay(1000);
@@ -445,23 +445,6 @@
 	return !gpio_get_value(cd_pin);
 }
 
-int sunxi_mmc_has_egon_boot_signature(struct mmc *mmc)
-{
-	char *buf = malloc(512);
-	int valid_signature = 0;
-
-	if (buf == NULL)
-		panic("Failed to allocate memory\n");
-
-	if (mmc_getcd(mmc) && mmc_init(mmc) == 0 &&
-	    mmc->block_dev.block_read(&mmc->block_dev, 16, 1, buf) == 1 &&
-	    strncmp(&buf[4], "eGON.BT0", 8) == 0)
-		valid_signature = 1;
-
-	free(buf);
-	return valid_signature;
-}
-
 static const struct mmc_ops sunxi_mmc_ops = {
 	.send_cmd	= sunxi_mmc_send_cmd,
 	.set_ios	= sunxi_mmc_set_ios,
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index c9d9432..f0a39a6 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -9,6 +9,8 @@
 
 #include <bouncebuf.h>
 #include <common.h>
+#include <dm/device.h>
+#include <errno.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
 #ifndef CONFIG_TEGRA186
@@ -19,6 +21,15 @@
 #include <asm/arch-tegra/tegra_mmc.h>
 #include <mmc.h>
 
+/*
+ * FIXME: TODO: This driver contains a number of ifdef CONFIG_TEGRA186 that
+ * should not be present. These are needed because newer Tegra SoCs support
+ * only the standard clock/reset APIs, whereas older Tegra SoCs support only
+ * a custom Tegra-specific API. ASAP the older Tegra SoCs' code should be
+ * fixed to implement the standard APIs, and all drivers converted to solely
+ * use the new standard APIs, with no ifdefs.
+ */
+
 DECLARE_GLOBAL_DATA_PTR;
 
 struct mmc_host mmc_host[CONFIG_SYS_MMC_MAX_DEVICE];
@@ -216,14 +227,14 @@
 	if (i == retry) {
 		printf("%s: waiting for status update\n", __func__);
 		writel(mask, &host->reg->norintsts);
-		return TIMEOUT;
+		return -ETIMEDOUT;
 	}
 
 	if (mask & TEGRA_MMC_NORINTSTS_CMD_TIMEOUT) {
 		/* Timeout Error */
 		debug("timeout: %08x cmd %d\n", mask, cmd->cmdidx);
 		writel(mask, &host->reg->norintsts);
-		return TIMEOUT;
+		return -ETIMEDOUT;
 	} else if (mask & TEGRA_MMC_NORINTSTS_ERR_INTERRUPT) {
 		/* Error Interrupt */
 		debug("error: %08x cmd %d\n", mask, cmd->cmdidx);
@@ -257,7 +268,7 @@
 			if (i == retry) {
 				printf("%s: card is still busy\n", __func__);
 				writel(mask, &host->reg->norintsts);
-				return TIMEOUT;
+				return -ETIMEDOUT;
 			}
 
 			cmd->response[0] = readl(&host->reg->rspreg0);
@@ -359,11 +370,14 @@
 	 */
 	if (clock == 0)
 		goto out;
-#ifndef CONFIG_TEGRA186
+#ifdef CONFIG_TEGRA186
+	{
+		ulong rate = clk_set_rate(&host->clk, clock);
+		div = (rate + clock - 1) / clock;
+	}
+#else
 	clock_adjust_periph_pll_div(host->mmc_id, CLOCK_ID_PERIPH, clock,
 				    &div);
-#else
-	div = (20000000 + clock - 1) / clock;
 #endif
 	debug("div = %d\n", div);
 
@@ -538,6 +552,9 @@
 {
 	struct mmc_host *host;
 	struct mmc *mmc;
+#ifdef CONFIG_TEGRA186
+	int ret;
+#endif
 
 	/* DT should have been read & host config filled in */
 	host = &mmc_host[dev_index];
@@ -549,7 +566,21 @@
 	      gpio_get_number(&host->cd_gpio));
 
 	host->clock = 0;
-#ifndef CONFIG_TEGRA186
+
+#ifdef CONFIG_TEGRA186
+	ret = reset_assert(&host->reset_ctl);
+	if (ret)
+		return ret;
+	ret = clk_enable(&host->clk);
+	if (ret)
+		return ret;
+	ret = clk_set_rate(&host->clk, 20000000);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+	ret = reset_deassert(&host->reset_ctl);
+	if (ret)
+		return ret;
+#else
 	clock_start_periph_pll(host->mmc_id, CLOCK_ID_PERIPH, 20000000);
 #endif
 
@@ -576,11 +607,7 @@
 	 *  (actually 52MHz)
 	 */
 	host->cfg.f_min = 375000;
-#ifndef CONFIG_TEGRA186
 	host->cfg.f_max = 48000000;
-#else
-	host->cfg.f_max = 375000;
-#endif
 
 	host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
@@ -612,7 +639,27 @@
 		return -FDT_ERR_NOTFOUND;
 	}
 
-#ifndef CONFIG_TEGRA186
+#ifdef CONFIG_TEGRA186
+	{
+		/*
+		 * FIXME: This variable should go away when the MMC device
+		 * actually is a udevice.
+		 */
+		struct udevice dev;
+		int ret;
+		dev.of_offset = node;
+		ret = reset_get_by_name(&dev, "sdmmc", &host->reset_ctl);
+		if (ret) {
+			debug("reset_get_by_index() failed: %d\n", ret);
+			return ret;
+		}
+		ret = clk_get_by_name(&dev, "sdmmc", &host->clk);
+		if (ret) {
+			debug("clk_get_by_index() failed: %d\n", ret);
+			return ret;
+		}
+	}
+#else
 	host->mmc_id = clock_decode_periph_id(blob, node);
 	if (host->mmc_id == PERIPH_ID_NONE) {
 		debug("%s: could not decode periph id\n", __func__);
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c
index 152e987..2a48378 100644
--- a/drivers/mmc/uniphier-sd.c
+++ b/drivers/mmc/uniphier-sd.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -7,7 +8,6 @@
 #include <common.h>
 #include <clk.h>
 #include <fdtdec.h>
-#include <mapmem.h>
 #include <mmc.h>
 #include <dm/device.h>
 #include <linux/compat.h>
@@ -162,7 +162,7 @@
 		 * display error log since this might be a part of sequence to
 		 * distinguish between SD and MMC.
 		 */
-		return TIMEOUT;
+		return -ETIMEDOUT;
 	}
 
 	if (info2 & UNIPHIER_SD_INFO2_ERR_TO) {
@@ -660,7 +660,7 @@
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
-	priv->regbase = map_sysmem(base, SZ_2K);
+	priv->regbase = devm_ioremap(dev, base, SZ_2K);
 	if (!priv->regbase)
 		return -ENOMEM;
 
@@ -735,7 +735,6 @@
 {
 	struct uniphier_sd_priv *priv = dev_get_priv(dev);
 
-	unmap_sysmem(priv->regbase);
 	mmc_destroy(priv->mmc);
 
 	return 0;
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index d405929..3815b94 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -17,10 +17,17 @@
 # define CONFIG_ZYNQ_SDHCI_MIN_FREQ	0
 #endif
 
+struct arasan_sdhci_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
 static int arasan_sdhci_probe(struct udevice *dev)
 {
+	struct 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);
+	int ret;
 
 	host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD |
 		       SDHCI_QUIRK_BROKEN_R1B;
@@ -31,13 +38,16 @@
 
 	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
 
-	add_sdhci(host, CONFIG_ZYNQ_SDHCI_MAX_FREQ,
-		  CONFIG_ZYNQ_SDHCI_MIN_FREQ);
-
-	upriv->mmc = host->mmc;
+	ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ZYNQ_SDHCI_MAX_FREQ,
+			      CONFIG_ZYNQ_SDHCI_MIN_FREQ);
+	host->mmc = &plat->mmc;
+	if (ret)
+		return ret;
+	host->mmc->priv = host;
 	host->mmc->dev = dev;
+	upriv->mmc = host->mmc;
 
-	return 0;
+	return sdhci_probe(dev);
 }
 
 static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
@@ -50,6 +60,18 @@
 	return 0;
 }
 
+static int arasan_sdhci_bind(struct udevice *dev)
+{
+	struct arasan_sdhci_plat *plat = dev_get_platdata(dev);
+	int ret;
+
+	ret = sdhci_bind(dev, &plat->mmc, &plat->cfg);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static const struct udevice_id arasan_sdhci_ids[] = {
 	{ .compatible = "arasan,sdhci-8.9a" },
 	{ }
@@ -60,6 +82,9 @@
 	.id		= UCLASS_MMC,
 	.of_match	= arasan_sdhci_ids,
 	.ofdata_to_platdata = arasan_sdhci_ofdata_to_platdata,
+	.ops		= &sdhci_ops,
+	.bind		= arasan_sdhci_bind,
 	.probe		= arasan_sdhci_probe,
 	.priv_auto_alloc_size = sizeof(struct sdhci_host),
+	.platdata_auto_alloc_size = sizeof(struct arasan_sdhci_plat),
 };
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index 8ccaff0..33c4a93 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -608,7 +608,7 @@
 	case CFI_CMDSET_INTEL_EXTENDED:
 	case CFI_CMDSET_INTEL_STANDARD:
 		if ((retcode == ERR_OK)
-		    && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) {
+		    && !flash_isset(info, sector, 0, FLASH_STATUS_DONE)) {
 			retcode = ERR_INVAL;
 			printf ("Flash %s error at address %lx\n", prompt,
 				info->start[sector]);
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 8c46a2f..5ce7d6d 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -64,12 +64,14 @@
 	  PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2).
 
 config NAND_SUNXI
-	bool "Support for NAND on Allwinner SoCs in SPL"
+	bool "Support for NAND on Allwinner SoCs"
 	depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
 	select SYS_NAND_SELF_INIT
 	---help---
-	Enable support for NAND. This option allows SPL to read from
-	sunxi NAND using DMA transfers.
+	Enable support for NAND. This option enables the standard and
+	SPL drivers.
+	The SPL driver only supports reading from the NAND using DMA
+	transfers.
 
 config NAND_ARASAN
 	bool "Configure Arasan Nand"
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 837d397..1df9273 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -66,6 +66,7 @@
 obj-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
 obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o
 obj-$(CONFIG_NAND_PLAT) += nand_plat.o
+obj-$(CONFIG_NAND_SUNXI) += sunxi_nand.o
 
 else  # minimal SPL drivers
 
diff --git a/drivers/mtd/nand/fsl_ifc_spl.c b/drivers/mtd/nand/fsl_ifc_spl.c
index cbeb74a..4e49a4e 100644
--- a/drivers/mtd/nand/fsl_ifc_spl.c
+++ b/drivers/mtd/nand/fsl_ifc_spl.c
@@ -11,6 +11,9 @@
 #include <asm/io.h>
 #include <fsl_ifc.h>
 #include <linux/mtd/nand.h>
+#ifdef CONFIG_CHAIN_OF_TRUST
+#include <fsl_validate.h>
+#endif
 
 static inline int is_blank(uchar *addr, int page_size)
 {
@@ -268,6 +271,27 @@
 	 */
 	flush_cache(CONFIG_SYS_NAND_U_BOOT_DST, CONFIG_SYS_NAND_U_BOOT_SIZE);
 #endif
+
+#ifdef CONFIG_CHAIN_OF_TRUST
+	/*
+	 * U-Boot header is appended at end of U-boot image, so
+	 * calculate U-boot header address using U-boot header size.
+	 */
+#define CONFIG_U_BOOT_HDR_ADDR \
+		((CONFIG_SYS_NAND_U_BOOT_START + \
+		  CONFIG_SYS_NAND_U_BOOT_SIZE) - \
+		 CONFIG_U_BOOT_HDR_SIZE)
+	spl_validate_uboot(CONFIG_U_BOOT_HDR_ADDR,
+			   CONFIG_SYS_NAND_U_BOOT_START);
+	/*
+	 * In case of failure in validation, spl_validate_uboot would
+	 * not return back in case of Production environment with ITS=1.
+	 * Thus U-Boot will not start.
+	 * In Development environment (ITS=0 and SB_EN=1), the function
+	 * may return back in case of non-fatal failures.
+	 */
+#endif
+
 	uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
 	uboot();
 }
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
index c90a3a7..94fc5c1 100644
--- a/drivers/mtd/nand/mxs_nand.c
+++ b/drivers/mtd/nand/mxs_nand.c
@@ -976,7 +976,7 @@
  * counted, so we know the physical geometry. This enables us to make some
  * important configuration decisions.
  *
- * The return value of this function propogates directly back to this driver's
+ * The return value of this function propagates directly back to this driver's
  * call to nand_scan(). Anything other than zero will cause this driver to
  * tear everything down and declare failure.
  */
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 6897167..d1287bc 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -29,6 +29,9 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <common.h>
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+#include <fdtdec.h>
+#endif
 #include <malloc.h>
 #include <watchdog.h>
 #include <linux/err.h>
@@ -2411,7 +2414,7 @@
 		int cached = writelen > bytes && page != blockmask;
 		uint8_t *wbuf = buf;
 		int use_bufpoi;
-		int part_pagewr = (column || writelen < (mtd->writesize - 1));
+		int part_pagewr = (column || writelen < mtd->writesize);
 
 		if (part_pagewr)
 			use_bufpoi = 1;
@@ -3763,6 +3766,66 @@
 	return type;
 }
 
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+DECLARE_GLOBAL_DATA_PTR;
+
+static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, int node)
+{
+	int ret, ecc_mode = -1, ecc_strength, ecc_step;
+	const void *blob = gd->fdt_blob;
+	const char *str;
+
+	ret = fdtdec_get_int(blob, node, "nand-bus-width", -1);
+	if (ret == 16)
+		chip->options |= NAND_BUSWIDTH_16;
+
+	if (fdtdec_get_bool(blob, node, "nand-on-flash-bbt"))
+		chip->bbt_options |= NAND_BBT_USE_FLASH;
+
+	str = fdt_getprop(blob, node, "nand-ecc-mode", NULL);
+	if (str) {
+		if (!strcmp(str, "none"))
+			ecc_mode = NAND_ECC_NONE;
+		else if (!strcmp(str, "soft"))
+			ecc_mode = NAND_ECC_SOFT;
+		else if (!strcmp(str, "hw"))
+			ecc_mode = NAND_ECC_HW;
+		else if (!strcmp(str, "hw_syndrome"))
+			ecc_mode = NAND_ECC_HW_SYNDROME;
+		else if (!strcmp(str, "hw_oob_first"))
+			ecc_mode = NAND_ECC_HW_OOB_FIRST;
+		else if (!strcmp(str, "soft_bch"))
+			ecc_mode = NAND_ECC_SOFT_BCH;
+	}
+
+
+	ecc_strength = fdtdec_get_int(blob, node, "nand-ecc-strength", -1);
+	ecc_step = fdtdec_get_int(blob, node, "nand-ecc-step-size", -1);
+
+	if ((ecc_step >= 0 && !(ecc_strength >= 0)) ||
+	    (!(ecc_step >= 0) && ecc_strength >= 0)) {
+		pr_err("must set both strength and step size in DT\n");
+		return -EINVAL;
+	}
+
+	if (ecc_mode >= 0)
+		chip->ecc.mode = ecc_mode;
+
+	if (ecc_strength >= 0)
+		chip->ecc.strength = ecc_strength;
+
+	if (ecc_step > 0)
+		chip->ecc.size = ecc_step;
+
+	return 0;
+}
+#else
+static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, int node)
+{
+	return 0;
+}
+#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
+
 /**
  * nand_scan_ident - [NAND Interface] Scan for the NAND device
  * @mtd: MTD device structure
@@ -3779,6 +3842,13 @@
 	int i, nand_maf_id, nand_dev_id;
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct nand_flash_dev *type;
+	int ret;
+
+	if (chip->flash_node) {
+		ret = nand_dt_init(mtd, chip, chip->flash_node);
+		if (ret)
+			return ret;
+	}
 
 	/* Set the default functions */
 	nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16);
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index 561d2cd..ce0a14e 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -62,6 +62,10 @@
 		{ .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} },
 		  SZ_8K, SZ_8K, SZ_2M, NAND_NEED_SCRAMBLING, 6, 640,
 		  NAND_ECC_INFO(40, SZ_1K), 4 },
+	{"H27QCG8T2E5R‐BCF 64G 3.3V 8-bit",
+		{ .id = {0xad, 0xde, 0x14, 0xa7, 0x42, 0x4a} },
+		  SZ_16K, SZ_8K, SZ_4M, NAND_NEED_SCRAMBLING, 6, 1664,
+		  NAND_ECC_INFO(56, SZ_1K), 1 },
 
 	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),
 	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),
diff --git a/drivers/mtd/nand/nand_spl_simple.c b/drivers/mtd/nand/nand_spl_simple.c
index 60a7607..55f48d3 100644
--- a/drivers/mtd/nand/nand_spl_simple.c
+++ b/drivers/mtd/nand/nand_spl_simple.c
@@ -209,6 +209,68 @@
 }
 #endif
 
+#ifdef CONFIG_SPL_UBI
+/*
+ * Temporary storage for non NAND page aligned and non NAND page sized
+ * reads. Note: This does not support runtime detected FLASH yet, but
+ * that should be reasonably easy to fix by making the buffer large
+ * enough :)
+ */
+static u8 scratch_buf[CONFIG_SYS_NAND_PAGE_SIZE];
+
+/**
+ * nand_spl_read_block - Read data from physical eraseblock into a buffer
+ * @block:	Number of the physical eraseblock
+ * @offset:	Data offset from the start of @peb
+ * @len:	Data size to read
+ * @dst:	Address of the destination buffer
+ *
+ * This could be further optimized if we'd have a subpage read
+ * function in the simple code. On NAND which allows subpage reads
+ * this would spare quite some time to readout e.g. the VID header of
+ * UBI.
+ *
+ * Notes:
+ *	@offset + @len are not allowed to be larger than a physical
+ *	erase block. No sanity check done for simplicity reasons.
+ *
+ * To support runtime detected flash this needs to be extended by
+ * information about the actual flash geometry, but thats beyond the
+ * scope of this effort and for most applications where fast boot is
+ * required it is not an issue anyway.
+ */
+int nand_spl_read_block(int block, int offset, int len, void *dst)
+{
+	int page, read;
+
+	/* Calculate the page number */
+	page = offset / CONFIG_SYS_NAND_PAGE_SIZE;
+
+	/* Offset to the start of a flash page */
+	offset = offset % CONFIG_SYS_NAND_PAGE_SIZE;
+
+	while (len) {
+		/*
+		 * Non page aligned reads go to the scratch buffer.
+		 * Page aligned reads go directly to the destination.
+		 */
+		if (offset || len < CONFIG_SYS_NAND_PAGE_SIZE) {
+			nand_read_page(block, page, scratch_buf);
+			read = min(len, CONFIG_SYS_NAND_PAGE_SIZE - offset);
+			memcpy(dst, scratch_buf + offset, read);
+			offset = 0;
+		} else {
+			nand_read_page(block, page, dst);
+			read = CONFIG_SYS_NAND_PAGE_SIZE;
+		}
+		page++;
+		len -= read;
+		dst += read;
+	}
+	return 0;
+}
+#endif
+
 int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
 {
 	unsigned int block, lastblock;
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index 67f293d..6e201d6 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -264,7 +264,8 @@
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct omap_nand_info *info = nand_get_controller_data(chip);
-	uint32_t *ptr, val = 0;
+	const uint32_t *ptr;
+	uint32_t val = 0;
 	int8_t i = 0, j;
 
 	switch (info->ecc_scheme) {
diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c
new file mode 100644
index 0000000..c4e2cd7
--- /dev/null
+++ b/drivers/mtd/nand/sunxi_nand.c
@@ -0,0 +1,1845 @@
+/*
+ * Copyright (C) 2013 Boris BREZILLON <b.brezillon.dev@gmail.com>
+ * Copyright (C) 2015 Roy Spliet <r.spliet@ultimaker.com>
+ *
+ * Derived from:
+ *	https://github.com/yuq/sunxi-nfc-mtd
+ *	Copyright (C) 2013 Qiang Yu <yuq825@gmail.com>
+ *
+ *	https://github.com/hno/Allwinner-Info
+ *	Copyright (C) 2013 Henrik Nordström <Henrik Nordström>
+ *
+ *	Copyright (C) 2013 Dmitriy B. <rzk333@gmail.com>
+ *	Copyright (C) 2013 Sergey Lapin <slapin@ossfans.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <memalign.h>
+#include <nand.h>
+
+#include <linux/kernel.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/io.h>
+
+#include <asm/gpio.h>
+#include <asm/arch/clock.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define NFC_REG_CTL		0x0000
+#define NFC_REG_ST		0x0004
+#define NFC_REG_INT		0x0008
+#define NFC_REG_TIMING_CTL	0x000C
+#define NFC_REG_TIMING_CFG	0x0010
+#define NFC_REG_ADDR_LOW	0x0014
+#define NFC_REG_ADDR_HIGH	0x0018
+#define NFC_REG_SECTOR_NUM	0x001C
+#define NFC_REG_CNT		0x0020
+#define NFC_REG_CMD		0x0024
+#define NFC_REG_RCMD_SET	0x0028
+#define NFC_REG_WCMD_SET	0x002C
+#define NFC_REG_IO_DATA		0x0030
+#define NFC_REG_ECC_CTL		0x0034
+#define NFC_REG_ECC_ST		0x0038
+#define NFC_REG_DEBUG		0x003C
+#define NFC_REG_ECC_ERR_CNT(x)	((0x0040 + (x)) & ~0x3)
+#define NFC_REG_USER_DATA(x)	(0x0050 + ((x) * 4))
+#define NFC_REG_SPARE_AREA	0x00A0
+#define NFC_REG_PAT_ID		0x00A4
+#define NFC_RAM0_BASE		0x0400
+#define NFC_RAM1_BASE		0x0800
+
+/* define bit use in NFC_CTL */
+#define NFC_EN			BIT(0)
+#define NFC_RESET		BIT(1)
+#define NFC_BUS_WIDTH_MSK	BIT(2)
+#define NFC_BUS_WIDTH_8		(0 << 2)
+#define NFC_BUS_WIDTH_16	(1 << 2)
+#define NFC_RB_SEL_MSK		BIT(3)
+#define NFC_RB_SEL(x)		((x) << 3)
+#define NFC_CE_SEL_MSK		(0x7 << 24)
+#define NFC_CE_SEL(x)		((x) << 24)
+#define NFC_CE_CTL		BIT(6)
+#define NFC_PAGE_SHIFT_MSK	(0xf << 8)
+#define NFC_PAGE_SHIFT(x)	(((x) < 10 ? 0 : (x) - 10) << 8)
+#define NFC_SAM			BIT(12)
+#define NFC_RAM_METHOD		BIT(14)
+#define NFC_DEBUG_CTL		BIT(31)
+
+/* define bit use in NFC_ST */
+#define NFC_RB_B2R		BIT(0)
+#define NFC_CMD_INT_FLAG	BIT(1)
+#define NFC_DMA_INT_FLAG	BIT(2)
+#define NFC_CMD_FIFO_STATUS	BIT(3)
+#define NFC_STA			BIT(4)
+#define NFC_NATCH_INT_FLAG	BIT(5)
+#define NFC_RB_STATE(x)		BIT(x + 8)
+
+/* define bit use in NFC_INT */
+#define NFC_B2R_INT_ENABLE	BIT(0)
+#define NFC_CMD_INT_ENABLE	BIT(1)
+#define NFC_DMA_INT_ENABLE	BIT(2)
+#define NFC_INT_MASK		(NFC_B2R_INT_ENABLE | \
+				 NFC_CMD_INT_ENABLE | \
+				 NFC_DMA_INT_ENABLE)
+
+/* define bit use in NFC_TIMING_CTL */
+#define NFC_TIMING_CTL_EDO	BIT(8)
+
+/* define NFC_TIMING_CFG register layout */
+#define NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD)		\
+	(((tWB) & 0x3) | (((tADL) & 0x3) << 2) |		\
+	(((tWHR) & 0x3) << 4) | (((tRHW) & 0x3) << 6) |		\
+	(((tCAD) & 0x7) << 8))
+
+/* define bit use in NFC_CMD */
+#define NFC_CMD_LOW_BYTE_MSK	0xff
+#define NFC_CMD_HIGH_BYTE_MSK	(0xff << 8)
+#define NFC_CMD(x)		(x)
+#define NFC_ADR_NUM_MSK		(0x7 << 16)
+#define NFC_ADR_NUM(x)		(((x) - 1) << 16)
+#define NFC_SEND_ADR		BIT(19)
+#define NFC_ACCESS_DIR		BIT(20)
+#define NFC_DATA_TRANS		BIT(21)
+#define NFC_SEND_CMD1		BIT(22)
+#define NFC_WAIT_FLAG		BIT(23)
+#define NFC_SEND_CMD2		BIT(24)
+#define NFC_SEQ			BIT(25)
+#define NFC_DATA_SWAP_METHOD	BIT(26)
+#define NFC_ROW_AUTO_INC	BIT(27)
+#define NFC_SEND_CMD3		BIT(28)
+#define NFC_SEND_CMD4		BIT(29)
+#define NFC_CMD_TYPE_MSK	(0x3 << 30)
+#define NFC_NORMAL_OP		(0 << 30)
+#define NFC_ECC_OP		(1 << 30)
+#define NFC_PAGE_OP		(2 << 30)
+
+/* define bit use in NFC_RCMD_SET */
+#define NFC_READ_CMD_MSK	0xff
+#define NFC_RND_READ_CMD0_MSK	(0xff << 8)
+#define NFC_RND_READ_CMD1_MSK	(0xff << 16)
+
+/* define bit use in NFC_WCMD_SET */
+#define NFC_PROGRAM_CMD_MSK	0xff
+#define NFC_RND_WRITE_CMD_MSK	(0xff << 8)
+#define NFC_READ_CMD0_MSK	(0xff << 16)
+#define NFC_READ_CMD1_MSK	(0xff << 24)
+
+/* define bit use in NFC_ECC_CTL */
+#define NFC_ECC_EN		BIT(0)
+#define NFC_ECC_PIPELINE	BIT(3)
+#define NFC_ECC_EXCEPTION	BIT(4)
+#define NFC_ECC_BLOCK_SIZE_MSK	BIT(5)
+#define NFC_ECC_BLOCK_512	(1 << 5)
+#define NFC_RANDOM_EN		BIT(9)
+#define NFC_RANDOM_DIRECTION	BIT(10)
+#define NFC_ECC_MODE_MSK	(0xf << 12)
+#define NFC_ECC_MODE(x)		((x) << 12)
+#define NFC_RANDOM_SEED_MSK	(0x7fff << 16)
+#define NFC_RANDOM_SEED(x)	((x) << 16)
+
+/* define bit use in NFC_ECC_ST */
+#define NFC_ECC_ERR(x)		BIT(x)
+#define NFC_ECC_PAT_FOUND(x)	BIT(x + 16)
+#define NFC_ECC_ERR_CNT(b, x)	(((x) >> ((b) * 8)) & 0xff)
+
+#define NFC_DEFAULT_TIMEOUT_MS	1000
+
+#define NFC_SRAM_SIZE		1024
+
+#define NFC_MAX_CS		7
+
+/*
+ * Ready/Busy detection type: describes the Ready/Busy detection modes
+ *
+ * @RB_NONE:	no external detection available, rely on STATUS command
+ *		and software timeouts
+ * @RB_NATIVE:	use sunxi NAND controller Ready/Busy support. The Ready/Busy
+ *		pin of the NAND flash chip must be connected to one of the
+ *		native NAND R/B pins (those which can be muxed to the NAND
+ *		Controller)
+ * @RB_GPIO:	use a simple GPIO to handle Ready/Busy status. The Ready/Busy
+ *		pin of the NAND flash chip must be connected to a GPIO capable
+ *		pin.
+ */
+enum sunxi_nand_rb_type {
+	RB_NONE,
+	RB_NATIVE,
+	RB_GPIO,
+};
+
+/*
+ * Ready/Busy structure: stores information related to Ready/Busy detection
+ *
+ * @type:	the Ready/Busy detection mode
+ * @info:	information related to the R/B detection mode. Either a gpio
+ *		id or a native R/B id (those supported by the NAND controller).
+ */
+struct sunxi_nand_rb {
+	enum sunxi_nand_rb_type type;
+	union {
+		struct gpio_desc gpio;
+		int nativeid;
+	} info;
+};
+
+/*
+ * Chip Select structure: stores information related to NAND Chip Select
+ *
+ * @cs:		the NAND CS id used to communicate with a NAND Chip
+ * @rb:		the Ready/Busy description
+ */
+struct sunxi_nand_chip_sel {
+	u8 cs;
+	struct sunxi_nand_rb rb;
+};
+
+/*
+ * sunxi HW ECC infos: stores information related to HW ECC support
+ *
+ * @mode:	the sunxi ECC mode field deduced from ECC requirements
+ * @layout:	the OOB layout depending on the ECC requirements and the
+ *		selected ECC mode
+ */
+struct sunxi_nand_hw_ecc {
+	int mode;
+	struct nand_ecclayout layout;
+};
+
+/*
+ * NAND chip structure: stores NAND chip device related information
+ *
+ * @node:		used to store NAND chips into a list
+ * @nand:		base NAND chip structure
+ * @mtd:		base MTD structure
+ * @clk_rate:		clk_rate required for this NAND chip
+ * @timing_cfg		TIMING_CFG register value for this NAND chip
+ * @selected:		current active CS
+ * @nsels:		number of CS lines required by the NAND chip
+ * @sels:		array of CS lines descriptions
+ */
+struct sunxi_nand_chip {
+	struct list_head node;
+	struct nand_chip nand;
+	unsigned long clk_rate;
+	u32 timing_cfg;
+	u32 timing_ctl;
+	int selected;
+	int addr_cycles;
+	u32 addr[2];
+	int cmd_cycles;
+	u8 cmd[2];
+	int nsels;
+	struct sunxi_nand_chip_sel sels[0];
+};
+
+static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
+{
+	return container_of(nand, struct sunxi_nand_chip, nand);
+}
+
+/*
+ * NAND Controller structure: stores sunxi NAND controller information
+ *
+ * @controller:		base controller structure
+ * @dev:		parent device (used to print error messages)
+ * @regs:		NAND controller registers
+ * @ahb_clk:		NAND Controller AHB clock
+ * @mod_clk:		NAND Controller mod clock
+ * @assigned_cs:	bitmask describing already assigned CS lines
+ * @clk_rate:		NAND controller current clock rate
+ * @chips:		a list containing all the NAND chips attached to
+ *			this NAND controller
+ * @complete:		a completion object used to wait for NAND
+ *			controller events
+ */
+struct sunxi_nfc {
+	struct nand_hw_control controller;
+	struct device *dev;
+	void __iomem *regs;
+	struct clk *ahb_clk;
+	struct clk *mod_clk;
+	unsigned long assigned_cs;
+	unsigned long clk_rate;
+	struct list_head chips;
+};
+
+static inline struct sunxi_nfc *to_sunxi_nfc(struct nand_hw_control *ctrl)
+{
+	return container_of(ctrl, struct sunxi_nfc, controller);
+}
+
+static void sunxi_nfc_set_clk_rate(unsigned long hz)
+{
+	struct sunxi_ccm_reg *const ccm =
+	(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	int div_m, div_n;
+
+	div_m = (clock_get_pll6() + hz - 1) / hz;
+	for (div_n = 0; div_n < 3 && div_m > 16; div_n++) {
+		if (div_m % 2)
+			div_m++;
+		div_m >>= 1;
+	}
+	if (div_m > 16)
+		div_m = 16;
+
+	/* config mod clock */
+	writel(CCM_NAND_CTRL_ENABLE | CCM_NAND_CTRL_PLL6 |
+	       CCM_NAND_CTRL_N(div_n) | CCM_NAND_CTRL_M(div_m),
+	       &ccm->nand0_clk_cfg);
+
+	/* gate on nand clock */
+	setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_NAND0));
+#ifdef CONFIG_MACH_SUN9I
+	setbits_le32(&ccm->ahb_gate1, (1 << AHB_GATE_OFFSET_DMA));
+#else
+	setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_DMA));
+#endif
+}
+
+static int sunxi_nfc_wait_int(struct sunxi_nfc *nfc, u32 flags,
+			      unsigned int timeout_ms)
+{
+	unsigned int timeout_ticks;
+	u32 time_start, status;
+	int ret = -ETIMEDOUT;
+
+	if (!timeout_ms)
+		timeout_ms = NFC_DEFAULT_TIMEOUT_MS;
+
+	timeout_ticks = (timeout_ms * CONFIG_SYS_HZ) / 1000;
+
+	time_start = get_timer(0);
+
+	do {
+		status = readl(nfc->regs + NFC_REG_ST);
+		if ((status & flags) == flags) {
+			ret = 0;
+			break;
+		}
+
+		udelay(1);
+	} while (get_timer(time_start) < timeout_ticks);
+
+	writel(status & flags, nfc->regs + NFC_REG_ST);
+
+	return ret;
+}
+
+static int sunxi_nfc_wait_cmd_fifo_empty(struct sunxi_nfc *nfc)
+{
+	unsigned long timeout = (CONFIG_SYS_HZ *
+				 NFC_DEFAULT_TIMEOUT_MS) / 1000;
+	u32 time_start;
+
+	time_start = get_timer(0);
+	do {
+		if (!(readl(nfc->regs + NFC_REG_ST) & NFC_CMD_FIFO_STATUS))
+			return 0;
+	} while (get_timer(time_start) < timeout);
+
+	dev_err(nfc->dev, "wait for empty cmd FIFO timedout\n");
+	return -ETIMEDOUT;
+}
+
+static int sunxi_nfc_rst(struct sunxi_nfc *nfc)
+{
+	unsigned long timeout = (CONFIG_SYS_HZ *
+				 NFC_DEFAULT_TIMEOUT_MS) / 1000;
+	u32 time_start;
+
+	writel(0, nfc->regs + NFC_REG_ECC_CTL);
+	writel(NFC_RESET, nfc->regs + NFC_REG_CTL);
+
+	time_start = get_timer(0);
+	do {
+		if (!(readl(nfc->regs + NFC_REG_CTL) & NFC_RESET))
+			return 0;
+	} while (get_timer(time_start) < timeout);
+
+	dev_err(nfc->dev, "wait for NAND controller reset timedout\n");
+	return -ETIMEDOUT;
+}
+
+static int sunxi_nfc_dev_ready(struct mtd_info *mtd)
+{
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
+	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
+	struct sunxi_nand_rb *rb;
+	unsigned long timeo = (sunxi_nand->nand.state == FL_ERASING ? 400 : 20);
+	int ret;
+
+	if (sunxi_nand->selected < 0)
+		return 0;
+
+	rb = &sunxi_nand->sels[sunxi_nand->selected].rb;
+
+	switch (rb->type) {
+	case RB_NATIVE:
+		ret = !!(readl(nfc->regs + NFC_REG_ST) &
+			 NFC_RB_STATE(rb->info.nativeid));
+		if (ret)
+			break;
+
+		sunxi_nfc_wait_int(nfc, NFC_RB_B2R, timeo);
+		ret = !!(readl(nfc->regs + NFC_REG_ST) &
+			 NFC_RB_STATE(rb->info.nativeid));
+		break;
+	case RB_GPIO:
+		ret = dm_gpio_get_value(&rb->info.gpio);
+		break;
+	case RB_NONE:
+	default:
+		ret = 0;
+		dev_err(nfc->dev, "cannot check R/B NAND status!\n");
+		break;
+	}
+
+	return ret;
+}
+
+static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
+	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
+	struct sunxi_nand_chip_sel *sel;
+	u32 ctl;
+
+	if (chip > 0 && chip >= sunxi_nand->nsels)
+		return;
+
+	if (chip == sunxi_nand->selected)
+		return;
+
+	ctl = readl(nfc->regs + NFC_REG_CTL) &
+	      ~(NFC_PAGE_SHIFT_MSK | NFC_CE_SEL_MSK | NFC_RB_SEL_MSK | NFC_EN);
+
+	if (chip >= 0) {
+		sel = &sunxi_nand->sels[chip];
+
+		ctl |= NFC_CE_SEL(sel->cs) | NFC_EN |
+		       NFC_PAGE_SHIFT(nand->page_shift - 10);
+		if (sel->rb.type == RB_NONE) {
+			nand->dev_ready = NULL;
+		} else {
+			nand->dev_ready = sunxi_nfc_dev_ready;
+			if (sel->rb.type == RB_NATIVE)
+				ctl |= NFC_RB_SEL(sel->rb.info.nativeid);
+		}
+
+		writel(mtd->writesize, nfc->regs + NFC_REG_SPARE_AREA);
+
+		if (nfc->clk_rate != sunxi_nand->clk_rate) {
+			sunxi_nfc_set_clk_rate(sunxi_nand->clk_rate);
+			nfc->clk_rate = sunxi_nand->clk_rate;
+		}
+	}
+
+	writel(sunxi_nand->timing_ctl, nfc->regs + NFC_REG_TIMING_CTL);
+	writel(sunxi_nand->timing_cfg, nfc->regs + NFC_REG_TIMING_CFG);
+	writel(ctl, nfc->regs + NFC_REG_CTL);
+
+	sunxi_nand->selected = chip;
+}
+
+static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
+	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
+	int ret;
+	int cnt;
+	int offs = 0;
+	u32 tmp;
+
+	while (len > offs) {
+		cnt = min(len - offs, NFC_SRAM_SIZE);
+
+		ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
+		if (ret)
+			break;
+
+		writel(cnt, nfc->regs + NFC_REG_CNT);
+		tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD;
+		writel(tmp, nfc->regs + NFC_REG_CMD);
+
+		ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0);
+		if (ret)
+			break;
+
+		if (buf)
+			memcpy_fromio(buf + offs, nfc->regs + NFC_RAM0_BASE,
+				      cnt);
+		offs += cnt;
+	}
+}
+
+static void sunxi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
+				int len)
+{
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
+	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
+	int ret;
+	int cnt;
+	int offs = 0;
+	u32 tmp;
+
+	while (len > offs) {
+		cnt = min(len - offs, NFC_SRAM_SIZE);
+
+		ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
+		if (ret)
+			break;
+
+		writel(cnt, nfc->regs + NFC_REG_CNT);
+		memcpy_toio(nfc->regs + NFC_RAM0_BASE, buf + offs, cnt);
+		tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
+		      NFC_ACCESS_DIR;
+		writel(tmp, nfc->regs + NFC_REG_CMD);
+
+		ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0);
+		if (ret)
+			break;
+
+		offs += cnt;
+	}
+}
+
+static uint8_t sunxi_nfc_read_byte(struct mtd_info *mtd)
+{
+	uint8_t ret;
+
+	sunxi_nfc_read_buf(mtd, &ret, 1);
+
+	return ret;
+}
+
+static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat,
+			       unsigned int ctrl)
+{
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
+	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
+	int ret;
+	u32 tmp;
+
+	ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
+	if (ret)
+		return;
+
+	if (ctrl & NAND_CTRL_CHANGE) {
+		tmp = readl(nfc->regs + NFC_REG_CTL);
+		if (ctrl & NAND_NCE)
+			tmp |= NFC_CE_CTL;
+		else
+			tmp &= ~NFC_CE_CTL;
+		writel(tmp, nfc->regs + NFC_REG_CTL);
+	}
+
+	if (dat == NAND_CMD_NONE && (ctrl & NAND_NCE) &&
+	    !(ctrl & (NAND_CLE | NAND_ALE))) {
+		u32 cmd = 0;
+
+		if (!sunxi_nand->addr_cycles && !sunxi_nand->cmd_cycles)
+			return;
+
+		if (sunxi_nand->cmd_cycles--)
+			cmd |= NFC_SEND_CMD1 | sunxi_nand->cmd[0];
+
+		if (sunxi_nand->cmd_cycles--) {
+			cmd |= NFC_SEND_CMD2;
+			writel(sunxi_nand->cmd[1],
+			       nfc->regs + NFC_REG_RCMD_SET);
+		}
+
+		sunxi_nand->cmd_cycles = 0;
+
+		if (sunxi_nand->addr_cycles) {
+			cmd |= NFC_SEND_ADR |
+			       NFC_ADR_NUM(sunxi_nand->addr_cycles);
+			writel(sunxi_nand->addr[0],
+			       nfc->regs + NFC_REG_ADDR_LOW);
+		}
+
+		if (sunxi_nand->addr_cycles > 4)
+			writel(sunxi_nand->addr[1],
+			       nfc->regs + NFC_REG_ADDR_HIGH);
+
+		writel(cmd, nfc->regs + NFC_REG_CMD);
+		sunxi_nand->addr[0] = 0;
+		sunxi_nand->addr[1] = 0;
+		sunxi_nand->addr_cycles = 0;
+		sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0);
+	}
+
+	if (ctrl & NAND_CLE) {
+		sunxi_nand->cmd[sunxi_nand->cmd_cycles++] = dat;
+	} else if (ctrl & NAND_ALE) {
+		sunxi_nand->addr[sunxi_nand->addr_cycles / 4] |=
+				dat << ((sunxi_nand->addr_cycles % 4) * 8);
+		sunxi_nand->addr_cycles++;
+	}
+}
+
+/* These seed values have been extracted from Allwinner's BSP */
+static const u16 sunxi_nfc_randomizer_page_seeds[] = {
+	0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72,
+	0x0d67, 0x67f9, 0x1be7, 0x077d, 0x032f, 0x0dac, 0x2716, 0x2436,
+	0x7922, 0x1510, 0x3860, 0x5287, 0x480f, 0x4252, 0x1789, 0x5a2d,
+	0x2a49, 0x5e10, 0x437f, 0x4b4e, 0x2f45, 0x216e, 0x5cb7, 0x7130,
+	0x2a3f, 0x60e4, 0x4dc9, 0x0ef0, 0x0f52, 0x1bb9, 0x6211, 0x7a56,
+	0x226d, 0x4ea7, 0x6f36, 0x3692, 0x38bf, 0x0c62, 0x05eb, 0x4c55,
+	0x60f4, 0x728c, 0x3b6f, 0x2037, 0x7f69, 0x0936, 0x651a, 0x4ceb,
+	0x6218, 0x79f3, 0x383f, 0x18d9, 0x4f05, 0x5c82, 0x2912, 0x6f17,
+	0x6856, 0x5938, 0x1007, 0x61ab, 0x3e7f, 0x57c2, 0x542f, 0x4f62,
+	0x7454, 0x2eac, 0x7739, 0x42d4, 0x2f90, 0x435a, 0x2e52, 0x2064,
+	0x637c, 0x66ad, 0x2c90, 0x0bad, 0x759c, 0x0029, 0x0986, 0x7126,
+	0x1ca7, 0x1605, 0x386a, 0x27f5, 0x1380, 0x6d75, 0x24c3, 0x0f8e,
+	0x2b7a, 0x1418, 0x1fd1, 0x7dc1, 0x2d8e, 0x43af, 0x2267, 0x7da3,
+	0x4e3d, 0x1338, 0x50db, 0x454d, 0x764d, 0x40a3, 0x42e6, 0x262b,
+	0x2d2e, 0x1aea, 0x2e17, 0x173d, 0x3a6e, 0x71bf, 0x25f9, 0x0a5d,
+	0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db,
+};
+
+/*
+ * sunxi_nfc_randomizer_ecc512_seeds and sunxi_nfc_randomizer_ecc1024_seeds
+ * have been generated using
+ * sunxi_nfc_randomizer_step(seed, (step_size * 8) + 15), which is what
+ * the randomizer engine does internally before de/scrambling OOB data.
+ *
+ * Those tables are statically defined to avoid calculating randomizer state
+ * at runtime.
+ */
+static const u16 sunxi_nfc_randomizer_ecc512_seeds[] = {
+	0x3346, 0x367f, 0x1f18, 0x769a, 0x4f64, 0x068c, 0x2ef1, 0x6b64,
+	0x28a9, 0x15d7, 0x30f8, 0x3659, 0x53db, 0x7c5f, 0x71d4, 0x4409,
+	0x26eb, 0x03cc, 0x655d, 0x47d4, 0x4daa, 0x0877, 0x712d, 0x3617,
+	0x3264, 0x49aa, 0x7f9e, 0x588e, 0x4fbc, 0x7176, 0x7f91, 0x6c6d,
+	0x4b95, 0x5fb7, 0x3844, 0x4037, 0x0184, 0x081b, 0x0ee8, 0x5b91,
+	0x293d, 0x1f71, 0x0e6f, 0x402b, 0x5122, 0x1e52, 0x22be, 0x3d2d,
+	0x75bc, 0x7c60, 0x6291, 0x1a2f, 0x61d4, 0x74aa, 0x4140, 0x29ab,
+	0x472d, 0x2852, 0x017e, 0x15e8, 0x5ec2, 0x17cf, 0x7d0f, 0x06b8,
+	0x117a, 0x6b94, 0x789b, 0x3126, 0x6ac5, 0x5be7, 0x150f, 0x51f8,
+	0x7889, 0x0aa5, 0x663d, 0x77e8, 0x0b87, 0x3dcb, 0x360d, 0x218b,
+	0x512f, 0x7dc9, 0x6a4d, 0x630a, 0x3547, 0x1dd2, 0x5aea, 0x69a5,
+	0x7bfa, 0x5e4f, 0x1519, 0x6430, 0x3a0e, 0x5eb3, 0x5425, 0x0c7a,
+	0x5540, 0x3670, 0x63c1, 0x31e9, 0x5a39, 0x2de7, 0x5979, 0x2891,
+	0x1562, 0x014b, 0x5b05, 0x2756, 0x5a34, 0x13aa, 0x6cb5, 0x2c36,
+	0x5e72, 0x1306, 0x0861, 0x15ef, 0x1ee8, 0x5a37, 0x7ac4, 0x45dd,
+	0x44c4, 0x7266, 0x2f41, 0x3ccc, 0x045e, 0x7d40, 0x7c66, 0x0fa0,
+};
+
+static const u16 sunxi_nfc_randomizer_ecc1024_seeds[] = {
+	0x2cf5, 0x35f1, 0x63a4, 0x5274, 0x2bd2, 0x778b, 0x7285, 0x32b6,
+	0x6a5c, 0x70d6, 0x757d, 0x6769, 0x5375, 0x1e81, 0x0cf3, 0x3982,
+	0x6787, 0x042a, 0x6c49, 0x1925, 0x56a8, 0x40a9, 0x063e, 0x7bd9,
+	0x4dbf, 0x55ec, 0x672e, 0x7334, 0x5185, 0x4d00, 0x232a, 0x7e07,
+	0x445d, 0x6b92, 0x528f, 0x4255, 0x53ba, 0x7d82, 0x2a2e, 0x3a4e,
+	0x75eb, 0x450c, 0x6844, 0x1b5d, 0x581a, 0x4cc6, 0x0379, 0x37b2,
+	0x419f, 0x0e92, 0x6b27, 0x5624, 0x01e3, 0x07c1, 0x44a5, 0x130c,
+	0x13e8, 0x5910, 0x0876, 0x60c5, 0x54e3, 0x5b7f, 0x2269, 0x509f,
+	0x7665, 0x36fd, 0x3e9a, 0x0579, 0x6295, 0x14ef, 0x0a81, 0x1bcc,
+	0x4b16, 0x64db, 0x0514, 0x4f07, 0x0591, 0x3576, 0x6853, 0x0d9e,
+	0x259f, 0x38b7, 0x64fb, 0x3094, 0x4693, 0x6ddd, 0x29bb, 0x0bc8,
+	0x3f47, 0x490e, 0x0c0e, 0x7933, 0x3c9e, 0x5840, 0x398d, 0x3e68,
+	0x4af1, 0x71f5, 0x57cf, 0x1121, 0x64eb, 0x3579, 0x15ac, 0x584d,
+	0x5f2a, 0x47e2, 0x6528, 0x6eac, 0x196e, 0x6b96, 0x0450, 0x0179,
+	0x609c, 0x06e1, 0x4626, 0x42c7, 0x273e, 0x486f, 0x0705, 0x1601,
+	0x145b, 0x407e, 0x062b, 0x57a5, 0x53f9, 0x5659, 0x4410, 0x3ccd,
+};
+
+static u16 sunxi_nfc_randomizer_step(u16 state, int count)
+{
+	state &= 0x7fff;
+
+	/*
+	 * This loop is just a simple implementation of a Fibonacci LFSR using
+	 * the x16 + x15 + 1 polynomial.
+	 */
+	while (count--)
+		state = ((state >> 1) |
+			 (((state ^ (state >> 1)) & 1) << 14)) & 0x7fff;
+
+	return state;
+}
+
+static u16 sunxi_nfc_randomizer_state(struct mtd_info *mtd, int page, bool ecc)
+{
+	const u16 *seeds = sunxi_nfc_randomizer_page_seeds;
+	int mod = mtd->erasesize / mtd->writesize;
+
+	if (mod > ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds))
+		mod = ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds);
+
+	if (ecc) {
+		if (mtd->ecc_step_size == 512)
+			seeds = sunxi_nfc_randomizer_ecc512_seeds;
+		else
+			seeds = sunxi_nfc_randomizer_ecc1024_seeds;
+	}
+
+	return seeds[page % mod];
+}
+
+static void sunxi_nfc_randomizer_config(struct mtd_info *mtd,
+					int page, bool ecc)
+{
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+	u32 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
+	u16 state;
+
+	if (!(nand->options & NAND_NEED_SCRAMBLING))
+		return;
+
+	ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
+	state = sunxi_nfc_randomizer_state(mtd, page, ecc);
+	ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_SEED_MSK;
+	writel(ecc_ctl | NFC_RANDOM_SEED(state), nfc->regs + NFC_REG_ECC_CTL);
+}
+
+static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd)
+{
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+
+	if (!(nand->options & NAND_NEED_SCRAMBLING))
+		return;
+
+	writel(readl(nfc->regs + NFC_REG_ECC_CTL) | NFC_RANDOM_EN,
+	       nfc->regs + NFC_REG_ECC_CTL);
+}
+
+static void sunxi_nfc_randomizer_disable(struct mtd_info *mtd)
+{
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+
+	if (!(nand->options & NAND_NEED_SCRAMBLING))
+		return;
+
+	writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_EN,
+	       nfc->regs + NFC_REG_ECC_CTL);
+}
+
+static void sunxi_nfc_randomize_bbm(struct mtd_info *mtd, int page, u8 *bbm)
+{
+	u16 state = sunxi_nfc_randomizer_state(mtd, page, true);
+
+	bbm[0] ^= state;
+	bbm[1] ^= sunxi_nfc_randomizer_step(state, 8);
+}
+
+static void sunxi_nfc_randomizer_write_buf(struct mtd_info *mtd,
+					   const uint8_t *buf, int len,
+					   bool ecc, int page)
+{
+	sunxi_nfc_randomizer_config(mtd, page, ecc);
+	sunxi_nfc_randomizer_enable(mtd);
+	sunxi_nfc_write_buf(mtd, buf, len);
+	sunxi_nfc_randomizer_disable(mtd);
+}
+
+static void sunxi_nfc_randomizer_read_buf(struct mtd_info *mtd, uint8_t *buf,
+					  int len, bool ecc, int page)
+{
+	sunxi_nfc_randomizer_config(mtd, page, ecc);
+	sunxi_nfc_randomizer_enable(mtd);
+	sunxi_nfc_read_buf(mtd, buf, len);
+	sunxi_nfc_randomizer_disable(mtd);
+}
+
+static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd)
+{
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+	struct sunxi_nand_hw_ecc *data = nand->ecc.priv;
+	u32 ecc_ctl;
+
+	ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
+	ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE |
+		     NFC_ECC_BLOCK_SIZE_MSK);
+	ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) | NFC_ECC_EXCEPTION;
+
+	if (nand->ecc.size == 512)
+		ecc_ctl |= NFC_ECC_BLOCK_512;
+
+	writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL);
+}
+
+static void sunxi_nfc_hw_ecc_disable(struct mtd_info *mtd)
+{
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+
+	writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_ECC_EN,
+	       nfc->regs + NFC_REG_ECC_CTL);
+}
+
+static inline void sunxi_nfc_user_data_to_buf(u32 user_data, u8 *buf)
+{
+	buf[0] = user_data;
+	buf[1] = user_data >> 8;
+	buf[2] = user_data >> 16;
+	buf[3] = user_data >> 24;
+}
+
+static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
+				       u8 *data, int data_off,
+				       u8 *oob, int oob_off,
+				       int *cur_off,
+				       unsigned int *max_bitflips,
+				       bool bbm, int page)
+{
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+	struct nand_ecc_ctrl *ecc = &nand->ecc;
+	int raw_mode = 0;
+	u32 status;
+	int ret;
+
+	if (*cur_off != data_off)
+		nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1);
+
+	sunxi_nfc_randomizer_read_buf(mtd, NULL, ecc->size, false, page);
+
+	if (data_off + ecc->size != oob_off)
+		nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
+
+	ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
+	if (ret)
+		return ret;
+
+	sunxi_nfc_randomizer_enable(mtd);
+	writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP,
+	       nfc->regs + NFC_REG_CMD);
+
+	ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0);
+	sunxi_nfc_randomizer_disable(mtd);
+	if (ret)
+		return ret;
+
+	*cur_off = oob_off + ecc->bytes + 4;
+
+	status = readl(nfc->regs + NFC_REG_ECC_ST);
+	if (status & NFC_ECC_PAT_FOUND(0)) {
+		u8 pattern = 0xff;
+
+		if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1)))
+			pattern = 0x0;
+
+		memset(data, pattern, ecc->size);
+		memset(oob, pattern, ecc->bytes + 4);
+
+		return 1;
+	}
+
+	ret = NFC_ECC_ERR_CNT(0, readl(nfc->regs + NFC_REG_ECC_ERR_CNT(0)));
+
+	memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size);
+
+	nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
+	sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4, true, page);
+
+	if (status & NFC_ECC_ERR(0)) {
+		/*
+		 * Re-read the data with the randomizer disabled to identify
+		 * bitflips in erased pages.
+		 */
+		if (nand->options & NAND_NEED_SCRAMBLING) {
+			nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1);
+			nand->read_buf(mtd, data, ecc->size);
+			nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
+			nand->read_buf(mtd, oob, ecc->bytes + 4);
+		}
+
+		ret = nand_check_erased_ecc_chunk(data,	ecc->size,
+						  oob, ecc->bytes + 4,
+						  NULL, 0, ecc->strength);
+		if (ret >= 0)
+			raw_mode = 1;
+	} else {
+		/*
+		 * The engine protects 4 bytes of OOB data per chunk.
+		 * Retrieve the corrected OOB bytes.
+		 */
+		sunxi_nfc_user_data_to_buf(readl(nfc->regs +
+						 NFC_REG_USER_DATA(0)),
+					   oob);
+
+		/* De-randomize the Bad Block Marker. */
+		if (bbm && nand->options & NAND_NEED_SCRAMBLING)
+			sunxi_nfc_randomize_bbm(mtd, page, oob);
+	}
+
+	if (ret < 0) {
+		mtd->ecc_stats.failed++;
+	} else {
+		mtd->ecc_stats.corrected += ret;
+		*max_bitflips = max_t(unsigned int, *max_bitflips, ret);
+	}
+
+	return raw_mode;
+}
+
+static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd,
+					    u8 *oob, int *cur_off,
+					    bool randomize, int page)
+{
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_ecc_ctrl *ecc = &nand->ecc;
+	int offset = ((ecc->bytes + 4) * ecc->steps);
+	int len = mtd->oobsize - offset;
+
+	if (len <= 0)
+		return;
+
+	if (*cur_off != offset)
+		nand->cmdfunc(mtd, NAND_CMD_RNDOUT,
+			      offset + mtd->writesize, -1);
+
+	if (!randomize)
+		sunxi_nfc_read_buf(mtd, oob + offset, len);
+	else
+		sunxi_nfc_randomizer_read_buf(mtd, oob + offset, len,
+					      false, page);
+
+	*cur_off = mtd->oobsize + mtd->writesize;
+}
+
+static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf)
+{
+	return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
+}
+
+static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
+					const u8 *data, int data_off,
+					const u8 *oob, int oob_off,
+					int *cur_off, bool bbm,
+					int page)
+{
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+	struct nand_ecc_ctrl *ecc = &nand->ecc;
+	int ret;
+
+	if (data_off != *cur_off)
+		nand->cmdfunc(mtd, NAND_CMD_RNDIN, data_off, -1);
+
+	sunxi_nfc_randomizer_write_buf(mtd, data, ecc->size, false, page);
+
+	/* Fill OOB data in */
+	if ((nand->options & NAND_NEED_SCRAMBLING) && bbm) {
+		u8 user_data[4];
+
+		memcpy(user_data, oob, 4);
+		sunxi_nfc_randomize_bbm(mtd, page, user_data);
+		writel(sunxi_nfc_buf_to_user_data(user_data),
+		       nfc->regs + NFC_REG_USER_DATA(0));
+	} else {
+		writel(sunxi_nfc_buf_to_user_data(oob),
+		       nfc->regs + NFC_REG_USER_DATA(0));
+	}
+
+	if (data_off + ecc->size != oob_off)
+		nand->cmdfunc(mtd, NAND_CMD_RNDIN, oob_off, -1);
+
+	ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
+	if (ret)
+		return ret;
+
+	sunxi_nfc_randomizer_enable(mtd);
+	writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
+	       NFC_ACCESS_DIR | NFC_ECC_OP,
+	       nfc->regs + NFC_REG_CMD);
+
+	ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0);
+	sunxi_nfc_randomizer_disable(mtd);
+	if (ret)
+		return ret;
+
+	*cur_off = oob_off + ecc->bytes + 4;
+
+	return 0;
+}
+
+static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd,
+					     u8 *oob, int *cur_off,
+					     int page)
+{
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_ecc_ctrl *ecc = &nand->ecc;
+	int offset = ((ecc->bytes + 4) * ecc->steps);
+	int len = mtd->oobsize - offset;
+
+	if (len <= 0)
+		return;
+
+	if (*cur_off != offset)
+		nand->cmdfunc(mtd, NAND_CMD_RNDIN,
+			      offset + mtd->writesize, -1);
+
+	sunxi_nfc_randomizer_write_buf(mtd, oob + offset, len, false, page);
+
+	*cur_off = mtd->oobsize + mtd->writesize;
+}
+
+static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd,
+				      struct nand_chip *chip, uint8_t *buf,
+				      int oob_required, int page)
+{
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+	unsigned int max_bitflips = 0;
+	int ret, i, cur_off = 0;
+	bool raw_mode = false;
+
+	sunxi_nfc_hw_ecc_enable(mtd);
+
+	for (i = 0; i < ecc->steps; i++) {
+		int data_off = i * ecc->size;
+		int oob_off = i * (ecc->bytes + 4);
+		u8 *data = buf + data_off;
+		u8 *oob = chip->oob_poi + oob_off;
+
+		ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob,
+						  oob_off + mtd->writesize,
+						  &cur_off, &max_bitflips,
+						  !i, page);
+		if (ret < 0)
+			return ret;
+		else if (ret)
+			raw_mode = true;
+	}
+
+	if (oob_required)
+		sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off,
+						!raw_mode, page);
+
+	sunxi_nfc_hw_ecc_disable(mtd);
+
+	return max_bitflips;
+}
+
+static int sunxi_nfc_hw_ecc_read_subpage(struct mtd_info *mtd,
+					 struct nand_chip *chip,
+					 uint32_t data_offs, uint32_t readlen,
+					 uint8_t *bufpoi, int page)
+{
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+	int ret, i, cur_off = 0;
+	unsigned int max_bitflips = 0;
+
+	sunxi_nfc_hw_ecc_enable(mtd);
+
+	chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+	for (i = data_offs / ecc->size;
+	     i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) {
+		int data_off = i * ecc->size;
+		int oob_off = i * (ecc->bytes + 4);
+		u8 *data = bufpoi + data_off;
+		u8 *oob = chip->oob_poi + oob_off;
+
+		ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off,
+			oob, oob_off + mtd->writesize,
+			&cur_off, &max_bitflips, !i, page);
+		if (ret < 0)
+			return ret;
+	}
+
+	sunxi_nfc_hw_ecc_disable(mtd);
+
+	return max_bitflips;
+}
+
+static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd,
+				       struct nand_chip *chip,
+				       const uint8_t *buf, int oob_required,
+				       int page)
+{
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+	int ret, i, cur_off = 0;
+
+	sunxi_nfc_hw_ecc_enable(mtd);
+
+	for (i = 0; i < ecc->steps; i++) {
+		int data_off = i * ecc->size;
+		int oob_off = i * (ecc->bytes + 4);
+		const u8 *data = buf + data_off;
+		const u8 *oob = chip->oob_poi + oob_off;
+
+		ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob,
+						   oob_off + mtd->writesize,
+						   &cur_off, !i, page);
+		if (ret)
+			return ret;
+	}
+
+	if (oob_required || (chip->options & NAND_NEED_SCRAMBLING))
+		sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi,
+						 &cur_off, page);
+
+	sunxi_nfc_hw_ecc_disable(mtd);
+
+	return 0;
+}
+
+static int sunxi_nfc_hw_ecc_write_subpage(struct mtd_info *mtd,
+					  struct nand_chip *chip,
+					  u32 data_offs, u32 data_len,
+					  const u8 *buf, int oob_required,
+					  int page)
+{
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+	int ret, i, cur_off = 0;
+
+	sunxi_nfc_hw_ecc_enable(mtd);
+
+	for (i = data_offs / ecc->size;
+	     i < DIV_ROUND_UP(data_offs + data_len, ecc->size); i++) {
+		int data_off = i * ecc->size;
+		int oob_off = i * (ecc->bytes + 4);
+		const u8 *data = buf + data_off;
+		const u8 *oob = chip->oob_poi + oob_off;
+
+		ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob,
+						   oob_off + mtd->writesize,
+						   &cur_off, !i, page);
+		if (ret)
+			return ret;
+	}
+
+	sunxi_nfc_hw_ecc_disable(mtd);
+
+	return 0;
+}
+
+static int sunxi_nfc_hw_syndrome_ecc_read_page(struct mtd_info *mtd,
+					       struct nand_chip *chip,
+					       uint8_t *buf, int oob_required,
+					       int page)
+{
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+	unsigned int max_bitflips = 0;
+	int ret, i, cur_off = 0;
+	bool raw_mode = false;
+
+	sunxi_nfc_hw_ecc_enable(mtd);
+
+	for (i = 0; i < ecc->steps; i++) {
+		int data_off = i * (ecc->size + ecc->bytes + 4);
+		int oob_off = data_off + ecc->size;
+		u8 *data = buf + (i * ecc->size);
+		u8 *oob = chip->oob_poi + (i * (ecc->bytes + 4));
+
+		ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob,
+						  oob_off, &cur_off,
+						  &max_bitflips, !i, page);
+		if (ret < 0)
+			return ret;
+		else if (ret)
+			raw_mode = true;
+	}
+
+	if (oob_required)
+		sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off,
+						!raw_mode, page);
+
+	sunxi_nfc_hw_ecc_disable(mtd);
+
+	return max_bitflips;
+}
+
+static int sunxi_nfc_hw_syndrome_ecc_write_page(struct mtd_info *mtd,
+						struct nand_chip *chip,
+						const uint8_t *buf,
+						int oob_required, int page)
+{
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+	int ret, i, cur_off = 0;
+
+	sunxi_nfc_hw_ecc_enable(mtd);
+
+	for (i = 0; i < ecc->steps; i++) {
+		int data_off = i * (ecc->size + ecc->bytes + 4);
+		int oob_off = data_off + ecc->size;
+		const u8 *data = buf + (i * ecc->size);
+		const u8 *oob = chip->oob_poi + (i * (ecc->bytes + 4));
+
+		ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off,
+						   oob, oob_off, &cur_off,
+						   false, page);
+		if (ret)
+			return ret;
+	}
+
+	if (oob_required || (chip->options & NAND_NEED_SCRAMBLING))
+		sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi,
+						 &cur_off, page);
+
+	sunxi_nfc_hw_ecc_disable(mtd);
+
+	return 0;
+}
+
+static const s32 tWB_lut[] = {6, 12, 16, 20};
+static const s32 tRHW_lut[] = {4, 8, 12, 20};
+
+static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration,
+		u32 clk_period)
+{
+	u32 clk_cycles = DIV_ROUND_UP(duration, clk_period);
+	int i;
+
+	for (i = 0; i < lut_size; i++) {
+		if (clk_cycles <= lut[i])
+			return i;
+	}
+
+	/* Doesn't fit */
+	return -EINVAL;
+}
+
+#define sunxi_nand_lookup_timing(l, p, c) \
+			_sunxi_nand_lookup_timing(l, ARRAY_SIZE(l), p, c)
+
+static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip,
+				       const struct nand_sdr_timings *timings)
+{
+	u32 min_clk_period = 0;
+	s32 tWB, tADL, tWHR, tRHW, tCAD;
+
+	/* T1 <=> tCLS */
+	if (timings->tCLS_min > min_clk_period)
+		min_clk_period = timings->tCLS_min;
+
+	/* T2 <=> tCLH */
+	if (timings->tCLH_min > min_clk_period)
+		min_clk_period = timings->tCLH_min;
+
+	/* T3 <=> tCS */
+	if (timings->tCS_min > min_clk_period)
+		min_clk_period = timings->tCS_min;
+
+	/* T4 <=> tCH */
+	if (timings->tCH_min > min_clk_period)
+		min_clk_period = timings->tCH_min;
+
+	/* T5 <=> tWP */
+	if (timings->tWP_min > min_clk_period)
+		min_clk_period = timings->tWP_min;
+
+	/* T6 <=> tWH */
+	if (timings->tWH_min > min_clk_period)
+		min_clk_period = timings->tWH_min;
+
+	/* T7 <=> tALS */
+	if (timings->tALS_min > min_clk_period)
+		min_clk_period = timings->tALS_min;
+
+	/* T8 <=> tDS */
+	if (timings->tDS_min > min_clk_period)
+		min_clk_period = timings->tDS_min;
+
+	/* T9 <=> tDH */
+	if (timings->tDH_min > min_clk_period)
+		min_clk_period = timings->tDH_min;
+
+	/* T10 <=> tRR */
+	if (timings->tRR_min > (min_clk_period * 3))
+		min_clk_period = DIV_ROUND_UP(timings->tRR_min, 3);
+
+	/* T11 <=> tALH */
+	if (timings->tALH_min > min_clk_period)
+		min_clk_period = timings->tALH_min;
+
+	/* T12 <=> tRP */
+	if (timings->tRP_min > min_clk_period)
+		min_clk_period = timings->tRP_min;
+
+	/* T13 <=> tREH */
+	if (timings->tREH_min > min_clk_period)
+		min_clk_period = timings->tREH_min;
+
+	/* T14 <=> tRC */
+	if (timings->tRC_min > (min_clk_period * 2))
+		min_clk_period = DIV_ROUND_UP(timings->tRC_min, 2);
+
+	/* T15 <=> tWC */
+	if (timings->tWC_min > (min_clk_period * 2))
+		min_clk_period = DIV_ROUND_UP(timings->tWC_min, 2);
+
+	/* T16 - T19 + tCAD */
+	tWB  = sunxi_nand_lookup_timing(tWB_lut, timings->tWB_max,
+					min_clk_period);
+	if (tWB < 0) {
+		dev_err(nfc->dev, "unsupported tWB\n");
+		return tWB;
+	}
+
+	tADL = DIV_ROUND_UP(timings->tADL_min, min_clk_period) >> 3;
+	if (tADL > 3) {
+		dev_err(nfc->dev, "unsupported tADL\n");
+		return -EINVAL;
+	}
+
+	tWHR = DIV_ROUND_UP(timings->tWHR_min, min_clk_period) >> 3;
+	if (tWHR > 3) {
+		dev_err(nfc->dev, "unsupported tWHR\n");
+		return -EINVAL;
+	}
+
+	tRHW = sunxi_nand_lookup_timing(tRHW_lut, timings->tRHW_min,
+					min_clk_period);
+	if (tRHW < 0) {
+		dev_err(nfc->dev, "unsupported tRHW\n");
+		return tRHW;
+	}
+
+	/*
+	 * TODO: according to ONFI specs this value only applies for DDR NAND,
+	 * but Allwinner seems to set this to 0x7. Mimic them for now.
+	 */
+	tCAD = 0x7;
+
+	/* TODO: A83 has some more bits for CDQSS, CS, CLHZ, CCS, WC */
+	chip->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD);
+
+	/*
+	 * ONFI specification 3.1, paragraph 4.15.2 dictates that EDO data
+	 * output cycle timings shall be used if the host drives tRC less than
+	 * 30 ns.
+	 */
+	chip->timing_ctl = (timings->tRC_min < 30000) ? NFC_TIMING_CTL_EDO : 0;
+
+	/* Convert min_clk_period from picoseconds to nanoseconds */
+	min_clk_period = DIV_ROUND_UP(min_clk_period, 1000);
+
+	/*
+	 * Convert min_clk_period into a clk frequency, then get the
+	 * appropriate rate for the NAND controller IP given this formula
+	 * (specified in the datasheet):
+	 * nand clk_rate = min_clk_rate
+	 */
+	chip->clk_rate = 1000000000L / min_clk_period;
+
+	return 0;
+}
+
+static int sunxi_nand_chip_init_timings(struct sunxi_nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(&chip->nand);
+	const struct nand_sdr_timings *timings;
+	int ret;
+	int mode;
+
+	mode = onfi_get_async_timing_mode(&chip->nand);
+	if (mode == ONFI_TIMING_MODE_UNKNOWN) {
+		mode = chip->nand.onfi_timing_mode_default;
+	} else {
+		uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {};
+		int i;
+
+		mode = fls(mode) - 1;
+		if (mode < 0)
+			mode = 0;
+
+		feature[0] = mode;
+		for (i = 0; i < chip->nsels; i++) {
+			chip->nand.select_chip(mtd, i);
+			ret = chip->nand.onfi_set_features(mtd,
+						&chip->nand,
+						ONFI_FEATURE_ADDR_TIMING_MODE,
+						feature);
+			chip->nand.select_chip(mtd, -1);
+			if (ret)
+				return ret;
+		}
+	}
+
+	timings = onfi_async_timing_mode_to_sdr_timings(mode);
+	if (IS_ERR(timings))
+		return PTR_ERR(timings);
+
+	return sunxi_nand_chip_set_timings(chip, timings);
+}
+
+static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
+					      struct nand_ecc_ctrl *ecc)
+{
+	static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
+	struct sunxi_nand_hw_ecc *data;
+	struct nand_ecclayout *layout;
+	int nsectors;
+	int ret;
+	int i;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	if (ecc->size != 512 && ecc->size != 1024)
+		return -EINVAL;
+
+	/* Prefer 1k ECC chunk over 512 ones */
+	if (ecc->size == 512 && mtd->writesize > 512) {
+		ecc->size = 1024;
+		ecc->strength *= 2;
+	}
+
+	/* Add ECC info retrieval from DT */
+	for (i = 0; i < ARRAY_SIZE(strengths); i++) {
+		if (ecc->strength <= strengths[i])
+			break;
+	}
+
+	if (i >= ARRAY_SIZE(strengths)) {
+		dev_err(nfc->dev, "unsupported strength\n");
+		ret = -ENOTSUPP;
+		goto err;
+	}
+
+	data->mode = i;
+
+	/* HW ECC always request ECC bytes for 1024 bytes blocks */
+	ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * 1024), 8);
+
+	/* HW ECC always work with even numbers of ECC bytes */
+	ecc->bytes = ALIGN(ecc->bytes, 2);
+
+	layout = &data->layout;
+	nsectors = mtd->writesize / ecc->size;
+
+	if (mtd->oobsize < ((ecc->bytes + 4) * nsectors)) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	layout->eccbytes = (ecc->bytes * nsectors);
+
+	ecc->layout = layout;
+	ecc->priv = data;
+
+	return 0;
+
+err:
+	kfree(data);
+
+	return ret;
+}
+
+#ifndef __UBOOT__
+static void sunxi_nand_hw_common_ecc_ctrl_cleanup(struct nand_ecc_ctrl *ecc)
+{
+	kfree(ecc->priv);
+}
+#endif /* __UBOOT__ */
+
+static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
+				       struct nand_ecc_ctrl *ecc)
+{
+	struct nand_ecclayout *layout;
+	int nsectors;
+	int i, j;
+	int ret;
+
+	ret = sunxi_nand_hw_common_ecc_ctrl_init(mtd, ecc);
+	if (ret)
+		return ret;
+
+	ecc->read_page = sunxi_nfc_hw_ecc_read_page;
+	ecc->write_page = sunxi_nfc_hw_ecc_write_page;
+	ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage;
+	ecc->write_subpage = sunxi_nfc_hw_ecc_write_subpage;
+	layout = ecc->layout;
+	nsectors = mtd->writesize / ecc->size;
+
+	for (i = 0; i < nsectors; i++) {
+		if (i) {
+			layout->oobfree[i].offset =
+				layout->oobfree[i - 1].offset +
+				layout->oobfree[i - 1].length +
+				ecc->bytes;
+			layout->oobfree[i].length = 4;
+		} else {
+			/*
+			 * The first 2 bytes are used for BB markers, hence we
+			 * only have 2 bytes available in the first user data
+			 * section.
+			 */
+			layout->oobfree[i].length = 2;
+			layout->oobfree[i].offset = 2;
+		}
+
+		for (j = 0; j < ecc->bytes; j++)
+			layout->eccpos[(ecc->bytes * i) + j] =
+					layout->oobfree[i].offset +
+					layout->oobfree[i].length + j;
+	}
+
+	if (mtd->oobsize > (ecc->bytes + 4) * nsectors) {
+		layout->oobfree[nsectors].offset =
+				layout->oobfree[nsectors - 1].offset +
+				layout->oobfree[nsectors - 1].length +
+				ecc->bytes;
+		layout->oobfree[nsectors].length = mtd->oobsize -
+				((ecc->bytes + 4) * nsectors);
+	}
+
+	return 0;
+}
+
+static int sunxi_nand_hw_syndrome_ecc_ctrl_init(struct mtd_info *mtd,
+						struct nand_ecc_ctrl *ecc)
+{
+	struct nand_ecclayout *layout;
+	int nsectors;
+	int i;
+	int ret;
+
+	ret = sunxi_nand_hw_common_ecc_ctrl_init(mtd, ecc);
+	if (ret)
+		return ret;
+
+	ecc->prepad = 4;
+	ecc->read_page = sunxi_nfc_hw_syndrome_ecc_read_page;
+	ecc->write_page = sunxi_nfc_hw_syndrome_ecc_write_page;
+
+	layout = ecc->layout;
+	nsectors = mtd->writesize / ecc->size;
+
+	for (i = 0; i < (ecc->bytes * nsectors); i++)
+		layout->eccpos[i] = i;
+
+	layout->oobfree[0].length = mtd->oobsize - i;
+	layout->oobfree[0].offset = i;
+
+	return 0;
+}
+
+#ifndef __UBOOT__
+static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc)
+{
+	switch (ecc->mode) {
+	case NAND_ECC_HW:
+	case NAND_ECC_HW_SYNDROME:
+		sunxi_nand_hw_common_ecc_ctrl_cleanup(ecc);
+		break;
+	case NAND_ECC_NONE:
+		kfree(ecc->layout);
+	default:
+		break;
+	}
+}
+#endif /* __UBOOT__ */
+
+static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc)
+{
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	int ret;
+
+	if (!ecc->size) {
+		ecc->size = nand->ecc_step_ds;
+		ecc->strength = nand->ecc_strength_ds;
+	}
+
+	if (!ecc->size || !ecc->strength)
+		return -EINVAL;
+
+	switch (ecc->mode) {
+	case NAND_ECC_SOFT_BCH:
+		break;
+	case NAND_ECC_HW:
+		ret = sunxi_nand_hw_ecc_ctrl_init(mtd, ecc);
+		if (ret)
+			return ret;
+		break;
+	case NAND_ECC_HW_SYNDROME:
+		ret = sunxi_nand_hw_syndrome_ecc_ctrl_init(mtd, ecc);
+		if (ret)
+			return ret;
+		break;
+	case NAND_ECC_NONE:
+		ecc->layout = kzalloc(sizeof(*ecc->layout), GFP_KERNEL);
+		if (!ecc->layout)
+			return -ENOMEM;
+		ecc->layout->oobfree[0].length = mtd->oobsize;
+	case NAND_ECC_SOFT:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int sunxi_nand_chip_init(int node, struct sunxi_nfc *nfc, int devnum)
+{
+	const struct nand_sdr_timings *timings;
+	const void *blob = gd->fdt_blob;
+	struct sunxi_nand_chip *chip;
+	struct mtd_info *mtd;
+	struct nand_chip *nand;
+	int nsels;
+	int ret;
+	int i;
+	u32 cs[8], rb[8];
+
+	if (!fdt_getprop(blob, node, "reg", &nsels))
+		return -EINVAL;
+
+	nsels /= sizeof(u32);
+	if (!nsels || nsels > 8) {
+		dev_err(dev, "invalid reg property size\n");
+		return -EINVAL;
+	}
+
+	chip = kzalloc(sizeof(*chip) +
+		       (nsels * sizeof(struct sunxi_nand_chip_sel)),
+		       GFP_KERNEL);
+	if (!chip) {
+		dev_err(dev, "could not allocate chip\n");
+		return -ENOMEM;
+	}
+
+	chip->nsels = nsels;
+	chip->selected = -1;
+
+	for (i = 0; i < nsels; i++) {
+		cs[i] = -1;
+		rb[i] = -1;
+	}
+
+	ret = fdtdec_get_int_array(gd->fdt_blob, node, "reg", cs, nsels);
+	if (ret) {
+		dev_err(dev, "could not retrieve reg property: %d\n", ret);
+		return ret;
+	}
+
+	ret = fdtdec_get_int_array(gd->fdt_blob, node, "allwinner,rb", rb,
+				   nsels);
+	if (ret) {
+		dev_err(dev, "could not retrieve reg property: %d\n", ret);
+		return ret;
+	}
+
+	for (i = 0; i < nsels; i++) {
+		int tmp = cs[i];
+
+		if (tmp > NFC_MAX_CS) {
+			dev_err(dev,
+				"invalid reg value: %u (max CS = 7)\n",
+				tmp);
+			return -EINVAL;
+		}
+
+		if (test_and_set_bit(tmp, &nfc->assigned_cs)) {
+			dev_err(dev, "CS %d already assigned\n", tmp);
+			return -EINVAL;
+		}
+
+		chip->sels[i].cs = tmp;
+
+		tmp = rb[i];
+		if (tmp >= 0 && tmp < 2) {
+			chip->sels[i].rb.type = RB_NATIVE;
+			chip->sels[i].rb.info.nativeid = tmp;
+		} else {
+			ret = gpio_request_by_name_nodev(blob, node,
+						"rb-gpios", i,
+						&chip->sels[i].rb.info.gpio,
+						GPIOD_IS_IN);
+			if (ret)
+				chip->sels[i].rb.type = RB_GPIO;
+			else
+				chip->sels[i].rb.type = RB_NONE;
+		}
+	}
+
+	timings = onfi_async_timing_mode_to_sdr_timings(0);
+	if (IS_ERR(timings)) {
+		ret = PTR_ERR(timings);
+		dev_err(dev,
+			"could not retrieve timings for ONFI mode 0: %d\n",
+			ret);
+		return ret;
+	}
+
+	ret = sunxi_nand_chip_set_timings(chip, timings);
+	if (ret) {
+		dev_err(dev, "could not configure chip timings: %d\n", ret);
+		return ret;
+	}
+
+	nand = &chip->nand;
+	/* Default tR value specified in the ONFI spec (chapter 4.15.1) */
+	nand->chip_delay = 200;
+	nand->controller = &nfc->controller;
+	/*
+	 * Set the ECC mode to the default value in case nothing is specified
+	 * in the DT.
+	 */
+	nand->ecc.mode = NAND_ECC_HW;
+	nand->flash_node = node;
+	nand->select_chip = sunxi_nfc_select_chip;
+	nand->cmd_ctrl = sunxi_nfc_cmd_ctrl;
+	nand->read_buf = sunxi_nfc_read_buf;
+	nand->write_buf = sunxi_nfc_write_buf;
+	nand->read_byte = sunxi_nfc_read_byte;
+
+	mtd = nand_to_mtd(nand);
+	ret = nand_scan_ident(mtd, nsels, NULL);
+	if (ret)
+		return ret;
+
+	if (nand->bbt_options & NAND_BBT_USE_FLASH)
+		nand->bbt_options |= NAND_BBT_NO_OOB;
+
+	if (nand->options & NAND_NEED_SCRAMBLING)
+		nand->options |= NAND_NO_SUBPAGE_WRITE;
+
+	nand->options |= NAND_SUBPAGE_READ;
+
+	ret = sunxi_nand_chip_init_timings(chip);
+	if (ret) {
+		dev_err(dev, "could not configure chip timings: %d\n", ret);
+		return ret;
+	}
+
+	ret = sunxi_nand_ecc_init(mtd, &nand->ecc);
+	if (ret) {
+		dev_err(dev, "ECC init failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = nand_scan_tail(mtd);
+	if (ret) {
+		dev_err(dev, "nand_scan_tail failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = nand_register(devnum, mtd);
+	if (ret) {
+		dev_err(dev, "failed to register mtd device: %d\n", ret);
+		return ret;
+	}
+
+	list_add_tail(&chip->node, &nfc->chips);
+
+	return 0;
+}
+
+static int sunxi_nand_chips_init(int node, struct sunxi_nfc *nfc)
+{
+	const void *blob = gd->fdt_blob;
+	int nand_node;
+	int ret, i = 0;
+
+	for (nand_node = fdt_first_subnode(blob, node); nand_node >= 0;
+	     nand_node = fdt_next_subnode(blob, nand_node))
+		i++;
+
+	if (i > 8) {
+		dev_err(dev, "too many NAND chips: %d (max = 8)\n", i);
+		return -EINVAL;
+	}
+
+	i = 0;
+	for (nand_node = fdt_first_subnode(blob, node); nand_node >= 0;
+	     nand_node = fdt_next_subnode(blob, nand_node)) {
+		ret = sunxi_nand_chip_init(nand_node, nfc, i++);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+#ifndef __UBOOT__
+static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc)
+{
+	struct sunxi_nand_chip *chip;
+
+	while (!list_empty(&nfc->chips)) {
+		chip = list_first_entry(&nfc->chips, struct sunxi_nand_chip,
+					node);
+		nand_release(&chip->mtd);
+		sunxi_nand_ecc_cleanup(&chip->nand.ecc);
+		list_del(&chip->node);
+		kfree(chip);
+	}
+}
+#endif /* __UBOOT__ */
+
+void sunxi_nand_init(void)
+{
+	const void *blob = gd->fdt_blob;
+	struct sunxi_nfc *nfc;
+	fdt_addr_t regs;
+	int node;
+	int ret;
+
+	nfc = kzalloc(sizeof(*nfc), GFP_KERNEL);
+	if (!nfc)
+		return;
+
+	spin_lock_init(&nfc->controller.lock);
+	init_waitqueue_head(&nfc->controller.wq);
+	INIT_LIST_HEAD(&nfc->chips);
+
+	node = fdtdec_next_compatible(blob, 0, COMPAT_SUNXI_NAND);
+	if (node < 0) {
+		pr_err("unable to find nfc node in device tree\n");
+		goto err;
+	}
+
+	if (!fdtdec_get_is_enabled(blob, node)) {
+		pr_err("nfc disabled in device tree\n");
+		goto err;
+	}
+
+	regs = fdtdec_get_addr(blob, node, "reg");
+	if (regs == FDT_ADDR_T_NONE) {
+		pr_err("unable to find nfc address in device tree\n");
+		goto err;
+	}
+
+	nfc->regs = (void *)regs;
+
+	ret = sunxi_nfc_rst(nfc);
+	if (ret)
+		goto err;
+
+	ret = sunxi_nand_chips_init(node, nfc);
+	if (ret) {
+		dev_err(dev, "failed to init nand chips\n");
+		goto err;
+	}
+
+	return;
+
+err:
+	kfree(nfc);
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Boris BREZILLON");
+MODULE_DESCRIPTION("Allwinner NAND Flash Controller driver");
diff --git a/drivers/mtd/nand/tegra_nand.c b/drivers/mtd/nand/tegra_nand.c
index 2032f65..38bd7a5 100644
--- a/drivers/mtd/nand/tegra_nand.c
+++ b/drivers/mtd/nand/tegra_nand.c
@@ -884,7 +884,7 @@
  * Decode NAND parameters from the device tree
  *
  * @param blob	Device tree blob
- * @param node	Node containing "nand-flash" compatble node
+ * @param node	Node containing "nand-flash" compatible node
  * @return 0 if ok, -ve on error (FDT_ERR_...)
  */
 static int fdt_decode_nand(const void *blob, int node, struct fdt_nand *config)
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 03deabc..0e35dc5 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -20,6 +20,7 @@
  */
 
 #include <common.h>
+#include <watchdog.h>
 #include <linux/compat.h>
 #include <linux/mtd/mtd.h>
 #include "linux/mtd/flashchip.h"
@@ -467,15 +468,18 @@
 static int onenand_wait(struct mtd_info *mtd, int state)
 {
 	struct onenand_chip *this = mtd->priv;
-	unsigned int flags = ONENAND_INT_MASTER;
 	unsigned int interrupt = 0;
 	unsigned int ctrl;
 
-	while (1) {
+	/* Wait at most 20ms ... */
+	u32 timeo = (CONFIG_SYS_HZ * 20) / 1000;
+	u32 time_start = get_timer(0);
+	do {
+		WATCHDOG_RESET();
+		if (get_timer(time_start) > timeo)
+			return -EIO;
 		interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
-		if (interrupt & flags)
-			break;
-	}
+	} while ((interrupt & ONENAND_INT_MASTER) == 0);
 
 	ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
 
@@ -1154,15 +1158,18 @@
 static int onenand_bbt_wait(struct mtd_info *mtd, int state)
 {
 	struct onenand_chip *this = mtd->priv;
-	unsigned int flags = ONENAND_INT_MASTER;
 	unsigned int interrupt;
 	unsigned int ctrl;
 
-	while (1) {
+	/* Wait at most 20ms ... */
+	u32 timeo = (CONFIG_SYS_HZ * 20) / 1000;
+	u32 time_start = get_timer(0);
+	do {
+		WATCHDOG_RESET();
+		if (get_timer(time_start) > timeo)
+			return ONENAND_BBT_READ_FATAL_ERROR;
 		interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
-		if (interrupt & flags)
-			break;
-	}
+	} while ((interrupt & ONENAND_INT_MASTER) == 0);
 
 	/* To get correct interrupt status in timeout case */
 	interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
@@ -2536,7 +2543,8 @@
 	this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM);
 
 	/* Wait reset */
-	this->wait(mtd, FL_RESETING);
+	if (this->wait(mtd, FL_RESETING))
+		return -ENXIO;
 
 	/* Restore system configuration 1 */
 	this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
@@ -2649,6 +2657,7 @@
 	mtd->_sync = onenand_sync;
 	mtd->_block_isbad = onenand_block_isbad;
 	mtd->_block_markbad = onenand_block_markbad;
+	mtd->writebufsize = mtd->writesize;
 
 	return 0;
 }
diff --git a/drivers/mtd/onenand/onenand_spl.c b/drivers/mtd/onenand/onenand_spl.c
index fe6b7d9..1925f41 100644
--- a/drivers/mtd/onenand/onenand_spl.c
+++ b/drivers/mtd/onenand/onenand_spl.c
@@ -93,6 +93,54 @@
 	return 0;
 }
 
+#ifdef CONFIG_SPL_UBI
+/* Temporary storage for non page aligned and non page sized reads. */
+static u8 scratch_buf[PAGE_4K];
+
+/**
+ * onenand_spl_read_block - Read data from physical eraseblock into a buffer
+ * @block:	Number of the physical eraseblock
+ * @offset:	Data offset from the start of @peb
+ * @len:	Data size to read
+ * @dst:	Address of the destination buffer
+ *
+ * Notes:
+ *	@offset + @len are not allowed to be larger than a physical
+ *	erase block. No sanity check done for simplicity reasons.
+ */
+int onenand_spl_read_block(int block, int offset, int len, void *dst)
+{
+	int page, read, psize;
+
+	psize = onenand_spl_get_geometry();
+	/* Calculate the page number */
+	page = offset / psize;
+	/* Offset to the start of a flash page */
+	offset = offset % psize;
+
+	while (len) {
+		/*
+		 * Non page aligned reads go to the scratch buffer.
+		 * Page aligned reads go directly to the destination.
+		 */
+		if (offset || len < psize) {
+			onenand_spl_read_page(block, page,
+			                      (uint32_t *)scratch_buf, psize);
+			read = min(len, psize - offset);
+			memcpy(dst, scratch_buf + offset, read);
+			offset = 0;
+		} else {
+			onenand_spl_read_page(block, page, dst, psize);
+			read = psize;
+		}
+		page++;
+		len -= read;
+		dst += read;
+	}
+	return 0;
+}
+#endif
+
 void onenand_spl_load_image(uint32_t offs, uint32_t size, void *dst)
 {
 	uint32_t *addr = (uint32_t *)dst;
diff --git a/drivers/mtd/onenand/onenand_uboot.c b/drivers/mtd/onenand/onenand_uboot.c
index ae60c3b..c15ec9d 100644
--- a/drivers/mtd/onenand/onenand_uboot.c
+++ b/drivers/mtd/onenand/onenand_uboot.c
@@ -24,33 +24,33 @@
 
 void onenand_init(void)
 {
+	int err = 0;
 	memset(&onenand_mtd, 0, sizeof(struct mtd_info));
 	memset(&onenand_chip, 0, sizeof(struct onenand_chip));
 
 	onenand_mtd.priv = &onenand_chip;
 
 #ifdef CONFIG_USE_ONENAND_BOARD_INIT
-	/*
-	 * It's used for some board init required
-	 */
-	onenand_board_init(&onenand_mtd);
+	/* It's used for some board init required */
+	err = onenand_board_init(&onenand_mtd);
 #else
 	onenand_chip.base = (void *) CONFIG_SYS_ONENAND_BASE;
 #endif
 
-	onenand_scan(&onenand_mtd, 1);
+	if (!err && !(onenand_scan(&onenand_mtd, 1))) {
 
-	if (onenand_chip.device_id & DEVICE_IS_FLEXONENAND)
-		puts("Flex-");
-	puts("OneNAND: ");
-	print_size(onenand_chip.chipsize, "\n");
+		if (onenand_chip.device_id & DEVICE_IS_FLEXONENAND)
+			puts("Flex-");
+		puts("OneNAND: ");
 
 #ifdef CONFIG_MTD_DEVICE
-	/*
-	 * Add MTD device so that we can reference it later
-	 * via the mtdcore infrastructure (e.g. ubi).
-	 */
-	onenand_mtd.name = dev_name;
-	add_mtd_device(&onenand_mtd);
+		/*
+		 * Add MTD device so that we can reference it later
+		 * via the mtdcore infrastructure (e.g. ubi).
+		 */
+		onenand_mtd.name = dev_name;
+		add_mtd_device(&onenand_mtd);
 #endif
+	}
+	print_size(onenand_chip.chipsize, "\n");
 }
diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig
index 3f7433c..1f23c8e 100644
--- a/drivers/mtd/spi/Kconfig
+++ b/drivers/mtd/spi/Kconfig
@@ -128,4 +128,16 @@
 
 	  If unsure, say N
 
+if SPL
+
+config SPL_SPI_SUNXI
+	bool "Support for SPI Flash on Allwinner SoCs in SPL"
+	depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUN8I_H3 || MACH_SUN50I
+	---help---
+	Enable support for SPI Flash. This option allows SPL to read from
+	sunxi SPI Flash. It uses the same method as the boot ROM, so does
+	not need any extra configuration.
+
+endif
+
 endmenu # menu "SPI Flash Support"
diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile
index c665836..6f47a66 100644
--- a/drivers/mtd/spi/Makefile
+++ b/drivers/mtd/spi/Makefile
@@ -10,6 +10,7 @@
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SPL_SPI_LOAD)	+= spi_spl_load.o
 obj-$(CONFIG_SPL_SPI_BOOT)	+= fsl_espi_spl.o
+obj-$(CONFIG_SPL_SPI_SUNXI)	+= sunxi_spi_spl.o
 endif
 
 obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi_flash.o sf_params.o sf.o
diff --git a/drivers/mtd/spi/sf_params.c b/drivers/mtd/spi/sf_params.c
index c577d9e..70ca236 100644
--- a/drivers/mtd/spi/sf_params.c
+++ b/drivers/mtd/spi/sf_params.c
@@ -22,7 +22,8 @@
 	{"AT45DB161D",	   0x1f2600, 0x0,	64 * 1024,    32, RD_NORM,		    SECT_4K},
 	{"AT45DB321D",	   0x1f2700, 0x0,	64 * 1024,    64, RD_NORM,		    SECT_4K},
 	{"AT45DB641D",	   0x1f2800, 0x0,	64 * 1024,   128, RD_NORM,		    SECT_4K},
-	{"AT25DF321",      0x1f4701, 0x0,	64 * 1024,    64, RD_NORM,		    SECT_4K},
+	{"AT25DF321A",     0x1f4701, 0x0,	64 * 1024,    64, RD_NORM,		    SECT_4K},
+	{"AT25DF321",      0x1f4700, 0x0,	64 * 1024,    64, RD_NORM,		    SECT_4K},
 	{"AT26DF081A",     0x1f4501, 0x0,	64 * 1024,    16, RD_NORM,		    SECT_4K},
 #endif
 #ifdef CONFIG_SPI_FLASH_EON		/* EON */
@@ -84,6 +85,7 @@
 	{"M25P64",	   0x202017, 0x0,       64 * 1024,   128, RD_NORM,			  0},
 	{"M25P128",	   0x202018, 0x0,      256 * 1024,    64, RD_NORM,			  0},
 	{"M25PX64",	   0x207117, 0x0,       64 * 1024,   128, RD_NORM,		    SECT_4K},
+	{"N25Q016A",       0x20bb15, 0x0,	64 * 1024,    32, RD_NORM,                  SECT_4K},
 	{"N25Q32",	   0x20ba16, 0x0,       64 * 1024,    64, RD_FULL,	   WR_QPP | SECT_4K},
 	{"N25Q32A",	   0x20bb16, 0x0,       64 * 1024,    64, RD_FULL,	   WR_QPP | SECT_4K},
 	{"N25Q64",	   0x20ba17, 0x0,       64 * 1024,   128, RD_FULL,	   WR_QPP | SECT_4K},
diff --git a/drivers/mtd/spi/sunxi_spi_spl.c b/drivers/mtd/spi/sunxi_spi_spl.c
new file mode 100644
index 0000000..e3ded5b
--- /dev/null
+++ b/drivers/mtd/spi/sunxi_spi_spl.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2016 Siarhei Siamashka <siarhei.siamashka@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <spl.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_SPL_OS_BOOT
+#error CONFIG_SPL_OS_BOOT is not supported yet
+#endif
+
+/*
+ * This is a very simple U-Boot image loading implementation, trying to
+ * replicate what the boot ROM is doing when loading the SPL. Because we
+ * know the exact pins where the SPI Flash is connected and also know
+ * that the Read Data Bytes (03h) command is supported, the hardware
+ * configuration is very simple and we don't need the extra flexibility
+ * of the SPI framework. Moreover, we rely on the default settings of
+ * the SPI controler hardware registers and only adjust what needs to
+ * be changed. This is good for the code size and this implementation
+ * adds less than 400 bytes to the SPL.
+ *
+ * There are two variants of the SPI controller in Allwinner SoCs:
+ * A10/A13/A20 (sun4i variant) and everything else (sun6i variant).
+ * Both of them are supported.
+ *
+ * The pin mixing part is SoC specific and only A10/A13/A20/H3/A64 are
+ * supported at the moment.
+ */
+
+/*****************************************************************************/
+/* SUN4I variant of the SPI controller                                       */
+/*****************************************************************************/
+
+#define SUN4I_SPI0_CCTL             (0x01C05000 + 0x1C)
+#define SUN4I_SPI0_CTL              (0x01C05000 + 0x08)
+#define SUN4I_SPI0_RX               (0x01C05000 + 0x00)
+#define SUN4I_SPI0_TX               (0x01C05000 + 0x04)
+#define SUN4I_SPI0_FIFO_STA         (0x01C05000 + 0x28)
+#define SUN4I_SPI0_BC               (0x01C05000 + 0x20)
+#define SUN4I_SPI0_TC               (0x01C05000 + 0x24)
+
+#define SUN4I_CTL_ENABLE            BIT(0)
+#define SUN4I_CTL_MASTER            BIT(1)
+#define SUN4I_CTL_TF_RST            BIT(8)
+#define SUN4I_CTL_RF_RST            BIT(9)
+#define SUN4I_CTL_XCH               BIT(10)
+
+/*****************************************************************************/
+/* SUN6I variant of the SPI controller                                       */
+/*****************************************************************************/
+
+#define SUN6I_SPI0_CCTL             (0x01C68000 + 0x24)
+#define SUN6I_SPI0_GCR              (0x01C68000 + 0x04)
+#define SUN6I_SPI0_TCR              (0x01C68000 + 0x08)
+#define SUN6I_SPI0_FIFO_STA         (0x01C68000 + 0x1C)
+#define SUN6I_SPI0_MBC              (0x01C68000 + 0x30)
+#define SUN6I_SPI0_MTC              (0x01C68000 + 0x34)
+#define SUN6I_SPI0_BCC              (0x01C68000 + 0x38)
+#define SUN6I_SPI0_TXD              (0x01C68000 + 0x200)
+#define SUN6I_SPI0_RXD              (0x01C68000 + 0x300)
+
+#define SUN6I_CTL_ENABLE            BIT(0)
+#define SUN6I_CTL_MASTER            BIT(1)
+#define SUN6I_CTL_SRST              BIT(31)
+#define SUN6I_TCR_XCH               BIT(31)
+
+/*****************************************************************************/
+
+#define CCM_AHB_GATING0             (0x01C20000 + 0x60)
+#define CCM_SPI0_CLK                (0x01C20000 + 0xA0)
+#define SUN6I_BUS_SOFT_RST_REG0     (0x01C20000 + 0x2C0)
+
+#define AHB_RESET_SPI0_SHIFT        20
+#define AHB_GATE_OFFSET_SPI0        20
+
+#define SPI0_CLK_DIV_BY_2           0x1000
+#define SPI0_CLK_DIV_BY_4           0x1001
+
+/*****************************************************************************/
+
+/*
+ * Allwinner A10/A20 SoCs were using pins PC0,PC1,PC2,PC23 for booting
+ * from SPI Flash, everything else is using pins PC0,PC1,PC2,PC3.
+ */
+static void spi0_pinmux_setup(unsigned int pin_function)
+{
+	unsigned int pin;
+
+	for (pin = SUNXI_GPC(0); pin <= SUNXI_GPC(2); pin++)
+		sunxi_gpio_set_cfgpin(pin, pin_function);
+
+	if (IS_ENABLED(CONFIG_MACH_SUN4I) || IS_ENABLED(CONFIG_MACH_SUN7I))
+		sunxi_gpio_set_cfgpin(SUNXI_GPC(23), pin_function);
+	else
+		sunxi_gpio_set_cfgpin(SUNXI_GPC(3), pin_function);
+}
+
+/*
+ * Setup 6 MHz from OSC24M (because the BROM is doing the same).
+ */
+static void spi0_enable_clock(void)
+{
+	/* Deassert SPI0 reset on SUN6I */
+	if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
+		setbits_le32(SUN6I_BUS_SOFT_RST_REG0,
+			     (1 << AHB_RESET_SPI0_SHIFT));
+
+	/* Open the SPI0 gate */
+	setbits_le32(CCM_AHB_GATING0, (1 << AHB_GATE_OFFSET_SPI0));
+
+	/* Divide by 4 */
+	writel(SPI0_CLK_DIV_BY_4, IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I) ?
+				  SUN6I_SPI0_CCTL : SUN4I_SPI0_CCTL);
+	/* 24MHz from OSC24M */
+	writel((1 << 31), CCM_SPI0_CLK);
+
+	if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I)) {
+		/* Enable SPI in the master mode and do a soft reset */
+		setbits_le32(SUN6I_SPI0_GCR, SUN6I_CTL_MASTER |
+					     SUN6I_CTL_ENABLE |
+					     SUN6I_CTL_SRST);
+		/* Wait for completion */
+		while (readl(SUN6I_SPI0_GCR) & SUN6I_CTL_SRST)
+			;
+	} else {
+		/* Enable SPI in the master mode and reset FIFO */
+		setbits_le32(SUN4I_SPI0_CTL, SUN4I_CTL_MASTER |
+					     SUN4I_CTL_ENABLE |
+					     SUN4I_CTL_TF_RST |
+					     SUN4I_CTL_RF_RST);
+	}
+}
+
+static void spi0_disable_clock(void)
+{
+	/* Disable the SPI0 controller */
+	if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
+		clrbits_le32(SUN6I_SPI0_GCR, SUN6I_CTL_MASTER |
+					     SUN6I_CTL_ENABLE);
+	else
+		clrbits_le32(SUN4I_SPI0_CTL, SUN4I_CTL_MASTER |
+					     SUN4I_CTL_ENABLE);
+
+	/* Disable the SPI0 clock */
+	writel(0, CCM_SPI0_CLK);
+
+	/* Close the SPI0 gate */
+	clrbits_le32(CCM_AHB_GATING0, (1 << AHB_GATE_OFFSET_SPI0));
+
+	/* Assert SPI0 reset on SUN6I */
+	if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
+		clrbits_le32(SUN6I_BUS_SOFT_RST_REG0,
+			     (1 << AHB_RESET_SPI0_SHIFT));
+}
+
+static int spi0_init(void)
+{
+	unsigned int pin_function = SUNXI_GPC_SPI0;
+	if (IS_ENABLED(CONFIG_MACH_SUN50I))
+		pin_function = SUN50I_GPC_SPI0;
+
+	spi0_pinmux_setup(pin_function);
+	spi0_enable_clock();
+}
+
+static void spi0_deinit(void)
+{
+	/* New SoCs can disable pins, older could only set them as input */
+	unsigned int pin_function = SUNXI_GPIO_INPUT;
+	if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
+		pin_function = SUNXI_GPIO_DISABLE;
+
+	spi0_disable_clock();
+	spi0_pinmux_setup(pin_function);
+}
+
+/*****************************************************************************/
+
+#define SPI_READ_MAX_SIZE 60 /* FIFO size, minus 4 bytes of the header */
+
+static void sunxi_spi0_read_data(u8 *buf, u32 addr, u32 bufsize,
+				 u32 spi_ctl_reg,
+				 u32 spi_ctl_xch_bitmask,
+				 u32 spi_fifo_reg,
+				 u32 spi_tx_reg,
+				 u32 spi_rx_reg,
+				 u32 spi_bc_reg,
+				 u32 spi_tc_reg,
+				 u32 spi_bcc_reg)
+{
+	writel(4 + bufsize, spi_bc_reg); /* Burst counter (total bytes) */
+	writel(4, spi_tc_reg);           /* Transfer counter (bytes to send) */
+	if (spi_bcc_reg)
+		writel(4, spi_bcc_reg);  /* SUN6I also needs this */
+
+	/* Send the Read Data Bytes (03h) command header */
+	writeb(0x03, spi_tx_reg);
+	writeb((u8)(addr >> 16), spi_tx_reg);
+	writeb((u8)(addr >> 8), spi_tx_reg);
+	writeb((u8)(addr), spi_tx_reg);
+
+	/* Start the data transfer */
+	setbits_le32(spi_ctl_reg, spi_ctl_xch_bitmask);
+
+	/* Wait until everything is received in the RX FIFO */
+	while ((readl(spi_fifo_reg) & 0x7F) < 4 + bufsize)
+		;
+
+	/* Skip 4 bytes */
+	readl(spi_rx_reg);
+
+	/* Read the data */
+	while (bufsize-- > 0)
+		*buf++ = readb(spi_rx_reg);
+
+	/* tSHSL time is up to 100 ns in various SPI flash datasheets */
+	udelay(1);
+}
+
+static void spi0_read_data(void *buf, u32 addr, u32 len)
+{
+	u8 *buf8 = buf;
+	u32 chunk_len;
+
+	while (len > 0) {
+		chunk_len = len;
+		if (chunk_len > SPI_READ_MAX_SIZE)
+			chunk_len = SPI_READ_MAX_SIZE;
+
+		if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I)) {
+			sunxi_spi0_read_data(buf8, addr, chunk_len,
+					     SUN6I_SPI0_TCR,
+					     SUN6I_TCR_XCH,
+					     SUN6I_SPI0_FIFO_STA,
+					     SUN6I_SPI0_TXD,
+					     SUN6I_SPI0_RXD,
+					     SUN6I_SPI0_MBC,
+					     SUN6I_SPI0_MTC,
+					     SUN6I_SPI0_BCC);
+		} else {
+			sunxi_spi0_read_data(buf8, addr, chunk_len,
+					     SUN4I_SPI0_CTL,
+					     SUN4I_CTL_XCH,
+					     SUN4I_SPI0_FIFO_STA,
+					     SUN4I_SPI0_TX,
+					     SUN4I_SPI0_RX,
+					     SUN4I_SPI0_BC,
+					     SUN4I_SPI0_TC,
+					     0);
+		}
+
+		len  -= chunk_len;
+		buf8 += chunk_len;
+		addr += chunk_len;
+	}
+}
+
+/*****************************************************************************/
+
+int spl_spi_load_image(void)
+{
+	int err;
+	struct image_header *header;
+	header = (struct image_header *)(CONFIG_SYS_TEXT_BASE);
+
+	spi0_init();
+
+	spi0_read_data((void *)header, CONFIG_SYS_SPI_U_BOOT_OFFS, 0x40);
+	err = spl_parse_image_header(header);
+	if (err)
+		return err;
+
+	spi0_read_data((void *)spl_image.load_addr, CONFIG_SYS_SPI_U_BOOT_OFFS,
+		       spl_image.size);
+
+	spi0_deinit();
+	return 0;
+}
diff --git a/drivers/mtd/ubispl/Makefile b/drivers/mtd/ubispl/Makefile
new file mode 100644
index 0000000..740dbed
--- /dev/null
+++ b/drivers/mtd/ubispl/Makefile
@@ -0,0 +1 @@
+obj-y += ubispl.o ../ubi/crc32.o
diff --git a/drivers/mtd/ubispl/ubi-wrapper.h b/drivers/mtd/ubispl/ubi-wrapper.h
new file mode 100644
index 0000000..72b9dcb
--- /dev/null
+++ b/drivers/mtd/ubispl/ubi-wrapper.h
@@ -0,0 +1,106 @@
+/*
+ * The parts taken from the kernel implementation are:
+ *
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * UBISPL specific defines:
+ *
+ * Copyright (c) Thomas Gleixner <tglx@linutronix.de>
+ *
+ * SPDX-License-Identifier: GPL 2.0+ BSD-3-Clause
+ */
+
+/*
+ * Contains various defines copy&pasted from ubi.h and ubi-user.h to make
+ * the upstream fastboot code happy.
+ */
+#ifndef __UBOOT_UBI_WRAPPER_H
+#define __UBOOT_UBI_WRAPPER_H
+
+/*
+ * Error codes returned by the I/O sub-system.
+ *
+ * UBI_IO_FF: the read region of flash contains only 0xFFs
+ * UBI_IO_FF_BITFLIPS: the same as %UBI_IO_FF, but also also there was a data
+ *                     integrity error reported by the MTD driver
+ *                     (uncorrectable ECC error in case of NAND)
+ * UBI_IO_BAD_HDR: the EC or VID header is corrupted (bad magic or CRC)
+ * UBI_IO_BAD_HDR_EBADMSG: the same as %UBI_IO_BAD_HDR, but also there was a
+ *                         data integrity error reported by the MTD driver
+ *                         (uncorrectable ECC error in case of NAND)
+ * UBI_IO_BITFLIPS: bit-flips were detected and corrected
+ *
+ * UBI_FASTMAP_ANCHOR:  u-boot SPL add on to tell the caller that the fastmap
+ *			anchor block has been found
+ *
+ * Note, it is probably better to have bit-flip and ebadmsg as flags which can
+ * be or'ed with other error code. But this is a big change because there are
+ * may callers, so it does not worth the risk of introducing a bug
+ */
+enum {
+	UBI_IO_FF = 1,
+	UBI_IO_FF_BITFLIPS,
+	UBI_IO_BAD_HDR,
+	UBI_IO_BAD_HDR_EBADMSG,
+	UBI_IO_BITFLIPS,
+	UBI_FASTMAP_ANCHOR,
+};
+
+/*
+ * UBI volume type constants.
+ *
+ * @UBI_DYNAMIC_VOLUME: dynamic volume
+ * @UBI_STATIC_VOLUME:  static volume
+ */
+enum {
+	UBI_DYNAMIC_VOLUME = 3,
+	UBI_STATIC_VOLUME  = 4,
+};
+
+/*
+ * Return codes of the fastmap sub-system
+ *
+ * UBI_NO_FASTMAP: No fastmap super block was found
+ * UBI_BAD_FASTMAP: A fastmap was found but it's unusable
+ */
+enum {
+	UBI_NO_FASTMAP = 1,
+	UBI_BAD_FASTMAP,
+};
+
+/**
+ * struct ubi_fastmap_layout - in-memory fastmap data structure.
+ * @e: PEBs used by the current fastmap
+ * @to_be_tortured: if non-zero tortured this PEB
+ * @used_blocks: number of used PEBs
+ * @max_pool_size: maximal size of the user pool
+ * @max_wl_pool_size: maximal size of the pool used by the WL sub-system
+ */
+struct ubi_fastmap_layout {
+	struct ubi_wl_entry *e[UBI_FM_MAX_BLOCKS];
+	int to_be_tortured[UBI_FM_MAX_BLOCKS];
+	int used_blocks;
+	int max_pool_size;
+	int max_wl_pool_size;
+};
+
+/**
+ * struct ubi_fm_pool - in-memory fastmap pool
+ * @pebs: PEBs in this pool
+ * @used: number of used PEBs
+ * @size: total number of PEBs in this pool
+ * @max_size: maximal size of the pool
+ *
+ * A pool gets filled with up to max_size.
+ * If all PEBs within the pool are used a new fastmap will be written
+ * to the flash and the pool gets refilled with empty PEBs.
+ *
+ */
+struct ubi_fm_pool {
+	int pebs[UBI_FM_MAX_POOL_SIZE];
+	int used;
+	int size;
+	int max_size;
+};
+
+#endif
diff --git a/drivers/mtd/ubispl/ubispl.c b/drivers/mtd/ubispl/ubispl.c
new file mode 100644
index 0000000..a81a8e7
--- /dev/null
+++ b/drivers/mtd/ubispl/ubispl.c
@@ -0,0 +1,926 @@
+/*
+ * Copyright (c) Thomas Gleixner <tglx@linutronix.de>
+ *
+ * The parts taken from the kernel implementation are:
+ *
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * SPDX-License-Identifier: GPL 2.0+ BSD-3-Clause
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <ubispl.h>
+
+#include <linux/crc32.h>
+
+#include "ubispl.h"
+
+/**
+ * ubi_calc_fm_size - calculates the fastmap size in bytes for an UBI device.
+ * @ubi: UBI device description object
+ */
+static size_t ubi_calc_fm_size(struct ubi_scan_info *ubi)
+{
+	size_t size;
+
+	size = sizeof(struct ubi_fm_sb) +
+		sizeof(struct ubi_fm_hdr) +
+		sizeof(struct ubi_fm_scan_pool) +
+		sizeof(struct ubi_fm_scan_pool) +
+		(ubi->peb_count * sizeof(struct ubi_fm_ec)) +
+		(sizeof(struct ubi_fm_eba) +
+		(ubi->peb_count * sizeof(__be32))) +
+		sizeof(struct ubi_fm_volhdr) * UBI_MAX_VOLUMES;
+	return roundup(size, ubi->leb_size);
+}
+
+static int ubi_io_read(struct ubi_scan_info *ubi, void *buf, int pnum,
+		       unsigned long from, unsigned long len)
+{
+	return ubi->read(pnum + ubi->peb_offset, from, len, buf);
+}
+
+static int ubi_io_is_bad(struct ubi_scan_info *ubi, int peb)
+{
+	return peb >= ubi->peb_count || peb < 0;
+}
+
+static int ubi_io_read_vid_hdr(struct ubi_scan_info *ubi, int pnum,
+			       struct ubi_vid_hdr *vh, int unused)
+{
+	u32 magic;
+	int res;
+
+	/* No point in rescanning a corrupt block */
+	if (test_bit(pnum, ubi->corrupt))
+		return UBI_IO_BAD_HDR;
+	/*
+	 * If the block has been scanned already, no need to rescan
+	 */
+	if (test_and_set_bit(pnum, ubi->scanned))
+		return 0;
+
+	res = ubi_io_read(ubi, vh, pnum, ubi->vid_offset, sizeof(*vh));
+
+	/*
+	 * Bad block, unrecoverable ECC error, skip the block
+	 */
+	if (res) {
+		ubi_dbg("Skipping bad or unreadable block %d", pnum);
+		vh->magic = 0;
+		generic_set_bit(pnum, ubi->corrupt);
+		return res;
+	}
+
+	/* Magic number available ? */
+	magic = be32_to_cpu(vh->magic);
+	if (magic != UBI_VID_HDR_MAGIC) {
+		generic_set_bit(pnum, ubi->corrupt);
+		if (magic == 0xffffffff)
+			return UBI_IO_FF;
+		ubi_msg("Bad magic in block 0%d %08x", pnum, magic);
+		return UBI_IO_BAD_HDR;
+	}
+
+	/* Header CRC correct ? */
+	if (crc32(UBI_CRC32_INIT, vh, UBI_VID_HDR_SIZE_CRC) !=
+	    be32_to_cpu(vh->hdr_crc)) {
+		ubi_msg("Bad CRC in block 0%d", pnum);
+		generic_set_bit(pnum, ubi->corrupt);
+		return UBI_IO_BAD_HDR;
+	}
+
+	ubi_dbg("RV: pnum: %i sqnum %llu", pnum, be64_to_cpu(vh->sqnum));
+
+	return 0;
+}
+
+static int ubi_rescan_fm_vid_hdr(struct ubi_scan_info *ubi,
+				 struct ubi_vid_hdr *vh,
+				 u32 fm_pnum, u32 fm_vol_id, u32 fm_lnum)
+{
+	int res;
+
+	if (ubi_io_is_bad(ubi, fm_pnum))
+		return -EINVAL;
+
+	res = ubi_io_read_vid_hdr(ubi, fm_pnum, vh, 0);
+	if (!res) {
+		/* Check volume id, volume type and lnum */
+		if (be32_to_cpu(vh->vol_id) == fm_vol_id &&
+		    vh->vol_type == UBI_VID_STATIC &&
+		    be32_to_cpu(vh->lnum) == fm_lnum)
+			return 0;
+		ubi_dbg("RS: PEB %u vol: %u : %u typ %u lnum %u %u",
+			fm_pnum, fm_vol_id, vh->vol_type,
+			be32_to_cpu(vh->vol_id),
+			fm_lnum, be32_to_cpu(vh->lnum));
+	}
+	return res;
+}
+
+/* Insert the logic block into the volume info */
+static int ubi_add_peb_to_vol(struct ubi_scan_info *ubi,
+			      struct ubi_vid_hdr *vh, u32 vol_id,
+			      u32 pnum, u32 lnum)
+{
+	struct ubi_vol_info *vi = ubi->volinfo + vol_id;
+	u32 *ltp;
+
+	/*
+	 * If the volume is larger than expected, yell and give up :(
+	 */
+	if (lnum >= UBI_MAX_VOL_LEBS) {
+		ubi_warn("Vol: %u LEB %d > %d", vol_id, lnum, UBI_MAX_VOL_LEBS);
+		return -EINVAL;
+	}
+
+	ubi_dbg("SC: Add PEB %u to Vol %u as LEB %u fnd %d sc %d",
+		pnum, vol_id, lnum, !!test_bit(lnum, vi->found),
+		!!test_bit(pnum, ubi->scanned));
+
+	/* Points to the translation entry */
+	ltp = vi->lebs_to_pebs + lnum;
+
+	/* If the block is already assigned, check sqnum */
+	if (__test_and_set_bit(lnum, vi->found)) {
+		u32 cur_pnum = *ltp;
+		struct ubi_vid_hdr *cur = ubi->blockinfo + cur_pnum;
+
+		/*
+		 * If the current block hase not yet been scanned, we
+		 * need to do that. The other block might be stale or
+		 * the current block corrupted and the FM not yet
+		 * updated.
+		 */
+		if (!test_bit(cur_pnum, ubi->scanned)) {
+			/*
+			 * If the scan fails, we use the valid block
+			 */
+			if (ubi_rescan_fm_vid_hdr(ubi, cur, cur_pnum, vol_id,
+						  lnum)) {
+				*ltp = pnum;
+				return 0;
+			}
+		}
+
+		/*
+		 * Should not happen ....
+		 */
+		if (test_bit(cur_pnum, ubi->corrupt)) {
+			*ltp = pnum;
+			return 0;
+		}
+
+		ubi_dbg("Vol %u LEB %u PEB %u->sqnum %llu NPEB %u->sqnum %llu",
+			vol_id, lnum, cur_pnum, be64_to_cpu(cur->sqnum), pnum,
+			be64_to_cpu(vh->sqnum));
+
+		/*
+		 * Compare sqnum and take the newer one
+		 */
+		if (be64_to_cpu(cur->sqnum) < be64_to_cpu(vh->sqnum))
+			*ltp = pnum;
+	} else {
+		*ltp = pnum;
+		if (lnum > vi->last_block)
+			vi->last_block = lnum;
+	}
+
+	return 0;
+}
+
+static int ubi_scan_vid_hdr(struct ubi_scan_info *ubi, struct ubi_vid_hdr *vh,
+			    u32 pnum)
+{
+	u32 vol_id, lnum;
+	int res;
+
+	if (ubi_io_is_bad(ubi, pnum))
+		return -EINVAL;
+
+	res = ubi_io_read_vid_hdr(ubi, pnum, vh, 0);
+	if (res)
+		return res;
+
+	/* Get volume id */
+	vol_id = be32_to_cpu(vh->vol_id);
+
+	/* If this is the fastmap anchor, return right away */
+	if (vol_id == UBI_FM_SB_VOLUME_ID)
+		return ubi->fm_enabled ? UBI_FASTMAP_ANCHOR : 0;
+
+	/* We only care about static volumes with an id < UBI_SPL_VOL_IDS */
+	if (vol_id >= UBI_SPL_VOL_IDS || vh->vol_type != UBI_VID_STATIC)
+		return 0;
+
+	/* We are only interested in the volumes to load */
+	if (!test_bit(vol_id, ubi->toload))
+		return 0;
+
+	lnum = be32_to_cpu(vh->lnum);
+	return ubi_add_peb_to_vol(ubi, vh, vol_id, pnum, lnum);
+}
+
+static int assign_aeb_to_av(struct ubi_scan_info *ubi, u32 pnum, u32 lnum,
+			     u32 vol_id, u32 vol_type, u32 used)
+{
+	struct ubi_vid_hdr *vh;
+
+	if (ubi_io_is_bad(ubi, pnum))
+		return -EINVAL;
+
+	ubi->fastmap_pebs++;
+
+	if (vol_id >= UBI_SPL_VOL_IDS || vol_type != UBI_STATIC_VOLUME)
+		return 0;
+
+	/* We are only interested in the volumes to load */
+	if (!test_bit(vol_id, ubi->toload))
+		return 0;
+
+	vh = ubi->blockinfo + pnum;
+
+	return ubi_scan_vid_hdr(ubi, vh, pnum);
+}
+
+static int scan_pool(struct ubi_scan_info *ubi, __be32 *pebs, int pool_size)
+{
+	struct ubi_vid_hdr *vh;
+	u32 pnum;
+	int i;
+
+	ubi_dbg("Scanning pool size: %d", pool_size);
+
+	for (i = 0; i < pool_size; i++) {
+		pnum = be32_to_cpu(pebs[i]);
+
+		if (ubi_io_is_bad(ubi, pnum)) {
+			ubi_err("FM: Bad PEB in fastmap pool! %u", pnum);
+			return UBI_BAD_FASTMAP;
+		}
+
+		vh = ubi->blockinfo + pnum;
+		/*
+		 * We allow the scan to fail here. The loader will notice
+		 * and look for a replacement.
+		 */
+		ubi_scan_vid_hdr(ubi, vh, pnum);
+	}
+	return 0;
+}
+
+/*
+ * Fastmap code is stolen from Linux kernel and this stub structure is used
+ * to make it happy.
+ */
+struct ubi_attach_info {
+	int i;
+};
+
+static int ubi_attach_fastmap(struct ubi_scan_info *ubi,
+			      struct ubi_attach_info *ai,
+			      struct ubi_fastmap_layout *fm)
+{
+	struct ubi_fm_hdr *fmhdr;
+	struct ubi_fm_scan_pool *fmpl1, *fmpl2;
+	struct ubi_fm_ec *fmec;
+	struct ubi_fm_volhdr *fmvhdr;
+	struct ubi_fm_eba *fm_eba;
+	int ret, i, j, pool_size, wl_pool_size;
+	size_t fm_pos = 0, fm_size = ubi->fm_size;
+	void *fm_raw = ubi->fm_buf;
+
+	memset(ubi->fm_used, 0, sizeof(ubi->fm_used));
+
+	fm_pos += sizeof(struct ubi_fm_sb);
+	if (fm_pos >= fm_size)
+		goto fail_bad;
+
+	fmhdr = (struct ubi_fm_hdr *)(fm_raw + fm_pos);
+	fm_pos += sizeof(*fmhdr);
+	if (fm_pos >= fm_size)
+		goto fail_bad;
+
+	if (be32_to_cpu(fmhdr->magic) != UBI_FM_HDR_MAGIC) {
+		ubi_err("bad fastmap header magic: 0x%x, expected: 0x%x",
+			be32_to_cpu(fmhdr->magic), UBI_FM_HDR_MAGIC);
+		goto fail_bad;
+	}
+
+	fmpl1 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
+	fm_pos += sizeof(*fmpl1);
+	if (fm_pos >= fm_size)
+		goto fail_bad;
+	if (be32_to_cpu(fmpl1->magic) != UBI_FM_POOL_MAGIC) {
+		ubi_err("bad fastmap pool magic: 0x%x, expected: 0x%x",
+			be32_to_cpu(fmpl1->magic), UBI_FM_POOL_MAGIC);
+		goto fail_bad;
+	}
+
+	fmpl2 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
+	fm_pos += sizeof(*fmpl2);
+	if (fm_pos >= fm_size)
+		goto fail_bad;
+	if (be32_to_cpu(fmpl2->magic) != UBI_FM_POOL_MAGIC) {
+		ubi_err("bad fastmap pool magic: 0x%x, expected: 0x%x",
+			be32_to_cpu(fmpl2->magic), UBI_FM_POOL_MAGIC);
+		goto fail_bad;
+	}
+
+	pool_size = be16_to_cpu(fmpl1->size);
+	wl_pool_size = be16_to_cpu(fmpl2->size);
+	fm->max_pool_size = be16_to_cpu(fmpl1->max_size);
+	fm->max_wl_pool_size = be16_to_cpu(fmpl2->max_size);
+
+	if (pool_size > UBI_FM_MAX_POOL_SIZE || pool_size < 0) {
+		ubi_err("bad pool size: %i", pool_size);
+		goto fail_bad;
+	}
+
+	if (wl_pool_size > UBI_FM_MAX_POOL_SIZE || wl_pool_size < 0) {
+		ubi_err("bad WL pool size: %i", wl_pool_size);
+		goto fail_bad;
+	}
+
+	if (fm->max_pool_size > UBI_FM_MAX_POOL_SIZE ||
+	    fm->max_pool_size < 0) {
+		ubi_err("bad maximal pool size: %i", fm->max_pool_size);
+		goto fail_bad;
+	}
+
+	if (fm->max_wl_pool_size > UBI_FM_MAX_POOL_SIZE ||
+	    fm->max_wl_pool_size < 0) {
+		ubi_err("bad maximal WL pool size: %i", fm->max_wl_pool_size);
+		goto fail_bad;
+	}
+
+	/* read EC values from free list */
+	for (i = 0; i < be32_to_cpu(fmhdr->free_peb_count); i++) {
+		fmec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
+		fm_pos += sizeof(*fmec);
+		if (fm_pos >= fm_size)
+			goto fail_bad;
+	}
+
+	/* read EC values from used list */
+	for (i = 0; i < be32_to_cpu(fmhdr->used_peb_count); i++) {
+		fmec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
+		fm_pos += sizeof(*fmec);
+		if (fm_pos >= fm_size)
+			goto fail_bad;
+
+		generic_set_bit(be32_to_cpu(fmec->pnum), ubi->fm_used);
+	}
+
+	/* read EC values from scrub list */
+	for (i = 0; i < be32_to_cpu(fmhdr->scrub_peb_count); i++) {
+		fmec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
+		fm_pos += sizeof(*fmec);
+		if (fm_pos >= fm_size)
+			goto fail_bad;
+	}
+
+	/* read EC values from erase list */
+	for (i = 0; i < be32_to_cpu(fmhdr->erase_peb_count); i++) {
+		fmec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
+		fm_pos += sizeof(*fmec);
+		if (fm_pos >= fm_size)
+			goto fail_bad;
+	}
+
+	/* Iterate over all volumes and read their EBA table */
+	for (i = 0; i < be32_to_cpu(fmhdr->vol_count); i++) {
+		u32 vol_id, vol_type, used, reserved;
+
+		fmvhdr = (struct ubi_fm_volhdr *)(fm_raw + fm_pos);
+		fm_pos += sizeof(*fmvhdr);
+		if (fm_pos >= fm_size)
+			goto fail_bad;
+
+		if (be32_to_cpu(fmvhdr->magic) != UBI_FM_VHDR_MAGIC) {
+			ubi_err("bad fastmap vol header magic: 0x%x, " \
+				"expected: 0x%x",
+				be32_to_cpu(fmvhdr->magic), UBI_FM_VHDR_MAGIC);
+			goto fail_bad;
+		}
+
+		vol_id = be32_to_cpu(fmvhdr->vol_id);
+		vol_type = fmvhdr->vol_type;
+		used = be32_to_cpu(fmvhdr->used_ebs);
+
+		fm_eba = (struct ubi_fm_eba *)(fm_raw + fm_pos);
+		fm_pos += sizeof(*fm_eba);
+		fm_pos += (sizeof(__be32) * be32_to_cpu(fm_eba->reserved_pebs));
+		if (fm_pos >= fm_size)
+			goto fail_bad;
+
+		if (be32_to_cpu(fm_eba->magic) != UBI_FM_EBA_MAGIC) {
+			ubi_err("bad fastmap EBA header magic: 0x%x, " \
+				"expected: 0x%x",
+				be32_to_cpu(fm_eba->magic), UBI_FM_EBA_MAGIC);
+			goto fail_bad;
+		}
+
+		reserved = be32_to_cpu(fm_eba->reserved_pebs);
+		ubi_dbg("FA: vol %u used %u res: %u", vol_id, used, reserved);
+		for (j = 0; j < reserved; j++) {
+			int pnum = be32_to_cpu(fm_eba->pnum[j]);
+
+			if ((int)be32_to_cpu(fm_eba->pnum[j]) < 0)
+				continue;
+
+			if (!__test_and_clear_bit(pnum, ubi->fm_used))
+				continue;
+
+			/*
+			 * We only handle static volumes so used_ebs
+			 * needs to be handed in. And we do not assign
+			 * the reserved blocks
+			 */
+			if (j >= used)
+				continue;
+
+			ret = assign_aeb_to_av(ubi, pnum, j, vol_id,
+					       vol_type, used);
+			if (!ret)
+				continue;
+
+			/*
+			 * Nasty: The fastmap claims that the volume
+			 * has one block more than it, but that block
+			 * is always empty and the other blocks have
+			 * the correct number of total LEBs in the
+			 * headers. Deal with it.
+			 */
+			if (ret != UBI_IO_FF && j != used - 1)
+				goto fail_bad;
+			ubi_dbg("FA: Vol: %u Ignoring empty LEB %d of %d",
+				vol_id, j, used);
+		}
+	}
+
+	ret = scan_pool(ubi, fmpl1->pebs, pool_size);
+	if (ret)
+		goto fail;
+
+	ret = scan_pool(ubi, fmpl2->pebs, wl_pool_size);
+	if (ret)
+		goto fail;
+
+#ifdef CHECKME
+	/*
+	 * If fastmap is leaking PEBs (must not happen), raise a
+	 * fat warning and fall back to scanning mode.
+	 * We do this here because in ubi_wl_init() it's too late
+	 * and we cannot fall back to scanning.
+	 */
+	if (WARN_ON(count_fastmap_pebs(ai) != ubi->peb_count -
+		    ai->bad_peb_count - fm->used_blocks))
+		goto fail_bad;
+#endif
+
+	return 0;
+
+fail_bad:
+	ret = UBI_BAD_FASTMAP;
+fail:
+	return ret;
+}
+
+static int ubi_scan_fastmap(struct ubi_scan_info *ubi,
+			    struct ubi_attach_info *ai,
+			    int fm_anchor)
+{
+	struct ubi_fm_sb *fmsb, *fmsb2;
+	struct ubi_vid_hdr *vh;
+	struct ubi_fastmap_layout *fm;
+	int i, used_blocks, pnum, ret = 0;
+	size_t fm_size;
+	__be32 crc, tmp_crc;
+	unsigned long long sqnum = 0;
+
+	fmsb = &ubi->fm_sb;
+	fm = &ubi->fm_layout;
+
+	ret = ubi_io_read(ubi, fmsb, fm_anchor, ubi->leb_start, sizeof(*fmsb));
+	if (ret && ret != UBI_IO_BITFLIPS)
+		goto free_fm_sb;
+	else if (ret == UBI_IO_BITFLIPS)
+		fm->to_be_tortured[0] = 1;
+
+	if (be32_to_cpu(fmsb->magic) != UBI_FM_SB_MAGIC) {
+		ubi_err("bad super block magic: 0x%x, expected: 0x%x",
+			be32_to_cpu(fmsb->magic), UBI_FM_SB_MAGIC);
+		ret = UBI_BAD_FASTMAP;
+		goto free_fm_sb;
+	}
+
+	if (fmsb->version != UBI_FM_FMT_VERSION) {
+		ubi_err("bad fastmap version: %i, expected: %i",
+			fmsb->version, UBI_FM_FMT_VERSION);
+		ret = UBI_BAD_FASTMAP;
+		goto free_fm_sb;
+	}
+
+	used_blocks = be32_to_cpu(fmsb->used_blocks);
+	if (used_blocks > UBI_FM_MAX_BLOCKS || used_blocks < 1) {
+		ubi_err("number of fastmap blocks is invalid: %i", used_blocks);
+		ret = UBI_BAD_FASTMAP;
+		goto free_fm_sb;
+	}
+
+	fm_size = ubi->leb_size * used_blocks;
+	if (fm_size != ubi->fm_size) {
+		ubi_err("bad fastmap size: %zi, expected: %zi", fm_size,
+			ubi->fm_size);
+		ret = UBI_BAD_FASTMAP;
+		goto free_fm_sb;
+	}
+
+	vh = &ubi->fm_vh;
+
+	for (i = 0; i < used_blocks; i++) {
+		pnum = be32_to_cpu(fmsb->block_loc[i]);
+
+		if (ubi_io_is_bad(ubi, pnum)) {
+			ret = UBI_BAD_FASTMAP;
+			goto free_hdr;
+		}
+
+#ifdef LATER
+		int image_seq;
+		ret = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
+		if (ret && ret != UBI_IO_BITFLIPS) {
+			ubi_err("unable to read fastmap block# %i EC (PEB: %i)",
+				i, pnum);
+			if (ret > 0)
+				ret = UBI_BAD_FASTMAP;
+			goto free_hdr;
+		} else if (ret == UBI_IO_BITFLIPS)
+			fm->to_be_tortured[i] = 1;
+
+		image_seq = be32_to_cpu(ech->image_seq);
+		if (!ubi->image_seq)
+			ubi->image_seq = image_seq;
+		/*
+		 * Older UBI implementations have image_seq set to zero, so
+		 * we shouldn't fail if image_seq == 0.
+		 */
+		if (image_seq && (image_seq != ubi->image_seq)) {
+			ubi_err("wrong image seq:%d instead of %d",
+				be32_to_cpu(ech->image_seq), ubi->image_seq);
+			ret = UBI_BAD_FASTMAP;
+			goto free_hdr;
+		}
+#endif
+		ret = ubi_io_read_vid_hdr(ubi, pnum, vh, 0);
+		if (ret && ret != UBI_IO_BITFLIPS) {
+			ubi_err("unable to read fastmap block# %i (PEB: %i)",
+				i, pnum);
+			goto free_hdr;
+		}
+
+		/*
+		 * Mainline code rescans the anchor header. We've done
+		 * that already so we merily copy it over.
+		 */
+		if (pnum == fm_anchor)
+			memcpy(vh, ubi->blockinfo + pnum, sizeof(*fm));
+
+		if (i == 0) {
+			if (be32_to_cpu(vh->vol_id) != UBI_FM_SB_VOLUME_ID) {
+				ubi_err("bad fastmap anchor vol_id: 0x%x," \
+					" expected: 0x%x",
+					be32_to_cpu(vh->vol_id),
+					UBI_FM_SB_VOLUME_ID);
+				ret = UBI_BAD_FASTMAP;
+				goto free_hdr;
+			}
+		} else {
+			if (be32_to_cpu(vh->vol_id) != UBI_FM_DATA_VOLUME_ID) {
+				ubi_err("bad fastmap data vol_id: 0x%x," \
+					" expected: 0x%x",
+					be32_to_cpu(vh->vol_id),
+					UBI_FM_DATA_VOLUME_ID);
+				ret = UBI_BAD_FASTMAP;
+				goto free_hdr;
+			}
+		}
+
+		if (sqnum < be64_to_cpu(vh->sqnum))
+			sqnum = be64_to_cpu(vh->sqnum);
+
+		ret = ubi_io_read(ubi, ubi->fm_buf + (ubi->leb_size * i), pnum,
+				  ubi->leb_start, ubi->leb_size);
+		if (ret && ret != UBI_IO_BITFLIPS) {
+			ubi_err("unable to read fastmap block# %i (PEB: %i, " \
+				"err: %i)", i, pnum, ret);
+			goto free_hdr;
+		}
+	}
+
+	fmsb2 = (struct ubi_fm_sb *)(ubi->fm_buf);
+	tmp_crc = be32_to_cpu(fmsb2->data_crc);
+	fmsb2->data_crc = 0;
+	crc = crc32(UBI_CRC32_INIT, ubi->fm_buf, fm_size);
+	if (crc != tmp_crc) {
+		ubi_err("fastmap data CRC is invalid");
+		ubi_err("CRC should be: 0x%x, calc: 0x%x", tmp_crc, crc);
+		ret = UBI_BAD_FASTMAP;
+		goto free_hdr;
+	}
+
+	fmsb2->sqnum = sqnum;
+
+	fm->used_blocks = used_blocks;
+
+	ret = ubi_attach_fastmap(ubi, ai, fm);
+	if (ret) {
+		if (ret > 0)
+			ret = UBI_BAD_FASTMAP;
+		goto free_hdr;
+	}
+
+	ubi->fm = fm;
+	ubi->fm_pool.max_size = ubi->fm->max_pool_size;
+	ubi->fm_wl_pool.max_size = ubi->fm->max_wl_pool_size;
+	ubi_msg("attached by fastmap %uMB %u blocks",
+		ubi->fsize_mb, ubi->peb_count);
+	ubi_dbg("fastmap pool size: %d", ubi->fm_pool.max_size);
+	ubi_dbg("fastmap WL pool size: %d", ubi->fm_wl_pool.max_size);
+
+out:
+	if (ret)
+		ubi_err("Attach by fastmap failed, doing a full scan!");
+	return ret;
+
+free_hdr:
+free_fm_sb:
+	goto out;
+}
+
+/*
+ * Scan the flash and attempt to attach via fastmap
+ */
+static void ipl_scan(struct ubi_scan_info *ubi)
+{
+	unsigned int pnum;
+	int res;
+
+	/*
+	 * Scan first for the fastmap super block
+	 */
+	for (pnum = 0; pnum < UBI_FM_MAX_START; pnum++) {
+		res = ubi_scan_vid_hdr(ubi, ubi->blockinfo + pnum, pnum);
+		/*
+		 * We ignore errors here as we are meriliy scanning
+		 * the headers.
+		 */
+		if (res != UBI_FASTMAP_ANCHOR)
+			continue;
+
+		/*
+		 * If fastmap is disabled, continue scanning. This
+		 * might happen because the previous attempt failed or
+		 * the caller disabled it right away.
+		 */
+		if (!ubi->fm_enabled)
+			continue;
+
+		/*
+		 * Try to attach the fastmap, if that fails continue
+		 * scanning.
+		 */
+		if (!ubi_scan_fastmap(ubi, NULL, pnum))
+			return;
+		/*
+		 * Fastmap failed. Clear everything we have and start
+		 * over. We are paranoid and do not trust anything.
+		 */
+		memset(ubi->volinfo, 0, sizeof(ubi->volinfo));
+		pnum = 0;
+		break;
+	}
+
+	/*
+	 * Continue scanning, ignore errors, we might find what we are
+	 * looking for,
+	 */
+	for (; pnum < ubi->peb_count; pnum++)
+		ubi_scan_vid_hdr(ubi, ubi->blockinfo + pnum, pnum);
+}
+
+/*
+ * Load a logical block of a volume into memory
+ */
+static int ubi_load_block(struct ubi_scan_info *ubi, uint8_t *laddr,
+			  struct ubi_vol_info *vi, u32 vol_id, u32 lnum,
+			  u32 last)
+{
+	struct ubi_vid_hdr *vh, *vrepl;
+	u32 pnum, crc, dlen;
+
+retry:
+	/*
+	 * If this is a fastmap run, we try to rescan full, otherwise
+	 * we simply give up.
+	 */
+	if (!test_bit(lnum, vi->found)) {
+		ubi_warn("LEB %d of %d is missing", lnum, last);
+		return -EINVAL;
+	}
+
+	pnum = vi->lebs_to_pebs[lnum];
+
+	ubi_dbg("Load vol %u LEB %u PEB %u", vol_id, lnum, pnum);
+
+	if (ubi_io_is_bad(ubi, pnum)) {
+		ubi_warn("Corrupted mapping block %d PB %d\n", lnum, pnum);
+		return -EINVAL;
+	}
+
+	if (test_bit(pnum, ubi->corrupt))
+		goto find_other;
+
+	/*
+	 * Lets try to read that block
+	 */
+	vh = ubi->blockinfo + pnum;
+
+	if (!test_bit(pnum, ubi->scanned)) {
+		ubi_warn("Vol: %u LEB %u PEB %u not yet scanned", vol_id,
+			 lnum, pnum);
+		if (ubi_rescan_fm_vid_hdr(ubi, vh, pnum, vol_id, lnum))
+			goto find_other;
+	}
+
+	/*
+	 * Check, if the total number of blocks is correct
+	 */
+	if (be32_to_cpu(vh->used_ebs) != last) {
+		ubi_dbg("Block count missmatch.");
+		ubi_dbg("vh->used_ebs: %d nrblocks: %d",
+			be32_to_cpu(vh->used_ebs), last);
+		generic_set_bit(pnum, ubi->corrupt);
+		goto find_other;
+	}
+
+	/*
+	 * Get the data length of this block.
+	 */
+	dlen = be32_to_cpu(vh->data_size);
+
+	/*
+	 * Read the data into RAM. We ignore the return value
+	 * here as the only thing which might go wrong are
+	 * bitflips. Try nevertheless.
+	 */
+	ubi_io_read(ubi, laddr, pnum, ubi->leb_start, dlen);
+
+	/* Calculate CRC over the data */
+	crc = crc32(UBI_CRC32_INIT, laddr, dlen);
+
+	if (crc != be32_to_cpu(vh->data_crc)) {
+		ubi_warn("Vol: %u LEB %u PEB %u data CRC failure", vol_id,
+			 lnum, pnum);
+		generic_set_bit(pnum, ubi->corrupt);
+		goto find_other;
+	}
+
+	/* We are good. Return the data length we read */
+	return dlen;
+
+find_other:
+	ubi_dbg("Find replacement for LEB %u PEB %u", lnum, pnum);
+	generic_clear_bit(lnum, vi->found);
+	vrepl = NULL;
+
+	for (pnum = 0; pnum < ubi->peb_count; pnum++) {
+		struct ubi_vid_hdr *tmp = ubi->blockinfo + pnum;
+		u32 t_vol_id = be32_to_cpu(tmp->vol_id);
+		u32 t_lnum = be32_to_cpu(tmp->lnum);
+
+		if (test_bit(pnum, ubi->corrupt))
+			continue;
+
+		if (t_vol_id != vol_id || t_lnum != lnum)
+			continue;
+
+		if (!test_bit(pnum, ubi->scanned)) {
+			ubi_warn("Vol: %u LEB %u PEB %u not yet scanned",
+				 vol_id, lnum, pnum);
+			if (ubi_rescan_fm_vid_hdr(ubi, tmp, pnum, vol_id, lnum))
+				continue;
+		}
+
+		/*
+		 * We found one. If its the first, assign it otherwise
+		 * compare the sqnum
+		 */
+		generic_set_bit(lnum, vi->found);
+
+		if (!vrepl) {
+			vrepl = tmp;
+			continue;
+		}
+
+		if (be64_to_cpu(vrepl->sqnum) < be64_to_cpu(tmp->sqnum))
+			vrepl = tmp;
+	}
+
+	if (vrepl) {
+		/* Update the vi table */
+		pnum = vrepl - ubi->blockinfo;
+		vi->lebs_to_pebs[lnum] = pnum;
+		ubi_dbg("Trying PEB %u for LEB %u", pnum, lnum);
+		vh = vrepl;
+	}
+	goto retry;
+}
+
+/*
+ * Load a volume into RAM
+ */
+static int ipl_load(struct ubi_scan_info *ubi, const u32 vol_id, uint8_t *laddr)
+{
+	struct ubi_vol_info *vi;
+	u32 lnum, last, len;
+
+	if (vol_id >= UBI_SPL_VOL_IDS)
+		return -EINVAL;
+
+	len = 0;
+	vi = ubi->volinfo + vol_id;
+	last = vi->last_block + 1;
+
+	/* Read the blocks to RAM, check CRC */
+	for (lnum = 0 ; lnum < last; lnum++) {
+		int res = ubi_load_block(ubi, laddr, vi, vol_id, lnum, last);
+
+		if (res < 0) {
+			ubi_warn("Failed to load volume %u", vol_id);
+			return res;
+		}
+		/* res is the data length of the read block */
+		laddr += res;
+		len += res;
+	}
+	return len;
+}
+
+int ubispl_load_volumes(struct ubispl_info *info, struct ubispl_load *lvols,
+			int nrvols)
+{
+	struct ubi_scan_info *ubi = info->ubi;
+	int res, i, fastmap = info->fastmap;
+	u32 fsize;
+
+retry:
+	/*
+	 * We do a partial initializiation of @ubi. Cleaning fm_buf is
+	 * not necessary.
+	 */
+	memset(ubi, 0, offsetof(struct ubi_scan_info, fm_buf));
+
+	ubi->read = info->read;
+
+	/* Precalculate the offsets */
+	ubi->vid_offset = info->vid_offset;
+	ubi->leb_start = info->leb_start;
+	ubi->leb_size = info->peb_size - ubi->leb_start;
+	ubi->peb_count = info->peb_count;
+	ubi->peb_offset = info->peb_offset;
+
+	fsize = info->peb_size * info->peb_count;
+	ubi->fsize_mb = fsize >> 20;
+
+	/* Fastmap init */
+	ubi->fm_size = ubi_calc_fm_size(ubi);
+	ubi->fm_enabled = fastmap;
+
+	for (i = 0; i < nrvols; i++) {
+		struct ubispl_load *lv = lvols + i;
+
+		generic_set_bit(lv->vol_id, ubi->toload);
+	}
+
+	ipl_scan(ubi);
+
+	for (i = 0; i < nrvols; i++) {
+		struct ubispl_load *lv = lvols + i;
+
+		ubi_msg("Loading VolId #%d", lv->vol_id);
+		res = ipl_load(ubi, lv->vol_id, lv->load_addr);
+		if (res < 0) {
+			if (fastmap) {
+				fastmap = 0;
+				goto retry;
+			}
+			ubi_warn("Failed");
+			return res;
+		}
+	}
+	return 0;
+}
diff --git a/drivers/mtd/ubispl/ubispl.h b/drivers/mtd/ubispl/ubispl.h
new file mode 100644
index 0000000..9227881
--- /dev/null
+++ b/drivers/mtd/ubispl/ubispl.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) Thomas Gleixner <tglx@linutronix.de>
+ *
+ * SPDX-License-Identifier: GPL 2.0+ BSD-3-Clause
+ */
+
+#ifndef _UBOOT_MTD_UBISPL_H
+#define _UBOOT_MTD_UBISPL_H
+
+#include "../ubi/ubi-media.h"
+#include "ubi-wrapper.h"
+
+/*
+ * The maximum number of volume ids we scan. So you can load volume id
+ * 0 to (CONFIG_SPL_UBI_VOL_ID_MAX - 1)
+ */
+#define UBI_SPL_VOL_IDS		CONFIG_SPL_UBI_VOL_IDS
+/*
+ * The size of the read buffer for the fastmap blocks. In theory up to
+ * UBI_FM_MAX_BLOCKS * CONFIG_SPL_MAX_PEB_SIZE. In practice today
+ * one or two blocks.
+ */
+#define UBI_FM_BUF_SIZE		(UBI_FM_MAX_BLOCKS*CONFIG_SPL_UBI_MAX_PEB_SIZE)
+/*
+ * The size of the bitmaps for the attach/ scan
+ */
+#define UBI_FM_BM_SIZE		((CONFIG_SPL_UBI_MAX_PEBS / BITS_PER_LONG) + 1)
+/*
+ * The maximum number of logical erase blocks per loadable volume
+ */
+#define UBI_MAX_VOL_LEBS	CONFIG_SPL_UBI_MAX_VOL_LEBS
+/*
+ * The bitmap size for the above to denote the found blocks inside the volume
+ */
+#define UBI_VOL_BM_SIZE		((UBI_MAX_VOL_LEBS / BITS_PER_LONG) + 1)
+
+/**
+ * struct ubi_vol_info - UBISPL internal volume represenation
+ * @last_block:		The last block (highest LEB) found for this volume
+ * @found:		Bitmap to mark found LEBS
+ * @lebs_to_pebs:	LEB to PEB translation table
+ */
+struct ubi_vol_info {
+	u32				last_block;
+	unsigned long			found[UBI_VOL_BM_SIZE];
+	u32				lebs_to_pebs[UBI_MAX_VOL_LEBS];
+};
+
+/**
+ * struct ubi_scan_info - UBISPL internal data for FM attach and full scan
+ *
+ * @read:		Read function to access the flash provided by the caller
+ * @peb_count:		Number of physical erase blocks in the UBI FLASH area
+ *			aka MTD partition.
+ * @peb_offset:		Offset of PEB0 in the UBI FLASH area (aka MTD partition)
+ *			to the real start of the FLASH in erase blocks.
+ * @fsize_mb:		Size of the scanned FLASH area in MB (stats only)
+ * @vid_offset:		Offset from the start of a PEB to the VID header
+ * @leb_start:		Offset from the start of a PEB to the data area
+ * @leb_size:		Size of the data area
+ *
+ * @fastmap_pebs:	Counter of PEBs "attached" by fastmap
+ * @fastmap_anchor:	The anchor PEB of the fastmap
+ * @fm_sb:		The fastmap super block data
+ * @fm_vh:		The fastmap VID header
+ * @fm:			Pointer to the fastmap layout
+ * @fm_layout:		The fastmap layout itself
+ * @fm_pool:		The pool of PEBs to scan at fastmap attach time
+ * @fm_wl_pool:		The pool of PEBs scheduled for wearleveling
+ *
+ * @fm_enabled:		Indicator whether fastmap attachment is enabled.
+ * @fm_used:		Bitmap to indicate the PEBS covered by fastmap
+ * @scanned:		Bitmap to indicate the PEBS of which the VID header
+ *			hase been physically scanned.
+ * @corrupt:		Bitmap to indicate corrupt blocks
+ * @toload:		Bitmap to indicate the volumes which should be loaded
+ *
+ * @blockinfo:		The vid headers of the scanned blocks
+ * @volinfo:		The volume information of the interesting (toload)
+ *			volumes
+ *
+ * @fm_buf:		The large fastmap attach buffer
+ */
+struct ubi_scan_info {
+	ubispl_read_flash		read;
+	unsigned int			fsize_mb;
+	unsigned int			peb_count;
+	unsigned int			peb_offset;
+
+	unsigned long			vid_offset;
+	unsigned long			leb_start;
+	unsigned long			leb_size;
+
+	/* Fastmap: The upstream required fields */
+	int				fastmap_pebs;
+	int				fastmap_anchor;
+	size_t				fm_size;
+	struct ubi_fm_sb		fm_sb;
+	struct ubi_vid_hdr		fm_vh;
+	struct ubi_fastmap_layout	*fm;
+	struct ubi_fastmap_layout	fm_layout;
+	struct ubi_fm_pool		fm_pool;
+	struct ubi_fm_pool		fm_wl_pool;
+
+	/* Fastmap: UBISPL specific data */
+	int				fm_enabled;
+	unsigned long			fm_used[UBI_FM_BM_SIZE];
+	unsigned long			scanned[UBI_FM_BM_SIZE];
+	unsigned long			corrupt[UBI_FM_BM_SIZE];
+	unsigned long			toload[UBI_FM_BM_SIZE];
+
+	/* Data for storing the VID and volume information */
+	struct ubi_vol_info		volinfo[UBI_SPL_VOL_IDS];
+	struct ubi_vid_hdr		blockinfo[CONFIG_SPL_UBI_MAX_PEBS];
+
+	/* The large buffer for the fastmap */
+	uint8_t				fm_buf[UBI_FM_BUF_SIZE];
+};
+
+#ifdef CFG_DEBUG
+#define ubi_dbg(fmt, ...) printf("UBI: debug:" fmt "\n", ##__VA_ARGS__)
+#else
+#define ubi_dbg(fmt, ...)
+#endif
+
+#ifdef CONFIG_UBI_SILENCE_MSG
+#define ubi_msg(fmt, ...)
+#else
+#define ubi_msg(fmt, ...) printf("UBI: " fmt "\n", ##__VA_ARGS__)
+#endif
+/* UBI warning messages */
+#define ubi_warn(fmt, ...) printf("UBI warning: " fmt "\n", ##__VA_ARGS__)
+/* UBI error messages */
+#define ubi_err(fmt, ...) printf("UBI error: " fmt "\n", ##__VA_ARGS__)
+
+#endif
diff --git a/drivers/net/4xx_enet.c b/drivers/net/4xx_enet.c
index bc52ed3..b718481 100644
--- a/drivers/net/4xx_enet.c
+++ b/drivers/net/4xx_enet.c
@@ -283,10 +283,9 @@
 static void emac_err (struct eth_device *dev, unsigned long isr);
 
 extern int phy_setup_aneg (char *devname, unsigned char addr);
-extern int emac4xx_miiphy_read (const char *devname, unsigned char addr,
-		unsigned char reg, unsigned short *value);
-extern int emac4xx_miiphy_write (const char *devname, unsigned char addr,
-		unsigned char reg, unsigned short value);
+int emac4xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg);
+int emac4xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+			 u16 value);
 
 int board_emac_count(void);
 
@@ -2015,8 +2014,17 @@
 		eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-		miiphy_register(dev->name,
-				emac4xx_miiphy_read, emac4xx_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+		mdiodev->read = emac4xx_miiphy_read;
+		mdiodev->write = emac4xx_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 #endif
 
 		if (0 == virgin) {
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index c1cb689..be3ed73 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -124,6 +124,11 @@
 	  100Mbit and 1 Gbit operation. You must enable CONFIG_PHYLIB to
 	  provide the PHY (physical media interface).
 
+config ETHOC
+	bool "OpenCores 10/100 Mbps Ethernet MAC"
+	help
+	  This MAC is present in OpenRISC and Xtensa XTFPGA boards.
+
 config MVPP2
 	bool "Marvell Armada 375 network interface support"
 	depends on ARMADA_375
@@ -152,6 +157,15 @@
 	  This driver supports Realtek 8169 series gigabit ethernet family of
 	  PCI/PCIe chipsets/adapters.
 
+config SUN8I_EMAC
+        bool "Allwinner Sun8i Ethernet MAC support"
+        depends on DM_ETH
+        select PHYLIB
+        help
+          This driver supports the  Allwinner based SUN8I/SUN50I Ethernet MAC.
+	  It can be found in H3/A64/A83T based SoCs and compatible with both
+	  External and Internal PHY's.
+
 config XILINX_AXIEMAC
 	depends on DM_ETH && (MICROBLAZE || ARCH_ZYNQ || ARCH_ZYNQMP)
 	select PHYLIB
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 5702592..a448526 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -24,6 +24,7 @@
 obj-$(CONFIG_E1000_SPI) += e1000_spi.o
 obj-$(CONFIG_EEPRO100) += eepro100.o
 obj-$(CONFIG_SUNXI_EMAC) += sunxi_emac.o
+obj-$(CONFIG_SUN8I_EMAC) += sun8i_emac.o
 obj-$(CONFIG_ENC28J60) += enc28j60.o
 obj-$(CONFIG_EP93XX) += ep93xx_eth.o
 obj-$(CONFIG_ETHOC) += ethoc.o
diff --git a/drivers/net/armada100_fec.c b/drivers/net/armada100_fec.c
index e6a6252..ba2cb1a 100644
--- a/drivers/net/armada100_fec.c
+++ b/drivers/net/armada100_fec.c
@@ -57,18 +57,19 @@
 	return !timeout;
 }
 
-static int smi_reg_read(const char *devname, u8 phy_addr, u8 phy_reg,
-			u16 *value)
+static int smi_reg_read(struct mii_dev *bus, int phy_addr, int devad,
+			int phy_reg)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	u16 value = 0;
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	struct armdfec_device *darmdfec = to_darmdfec(dev);
 	struct armdfec_reg *regs = darmdfec->regs;
 	u32 val;
 
 	if (phy_addr == PHY_ADR_REQ && phy_reg == PHY_ADR_REQ) {
 		val = readl(&regs->phyadr);
-		*value = val & 0x1f;
-		return 0;
+		value = val & 0x1f;
+		return value;
 	}
 
 	/* check parameters */
@@ -99,15 +100,15 @@
 		return -1;
 	}
 	val = readl(&regs->smi);
-	*value = val & 0xffff;
+	value = val & 0xffff;
 
-	return 0;
+	return value;
 }
 
-static int smi_reg_write(const char *devname,
-	 u8 phy_addr, u8 phy_reg, u16 value)
+static int smi_reg_write(struct mii_dev *bus, int phy_addr, int devad,
+			 int phy_reg, u16 value)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	struct armdfec_device *darmdfec = to_darmdfec(dev);
 	struct armdfec_reg *regs = darmdfec->regs;
 
@@ -711,7 +712,17 @@
 	eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name, smi_reg_read, smi_reg_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = smi_reg_read;
+	mdiodev->write = smi_reg_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 	return 0;
 
diff --git a/drivers/net/at91_emac.c b/drivers/net/at91_emac.c
index 9151600..be3d82e 100644
--- a/drivers/net/at91_emac.c
+++ b/drivers/net/at91_emac.c
@@ -159,23 +159,23 @@
 	return (at91_emac_t *) netdev->iobase;
 }
 
-int  at91emac_mii_read(const char *devname, unsigned char addr,
-		unsigned char reg, unsigned short *value)
+int at91emac_mii_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
+	unsigned short value = 0;
 	at91_emac_t *emac;
 
-	emac = get_emacbase_by_name(devname);
-	at91emac_read(emac , addr, reg, value);
-	return 0;
+	emac = get_emacbase_by_name(bus->name);
+	at91emac_read(emac , addr, reg, &value);
+	return value;
 }
 
 
-int  at91emac_mii_write(const char *devname, unsigned char addr,
-		unsigned char reg, unsigned short value)
+int at91emac_mii_write(struct mii_dev *bus, int addr, int devad, int reg,
+		       u16 value)
 {
 	at91_emac_t *emac;
 
-	emac = get_emacbase_by_name(devname);
+	emac = get_emacbase_by_name(bus->name);
 	at91emac_write(emac, addr, reg, value);
 	return 0;
 }
@@ -502,7 +502,17 @@
 	eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name, at91emac_mii_read, at91emac_mii_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = at91emac_mii_read;
+	mdiodev->write = at91emac_mii_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 	return 1;
 }
diff --git a/drivers/net/bcm-sf2-eth-gmac.c b/drivers/net/bcm-sf2-eth-gmac.c
index 977feec..f2853cf 100644
--- a/drivers/net/bcm-sf2-eth-gmac.c
+++ b/drivers/net/bcm-sf2-eth-gmac.c
@@ -596,12 +596,10 @@
 	return tmp & (1 << GMAC_MII_BUSY_SHIFT);
 }
 
-int gmac_miiphy_read(const char *devname, unsigned char phyaddr,
-			unsigned char reg, unsigned short *value)
+int gmac_miiphy_read(struct mii_dev *bus, int phyaddr, int devad, int reg)
 {
 	uint32_t tmp = 0;
-
-	(void)devname;
+	u16 value = 0;
 
 	/* Busy wait timeout is 1ms */
 	if (gmac_mii_busywait(1000)) {
@@ -621,18 +619,16 @@
 		return -1;
 	}
 
-	*value = readl(GMAC_MII_DATA_ADDR) & 0xffff;
-	debug("MII read data 0x%x\n", *value);
-	return 0;
+	value = readl(GMAC_MII_DATA_ADDR) & 0xffff;
+	debug("MII read data 0x%x\n", value);
+	return value;
 }
 
-int gmac_miiphy_write(const char *devname, unsigned char phyaddr,
-			 unsigned char reg, unsigned short value)
+int gmac_miiphy_write(struct mii_dev *bus, int phyaddr, int devad, int reg,
+		      u16 value)
 {
 	uint32_t tmp = 0;
 
-	(void)devname;
-
 	/* Busy wait timeout is 1ms */
 	if (gmac_mii_busywait(1000)) {
 		error("%s: Prepare MII write: MII/MDIO busy\n", __func__);
diff --git a/drivers/net/bcm-sf2-eth.c b/drivers/net/bcm-sf2-eth.c
index eab4c1f..e274736 100644
--- a/drivers/net/bcm-sf2-eth.c
+++ b/drivers/net/bcm-sf2-eth.c
@@ -244,7 +244,18 @@
 	eth_register(dev);
 
 #ifdef CONFIG_CMD_MII
-	miiphy_register(dev->name, eth->miiphy_read, eth->miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = eth->miiphy_read;
+	mdiodev->write = eth->miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 
 	/* Initialization */
diff --git a/drivers/net/bcm-sf2-eth.h b/drivers/net/bcm-sf2-eth.h
index 49a5836..6104aff 100644
--- a/drivers/net/bcm-sf2-eth.h
+++ b/drivers/net/bcm-sf2-eth.h
@@ -54,10 +54,10 @@
 	struct phy_device *port[BCM_ETH_MAX_PORT_NUM];
 	int port_num;
 
-	int (*miiphy_read)(const char *devname, unsigned char phyaddr,
-			   unsigned char reg, unsigned short *value);
-	int (*miiphy_write)(const char *devname, unsigned char phyaddr,
-			    unsigned char reg, unsigned short value);
+	int (*miiphy_read)(struct mii_dev *bus, int phyaddr, int devad,
+			   int reg);
+	int (*miiphy_write)(struct mii_dev *bus, int phyaddr, int devad,
+			    int reg, u16 value);
 
 	int (*mac_init)(struct eth_device *dev);
 	int (*enable_mac)(void);
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index 61cb1b0..26a626b 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -13,6 +13,7 @@
 #include <command.h>
 #include <malloc.h>
 #include <miiphy.h>
+#include <linux/mdio.h>
 #include <linux/mii.h>
 
 #include <asm/blackfin.h>
@@ -72,18 +73,20 @@
 	return 0;
 }
 
-static int bfin_miiphy_read(const char *devname, uchar addr, uchar reg, ushort *val)
+static int bfin_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
+	ushort val = 0;
 	if (bfin_miiphy_wait())
 		return 1;
 	bfin_write_EMAC_STAADD(SET_PHYAD(addr) | SET_REGAD(reg) | STABUSY);
 	if (bfin_miiphy_wait())
 		return 1;
-	*val = bfin_read_EMAC_STADAT();
-	return 0;
+	val = bfin_read_EMAC_STADAT();
+	return val;
 }
 
-static int bfin_miiphy_write(const char *devname, uchar addr, uchar reg, ushort val)
+static int bfin_miiphy_write(struct mii_dev *bus, int addr, int devad,
+			     int reg, u16 val)
 {
 	if (bfin_miiphy_wait())
 		return 1;
@@ -113,7 +116,19 @@
 	eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name, bfin_miiphy_read, bfin_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = bfin_miiphy_read;
+	mdiodev->write = bfin_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
+
+	dev->priv = mdiodev;
 #endif
 
 	return 0;
@@ -222,8 +237,9 @@
 static int bfin_miiphy_init(struct eth_device *dev, int *opmode)
 {
 	const unsigned short pins[] = CONFIG_BFIN_MAC_PINS;
-	u16 phydat;
+	int phydat;
 	size_t count;
+	struct mii_dev *mdiodev = dev->priv;
 
 	/* Enable PHY output */
 	bfin_write_VR_CTL(bfin_read_VR_CTL() | CLKBUFOE);
@@ -236,12 +252,15 @@
 	bfin_write_EMAC_SYSCTL(RXDWA | RXCKS | SET_MDCDIV(MDC_FREQ_TO_DIV(CONFIG_PHY_CLOCK_FREQ)));
 
 	/* turn on auto-negotiation and wait for link to come up */
-	bfin_miiphy_write(dev->name, CONFIG_PHY_ADDR, MII_BMCR, BMCR_ANENABLE);
+	bfin_miiphy_write(mdiodev, CONFIG_PHY_ADDR, MDIO_DEVAD_NONE, MII_BMCR,
+			  BMCR_ANENABLE);
 	count = 0;
 	while (1) {
 		++count;
-		if (bfin_miiphy_read(dev->name, CONFIG_PHY_ADDR, MII_BMSR, &phydat))
-			return -1;
+		phydat = bfin_miiphy_read(mdiodev, CONFIG_PHY_ADDR,
+					  MDIO_DEVAD_NONE, MII_BMSR);
+		if (phydat < 0)
+			return phydat;
 		if (phydat & BMSR_LSTATUS)
 			break;
 		if (count > 30000) {
@@ -252,8 +271,10 @@
 	}
 
 	/* see what kind of link we have */
-	if (bfin_miiphy_read(dev->name, CONFIG_PHY_ADDR, MII_LPA, &phydat))
-		return -1;
+	phydat = bfin_miiphy_read(mdiodev, CONFIG_PHY_ADDR, MDIO_DEVAD_NONE,
+				  MII_LPA);
+	if (phydat < 0)
+		return phydat;
 	if (phydat & LPA_DUPLEX)
 		*opmode = FDMODE;
 	else
diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c
index 2ce4ec6..81ccc61 100644
--- a/drivers/net/cpsw.c
+++ b/drivers/net/cpsw.c
@@ -22,6 +22,7 @@
 #include <netdev.h>
 #include <cpsw.h>
 #include <asm/errno.h>
+#include <asm/gpio.h>
 #include <asm/io.h>
 #include <phy.h>
 #include <asm/arch/cpu.h>
@@ -907,7 +908,7 @@
 	int timeout = CPDMA_TIMEOUT;
 
 	flush_dcache_range((unsigned long)packet,
-			   (unsigned long)packet + length);
+			   (unsigned long)packet + ALIGN(length, PKTALIGN));
 
 	/* first reap completed packets */
 	while (timeout-- &&
@@ -1145,19 +1146,22 @@
 
 static inline fdt_addr_t cpsw_get_addr_by_node(const void *fdt, int node)
 {
-	return fdtdec_get_addr_size_auto_noparent(fdt, node, "reg", 0, NULL);
+	return fdtdec_get_addr_size_auto_noparent(fdt, node, "reg", 0, NULL,
+						  false);
 }
 
 static int cpsw_eth_ofdata_to_platdata(struct udevice *dev)
 {
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 	struct cpsw_priv *priv = dev_get_priv(dev);
+	struct gpio_desc *mode_gpios;
 	const char *phy_mode;
 	const void *fdt = gd->fdt_blob;
 	int node = dev->of_offset;
 	int subnode;
 	int slave_index = 0;
 	int active_slave;
+	int num_mode_gpios;
 	int ret;
 
 	pdata->iobase = dev_get_addr(dev);
@@ -1203,6 +1207,15 @@
 		return -ENOENT;
 	}
 
+	num_mode_gpios = gpio_get_list_count(dev, "mode-gpios");
+	if (num_mode_gpios > 0) {
+		mode_gpios = malloc(sizeof(struct gpio_desc) *
+				    num_mode_gpios);
+		gpio_request_list_by_name(dev, "mode-gpios", mode_gpios,
+					  num_mode_gpios, GPIOD_IS_OUT);
+		free(mode_gpios);
+	}
+
 	active_slave = fdtdec_get_int(fdt, node, "active_slave", 0);
 	priv->data.active_slave = active_slave;
 
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index b030498..ca457b8 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -243,11 +243,10 @@
 
 	if (tmp & MDIO_USERACCESS0_ACK) {
 		*data = tmp & 0xffff;
-		return(1);
+		return 0;
 	}
 
-	*data = -1;
-	return(0);
+	return -EIO;
 }
 
 /* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */
@@ -268,7 +267,7 @@
 	while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
 		;
 
-	return(1);
+	return 0;
 }
 
 /* PHY functions for a generic PHY */
@@ -390,14 +389,20 @@
 
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-static int davinci_mii_phy_read(const char *devname, unsigned char addr, unsigned char reg, unsigned short *value)
+static int davinci_mii_phy_read(struct mii_dev *bus, int addr, int devad,
+				int reg)
 {
-	return(davinci_eth_phy_read(addr, reg, value) ? 0 : 1);
+	unsigned short value = 0;
+	int retval = davinci_eth_phy_read(addr, reg, &value);
+	if (retval < 0)
+		return retval;
+	return value;
 }
 
-static int davinci_mii_phy_write(const char *devname, unsigned char addr, unsigned char reg, unsigned short value)
+static int davinci_mii_phy_write(struct mii_dev *bus, int addr, int devad,
+				 int reg, u16 value)
 {
-	return(davinci_eth_phy_write(addr, reg, value) ? 0 : 1);
+	return davinci_eth_phy_write(addr, reg, value);
 }
 #endif
 
@@ -883,8 +888,17 @@
 
 		debug("Ethernet PHY: %s\n", phy[i].name);
 
-		miiphy_register(phy[i].name, davinci_mii_phy_read,
-						davinci_mii_phy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, phy[i].name, MDIO_NAME_LEN);
+		mdiodev->read = davinci_mii_phy_read;
+		mdiodev->write = davinci_mii_phy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 	}
 
 #if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c
index 196989b..3332ad9 100644
--- a/drivers/net/e1000.c
+++ b/drivers/net/e1000.c
@@ -5513,7 +5513,8 @@
 	struct udevice *dev;
 	char name[30];
 	int ret;
-#else
+#endif
+#if !defined(CONFIG_DM_ETH) || defined(CONFIG_E1000_SPI)
 	struct e1000_hw *hw;
 #endif
 	int cardnum;
@@ -5549,6 +5550,9 @@
 	}
 
 #ifdef CONFIG_E1000_SPI
+#ifdef CONFIG_DM_ETH
+	hw = dev_get_priv(dev);
+#endif
 	/* Handle the "SPI" subcommand */
 	if (!strcmp(argv[2], "spi"))
 		return do_e1000_spi(cmdtp, hw, argc - 3, argv + 3);
diff --git a/drivers/net/e1000_spi.c b/drivers/net/e1000_spi.c
index 576ddb8..cb5f93d 100644
--- a/drivers/net/e1000_spi.c
+++ b/drivers/net/e1000_spi.c
@@ -94,17 +94,17 @@
 
 	/* Make sure it has an SPI chip */
 	if (hw->eeprom.type != e1000_eeprom_spi) {
-		E1000_ERR(hw->nic, "No attached SPI EEPROM found!\n");
+		E1000_ERR(hw, "No attached SPI EEPROM found!\n");
 		return NULL;
 	}
 
 	/* Argument sanity checks */
 	if (cs != 0) {
-		E1000_ERR(hw->nic, "No such SPI chip: %u\n", cs);
+		E1000_ERR(hw, "No such SPI chip: %u\n", cs);
 		return NULL;
 	}
 	if (mode != SPI_MODE_0) {
-		E1000_ERR(hw->nic, "Only SPI MODE-0 is supported!\n");
+		E1000_ERR(hw, "Only SPI MODE-0 is supported!\n");
 		return NULL;
 	}
 
@@ -124,7 +124,7 @@
 	struct e1000_hw *hw = e1000_hw_from_spi(spi);
 
 	if (e1000_acquire_eeprom(hw)) {
-		E1000_ERR(hw->nic, "EEPROM SPI cannot be acquired!\n");
+		E1000_ERR(hw, "EEPROM SPI cannot be acquired!\n");
 		return -1;
 	}
 
@@ -342,41 +342,41 @@
 
 	/* Extra sanity checks */
 	if (!length) {
-		E1000_ERR(hw->nic, "Requested zero-sized dump!\n");
+		E1000_ERR(hw, "Requested zero-sized dump!\n");
 		return 1;
 	}
 	if ((0x10000 < length) || (0x10000 - length < offset)) {
-		E1000_ERR(hw->nic, "Can't dump past 0xFFFF!\n");
+		E1000_ERR(hw, "Can't dump past 0xFFFF!\n");
 		return 1;
 	}
 
 	/* Allocate a buffer to hold stuff */
 	buffer = malloc(length);
 	if (!buffer) {
-		E1000_ERR(hw->nic, "Out of Memory!\n");
+		E1000_ERR(hw, "Out of Memory!\n");
 		return 1;
 	}
 
 	/* Acquire the EEPROM and perform the dump */
 	if (e1000_acquire_eeprom(hw)) {
-		E1000_ERR(hw->nic, "EEPROM SPI cannot be acquired!\n");
+		E1000_ERR(hw, "EEPROM SPI cannot be acquired!\n");
 		free(buffer);
 		return 1;
 	}
 	err = e1000_spi_eeprom_dump(hw, buffer, offset, length, true);
 	e1000_release_eeprom(hw);
 	if (err) {
-		E1000_ERR(hw->nic, "Interrupted!\n");
+		E1000_ERR(hw, "Interrupted!\n");
 		free(buffer);
 		return 1;
 	}
 
 	/* Now hexdump the result */
 	printf("%s: ===== Intel e1000 EEPROM (0x%04hX - 0x%04hX) =====",
-			hw->nic->name, offset, offset + length - 1);
+			hw->name, offset, offset + length - 1);
 	for (i = 0; i < length; i++) {
 		if ((i & 0xF) == 0)
-			printf("\n%s: %04hX: ", hw->nic->name, offset + i);
+			printf("\n%s: %04hX: ", hw->name, offset + i);
 		else if ((i & 0xF) == 0x8)
 			printf(" ");
 		printf(" %02hx", buffer[i]);
@@ -407,29 +407,29 @@
 
 	/* Extra sanity checks */
 	if (!length) {
-		E1000_ERR(hw->nic, "Requested zero-sized dump!\n");
+		E1000_ERR(hw, "Requested zero-sized dump!\n");
 		return 1;
 	}
 	if ((0x10000 < length) || (0x10000 - length < offset)) {
-		E1000_ERR(hw->nic, "Can't dump past 0xFFFF!\n");
+		E1000_ERR(hw, "Can't dump past 0xFFFF!\n");
 		return 1;
 	}
 
 	/* Acquire the EEPROM */
 	if (e1000_acquire_eeprom(hw)) {
-		E1000_ERR(hw->nic, "EEPROM SPI cannot be acquired!\n");
+		E1000_ERR(hw, "EEPROM SPI cannot be acquired!\n");
 		return 1;
 	}
 
 	/* Perform the programming operation */
 	if (e1000_spi_eeprom_dump(hw, dest, offset, length, true) < 0) {
-		E1000_ERR(hw->nic, "Interrupted!\n");
+		E1000_ERR(hw, "Interrupted!\n");
 		e1000_release_eeprom(hw);
 		return 1;
 	}
 
 	e1000_release_eeprom(hw);
-	printf("%s: ===== EEPROM DUMP COMPLETE =====\n", hw->nic->name);
+	printf("%s: ===== EEPROM DUMP COMPLETE =====\n", hw->name);
 	return 0;
 }
 
@@ -452,19 +452,19 @@
 
 	/* Acquire the EEPROM */
 	if (e1000_acquire_eeprom(hw)) {
-		E1000_ERR(hw->nic, "EEPROM SPI cannot be acquired!\n");
+		E1000_ERR(hw, "EEPROM SPI cannot be acquired!\n");
 		return 1;
 	}
 
 	/* Perform the programming operation */
 	if (e1000_spi_eeprom_program(hw, source, offset, length, true) < 0) {
-		E1000_ERR(hw->nic, "Interrupted!\n");
+		E1000_ERR(hw, "Interrupted!\n");
 		e1000_release_eeprom(hw);
 		return 1;
 	}
 
 	e1000_release_eeprom(hw);
-	printf("%s: ===== EEPROM PROGRAMMED =====\n", hw->nic->name);
+	printf("%s: ===== EEPROM PROGRAMMED =====\n", hw->name);
 	return 0;
 }
 
@@ -488,19 +488,19 @@
 	length = sizeof(uint16_t) * (EEPROM_CHECKSUM_REG + 1);
 	buffer = malloc(length);
 	if (!buffer) {
-		E1000_ERR(hw->nic, "Unable to allocate EEPROM buffer!\n");
+		E1000_ERR(hw, "Unable to allocate EEPROM buffer!\n");
 		return 1;
 	}
 
 	/* Acquire the EEPROM */
 	if (e1000_acquire_eeprom(hw)) {
-		E1000_ERR(hw->nic, "EEPROM SPI cannot be acquired!\n");
+		E1000_ERR(hw, "EEPROM SPI cannot be acquired!\n");
 		return 1;
 	}
 
 	/* Read the EEPROM */
 	if (e1000_spi_eeprom_dump(hw, buffer, 0, length, true) < 0) {
-		E1000_ERR(hw->nic, "Interrupted!\n");
+		E1000_ERR(hw, "Interrupted!\n");
 		e1000_release_eeprom(hw);
 		return 1;
 	}
@@ -514,15 +514,15 @@
 	/* Verify it! */
 	if (checksum_reg == checksum) {
 		printf("%s: INFO: EEPROM checksum is correct! (0x%04hx)\n",
-				hw->nic->name, checksum);
+				hw->name, checksum);
 		e1000_release_eeprom(hw);
 		return 0;
 	}
 
 	/* Hrm, verification failed, print an error */
-	E1000_ERR(hw->nic, "EEPROM checksum is incorrect!\n");
-	E1000_ERR(hw->nic, "  ...register was 0x%04hx, calculated 0x%04hx\n",
-			checksum_reg, checksum);
+	E1000_ERR(hw, "EEPROM checksum is incorrect!\n");
+	E1000_ERR(hw, "  ...register was 0x%04hx, calculated 0x%04hx\n",
+		  checksum_reg, checksum);
 
 	/* If they didn't ask us to update it, just return an error */
 	if (!upd) {
@@ -531,11 +531,11 @@
 	}
 
 	/* Ok, correct it! */
-	printf("%s: Reprogramming the EEPROM checksum...\n", hw->nic->name);
+	printf("%s: Reprogramming the EEPROM checksum...\n", hw->name);
 	buffer[i] = cpu_to_le16(checksum);
 	if (e1000_spi_eeprom_program(hw, &buffer[i], i * sizeof(uint16_t),
 			sizeof(uint16_t), true)) {
-		E1000_ERR(hw->nic, "Interrupted!\n");
+		E1000_ERR(hw, "Interrupted!\n");
 		e1000_release_eeprom(hw);
 		return 1;
 	}
@@ -554,7 +554,8 @@
 
 	/* Make sure it has an SPI chip */
 	if (hw->eeprom.type != e1000_eeprom_spi) {
-		E1000_ERR(hw->nic, "No attached SPI EEPROM found!\n");
+		E1000_ERR(hw, "No attached SPI EEPROM found (%d)!\n",
+			  hw->eeprom.type);
 		return 1;
 	}
 
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index d4a6386..0f350cb 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -334,34 +334,35 @@
 	return dev;
 }
 
-static int eepro100_miiphy_read(const char *devname, unsigned char addr,
-		unsigned char reg, unsigned short *value)
+static int eepro100_miiphy_read(struct mii_dev *bus, int addr, int devad,
+				int reg)
 {
+	unsigned short value = 0;
 	struct eth_device *dev;
 
-	dev = verify_phyaddr(devname, addr);
+	dev = verify_phyaddr(bus->name, addr);
 	if (dev == NULL)
 		return -1;
 
-	if (get_phyreg(dev, addr, reg, value) != 0) {
-		printf("%s: mii read timeout!\n", devname);
+	if (get_phyreg(dev, addr, reg, &value) != 0) {
+		printf("%s: mii read timeout!\n", bus->name);
 		return -1;
 	}
 
-	return 0;
+	return value;
 }
 
-static int eepro100_miiphy_write(const char *devname, unsigned char addr,
-		unsigned char reg, unsigned short value)
+static int eepro100_miiphy_write(struct mii_dev *bus, int addr, int devad,
+				 int reg, u16 value)
 {
 	struct eth_device *dev;
 
-	dev = verify_phyaddr(devname, addr);
+	dev = verify_phyaddr(bus->name, addr);
 	if (dev == NULL)
 		return -1;
 
 	if (set_phyreg(dev, addr, reg, value) != 0) {
-		printf("%s: mii write timeout!\n", devname);
+		printf("%s: mii write timeout!\n", bus->name);
 		return -1;
 	}
 
@@ -451,8 +452,17 @@
 
 #if defined (CONFIG_MII) || defined(CONFIG_CMD_MII)
 		/* register mii command access routines */
-		miiphy_register(dev->name,
-				eepro100_miiphy_read, eepro100_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+		mdiodev->read = eepro100_miiphy_read;
+		mdiodev->write = eepro100_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 #endif
 
 		card_number++;
diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c
index 611eabb..2fe323a 100644
--- a/drivers/net/enc28j60.c
+++ b/drivers/net/enc28j60.c
@@ -742,9 +742,10 @@
  *
  * This function is registered with miiphy_register().
  */
-int enc_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
+int enc_miiphy_read(struct mii_dev *bus, int phy_adr, int devad, int reg)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	u16 value = 0;
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	enc_dev_t *enc;
 
 	if (!dev || phy_adr != 0)
@@ -757,9 +758,9 @@
 		enc_release_bus(enc);
 		return -1;
 	}
-	*value = enc_phy_read(enc, reg);
+	value = enc_phy_read(enc, reg);
 	enc_release_bus(enc);
-	return 0;
+	return value;
 }
 
 /*
@@ -767,9 +768,10 @@
  *
  * This function is registered with miiphy_register().
  */
-int enc_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value)
+int enc_miiphy_write(struct mii_dev *bus, int phy_adr, int devad, int reg,
+		     u16 value)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	enc_dev_t *enc;
 
 	if (!dev || phy_adr != 0)
@@ -958,7 +960,17 @@
 	sprintf(dev->name, "enc%i.%i", bus, cs);
 	eth_register(dev);
 #if defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name, enc_miiphy_read, enc_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = enc_miiphy_read;
+	mdiodev->write = enc_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 	return 0;
 }
diff --git a/drivers/net/ep93xx_eth.c b/drivers/net/ep93xx_eth.c
index a3721c5..a94191b 100644
--- a/drivers/net/ep93xx_eth.c
+++ b/drivers/net/ep93xx_eth.c
@@ -30,10 +30,10 @@
 #define GET_REGS(eth_dev)	(GET_PRIV(eth_dev)->regs)
 
 /* ep93xx_miiphy ops forward declarations */
-static int ep93xx_miiphy_read(const char * const dev, unsigned char const addr,
-			unsigned char const reg, unsigned short * const value);
-static int ep93xx_miiphy_write(const char * const dev, unsigned char const addr,
-			unsigned char const reg, unsigned short const value);
+static int ep93xx_miiphy_read(struct mii_dev *bus, int addr, int devad,
+			      int reg);
+static int ep93xx_miiphy_write(struct mii_dev *bus, int addr, int devad,
+			       int reg, u16 value);
 
 #if defined(EP93XX_MAC_DEBUG)
 /**
@@ -421,7 +421,17 @@
 #if defined(CONFIG_MII)
 int ep93xx_miiphy_initialize(bd_t * const bd)
 {
-	miiphy_register("ep93xx_eth0", ep93xx_miiphy_read, ep93xx_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, "ep93xx_eth0", MDIO_NAME_LEN);
+	mdiodev->read = ep93xx_miiphy_read;
+	mdiodev->write = ep93xx_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 	return 0;
 }
 #endif
@@ -542,9 +552,10 @@
 /**
  * Read a 16-bit value from an MII register.
  */
-static int ep93xx_miiphy_read(const char * const dev, unsigned char const addr,
-			unsigned char const reg, unsigned short * const value)
+static int ep93xx_miiphy_read(struct mii_dev *bus, int addr, int devad,
+			      int reg)
 {
+	unsigned short value = 0;
 	struct mac_regs *mac = (struct mac_regs *)MAC_BASE;
 	int ret = -1;
 	uint32_t self_ctl;
@@ -552,10 +563,9 @@
 	debug("+ep93xx_miiphy_read");
 
 	/* Parameter checks */
-	BUG_ON(dev == NULL);
+	BUG_ON(bus->name == NULL);
 	BUG_ON(addr > MII_ADDRESS_MAX);
 	BUG_ON(reg > MII_REGISTER_MAX);
-	BUG_ON(value == NULL);
 
 	/*
 	 * Save the current SelfCTL register value.  Set MAC to suppress
@@ -579,7 +589,7 @@
 	while (readl(&mac->miists) & MIISTS_BUSY)
 		; /* noop */
 
-	*value = (unsigned short)readl(&mac->miidata);
+	value = (unsigned short)readl(&mac->miidata);
 
 	/* Restore the saved SelfCTL value and return. */
 	writel(self_ctl, &mac->selfctl);
@@ -588,14 +598,16 @@
 	/* Fall through */
 
 	debug("-ep93xx_miiphy_read");
-	return ret;
+	if (ret < 0)
+		return ret;
+	return value;
 }
 
 /**
  * Write a 16-bit value to an MII register.
  */
-static int ep93xx_miiphy_write(const char * const dev, unsigned char const addr,
-			unsigned char const reg, unsigned short const value)
+static int ep93xx_miiphy_write(struct mii_dev *bus, int addr, int devad,
+			       int reg, u16 value)
 {
 	struct mac_regs *mac = (struct mac_regs *)MAC_BASE;
 	int ret = -1;
@@ -604,7 +616,7 @@
 	debug("+ep93xx_miiphy_write");
 
 	/* Parameter checks */
-	BUG_ON(dev == NULL);
+	BUG_ON(bus->name == NULL);
 	BUG_ON(addr > MII_ADDRESS_MAX);
 	BUG_ON(reg > MII_REGISTER_MAX);
 
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index edb3c80..ad8c462 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -5,19 +5,20 @@
  * Copyright (C) 2008-2009 Avionic Design GmbH
  *   Thierry Reding <thierry.reding@avionic-design.de>
  * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
+ * Copyright (C) 2016 Cadence Design Systems Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * SPDX-License-Identifier:	GPL-2.0
  */
 
 #include <common.h>
-#include <command.h>
+#include <dm/device.h>
+#include <dm/platform_data/net_ethoc.h>
+#include <linux/io.h>
 #include <malloc.h>
 #include <net.h>
 #include <miiphy.h>
-#include <asm/io.h>
 #include <asm/cache.h>
+#include <wait_bit.h>
 
 /* register offsets */
 #define	MODER		0x00
@@ -162,6 +163,7 @@
 #define	ETHOC_BD_BASE		0x400
 #define	ETHOC_TIMEOUT		(HZ / 2)
 #define	ETHOC_MII_TIMEOUT	(1 + (HZ / 5))
+#define	ETHOC_IOSIZE		0x54
 
 /**
  * struct ethoc - driver-private device structure
@@ -177,6 +179,14 @@
 	u32 dty_tx;
 	u32 num_rx;
 	u32 cur_rx;
+	void __iomem *iobase;
+	void __iomem *packet;
+	phys_addr_t packet_phys;
+
+#ifdef CONFIG_PHYLIB
+	struct mii_dev *bus;
+	struct phy_device *phydev;
+#endif
 };
 
 /**
@@ -189,65 +199,68 @@
 	u32 addr;
 };
 
+static inline u32 *ethoc_reg(struct ethoc *priv, size_t offset)
+{
+	return priv->iobase + offset;
+}
+
-static inline u32 ethoc_read(struct eth_device *dev, size_t offset)
+static inline u32 ethoc_read(struct ethoc *priv, size_t offset)
 {
-	return readl(dev->iobase + offset);
+	return readl(ethoc_reg(priv, offset));
 }
 
-static inline void ethoc_write(struct eth_device *dev, size_t offset, u32 data)
+static inline void ethoc_write(struct ethoc *priv, size_t offset, u32 data)
 {
-	writel(data, dev->iobase + offset);
+	writel(data, ethoc_reg(priv, offset));
 }
 
-static inline void ethoc_read_bd(struct eth_device *dev, int index,
+static inline void ethoc_read_bd(struct ethoc *priv, int index,
 				 struct ethoc_bd *bd)
 {
 	size_t offset = ETHOC_BD_BASE + (index * sizeof(struct ethoc_bd));
-	bd->stat = ethoc_read(dev, offset + 0);
-	bd->addr = ethoc_read(dev, offset + 4);
+	bd->stat = ethoc_read(priv, offset + 0);
+	bd->addr = ethoc_read(priv, offset + 4);
 }
 
-static inline void ethoc_write_bd(struct eth_device *dev, int index,
+static inline void ethoc_write_bd(struct ethoc *priv, int index,
 				  const struct ethoc_bd *bd)
 {
 	size_t offset = ETHOC_BD_BASE + (index * sizeof(struct ethoc_bd));
-	ethoc_write(dev, offset + 0, bd->stat);
-	ethoc_write(dev, offset + 4, bd->addr);
+	ethoc_write(priv, offset + 0, bd->stat);
+	ethoc_write(priv, offset + 4, bd->addr);
 }
 
-static int ethoc_set_mac_address(struct eth_device *dev)
+static int ethoc_write_hwaddr_common(struct ethoc *priv, u8 *mac)
 {
-	u8 *mac = dev->enetaddr;
-
-	ethoc_write(dev, MAC_ADDR0, (mac[2] << 24) | (mac[3] << 16) |
+	ethoc_write(priv, MAC_ADDR0, (mac[2] << 24) | (mac[3] << 16) |
 		    (mac[4] << 8) | (mac[5] << 0));
-	ethoc_write(dev, MAC_ADDR1, (mac[0] << 8) | (mac[1] << 0));
+	ethoc_write(priv, MAC_ADDR1, (mac[0] << 8) | (mac[1] << 0));
 	return 0;
 }
 
-static inline void ethoc_ack_irq(struct eth_device *dev, u32 mask)
+static inline void ethoc_ack_irq(struct ethoc *priv, u32 mask)
 {
-	ethoc_write(dev, INT_SOURCE, mask);
+	ethoc_write(priv, INT_SOURCE, mask);
 }
 
-static inline void ethoc_enable_rx_and_tx(struct eth_device *dev)
+static inline void ethoc_enable_rx_and_tx(struct ethoc *priv)
 {
-	u32 mode = ethoc_read(dev, MODER);
+	u32 mode = ethoc_read(priv, MODER);
 	mode |= MODER_RXEN | MODER_TXEN;
-	ethoc_write(dev, MODER, mode);
+	ethoc_write(priv, MODER, mode);
 }
 
-static inline void ethoc_disable_rx_and_tx(struct eth_device *dev)
+static inline void ethoc_disable_rx_and_tx(struct ethoc *priv)
 {
-	u32 mode = ethoc_read(dev, MODER);
+	u32 mode = ethoc_read(priv, MODER);
 	mode &= ~(MODER_RXEN | MODER_TXEN);
-	ethoc_write(dev, MODER, mode);
+	ethoc_write(priv, MODER, mode);
 }
 
-static int ethoc_init_ring(struct eth_device *dev)
+static int ethoc_init_ring(struct ethoc *priv)
 {
-	struct ethoc *priv = (struct ethoc *)dev->priv;
 	struct ethoc_bd bd;
+	phys_addr_t addr = priv->packet_phys;
 	int i;
 
 	priv->cur_tx = 0;
@@ -256,68 +269,94 @@
 
 	/* setup transmission buffers */
 	bd.stat = TX_BD_IRQ | TX_BD_CRC;
+	bd.addr = 0;
 
 	for (i = 0; i < priv->num_tx; i++) {
+		if (addr) {
+			bd.addr = addr;
+			addr += PKTSIZE_ALIGN;
+		}
 		if (i == priv->num_tx - 1)
 			bd.stat |= TX_BD_WRAP;
 
-		ethoc_write_bd(dev, i, &bd);
+		ethoc_write_bd(priv, i, &bd);
 	}
 
 	bd.stat = RX_BD_EMPTY | RX_BD_IRQ;
 
 	for (i = 0; i < priv->num_rx; i++) {
-		bd.addr = (u32)net_rx_packets[i];
+		if (addr) {
+			bd.addr = addr;
+			addr += PKTSIZE_ALIGN;
+		} else {
+			bd.addr = virt_to_phys(net_rx_packets[i]);
+		}
 		if (i == priv->num_rx - 1)
 			bd.stat |= RX_BD_WRAP;
 
-		flush_dcache_range(bd.addr, bd.addr + PKTSIZE_ALIGN);
-		ethoc_write_bd(dev, priv->num_tx + i, &bd);
+		flush_dcache_range((ulong)net_rx_packets[i],
+				   (ulong)net_rx_packets[i] + PKTSIZE_ALIGN);
+		ethoc_write_bd(priv, priv->num_tx + i, &bd);
 	}
 
 	return 0;
 }
 
-static int ethoc_reset(struct eth_device *dev)
+static int ethoc_reset(struct ethoc *priv)
 {
 	u32 mode;
 
 	/* TODO: reset controller? */
 
-	ethoc_disable_rx_and_tx(dev);
+	ethoc_disable_rx_and_tx(priv);
 
 	/* TODO: setup registers */
 
 	/* enable FCS generation and automatic padding */
-	mode = ethoc_read(dev, MODER);
+	mode = ethoc_read(priv, MODER);
 	mode |= MODER_CRC | MODER_PAD;
-	ethoc_write(dev, MODER, mode);
+	ethoc_write(priv, MODER, mode);
 
 	/* set full-duplex mode */
-	mode = ethoc_read(dev, MODER);
+	mode = ethoc_read(priv, MODER);
 	mode |= MODER_FULLD;
-	ethoc_write(dev, MODER, mode);
-	ethoc_write(dev, IPGT, 0x15);
+	ethoc_write(priv, MODER, mode);
+	ethoc_write(priv, IPGT, 0x15);
 
-	ethoc_ack_irq(dev, INT_MASK_ALL);
-	ethoc_enable_rx_and_tx(dev);
+	ethoc_ack_irq(priv, INT_MASK_ALL);
+	ethoc_enable_rx_and_tx(priv);
 	return 0;
 }
 
-static int ethoc_init(struct eth_device *dev, bd_t * bd)
+static int ethoc_init_common(struct ethoc *priv)
 {
-	struct ethoc *priv = (struct ethoc *)dev->priv;
-	printf("ethoc\n");
+	int ret = 0;
 
 	priv->num_tx = 1;
 	priv->num_rx = PKTBUFSRX;
-	ethoc_write(dev, TX_BD_NUM, priv->num_tx);
-	ethoc_init_ring(dev);
-	ethoc_reset(dev);
+	ethoc_write(priv, TX_BD_NUM, priv->num_tx);
+	ethoc_init_ring(priv);
+	ethoc_reset(priv);
 
-	return 0;
+#ifdef CONFIG_PHYLIB
+	ret = phy_startup(priv->phydev);
+	if (ret) {
+		printf("Could not initialize PHY %s\n",
+		       priv->phydev->dev->name);
+		return ret;
+	}
+#endif
+	return ret;
 }
 
+static void ethoc_stop_common(struct ethoc *priv)
+{
+	ethoc_disable_rx_and_tx(priv);
+#ifdef CONFIG_PHYLIB
+	phy_shutdown(priv->phydev);
+#endif
+}
+
 static int ethoc_update_rx_stats(struct ethoc_bd *bd)
 {
 	int ret = 0;
@@ -353,37 +392,46 @@
 	return ret;
 }
 
-static int ethoc_rx(struct eth_device *dev, int limit)
+static int ethoc_rx_common(struct ethoc *priv, uchar **packetp)
 {
-	struct ethoc *priv = (struct ethoc *)dev->priv;
-	int count;
+	struct ethoc_bd bd;
+	u32 i = priv->cur_rx % priv->num_rx;
+	u32 entry = priv->num_tx + i;
 
-	for (count = 0; count < limit; ++count) {
-		u32 entry;
-		struct ethoc_bd bd;
+	ethoc_read_bd(priv, entry, &bd);
+	if (bd.stat & RX_BD_EMPTY)
+		return -EAGAIN;
 
-		entry = priv->num_tx + (priv->cur_rx % priv->num_rx);
-		ethoc_read_bd(dev, entry, &bd);
-		if (bd.stat & RX_BD_EMPTY)
-			break;
+	debug("%s(): RX buffer %d, %x received\n",
+	      __func__, priv->cur_rx, bd.stat);
+	if (ethoc_update_rx_stats(&bd) == 0) {
+		int size = bd.stat >> 16;
 
-		debug("%s(): RX buffer %d, %x received\n",
-		      __func__, priv->cur_rx, bd.stat);
-		if (ethoc_update_rx_stats(&bd) == 0) {
-			int size = bd.stat >> 16;
-			size -= 4;	/* strip the CRC */
-			net_process_received_packet((void *)bd.addr, size);
-		}
+		size -= 4;	/* strip the CRC */
+		if (priv->packet)
+			*packetp = priv->packet + entry * PKTSIZE_ALIGN;
+		else
+			*packetp = net_rx_packets[i];
+		return size;
+	} else {
+		return 0;
+	}
+}
+
+static int ethoc_is_new_packet_received(struct ethoc *priv)
+{
+	u32 pending;
 
-		/* clear the buffer descriptor so it can be reused */
-		flush_dcache_range(bd.addr, bd.addr + PKTSIZE_ALIGN);
-		bd.stat &= ~RX_BD_STATS;
-		bd.stat |= RX_BD_EMPTY;
-		ethoc_write_bd(dev, entry, &bd);
-		priv->cur_rx++;
+	pending = ethoc_read(priv, INT_SOURCE);
+	ethoc_ack_irq(priv, pending);
+	if (pending & INT_MASK_BUSY)
+		debug("%s(): packet dropped\n", __func__);
+	if (pending & INT_MASK_RX) {
+		debug("%s(): rx irq\n", __func__);
+		return 1;
 	}
 
-	return count;
+	return 0;
 }
 
 static int ethoc_update_tx_stats(struct ethoc_bd *bd)
@@ -403,52 +451,57 @@
 	return 0;
 }
 
-static void ethoc_tx(struct eth_device *dev)
+static void ethoc_tx(struct ethoc *priv)
 {
-	struct ethoc *priv = (struct ethoc *)dev->priv;
 	u32 entry = priv->dty_tx % priv->num_tx;
 	struct ethoc_bd bd;
 
-	ethoc_read_bd(dev, entry, &bd);
+	ethoc_read_bd(priv, entry, &bd);
 	if ((bd.stat & TX_BD_READY) == 0)
 		(void)ethoc_update_tx_stats(&bd);
 }
 
-static int ethoc_send(struct eth_device *dev, void *packet, int length)
+static int ethoc_send_common(struct ethoc *priv, void *packet, int length)
 {
-	struct ethoc *priv = (struct ethoc *)dev->priv;
 	struct ethoc_bd bd;
 	u32 entry;
 	u32 pending;
 	int tmo;
 
 	entry = priv->cur_tx % priv->num_tx;
-	ethoc_read_bd(dev, entry, &bd);
+	ethoc_read_bd(priv, entry, &bd);
 	if (unlikely(length < ETHOC_ZLEN))
 		bd.stat |= TX_BD_PAD;
 	else
 		bd.stat &= ~TX_BD_PAD;
-	bd.addr = (u32)packet;
 
-	flush_dcache_range(bd.addr, bd.addr + length);
+	if (priv->packet) {
+		void *p = priv->packet + entry * PKTSIZE_ALIGN;
+
+		memcpy(p, packet, length);
+		packet = p;
+	} else {
+		bd.addr = virt_to_phys(packet);
+	}
+	flush_dcache_range((ulong)packet, (ulong)packet + length);
 	bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK);
 	bd.stat |= TX_BD_LEN(length);
-	ethoc_write_bd(dev, entry, &bd);
+	ethoc_write_bd(priv, entry, &bd);
 
 	/* start transmit */
 	bd.stat |= TX_BD_READY;
-	ethoc_write_bd(dev, entry, &bd);
+	ethoc_write_bd(priv, entry, &bd);
 
 	/* wait for transfer to succeed */
 	tmo = get_timer(0) + 5 * CONFIG_SYS_HZ;
 	while (1) {
-		pending = ethoc_read(dev, INT_SOURCE);
-		ethoc_ack_irq(dev, pending & ~INT_MASK_RX);
+		pending = ethoc_read(priv, INT_SOURCE);
+		ethoc_ack_irq(priv, pending & ~INT_MASK_RX);
 		if (pending & INT_MASK_BUSY)
 			debug("%s(): packet dropped\n", __func__);
 
 		if (pending & INT_MASK_TX) {
-			ethoc_tx(dev);
+			ethoc_tx(priv);
 			break;
 		}
 		if (get_timer(0) >= tmo) {
@@ -461,24 +514,290 @@
 	return 0;
 }
 
+static int ethoc_free_pkt_common(struct ethoc *priv)
+{
+	struct ethoc_bd bd;
+	u32 i = priv->cur_rx % priv->num_rx;
+	u32 entry = priv->num_tx + i;
+	void *src;
+
+	ethoc_read_bd(priv, entry, &bd);
+
+	if (priv->packet)
+		src = priv->packet + entry * PKTSIZE_ALIGN;
+	else
+		src = net_rx_packets[i];
+	/* clear the buffer descriptor so it can be reused */
+	flush_dcache_range((ulong)src,
+			   (ulong)src + PKTSIZE_ALIGN);
+	bd.stat &= ~RX_BD_STATS;
+	bd.stat |= RX_BD_EMPTY;
+	ethoc_write_bd(priv, entry, &bd);
+	priv->cur_rx++;
+
+	return 0;
+}
+
+#ifdef CONFIG_PHYLIB
+
+static int ethoc_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
+{
+	struct ethoc *priv = bus->priv;
+	int rc;
+
+	ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg));
+	ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ);
+
+	rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS),
+			  MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
+
+	if (rc == 0) {
+		u32 data = ethoc_read(priv, MIIRX_DATA);
+
+		/* reset MII command register */
+		ethoc_write(priv, MIICOMMAND, 0);
+		return data;
+	}
+	return rc;
+}
+
+static int ethoc_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
+			    u16 val)
+{
+	struct ethoc *priv = bus->priv;
+	int rc;
+
+	ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg));
+	ethoc_write(priv, MIITX_DATA, val);
+	ethoc_write(priv, MIICOMMAND, MIICOMMAND_WRITE);
+
+	rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS),
+			  MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
+
+	if (rc == 0) {
+		/* reset MII command register */
+		ethoc_write(priv, MIICOMMAND, 0);
+	}
+	return rc;
+}
+
+static int ethoc_mdio_init(const char *name, struct ethoc *priv)
+{
+	struct mii_dev *bus = mdio_alloc();
+	int ret;
+
+	if (!bus) {
+		printf("Failed to allocate MDIO bus\n");
+		return -ENOMEM;
+	}
+
+	bus->read = ethoc_mdio_read;
+	bus->write = ethoc_mdio_write;
+	snprintf(bus->name, sizeof(bus->name), "%s", name);
+	bus->priv = priv;
+
+	ret = mdio_register(bus);
+	if (ret < 0)
+		return ret;
+
+	priv->bus = miiphy_get_dev_by_name(name);
+	return 0;
+}
+
+static int ethoc_phy_init(struct ethoc *priv, void *dev)
+{
+	struct phy_device *phydev;
+	int mask = 0xffffffff;
+
+#ifdef CONFIG_PHY_ADDR
+	mask = 1 << CONFIG_PHY_ADDR;
+#endif
+
+	phydev = phy_find_by_mask(priv->bus, mask, PHY_INTERFACE_MODE_MII);
+	if (!phydev)
+		return -ENODEV;
+
+	phy_connect_dev(phydev, dev);
+
+	phydev->supported &= PHY_BASIC_FEATURES;
+	phydev->advertising = phydev->supported;
+
+	priv->phydev = phydev;
+	phy_config(phydev);
+
+	return 0;
+}
+
+#else
+
+static inline int ethoc_mdio_init(const char *name, struct ethoc *priv)
+{
+	return 0;
+}
+
+static inline int ethoc_phy_init(struct ethoc *priv, void *dev)
+{
+	return 0;
+}
+
+#endif
+
+#ifdef CONFIG_DM_ETH
+
+static int ethoc_write_hwaddr(struct udevice *dev)
+{
+	struct ethoc_eth_pdata *pdata = dev_get_platdata(dev);
+	struct ethoc *priv = dev_get_priv(dev);
+	u8 *mac = pdata->eth_pdata.enetaddr;
+
+	return ethoc_write_hwaddr_common(priv, mac);
+}
+
+static int ethoc_send(struct udevice *dev, void *packet, int length)
+{
+	return ethoc_send_common(dev_get_priv(dev), packet, length);
+}
+
+static int ethoc_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+	return ethoc_free_pkt_common(dev_get_priv(dev));
+}
+
+static int ethoc_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct ethoc *priv = dev_get_priv(dev);
+
+	if (flags & ETH_RECV_CHECK_DEVICE)
+		if (!ethoc_is_new_packet_received(priv))
+			return -EAGAIN;
+
+	return ethoc_rx_common(priv, packetp);
+}
+
+static int ethoc_start(struct udevice *dev)
+{
+	return ethoc_init_common(dev_get_priv(dev));
+}
+
+static void ethoc_stop(struct udevice *dev)
+{
+	ethoc_stop_common(dev_get_priv(dev));
+}
+
+static int ethoc_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ethoc_eth_pdata *pdata = dev_get_platdata(dev);
+	fdt_addr_t addr;
+
+	pdata->eth_pdata.iobase = dev_get_addr(dev);
+	addr = dev_get_addr_index(dev, 1);
+	if (addr != FDT_ADDR_T_NONE)
+		pdata->packet_base = addr;
+	return 0;
+}
+
+static int ethoc_probe(struct udevice *dev)
+{
+	struct ethoc_eth_pdata *pdata = dev_get_platdata(dev);
+	struct ethoc *priv = dev_get_priv(dev);
+
+	priv->iobase = ioremap(pdata->eth_pdata.iobase, ETHOC_IOSIZE);
+	if (pdata->packet_base) {
+		priv->packet_phys = pdata->packet_base;
+		priv->packet = ioremap(pdata->packet_base,
+				       (1 + PKTBUFSRX) * PKTSIZE_ALIGN);
+	}
+
+	ethoc_mdio_init(dev->name, priv);
+	ethoc_phy_init(priv, dev);
+
+	return 0;
+}
+
+static int ethoc_remove(struct udevice *dev)
+{
+	struct ethoc *priv = dev_get_priv(dev);
+
+#ifdef CONFIG_PHYLIB
+	free(priv->phydev);
+	mdio_unregister(priv->bus);
+	mdio_free(priv->bus);
+#endif
+	iounmap(priv->iobase);
+	return 0;
+}
+
+static const struct eth_ops ethoc_ops = {
+	.start		= ethoc_start,
+	.stop		= ethoc_stop,
+	.send		= ethoc_send,
+	.recv		= ethoc_recv,
+	.free_pkt	= ethoc_free_pkt,
+	.write_hwaddr	= ethoc_write_hwaddr,
+};
+
+static const struct udevice_id ethoc_ids[] = {
+	{ .compatible = "opencores,ethoc" },
+	{ }
+};
+
+U_BOOT_DRIVER(ethoc) = {
+	.name				= "ethoc",
+	.id				= UCLASS_ETH,
+	.of_match			= ethoc_ids,
+	.ofdata_to_platdata		= ethoc_ofdata_to_platdata,
+	.probe				= ethoc_probe,
+	.remove				= ethoc_remove,
+	.ops				= &ethoc_ops,
+	.priv_auto_alloc_size		= sizeof(struct ethoc),
+	.platdata_auto_alloc_size	= sizeof(struct ethoc_eth_pdata),
+};
+
+#else
+
+static int ethoc_init(struct eth_device *dev, bd_t *bd)
+{
+	struct ethoc *priv = (struct ethoc *)dev->priv;
+
+	return ethoc_init_common(priv);
+}
+
+static int ethoc_write_hwaddr(struct eth_device *dev)
+{
+	struct ethoc *priv = (struct ethoc *)dev->priv;
+	u8 *mac = dev->enetaddr;
+
+	return ethoc_write_hwaddr_common(priv, mac);
+}
+
+static int ethoc_send(struct eth_device *dev, void *packet, int length)
+{
+	return ethoc_send_common(dev->priv, packet, length);
+}
+
 static void ethoc_halt(struct eth_device *dev)
 {
-	ethoc_disable_rx_and_tx(dev);
+	ethoc_disable_rx_and_tx(dev->priv);
 }
 
 static int ethoc_recv(struct eth_device *dev)
 {
-	u32 pending;
+	struct ethoc *priv = (struct ethoc *)dev->priv;
+	int count;
 
-	pending = ethoc_read(dev, INT_SOURCE);
-	ethoc_ack_irq(dev, pending);
-	if (pending & INT_MASK_BUSY)
-		debug("%s(): packet dropped\n", __func__);
-	if (pending & INT_MASK_RX) {
-		debug("%s(): rx irq\n", __func__);
-		ethoc_rx(dev, PKTBUFSRX);
-	}
+	if (!ethoc_is_new_packet_received(priv))
+		return 0;
+
+	for (count = 0; count < PKTBUFSRX; ++count) {
+		uchar *packetp;
+		int size = ethoc_rx_common(priv, &packetp);
 
+		if (size < 0)
+			break;
+		if (size > 0)
+			net_process_received_packet(packetp, size);
+		ethoc_free_pkt_common(priv);
+	}
 	return 0;
 }
 
@@ -503,9 +822,16 @@
 	dev->halt = ethoc_halt;
 	dev->send = ethoc_send;
 	dev->recv = ethoc_recv;
-	dev->write_hwaddr = ethoc_set_mac_address;
+	dev->write_hwaddr = ethoc_write_hwaddr;
 	sprintf(dev->name, "%s-%hu", "ETHOC", dev_num);
+	priv->iobase = ioremap(dev->iobase, ETHOC_IOSIZE);
 
 	eth_register(dev);
+
+	ethoc_mdio_init(dev->name, priv);
+	ethoc_phy_init(priv, dev);
+
 	return 1;
 }
+
+#endif
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 360f8e4..e871b3e 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -233,6 +233,7 @@
 	return ret;
 }
 
+#ifndef CONFIG_FEC_FIXED_SPEED
 static int miiphy_wait_aneg(struct eth_device *dev)
 {
 	uint32_t start;
@@ -260,6 +261,7 @@
 
 	return 0;
 }
+#endif /* CONFIG_FEC_FIXED_SPEED */
 #endif
 
 static int fec_rx_task_enable(struct fec_priv *fec)
@@ -502,6 +504,8 @@
 		}
 		speed = fec->phydev->speed;
 	}
+#elif CONFIG_FEC_FIXED_SPEED
+	speed = CONFIG_FEC_FIXED_SPEED;
 #else
 	miiphy_wait_aneg(edev);
 	speed = miiphy_speed(edev->name, fec->phy_id);
diff --git a/drivers/net/fm/Makefile b/drivers/net/fm/Makefile
index 493cdc6..344fbe2 100644
--- a/drivers/net/fm/Makefile
+++ b/drivers/net/fm/Makefile
@@ -39,3 +39,4 @@
 obj-$(CONFIG_PPC_B4420) += b4860.o
 obj-$(CONFIG_PPC_B4860) += b4860.o
 obj-$(CONFIG_LS1043A)	+= ls1043.o
+obj-$(CONFIG_LS1046A)	+= ls1046.o
diff --git a/drivers/net/fm/ls1046.c b/drivers/net/fm/ls1046.c
new file mode 100644
index 0000000..bf55554
--- /dev/null
+++ b/drivers/net/fm/ls1046.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+#include <phy.h>
+#include <fm_eth.h>
+#include <asm/io.h>
+#include <asm/arch/fsl_serdes.h>
+
+#define FSL_CHASSIS2_RCWSR13_EC1		0xe0000000 /* bits 416..418 */
+#define FSL_CHASSIS2_RCWSR13_EC1_DTSEC3_RGMII	0x00000000
+#define FSL_CHASSIS2_RCWSR13_EC1_GPIO		0x20000000
+#define FSL_CHASSIS2_RCWSR13_EC1_FTM		0xa0000000
+#define FSL_CHASSIS2_RCWSR13_EC2		0x1c000000 /* bits 419..421 */
+#define FSL_CHASSIS2_RCWSR13_EC2_DTSEC4_RGMII	0x00000000
+#define FSL_CHASSIS2_RCWSR13_EC2_GPIO		0x04000000
+#define FSL_CHASSIS2_RCWSR13_EC2_1588		0x08000000
+#define FSL_CHASSIS2_RCWSR13_EC2_FTM		0x14000000
+
+u32 port_to_devdisr[] = {
+	[FM1_DTSEC1] = FSL_CHASSIS2_DEVDISR2_DTSEC1_1,
+	[FM1_DTSEC2] = FSL_CHASSIS2_DEVDISR2_DTSEC1_2,
+	[FM1_DTSEC3] = FSL_CHASSIS2_DEVDISR2_DTSEC1_3,
+	[FM1_DTSEC4] = FSL_CHASSIS2_DEVDISR2_DTSEC1_4,
+	[FM1_DTSEC5] = FSL_CHASSIS2_DEVDISR2_DTSEC1_5,
+	[FM1_DTSEC6] = FSL_CHASSIS2_DEVDISR2_DTSEC1_6,
+	[FM1_DTSEC9] = FSL_CHASSIS2_DEVDISR2_DTSEC1_9,
+	[FM1_DTSEC10] = FSL_CHASSIS2_DEVDISR2_DTSEC1_10,
+	[FM1_10GEC1] = FSL_CHASSIS2_DEVDISR2_10GEC1_1,
+	[FM1_10GEC2] = FSL_CHASSIS2_DEVDISR2_10GEC1_2,
+	[FM1_10GEC3] = FSL_CHASSIS2_DEVDISR2_10GEC1_3,
+	[FM1_10GEC4] = FSL_CHASSIS2_DEVDISR2_10GEC1_4,
+};
+
+static int is_device_disabled(enum fm_port port)
+{
+	struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	u32 devdisr2 = in_be32(&gur->devdisr2);
+
+	return port_to_devdisr[port] & devdisr2;
+}
+
+void fman_disable_port(enum fm_port port)
+{
+	struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+
+	setbits_be32(&gur->devdisr2, port_to_devdisr[port]);
+}
+
+phy_interface_t fman_port_enet_if(enum fm_port port)
+{
+	struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	u32 rcwsr13 = in_be32(&gur->rcwsr[13]);
+
+	if (is_device_disabled(port))
+		return PHY_INTERFACE_MODE_NONE;
+
+	if ((port == FM1_10GEC1) && (is_serdes_configured(XFI_FM1_MAC9)))
+		return PHY_INTERFACE_MODE_XGMII;
+
+	if ((port == FM1_DTSEC9) && (is_serdes_configured(XFI_FM1_MAC9)))
+		return PHY_INTERFACE_MODE_NONE;
+
+	if ((port == FM1_10GEC2) && (is_serdes_configured(XFI_FM1_MAC10)))
+		return PHY_INTERFACE_MODE_XGMII;
+
+	if ((port == FM1_DTSEC10) && (is_serdes_configured(XFI_FM1_MAC10)))
+		return PHY_INTERFACE_MODE_NONE;
+
+	if (port == FM1_DTSEC3)
+		if ((rcwsr13 & FSL_CHASSIS2_RCWSR13_EC1) ==
+				FSL_CHASSIS2_RCWSR13_EC1_DTSEC3_RGMII)
+			return PHY_INTERFACE_MODE_RGMII;
+
+	if (port == FM1_DTSEC4)
+		if ((rcwsr13 & FSL_CHASSIS2_RCWSR13_EC2) ==
+				FSL_CHASSIS2_RCWSR13_EC2_DTSEC4_RGMII)
+			return PHY_INTERFACE_MODE_RGMII;
+
+	/* handle SGMII, only MAC 2/5/6/9/10 available */
+	switch (port) {
+	case FM1_DTSEC2:
+	case FM1_DTSEC5:
+	case FM1_DTSEC6:
+	case FM1_DTSEC9:
+	case FM1_DTSEC10:
+		if (is_serdes_configured(SGMII_FM1_DTSEC2 + port - FM1_DTSEC2))
+			return PHY_INTERFACE_MODE_SGMII;
+		break;
+	default:
+		break;
+	}
+
+	/* handle 2.5G SGMII, only MAC 5/9/10 available */
+	switch (port) {
+	case FM1_DTSEC5:
+	case FM1_DTSEC9:
+	case FM1_DTSEC10:
+		if (is_serdes_configured(SGMII_2500_FM1_DTSEC5 +
+					 port - FM1_DTSEC5))
+			return PHY_INTERFACE_MODE_SGMII_2500;
+		break;
+	default:
+		break;
+	}
+
+	/* handle QSGMII, only MAC 1/5/6/10 available */
+	switch (port) {
+	case FM1_DTSEC1:
+	case FM1_DTSEC5:
+	case FM1_DTSEC6:
+	case FM1_DTSEC10:
+		if (is_serdes_configured(QSGMII_FM1_A))
+			return PHY_INTERFACE_MODE_QSGMII;
+		break;
+	default:
+		break;
+	}
+
+	return PHY_INTERFACE_MODE_NONE;
+}
diff --git a/drivers/net/fsl_mcdmafec.c b/drivers/net/fsl_mcdmafec.c
index 792534b..15a3ce0 100644
--- a/drivers/net/fsl_mcdmafec.c
+++ b/drivers/net/fsl_mcdmafec.c
@@ -556,8 +556,17 @@
 		eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-		miiphy_register(dev->name,
-				mcffec_miiphy_read, mcffec_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+		mdiodev->read = mcffec_miiphy_read;
+		mdiodev->write = mcffec_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 #endif
 
 		if (i > 0)
diff --git a/drivers/net/ftmac110.c b/drivers/net/ftmac110.c
index 4f17015..8fa767a 100644
--- a/drivers/net/ftmac110.c
+++ b/drivers/net/ftmac110.c
@@ -364,32 +364,35 @@
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 
-static int ftmac110_mdio_read(
-	const char *devname, uint8_t addr, uint8_t reg, uint16_t *value)
+static int ftmac110_mdio_read(struct mii_dev *bus, int addr, int devad,
+			      int reg)
 {
+	uint16_t value = 0;
 	int ret = 0;
 	struct eth_device *dev;
 
-	dev = eth_get_dev_by_name(devname);
+	dev = eth_get_dev_by_name(bus->name);
 	if (dev == NULL) {
-		printf("%s: no such device\n", devname);
+		printf("%s: no such device\n", bus->name);
 		ret = -1;
 	} else {
-		*value = mdio_read(dev, addr, reg);
+		value = mdio_read(dev, addr, reg);
 	}
 
-	return ret;
+	if (ret < 0)
+		return ret;
+	return value;
 }
 
-static int ftmac110_mdio_write(
-	const char *devname, uint8_t addr, uint8_t reg, uint16_t value)
+static int ftmac110_mdio_write(struct mii_dev *bus, int addr, int devad,
+			       int reg, u16 value)
 {
 	int ret = 0;
 	struct eth_device *dev;
 
-	dev = eth_get_dev_by_name(devname);
+	dev = eth_get_dev_by_name(bus->name);
 	if (dev == NULL) {
-		printf("%s: no such device\n", devname);
+		printf("%s: no such device\n", bus->name);
 		ret = -1;
 	} else {
 		mdio_write(dev, addr, reg, value);
@@ -468,7 +471,17 @@
 	eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name, ftmac110_mdio_read, ftmac110_mdio_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = ftmac110_mdio_read;
+	mdiodev->write = ftmac110_mdio_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 
 	card_nr++;
diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c
index 6b28df0..e41b7d1 100644
--- a/drivers/net/keystone_net.c
+++ b/drivers/net/keystone_net.c
@@ -11,6 +11,7 @@
 #include <console.h>
 
 #include <dm.h>
+#include <dm/lists.h>
 
 #include <net.h>
 #include <phy.h>
@@ -765,6 +766,8 @@
 	hw_config_streaming_switch();
 
 	if (priv->has_mdio) {
+		keystone2_mdio_reset(priv->mdio_bus);
+
 		phy_startup(priv->phydev);
 		if (priv->phydev->link == 0) {
 			error("phy startup failed\n");
@@ -906,27 +909,38 @@
 		pll_pa_clk_sel();
 
 
-	priv->net_rx_buffs.buff_ptr = rx_buffs,
-	priv->net_rx_buffs.num_buffs = RX_BUFF_NUMS,
-	priv->net_rx_buffs.buff_len = RX_BUFF_LEN,
+	priv->net_rx_buffs.buff_ptr = rx_buffs;
+	priv->net_rx_buffs.num_buffs = RX_BUFF_NUMS;
+	priv->net_rx_buffs.buff_len = RX_BUFF_LEN;
 
-	/* Register MDIO bus */
-	mdio_bus = mdio_alloc();
-	if (!mdio_bus) {
-		error("MDIO alloc failed\n");
-		return -ENOMEM;
-	}
-	priv->mdio_bus = mdio_bus;
-	mdio_bus->read	= keystone2_mdio_read;
-	mdio_bus->write	= keystone2_mdio_write;
-	mdio_bus->reset	= keystone2_mdio_reset;
-	mdio_bus->priv	= priv->mdio_base;
-	sprintf(mdio_bus->name, "ethernet-mdio");
+	if (priv->slave_port == 1) {
+		/*
+		 * Register MDIO bus for slave 0 only, other slave have
+		 * to re-use the same
+		 */
+		mdio_bus = mdio_alloc();
+		if (!mdio_bus) {
+			error("MDIO alloc failed\n");
+			return -ENOMEM;
+		}
+		priv->mdio_bus = mdio_bus;
+		mdio_bus->read	= keystone2_mdio_read;
+		mdio_bus->write	= keystone2_mdio_write;
+		mdio_bus->reset	= keystone2_mdio_reset;
+		mdio_bus->priv	= priv->mdio_base;
+		sprintf(mdio_bus->name, "ethernet-mdio");
+
+		ret = mdio_register(mdio_bus);
+		if (ret) {
+			error("MDIO bus register failed\n");
+			return ret;
+		}
+	} else {
+		/* Get the MDIO bus from slave 0 device */
+		struct ks2_eth_priv *parent_priv;
 
-	ret = mdio_register(mdio_bus);
-	if (ret) {
-		error("MDIO bus register failed\n");
-		return ret;
+		parent_priv = dev_get_priv(dev->parent);
+		priv->mdio_bus = parent_priv->mdio_bus;
 	}
 
 #ifndef CONFIG_SOC_K2G
@@ -935,8 +949,11 @@
 
 	priv->netcp_pktdma = &netcp_pktdma;
 
-	priv->phydev = phy_connect(mdio_bus, priv->phy_addr, dev, priv->phy_if);
-	phy_config(priv->phydev);
+	if (priv->has_mdio) {
+		priv->phydev = phy_connect(priv->mdio_bus, priv->phy_addr,
+					   dev, priv->phy_if);
+		phy_config(priv->phydev);
+	}
 
 	return 0;
 }
@@ -962,39 +979,103 @@
 	.write_hwaddr		= ks2_eth_write_hwaddr,
 };
 
-
-static int ks2_eth_ofdata_to_platdata(struct udevice *dev)
+static int ks2_eth_bind_slaves(struct udevice *dev, int gbe, int *gbe_0)
 {
-	struct ks2_eth_priv *priv = dev_get_priv(dev);
-	struct eth_pdata *pdata = dev_get_platdata(dev);
 	const void *fdt = gd->fdt_blob;
+	struct udevice *sl_dev;
 	int interfaces;
-	int interface_0;
-	int netcp_gbe_0;
-	int phy;
+	int sec_slave;
+	int slave;
+	int ret;
+	char *slave_name;
+
+	interfaces = fdt_subnode_offset(fdt, gbe, "interfaces");
+	fdt_for_each_subnode(fdt, slave, interfaces) {
+		int slave_no;
+
+		slave_no = fdtdec_get_int(fdt, slave, "slave-port", -ENOENT);
+		if (slave_no == -ENOENT)
+			continue;
+
+		if (slave_no == 0) {
+			/* This is the current eth device */
+			*gbe_0 = slave;
+		} else {
+			/* Slave devices to be registered */
+			slave_name = malloc(20);
+			snprintf(slave_name, 20, "netcp@slave-%d", slave_no);
+			ret = device_bind_driver_to_node(dev, "eth_ks2_sl",
+							 slave_name, slave,
+							 &sl_dev);
+			if (ret) {
+				error("ks2_net - not able to bind slave interfaces\n");
+				return ret;
+			}
+		}
+	}
+
+	sec_slave = fdt_subnode_offset(fdt, gbe, "secondary-slave-ports");
+	fdt_for_each_subnode(fdt, slave, sec_slave) {
+		int slave_no;
+
+		slave_no = fdtdec_get_int(fdt, slave, "slave-port", -ENOENT);
+		if (slave_no == -ENOENT)
+			continue;
+
+		/* Slave devices to be registered */
+		slave_name = malloc(20);
+		snprintf(slave_name, 20, "netcp@slave-%d", slave_no);
+		ret = device_bind_driver_to_node(dev, "eth_ks2_sl", slave_name,
+						 slave, &sl_dev);
+		if (ret) {
+			error("ks2_net - not able to bind slave interfaces\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int ks2_eth_parse_slave_interface(int netcp, int slave,
+					 struct ks2_eth_priv *priv,
+					 struct eth_pdata *pdata)
+{
+	const void *fdt = gd->fdt_blob;
 	int mdio;
-	u32 dma_channel[6];
+	int phy;
+	int dma_count;
+	u32 dma_channel[8];
 
-	interfaces = fdt_subnode_offset(fdt, dev->of_offset,
-					"netcp-interfaces");
-	interface_0 = fdt_subnode_offset(fdt, interfaces, "interface-0");
+	priv->slave_port = fdtdec_get_int(fdt, slave, "slave-port", -1);
+	priv->net_rx_buffs.rx_flow = priv->slave_port * 8;
 
-	netcp_gbe_0 = fdtdec_lookup_phandle(fdt, interface_0, "netcp-gbe");
-	priv->link_type = fdtdec_get_int(fdt, netcp_gbe_0,
-					 "link-interface", -1);
-	priv->slave_port = fdtdec_get_int(fdt, netcp_gbe_0, "slave-port", -1);
 	/* U-Boot slave port number starts with 1 instead of 0 */
 	priv->slave_port += 1;
 
-	phy = fdtdec_lookup_phandle(fdt, netcp_gbe_0, "phy-handle");
-	priv->phy_addr = fdtdec_get_int(fdt, phy, "reg", -1);
+	dma_count = fdtdec_get_int_array_count(fdt, netcp,
+					       "ti,navigator-dmas",
+					       dma_channel, 8);
 
-	mdio = fdt_parent_offset(fdt, phy);
-	if (mdio < 0) {
-		error("mdio dt not found\n");
-		return -ENODEV;
+	if (dma_count > (2 * priv->slave_port)) {
+		int dma_idx;
+
+		dma_idx = priv->slave_port * 2 - 1;
+		priv->net_rx_buffs.rx_flow = dma_channel[dma_idx];
 	}
-	priv->mdio_base = (void *)fdtdec_get_addr(fdt, mdio, "reg");
+
+	priv->link_type = fdtdec_get_int(fdt, slave, "link-interface", -1);
+
+	phy = fdtdec_lookup_phandle(fdt, slave, "phy-handle");
+	if (phy >= 0) {
+		priv->phy_addr = fdtdec_get_int(fdt, phy, "reg", -1);
+
+		mdio = fdt_parent_offset(fdt, phy);
+		if (mdio < 0) {
+			error("mdio dt not found\n");
+			return -ENODEV;
+		}
+		priv->mdio_base = (void *)fdtdec_get_addr(fdt, mdio, "reg");
+	}
 
 	if (priv->link_type == LINK_TYPE_MAC_TO_PHY_MODE) {
 		priv->phy_if = PHY_INTERFACE_MODE_SGMII;
@@ -1002,20 +1083,71 @@
 		priv->sgmii_link_type = SGMII_LINK_MAC_PHY;
 		priv->has_mdio = true;
 	}
-	pdata->iobase = dev_get_addr(dev);
 
-	fdtdec_get_int_array(fdt, dev->of_offset, "ti,navigator-dmas",
-			     dma_channel, 6);
-	priv->net_rx_buffs.rx_flow = dma_channel[1];
+	return 0;
+}
+
+static int ks2_sl_eth_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ks2_eth_priv *priv = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	const void *fdt = gd->fdt_blob;
+	int slave = dev->of_offset;
+	int interfaces;
+	int gbe;
+	int netcp_devices;
+	int netcp;
+
+	interfaces = fdt_parent_offset(fdt, slave);
+	gbe = fdt_parent_offset(fdt, interfaces);
+	netcp_devices = fdt_parent_offset(fdt, gbe);
+	netcp = fdt_parent_offset(fdt, netcp_devices);
+
+	ks2_eth_parse_slave_interface(netcp, slave, priv, pdata);
+
+	pdata->iobase = fdtdec_get_addr(fdt, netcp, "reg");
 
 	return 0;
 }
 
+static int ks2_eth_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ks2_eth_priv *priv = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	const void *fdt = gd->fdt_blob;
+	int gbe_0 = -ENODEV;
+	int netcp_devices;
+	int gbe;
+
+	netcp_devices = fdt_subnode_offset(fdt, dev->of_offset,
+					   "netcp-devices");
+	gbe = fdt_subnode_offset(fdt, netcp_devices, "gbe");
+
+	ks2_eth_bind_slaves(dev, gbe, &gbe_0);
+
+	ks2_eth_parse_slave_interface(dev->of_offset, gbe_0, priv, pdata);
+
+	pdata->iobase = dev_get_addr(dev);
+
+	return 0;
+}
+
 static const struct udevice_id ks2_eth_ids[] = {
 	{ .compatible = "ti,netcp-1.0" },
 	{ }
 };
 
+U_BOOT_DRIVER(eth_ks2_slave) = {
+	.name	= "eth_ks2_sl",
+	.id	= UCLASS_ETH,
+	.ofdata_to_platdata = ks2_sl_eth_ofdata_to_platdata,
+	.probe	= ks2_eth_probe,
+	.remove	= ks2_eth_remove,
+	.ops	= &ks2_eth_ops,
+	.priv_auto_alloc_size = sizeof(struct ks2_eth_priv),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+	.flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
 
 U_BOOT_DRIVER(eth_ks2) = {
 	.name	= "eth_ks2",
diff --git a/drivers/net/lpc32xx_eth.c b/drivers/net/lpc32xx_eth.c
index 6cc273c..2dd69f3 100644
--- a/drivers/net/lpc32xx_eth.c
+++ b/drivers/net/lpc32xx_eth.c
@@ -226,9 +226,11 @@
  *
  * Returns 16bit phy register value, or 0xffff on error
  */
-static int mii_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 *data)
+static int mii_reg_read(struct mii_dev *bus, int phy_adr, int devad,
+			int reg_ofs)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	u16 data = 0;
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	struct lpc32xx_eth_device *dlpc32xx_eth = to_lpc32xx_eth(dev);
 	struct lpc32xx_eth_registers *regs = dlpc32xx_eth->regs;
 	u32 mind_reg;
@@ -270,12 +272,12 @@
 		return -EFAULT;
 	}
 
-	*data = (u16) readl(&regs->mrdd);
+	data = (u16) readl(&regs->mrdd);
 
 	debug("%s:(adr %d, off %d) => %04x\n", __func__, phy_adr,
-	      reg_ofs, *data);
+	      reg_ofs, data);
 
-	return 0;
+	return data;
 }
 
 /*
@@ -284,9 +286,10 @@
  * Returns 0 if write succeed, -EINVAL on bad parameters
  * -ETIME on timeout
  */
-static int mii_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data)
+static int mii_reg_write(struct mii_dev *bus, int phy_adr, int devad,
+			 int reg_ofs, u16 data)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	struct lpc32xx_eth_device *dlpc32xx_eth = to_lpc32xx_eth(dev);
 	struct lpc32xx_eth_registers *regs = dlpc32xx_eth->regs;
 	u32 mind_reg;
@@ -333,25 +336,6 @@
 }
 #endif
 
-#if defined(CONFIG_PHYLIB)
-int lpc32xx_eth_phy_read(struct mii_dev *bus, int phy_addr, int dev_addr,
-	int reg_addr)
-{
-	u16 data;
-	int ret;
-	ret = mii_reg_read(bus->name, phy_addr, reg_addr, &data);
-	if (ret)
-		return ret;
-	return data;
-}
-
-int lpc32xx_eth_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr,
-	int reg_addr, u16 data)
-{
-	return mii_reg_write(bus->name, phy_addr, reg_addr, data);
-}
-#endif
-
 /*
  * Provide default Ethernet buffers base address if target did not.
  * Locate buffers in SRAM at 0x00001000 to avoid cache issues and
@@ -580,8 +564,8 @@
 		printf("mdio_alloc failed\n");
 		return -ENOMEM;
 	}
-	bus->read = lpc32xx_eth_phy_read;
-	bus->write = lpc32xx_eth_phy_write;
+	bus->read = mii_reg_read;
+	bus->write = mii_reg_write;
 	strcpy(bus->name, dev->name);
 
 	ret = mdio_register(bus);
@@ -645,7 +629,17 @@
 #if defined(CONFIG_PHYLIB)
 	lpc32xx_eth_phylib_init(dev, CONFIG_PHY_ADDR);
 #elif defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name, mii_reg_read, mii_reg_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = mii_reg_read;
+	mdiodev->write = mii_reg_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 
 	return 0;
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 0835fdc..921537f 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -43,6 +43,8 @@
 
 #include "macb.h"
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #define MACB_RX_BUFFER_SIZE		4096
 #define MACB_RX_RING_SIZE		(MACB_RX_BUFFER_SIZE / 128)
 #define MACB_TX_RING_SIZE		16
@@ -108,6 +110,10 @@
 #endif
 	unsigned short		phy_addr;
 	struct mii_dev		*bus;
+
+#ifdef CONFIG_DM_ETH
+	phy_interface_t		phy_interface;
+#endif
 };
 #ifndef CONFIG_DM_ETH
 #define to_macb(_nd) container_of(_nd, struct macb_device, netdev)
@@ -199,39 +205,41 @@
 
 #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
 
-int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
+int macb_miiphy_read(struct mii_dev *bus, int phy_adr, int devad, int reg)
 {
+	u16 value = 0;
 #ifdef CONFIG_DM_ETH
-	struct udevice *dev = eth_get_dev_by_name(devname);
+	struct udevice *dev = eth_get_dev_by_name(bus->name);
 	struct macb_device *macb = dev_get_priv(dev);
 #else
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	struct macb_device *macb = to_macb(dev);
 #endif
 
 	if (macb->phy_addr != phy_adr)
 		return -1;
 
-	arch_get_mdio_control(devname);
-	*value = macb_mdio_read(macb, reg);
+	arch_get_mdio_control(bus->name);
+	value = macb_mdio_read(macb, reg);
 
-	return 0;
+	return value;
 }
 
-int macb_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value)
+int macb_miiphy_write(struct mii_dev *bus, int phy_adr, int devad, int reg,
+		      u16 value)
 {
 #ifdef CONFIG_DM_ETH
-	struct udevice *dev = eth_get_dev_by_name(devname);
+	struct udevice *dev = eth_get_dev_by_name(bus->name);
 	struct macb_device *macb = dev_get_priv(dev);
 #else
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	struct macb_device *macb = to_macb(dev);
 #endif
 
 	if (macb->phy_addr != phy_adr)
 		return -1;
 
-	arch_get_mdio_control(devname);
+	arch_get_mdio_control(bus->name);
 	macb_mdio_write(macb, reg, value);
 
 	return 0;
@@ -434,7 +442,7 @@
 }
 
 #ifdef CONFIG_MACB_SEARCH_PHY
-static int macb_phy_find(struct macb_device *macb)
+static int macb_phy_find(struct macb_device *macb, const char *name)
 {
 	int i;
 	u16 phy_id;
@@ -444,21 +452,27 @@
 		macb->phy_addr = i;
 		phy_id = macb_mdio_read(macb, MII_PHYSID1);
 		if (phy_id != 0xffff) {
-			printf("%s: PHY present at %d\n", macb->netdev.name, i);
+			printf("%s: PHY present at %d\n", name, i);
 			return 1;
 		}
 	}
 
 	/* PHY isn't up to snuff */
-	printf("%s: PHY not found\n", macb->netdev.name);
+	printf("%s: PHY not found\n", name);
 
 	return 0;
 }
 #endif /* CONFIG_MACB_SEARCH_PHY */
 
-
+#ifdef CONFIG_DM_ETH
+static int macb_phy_init(struct udevice *dev, const char *name)
+#else
 static int macb_phy_init(struct macb_device *macb, const char *name)
+#endif
 {
+#ifdef CONFIG_DM_ETH
+	struct macb_device *macb = dev_get_priv(dev);
+#endif
 #ifdef CONFIG_PHYLIB
 	struct phy_device *phydev;
 #endif
@@ -470,7 +484,7 @@
 	arch_get_mdio_control(name);
 #ifdef CONFIG_MACB_SEARCH_PHY
 	/* Auto-detect phy_addr */
-	if (!macb_phy_find(macb))
+	if (!macb_phy_find(macb, name))
 		return 0;
 #endif /* CONFIG_MACB_SEARCH_PHY */
 
@@ -482,9 +496,14 @@
 	}
 
 #ifdef CONFIG_PHYLIB
+#ifdef CONFIG_DM_ETH
+	phydev = phy_connect(macb->bus, macb->phy_addr, dev,
+			     macb->phy_interface);
+#else
 	/* need to consider other phy interface mode */
 	phydev = phy_connect(macb->bus, macb->phy_addr, &macb->netdev,
 			     PHY_INTERFACE_MODE_RGMII);
+#endif
 	if (!phydev) {
 		printf("phy_connect failed\n");
 		return -ENODEV;
@@ -585,8 +604,15 @@
 	return 0;
 }
 
+#ifdef CONFIG_DM_ETH
+static int _macb_init(struct udevice *dev, const char *name)
+#else
 static int _macb_init(struct macb_device *macb, const char *name)
+#endif
 {
+#ifdef CONFIG_DM_ETH
+	struct macb_device *macb = dev_get_priv(dev);
+#endif
 	unsigned long paddr;
 	int i;
 
@@ -634,13 +660,35 @@
 		 * When the GMAC IP without GE feature, this bit is used
 		 * to select interface between RMII and MII.
 		 */
+#ifdef CONFIG_DM_ETH
+		if (macb->phy_interface == PHY_INTERFACE_MODE_RMII)
+			gem_writel(macb, UR, GEM_BIT(RGMII));
+		else
+			gem_writel(macb, UR, 0);
+#else
 #if defined(CONFIG_RGMII) || defined(CONFIG_RMII)
 		gem_writel(macb, UR, GEM_BIT(RGMII));
 #else
 		gem_writel(macb, UR, 0);
 #endif
+#endif
 	} else {
 	/* choose RMII or MII mode. This depends on the board */
+#ifdef CONFIG_DM_ETH
+#ifdef CONFIG_AT91FAMILY
+		if (macb->phy_interface == PHY_INTERFACE_MODE_RMII) {
+			macb_writel(macb, USRIO,
+				    MACB_BIT(RMII) | MACB_BIT(CLKEN));
+		} else {
+			macb_writel(macb, USRIO, MACB_BIT(CLKEN));
+		}
+#else
+		if (macb->phy_interface == PHY_INTERFACE_MODE_RMII)
+			macb_writel(macb, USRIO, 0);
+		else
+			macb_writel(macb, USRIO, MACB_BIT(MII));
+#endif
+#else
 #ifdef CONFIG_RMII
 #ifdef CONFIG_AT91FAMILY
 	macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN));
@@ -654,9 +702,14 @@
 	macb_writel(macb, USRIO, MACB_BIT(MII));
 #endif
 #endif /* CONFIG_RMII */
+#endif
 	}
 
+#ifdef CONFIG_DM_ETH
+	if (!macb_phy_init(dev, name))
+#else
 	if (!macb_phy_init(macb, name))
+#endif
 		return -1;
 
 	/* Enable TX and RX */
@@ -862,7 +915,17 @@
 	eth_register(netdev);
 
 #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
-	miiphy_register(netdev->name, macb_miiphy_read, macb_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, netdev->name, MDIO_NAME_LEN);
+	mdiodev->read = macb_miiphy_read;
+	mdiodev->write = macb_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 	macb->bus = miiphy_get_dev_by_name(netdev->name);
 #endif
 	return 0;
@@ -873,9 +936,7 @@
 
 static int macb_start(struct udevice *dev)
 {
-	struct macb_device *macb = dev_get_priv(dev);
-
-	return _macb_init(macb, dev->name);
+	return _macb_init(dev, dev->name);
 }
 
 static int macb_send(struct udevice *dev, void *packet, int length)
@@ -933,11 +994,33 @@
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 	struct macb_device *macb = dev_get_priv(dev);
 
+#ifdef CONFIG_DM_ETH
+	const char *phy_mode;
+
+	phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL);
+	if (phy_mode)
+		macb->phy_interface = phy_get_interface_by_name(phy_mode);
+	if (macb->phy_interface == -1) {
+		debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
+		return -EINVAL;
+	}
+#endif
+
 	macb->regs = (void *)pdata->iobase;
 
 	_macb_eth_initialize(macb);
 #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
-	miiphy_register(dev->name, macb_miiphy_read, macb_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = macb_miiphy_read;
+	mdiodev->write = macb_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 	macb->bus = miiphy_get_dev_by_name(dev->name);
 #endif
 
diff --git a/drivers/net/mcffec.c b/drivers/net/mcffec.c
index fd73099..e1b06b2 100644
--- a/drivers/net/mcffec.c
+++ b/drivers/net/mcffec.c
@@ -595,8 +595,17 @@
 		eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-		miiphy_register(dev->name,
-				mcffec_miiphy_read, mcffec_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+		mdiodev->read = mcffec_miiphy_read;
+		mdiodev->write = mcffec_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 #endif
 		if (i > 0)
 			fec_info[i - 1].next = &fec_info[i];
diff --git a/drivers/net/mcfmii.c b/drivers/net/mcfmii.c
index 17a780c..103e365 100644
--- a/drivers/net/mcfmii.c
+++ b/drivers/net/mcfmii.c
@@ -277,8 +277,7 @@
  *	  Otherwise they hang in mii_send() !!! Sorry!
  */
 
-int mcffec_miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
-		       unsigned short *value)
+int mcffec_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
 	short rdreg;		/* register working value */
 
@@ -287,28 +286,22 @@
 #endif
 	rdreg = mii_send(mk_mii_read(addr, reg));
 
-	*value = rdreg;
-
 #ifdef MII_DEBUG
-	printf("0x%04x\n", *value);
+	printf("0x%04x\n", rdreg);
 #endif
 
-	return 0;
+	return rdreg;
 }
 
-int mcffec_miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
-			unsigned short value)
+int mcffec_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+			u16 value)
 {
 #ifdef MII_DEBUG
-	printf("miiphy_write(0x%x) @ 0x%x = ", reg, addr);
+	printf("miiphy_write(0x%x) @ 0x%x = 0x%04x\n", reg, addr, value);
 #endif
 
 	mii_send(mk_mii_write(addr, reg, value));
 
-#ifdef MII_DEBUG
-	printf("0x%04x\n", value);
-#endif
-
 	return 0;
 }
 
diff --git a/drivers/net/mpc512x_fec.c b/drivers/net/mpc512x_fec.c
index e850672..b3746fb 100644
--- a/drivers/net/mpc512x_fec.c
+++ b/drivers/net/mpc512x_fec.c
@@ -22,8 +22,10 @@
 #error "CONFIG_MII has to be defined!"
 #endif
 
-int fec512x_miiphy_read(const char *devname, u8 phyAddr, u8 regAddr, u16 * retVal);
-int fec512x_miiphy_write(const char *devname, u8 phyAddr, u8 regAddr, u16 data);
+int fec512x_miiphy_read(struct mii_dev *bus, int phyAddr, int devad,
+			int regAddr);
+int fec512x_miiphy_write(struct mii_dev *bus, int phyAddr, int devad,
+			 int regAddr, u16 data);
 int mpc512x_fec_init_phy(struct eth_device *dev, bd_t * bis);
 
 static uchar rx_buff[FEC_BUFFER_SIZE];
@@ -639,8 +641,17 @@
 	eth_register (dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register (dev->name,
-			fec512x_miiphy_read, fec512x_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = fec512x_miiphy_read;
+	mdiodev->write = fec512x_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 
 	/* Clean up space FEC's MIB and FIFO RAM ...*/
@@ -670,8 +681,10 @@
 
 /* MII-interface related functions */
 /********************************************************************/
-int fec512x_miiphy_read(const char *devname, u8 phyAddr, u8 regAddr, u16 *retVal)
+int fec512x_miiphy_read(struct mii_dev *bus, int phyAddr, int devad,
+			int regAddr)
 {
+	u16 retVal = 0;
 	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
 	volatile fec512x_t *eth = &im->fec;
 	u32 reg;		/* convenient holder for the PHY register */
@@ -711,13 +724,14 @@
 	/*
 	 * it's now safe to read the PHY's register
 	 */
-	*retVal = (u16) in_be32(&eth->mii_data);
+	retVal = (u16) in_be32(&eth->mii_data);
 
-	return 0;
+	return retVal;
 }
 
 /********************************************************************/
-int fec512x_miiphy_write(const char *devname, u8 phyAddr, u8 regAddr, u16 data)
+int fec512x_miiphy_write(struct mii_dev *bus, int phyAddr, int devad,
+			 int regAddr, u16 data)
 {
 	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
 	volatile fec512x_t *eth = &im->fec;
diff --git a/drivers/net/mpc5xxx_fec.c b/drivers/net/mpc5xxx_fec.c
index e13b4cf..d75e858 100644
--- a/drivers/net/mpc5xxx_fec.c
+++ b/drivers/net/mpc5xxx_fec.c
@@ -35,8 +35,10 @@
     uint8 head[16];             /* MAC header(6 + 6 + 2) + 2(aligned) */
 } NBUF;
 
-int fec5xxx_miiphy_read(const char *devname, uint8 phyAddr, uint8 regAddr, uint16 *retVal);
-int fec5xxx_miiphy_write(const char *devname, uint8 phyAddr, uint8 regAddr, uint16 data);
+int fec5xxx_miiphy_read(struct mii_dev *bus, int phyAddr, int devad,
+			int regAddr);
+int fec5xxx_miiphy_write(struct mii_dev *bus, int phyAddr, int devad,
+			 int regAddr, u16 data);
 
 static int mpc5xxx_fec_init_phy(struct eth_device *dev, bd_t * bis);
 
@@ -917,8 +919,17 @@
 	eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register (dev->name,
-			fec5xxx_miiphy_read, fec5xxx_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = fec5xxx_miiphy_read;
+	mdiodev->write = fec5xxx_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 
 	/*
@@ -941,8 +952,10 @@
 
 /* MII-interface related functions */
 /********************************************************************/
-int fec5xxx_miiphy_read(const char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal)
+int fec5xxx_miiphy_read(struct mii_dev *bus, int phyAddr, int devad,
+			int regAddr)
 {
+	uint16 retVal = 0;
 	ethernet_regs *eth = (ethernet_regs *)MPC5XXX_FEC;
 	uint32 reg;		/* convenient holder for the PHY register */
 	uint32 phy;		/* convenient holder for the PHY */
@@ -977,13 +990,14 @@
 	/*
 	 * it's now safe to read the PHY's register
 	 */
-	*retVal = (uint16) eth->mii_data;
+	retVal = (uint16) eth->mii_data;
 
-	return 0;
+	return retVal;
 }
 
 /********************************************************************/
-int fec5xxx_miiphy_write(const char *devname, uint8 phyAddr, uint8 regAddr, uint16 data)
+int fec5xxx_miiphy_write(struct mii_dev *bus, int phyAddr, int devad,
+			 int regAddr, u16 data)
 {
 	ethernet_regs *eth = (ethernet_regs *)MPC5XXX_FEC;
 	uint32 reg;		/* convenient holder for the PHY register */
diff --git a/drivers/net/mvgbe.c b/drivers/net/mvgbe.c
index b16be92..a1c7ea0 100644
--- a/drivers/net/mvgbe.c
+++ b/drivers/net/mvgbe.c
@@ -48,9 +48,11 @@
  *
  * Returns 16bit phy register value, or 0xffff on error
  */
-static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 * data)
+static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad,
+			int reg_ofs)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	u16 data = 0;
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	struct mvgbe_device *dmvgbe = to_mvgbe(dev);
 	struct mvgbe_registers *regs = dmvgbe->regs;
 	u32 smi_reg;
@@ -60,8 +62,8 @@
 	if (phy_adr == MV_PHY_ADR_REQUEST &&
 			reg_ofs == MV_PHY_ADR_REQUEST) {
 		/* */
-		*data = (u16) (MVGBE_REG_RD(regs->phyadr) & PHYADR_MASK);
-		return 0;
+		data = (u16) (MVGBE_REG_RD(regs->phyadr) & PHYADR_MASK);
+		return data;
 	}
 	/* check parameters */
 	if (phy_adr > PHYADR_MASK) {
@@ -111,12 +113,12 @@
 	for (timeout = 0; timeout < MVGBE_PHY_SMI_TIMEOUT; timeout++)
 		;
 
-	*data = (u16) (MVGBE_REG_RD(MVGBE_SMI_REG) & MVGBE_PHY_SMI_DATA_MASK);
+	data = (u16) (MVGBE_REG_RD(MVGBE_SMI_REG) & MVGBE_PHY_SMI_DATA_MASK);
 
 	debug("%s:(adr %d, off %d) value= %04x\n", __func__, phy_adr, reg_ofs,
-	      *data);
+	      data);
 
-	return 0;
+	return data;
 }
 
 /*
@@ -125,9 +127,10 @@
  * Returns 0 if write succeed, -EINVAL on bad parameters
  * -ETIME on timeout
  */
-static int smi_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data)
+static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad,
+			 int reg_ofs, u16 data)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	struct mvgbe_device *dmvgbe = to_mvgbe(dev);
 	struct mvgbe_registers *regs = dmvgbe->regs;
 	u32 smi_reg;
@@ -785,7 +788,17 @@
 #if defined(CONFIG_PHYLIB)
 		mvgbe_phylib_init(dev, PHY_BASE_ADR + devnum);
 #elif defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-		miiphy_register(dev->name, smi_reg_read, smi_reg_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+		mdiodev->read = smi_reg_read;
+		mdiodev->write = smi_reg_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 		/* Set phy address of the port */
 		miiphy_write(dev->name, MV_PHY_ADR_REQUEST,
 				MV_PHY_ADR_REQUEST, PHY_BASE_ADR + devnum);
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 58d287b..4eeb0f6 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -8,6 +8,7 @@
  */
 #include <config.h>
 #include <common.h>
+#include <errno.h>
 #include <phy.h>
 
 #define PHY_AUTONEGOTIATE_TIMEOUT 5000
diff --git a/drivers/net/phy/miiphybb.c b/drivers/net/phy/miiphybb.c
index 5cda0b8..af676b9 100644
--- a/drivers/net/phy/miiphybb.c
+++ b/drivers/net/phy/miiphybb.c
@@ -230,24 +230,18 @@
  * Returns:
  *   0 on success
  */
-int bb_miiphy_read(const char *devname, unsigned char addr,
-		   unsigned char reg, unsigned short *value)
+int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg)
 {
 	short rdreg; /* register working value */
 	int v;
 	int j; /* counter */
 	struct bb_miiphy_bus *bus;
 
-	bus = bb_miiphy_getbus(devname);
+	bus = bb_miiphy_getbus(miidev->name);
 	if (bus == NULL) {
 		return -1;
 	}
 
-	if (value == NULL) {
-		puts("NULL value pointer\n");
-		return -1;
-	}
-
 	miiphy_pre (bus, 1, addr, reg);
 
 	/* tri-state our MDIO I/O pin so we can read */
@@ -267,8 +261,7 @@
 			bus->set_mdc(bus, 1);
 			bus->delay(bus);
 		}
-		/* There is no PHY, set value to 0xFFFF and return */
-		*value = 0xFFFF;
+		/* There is no PHY, return */
 		return -1;
 	}
 
@@ -294,13 +287,11 @@
 	bus->set_mdc(bus, 1);
 	bus->delay(bus);
 
-	*value = rdreg;
-
 #ifdef DEBUG
-	printf ("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, *value);
+	printf("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, rdreg);
 #endif
 
-	return 0;
+	return rdreg;
 }
 
 
@@ -311,13 +302,13 @@
  * Returns:
  *   0 on success
  */
-int bb_miiphy_write (const char *devname, unsigned char addr,
-		     unsigned char reg, unsigned short value)
+int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg,
+		    u16 value)
 {
 	struct bb_miiphy_bus *bus;
 	int j;			/* counter */
 
-	bus = bb_miiphy_getbus(devname);
+	bus = bb_miiphy_getbus(miidev->name);
 	if (bus == NULL) {
 		/* Bus not found! */
 		return -1;
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 2fa2016..79c1db2 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -566,7 +566,17 @@
 	eth_register(dev);
 
 	bb_miiphy_buses[0].priv = eth;
-	miiphy_register(dev->name, bb_miiphy_read, bb_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = bb_miiphy_read;
+	mdiodev->write = bb_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 
 	if (!eth_getenv_enetaddr("ethaddr", dev->enetaddr))
 		puts("Please set MAC address\n");
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index c85a178..feae8c0 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -219,20 +219,27 @@
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 /* wrapper for smc911x_eth_phy_read */
-static int smc911x_miiphy_read(const char *devname, u8 phy, u8 reg, u16 *val)
+static int smc911x_miiphy_read(struct mii_dev *bus, int phy, int devad,
+			       int reg)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
-	if (dev)
-		return smc911x_eth_phy_read(dev, phy, reg, val);
-	return -1;
+	u16 val = 0;
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
+	if (dev) {
+		int retval = smc911x_eth_phy_read(dev, phy, reg, &val);
+		if (retval < 0)
+			return retval;
+		return val;
+	}
+	return -ENODEV;
 }
 /* wrapper for smc911x_eth_phy_write */
-static int smc911x_miiphy_write(const char *devname, u8 phy, u8 reg, u16 val)
+static int smc911x_miiphy_write(struct mii_dev *bus, int phy, int devad,
+				int reg, u16 val)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	if (dev)
 		return smc911x_eth_phy_write(dev, phy, reg, val);
-	return -1;
+	return -ENODEV;
 }
 #endif
 
@@ -276,7 +283,17 @@
 	eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name, smc911x_miiphy_read, smc911x_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = smc911x_miiphy_read;
+	mdiodev->write = smc911x_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 
 	return 1;
diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
new file mode 100644
index 0000000..4c149e1
--- /dev/null
+++ b/drivers/net/sun8i_emac.c
@@ -0,0 +1,785 @@
+/*
+ * (C) Copyright 2016
+ * Author: Amit Singh Tomar, amittomer25@gmail.com
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * Ethernet driver for H3/A64/A83T based SoC's
+ *
+ * It is derived from the work done by
+ * LABBE Corentin & Chen-Yu Tsai for Linux, THANKS!
+ *
+*/
+
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gpio.h>
+#include <common.h>
+#include <dm.h>
+#include <fdt_support.h>
+#include <linux/err.h>
+#include <malloc.h>
+#include <miiphy.h>
+#include <net.h>
+
+#define MDIO_CMD_MII_BUSY		BIT(0)
+#define MDIO_CMD_MII_WRITE		BIT(1)
+
+#define MDIO_CMD_MII_PHY_REG_ADDR_MASK	0x000001f0
+#define MDIO_CMD_MII_PHY_REG_ADDR_SHIFT	4
+#define MDIO_CMD_MII_PHY_ADDR_MASK	0x0001f000
+#define MDIO_CMD_MII_PHY_ADDR_SHIFT	12
+
+#define CONFIG_TX_DESCR_NUM	32
+#define CONFIG_RX_DESCR_NUM	32
+#define CONFIG_ETH_BUFSIZE	2048 /* Note must be dma aligned */
+
+/*
+ * The datasheet says that each descriptor can transfers up to 4096 bytes
+ * But later, the register documentation reduces that value to 2048,
+ * using 2048 cause strange behaviours and even BSP driver use 2047
+ */
+#define CONFIG_ETH_RXSIZE	2044 /* Note must fit in ETH_BUFSIZE */
+
+#define TX_TOTAL_BUFSIZE	(CONFIG_ETH_BUFSIZE * CONFIG_TX_DESCR_NUM)
+#define RX_TOTAL_BUFSIZE	(CONFIG_ETH_BUFSIZE * CONFIG_RX_DESCR_NUM)
+
+#define H3_EPHY_DEFAULT_VALUE	0x58000
+#define H3_EPHY_DEFAULT_MASK	GENMASK(31, 15)
+#define H3_EPHY_ADDR_SHIFT	20
+#define REG_PHY_ADDR_MASK	GENMASK(4, 0)
+#define H3_EPHY_LED_POL		BIT(17)	/* 1: active low, 0: active high */
+#define H3_EPHY_SHUTDOWN	BIT(16)	/* 1: shutdown, 0: power up */
+#define H3_EPHY_SELECT		BIT(15) /* 1: internal PHY, 0: external PHY */
+
+#define SC_RMII_EN		BIT(13)
+#define SC_EPIT			BIT(2) /* 1: RGMII, 0: MII */
+#define SC_ETCS_MASK		GENMASK(1, 0)
+#define SC_ETCS_EXT_GMII	0x1
+#define SC_ETCS_INT_GMII	0x2
+
+#define CONFIG_MDIO_TIMEOUT	(3 * CONFIG_SYS_HZ)
+
+#define AHB_GATE_OFFSET_EPHY	0
+
+#if defined(CONFIG_MACH_SUN8I_H3)
+#define SUN8I_GPD8_GMAC		2
+#else
+#define SUN8I_GPD8_GMAC		4
+#endif
+
+/* H3/A64 EMAC Register's offset */
+#define EMAC_CTL0		0x00
+#define EMAC_CTL1		0x04
+#define EMAC_INT_STA		0x08
+#define EMAC_INT_EN		0x0c
+#define EMAC_TX_CTL0		0x10
+#define EMAC_TX_CTL1		0x14
+#define EMAC_TX_FLOW_CTL	0x1c
+#define EMAC_TX_DMA_DESC	0x20
+#define EMAC_RX_CTL0		0x24
+#define EMAC_RX_CTL1		0x28
+#define EMAC_RX_DMA_DESC	0x34
+#define EMAC_MII_CMD		0x48
+#define EMAC_MII_DATA		0x4c
+#define EMAC_ADDR0_HIGH		0x50
+#define EMAC_ADDR0_LOW		0x54
+#define EMAC_TX_DMA_STA		0xb0
+#define EMAC_TX_CUR_DESC	0xb4
+#define EMAC_TX_CUR_BUF		0xb8
+#define EMAC_RX_DMA_STA		0xc0
+#define EMAC_RX_CUR_DESC	0xc4
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum emac_variant {
+	A83T_EMAC = 1,
+	H3_EMAC,
+	A64_EMAC,
+};
+
+struct emac_dma_desc {
+	u32 status;
+	u32 st;
+	u32 buf_addr;
+	u32 next;
+} __aligned(ARCH_DMA_MINALIGN);
+
+struct emac_eth_dev {
+	struct emac_dma_desc rx_chain[CONFIG_TX_DESCR_NUM];
+	struct emac_dma_desc tx_chain[CONFIG_RX_DESCR_NUM];
+	char rxbuffer[RX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
+	char txbuffer[TX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
+
+	u32 interface;
+	u32 phyaddr;
+	u32 link;
+	u32 speed;
+	u32 duplex;
+	u32 phy_configured;
+	u32 tx_currdescnum;
+	u32 rx_currdescnum;
+	u32 addr;
+	u32 tx_slot;
+	bool use_internal_phy;
+
+	enum emac_variant variant;
+	void *mac_reg;
+	phys_addr_t sysctl_reg;
+	struct phy_device *phydev;
+	struct mii_dev *bus;
+};
+
+static int sun8i_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
+{
+	struct emac_eth_dev *priv = bus->priv;
+	ulong start;
+	u32 miiaddr = 0;
+	int timeout = CONFIG_MDIO_TIMEOUT;
+
+	miiaddr &= ~MDIO_CMD_MII_WRITE;
+	miiaddr &= ~MDIO_CMD_MII_PHY_REG_ADDR_MASK;
+	miiaddr |= (reg << MDIO_CMD_MII_PHY_REG_ADDR_SHIFT) &
+		MDIO_CMD_MII_PHY_REG_ADDR_MASK;
+
+	miiaddr &= ~MDIO_CMD_MII_PHY_ADDR_MASK;
+
+	miiaddr |= (addr << MDIO_CMD_MII_PHY_ADDR_SHIFT) &
+		MDIO_CMD_MII_PHY_ADDR_MASK;
+
+	miiaddr |= MDIO_CMD_MII_BUSY;
+
+	writel(miiaddr, priv->mac_reg + EMAC_MII_CMD);
+
+	start = get_timer(0);
+	while (get_timer(start) < timeout) {
+		if (!(readl(priv->mac_reg + EMAC_MII_CMD) & MDIO_CMD_MII_BUSY))
+			return readl(priv->mac_reg + EMAC_MII_DATA);
+		udelay(10);
+	};
+
+	return -1;
+}
+
+static int sun8i_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
+			    u16 val)
+{
+	struct emac_eth_dev *priv = bus->priv;
+	ulong start;
+	u32 miiaddr = 0;
+	int ret = -1, timeout = CONFIG_MDIO_TIMEOUT;
+
+	miiaddr &= ~MDIO_CMD_MII_PHY_REG_ADDR_MASK;
+	miiaddr |= (reg << MDIO_CMD_MII_PHY_REG_ADDR_SHIFT) &
+		MDIO_CMD_MII_PHY_REG_ADDR_MASK;
+
+	miiaddr &= ~MDIO_CMD_MII_PHY_ADDR_MASK;
+	miiaddr |= (addr << MDIO_CMD_MII_PHY_ADDR_SHIFT) &
+		MDIO_CMD_MII_PHY_ADDR_MASK;
+
+	miiaddr |= MDIO_CMD_MII_WRITE;
+	miiaddr |= MDIO_CMD_MII_BUSY;
+
+	writel(miiaddr, priv->mac_reg + EMAC_MII_CMD);
+	writel(val, priv->mac_reg + EMAC_MII_DATA);
+
+	start = get_timer(0);
+	while (get_timer(start) < timeout) {
+		if (!(readl(priv->mac_reg + EMAC_MII_CMD) &
+					MDIO_CMD_MII_BUSY)) {
+			ret = 0;
+			break;
+		}
+		udelay(10);
+	};
+
+	return ret;
+}
+
+static int _sun8i_write_hwaddr(struct emac_eth_dev *priv, u8 *mac_id)
+{
+	u32 macid_lo, macid_hi;
+
+	macid_lo = mac_id[0] + (mac_id[1] << 8) + (mac_id[2] << 16) +
+		(mac_id[3] << 24);
+	macid_hi = mac_id[4] + (mac_id[5] << 8);
+
+	writel(macid_hi, priv->mac_reg + EMAC_ADDR0_HIGH);
+	writel(macid_lo, priv->mac_reg + EMAC_ADDR0_LOW);
+
+	return 0;
+}
+
+static void sun8i_adjust_link(struct emac_eth_dev *priv,
+			      struct phy_device *phydev)
+{
+	u32 v;
+
+	v = readl(priv->mac_reg + EMAC_CTL0);
+
+	if (phydev->duplex)
+		v |= BIT(0);
+	else
+		v &= ~BIT(0);
+
+	v &= ~0x0C;
+
+	switch (phydev->speed) {
+	case 1000:
+		break;
+	case 100:
+		v |= BIT(2);
+		v |= BIT(3);
+		break;
+	case 10:
+		v |= BIT(3);
+		break;
+	}
+	writel(v, priv->mac_reg + EMAC_CTL0);
+}
+
+static int sun8i_emac_set_syscon_ephy(struct emac_eth_dev *priv, u32 *reg)
+{
+	if (priv->use_internal_phy) {
+		/* H3 based SoC's that has an Internal 100MBit PHY
+		 * needs to be configured and powered up before use
+		*/
+		*reg &= ~H3_EPHY_DEFAULT_MASK;
+		*reg |=  H3_EPHY_DEFAULT_VALUE;
+		*reg |= priv->phyaddr << H3_EPHY_ADDR_SHIFT;
+		*reg &= ~H3_EPHY_SHUTDOWN;
+		*reg |= H3_EPHY_SELECT;
+	} else
+		/* This is to select External Gigabit PHY on
+		 * the boards with H3 SoC.
+		*/
+		*reg &= ~H3_EPHY_SELECT;
+
+	return 0;
+}
+
+static int sun8i_emac_set_syscon(struct emac_eth_dev *priv)
+{
+	int ret;
+	u32 reg;
+
+	reg = readl(priv->sysctl_reg);
+
+	if (priv->variant == H3_EMAC) {
+		ret = sun8i_emac_set_syscon_ephy(priv, &reg);
+		if (ret)
+			return ret;
+	}
+
+	reg &= ~(SC_ETCS_MASK | SC_EPIT);
+	if (priv->variant == H3_EMAC || priv->variant == A64_EMAC)
+		reg &= ~SC_RMII_EN;
+
+	switch (priv->interface) {
+	case PHY_INTERFACE_MODE_MII:
+		/* default */
+		break;
+	case PHY_INTERFACE_MODE_RGMII:
+		reg |= SC_EPIT | SC_ETCS_INT_GMII;
+		break;
+	case PHY_INTERFACE_MODE_RMII:
+		if (priv->variant == H3_EMAC ||
+		    priv->variant == A64_EMAC) {
+			reg |= SC_RMII_EN | SC_ETCS_EXT_GMII;
+		break;
+		}
+		/* RMII not supported on A83T */
+	default:
+		debug("%s: Invalid PHY interface\n", __func__);
+		return -EINVAL;
+	}
+
+	writel(reg, priv->sysctl_reg);
+
+	return 0;
+}
+
+static int sun8i_phy_init(struct emac_eth_dev *priv, void *dev)
+{
+	struct phy_device *phydev;
+
+	phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface);
+	if (!phydev)
+		return -ENODEV;
+
+	phy_connect_dev(phydev, dev);
+
+	priv->phydev = phydev;
+	phy_config(priv->phydev);
+
+	return 0;
+}
+
+static void rx_descs_init(struct emac_eth_dev *priv)
+{
+	struct emac_dma_desc *desc_table_p = &priv->rx_chain[0];
+	char *rxbuffs = &priv->rxbuffer[0];
+	struct emac_dma_desc *desc_p;
+	u32 idx;
+
+	/* flush Rx buffers */
+	flush_dcache_range((uintptr_t)rxbuffs, (ulong)rxbuffs +
+			RX_TOTAL_BUFSIZE);
+
+	for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) {
+		desc_p = &desc_table_p[idx];
+		desc_p->buf_addr = (uintptr_t)&rxbuffs[idx * CONFIG_ETH_BUFSIZE]
+			;
+		desc_p->next = (uintptr_t)&desc_table_p[idx + 1];
+		desc_p->st |= CONFIG_ETH_RXSIZE;
+		desc_p->status = BIT(31);
+	}
+
+	/* Correcting the last pointer of the chain */
+	desc_p->next = (uintptr_t)&desc_table_p[0];
+
+	flush_dcache_range((uintptr_t)priv->rx_chain,
+			   (uintptr_t)priv->rx_chain +
+			sizeof(priv->rx_chain));
+
+	writel((uintptr_t)&desc_table_p[0], (priv->mac_reg + EMAC_RX_DMA_DESC));
+	priv->rx_currdescnum = 0;
+}
+
+static void tx_descs_init(struct emac_eth_dev *priv)
+{
+	struct emac_dma_desc *desc_table_p = &priv->tx_chain[0];
+	char *txbuffs = &priv->txbuffer[0];
+	struct emac_dma_desc *desc_p;
+	u32 idx;
+
+	for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) {
+		desc_p = &desc_table_p[idx];
+		desc_p->buf_addr = (uintptr_t)&txbuffs[idx * CONFIG_ETH_BUFSIZE]
+			;
+		desc_p->next = (uintptr_t)&desc_table_p[idx + 1];
+		desc_p->status = (1 << 31);
+		desc_p->st = 0;
+	}
+
+	/* Correcting the last pointer of the chain */
+	desc_p->next =  (uintptr_t)&desc_table_p[0];
+
+	/* Flush all Tx buffer descriptors */
+	flush_dcache_range((uintptr_t)priv->tx_chain,
+			   (uintptr_t)priv->tx_chain +
+			sizeof(priv->tx_chain));
+
+	writel((uintptr_t)&desc_table_p[0], priv->mac_reg + EMAC_TX_DMA_DESC);
+	priv->tx_currdescnum = 0;
+}
+
+static int _sun8i_emac_eth_init(struct emac_eth_dev *priv, u8 *enetaddr)
+{
+	u32 reg, v;
+	int timeout = 100;
+
+	reg = readl((priv->mac_reg + EMAC_CTL1));
+
+	if (!(reg & 0x1)) {
+		/* Soft reset MAC */
+		setbits_le32((priv->mac_reg + EMAC_CTL1), 0x1);
+		do {
+			reg = readl(priv->mac_reg + EMAC_CTL1);
+		} while ((reg & 0x01) != 0 &&  (--timeout));
+		if (!timeout) {
+			printf("%s: Timeout\n", __func__);
+			return -1;
+		}
+	}
+
+	/* Rewrite mac address after reset */
+	_sun8i_write_hwaddr(priv, enetaddr);
+
+	v = readl(priv->mac_reg + EMAC_TX_CTL1);
+	/* TX_MD Transmission starts after a full frame located in TX DMA FIFO*/
+	v |= BIT(1);
+	writel(v, priv->mac_reg + EMAC_TX_CTL1);
+
+	v = readl(priv->mac_reg + EMAC_RX_CTL1);
+	/* RX_MD RX DMA reads data from RX DMA FIFO to host memory after a
+	 * complete frame has been written to RX DMA FIFO
+	 */
+	v |= BIT(1);
+	writel(v, priv->mac_reg + EMAC_RX_CTL1);
+
+	/* DMA */
+	writel(8 << 24, priv->mac_reg + EMAC_CTL1);
+
+	/* Initialize rx/tx descriptors */
+	rx_descs_init(priv);
+	tx_descs_init(priv);
+
+	/* PHY Start Up */
+	genphy_parse_link(priv->phydev);
+
+	sun8i_adjust_link(priv, priv->phydev);
+
+	/* Start RX DMA */
+	v = readl(priv->mac_reg + EMAC_RX_CTL1);
+	v |= BIT(30);
+	writel(v, priv->mac_reg + EMAC_RX_CTL1);
+	/* Start TX DMA */
+	v = readl(priv->mac_reg + EMAC_TX_CTL1);
+	v |= BIT(30);
+	writel(v, priv->mac_reg + EMAC_TX_CTL1);
+
+	/* Enable RX/TX */
+	setbits_le32(priv->mac_reg + EMAC_RX_CTL0, BIT(31));
+	setbits_le32(priv->mac_reg + EMAC_TX_CTL0, BIT(31));
+
+	return 0;
+}
+
+static int parse_phy_pins(struct udevice *dev)
+{
+	int offset;
+	const char *pin_name;
+	int drive, pull, i;
+
+	offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset,
+				       "pinctrl-0");
+	if (offset < 0) {
+		printf("WARNING: emac: cannot find pinctrl-0 node\n");
+		return offset;
+	}
+
+	drive = fdt_getprop_u32_default_node(gd->fdt_blob, offset, 0,
+					     "allwinner,drive", 4);
+	pull = fdt_getprop_u32_default_node(gd->fdt_blob, offset, 0,
+					    "allwinner,pull", 0);
+	for (i = 0; ; i++) {
+		int pin;
+
+		if (fdt_get_string_index(gd->fdt_blob, offset,
+					 "allwinner,pins", i, &pin_name))
+			break;
+		if (pin_name[0] != 'P')
+			continue;
+		pin = (pin_name[1] - 'A') << 5;
+		if (pin >= 26 << 5)
+			continue;
+		pin += simple_strtol(&pin_name[2], NULL, 10);
+
+		sunxi_gpio_set_cfgpin(pin, SUN8I_GPD8_GMAC);
+		sunxi_gpio_set_drv(pin, drive);
+		sunxi_gpio_set_pull(pin, pull);
+	}
+
+	if (!i) {
+		printf("WARNING: emac: cannot find allwinner,pins property\n");
+		return -2;
+	}
+
+	return 0;
+}
+
+static int _sun8i_eth_recv(struct emac_eth_dev *priv, uchar **packetp)
+{
+	u32 status, desc_num = priv->rx_currdescnum;
+	struct emac_dma_desc *desc_p = &priv->rx_chain[desc_num];
+	int length = -EAGAIN;
+	int good_packet = 1;
+	uintptr_t desc_start = (uintptr_t)desc_p;
+	uintptr_t desc_end = desc_start +
+		roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
+
+	ulong data_start = (uintptr_t)desc_p->buf_addr;
+	ulong data_end;
+
+	/* Invalidate entire buffer descriptor */
+	invalidate_dcache_range(desc_start, desc_end);
+
+	status = desc_p->status;
+
+	/* Check for DMA own bit */
+	if (!(status & BIT(31))) {
+		length = (desc_p->status >> 16) & 0x3FFF;
+
+		if (length < 0x40) {
+			good_packet = 0;
+			debug("RX: Bad Packet (runt)\n");
+		}
+
+		data_end = data_start + length;
+		/* Invalidate received data */
+		invalidate_dcache_range(rounddown(data_start,
+						  ARCH_DMA_MINALIGN),
+					roundup(data_end,
+						ARCH_DMA_MINALIGN));
+		if (good_packet) {
+			if (length > CONFIG_ETH_RXSIZE) {
+				printf("Received packet is too big (len=%d)\n",
+				       length);
+				return -EMSGSIZE;
+			}
+			*packetp = (uchar *)(ulong)desc_p->buf_addr;
+			return length;
+		}
+	}
+
+	return length;
+}
+
+static int _sun8i_emac_eth_send(struct emac_eth_dev *priv, void *packet,
+				int len)
+{
+	u32 v, desc_num = priv->tx_currdescnum;
+	struct emac_dma_desc *desc_p = &priv->tx_chain[desc_num];
+	uintptr_t desc_start = (uintptr_t)desc_p;
+	uintptr_t desc_end = desc_start +
+		roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
+
+	uintptr_t data_start = (uintptr_t)desc_p->buf_addr;
+	uintptr_t data_end = data_start +
+		roundup(len, ARCH_DMA_MINALIGN);
+
+	/* Invalidate entire buffer descriptor */
+	invalidate_dcache_range(desc_start, desc_end);
+
+	desc_p->st = len;
+	/* Mandatory undocumented bit */
+	desc_p->st |= BIT(24);
+
+	memcpy((void *)data_start, packet, len);
+
+	/* Flush data to be sent */
+	flush_dcache_range(data_start, data_end);
+
+	/* frame end */
+	desc_p->st |= BIT(30);
+	desc_p->st |= BIT(31);
+
+	/*frame begin */
+	desc_p->st |= BIT(29);
+	desc_p->status = BIT(31);
+
+	/*Descriptors st and status field has changed, so FLUSH it */
+	flush_dcache_range(desc_start, desc_end);
+
+	/* Move to next Descriptor and wrap around */
+	if (++desc_num >= CONFIG_TX_DESCR_NUM)
+		desc_num = 0;
+	priv->tx_currdescnum = desc_num;
+
+	/* Start the DMA */
+	v = readl(priv->mac_reg + EMAC_TX_CTL1);
+	v |= BIT(31);/* mandatory */
+	v |= BIT(30);/* mandatory */
+	writel(v, priv->mac_reg + EMAC_TX_CTL1);
+
+	return 0;
+}
+
+static int sun8i_eth_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct emac_eth_dev *priv = dev_get_priv(dev);
+
+	return _sun8i_write_hwaddr(priv, pdata->enetaddr);
+}
+
+static void sun8i_emac_board_setup(struct emac_eth_dev *priv)
+{
+	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+	if (priv->use_internal_phy) {
+		/* Set clock gating for ephy */
+		setbits_le32(&ccm->bus_gate4, BIT(AHB_GATE_OFFSET_EPHY));
+
+		/* Deassert EPHY */
+		setbits_le32(&ccm->ahb_reset2_cfg, BIT(AHB_RESET_OFFSET_EPHY));
+	}
+
+	/* Set clock gating for emac */
+	setbits_le32(&ccm->ahb_gate0, BIT(AHB_GATE_OFFSET_GMAC));
+
+	/* De-assert EMAC */
+	setbits_le32(&ccm->ahb_reset0_cfg, BIT(AHB_RESET_OFFSET_GMAC));
+}
+
+static int sun8i_mdio_init(const char *name, struct  emac_eth_dev *priv)
+{
+	struct mii_dev *bus = mdio_alloc();
+
+	if (!bus) {
+		debug("Failed to allocate MDIO bus\n");
+		return -ENOMEM;
+	}
+
+	bus->read = sun8i_mdio_read;
+	bus->write = sun8i_mdio_write;
+	snprintf(bus->name, sizeof(bus->name), name);
+	bus->priv = (void *)priv;
+
+	return  mdio_register(bus);
+}
+
+static int sun8i_emac_eth_start(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	return _sun8i_emac_eth_init(dev->priv, pdata->enetaddr);
+}
+
+static int sun8i_emac_eth_send(struct udevice *dev, void *packet, int length)
+{
+	struct emac_eth_dev *priv = dev_get_priv(dev);
+
+	return _sun8i_emac_eth_send(priv, packet, length);
+}
+
+static int sun8i_emac_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct emac_eth_dev *priv = dev_get_priv(dev);
+
+	return _sun8i_eth_recv(priv, packetp);
+}
+
+static int _sun8i_free_pkt(struct emac_eth_dev *priv)
+{
+	u32 desc_num = priv->rx_currdescnum;
+	struct emac_dma_desc *desc_p = &priv->rx_chain[desc_num];
+	uintptr_t desc_start = (uintptr_t)desc_p;
+	uintptr_t desc_end = desc_start +
+		roundup(sizeof(u32), ARCH_DMA_MINALIGN);
+
+	/* Make the current descriptor valid again */
+	desc_p->status |= BIT(31);
+
+	/* Flush Status field of descriptor */
+	flush_dcache_range(desc_start, desc_end);
+
+	/* Move to next desc and wrap-around condition. */
+	if (++desc_num >= CONFIG_RX_DESCR_NUM)
+		desc_num = 0;
+	priv->rx_currdescnum = desc_num;
+
+	return 0;
+}
+
+static int sun8i_eth_free_pkt(struct udevice *dev, uchar *packet,
+			      int length)
+{
+	struct emac_eth_dev *priv = dev_get_priv(dev);
+
+	return _sun8i_free_pkt(priv);
+}
+
+static void sun8i_emac_eth_stop(struct udevice *dev)
+{
+	struct emac_eth_dev *priv = dev_get_priv(dev);
+
+	/* Stop Rx/Tx transmitter */
+	clrbits_le32(priv->mac_reg + EMAC_RX_CTL0, BIT(31));
+	clrbits_le32(priv->mac_reg + EMAC_TX_CTL0, BIT(31));
+
+	/* Stop TX DMA */
+	clrbits_le32(priv->mac_reg + EMAC_TX_CTL1, BIT(30));
+
+	phy_shutdown(priv->phydev);
+}
+
+static int sun8i_emac_eth_probe(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct emac_eth_dev *priv = dev_get_priv(dev);
+
+	priv->mac_reg = (void *)pdata->iobase;
+
+	sun8i_emac_board_setup(priv);
+	sun8i_emac_set_syscon(priv);
+
+	sun8i_mdio_init(dev->name, priv);
+	priv->bus = miiphy_get_dev_by_name(dev->name);
+
+	return sun8i_phy_init(priv, dev);
+}
+
+static const struct eth_ops sun8i_emac_eth_ops = {
+	.start                  = sun8i_emac_eth_start,
+	.write_hwaddr           = sun8i_eth_write_hwaddr,
+	.send                   = sun8i_emac_eth_send,
+	.recv                   = sun8i_emac_eth_recv,
+	.free_pkt               = sun8i_eth_free_pkt,
+	.stop                   = sun8i_emac_eth_stop,
+};
+
+static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct emac_eth_dev *priv = dev_get_priv(dev);
+	const char *phy_mode;
+	int offset = 0;
+
+	pdata->iobase = dev_get_addr_name(dev, "emac");
+	priv->sysctl_reg = dev_get_addr_name(dev, "syscon");
+
+	pdata->phy_interface = -1;
+	priv->phyaddr = -1;
+	priv->use_internal_phy = false;
+
+	offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset,
+				       "phy");
+	if (offset > 0)
+		priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg",
+					       -1);
+
+	phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL);
+
+	if (phy_mode)
+		pdata->phy_interface = phy_get_interface_by_name(phy_mode);
+	printf("phy interface%d\n", pdata->phy_interface);
+
+	if (pdata->phy_interface == -1) {
+		debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
+		return -EINVAL;
+	}
+
+	priv->variant = dev_get_driver_data(dev);
+
+	if (!priv->variant) {
+		printf("%s: Missing variant '%s'\n", __func__,
+		       (char *)priv->variant);
+		return -EINVAL;
+	}
+
+	if (priv->variant == H3_EMAC) {
+		if (fdt_getprop(gd->fdt_blob, dev->of_offset,
+				"allwinner,use-internal-phy", NULL))
+			priv->use_internal_phy = true;
+	}
+
+	priv->interface = pdata->phy_interface;
+
+	if (!priv->use_internal_phy)
+		parse_phy_pins(dev);
+
+	return 0;
+}
+
+static const struct udevice_id sun8i_emac_eth_ids[] = {
+	{.compatible = "allwinner,sun8i-h3-emac", .data = (uintptr_t)H3_EMAC },
+	{.compatible = "allwinner,sun50i-a64-emac",
+		.data = (uintptr_t)A64_EMAC },
+	{.compatible = "allwinner,sun8i-a83t-emac",
+		.data = (uintptr_t)A83T_EMAC },
+	{ }
+};
+
+U_BOOT_DRIVER(eth_sun8i_emac) = {
+	.name   = "eth_sun8i_emac",
+	.id     = UCLASS_ETH,
+	.of_match = sun8i_emac_eth_ids,
+	.ofdata_to_platdata = sun8i_emac_eth_ofdata_to_platdata,
+	.probe  = sun8i_emac_eth_probe,
+	.ops    = &sun8i_emac_eth_ops,
+	.priv_auto_alloc_size = sizeof(struct emac_eth_dev),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+	.flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
diff --git a/drivers/pch/pch-uclass.c b/drivers/pch/pch-uclass.c
index 7216660..af794eb 100644
--- a/drivers/pch/pch-uclass.c
+++ b/drivers/pch/pch-uclass.c
@@ -8,7 +8,6 @@
 #include <common.h>
 #include <dm.h>
 #include <pch.h>
-#include <dm/root.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -55,20 +54,8 @@
 	return ops->get_io_base(dev, iobasep);
 }
 
-static int pch_uclass_post_bind(struct udevice *bus)
-{
-	/*
-	 * Scan the device tree for devices
-	 *
-	 * Before relocation, only bind devices marked for pre-relocation
-	 * use.
-	 */
-	return dm_scan_fdt_node(bus, gd->fdt_blob, bus->of_offset,
-				gd->flags & GD_FLG_RELOC ? false : true);
-}
-
 UCLASS_DRIVER(pch) = {
 	.id		= UCLASS_PCH,
 	.name		= "pch",
-	.post_bind	= pch_uclass_post_bind,
+	.post_bind	= dm_scan_fdt_dev,
 };
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 26aa2b0..669e37b 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -31,6 +31,7 @@
 config PCI_TEGRA
 	bool "Tegra PCI support"
 	depends on TEGRA
+	depends on (TEGRA186 && POWER_DOMAIN) || (!TEGRA186)
 	help
 	  Enable support for the PCIe controller found on some generations of
 	  Tegra. Tegra20 has 2 root ports with a total of 4 lanes, Tegra30 has
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 32590ce..342b78c 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -13,7 +13,6 @@
 #include <pci.h>
 #include <asm/io.h>
 #include <dm/lists.h>
-#include <dm/root.h>
 #include <dm/device-internal.h>
 #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
 #include <asm/fsp/fsp_support.h>
@@ -753,27 +752,6 @@
 	return ret;
 }
 
-static int pci_uclass_post_bind(struct udevice *bus)
-{
-	/*
-	 * If there is no pci device listed in the device tree,
-	 * don't bother scanning the device tree.
-	 */
-	if (bus->of_offset == -1)
-		return 0;
-
-	/*
-	 * Scan the device tree for devices. This does not probe the PCI bus,
-	 * as this is not permitted while binding. It just finds devices
-	 * mentioned in the device tree.
-	 *
-	 * Before relocation, only bind devices marked for pre-relocation
-	 * use.
-	 */
-	return dm_scan_fdt_node(bus, gd->fdt_blob, bus->of_offset,
-				gd->flags & GD_FLG_RELOC ? false : true);
-}
-
 static int decode_regions(struct pci_controller *hose, const void *blob,
 			  int parent_node, int node)
 {
@@ -1254,7 +1232,7 @@
 	.id		= UCLASS_PCI,
 	.name		= "pci",
 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
-	.post_bind	= pci_uclass_post_bind,
+	.post_bind	= dm_scan_fdt_dev,
 	.pre_probe	= pci_uclass_pre_probe,
 	.post_probe	= pci_uclass_post_probe,
 	.child_post_bind = pci_uclass_child_post_bind,
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 4b73a0f..6b36c18 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -458,6 +458,10 @@
 {
 	hose_head = NULL;
 
+	/* allow env to disable pci init/enum */
+	if (getenv("pcidisable") != NULL)
+		return;
+
 	/* now call board specific pci_init()... */
 	pci_init_board();
 }
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
index 9eb605b..399055b 100644
--- a/drivers/pci/pci_rom.c
+++ b/drivers/pci/pci_rom.c
@@ -39,14 +39,9 @@
 	return true;
 }
 
-static bool should_load_oprom(struct udevice *dev)
+__weak bool board_should_load_oprom(struct udevice *dev)
 {
-	if (IS_ENABLED(CONFIG_ALWAYS_LOAD_OPROM))
-		return 1;
-	if (board_should_run_oprom(dev))
-		return 1;
-
-	return 0;
+	return true;
 }
 
 __weak uint32_t board_map_oprom_vendev(uint32_t vendev)
@@ -278,7 +273,7 @@
 		return -ENODEV;
 	}
 
-	if (!should_load_oprom(dev))
+	if (!board_should_load_oprom(dev))
 		return -ENXIO;
 
 	ret = pci_rom_probe(dev, &rom);
diff --git a/drivers/pci/pci_sandbox.c b/drivers/pci/pci_sandbox.c
index 6de5130..6a84ee3 100644
--- a/drivers/pci/pci_sandbox.c
+++ b/drivers/pci/pci_sandbox.c
@@ -10,7 +10,6 @@
 #include <fdtdec.h>
 #include <inttypes.h>
 #include <pci.h>
-#include <dm/root.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -52,12 +51,6 @@
 	return ops->read_config(emul, offset, valuep, size);
 }
 
-static int sandbox_pci_child_post_bind(struct udevice *dev)
-{
-	/* Attach an emulator if we can */
-	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
-}
-
 static const struct dm_pci_ops sandbox_pci_ops = {
 	.read_config = sandbox_pci_read_config,
 	.write_config = sandbox_pci_write_config,
@@ -73,7 +66,9 @@
 	.id	= UCLASS_PCI,
 	.of_match = sandbox_pci_ids,
 	.ops	= &sandbox_pci_ops,
-	.child_post_bind = sandbox_pci_child_post_bind,
+
+	/* Attach an emulator if we can */
+	.child_post_bind = dm_scan_fdt_dev,
 	.per_child_platdata_auto_alloc_size =
 			sizeof(struct pci_child_platdata),
 };
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c
index 352cdef..ea8adb98 100644
--- a/drivers/pci/pci_tegra.c
+++ b/drivers/pci/pci_tegra.c
@@ -13,22 +13,35 @@
 #define pr_fmt(fmt) "tegra-pcie: " fmt
 
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 #include <errno.h>
 #include <fdtdec.h>
 #include <malloc.h>
 #include <pci.h>
+#include <power-domain.h>
+#include <reset.h>
 
 #include <asm/io.h>
 #include <asm/gpio.h>
 
+#include <linux/list.h>
+
+#ifndef CONFIG_TEGRA186
 #include <asm/arch/clock.h>
 #include <asm/arch/powergate.h>
 #include <asm/arch-tegra/xusb-padctl.h>
-
-#include <linux/list.h>
-
 #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
+#endif
+
+/*
+ * FIXME: TODO: This driver contains a number of ifdef CONFIG_TEGRA186 that
+ * should not be present. These are needed because newer Tegra SoCs support
+ * only the standard clock/reset APIs, whereas older Tegra SoCs support only
+ * a custom Tegra-specific API. ASAP the older Tegra SoCs' code should be
+ * fixed to implement the standard APIs, and all drivers converted to solely
+ * use the new standard APIs, with no ifdefs.
+ */
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -103,6 +116,9 @@
 #define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_222	(0x1 << 20)
 #define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1	(0x1 << 20)
 #define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_411	(0x2 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_401	(0x0 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_211	(0x1 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_111	(0x2 << 20)
 
 #define AFI_FUSE			0x104
 #define  AFI_FUSE_PCIE_T0_GEN2_DIS	(1 << 2)
@@ -110,6 +126,7 @@
 #define AFI_PEX0_CTRL			0x110
 #define AFI_PEX1_CTRL			0x118
 #define AFI_PEX2_CTRL			0x128
+#define AFI_PEX2_CTRL_T186		0x19c
 #define  AFI_PEX_CTRL_RST		(1 << 0)
 #define  AFI_PEX_CTRL_CLKREQ_EN		(1 << 1)
 #define  AFI_PEX_CTRL_REFCLK_EN		(1 << 3)
@@ -173,6 +190,7 @@
 	TEGRA30_PCIE,
 	TEGRA124_PCIE,
 	TEGRA210_PCIE,
+	TEGRA186_PCIE,
 };
 
 struct tegra_pcie_port {
@@ -189,6 +207,7 @@
 	unsigned int num_ports;
 	unsigned long pads_pll_ctl;
 	unsigned long tx_ref_sel;
+	unsigned long afi_pex2_ctrl;
 	u32 pads_refclk_cfg0;
 	u32 pads_refclk_cfg1;
 	bool has_pex_clkreq_en;
@@ -209,7 +228,17 @@
 	unsigned long xbar;
 
 	const struct tegra_pcie_soc *soc;
+
+#ifdef CONFIG_TEGRA186
+	struct clk clk_afi;
+	struct clk clk_pex;
+	struct reset_ctl reset_afi;
+	struct reset_ctl reset_pex;
+	struct reset_ctl reset_pcie_x;
+	struct power_domain pwrdom;
+#else
 	struct tegra_xusb_phy *phy;
+#endif
 };
 
 static void afi_writel(struct tegra_pcie *pcie, unsigned long value,
@@ -229,10 +258,12 @@
 	writel(value, pcie->pads.start + offset);
 }
 
+#ifndef CONFIG_TEGRA186
 static unsigned long pads_readl(struct tegra_pcie *pcie, unsigned long offset)
 {
 	return readl(pcie->pads.start + offset);
 }
+#endif
 
 static unsigned long rp_readl(struct tegra_pcie_port *port,
 			      unsigned long offset)
@@ -400,6 +431,24 @@
 			return 0;
 		}
 		break;
+	case TEGRA186_PCIE:
+		switch (lanes) {
+		case 0x0010004:
+			debug("x4 x1 configuration\n");
+			*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_401;
+			return 0;
+
+		case 0x0010102:
+			debug("x2 x1 x1 configuration\n");
+			*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_211;
+			return 0;
+
+		case 0x0010101:
+			debug("x1 x1 x1 configuration\n");
+			*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_111;
+			return 0;
+		}
+		break;
 	default:
 		break;
 	}
@@ -471,6 +520,7 @@
 		return err;
 	}
 
+#ifndef CONFIG_TEGRA186
 	pcie->phy = tegra_xusb_phy_get(TEGRA_XUSB_PADCTL_PCIE);
 	if (pcie->phy) {
 		err = tegra_xusb_phy_prepare(pcie->phy);
@@ -479,6 +529,7 @@
 			return err;
 		}
 	}
+#endif
 
 	fdt_for_each_subnode(fdt, subnode, node) {
 		unsigned int index = 0, num_lanes = 0;
@@ -523,6 +574,44 @@
 	return 0;
 }
 
+#ifdef CONFIG_TEGRA186
+static int tegra_pcie_power_on(struct tegra_pcie *pcie)
+{
+	int ret;
+
+	ret = power_domain_on(&pcie->pwrdom);
+	if (ret) {
+		error("power_domain_on() failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_enable(&pcie->clk_afi);
+	if (ret) {
+		error("clk_enable(afi) failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_enable(&pcie->clk_pex);
+	if (ret) {
+		error("clk_enable(pex) failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = reset_deassert(&pcie->reset_afi);
+	if (ret) {
+		error("reset_deassert(afi) failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = reset_deassert(&pcie->reset_pex);
+	if (ret) {
+		error("reset_deassert(pex) failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+#else
 static int tegra_pcie_power_on(struct tegra_pcie *pcie)
 {
 	const struct tegra_pcie_soc *soc = pcie->soc;
@@ -639,6 +728,7 @@
 
 	return 0;
 }
+#endif
 
 static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
 {
@@ -647,7 +737,11 @@
 	u32 value;
 	int err;
 
+#ifdef CONFIG_TEGRA186
+	{
+#else
 	if (pcie->phy) {
+#endif
 		value = afi_readl(pcie, AFI_PLLE_CONTROL);
 		value &= ~AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL;
 		value |= AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN;
@@ -675,6 +769,7 @@
 
 	afi_writel(pcie, value, AFI_FUSE);
 
+#ifndef CONFIG_TEGRA186
 	if (pcie->phy)
 		err = tegra_xusb_phy_enable(pcie->phy);
 	else
@@ -684,9 +779,18 @@
 		error("failed to power on PHY: %d\n", err);
 		return err;
 	}
+#endif
 
 	/* take the PCIEXCLK logic out of reset */
+#ifdef CONFIG_TEGRA186
+	err = reset_deassert(&pcie->reset_pcie_x);
+	if (err) {
+		error("reset_deassert(pcie_x) failed: %d\n", err);
+		return err;
+	}
+#else
 	reset_set_enable(PERIPH_ID_PCIEXCLK, 0);
+#endif
 
 	/* finally enable PCIe */
 	value = afi_readl(pcie, AFI_CONFIGURATION);
@@ -787,7 +891,7 @@
 		break;
 
 	case 2:
-		ret = AFI_PEX2_CTRL;
+		ret = port->pcie->soc->afi_pex2_ctrl;
 		break;
 	}
 
@@ -945,6 +1049,7 @@
 		.num_ports = 3,
 		.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
 		.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
+		.afi_pex2_ctrl = AFI_PEX2_CTRL,
 		.pads_refclk_cfg0 = 0xfa5cfa5c,
 		.pads_refclk_cfg1 = 0xfa5cfa5c,
 		.has_pex_clkreq_en = true,
@@ -972,7 +1077,16 @@
 		.has_cml_clk = true,
 		.has_gen2 = true,
 		.force_pca_enable = true,
-	}
+	},
+	[TEGRA186_PCIE] = {
+		.num_ports = 3,
+		.afi_pex2_ctrl = AFI_PEX2_CTRL_T186,
+		.pads_refclk_cfg0 = 0x80b880b8,
+		.pads_refclk_cfg1 = 0x000480b8,
+		.has_pex_clkreq_en = true,
+		.has_pex_bias_ctrl = true,
+		.has_gen2 = true,
+	},
 };
 
 static int pci_tegra_ofdata_to_platdata(struct udevice *dev)
@@ -996,6 +1110,44 @@
 	struct tegra_pcie *pcie = dev_get_priv(dev);
 	int err;
 
+#ifdef CONFIG_TEGRA186
+	err = clk_get_by_name(dev, "afi", &pcie->clk_afi);
+	if (err) {
+		debug("clk_get_by_name(afi) failed: %d\n", err);
+		return err;
+	}
+
+	err = clk_get_by_name(dev, "pex", &pcie->clk_pex);
+	if (err) {
+		debug("clk_get_by_name(pex) failed: %d\n", err);
+		return err;
+	}
+
+	err = reset_get_by_name(dev, "afi", &pcie->reset_afi);
+	if (err) {
+		debug("reset_get_by_name(afi) failed: %d\n", err);
+		return err;
+	}
+
+	err = reset_get_by_name(dev, "pex", &pcie->reset_pex);
+	if (err) {
+		debug("reset_get_by_name(pex) failed: %d\n", err);
+		return err;
+	}
+
+	err = reset_get_by_name(dev, "pcie_x", &pcie->reset_pcie_x);
+	if (err) {
+		debug("reset_get_by_name(pcie_x) failed: %d\n", err);
+		return err;
+	}
+
+	err = power_domain_get(dev, &pcie->pwrdom);
+	if (err) {
+		debug("power_domain_get() failed: %d\n", err);
+		return err;
+	}
+#endif
+
 	err = tegra_pcie_power_on(pcie);
 	if (err < 0) {
 		error("failed to power on");
@@ -1033,6 +1185,7 @@
 	{ .compatible = "nvidia,tegra30-pcie", .data = TEGRA30_PCIE },
 	{ .compatible = "nvidia,tegra124-pcie", .data = TEGRA124_PCIE },
 	{ .compatible = "nvidia,tegra210-pcie", .data = TEGRA210_PCIE },
+	{ .compatible = "nvidia,tegra186-pcie", .data = TEGRA186_PCIE },
 	{ }
 };
 
diff --git a/drivers/pci/pcie_imx.c b/drivers/pci/pcie_imx.c
index c14bb0a..732d59d 100644
--- a/drivers/pci/pcie_imx.c
+++ b/drivers/pci/pcie_imx.c
@@ -595,7 +595,7 @@
 	while (!imx6_pcie_link_up()) {
 		udelay(10);
 		count++;
-		if (count >= 2000) {
+		if (count >= 4000) {
 #ifdef CONFIG_PCI_SCAN_SHOW
 			puts("PCI:   pcie phy link never came up\n");
 #endif
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 1785e3b..44b53b9 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -123,24 +123,31 @@
 	  both the GPIO definitions and pin control functions for each
 	  available multiplex function.
 
-config ROCKCHIP_PINCTRL
-	bool "Rockchip pin control driver"
+config ROCKCHIP_RK3036_PINCTRL
+	bool "Rockchip rk3036 pin control driver"
 	depends on DM
 	help
-	  Support pin multiplexing control on Rockchip SoCs. The driver is
+	  Support pin multiplexing control on Rockchip rk3036 SoCs. The driver is
 	  controlled by a device tree node which contains both the GPIO
 	  definitions and pin control functions for each available multiplex
 	  function.
 
-config ROCKCHIP_3036_PINCTRL
-	bool "Rockchip rk3036 pin control driver"
+config ROCKCHIP_RK3288_PINCTRL
+	bool "Rockchip pin control driver"
 	depends on DM
 	help
-	  Support pin multiplexing control on Rockchip rk3036 SoCs. The driver is
-	  controlled by a device tree node which contains both the GPIO
+	  Support pin multiplexing control on Rockchip rk3288 SoCs. The driver
+	  is controlled by a device tree node which contains both the GPIO
 	  definitions and pin control functions for each available multiplex
 	  function.
 
+config PINCTRL_AT91PIO4
+	bool "AT91 PIO4 pinctrl driver"
+	depends on DM
+	help
+	  This option is to enable the AT91 pinctrl driver for AT91 PIO4
+	  controller which is available on SAMA5D2 SoC.
+
 config PINCTRL_SANDBOX
 	bool "Sandbox pinctrl driver"
 	depends on SANDBOX
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 7f94681..c92ab8c 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -5,6 +5,7 @@
 obj-y					+= pinctrl-uclass.o
 obj-$(CONFIG_$(SPL_)PINCTRL_GENERIC)	+= pinctrl-generic.o
 
+obj-$(CONFIG_PINCTRL_AT91PIO4)		+= pinctrl-at91-pio4.o
 obj-y					+= nxp/
 obj-$(CONFIG_ARCH_ATH79) += ath79/
 obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
new file mode 100644
index 0000000..6d4aadc
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -0,0 +1,182 @@
+/*
+ * Atmel PIO4 pinctrl driver
+ *
+ * Copyright (C) 2016 Atmel Corporation
+ *               Wenyou.Yang <wenyou.yang@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm/device.h>
+#include <dm/pinctrl.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <mach/atmel_pio4.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Warning:
+ * In order to not introduce confusion between Atmel PIO groups and pinctrl
+ * framework groups, Atmel PIO groups will be called banks.
+ */
+
+struct atmel_pio4_platdata {
+	struct atmel_pio4_port *reg_base;
+};
+
+static const struct pinconf_param conf_params[] = {
+	{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
+	{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
+	{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
+	{ "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
+	{ "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
+	{ "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
+	{ "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
+};
+
+static u32 atmel_pinctrl_get_pinconf(const void *blob, int node)
+{
+	const struct pinconf_param *params;
+	u32 param, arg, conf = 0;
+	u32 i;
+
+	for (i = 0; i < ARRAY_SIZE(conf_params); i++) {
+		params = &conf_params[i];
+		if (!fdt_get_property(blob, node, params->property, NULL))
+			continue;
+
+		param = params->param;
+		arg = params->default_value;
+
+		switch (param) {
+		case PIN_CONFIG_BIAS_DISABLE:
+			conf &= (~ATMEL_PIO_PUEN_MASK);
+			conf &= (~ATMEL_PIO_PDEN_MASK);
+			break;
+		case PIN_CONFIG_BIAS_PULL_UP:
+			conf |= ATMEL_PIO_PUEN_MASK;
+			break;
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			conf |= ATMEL_PIO_PDEN_MASK;
+			break;
+		case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+			if (arg == 0)
+				conf &= (~ATMEL_PIO_OPD_MASK);
+			else
+				conf |= ATMEL_PIO_OPD_MASK;
+			break;
+		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+			if (arg == 0)
+				conf |= ATMEL_PIO_SCHMITT_MASK;
+			else
+				conf &= (~ATMEL_PIO_SCHMITT_MASK);
+			break;
+		case PIN_CONFIG_INPUT_DEBOUNCE:
+			if (arg == 0) {
+				conf &= (~ATMEL_PIO_IFEN_MASK);
+				conf &= (~ATMEL_PIO_IFSCEN_MASK);
+			} else {
+				conf |= ATMEL_PIO_IFEN_MASK;
+				conf |= ATMEL_PIO_IFSCEN_MASK;
+			}
+			break;
+		default:
+			printf("%s: Unsupported configuration parameter: %u\n",
+			       __func__, param);
+			break;
+		}
+	}
+
+	return conf;
+}
+
+static inline struct atmel_pio4_port *atmel_pio4_bank_base(struct udevice *dev,
+							   u32 bank)
+{
+	struct atmel_pio4_platdata *plat = dev_get_platdata(dev);
+	struct atmel_pio4_port *bank_base =
+			(struct atmel_pio4_port *)((u32)plat->reg_base +
+			ATMEL_PIO_BANK_OFFSET * bank);
+
+	return bank_base;
+}
+
+#define MAX_PINMUX_ENTRIES	40
+
+static int atmel_pinctrl_set_state(struct udevice *dev, struct udevice *config)
+{
+	struct atmel_pio4_port *bank_base;
+	const void *blob = gd->fdt_blob;
+	int node = config->of_offset;
+	u32 offset, func, bank, line;
+	u32 cells[MAX_PINMUX_ENTRIES];
+	u32 i, conf;
+	int count;
+
+	conf = atmel_pinctrl_get_pinconf(blob, node);
+
+	count = fdtdec_get_int_array_count(blob, node, "pinmux",
+					   cells, ARRAY_SIZE(cells));
+	if (count < 0) {
+		printf("%s: bad pinmux array %d\n", __func__, count);
+		return -EINVAL;
+	}
+
+	if (count > MAX_PINMUX_ENTRIES) {
+		printf("%s: unsupported pinmux array count %d\n",
+		       __func__, count);
+		return -EINVAL;
+	}
+
+	for (i = 0 ; i < count; i++) {
+		offset = ATMEL_GET_PIN_NO(cells[i]);
+		func = ATMEL_GET_PIN_FUNC(cells[i]);
+
+		bank = ATMEL_PIO_BANK(offset);
+		line = ATMEL_PIO_LINE(offset);
+
+		bank_base = atmel_pio4_bank_base(dev, bank);
+
+		writel(BIT(line), &bank_base->mskr);
+		conf &= (~ATMEL_PIO_CFGR_FUNC_MASK);
+		conf |= (func & ATMEL_PIO_CFGR_FUNC_MASK);
+		writel(conf, &bank_base->cfgr);
+	}
+
+	return 0;
+}
+
+const struct pinctrl_ops atmel_pinctrl_ops  = {
+	.set_state = atmel_pinctrl_set_state,
+};
+
+static int atmel_pinctrl_probe(struct udevice *dev)
+{
+	struct atmel_pio4_platdata *plat = dev_get_platdata(dev);
+	fdt_addr_t addr_base;
+
+	dev = dev_get_parent(dev);
+	addr_base = dev_get_addr(dev);
+	if (addr_base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	plat->reg_base = (struct atmel_pio4_port *)addr_base;
+
+	return 0;
+}
+
+static const struct udevice_id atmel_pinctrl_match[] = {
+	{ .compatible = "atmel,sama5d2-pinctrl" },
+	{}
+};
+
+U_BOOT_DRIVER(atmel_pinctrl) = {
+	.name = "pinctrl_atmel_pio4",
+	.id = UCLASS_PINCTRL,
+	.of_match = atmel_pinctrl_match,
+	.probe = atmel_pinctrl_probe,
+	.platdata_auto_alloc_size = sizeof(struct atmel_pio4_platdata),
+	.ops = &atmel_pinctrl_ops,
+};
diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c
index fd04b26..7397de2 100644
--- a/drivers/pinctrl/pinctrl-uclass.c
+++ b/drivers/pinctrl/pinctrl-uclass.c
@@ -113,7 +113,7 @@
 }
 
 /**
- * pinconfig_post-bind() - post binding for PINCONFIG uclass
+ * pinconfig_post_bind() - post binding for PINCONFIG uclass
  * Recursively bind its children as pinconfig devices.
  *
  * @dev: pinconfig device
@@ -257,7 +257,7 @@
 }
 
 /**
- * pinconfig_post-bind() - post binding for PINCTRL uclass
+ * pinconfig_post_bind() - post binding for PINCTRL uclass
  * Recursively bind child nodes as pinconfig devices in case of full pinctrl.
  *
  * @dev: pinctrl device
diff --git a/drivers/pinctrl/pinctrl_pic32.c b/drivers/pinctrl/pinctrl_pic32.c
index 5cf97ec..9acac29 100644
--- a/drivers/pinctrl/pinctrl_pic32.c
+++ b/drivers/pinctrl/pinctrl_pic32.c
@@ -10,7 +10,6 @@
 #include <errno.h>
 #include <asm/io.h>
 #include <dm/pinctrl.h>
-#include <dm/root.h>
 #include <mach/pic32.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -341,12 +340,6 @@
 	return 0;
 }
 
-static int pic32_pinctrl_bind(struct udevice *dev)
-{
-	/* scan child GPIO banks */
-	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
-}
-
 static const struct udevice_id pic32_pinctrl_ids[] = {
 	{ .compatible = "microchip,pic32mzda-pinctrl" },
 	{ }
@@ -358,6 +351,6 @@
 	.of_match	= pic32_pinctrl_ids,
 	.ops		= &pic32_pinctrl_ops,
 	.probe		= pic32_pinctrl_probe,
-	.bind		= pic32_pinctrl_bind,
+	.bind		= dm_scan_fdt_dev,
 	.priv_auto_alloc_size = sizeof(struct pic32_pinctrl_priv),
 };
diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
index 6fa7d00..64e9587 100644
--- a/drivers/pinctrl/rockchip/Makefile
+++ b/drivers/pinctrl/rockchip/Makefile
@@ -5,5 +5,5 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-$(CONFIG_ROCKCHIP_PINCTRL) += pinctrl_rk3288.o
-obj-$(CONFIG_ROCKCHIP_3036_PINCTRL) += pinctrl_rk3036.o
+obj-$(CONFIG_ROCKCHIP_RK3036_PINCTRL) += pinctrl_rk3036.o
+obj-$(CONFIG_ROCKCHIP_RK3288_PINCTRL) += pinctrl_rk3288.o
diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3036.c b/drivers/pinctrl/rockchip/pinctrl_rk3036.c
index 1f78bf8..6aea856 100644
--- a/drivers/pinctrl/rockchip/pinctrl_rk3036.c
+++ b/drivers/pinctrl/rockchip/pinctrl_rk3036.c
@@ -15,7 +15,6 @@
 #include <asm/arch/hardware.h>
 #include <asm/arch/periph.h>
 #include <dm/pinctrl.h>
-#include <dm/root.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -253,12 +252,6 @@
 	.get_periph_id	= rk3036_pinctrl_get_periph_id,
 };
 
-static int rk3036_pinctrl_bind(struct udevice *dev)
-{
-	/* scan child GPIO banks */
-	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
-}
-
 static int rk3036_pinctrl_probe(struct udevice *dev)
 {
 	struct rk3036_pinctrl_priv *priv = dev_get_priv(dev);
@@ -279,6 +272,6 @@
 	.of_match	= rk3036_pinctrl_ids,
 	.priv_auto_alloc_size = sizeof(struct rk3036_pinctrl_priv),
 	.ops		= &rk3036_pinctrl_ops,
-	.bind		= rk3036_pinctrl_bind,
+	.bind		= dm_scan_fdt_dev,
 	.probe		= rk3036_pinctrl_probe,
 };
diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3288.c b/drivers/pinctrl/rockchip/pinctrl_rk3288.c
index 1fa1daa..0322264 100644
--- a/drivers/pinctrl/rockchip/pinctrl_rk3288.c
+++ b/drivers/pinctrl/rockchip/pinctrl_rk3288.c
@@ -17,7 +17,6 @@
 #include <asm/arch/periph.h>
 #include <asm/arch/pmu_rk3288.h>
 #include <dm/pinctrl.h>
-#include <dm/root.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -476,6 +475,7 @@
 static int rk3288_pinctrl_get_periph_id(struct udevice *dev,
 					struct udevice *periph)
 {
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	u32 cell[3];
 	int ret;
 
@@ -506,6 +506,7 @@
 	case 103:
 		return PERIPH_ID_HDMI;
 	}
+#endif
 
 	return -ENOENT;
 }
@@ -587,6 +588,7 @@
 	struct rk3288_pinctrl_priv *priv = dev_get_priv(dev);
 	uint shift, ind = index;
 	uint mask;
+	uint value;
 	u32 *addr;
 	int ret;
 
@@ -595,7 +597,18 @@
 					  &mask);
 	if (ret)
 		return ret;
-	rk_clrsetreg(addr, mask << shift, muxval << shift);
+
+	/*
+	 * PMU_GPIO0 registers cannot be selectively written so we cannot use
+	 * rk_clrsetreg() here.  However, the upper 16 bits are reserved and
+	 * are ignored when written, so we can use the same code as for the
+	 * other GPIO banks providing that we preserve the value of the other
+	 * bits.
+	 */
+	value = readl(addr);
+	value &= ~(mask << shift);
+	value |= (mask << (shift + 16)) | (muxval << shift);
+	writel(value, addr);
 
 	/* Handle pullup/pulldown */
 	if (flags) {
@@ -613,7 +626,12 @@
 			addr = &priv->grf->gpio1_p[banknum - 1][ind];
 		debug("%s: addr=%p, val=%x, shift=%x\n", __func__, addr, val,
 		      shift);
-		rk_clrsetreg(addr, 3 << shift, val << shift);
+
+		/* As above, rk_clrsetreg() cannot be used here. */
+		value = readl(addr);
+		value &= ~(mask << shift);
+		value |= (3 << (shift + 16)) | (val << shift);
+		writel(value, addr);
 	}
 
 	return 0;
@@ -662,12 +680,6 @@
 	.get_periph_id	= rk3288_pinctrl_get_periph_id,
 };
 
-static int rk3288_pinctrl_bind(struct udevice *dev)
-{
-	/* scan child GPIO banks */
-	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
-}
-
 #ifndef CONFIG_SPL_BUILD
 static int rk3288_pinctrl_parse_tables(struct rk3288_pinctrl_priv *priv,
 				       struct rockchip_pin_bank *banks,
@@ -719,11 +731,13 @@
 };
 
 U_BOOT_DRIVER(pinctrl_rk3288) = {
-	.name		= "pinctrl_rk3288",
+	.name		= "rockchip_rk3288_pinctrl",
 	.id		= UCLASS_PINCTRL,
 	.of_match	= rk3288_pinctrl_ids,
 	.priv_auto_alloc_size = sizeof(struct rk3288_pinctrl_priv),
 	.ops		= &rk3288_pinctrl_ops,
-	.bind		= rk3288_pinctrl_bind,
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	.bind		= dm_scan_fdt_dev,
+#endif
 	.probe		= rk3288_pinctrl_probe,
 };
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index 225a05c..3f891f1 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -1,11 +1,10 @@
 /*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <common.h>
-#include <mapmem.h>
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/sizes.h>
@@ -188,7 +187,7 @@
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
-	priv->base = map_sysmem(addr, SZ_4K);
+	priv->base = devm_ioremap(dev, addr, SZ_4K);
 	if (!priv->base)
 		return -ENOMEM;
 
@@ -196,12 +195,3 @@
 
 	return 0;
 }
-
-int uniphier_pinctrl_remove(struct udevice *dev)
-{
-	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
-
-	unmap_sysmem(priv->base);
-
-	return 0;
-}
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c
index e95870f..e42602b 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c
@@ -101,7 +101,6 @@
 	.id = UCLASS_PINCTRL,
 	.of_match = of_match_ptr(uniphier_ld11_pinctrl_match),
 	.probe = uniphier_ld11_pinctrl_probe,
-	.remove = uniphier_pinctrl_remove,
 	.priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
 	.ops = &uniphier_pinctrl_ops,
 };
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c
index e903196..d6ae512 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c
@@ -115,7 +115,6 @@
 	.id = UCLASS_PINCTRL,
 	.of_match = of_match_ptr(uniphier_ld20_pinctrl_match),
 	.probe = uniphier_ld20_pinctrl_probe,
-	.remove = uniphier_pinctrl_remove,
 	.priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
 	.ops = &uniphier_pinctrl_ops,
 };
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
index dbb9499..955858a 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -135,7 +136,6 @@
 	.id = UCLASS_PINCTRL,
 	.of_match = of_match_ptr(uniphier_ld4_pinctrl_match),
 	.probe = uniphier_ld4_pinctrl_probe,
-	.remove = uniphier_pinctrl_remove,
 	.priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
 	.ops = &uniphier_pinctrl_ops,
 };
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
index 8b40801..5f9407e 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -135,7 +136,6 @@
 	.id = UCLASS_PINCTRL,
 	.of_match = of_match_ptr(uniphier_ld6b_pinctrl_match),
 	.probe = uniphier_ld6b_pinctrl_probe,
-	.remove = uniphier_pinctrl_remove,
 	.priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
 	.ops = &uniphier_pinctrl_ops,
 };
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
index dace726..6f349dc 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -143,7 +144,6 @@
 	.id = UCLASS_PINCTRL,
 	.of_match = of_match_ptr(uniphier_pro4_pinctrl_match),
 	.probe = uniphier_pro4_pinctrl_probe,
-	.remove = uniphier_pinctrl_remove,
 	.priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
 	.ops = &uniphier_pinctrl_ops,
 	.flags = DM_FLAG_PRE_RELOC,
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
index 50b41cc..268cdea 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -134,7 +135,6 @@
 	.id = UCLASS_PINCTRL,
 	.of_match = of_match_ptr(uniphier_pro5_pinctrl_match),
 	.probe = uniphier_pro5_pinctrl_probe,
-	.remove = uniphier_pinctrl_remove,
 	.priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
 	.ops = &uniphier_pinctrl_ops,
 	.flags = DM_FLAG_PRE_RELOC,
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
index 9223eeb..b534274 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -147,7 +148,6 @@
 	.id = UCLASS_PINCTRL,
 	.of_match = of_match_ptr(uniphier_pxs2_pinctrl_match),
 	.probe = uniphier_pxs2_pinctrl_probe,
-	.remove = uniphier_pinctrl_remove,
 	.priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
 	.ops = &uniphier_pinctrl_ops,
 };
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
index cee0eb1..a85e055 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -143,7 +144,6 @@
 	.id = UCLASS_PINCTRL,
 	.of_match = of_match_ptr(uniphier_sld8_pinctrl_match),
 	.probe = uniphier_sld8_pinctrl_probe,
-	.remove = uniphier_pinctrl_remove,
 	.priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
 	.ops = &uniphier_pinctrl_ops,
 };
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier.h b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
index 4bb8932..4de5b03 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier.h
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -119,6 +120,4 @@
 int uniphier_pinctrl_probe(struct udevice *dev,
 			   struct uniphier_pinctrl_socdata *socdata);
 
-int uniphier_pinctrl_remove(struct udevice *dev);
-
 #endif /* __PINCTRL_UNIPHIER_H__ */
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 3c44167..f2c5629 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -1,5 +1,7 @@
 menu "Power"
 
+source "drivers/power/domain/Kconfig"
+
 source "drivers/power/pmic/Kconfig"
 
 source "drivers/power/regulator/Kconfig"
@@ -13,12 +15,12 @@
 	default SUNXI_NO_PMIC if MACH_SUN8I_H3 || MACH_SUN50I
 
 config SUNXI_NO_PMIC
-	boolean "board without a pmic"
+	bool "board without a pmic"
 	---help---
 	Select this for boards which do not use a PMIC.
 
 config AXP152_POWER
-	boolean "axp152 pmic support"
+	bool "axp152 pmic support"
 	depends on MACH_SUN5I
 	select CMD_POWEROFF
 	---help---
@@ -26,7 +28,7 @@
 	A10s boards.
 
 config AXP209_POWER
-	boolean "axp209 pmic support"
+	bool "axp209 pmic support"
 	depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
 	select CMD_POWEROFF
 	---help---
@@ -34,7 +36,7 @@
 	A10, A13 and A20 boards.
 
 config AXP221_POWER
-	boolean "axp221 / axp223 pmic support"
+	bool "axp221 / axp223 pmic support"
 	depends on MACH_SUN6I || MACH_SUN8I_A23 || MACH_SUN8I_A33
 	select CMD_POWEROFF
 	---help---
@@ -42,14 +44,14 @@
 	A23 and A31 boards.
 
 config AXP809_POWER
-	boolean "axp809 pmic support"
+	bool "axp809 pmic support"
 	depends on MACH_SUN9I
 	select CMD_POWEROFF
 	---help---
 	Say y here to enable support for the axp809 pmic found on A80 boards.
 
 config AXP818_POWER
-	boolean "axp818 pmic support"
+	bool "axp818 pmic support"
 	depends on MACH_SUN8I_A83T
 	select CMD_POWEROFF
 	---help---
@@ -57,7 +59,7 @@
 	A83T dev board.
 
 config SY8106A_POWER
-	boolean "SY8106A pmic support"
+	bool "SY8106A pmic support"
 	depends on MACH_SUN8I_H3
 	---help---
 	Select this to enable support for the SY8106A pmic found on some
diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
new file mode 100644
index 0000000..132e332
--- /dev/null
+++ b/drivers/power/domain/Kconfig
@@ -0,0 +1,27 @@
+menu "Power Domain Support"
+
+config POWER_DOMAIN
+	bool "Enable power domain support using Driver Model"
+	depends on DM && OF_CONTROL
+	help
+	  Enable support for the power domain driver class. Many SoCs allow
+	  power to be applied to or removed from portions of the SoC (power
+	  domains). This may be used to save power. This API provides the
+	  means to control such power management hardware.
+
+config SANDBOX_POWER_DOMAIN
+	bool "Enable the sandbox power domain test driver"
+	depends on POWER_DOMAIN && SANDBOX
+	help
+	  Enable support for a test power domain driver implementation, which
+	  simply accepts requests to power on/off various HW modules without
+	  actually doing anything beyond a little error checking.
+
+config TEGRA186_POWER_DOMAIN
+	bool "Enable Tegra186 BPMP-based power domain driver"
+	depends on TEGRA186_BPMP
+	help
+	  Enable support for manipulating Tegra's on-SoC power domains via IPC
+	  requests to the BPMP (Boot and Power Management Processor).
+
+endmenu
diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
new file mode 100644
index 0000000..2c3d926
--- /dev/null
+++ b/drivers/power/domain/Makefile
@@ -0,0 +1,8 @@
+# Copyright (c) 2016, NVIDIA CORPORATION.
+#
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_POWER_DOMAIN) += power-domain-uclass.o
+obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o
+obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain-test.o
+obj-$(CONFIG_TEGRA186_POWER_DOMAIN) += tegra186-power-domain.o
diff --git a/drivers/power/domain/power-domain-uclass.c b/drivers/power/domain/power-domain-uclass.c
new file mode 100644
index 0000000..1bb6262
--- /dev/null
+++ b/drivers/power/domain/power-domain-uclass.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <power-domain.h>
+#include <power-domain-uclass.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static inline struct power_domain_ops *power_domain_dev_ops(struct udevice *dev)
+{
+	return (struct power_domain_ops *)dev->driver->ops;
+}
+
+static int power_domain_of_xlate_default(struct power_domain *power_domain,
+				       struct fdtdec_phandle_args *args)
+{
+	debug("%s(power_domain=%p)\n", __func__, power_domain);
+
+	if (args->args_count != 1) {
+		debug("Invalid args_count: %d\n", args->args_count);
+		return -EINVAL;
+	}
+
+	power_domain->id = args->args[0];
+
+	return 0;
+}
+
+int power_domain_get(struct udevice *dev, struct power_domain *power_domain)
+{
+	struct fdtdec_phandle_args args;
+	int ret;
+	struct udevice *dev_power_domain;
+	struct power_domain_ops *ops;
+
+	debug("%s(dev=%p, power_domain=%p)\n", __func__, dev, power_domain);
+
+	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
+					     "power-domains",
+					     "#power-domain-cells", 0, 0,
+					     &args);
+	if (ret) {
+		debug("%s: fdtdec_parse_phandle_with_args failed: %d\n",
+		      __func__, ret);
+		return ret;
+	}
+
+	ret = uclass_get_device_by_of_offset(UCLASS_POWER_DOMAIN, args.node,
+					     &dev_power_domain);
+	if (ret) {
+		debug("%s: uclass_get_device_by_of_offset failed: %d\n",
+		      __func__, ret);
+		return ret;
+	}
+	ops = power_domain_dev_ops(dev_power_domain);
+
+	power_domain->dev = dev_power_domain;
+	if (ops->of_xlate)
+		ret = ops->of_xlate(power_domain, &args);
+	else
+		ret = power_domain_of_xlate_default(power_domain, &args);
+	if (ret) {
+		debug("of_xlate() failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = ops->request(power_domain);
+	if (ret) {
+		debug("ops->request() failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int power_domain_free(struct power_domain *power_domain)
+{
+	struct power_domain_ops *ops = power_domain_dev_ops(power_domain->dev);
+
+	debug("%s(power_domain=%p)\n", __func__, power_domain);
+
+	return ops->free(power_domain);
+}
+
+int power_domain_on(struct power_domain *power_domain)
+{
+	struct power_domain_ops *ops = power_domain_dev_ops(power_domain->dev);
+
+	debug("%s(power_domain=%p)\n", __func__, power_domain);
+
+	return ops->on(power_domain);
+}
+
+int power_domain_off(struct power_domain *power_domain)
+{
+	struct power_domain_ops *ops = power_domain_dev_ops(power_domain->dev);
+
+	debug("%s(power_domain=%p)\n", __func__, power_domain);
+
+	return ops->off(power_domain);
+}
+
+UCLASS_DRIVER(power_domain) = {
+	.id		= UCLASS_POWER_DOMAIN,
+	.name		= "power_domain",
+};
diff --git a/drivers/power/domain/sandbox-power-domain-test.c b/drivers/power/domain/sandbox-power-domain-test.c
new file mode 100644
index 0000000..92a3a2a
--- /dev/null
+++ b/drivers/power/domain/sandbox-power-domain-test.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <power-domain.h>
+#include <asm/io.h>
+#include <asm/power-domain.h>
+
+struct sandbox_power_domain_test {
+	struct power_domain pd;
+};
+
+int sandbox_power_domain_test_get(struct udevice *dev)
+{
+	struct sandbox_power_domain_test *sbrt = dev_get_priv(dev);
+
+	return power_domain_get(dev, &sbrt->pd);
+}
+
+int sandbox_power_domain_test_on(struct udevice *dev)
+{
+	struct sandbox_power_domain_test *sbrt = dev_get_priv(dev);
+
+	return power_domain_on(&sbrt->pd);
+}
+
+int sandbox_power_domain_test_off(struct udevice *dev)
+{
+	struct sandbox_power_domain_test *sbrt = dev_get_priv(dev);
+
+	return power_domain_off(&sbrt->pd);
+}
+
+int sandbox_power_domain_test_free(struct udevice *dev)
+{
+	struct sandbox_power_domain_test *sbrt = dev_get_priv(dev);
+
+	return power_domain_free(&sbrt->pd);
+}
+
+static const struct udevice_id sandbox_power_domain_test_ids[] = {
+	{ .compatible = "sandbox,power-domain-test" },
+	{ }
+};
+
+U_BOOT_DRIVER(sandbox_power_domain_test) = {
+	.name = "sandbox_power_domain_test",
+	.id = UCLASS_MISC,
+	.of_match = sandbox_power_domain_test_ids,
+	.priv_auto_alloc_size = sizeof(struct sandbox_power_domain_test),
+};
diff --git a/drivers/power/domain/sandbox-power-domain.c b/drivers/power/domain/sandbox-power-domain.c
new file mode 100644
index 0000000..9071346
--- /dev/null
+++ b/drivers/power/domain/sandbox-power-domain.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <power-domain-uclass.h>
+#include <asm/io.h>
+#include <asm/power-domain.h>
+
+#define SANDBOX_POWER_DOMAINS 3
+
+struct sandbox_power_domain {
+	bool on[SANDBOX_POWER_DOMAINS];
+};
+
+static int sandbox_power_domain_request(struct power_domain *power_domain)
+{
+	debug("%s(power_domain=%p)\n", __func__, power_domain);
+
+	if (power_domain->id >= SANDBOX_POWER_DOMAINS)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int sandbox_power_domain_free(struct power_domain *power_domain)
+{
+	debug("%s(power_domain=%p)\n", __func__, power_domain);
+
+	return 0;
+}
+
+static int sandbox_power_domain_on(struct power_domain *power_domain)
+{
+	struct sandbox_power_domain *sbr = dev_get_priv(power_domain->dev);
+
+	debug("%s(power_domain=%p)\n", __func__, power_domain);
+
+	sbr->on[power_domain->id] = true;
+
+	return 0;
+}
+
+static int sandbox_power_domain_off(struct power_domain *power_domain)
+{
+	struct sandbox_power_domain *sbr = dev_get_priv(power_domain->dev);
+
+	debug("%s(power_domain=%p)\n", __func__, power_domain);
+
+	sbr->on[power_domain->id] = false;
+
+	return 0;
+}
+
+static int sandbox_power_domain_bind(struct udevice *dev)
+{
+	debug("%s(dev=%p)\n", __func__, dev);
+
+	return 0;
+}
+
+static int sandbox_power_domain_probe(struct udevice *dev)
+{
+	debug("%s(dev=%p)\n", __func__, dev);
+
+	return 0;
+}
+
+static const struct udevice_id sandbox_power_domain_ids[] = {
+	{ .compatible = "sandbox,power-domain" },
+	{ }
+};
+
+struct power_domain_ops sandbox_power_domain_ops = {
+	.request = sandbox_power_domain_request,
+	.free = sandbox_power_domain_free,
+	.on = sandbox_power_domain_on,
+	.off = sandbox_power_domain_off,
+};
+
+U_BOOT_DRIVER(sandbox_power_domain) = {
+	.name = "sandbox_power_domain",
+	.id = UCLASS_POWER_DOMAIN,
+	.of_match = sandbox_power_domain_ids,
+	.bind = sandbox_power_domain_bind,
+	.probe = sandbox_power_domain_probe,
+	.priv_auto_alloc_size = sizeof(struct sandbox_power_domain),
+	.ops = &sandbox_power_domain_ops,
+};
+
+int sandbox_power_domain_query(struct udevice *dev, unsigned long id)
+{
+	struct sandbox_power_domain *sbr = dev_get_priv(dev);
+
+	debug("%s(dev=%p, id=%ld)\n", __func__, dev, id);
+
+	if (id >= SANDBOX_POWER_DOMAINS)
+		return -EINVAL;
+
+	return sbr->on[id];
+}
diff --git a/drivers/power/domain/tegra186-power-domain.c b/drivers/power/domain/tegra186-power-domain.c
new file mode 100644
index 0000000..41d84de
--- /dev/null
+++ b/drivers/power/domain/tegra186-power-domain.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <misc.h>
+#include <power-domain-uclass.h>
+#include <asm/arch-tegra/bpmp_abi.h>
+
+#define UPDATE	BIT(0)
+#define ON	BIT(1)
+
+static int tegra186_power_domain_request(struct power_domain *power_domain)
+{
+	debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__,
+	      power_domain, power_domain->dev, power_domain->id);
+
+	return 0;
+}
+
+static int tegra186_power_domain_free(struct power_domain *power_domain)
+{
+	debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__,
+	      power_domain, power_domain->dev, power_domain->id);
+
+	return 0;
+}
+
+static int tegra186_power_domain_common(struct power_domain *power_domain,
+					bool on)
+{
+	struct mrq_pg_update_state_request req;
+	int on_state = on ? ON : 0;
+	int ret;
+
+	req.partition_id = power_domain->id;
+	req.logic_state = UPDATE | on_state;
+	req.sram_state = UPDATE | on_state;
+	/*
+	 * Drivers manage their own clocks so they don't get out of sync, and
+	 * since some power domains have many clocks, only a subset of which
+	 * are actually needed depending on use-case.
+	 */
+	req.clock_state = UPDATE;
+
+	ret = misc_call(power_domain->dev->parent, MRQ_PG_UPDATE_STATE, &req,
+			sizeof(req), NULL, 0);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int tegra186_power_domain_on(struct power_domain *power_domain)
+{
+	debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__,
+	      power_domain, power_domain->dev, power_domain->id);
+
+	return tegra186_power_domain_common(power_domain, true);
+}
+
+static int tegra186_power_domain_off(struct power_domain *power_domain)
+{
+	debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__,
+	      power_domain, power_domain->dev, power_domain->id);
+
+	return tegra186_power_domain_common(power_domain, false);
+}
+
+struct power_domain_ops tegra186_power_domain_ops = {
+	.request = tegra186_power_domain_request,
+	.free = tegra186_power_domain_free,
+	.on = tegra186_power_domain_on,
+	.off = tegra186_power_domain_off,
+};
+
+static int tegra186_power_domain_probe(struct udevice *dev)
+{
+	debug("%s(dev=%p)\n", __func__, dev);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(tegra186_power_domain) = {
+	.name = "tegra186_power_domain",
+	.id = UCLASS_POWER_DOMAIN,
+	.probe = tegra186_power_domain_probe,
+	.ops = &tegra186_power_domain_ops,
+};
diff --git a/drivers/power/pmic/act8846.c b/drivers/power/pmic/act8846.c
index ff096b3..e8164bf 100644
--- a/drivers/power/pmic/act8846.c
+++ b/drivers/power/pmic/act8846.c
@@ -29,7 +29,7 @@
 			  int len)
 {
 	if (dm_i2c_write(dev, reg, buff, len)) {
-		debug("write error to device: %p register: %#x!", dev, reg);
+		debug("write error to device: %p register: %#x!\n", dev, reg);
 		return -EIO;
 	}
 
@@ -39,7 +39,7 @@
 static int act8846_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
 {
 	if (dm_i2c_read(dev, reg, buff, len)) {
-		debug("read error from device: %p register: %#x!", dev, reg);
+		debug("read error from device: %p register: %#x!\n", dev, reg);
 		return -EIO;
 	}
 
diff --git a/drivers/power/pmic/pm8916.c b/drivers/power/pmic/pm8916.c
index d4c7d4a..2b65c69 100644
--- a/drivers/power/pmic/pm8916.c
+++ b/drivers/power/pmic/pm8916.c
@@ -7,7 +7,6 @@
  */
 #include <common.h>
 #include <dm.h>
-#include <dm/root.h>
 #include <power/pmic.h>
 #include <spmi/spmi.h>
 
@@ -79,17 +78,11 @@
 	return 0;
 }
 
-
-static int pm8916_bind(struct udevice *dev)
-{
-	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
-}
-
 U_BOOT_DRIVER(pmic_pm8916) = {
 	.name = "pmic_pm8916",
 	.id = UCLASS_PMIC,
 	.of_match = pm8916_ids,
-	.bind = pm8916_bind,
+	.bind = dm_scan_fdt_dev,
 	.probe = pm8916_probe,
 	.ops = &pm8916_ops,
 	.priv_auto_alloc_size = sizeof(struct pm8916_priv),
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index 465ff3f..17f22dd 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -13,7 +13,7 @@
 	- 'drivers/power/pmic/regulator-uclass.c'
 	It's important to call the device_bind() with the proper node offset,
 	when binding the regulator devices. The pmic_bind_childs() can be used
-	for this purpose if PMIC I/O driver is implemented or dm_scan_fdt_node()
+	for this purpose if PMIC I/O driver is implemented or dm_scan_fdt_dev()
 	otherwise. Detailed information can be found in the header file.
 
 config SPL_DM_REGULATOR
diff --git a/drivers/power/regulator/act8846.c b/drivers/power/regulator/act8846.c
index 255f8b0..d506165 100644
--- a/drivers/power/regulator/act8846.c
+++ b/drivers/power/regulator/act8846.c
@@ -88,7 +88,7 @@
 	int reg = dev->driver_data;
 	int ret;
 
-	ret = pmic_reg_read(dev->parent, reg);
+	ret = pmic_reg_read(dev->parent, addr_vol[reg]);
 	if (ret < 0)
 		return ret;
 
@@ -120,7 +120,7 @@
 	int reg = dev->driver_data;
 	int ret;
 
-	ret = pmic_reg_read(dev->parent, reg);
+	ret = pmic_reg_read(dev->parent, addr_ctl[reg]);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c
index 40cccc2..468c92e 100644
--- a/drivers/qe/uec.c
+++ b/drivers/qe/uec.c
@@ -623,20 +623,20 @@
  * Returns:
  *  0 on success
  */
-static int uec_miiphy_read(const char *devname, unsigned char addr,
-			    unsigned char reg, unsigned short *value)
+static int uec_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
+	unsigned short value = 0;
 	int devindex = 0;
 
-	if (devname == NULL || value == NULL) {
+	if (bus->name == NULL) {
 		debug("%s: NULL pointer given\n", __FUNCTION__);
 	} else {
-		devindex = uec_miiphy_find_dev_by_name(devname);
+		devindex = uec_miiphy_find_dev_by_name(bus->name);
 		if (devindex >= 0) {
-			*value = uec_read_phy_reg(devlist[devindex], addr, reg);
+			value = uec_read_phy_reg(devlist[devindex], addr, reg);
 		}
 	}
-	return 0;
+	return value;
 }
 
 /*
@@ -645,15 +645,15 @@
  * Returns:
  *  0 on success
  */
-static int uec_miiphy_write(const char *devname, unsigned char addr,
-			     unsigned char reg, unsigned short value)
+static int uec_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+			    u16 value)
 {
 	int devindex = 0;
 
-	if (devname == NULL) {
+	if (bus->name == NULL) {
 		debug("%s: NULL pointer given\n", __FUNCTION__);
 	} else {
-		devindex = uec_miiphy_find_dev_by_name(devname);
+		devindex = uec_miiphy_find_dev_by_name(bus->name);
 		if (devindex >= 0) {
 			uec_write_phy_reg(devlist[devindex], addr, reg, value);
 		}
@@ -1399,7 +1399,17 @@
 	}
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name, uec_miiphy_read, uec_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = uec_miiphy_read;
+	mdiodev->write = uec_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 
 	return 1;
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 0fe8cc3..5b84f21 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -20,4 +20,11 @@
 	  simply accepts requests to reset various HW modules without actually
 	  doing anything beyond a little error checking.
 
+config TEGRA186_RESET
+	bool "Enable Tegra186 BPMP-based reset driver"
+	depends on TEGRA186_BPMP
+	help
+	  Enable support for manipulating Tegra's on-SoC reset signals via IPC
+	  requests to the BPMP (Boot and Power Management Processor).
+
 endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 71f3b21..ff0e090 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -5,3 +5,4 @@
 obj-$(CONFIG_DM_RESET) += reset-uclass.o
 obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset.o
 obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset-test.o
+obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o
diff --git a/drivers/reset/tegra186-reset.c b/drivers/reset/tegra186-reset.c
new file mode 100644
index 0000000..228adda
--- /dev/null
+++ b/drivers/reset/tegra186-reset.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <misc.h>
+#include <reset-uclass.h>
+#include <asm/arch-tegra/bpmp_abi.h>
+
+static int tegra186_reset_request(struct reset_ctl *reset_ctl)
+{
+	debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+	      reset_ctl->dev, reset_ctl->id);
+
+	return 0;
+}
+
+static int tegra186_reset_free(struct reset_ctl *reset_ctl)
+{
+	debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+	      reset_ctl->dev, reset_ctl->id);
+
+	return 0;
+}
+
+static int tegra186_reset_common(struct reset_ctl *reset_ctl,
+				 enum mrq_reset_commands cmd)
+{
+	struct mrq_reset_request req;
+	int ret;
+
+	req.cmd = cmd;
+	req.reset_id = reset_ctl->id;
+
+	ret = misc_call(reset_ctl->dev->parent, MRQ_RESET, &req, sizeof(req),
+			NULL, 0);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int tegra186_reset_assert(struct reset_ctl *reset_ctl)
+{
+	debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+	      reset_ctl->dev, reset_ctl->id);
+
+	return tegra186_reset_common(reset_ctl, CMD_RESET_ASSERT);
+}
+
+static int tegra186_reset_deassert(struct reset_ctl *reset_ctl)
+{
+	debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+	      reset_ctl->dev, reset_ctl->id);
+
+	return tegra186_reset_common(reset_ctl, CMD_RESET_DEASSERT);
+}
+
+struct reset_ops tegra186_reset_ops = {
+	.request = tegra186_reset_request,
+	.free = tegra186_reset_free,
+	.rst_assert = tegra186_reset_assert,
+	.rst_deassert = tegra186_reset_deassert,
+};
+
+static int tegra186_reset_probe(struct udevice *dev)
+{
+	debug("%s(dev=%p)\n", __func__, dev);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(tegra186_reset) = {
+	.name		= "tegra186_reset",
+	.id		= UCLASS_RESET,
+	.probe		= tegra186_reset_probe,
+	.ops = &tegra186_reset_ops,
+};
diff --git a/drivers/rtc/date.c b/drivers/rtc/date.c
index 8c643a0..bfa2e13 100644
--- a/drivers/rtc/date.c
+++ b/drivers/rtc/date.c
@@ -5,10 +5,6 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-/*
- * Date & Time support for Philips PCF8563 RTC
- */
-
 #include <common.h>
 #include <command.h>
 #include <errno.h>
@@ -28,53 +24,52 @@
 	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
 };
 
+static int month_offset[] = {
+	0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+};
+
 /*
  * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
  */
 int rtc_calc_weekday(struct rtc_time *tm)
 {
-	int leapsToDate;
-	int lastYear;
+	int leaps_to_date;
+	int last_year;
 	int day;
-	int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
 
 	if (tm->tm_year < 1753)
-		return -EINVAL;
-	lastYear=tm->tm_year-1;
+		return -1;
+	last_year = tm->tm_year - 1;
 
-	/*
-	 * Number of leap corrections to apply up to end of last year
-	 */
-	leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;
+	/* Number of leap corrections to apply up to end of last year */
+	leaps_to_date = last_year / 4 - last_year / 100 + last_year / 400;
 
 	/*
 	 * This year is a leap year if it is divisible by 4 except when it is
 	 * divisible by 100 unless it is divisible by 400
 	 *
-	 * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be
+	 * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 is.
 	 */
-	if((tm->tm_year%4==0) &&
-	   ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) &&
-	   (tm->tm_mon>2)) {
-		/*
-		 * We are past Feb. 29 in a leap year
-		 */
-		day=1;
+	if (tm->tm_year % 4 == 0 &&
+	    ((tm->tm_year % 100 != 0) || (tm->tm_year % 400 == 0)) &&
+	    tm->tm_mon > 2) {
+		/* We are past Feb. 29 in a leap year */
+		day = 1;
 	} else {
-		day=0;
+		day = 0;
 	}
 
-	day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday;
-
-	tm->tm_wday=day%7;
+	day += last_year * 365 + leaps_to_date + month_offset[tm->tm_mon - 1] +
+			tm->tm_mday;
+	tm->tm_wday = day % 7;
 
 	return 0;
 }
 
 int rtc_to_tm(int tim, struct rtc_time *tm)
 {
-	register int    i;
-	register long   hms, day;
+	register int i;
+	register long hms, day;
 
 	day = tim / SECDAY;
 	hms = tim % SECDAY;
@@ -85,22 +80,19 @@
 	tm->tm_sec = (hms % 3600) % 60;
 
 	/* Number of years in days */
-	for (i = STARTOFTIME; day >= days_in_year(i); i++) {
+	for (i = STARTOFTIME; day >= days_in_year(i); i++)
 		day -= days_in_year(i);
-	}
 	tm->tm_year = i;
 
 	/* Number of months in days left */
-	if (leapyear(tm->tm_year)) {
+	if (leapyear(tm->tm_year))
 		days_in_month(FEBRUARY) = 29;
-	}
-	for (i = 1; day >= days_in_month(i); i++) {
+	for (i = 1; day >= days_in_month(i); i++)
 		day -= days_in_month(i);
-	}
 	days_in_month(FEBRUARY) = 28;
 	tm->tm_mon = i;
 
-	/* Days are what is left over (+1) from all that. */
+	/* Days are what is left over (+1) from all that */
 	tm->tm_mday = day + 1;
 
 	/* Zero unused fields */
@@ -113,19 +105,20 @@
 	return rtc_calc_weekday(tm);
 }
 
-/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
+/*
+ * Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
  * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
  *
  * [For the Julian calendar (which was used in Russia before 1917,
  * Britain & colonies before 1752, anywhere else before 1582,
  * and is still in use by some communities) leave out the
- * -year/100+year/400 terms, and add 10.]
+ * -year / 100 + year / 400 terms, and add 10.]
  *
  * This algorithm was first published by Gauss (I think).
  *
  * WARNING: this function will overflow on 2106-02-07 06:28:16 on
- * machines were long is 32-bit! (However, as time_t is signed, we
+ * machines where long is 32-bit! (However, as time_t is signed, we
  * will already get problems at other places on 2038-01-19 03:14:08)
  */
 unsigned long rtc_mktime(const struct rtc_time *tm)
@@ -135,8 +128,8 @@
 	int days, hours;
 
 	mon -= 2;
-	if (0 >= (int)mon) {	/* 1..12 -> 11,12,1..10 */
-		mon += 12;		/* Puts Feb last since it has leap day */
+	if (0 >= (int)mon) {	/* 1..12 -> 11, 12, 1..10 */
+		mon += 12;	/* Puts Feb last since it has leap day */
 		year -= 1;
 	}
 
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 0e38903..9ff7234 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -312,6 +312,15 @@
 	  be used. It can be a constant or a function to get clock, eg,
 	  get_serial_clock().
 
+config ROCKCHIP_SERIAL
+	bool "Rockchip on-chip UART support"
+	depends on DM_SERIAL && SPL_OF_PLATDATA
+	help
+	  Select this to enable a debug UART for Rockchip devices when using
+	  CONFIG_OF_PLATDATA (i.e. a compiled-in device tree replacemenmt).
+	  This uses the ns16550 driver, converting the platdata from of-platdata
+	  to the ns16550 format.
+
 config SANDBOX_SERIAL
 	bool "Sandbox UART support"
 	depends on SANDBOX
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 92cbea5..6986d65 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -28,6 +28,9 @@
 obj-$(CONFIG_MXC_UART) += serial_mxc.o
 obj-$(CONFIG_PXA_SERIAL) += serial_pxa.o
 obj-$(CONFIG_MESON_SERIAL) += serial_meson.o
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_ROCKCHIP_SERIAL) += serial_rockchip.o
+endif
 obj-$(CONFIG_S3C24X0_SERIAL) += serial_s3c24x0.o
 obj-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
 obj-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index c6cb3eb..88fca15 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -347,7 +347,7 @@
 	return 0;
 }
 
-#if CONFIG_IS_ENABLED(OF_CONTROL)
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
 int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
 {
 	struct ns16550_platdata *plat = dev->platdata;
@@ -416,6 +416,7 @@
 	.setbrg = ns16550_serial_setbrg,
 };
 
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 #if CONFIG_IS_ENABLED(OF_CONTROL)
 /*
  * Please consider existing compatible strings before adding a new
@@ -452,4 +453,5 @@
 	.flags	= DM_FLAG_PRE_RELOC,
 };
 #endif
+#endif /* !OF_PLATDATA */
 #endif /* CONFIG_DM_SERIAL */
diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c
index 58f882b..bcc3465 100644
--- a/drivers/serial/sandbox.c
+++ b/drivers/serial/sandbox.c
@@ -115,7 +115,9 @@
 		return 0;
 
 	os_usleep(100);
+#ifndef CONFIG_SPL_BUILD
 	video_sync_all();
+#endif
 	if (next_index == serial_buf_read)
 		return 1;	/* buffer full */
 
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index 0ce5c44..19f38e1 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -33,7 +33,13 @@
 	struct udevice *dev;
 	int node;
 
-	if (CONFIG_IS_ENABLED(OF_CONTROL) && blob) {
+	if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
+		uclass_first_device(UCLASS_SERIAL, &dev);
+		if (dev) {
+			gd->cur_serial_dev = dev;
+			return;
+		}
+	} else if (CONFIG_IS_ENABLED(OF_CONTROL) && blob) {
 		/* Check for a chosen console */
 		node = fdtdec_get_chosen_node(blob, "stdout-path");
 		if (node < 0) {
diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c
index 1563bb3..8545714 100644
--- a/drivers/serial/serial_mxc.c
+++ b/drivers/serial/serial_mxc.c
@@ -76,6 +76,7 @@
 #define  UFCR_RXTL_SHF   0       /* Receiver trigger level shift */
 #define  UFCR_RFDIV      (7<<7)  /* Reference freq divider mask */
 #define  UFCR_RFDIV_SHF  7      /* Reference freq divider shift */
+#define  UFCR_DCEDTE	 (1<<6)  /* DTE mode select */
 #define  UFCR_TXTL_SHF   10      /* Transmitter trigger level shift */
 #define  USR1_PARITYERR  (1<<15) /* Parity error interrupt flag */
 #define  USR1_RTSS	 (1<<14) /* RTS pin status */
@@ -269,8 +270,13 @@
 	struct mxc_serial_platdata *plat = dev->platdata;
 	struct mxc_uart *const uart = plat->reg;
 	u32 clk = imx_get_uartclk();
+	u32 tmp;
+
+	tmp = 4 << UFCR_RFDIV_SHF;
+	if (plat->use_dte)
+		tmp |= UFCR_DCEDTE;
+	writel(tmp, &uart->fcr);
 
-	writel(4 << 7, &uart->fcr); /* divide input clock by 2 */
 	writel(0xf, &uart->bir);
 	writel(clk / (2 * baudrate), &uart->bmr);
 
diff --git a/drivers/serial/serial_rockchip.c b/drivers/serial/serial_rockchip.c
new file mode 100644
index 0000000..6bac95a
--- /dev/null
+++ b/drivers/serial/serial_rockchip.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <ns16550.h>
+#include <serial.h>
+#include <asm/arch/clock.h>
+
+struct rockchip_uart_platdata {
+	struct dtd_rockchip_rk3288_uart dtplat;
+	struct ns16550_platdata plat;
+};
+
+struct dtd_rockchip_rk3288_uart *dtplat, s_dtplat;
+
+static int rockchip_serial_probe(struct udevice *dev)
+{
+	struct rockchip_uart_platdata *plat = dev_get_platdata(dev);
+
+	/* Create some new platform data for the standard driver */
+	plat->plat.base = plat->dtplat.reg[0];
+	plat->plat.reg_shift = plat->dtplat.reg_shift;
+	plat->plat.clock = plat->dtplat.clock_frequency;
+	dev->platdata = &plat->plat;
+
+	return ns16550_serial_probe(dev);
+}
+
+U_BOOT_DRIVER(rockchip_rk3288_uart) = {
+	.name	= "rockchip_rk3288_uart",
+	.id	= UCLASS_SERIAL,
+	.priv_auto_alloc_size = sizeof(struct NS16550),
+	.platdata_auto_alloc_size = sizeof(struct rockchip_uart_platdata),
+	.probe	= rockchip_serial_probe,
+	.ops	= &ns16550_serial_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c
index 8693c1e..ef7cf0f 100644
--- a/drivers/serial/serial_sh.c
+++ b/drivers/serial/serial_sh.c
@@ -17,6 +17,8 @@
 #include <dm/platform_data/serial_sh.h>
 #include "serial_sh.h"
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #if defined(CONFIG_CPU_SH7760) || \
 	defined(CONFIG_CPU_SH7780) || \
 	defined(CONFIG_CPU_SH7785) || \
@@ -201,9 +203,36 @@
 	.setbrg = sh_serial_setbrg,
 };
 
+#ifdef CONFIG_OF_CONTROL
+static const struct udevice_id sh_serial_id[] ={
+	{.compatible = "renesas,sci", .data = PORT_SCI},
+	{.compatible = "renesas,scif", .data = PORT_SCIF},
+	{.compatible = "renesas,scifa", .data = PORT_SCIFA},
+	{}
+};
+
+static int sh_serial_ofdata_to_platdata(struct udevice *dev)
+{
+	struct sh_serial_platdata *plat = dev_get_platdata(dev);
+	fdt_addr_t addr;
+
+	addr = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	plat->base = addr;
+	plat->clk = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "clock", 1);
+	plat->type = dev_get_driver_data(dev);
+	return 0;
+}
+#endif
+
 U_BOOT_DRIVER(serial_sh) = {
 	.name	= "serial_sh",
 	.id	= UCLASS_SERIAL,
+	.of_match = of_match_ptr(sh_serial_id),
+	.ofdata_to_platdata = of_match_ptr(sh_serial_ofdata_to_platdata),
+	.platdata_auto_alloc_size = sizeof(struct sh_serial_platdata),
 	.probe	= sh_serial_probe,
 	.ops	= &sh_serial_ops,
 	.flags	= DM_FLAG_PRE_RELOC,
@@ -234,6 +263,8 @@
 
 #if defined(CONFIG_SCIF_A)
 	#define SCIF_BASE_PORT	PORT_SCIFA
+#elif defined(CONFIG_SCI)
+	#define SCIF_BASE_PORT  PORT_SCI
 #else
 	#define SCIF_BASE_PORT	PORT_SCIF
 #endif
diff --git a/drivers/serial/serial_stm32x7.c b/drivers/serial/serial_stm32x7.c
index cfbfab7..592c0bd 100644
--- a/drivers/serial/serial_stm32x7.c
+++ b/drivers/serial/serial_stm32x7.c
@@ -9,6 +9,7 @@
 #include <dm.h>
 #include <asm/io.h>
 #include <serial.h>
+#include <asm/arch/stm32.h>
 #include <dm/platform_data/serial_stm32x7.h>
 #include "serial_stm32x7.h"
 
@@ -18,7 +19,20 @@
 {
 	struct stm32x7_serial_platdata *plat = dev->platdata;
 	struct stm32_usart *const usart = plat->base;
-	writel(plat->clock/baudrate, &usart->brr);
+	u32  clock, int_div, frac_div, tmp;
+
+	if (((u32)usart & STM32_BUS_MASK) == APB1_PERIPH_BASE)
+		clock = clock_get(CLOCK_APB1);
+	else if (((u32)usart & STM32_BUS_MASK) == APB2_PERIPH_BASE)
+		clock = clock_get(CLOCK_APB2);
+	else
+		return -EINVAL;
+
+	int_div = (25 * clock) / (4 * baudrate);
+	tmp = ((int_div / 100) << USART_BRR_M_SHIFT) & USART_BRR_M_MASK;
+	frac_div = int_div - (100 * (tmp >> USART_BRR_M_SHIFT));
+	tmp |= (((frac_div * 16) + 50) / 100) & USART_BRR_F_MASK;
+	writel(tmp, &usart->brr);
 
 	return 0;
 }
diff --git a/drivers/serial/serial_uniphier.c b/drivers/serial/serial_uniphier.c
index 525f0a4..ab607b7 100644
--- a/drivers/serial/serial_uniphier.c
+++ b/drivers/serial/serial_uniphier.c
@@ -1,5 +1,7 @@
 /*
- * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2012-2015 Panasonic Corporation
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -9,7 +11,6 @@
 #include <linux/sizes.h>
 #include <asm/errno.h>
 #include <dm/device.h>
-#include <mapmem.h>
 #include <serial.h>
 #include <fdtdec.h>
 
@@ -98,7 +99,7 @@
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
-	port = map_sysmem(base, SZ_64);
+	port = devm_ioremap(dev, base, SZ_64);
 	if (!port)
 		return -ENOMEM;
 
@@ -115,13 +116,6 @@
 	return 0;
 }
 
-static int uniphier_serial_remove(struct udevice *dev)
-{
-	unmap_sysmem(uniphier_serial_port(dev));
-
-	return 0;
-}
-
 static const struct udevice_id uniphier_uart_of_match[] = {
 	{ .compatible = "socionext,uniphier-uart" },
 	{ /* sentinel */ }
@@ -139,7 +133,6 @@
 	.id = UCLASS_SERIAL,
 	.of_match = uniphier_uart_of_match,
 	.probe = uniphier_serial_probe,
-	.remove = uniphier_serial_remove,
 	.priv_auto_alloc_size = sizeof(struct uniphier_serial_private_data),
 	.ops = &uniphier_serial_ops,
 };
diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c
index 66d54e3..4f6e7e4 100644
--- a/drivers/serial/serial_zynq.c
+++ b/drivers/serial/serial_zynq.c
@@ -5,6 +5,7 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#include <clk.h>
 #include <common.h>
 #include <debug_uart.h>
 #include <dm.h>
@@ -108,8 +109,33 @@
 int zynq_serial_setbrg(struct udevice *dev, int baudrate)
 {
 	struct zynq_uart_priv *priv = dev_get_priv(dev);
-	unsigned long clock = get_uart_clk(0);
+	unsigned long clock;
 
+#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
+	int ret;
+	struct clk clk;
+
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret < 0) {
+		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;
+	}
+	debug("%s: CLK %ld\n", __func__, clock);
+
+	ret = clk_enable(&clk);
+	if (ret && ret != -ENOSYS) {
+		dev_err(dev, "failed to enable clock\n");
+		return ret;
+	}
+#else
+	clock = get_uart_clk(0);
+#endif
 	_uart_zynq_serial_setbrg(priv->regs, clock, baudrate);
 
 	return 0;
diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index 4f7fd52..a5244ff 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -191,6 +191,7 @@
 	struct udevice *bus = dev->parent;
 	struct cadence_spi_platdata *plat = bus->platdata;
 	struct cadence_spi_priv *priv = dev_get_priv(bus);
+	struct dm_spi_slave_platdata *dm_plat = dev_get_parent_platdata(dev);
 	void *base = priv->regbase;
 	u8 *cmd_buf = priv->cmd_buf;
 	size_t data_bytes;
@@ -250,7 +251,7 @@
 		break;
 		case CQSPI_INDIRECT_READ:
 			err = cadence_qspi_apb_indirect_read_setup(plat,
-				priv->cmd_len, cmd_buf);
+				priv->cmd_len, dm_plat->mode_rx, cmd_buf);
 			if (!err) {
 				err = cadence_qspi_apb_indirect_read_execute
 				(plat, data_bytes, din);
diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h
index 2912e36..a849f7b 100644
--- a/drivers/spi/cadence_qspi.h
+++ b/drivers/spi/cadence_qspi.h
@@ -53,7 +53,7 @@
 	unsigned int txlen,  const u8 *txbuf);
 
 int cadence_qspi_apb_indirect_read_setup(struct cadence_spi_platdata *plat,
-	unsigned int cmdlen, const u8 *cmdbuf);
+	unsigned int cmdlen, unsigned int rx_width, const u8 *cmdbuf);
 int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat,
 	unsigned int rxlen, u8 *rxbuf);
 int cadence_qspi_apb_indirect_write_setup(struct cadence_spi_platdata *plat,
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index a71531d..1d68379 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -29,6 +29,7 @@
 #include <asm/io.h>
 #include <asm/errno.h>
 #include <wait_bit.h>
+#include <spi.h>
 #include "cadence_qspi.h"
 
 #define CQSPI_REG_POLL_US			(1) /* 1us */
@@ -45,7 +46,6 @@
 #define CQSPI_INST_TYPE_QUAD			(2)
 
 #define CQSPI_STIG_DATA_LEN_MAX			(8)
-#define CQSPI_INDIRECTTRIGGER_ADDR_MASK		(0xFFFFF)
 
 #define CQSPI_DUMMY_CLKS_PER_BYTE		(8)
 #define CQSPI_DUMMY_BYTES_MAX			(4)
@@ -293,8 +293,11 @@
 	debug("%s: ref_clk %dHz sclk %dHz Div 0x%x\n", __func__,
 	      ref_clk_hz, sclk_hz, div);
 
-	div = (div & CQSPI_REG_CONFIG_BAUD_MASK) << CQSPI_REG_CONFIG_BAUD_LSB;
-	reg |= div;
+	/* ensure the baud rate doesn't exceed the max value */
+	if (div > CQSPI_REG_CONFIG_BAUD_MASK)
+		div = CQSPI_REG_CONFIG_BAUD_MASK;
+
+	reg |= (div << CQSPI_REG_CONFIG_BAUD_LSB);
 	writel(reg, reg_base + CQSPI_REG_CONFIG);
 
 	cadence_qspi_apb_controller_enable(reg_base);
@@ -549,7 +552,7 @@
 
 /* Opcode + Address (3/4 bytes) + dummy bytes (0-4 bytes) */
 int cadence_qspi_apb_indirect_read_setup(struct cadence_spi_platdata *plat,
-	unsigned int cmdlen, const u8 *cmdbuf)
+	unsigned int cmdlen, unsigned int rx_width, const u8 *cmdbuf)
 {
 	unsigned int reg;
 	unsigned int rd_reg;
@@ -573,16 +576,15 @@
 		addr_bytes = cmdlen - 1;
 
 	/* Setup the indirect trigger address */
-	writel(((u32)plat->ahbbase & CQSPI_INDIRECTTRIGGER_ADDR_MASK),
+	writel((u32)plat->ahbbase,
 	       plat->regbase + CQSPI_REG_INDIRECTTRIGGER);
 
 	/* Configure the opcode */
 	rd_reg = cmdbuf[0] << CQSPI_REG_RD_INSTR_OPCODE_LSB;
 
-#if (CONFIG_SPI_FLASH_QUAD == 1)
-	/* Instruction and address at DQ0, data at DQ0-3. */
-	rd_reg |= CQSPI_INST_TYPE_QUAD << CQSPI_REG_RD_INSTR_TYPE_DATA_LSB;
-#endif
+	if (rx_width & SPI_RX_QUAD)
+		/* Instruction and address at DQ0, data at DQ0-3. */
+		rd_reg |= CQSPI_INST_TYPE_QUAD << CQSPI_REG_RD_INSTR_TYPE_DATA_LSB;
 
 	/* Get address */
 	addr_value = cadence_qspi_apb_cmd2addr(&cmdbuf[1], addr_bytes);
@@ -714,7 +716,7 @@
 		return -EINVAL;
 	}
 	/* Setup the indirect trigger address */
-	writel(((u32)plat->ahbbase & CQSPI_INDIRECTTRIGGER_ADDR_MASK),
+	writel((u32)plat->ahbbase,
 	       plat->regbase + CQSPI_REG_INDIRECTTRIGGER);
 
 	/* Configure the opcode */
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
index 0bd4f88..20aa99a 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -14,6 +14,7 @@
 #include <malloc.h>
 #include <asm/io.h>
 #include <asm/arch/hardware.h>
+#include <dm.h>
 
 /* SPIGCR0 */
 #define SPIGCR0_SPIENA_MASK	0x1
@@ -51,6 +52,7 @@
 /* SPIDEF */
 #define SPIDEF_CSDEF0_MASK	BIT(0)
 
+#ifndef CONFIG_DM_SPI
 #define SPI0_BUS		0
 #define SPI0_BASE		CONFIG_SYS_SPI_BASE
 /*
@@ -83,6 +85,9 @@
 #define SPI2_NUM_CS		CONFIG_SYS_SPI2_NUM_CS
 #define SPI2_BASE		CONFIG_SYS_SPI2_BASE
 #endif
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
 
 /* davinci spi register set */
 struct davinci_spi_regs {
@@ -114,16 +119,17 @@
 
 /* davinci spi slave */
 struct davinci_spi_slave {
+#ifndef CONFIG_DM_SPI
 	struct spi_slave slave;
+#endif
 	struct davinci_spi_regs *regs;
-	unsigned int freq;
+	unsigned int freq; /* current SPI bus frequency */
+	unsigned int mode; /* current SPI mode used */
+	u8 num_cs;	   /* total no. of CS available */
+	u8 cur_cs;	   /* CS of current slave */
+	bool half_duplex;  /* true, if master is half-duplex only */
 };
 
-static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave)
-{
-	return container_of(slave, struct davinci_spi_slave, slave);
-}
-
 /*
  * This functions needs to act like a macro to avoid pipeline reloads in the
  * loops below. Use always_inline. This gains us about 160KiB/s and the bloat
@@ -144,15 +150,14 @@
 	return buf_reg_val;
 }
 
-static int davinci_spi_read(struct spi_slave *slave, unsigned int len,
+static int davinci_spi_read(struct davinci_spi_slave *ds, unsigned int len,
 			    u8 *rxp, unsigned long flags)
 {
-	struct davinci_spi_slave *ds = to_davinci_spi(slave);
 	unsigned int data1_reg_val;
 
 	/* enable CS hold, CS[n] and clear the data bits */
 	data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
-			 (slave->cs << SPIDAT1_CSNR_SHIFT));
+			 (ds->cur_cs << SPIDAT1_CSNR_SHIFT));
 
 	/* wait till TXFULL is deasserted */
 	while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
@@ -175,15 +180,14 @@
 	return 0;
 }
 
-static int davinci_spi_write(struct spi_slave *slave, unsigned int len,
+static int davinci_spi_write(struct davinci_spi_slave *ds, unsigned int len,
 			     const u8 *txp, unsigned long flags)
 {
-	struct davinci_spi_slave *ds = to_davinci_spi(slave);
 	unsigned int data1_reg_val;
 
 	/* enable CS hold and clear the data bits */
 	data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
-			 (slave->cs << SPIDAT1_CSNR_SHIFT));
+			 (ds->cur_cs << SPIDAT1_CSNR_SHIFT));
 
 	/* wait till TXFULL is deasserted */
 	while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
@@ -209,16 +213,15 @@
 	return 0;
 }
 
-#ifndef CONFIG_SPI_HALF_DUPLEX
-static int davinci_spi_read_write(struct spi_slave *slave, unsigned int len,
-				  u8 *rxp, const u8 *txp, unsigned long flags)
+static int davinci_spi_read_write(struct davinci_spi_slave *ds, unsigned
+				  int len, u8 *rxp, const u8 *txp,
+				  unsigned long flags)
 {
-	struct davinci_spi_slave *ds = to_davinci_spi(slave);
 	unsigned int data1_reg_val;
 
 	/* enable CS hold and clear the data bits */
 	data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
-			 (slave->cs << SPIDAT1_CSNR_SHIFT));
+			 (ds->cur_cs << SPIDAT1_CSNR_SHIFT));
 
 	/* wait till TXFULL is deasserted */
 	while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
@@ -237,7 +240,115 @@
 
 	return 0;
 }
-#endif
+
+
+static int __davinci_spi_claim_bus(struct davinci_spi_slave *ds, int cs)
+{
+	unsigned int mode = 0, scalar;
+
+	/* Enable the SPI hardware */
+	writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
+	udelay(1000);
+	writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0);
+
+	/* Set master mode, powered up and not activated */
+	writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1);
+
+	/* CS, CLK, SIMO and SOMI are functional pins */
+	writel(((1 << cs) | SPIPC0_CLKFUN_MASK |
+		SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0);
+
+	/* setup format */
+	scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF;
+
+	/*
+	 * Use following format:
+	 *   character length = 8,
+	 *   MSB shifted out first
+	 */
+	if (ds->mode & SPI_CPOL)
+		mode |= SPI_CPOL;
+	if (!(ds->mode & SPI_CPHA))
+		mode |= SPI_CPHA;
+	writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) |
+		(mode << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0);
+
+	/*
+	 * Including a minor delay. No science here. Should be good even with
+	 * no delay
+	 */
+	writel((50 << SPI_C2TDELAY_SHIFT) |
+		(50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay);
+
+	/* default chip select register */
+	writel(SPIDEF_CSDEF0_MASK, &ds->regs->def);
+
+	/* no interrupts */
+	writel(0, &ds->regs->int0);
+	writel(0, &ds->regs->lvl);
+
+	/* enable SPI */
+	writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1);
+
+	return 0;
+}
+
+static int __davinci_spi_release_bus(struct davinci_spi_slave *ds)
+{
+	/* Disable the SPI hardware */
+	writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
+
+	return 0;
+}
+
+static int __davinci_spi_xfer(struct davinci_spi_slave *ds,
+		unsigned int bitlen,  const void *dout, void *din,
+		unsigned long flags)
+{
+	unsigned int len;
+
+	if (bitlen == 0)
+		/* Finish any previously submitted transfers */
+		goto out;
+
+	/*
+	 * It's not clear how non-8-bit-aligned transfers are supposed to be
+	 * represented as a stream of bytes...this is a limitation of
+	 * the current SPI interface - here we terminate on receiving such a
+	 * transfer request.
+	 */
+	if (bitlen % 8) {
+		/* Errors always terminate an ongoing transfer */
+		flags |= SPI_XFER_END;
+		goto out;
+	}
+
+	len = bitlen / 8;
+
+	if (!dout)
+		return davinci_spi_read(ds, len, din, flags);
+	if (!din)
+		return davinci_spi_write(ds, len, dout, flags);
+	if (!ds->half_duplex)
+		return davinci_spi_read_write(ds, len, din, dout, flags);
+
+	printf("SPI full duplex not supported\n");
+	flags |= SPI_XFER_END;
+
+out:
+	if (flags & SPI_XFER_END) {
+		u8 dummy = 0;
+		davinci_spi_write(ds, 1, &dummy, flags);
+	}
+	return 0;
+}
+
+#ifndef CONFIG_DM_SPI
+
+static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave)
+{
+	return container_of(slave, struct davinci_spi_slave, slave);
+}
 
 int spi_cs_is_valid(unsigned int bus, unsigned int cs)
 {
@@ -313,6 +424,7 @@
 	}
 
 	ds->freq = max_hz;
+	ds->mode = mode;
 
 	return &ds->slave;
 }
@@ -324,104 +436,143 @@
 	free(ds);
 }
 
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+	     const void *dout, void *din, unsigned long flags)
+{
+	struct davinci_spi_slave *ds = to_davinci_spi(slave);
+
+	ds->cur_cs = slave->cs;
+
+	return __davinci_spi_xfer(ds, bitlen, dout, din, flags);
+}
+
 int spi_claim_bus(struct spi_slave *slave)
 {
 	struct davinci_spi_slave *ds = to_davinci_spi(slave);
-	unsigned int scalar;
 
-	/* Enable the SPI hardware */
-	writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
-	udelay(1000);
-	writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0);
+#ifdef CONFIG_SPI_HALF_DUPLEX
+	ds->half_duplex = true;
+#else
+	ds->half_duplex = false;
+#endif
+	return __davinci_spi_claim_bus(ds, ds->slave.cs);
+}
 
-	/* Set master mode, powered up and not activated */
-	writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1);
+void spi_release_bus(struct spi_slave *slave)
+{
+	struct davinci_spi_slave *ds = to_davinci_spi(slave);
 
-	/* CS, CLK, SIMO and SOMI are functional pins */
-	writel(((1 << slave->cs) | SPIPC0_CLKFUN_MASK |
-		SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0);
+	__davinci_spi_release_bus(ds);
+}
 
-	/* setup format */
-	scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF;
+#else
+static int davinci_spi_set_speed(struct udevice *bus, uint max_hz)
+{
+	struct davinci_spi_slave *ds = dev_get_priv(bus);
 
-	/*
-	 * Use following format:
-	 *   character length = 8,
-	 *   clock signal delayed by half clk cycle,
-	 *   clock low in idle state - Mode 0,
-	 *   MSB shifted out first
-	 */
-	writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) |
-		(1 << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0);
+	debug("%s speed %u\n", __func__, max_hz);
+	if (max_hz > CONFIG_SYS_SPI_CLK / 2)
+		return -EINVAL;
 
-	/*
-	 * Including a minor delay. No science here. Should be good even with
-	 * no delay
-	 */
-	writel((50 << SPI_C2TDELAY_SHIFT) |
-		(50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay);
+	ds->freq = max_hz;
 
-	/* default chip select register */
-	writel(SPIDEF_CSDEF0_MASK, &ds->regs->def);
+	return 0;
+}
 
-	/* no interrupts */
-	writel(0, &ds->regs->int0);
-	writel(0, &ds->regs->lvl);
+static int davinci_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct davinci_spi_slave *ds = dev_get_priv(bus);
 
-	/* enable SPI */
-	writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1);
+	debug("%s mode %u\n", __func__, mode);
+	ds->mode = mode;
 
 	return 0;
 }
 
-void spi_release_bus(struct spi_slave *slave)
+static int davinci_spi_claim_bus(struct udevice *dev)
 {
-	struct davinci_spi_slave *ds = to_davinci_spi(slave);
+	struct dm_spi_slave_platdata *slave_plat =
+		dev_get_parent_platdata(dev);
+	struct udevice *bus = dev->parent;
+	struct davinci_spi_slave *ds = dev_get_priv(bus);
 
-	/* Disable the SPI hardware */
-	writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
+	if (slave_plat->cs >= ds->num_cs) {
+		printf("Invalid SPI chipselect\n");
+		return -EINVAL;
+	}
+	ds->half_duplex = slave_plat->mode & SPI_PREAMBLE;
+
+	return __davinci_spi_claim_bus(ds, slave_plat->cs);
 }
 
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
-	     const void *dout, void *din, unsigned long flags)
+static int davinci_spi_release_bus(struct udevice *dev)
 {
-	unsigned int len;
+	struct davinci_spi_slave *ds = dev_get_priv(dev->parent);
 
-	if (bitlen == 0)
-		/* Finish any previously submitted transfers */
-		goto out;
+	return __davinci_spi_release_bus(ds);
+}
 
-	/*
-	 * It's not clear how non-8-bit-aligned transfers are supposed to be
-	 * represented as a stream of bytes...this is a limitation of
-	 * the current SPI interface - here we terminate on receiving such a
-	 * transfer request.
-	 */
-	if (bitlen % 8) {
-		/* Errors always terminate an ongoing transfer */
-		flags |= SPI_XFER_END;
-		goto out;
+static int davinci_spi_xfer(struct udevice *dev, unsigned int bitlen,
+			    const void *dout, void *din,
+			    unsigned long flags)
+{
+	struct dm_spi_slave_platdata *slave =
+		dev_get_parent_platdata(dev);
+	struct udevice *bus = dev->parent;
+	struct davinci_spi_slave *ds = dev_get_priv(bus);
+
+	if (slave->cs >= ds->num_cs) {
+		printf("Invalid SPI chipselect\n");
+		return -EINVAL;
 	}
+	ds->cur_cs = slave->cs;
 
-	len = bitlen / 8;
+	return __davinci_spi_xfer(ds, bitlen, dout, din, flags);
+}
 
-	if (!dout)
-		return davinci_spi_read(slave, len, din, flags);
-	else if (!din)
-		return davinci_spi_write(slave, len, dout, flags);
-#ifndef CONFIG_SPI_HALF_DUPLEX
-	else
-		return davinci_spi_read_write(slave, len, din, dout, flags);
-#else
-	printf("SPI full duplex transaction requested with "
-	       "CONFIG_SPI_HALF_DUPLEX defined.\n");
-	flags |= SPI_XFER_END;
-#endif
+static int davinci_spi_probe(struct udevice *bus)
+{
+	/* Nothing to do */
+	return 0;
+}
 
-out:
-	if (flags & SPI_XFER_END) {
-		u8 dummy = 0;
-		davinci_spi_write(slave, 1, &dummy, flags);
+static int davinci_ofdata_to_platadata(struct udevice *bus)
+{
+	struct davinci_spi_slave *ds = dev_get_priv(bus);
+	const void *blob = gd->fdt_blob;
+	int node = bus->of_offset;
+
+	ds->regs = dev_map_physmem(bus, sizeof(struct davinci_spi_regs));
+	if (!ds->regs) {
+		printf("%s: could not map device address\n", __func__);
+		return -EINVAL;
 	}
+	ds->num_cs = fdtdec_get_int(blob, node, "num-cs", 4);
+
 	return 0;
 }
+
+static const struct dm_spi_ops davinci_spi_ops = {
+	.claim_bus	= davinci_spi_claim_bus,
+	.release_bus	= davinci_spi_release_bus,
+	.xfer		= davinci_spi_xfer,
+	.set_speed	= davinci_spi_set_speed,
+	.set_mode	= davinci_spi_set_mode,
+};
+
+static const struct udevice_id davinci_spi_ids[] = {
+	{ .compatible = "ti,keystone-spi" },
+	{ .compatible = "ti,dm6441-spi" },
+	{ }
+};
+
+U_BOOT_DRIVER(davinci_spi) = {
+	.name = "davinci_spi",
+	.id = UCLASS_SPI,
+	.of_match = davinci_spi_ids,
+	.ops = &davinci_spi_ops,
+	.ofdata_to_platdata = davinci_ofdata_to_platadata,
+	.priv_auto_alloc_size = sizeof(struct davinci_spi_slave),
+	.probe = davinci_spi_probe,
+};
+#endif
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
index 75cbab2..2144fca 100644
--- a/drivers/spi/fsl_qspi.c
+++ b/drivers/spi/fsl_qspi.c
@@ -386,6 +386,7 @@
 {
 	struct fsl_qspi_regs *regs = priv->regs;
 	u32 mcr_reg;
+	void *rx_addr = NULL;
 
 	mcr_reg = qspi_read32(priv->flags, &regs->mcr);
 
@@ -393,8 +394,9 @@
 		     QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
 		     QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
 
+	rx_addr = (void *)(uintptr_t)(priv->cur_amba_base + priv->sf_addr);
 	/* Read out the data directly from the AHB buffer. */
-	memcpy(rxbuf, (u8 *)(priv->cur_amba_base + priv->sf_addr), len);
+	memcpy(rxbuf, rx_addr, len);
 
 	qspi_write32(priv->flags, &regs->mcr, mcr_reg);
 }
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 84b6786..247abfa 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -12,7 +12,6 @@
 #include <spi.h>
 #include <dm/device-internal.h>
 #include <dm/uclass-internal.h>
-#include <dm/root.h>
 #include <dm/lists.h>
 #include <dm/util.h>
 
@@ -109,12 +108,6 @@
 	return dm_spi_xfer(slave->dev, bitlen, dout, din, flags);
 }
 
-static int spi_post_bind(struct udevice *dev)
-{
-	/* Scan the bus for devices */
-	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
-}
-
 static int spi_child_post_bind(struct udevice *dev)
 {
 	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
@@ -278,6 +271,7 @@
 		       struct udevice **busp, struct spi_slave **devp)
 {
 	struct udevice *bus, *dev;
+	struct dm_spi_slave_platdata *plat;
 	bool created = false;
 	int ret;
 
@@ -294,8 +288,6 @@
 	 * SPI flash chip - we will bind to the correct driver.
 	 */
 	if (ret == -ENODEV && drv_name) {
-		struct dm_spi_slave_platdata *plat;
-
 		debug("%s: Binding new device '%s', busnum=%d, cs=%d, driver=%s\n",
 		      __func__, dev_name, busnum, cs, drv_name);
 		ret = device_bind_driver(bus, drv_name, dev_name, &dev);
@@ -322,6 +314,11 @@
 		slave->dev = dev;
 	}
 
+	plat = dev_get_parent_platdata(dev);
+	if (!speed) {
+		speed = plat->max_hz;
+		mode = plat->mode;
+	}
 	ret = spi_set_speed_mode(bus, speed, mode);
 	if (ret)
 		goto err;
@@ -333,7 +330,7 @@
 	return 0;
 
 err:
-	debug("%s: Error path, credted=%d, device '%s'\n", __func__,
+	debug("%s: Error path, created=%d, device '%s'\n", __func__,
 	      created, dev->name);
 	if (created) {
 		device_remove(dev);
@@ -442,7 +439,7 @@
 	.id		= UCLASS_SPI,
 	.name		= "spi",
 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
-	.post_bind	= spi_post_bind,
+	.post_bind	= dm_scan_fdt_dev,
 	.post_probe	= spi_post_probe,
 	.child_pre_probe = spi_child_pre_probe,
 	.per_device_auto_alloc_size = sizeof(struct dm_spi_bus),
diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c
index 9a372ad..bb72cb0 100644
--- a/drivers/spi/ti_qspi.c
+++ b/drivers/spi/ti_qspi.c
@@ -21,7 +21,8 @@
 
 /* ti qpsi register bit masks */
 #define QSPI_TIMEOUT                    2000000
-#define QSPI_FCLK                       192000000
+#define QSPI_FCLK			192000000
+#define QSPI_DRA7XX_FCLK                76800000
 /* clock control */
 #define QSPI_CLK_EN                     BIT(31)
 #define QSPI_CLK_DIV_MAX                0xffff
@@ -101,6 +102,7 @@
 #endif
 	struct ti_qspi_regs *base;
 	void *ctrl_mod_mmap;
+	ulong fclk;
 	unsigned int mode;
 	u32 cmd;
 	u32 dc;
@@ -110,12 +112,12 @@
 {
 	uint clk_div;
 
-	debug("ti_spi_set_speed: hz: %d, clock divider %d\n", hz, clk_div);
-
 	if (!hz)
 		clk_div = 0;
 	else
-		clk_div = (QSPI_FCLK / hz) - 1;
+		clk_div = (priv->fclk / hz) - 1;
+
+	debug("ti_spi_set_speed: hz: %d, clock divider %d\n", hz, clk_div);
 
 	/* disable SCLK */
 	writel(readl(&priv->base->clk_ctrl) & ~QSPI_CLK_EN,
@@ -247,13 +249,9 @@
 			debug("tx done, status %08x\n", status);
 		}
 		if (rxp) {
-			priv->cmd |= QSPI_RD_SNGL;
 			debug("rx cmd %08x dc %08x\n",
-			      priv->cmd, priv->dc);
-			#ifdef CONFIG_DRA7XX
-				udelay(500);
-			#endif
-			writel(priv->cmd, &priv->base->cmd);
+			      ((u32)(priv->cmd | QSPI_RD_SNGL)), priv->dc);
+			writel(priv->cmd | QSPI_RD_SNGL, &priv->base->cmd);
 			status = readl(&priv->base->status);
 			timeout = QSPI_TIMEOUT;
 			while ((status & QSPI_WC_BUSY) != QSPI_XFER_DONE) {
@@ -370,8 +368,10 @@
 #if defined(CONFIG_DRA7XX) || defined(CONFIG_AM57XX)
 	priv->ctrl_mod_mmap = (void *)CORE_CTRL_IO;
 	priv->slave.memory_map = (void *)MMAP_START_ADDR_DRA;
+	priv->fclk = QSPI_DRA7XX_FCLK;
 #else
 	priv->slave.memory_map = (void *)MMAP_START_ADDR_AM43x;
+	priv->fclk = QSPI_FCLK;
 #endif
 
 	ti_spi_set_speed(priv, max_hz);
@@ -524,7 +524,10 @@
 
 static int ti_qspi_probe(struct udevice *bus)
 {
-	/* Nothing to do in probe */
+	struct ti_qspi_priv *priv = dev_get_priv(bus);
+
+	priv->fclk = dev_get_driver_data(bus);
+
 	return 0;
 }
 
@@ -576,8 +579,8 @@
 };
 
 static const struct udevice_id ti_qspi_ids[] = {
-	{ .compatible = "ti,dra7xxx-qspi" },
-	{ .compatible = "ti,am4372-qspi" },
+	{ .compatible = "ti,dra7xxx-qspi",	.data = QSPI_DRA7XX_FCLK},
+	{ .compatible = "ti,am4372-qspi",	.data = QSPI_FCLK},
 	{ }
 };
 
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index 8d25b45..ab4878e 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -9,13 +9,13 @@
 	  to connect PMIC devices on various SoCs.
 
 config SPMI_MSM
-	boolean "Support Qualcomm SPMI bus"
+	bool "Support Qualcomm SPMI bus"
 	depends on SPMI
 	---help---
 	  Support SPMI bus implementation found on Qualcomm Snapdragon SoCs.
 
 config SPMI_SANDBOX
-	boolean "Support for Sandbox SPMI bus"
+	bool "Support for Sandbox SPMI bus"
 	depends on SPMI
 	---help---
 	  Demo SPMI bus implementation. Emulates part of PM8916 as single
diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c
index 0cef505..48bc157 100644
--- a/drivers/spmi/spmi-msm.c
+++ b/drivers/spmi/spmi-msm.c
@@ -153,11 +153,12 @@
 	priv->spmi_core = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
 							   parent->of_offset,
 							   dev->of_offset,
-							   "reg", 1, NULL);
+							   "reg", 1, NULL,
+							   false);
 	priv->spmi_obs = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
 							  parent->of_offset,
 							  dev->of_offset, "reg",
-							  2, NULL);
+							  2, NULL, false);
 	if (priv->arb_chnl == FDT_ADDR_T_NONE ||
 	    priv->spmi_core == FDT_ADDR_T_NONE ||
 	    priv->spmi_obs == FDT_ADDR_T_NONE)
diff --git a/drivers/spmi/spmi-uclass.c b/drivers/spmi/spmi-uclass.c
index 4ddd51b..6edece2 100644
--- a/drivers/spmi/spmi-uclass.c
+++ b/drivers/spmi/spmi-uclass.c
@@ -9,7 +9,6 @@
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
-#include <dm/root.h>
 #include <spmi/spmi.h>
 #include <linux/ctype.h>
 
@@ -36,13 +35,8 @@
 	return ops->write(dev, usid, pid, reg, value);
 }
 
-static int spmi_post_bind(struct udevice *dev)
-{
-	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
-}
-
 UCLASS_DRIVER(spmi) = {
 	.id		= UCLASS_SPMI,
 	.name		= "spmi",
-	.post_bind	= spmi_post_bind,
+	.post_bind	= dm_scan_fdt_dev,
 };
diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig
new file mode 100644
index 0000000..05a37b9
--- /dev/null
+++ b/drivers/sysreset/Kconfig
@@ -0,0 +1,16 @@
+#
+# System reset devices
+#
+
+menu "System reset device drivers"
+
+config SYSRESET
+	bool "Enable support for system reset drivers"
+	depends on DM
+	help
+	  Enable system reset drivers which can be used to reset the CPU or
+	  board. Each driver can provide a reset method which will be called
+	  to effect a reset. The uclass will try all available drivers when
+	  reset_walk() is called.
+
+endmenu
diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile
new file mode 100644
index 0000000..fa75cc5
--- /dev/null
+++ b/drivers/sysreset/Makefile
@@ -0,0 +1,16 @@
+#
+# (C) Copyright 2016 Cadence Design Systems Inc.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_SYSRESET) += sysreset-uclass.o
+
+ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_ROCKCHIP_RK3036) += sysreset_rk3036.o
+endif
+obj-$(CONFIG_ROCKCHIP_RK3288) += sysreset_rk3288.o
+obj-$(CONFIG_ROCKCHIP_RK3399) += sysreset_rk3399.o
+obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o
+obj-$(CONFIG_ARCH_SNAPDRAGON) += sysreset_snapdragon.o
+obj-$(CONFIG_TARGET_XTFPGA) += sysreset_xtfpga.o
diff --git a/drivers/misc/sysreset-uclass.c b/drivers/sysreset/sysreset-uclass.c
similarity index 100%
rename from drivers/misc/sysreset-uclass.c
rename to drivers/sysreset/sysreset-uclass.c
diff --git a/arch/arm/mach-rockchip/rk3036/reset_rk3036.c b/drivers/sysreset/sysreset_rk3036.c
similarity index 100%
rename from arch/arm/mach-rockchip/rk3036/reset_rk3036.c
rename to drivers/sysreset/sysreset_rk3036.c
diff --git a/arch/arm/mach-rockchip/rk3288/reset_rk3288.c b/drivers/sysreset/sysreset_rk3288.c
similarity index 100%
rename from arch/arm/mach-rockchip/rk3288/reset_rk3288.c
rename to drivers/sysreset/sysreset_rk3288.c
diff --git a/drivers/sysreset/sysreset_rk3399.c b/drivers/sysreset/sysreset_rk3399.c
new file mode 100644
index 0000000..9a55546
--- /dev/null
+++ b/drivers/sysreset/sysreset_rk3399.c
@@ -0,0 +1,45 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <sysreset.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk3399.h>
+#include <asm/arch/hardware.h>
+#include <linux/err.h>
+
+int rk3399_sysreset_request(struct udevice *dev, enum sysreset_t type)
+{
+	struct rk3399_cru *cru = rockchip_get_cru();
+
+	if (IS_ERR(cru))
+		return PTR_ERR(cru);
+	switch (type) {
+	case SYSRESET_WARM:
+		writel(0xeca8, &cru->glb_srst_snd_value);
+		break;
+	case SYSRESET_COLD:
+		writel(0xfdb9, &cru->glb_srst_fst_value);
+		break;
+	default:
+		return -EPROTONOSUPPORT;
+	}
+
+	return -EINPROGRESS;
+}
+
+static struct sysreset_ops rk3399_sysreset = {
+	.request	= rk3399_sysreset_request,
+};
+
+U_BOOT_DRIVER(sysreset_rk3399) = {
+	.name	= "rk3399_sysreset",
+	.id	= UCLASS_SYSRESET,
+	.ops	= &rk3399_sysreset,
+};
diff --git a/drivers/misc/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c
similarity index 100%
rename from drivers/misc/sysreset_sandbox.c
rename to drivers/sysreset/sysreset_sandbox.c
diff --git a/arch/arm/mach-snapdragon/reset.c b/drivers/sysreset/sysreset_snapdragon.c
similarity index 100%
rename from arch/arm/mach-snapdragon/reset.c
rename to drivers/sysreset/sysreset_snapdragon.c
diff --git a/drivers/sysreset/sysreset_xtfpga.c b/drivers/sysreset/sysreset_xtfpga.c
new file mode 100644
index 0000000..54fd5a0
--- /dev/null
+++ b/drivers/sysreset/sysreset_xtfpga.c
@@ -0,0 +1,37 @@
+/*
+ * Cadence Tensilica xtfpga system reset driver.
+ *
+ * (C) Copyright 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <sysreset.h>
+#include <asm/io.h>
+
+static int xtfpga_reset_request(struct udevice *dev, enum sysreset_t type)
+{
+	switch (type) {
+	case SYSRESET_COLD:
+		writel(CONFIG_SYS_FPGAREG_RESET_CODE,
+		       CONFIG_SYS_FPGAREG_RESET);
+		break;
+	default:
+		return -EPROTONOSUPPORT;
+	}
+
+	return -EINPROGRESS;
+}
+
+static struct sysreset_ops xtfpga_sysreset_ops = {
+	.request	= xtfpga_reset_request,
+};
+
+U_BOOT_DRIVER(xtfpga_sysreset) = {
+	.name	= "xtfpga_sysreset",
+	.id	= UCLASS_SYSRESET,
+	.ops	= &xtfpga_sysreset_ops,
+};
diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig
index 9a7b7f5..7ab34ce 100644
--- a/drivers/tpm/Kconfig
+++ b/drivers/tpm/Kconfig
@@ -15,7 +15,7 @@
 
 config TPM_ATMEL_TWI
 	bool "Enable Atmel TWI TPM device driver"
-	depends on TPM && DM_I2C
+	depends on TPM
 	help
 	  This driver supports an Atmel TPM device connected on the I2C bus.
 	  The usual tpm operations and the 'tpm' command can be used to talk
diff --git a/drivers/tpm/tpm_atmel_twi.c b/drivers/tpm/tpm_atmel_twi.c
index 2aa9381..eba654b 100644
--- a/drivers/tpm/tpm_atmel_twi.c
+++ b/drivers/tpm/tpm_atmel_twi.c
@@ -81,14 +81,23 @@
 	print_buffer(0, (void *)sendbuf, 1, send_size, 0);
 #endif
 
+#ifndef CONFIG_DM_I2C
 	res = i2c_write(0x29, 0, 0, (uchar *)sendbuf, send_size);
+#else
+	res = dm_i2c_write(dev, 0, sendbuf, send_size);
+#endif
 	if (res) {
 		printf("i2c_write returned %d\n", res);
 		return -1;
 	}
 
 	start = get_timer(0);
-	while ((res = i2c_read(0x29, 0, 0, recvbuf, 10))) {
+#ifndef CONFIG_DM_I2C
+	while ((res = i2c_read(0x29, 0, 0, recvbuf, 10)))
+#else
+	while ((res = dm_i2c_read(dev, 0, recvbuf, 10)))
+#endif
+	{
 		/* TODO Use TIS_TIMEOUT from tpm_tis_infineon.h */
 		if (get_timer(start) > ATMEL_TPM_TIMEOUT_MS) {
 			puts("tpm timed out\n");
@@ -99,7 +108,11 @@
 	if (!res) {
 		*recv_len = get_unaligned_be32(recvbuf + 2);
 		if (*recv_len > 10)
+#ifndef CONFIG_DM_I2C
 			res = i2c_read(0x29, 0, 0, recvbuf, *recv_len);
+#else
+			res = dm_i2c_read(dev, 0, recvbuf, *recv_len);
+#endif
 	}
 	if (res) {
 		printf("i2c_read returned %d (rlen=%d)\n", res, *recv_len);
diff --git a/drivers/usb/emul/usb-emul-uclass.c b/drivers/usb/emul/usb-emul-uclass.c
index ee7ea5a..6e03c1e 100644
--- a/drivers/usb/emul/usb-emul-uclass.c
+++ b/drivers/usb/emul/usb-emul-uclass.c
@@ -8,7 +8,6 @@
 #include <common.h>
 #include <dm.h>
 #include <usb.h>
-#include <dm/root.h>
 #include <dm/device-internal.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -265,12 +264,6 @@
 	return 0;
 }
 
-int usb_emul_post_bind(struct udevice *dev)
-{
-	/* Scan the bus for devices */
-	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
-}
-
 void usb_emul_reset(struct udevice *dev)
 {
 	struct usb_dev_platdata *plat = dev_get_parent_platdata(dev);
@@ -282,7 +275,7 @@
 UCLASS_DRIVER(usb_emul) = {
 	.id		= UCLASS_USB_EMUL,
 	.name		= "usb_emul",
-	.post_bind	= usb_emul_post_bind,
+	.post_bind	= dm_scan_fdt_dev,
 	.per_child_auto_alloc_size = sizeof(struct usb_device),
 	.per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata),
 };
diff --git a/drivers/usb/eth/asix88179.c b/drivers/usb/eth/asix88179.c
index 5e1ea86..7548269 100644
--- a/drivers/usb/eth/asix88179.c
+++ b/drivers/usb/eth/asix88179.c
@@ -7,6 +7,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <usb.h>
 #include <net.h>
 #include <linux/mii.h>
@@ -185,6 +186,7 @@
 #define FLAG_TYPE_SITECOM	(1U << 3)
 #define FLAG_TYPE_SAMSUNG	(1U << 4)
 #define FLAG_TYPE_LENOVO	(1U << 5)
+#define FLAG_TYPE_GX3		(1U << 6)
 
 /* local vars */
 static const struct {
@@ -196,10 +198,18 @@
 	{7, 0xcc, 0x4c, 0x04, 8},
 };
 
+#ifndef CONFIG_DM_ETH
 static int curr_eth_dev; /* index for name of next device detected */
+#endif
 
 /* driver private */
 struct asix_private {
+#ifdef CONFIG_DM_ETH
+	struct ueth_data ueth;
+	unsigned pkt_cnt;
+	uint8_t *pkt_data;
+	uint32_t *pkt_hdr;
+#endif
 	int flags;
 	int rx_urb_size;
 	int maxpacketsize;
@@ -258,36 +268,32 @@
 	return len == size ? 0 : ECOMM;
 }
 
-static int asix_read_mac(struct eth_device *eth)
+static int asix_read_mac(struct ueth_data *dev, uint8_t *enetaddr)
 {
-	struct ueth_data *dev = (struct ueth_data *)eth->priv;
-	u8 buf[ETH_ALEN];
-
-	asix_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, 6, 6, buf);
-	debug("asix_read_mac() returning %02x:%02x:%02x:%02x:%02x:%02x\n",
-	      buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
+	int ret;
 
-	memcpy(eth->enetaddr, buf, ETH_ALEN);
+	ret = asix_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, 6, 6, enetaddr);
+	if (ret < 0)
+		debug("Failed to read MAC address: %02x\n", ret);
 
-	return 0;
+	return ret;
 }
 
-static int asix_write_mac(struct eth_device *eth)
+static int asix_write_mac(struct ueth_data *dev, uint8_t *enetaddr)
 {
-	struct ueth_data *dev = (struct ueth_data *)eth->priv;
 	int ret;
 
 	ret = asix_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN,
-				 ETH_ALEN, eth->enetaddr);
+				 ETH_ALEN, enetaddr);
 	if (ret < 0)
 		debug("Failed to set MAC address: %02x\n", ret);
 
 	return ret;
 }
 
-static int asix_basic_reset(struct ueth_data *dev)
+static int asix_basic_reset(struct ueth_data *dev,
+			struct asix_private *dev_priv)
 {
-	struct asix_private *dev_priv = (struct asix_private *)dev->dev_priv;
 	u8 buf[5];
 	u16 *tmp16;
 	u8 *tmp;
@@ -386,13 +392,9 @@
 	}
 }
 
-/*
- * Asix callbacks
- */
-static int asix_init(struct eth_device *eth, bd_t *bd)
+static int asix_init_common(struct ueth_data *dev,
+			struct asix_private *dev_priv)
 {
-	struct ueth_data *dev = (struct ueth_data *)eth->priv;
-	struct asix_private *dev_priv = (struct asix_private *)dev->dev_priv;
 	u8 buf[2], tmp[5], link_sts;
 	u16 *tmp16, mode;
 
@@ -410,7 +412,7 @@
 	if (asix_wait_link(dev) != 0) {
 		/*reset device and try again*/
 		printf("Reset Ethernet Device\n");
-		asix_basic_reset(dev);
+		asix_basic_reset(dev, dev_priv);
 		if (asix_wait_link(dev) != 0)
 			goto out_err;
 	}
@@ -462,11 +464,10 @@
 	return -1;
 }
 
-static int asix_send(struct eth_device *eth, void *packet, int length)
+static int asix_send_common(struct ueth_data *dev,
+			struct asix_private *dev_priv,
+			void *packet, int length)
 {
-	struct ueth_data *dev = (struct ueth_data *)eth->priv;
-	struct asix_private *dev_priv = (struct asix_private *)dev->dev_priv;
-
 	int err;
 	u32 packet_len, tx_hdr2;
 	int actual_len, framesize;
@@ -503,6 +504,33 @@
 	return err;
 }
 
+#ifndef CONFIG_DM_ETH
+/*
+ * Asix callbacks
+ */
+static int asix_init(struct eth_device *eth, bd_t *bd)
+{
+	struct ueth_data *dev = (struct ueth_data *)eth->priv;
+	struct asix_private *dev_priv = (struct asix_private *)dev->dev_priv;
+
+	return asix_init_common(dev, dev_priv);
+}
+
+static int asix_write_hwaddr(struct eth_device *eth)
+{
+	struct ueth_data *dev = (struct ueth_data *)eth->priv;
+
+	return asix_write_mac(dev, eth->enetaddr);
+}
+
+static int asix_send(struct eth_device *eth, void *packet, int length)
+{
+	struct ueth_data *dev = (struct ueth_data *)eth->priv;
+	struct asix_private *dev_priv = (struct asix_private *)dev->dev_priv;
+
+	return asix_send_common(dev, dev_priv, packet, length);
+}
+
 static int asix_recv(struct eth_device *eth)
 {
 	struct ueth_data *dev = (struct ueth_data *)eth->priv;
@@ -542,7 +570,7 @@
 
 
 	rx_hdr = *(u32 *)(recv_buf + actual_len - 4);
-	le32_to_cpus(&pkt_hdr);
+	le32_to_cpus(&rx_hdr);
 
 	pkt_cnt = (u16)rx_hdr;
 	hdr_off = (u16)(rx_hdr >> 16);
@@ -596,6 +624,7 @@
 	{ 0x0df6, 0x0072, FLAG_TYPE_SITECOM },
 	{ 0x04e8, 0xa100, FLAG_TYPE_SAMSUNG },
 	{ 0x17ef, 0x304b, FLAG_TYPE_LENOVO },
+	{ 0x04b4, 0x3610, FLAG_TYPE_GX3 },
 	{ 0x0000, 0x0000, FLAG_NONE }	/* END - Do not remove */
 };
 
@@ -691,6 +720,8 @@
 int ax88179_eth_get_info(struct usb_device *dev, struct ueth_data *ss,
 				struct eth_device *eth)
 {
+	struct asix_private *dev_priv = (struct asix_private *)ss->dev_priv;
+
 	if (!eth) {
 		debug("%s: missing parameter.\n", __func__);
 		return 0;
@@ -700,16 +731,190 @@
 	eth->send = asix_send;
 	eth->recv = asix_recv;
 	eth->halt = asix_halt;
-	eth->write_hwaddr = asix_write_mac;
+	eth->write_hwaddr = asix_write_hwaddr;
 	eth->priv = ss;
 
-	if (asix_basic_reset(ss))
+	if (asix_basic_reset(ss, dev_priv))
 		return 0;
 
 	/* Get the MAC address */
-	if (asix_read_mac(eth))
+	if (asix_read_mac(ss, eth->enetaddr))
 		return 0;
 	debug("MAC %pM\n", eth->enetaddr);
 
 	return 1;
 }
+
+#else /* !CONFIG_DM_ETH */
+
+static int ax88179_eth_start(struct udevice *dev)
+{
+	struct asix_private *priv = dev_get_priv(dev);
+
+	return asix_init_common(&priv->ueth, priv);
+}
+
+void ax88179_eth_stop(struct udevice *dev)
+{
+	struct asix_private *priv = dev_get_priv(dev);
+	struct ueth_data *ueth = &priv->ueth;
+
+	debug("** %s()\n", __func__);
+
+	usb_ether_advance_rxbuf(ueth, -1);
+	priv->pkt_cnt = 0;
+	priv->pkt_data = NULL;
+	priv->pkt_hdr = NULL;
+}
+
+int ax88179_eth_send(struct udevice *dev, void *packet, int length)
+{
+	struct asix_private *priv = dev_get_priv(dev);
+
+	return asix_send_common(&priv->ueth, priv, packet, length);
+}
+
+int ax88179_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct asix_private *priv = dev_get_priv(dev);
+	struct ueth_data *ueth = &priv->ueth;
+	int ret, len;
+	u16 pkt_len;
+
+	/* No packet left, get a new one */
+	if (priv->pkt_cnt == 0) {
+		uint8_t *ptr;
+		u16 pkt_cnt;
+		u16 hdr_off;
+		u32 rx_hdr;
+
+		len = usb_ether_get_rx_bytes(ueth, &ptr);
+		debug("%s: first try, len=%d\n", __func__, len);
+		if (!len) {
+			if (!(flags & ETH_RECV_CHECK_DEVICE))
+				return -EAGAIN;
+
+			ret = usb_ether_receive(ueth, priv->rx_urb_size);
+			if (ret < 0)
+				return ret;
+
+			len = usb_ether_get_rx_bytes(ueth, &ptr);
+			debug("%s: second try, len=%d\n", __func__, len);
+		}
+
+		if (len < 4) {
+			usb_ether_advance_rxbuf(ueth, -1);
+			return -EMSGSIZE;
+		}
+
+		rx_hdr = *(u32 *)(ptr + len - 4);
+		le32_to_cpus(&rx_hdr);
+
+		pkt_cnt = (u16)rx_hdr;
+		if (pkt_cnt == 0) {
+			usb_ether_advance_rxbuf(ueth, -1);
+			return 0;
+		}
+
+		hdr_off = (u16)(rx_hdr >> 16);
+		if (hdr_off > len - 4) {
+			usb_ether_advance_rxbuf(ueth, -1);
+			return -EIO;
+		}
+
+		priv->pkt_cnt = pkt_cnt;
+		priv->pkt_data = ptr;
+		priv->pkt_hdr = (u32 *)(ptr + hdr_off);
+		debug("%s: %d packets received, pkt header at %d\n",
+		      __func__, (int)priv->pkt_cnt, (int)hdr_off);
+	}
+
+	le32_to_cpus(priv->pkt_hdr);
+	pkt_len = (*priv->pkt_hdr >> 16) & 0x1fff;
+
+	*packetp = priv->pkt_data + 2;
+
+	priv->pkt_data += (pkt_len + 7) & 0xFFF8;
+	priv->pkt_cnt--;
+	priv->pkt_hdr++;
+
+	debug("%s: return packet of %d bytes (%d packets left)\n",
+	      __func__, (int)pkt_len, priv->pkt_cnt);
+	return pkt_len;
+}
+
+static int ax88179_free_pkt(struct udevice *dev, uchar *packet, int packet_len)
+{
+	struct asix_private *priv = dev_get_priv(dev);
+	struct ueth_data *ueth = &priv->ueth;
+
+	if (priv->pkt_cnt == 0)
+		usb_ether_advance_rxbuf(ueth, -1);
+
+	return 0;
+}
+
+int ax88179_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct asix_private *priv = dev_get_priv(dev);
+	struct ueth_data *ueth = &priv->ueth;
+
+	return asix_write_mac(ueth, pdata->enetaddr);
+}
+
+static int ax88179_eth_probe(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct asix_private *priv = dev_get_priv(dev);
+	struct usb_device *usb_dev;
+	int ret;
+
+	priv->flags = dev->driver_data;
+	ret = usb_ether_register(dev, &priv->ueth, AX_RX_URB_SIZE);
+	if (ret)
+		return ret;
+
+	usb_dev = priv->ueth.pusb_dev;
+	priv->maxpacketsize = usb_dev->epmaxpacketout[AX_ENDPOINT_OUT];
+
+	/* Get the MAC address */
+	ret = asix_read_mac(&priv->ueth, pdata->enetaddr);
+	if (ret)
+		return ret;
+	debug("MAC %pM\n", pdata->enetaddr);
+
+	return 0;
+}
+
+static const struct eth_ops ax88179_eth_ops = {
+	.start = ax88179_eth_start,
+	.send = ax88179_eth_send,
+	.recv = ax88179_eth_recv,
+	.free_pkt = ax88179_free_pkt,
+	.stop = ax88179_eth_stop,
+	.write_hwaddr = ax88179_write_hwaddr,
+};
+
+U_BOOT_DRIVER(ax88179_eth) = {
+	.name = "ax88179_eth",
+	.id = UCLASS_ETH,
+	.probe = ax88179_eth_probe,
+	.ops = &ax88179_eth_ops,
+	.priv_auto_alloc_size = sizeof(struct asix_private),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
+
+static const struct usb_device_id ax88179_eth_id_table[] = {
+	{ USB_DEVICE(0x0b95, 0x1790), .driver_info = FLAG_TYPE_AX88179 },
+	{ USB_DEVICE(0x0b95, 0x178a), .driver_info = FLAG_TYPE_AX88178a },
+	{ USB_DEVICE(0x2001, 0x4a00), .driver_info = FLAG_TYPE_DLINK_DUB1312 },
+	{ USB_DEVICE(0x0df6, 0x0072), .driver_info = FLAG_TYPE_SITECOM },
+	{ USB_DEVICE(0x04e8, 0xa100), .driver_info = FLAG_TYPE_SAMSUNG },
+	{ USB_DEVICE(0x17ef, 0x304b), .driver_info = FLAG_TYPE_LENOVO },
+	{ USB_DEVICE(0x04b4, 0x3610), .driver_info = FLAG_TYPE_GX3 },
+	{ }		/* Terminating entry */
+};
+
+U_BOOT_USB_DEVICE(ax88179_eth, ax88179_eth_id_table);
+#endif /* !CONFIG_DM_ETH */
diff --git a/drivers/usb/eth/r8152.c b/drivers/usb/eth/r8152.c
index 325b70c..070aadf 100644
--- a/drivers/usb/eth/r8152.c
+++ b/drivers/usb/eth/r8152.c
@@ -3,9 +3,10 @@
  *
  * SPDX-License-Identifier:	GPL-2.0
  *
-  */
+ */
 
 #include <common.h>
+#include <dm.h>
 #include <errno.h>
 #include <malloc.h>
 #include <usb.h>
@@ -15,6 +16,7 @@
 #include "usb_ether.h"
 #include "r8152.h"
 
+#ifndef CONFIG_DM_ETH
 /* local vars */
 static int curr_eth_dev; /* index for name of next device detected */
 
@@ -23,12 +25,6 @@
 	unsigned short product;
 };
 
-struct r8152_version {
-	unsigned short tcr;
-	unsigned short version;
-	bool           gmii;
-};
-
 static const struct r8152_dongle const r8152_dongles[] = {
 	/* Realtek */
 	{ 0x0bda, 0x8050 },
@@ -54,6 +50,13 @@
 	/* Nvidia */
 	{ 0x0955, 0x09ff },
 };
+#endif
+
+struct r8152_version {
+	unsigned short tcr;
+	unsigned short version;
+	bool           gmii;
+};
 
 static const struct r8152_version const r8152_versions[] = {
 	{ 0x4c00, RTL_VER_01, 0 },
@@ -1176,11 +1179,8 @@
 	return ret;
 }
 
-static int r8152_init(struct eth_device *eth, bd_t *bd)
+static int r8152_init_common(struct r8152 *tp)
 {
-	struct ueth_data *dev = (struct ueth_data *)eth->priv;
-	struct r8152 *tp = (struct r8152 *)dev->dev_priv;
-
 	u8 speed;
 	int timeout = 0;
 	int link_detected;
@@ -1210,14 +1210,11 @@
 	return 0;
 }
 
-static int r8152_send(struct eth_device *eth, void *packet, int length)
+static int r8152_send_common(struct ueth_data *ueth, void *packet, int length)
 {
-	struct ueth_data *dev = (struct ueth_data *)eth->priv;
-
+	struct usb_device *udev = ueth->pusb_dev;
 	u32 opts1, opts2 = 0;
-
 	int err;
-
 	int actual_len;
 	unsigned char msg[PKTSIZE + sizeof(struct tx_desc)];
 	struct tx_desc *tx_desc = (struct tx_desc *)msg;
@@ -1231,18 +1228,31 @@
 
 	memcpy(msg + sizeof(struct tx_desc), (void *)packet, length);
 
-	err = usb_bulk_msg(dev->pusb_dev,
-				usb_sndbulkpipe(dev->pusb_dev, dev->ep_out),
-				(void *)msg,
-				length + sizeof(struct tx_desc),
-				&actual_len,
-				USB_BULK_SEND_TIMEOUT);
+	err = usb_bulk_msg(udev, usb_sndbulkpipe(udev, ueth->ep_out),
+			   (void *)msg, length + sizeof(struct tx_desc),
+			   &actual_len, USB_BULK_SEND_TIMEOUT);
 	debug("Tx: len = %zu, actual = %u, err = %d\n",
 	      length + sizeof(struct tx_desc), actual_len, err);
 
 	return err;
 }
 
+#ifndef CONFIG_DM_ETH
+static int r8152_init(struct eth_device *eth, bd_t *bd)
+{
+	struct ueth_data *dev = (struct ueth_data *)eth->priv;
+	struct r8152 *tp = (struct r8152 *)dev->dev_priv;
+
+	return r8152_init_common(tp);
+}
+
+static int r8152_send(struct eth_device *eth, void *packet, int length)
+{
+	struct ueth_data *dev = (struct ueth_data *)eth->priv;
+
+	return r8152_send_common(dev, packet, length);
+}
+
 static int r8152_recv(struct eth_device *eth)
 {
 	struct ueth_data *dev = (struct ueth_data *)eth->priv;
@@ -1454,3 +1464,186 @@
 	debug("MAC %pM\n", eth->enetaddr);
 	return 1;
 }
+#endif /* !CONFIG_DM_ETH */
+
+#ifdef CONFIG_DM_ETH
+static int r8152_eth_start(struct udevice *dev)
+{
+	struct r8152 *tp = dev_get_priv(dev);
+
+	debug("** %s (%d)\n", __func__, __LINE__);
+
+	return r8152_init_common(tp);
+}
+
+void r8152_eth_stop(struct udevice *dev)
+{
+	struct r8152 *tp = dev_get_priv(dev);
+
+	debug("** %s (%d)\n", __func__, __LINE__);
+
+	tp->rtl_ops.disable(tp);
+}
+
+int r8152_eth_send(struct udevice *dev, void *packet, int length)
+{
+	struct r8152 *tp = dev_get_priv(dev);
+
+	return r8152_send_common(&tp->ueth, packet, length);
+}
+
+int r8152_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct r8152 *tp = dev_get_priv(dev);
+	struct ueth_data *ueth = &tp->ueth;
+	uint8_t *ptr;
+	int ret, len;
+	struct rx_desc *rx_desc;
+	u16 packet_len;
+
+	len = usb_ether_get_rx_bytes(ueth, &ptr);
+	debug("%s: first try, len=%d\n", __func__, len);
+	if (!len) {
+		if (!(flags & ETH_RECV_CHECK_DEVICE))
+			return -EAGAIN;
+		ret = usb_ether_receive(ueth, RTL8152_AGG_BUF_SZ);
+		if (ret)
+			return ret;
+
+		len = usb_ether_get_rx_bytes(ueth, &ptr);
+		debug("%s: second try, len=%d\n", __func__, len);
+	}
+
+	rx_desc = (struct rx_desc *)ptr;
+	packet_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
+	packet_len -= CRC_SIZE;
+
+	if (packet_len > len - (sizeof(struct rx_desc) + CRC_SIZE)) {
+		debug("Rx: too large packet: %d\n", packet_len);
+		goto err;
+	}
+
+	*packetp = ptr + sizeof(struct rx_desc);
+	return packet_len;
+
+err:
+	usb_ether_advance_rxbuf(ueth, -1);
+	return -ENOSPC;
+}
+
+static int r8152_free_pkt(struct udevice *dev, uchar *packet, int packet_len)
+{
+	struct r8152 *tp = dev_get_priv(dev);
+
+	packet_len += sizeof(struct rx_desc) + CRC_SIZE;
+	packet_len = ALIGN(packet_len, 8);
+	usb_ether_advance_rxbuf(&tp->ueth, packet_len);
+
+	return 0;
+}
+
+static int r8152_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct r8152 *tp = dev_get_priv(dev);
+
+	unsigned char enetaddr[8] = { 0 };
+
+	debug("** %s (%d)\n", __func__, __LINE__);
+	memcpy(enetaddr, pdata->enetaddr, ETH_ALEN);
+
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
+	pla_ocp_write(tp, PLA_IDR, BYTE_EN_SIX_BYTES, 8, enetaddr);
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
+
+	debug("MAC %pM\n", pdata->enetaddr);
+	return 0;
+}
+
+int r8152_read_rom_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct r8152 *tp = dev_get_priv(dev);
+
+	debug("** %s (%d)\n", __func__, __LINE__);
+	r8152_read_mac(tp, pdata->enetaddr);
+	return 0;
+}
+
+static int r8152_eth_probe(struct udevice *dev)
+{
+	struct usb_device *udev = dev_get_parent_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct r8152 *tp = dev_get_priv(dev);
+	struct ueth_data *ueth = &tp->ueth;
+	int ret;
+
+	tp->udev = udev;
+	r8152_read_mac(tp, pdata->enetaddr);
+
+	r8152b_get_version(tp);
+
+	ret = rtl_ops_init(tp);
+	if (ret)
+		return ret;
+
+	tp->rtl_ops.init(tp);
+	tp->rtl_ops.up(tp);
+
+	rtl8152_set_speed(tp, AUTONEG_ENABLE,
+			  tp->supports_gmii ? SPEED_1000 : SPEED_100,
+			  DUPLEX_FULL);
+
+	return usb_ether_register(dev, ueth, RTL8152_AGG_BUF_SZ);
+}
+
+static const struct eth_ops r8152_eth_ops = {
+	.start	= r8152_eth_start,
+	.send	= r8152_eth_send,
+	.recv	= r8152_eth_recv,
+	.free_pkt = r8152_free_pkt,
+	.stop	= r8152_eth_stop,
+	.write_hwaddr = r8152_write_hwaddr,
+	.read_rom_hwaddr = r8152_read_rom_hwaddr,
+};
+
+U_BOOT_DRIVER(r8152_eth) = {
+	.name	= "r8152_eth",
+	.id	= UCLASS_ETH,
+	.probe = r8152_eth_probe,
+	.ops	= &r8152_eth_ops,
+	.priv_auto_alloc_size = sizeof(struct r8152),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
+
+static const struct usb_device_id r8152_eth_id_table[] = {
+	/* Realtek */
+	{ USB_DEVICE(0x0bda, 0x8050) },
+	{ USB_DEVICE(0x0bda, 0x8152) },
+	{ USB_DEVICE(0x0bda, 0x8153) },
+
+	/* Samsung */
+	{ USB_DEVICE(0x04e8, 0xa101) },
+
+	/* Lenovo */
+	{ USB_DEVICE(0x17ef, 0x304f) },
+	{ USB_DEVICE(0x17ef, 0x3052) },
+	{ USB_DEVICE(0x17ef, 0x3054) },
+	{ USB_DEVICE(0x17ef, 0x3057) },
+	{ USB_DEVICE(0x17ef, 0x7205) },
+	{ USB_DEVICE(0x17ef, 0x720a) },
+	{ USB_DEVICE(0x17ef, 0x720b) },
+	{ USB_DEVICE(0x17ef, 0x720c) },
+
+	/* TP-LINK */
+	{ USB_DEVICE(0x2357, 0x0601) },
+
+	/* Nvidia */
+	{ USB_DEVICE(0x0955, 0x09ff) },
+
+	{ }		/* Terminating entry */
+};
+
+U_BOOT_USB_DEVICE(r8152_eth, r8152_eth_id_table);
+#endif /* CONFIG_DM_ETH */
+
diff --git a/drivers/usb/eth/r8152.h b/drivers/usb/eth/r8152.h
index cd44da2..784ad99 100644
--- a/drivers/usb/eth/r8152.h
+++ b/drivers/usb/eth/r8152.h
@@ -594,6 +594,10 @@
 	u16 ocp_base;
 
 	u8 version;
+
+#ifdef CONFIG_DM_ETH
+	struct ueth_data ueth;
+#endif
 };
 
 int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
diff --git a/drivers/usb/eth/r8152_fw.c b/drivers/usb/eth/r8152_fw.c
index f820b16..b6c8228 100644
--- a/drivers/usb/eth/r8152_fw.c
+++ b/drivers/usb/eth/r8152_fw.c
@@ -5,7 +5,9 @@
  *
   */
 #include <common.h>
+#include <dm.h>
 #include <errno.h>
+#include "usb_ether.h"
 #include "r8152.h"
 
 static u8 r8152b_pla_patch_a[] = {
diff --git a/drivers/usb/eth/smsc95xx.c b/drivers/usb/eth/smsc95xx.c
index 08eaed5..7d9abfd 100644
--- a/drivers/usb/eth/smsc95xx.c
+++ b/drivers/usb/eth/smsc95xx.c
@@ -391,8 +391,8 @@
 					struct smsc95xx_private *priv,
 					unsigned char *enetaddr)
 {
-	u32 addr_lo = __get_unaligned_le32(&enetaddr[0]);
-	u32 addr_hi = __get_unaligned_le16(&enetaddr[4]);
+	u32 addr_lo = get_unaligned_le32(&enetaddr[0]);
+	u32 addr_hi = get_unaligned_le16(&enetaddr[4]);
 	int ret;
 
 	/* set hardware address */
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index ae62476..40839d8 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -43,6 +43,11 @@
 	  USBA is the integrated high-speed USB Device controller on
 	  the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
 
+config USB_GADGET_BCM_UDC_OTG_PHY
+	bool "Broadcom UDC OTG PHY"
+	help
+	  Enable the Broadcom UDC OTG physical device interface.
+
 config USB_GADGET_DWC2_OTG
 	bool "DesignWare USB2.0 HS OTG controller (gadget mode)"
 	select USB_GADGET_DUALSPEED
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c
index a23278d..029927f 100644
--- a/drivers/usb/gadget/dwc2_udc_otg.c
+++ b/drivers/usb/gadget/dwc2_udc_otg.c
@@ -403,6 +403,7 @@
 	int i;
 	unsigned int uTemp = writel(CORE_SOFT_RESET, &reg->grstctl);
 	uint32_t dflt_gusbcfg;
+	uint32_t rx_fifo_sz, tx_fifo_sz, np_tx_fifo_sz;
 
 	debug("Reseting OTG controller\n");
 
@@ -467,18 +468,27 @@
 	/* 10. Unmask device IN EP common interrupts*/
 	writel(DIEPMSK_INIT, &reg->diepmsk);
 
+	rx_fifo_sz = RX_FIFO_SIZE;
+	np_tx_fifo_sz = NPTX_FIFO_SIZE;
+	tx_fifo_sz = PTX_FIFO_SIZE;
+
+	if (dev->pdata->rx_fifo_sz)
+		rx_fifo_sz = dev->pdata->rx_fifo_sz;
+	if (dev->pdata->np_tx_fifo_sz)
+		np_tx_fifo_sz = dev->pdata->np_tx_fifo_sz;
+	if (dev->pdata->tx_fifo_sz)
+		tx_fifo_sz = dev->pdata->tx_fifo_sz;
+
 	/* 11. Set Rx FIFO Size (in 32-bit words) */
-	writel(RX_FIFO_SIZE >> 2, &reg->grxfsiz);
+	writel(rx_fifo_sz, &reg->grxfsiz);
 
 	/* 12. Set Non Periodic Tx FIFO Size */
-	writel((NPTX_FIFO_SIZE >> 2) << 16 | ((RX_FIFO_SIZE >> 2)) << 0,
+	writel((np_tx_fifo_sz << 16) | rx_fifo_sz,
 	       &reg->gnptxfsiz);
 
 	for (i = 1; i < DWC2_MAX_HW_ENDPOINTS; i++)
-		writel((PTX_FIFO_SIZE >> 2) << 16 |
-		       ((RX_FIFO_SIZE + NPTX_FIFO_SIZE +
-			 PTX_FIFO_SIZE*(i-1)) >> 2) << 0,
-		       &reg->dieptxf[i-1]);
+		writel((rx_fifo_sz + np_tx_fifo_sz + tx_fifo_sz*(i-1)) |
+			tx_fifo_sz << 16, &reg->dieptxf[i-1]);
 
 	/* Flush the RX FIFO */
 	writel(RX_FIFO_FLUSH, &reg->grstctl);
diff --git a/drivers/usb/gadget/dwc2_udc_otg_regs.h b/drivers/usb/gadget/dwc2_udc_otg_regs.h
index 78ec90e..c94396a 100644
--- a/drivers/usb/gadget/dwc2_udc_otg_regs.h
+++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h
@@ -130,9 +130,9 @@
 #define HIGH_SPEED_CONTROL_PKT_SIZE	64
 #define HIGH_SPEED_BULK_PKT_SIZE	512
 
-#define RX_FIFO_SIZE			(1024*4)
-#define NPTX_FIFO_SIZE			(1024*4)
-#define PTX_FIFO_SIZE			(1536*1)
+#define RX_FIFO_SIZE			(1024)
+#define NPTX_FIFO_SIZE			(1024)
+#define PTX_FIFO_SIZE			(384)
 
 #define DEPCTL_TXFNUM_0		(0x0<<22)
 #define DEPCTL_TXFNUM_1		(0x1<<22)
diff --git a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c
index 12f5c85..0d6d2fb 100644
--- a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c
+++ b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c
@@ -110,6 +110,9 @@
 
 	ctrl =  readl(&reg->out_endp[ep_num].doepctl);
 
+	invalidate_dcache_range((unsigned long) ep->dma_buf,
+				(unsigned long) ep->dma_buf + ep->len);
+
 	writel((unsigned int) ep->dma_buf, &reg->out_endp[ep_num].doepdma);
 	writel(DOEPT_SIZ_PKT_CNT(pktcnt) | DOEPT_SIZ_XFER_SIZE(length),
 	       &reg->out_endp[ep_num].doeptsiz);
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 89580cc..e0699d4 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -3,8 +3,12 @@
 #
 comment "USB Host Controller Drivers"
 
+config USB_HOST
+	bool
+
 config USB_XHCI_HCD
 	bool "xHCI HCD (USB 3.0) support"
+	select USB_HOST
 	---help---
 	  The eXtensible Host Controller Interface (xHCI) is standard for USB 3.0
 	  "SuperSpeed" host controller hardware.
@@ -24,18 +28,11 @@
 	  Say Y or if your system has a Dual Role SuperSpeed
 	  USB controller based on the DesignWare USB3 IP Core.
 
-endif
-
-config USB_OHCI_GENERIC
-	bool "Support for generic OHCI USB controller"
-	depends on OF_CONTROL
-	depends on DM_USB
-	default n
-	---help---
-	  Enables support for generic OHCI controller.
+endif # USB_XHCI_HCD
 
 config USB_EHCI_HCD
 	bool "EHCI HCD (USB 2.0) support"
+	select USB_HOST
 	---help---
 	  The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0
 	  "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware.
@@ -60,6 +57,13 @@
 
 if USB_EHCI_HCD
 
+config USB_EHCI_ATMEL
+	bool  "Support for Atmel on-chip EHCI USB controller"
+	depends on ARCH_AT91
+	default y
+	---help---
+	  Enables support for the on-chip EHCI controller on Atmel chips.
+
 config USB_EHCI_MARVELL
 	bool "Support for MVEBU (AXP / A38x) on-chip EHCI USB controller"
 	depends on ARCH_MVEBU
@@ -74,6 +78,22 @@
 	---help---
 	  Enables support for the on-chip EHCI controller on i.MX6 SoCs.
 
+config USB_EHCI_MX7
+	bool "Support for i.MX7 on-chip EHCI USB controller"
+	depends on ARCH_MX7
+	default y
+	---help---
+	  Enables support for the on-chip EHCI controller on i.MX7 SoCs.
+
+if USB_EHCI_MX7
+
+config MXC_USB_OTG_HACTIVE
+	bool "USB Power pin high active"
+	---help---
+	  Set the USB Power pin polarity to be high active (PWR_POL)
+
+endif
+
 config USB_EHCI_MSM
 	bool "Support for Qualcomm on-chip EHCI USB controller"
 	depends on DM_USB
@@ -85,6 +105,13 @@
 	  This driver supports combination of Chipidea USB controller
 	  and Synapsys USB PHY in host mode only.
 
+config USB_EHCI_ZYNQ
+	bool "Support for Xilinx Zynq on-chip EHCI USB controller"
+	depends on ARCH_ZYNQ
+	default y
+	---help---
+	  Enable support for Zynq on-chip EHCI USB controller
+
 config USB_EHCI_GENERIC
 	bool "Support for generic EHCI USB controller"
 	depends on OF_CONTROL
@@ -93,4 +120,46 @@
 	---help---
 	  Enables support for generic EHCI controller.
 
-endif
+endif # USB_EHCI_HCD
+
+config USB_OHCI_HCD
+	bool "OHCI HCD (USB 1.1) support"
+	---help---
+	  The Open Host Controller Interface (OHCI) is a standard for accessing
+	  USB 1.1 host controller hardware.  It does more in hardware than Intel's
+	  UHCI specification.  If your USB host controller follows the OHCI spec,
+	  say Y.  On most non-x86 systems, and on x86 hardware that's not using a
+	  USB controller from Intel or VIA, this is appropriate.  If your host
+	  controller doesn't use PCI, this is probably appropriate.  For a PCI
+	  based system where you're not sure, the "lspci -v" entry will list the
+	  right "prog-if" for your USB controller(s):  EHCI, OHCI, or UHCI.
+
+if USB_OHCI_HCD
+
+config USB_OHCI_GENERIC
+	bool "Support for generic OHCI USB controller"
+	depends on OF_CONTROL
+	depends on DM_USB
+	select USB_HOST
+	---help---
+	  Enables support for generic OHCI controller.
+
+endif # USB_OHCI_HCD
+
+config USB_UHCI_HCD
+	bool "UHCI HCD (most Intel and VIA) support"
+	select USB_HOST
+	---help---
+	  The Universal Host Controller Interface is a standard by Intel for
+	  accessing the USB hardware in the PC (which is also called the USB
+	  host controller). If your USB host controller conforms to this
+	  standard, you may want to say Y, but see below. All recent boards
+	  with Intel PCI chipsets (like intel 430TX, 440FX, 440LX, 440BX,
+	  i810, i820) conform to this standard. Also all VIA PCI chipsets
+	  (like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro
+	  133) and LEON/GRLIB SoCs with the GRUSBHC controller.
+	  If unsure, say Y.
+
+if USB_UHCI_HCD
+
+endif # USB_UHCI_HCD
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 1d7d280..d65bbe9 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -7,12 +7,18 @@
  */
 
 #include <common.h>
+#include <clk.h>
+#include <dm.h>
 #include <usb.h>
 #include <asm/io.h>
 #include <asm/arch/clk.h>
 
 #include "ehci.h"
 
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_DM_USB
+
 int ehci_hcd_init(int index, enum usb_init_type init,
 		struct ehci_hccr **hccr, struct ehci_hcor **hcor)
 {
@@ -41,3 +47,113 @@
 
 	return 0;
 }
+
+#else
+
+struct ehci_atmel_priv {
+	struct ehci_ctrl ehci;
+};
+
+static int ehci_atmel_enable_clk(struct udevice *dev)
+{
+	struct udevice *dev_clk;
+	struct clk clk;
+	int periph;
+	int ret;
+
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret)
+		return ret;
+
+	ret = clk_enable(&clk);
+	if (ret)
+		return ret;
+
+	ret = clk_get_by_index(dev, 1, &clk);
+	if (ret)
+		return -EINVAL;
+
+	periph = fdtdec_get_uint(gd->fdt_blob, clk.dev->of_offset, "reg", -1);
+	if (periph < 0)
+		return -EINVAL;
+
+	dev_clk = dev_get_parent(clk.dev);
+	if (!dev_clk)
+		return -ENODEV;
+
+	ret = clk_request(dev_clk, &clk);
+	if (ret)
+		return ret;
+
+	clk.id = periph;
+	ret = clk_enable(&clk);
+	if (ret)
+		return ret;
+
+	clk_free(&clk);
+
+	return 0;
+}
+
+static int ehci_atmel_probe(struct udevice *dev)
+{
+	struct ehci_hccr *hccr;
+	struct ehci_hcor *hcor;
+	fdt_addr_t hcd_base;
+	int ret;
+
+	ret = ehci_atmel_enable_clk(dev);
+	if (ret) {
+		debug("Failed to enable USB Host clock\n");
+		return ret;
+	}
+
+	/*
+	 * Get the base address for EHCI controller from the device node
+	 */
+	hcd_base = dev_get_addr(dev);
+	if (hcd_base == FDT_ADDR_T_NONE) {
+		debug("Can't get the EHCI register base address\n");
+		return -ENXIO;
+	}
+
+	hccr = (struct ehci_hccr *)hcd_base;
+	hcor = (struct ehci_hcor *)
+		((u32)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+	debug("echi-atmel: init hccr %x and hcor %x hc_length %d\n",
+	      (u32)hccr, (u32)hcor,
+	      (u32)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+	return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
+}
+
+static int ehci_atmel_remove(struct udevice *dev)
+{
+	int ret;
+
+	ret = ehci_deregister(dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct udevice_id ehci_usb_ids[] = {
+	{ .compatible = "atmel,at91sam9g45-ehci", },
+	{ }
+};
+
+U_BOOT_DRIVER(ehci_atmel) = {
+	.name		= "ehci_atmel",
+	.id		= UCLASS_USB,
+	.of_match	= ehci_usb_ids,
+	.probe		= ehci_atmel_probe,
+	.remove		= ehci_atmel_remove,
+	.ops		= &ehci_usb_ops,
+	.platdata_auto_alloc_size = sizeof(struct usb_platdata),
+	.priv_auto_alloc_size = sizeof(struct ehci_atmel_priv),
+	.flags		= DM_FLAG_ALLOC_PRIV_DMA,
+};
+
+#endif
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index fa916ed..f5e3ae7 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2009, 2011 Freescale Semiconductor, Inc.
+ * (C) Copyright 2009, 2011, 2016 Freescale Semiconductor, Inc.
  *
  * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB
  *
@@ -16,14 +16,32 @@
 #include <hwconfig.h>
 #include <fsl_usb.h>
 #include <fdt_support.h>
+#include <dm.h>
 
 #include "ehci.h"
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
 #define CONFIG_USB_MAX_CONTROLLER_COUNT 1
 #endif
 
+#ifdef CONFIG_DM_USB
+struct ehci_fsl_priv {
+	struct ehci_ctrl ehci;
+	fdt_addr_t hcd_base;
+	char *phy_type;
+};
+#endif
+
 static void set_txfifothresh(struct usb_ehci *, u32);
+#ifdef CONFIG_DM_USB
+static int ehci_fsl_init(struct ehci_fsl_priv *priv, struct usb_ehci *ehci,
+		  struct ehci_hccr *hccr, struct ehci_hcor *hcor);
+#else
+static int ehci_fsl_init(int index, struct usb_ehci *ehci,
+			 struct ehci_hccr *hccr, struct ehci_hcor *hcor);
+#endif
 
 /* Check USB PHY clock valid */
 static int usb_phy_clk_valid(struct usb_ehci *ehci)
@@ -35,8 +53,101 @@
 	} else {
 		return 1;
 	}
+}
+
+#ifdef CONFIG_DM_USB
+static int ehci_fsl_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ehci_fsl_priv *priv = dev_get_priv(dev);
+	const void *prop;
+
+	prop = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy_type",
+			   NULL);
+	if (prop) {
+		priv->phy_type = (char *)prop;
+		debug("phy_type %s\n", priv->phy_type);
+	}
+
+	return 0;
+}
+
+static int ehci_fsl_init_after_reset(struct ehci_ctrl *ctrl)
+{
+	struct usb_ehci *ehci = NULL;
+	struct ehci_fsl_priv *priv = container_of(ctrl, struct ehci_fsl_priv,
+						   ehci);
+
+	ehci = (struct usb_ehci *)priv->hcd_base;
+	if (ehci_fsl_init(priv, ehci, priv->ehci.hccr, priv->ehci.hcor) < 0)
+		return -ENXIO;
+
+	return 0;
+}
+
+static const struct ehci_ops fsl_ehci_ops = {
+	.init_after_reset = ehci_fsl_init_after_reset,
+};
+
+static int ehci_fsl_probe(struct udevice *dev)
+{
+	struct ehci_fsl_priv *priv = dev_get_priv(dev);
+	struct usb_ehci *ehci = NULL;
+	struct ehci_hccr *hccr;
+	struct ehci_hcor *hcor;
+
+	/*
+	 * Get the base address for EHCI controller from the device node
+	 */
+	priv->hcd_base = dev_get_addr(dev);
+	if (priv->hcd_base == FDT_ADDR_T_NONE) {
+		debug("Can't get the EHCI register base address\n");
+		return -ENXIO;
+	}
+	ehci = (struct usb_ehci *)priv->hcd_base;
+	hccr = (struct ehci_hccr *)(&ehci->caplength);
+	hcor = (struct ehci_hcor *)
+		((u32)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+	if (ehci_fsl_init(priv, ehci, hccr, hcor) < 0)
+		return -ENXIO;
+
+	debug("ehci-fsl: init hccr %x and hcor %x hc_length %d\n",
+	      (u32)hccr, (u32)hcor,
+	      (u32)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+	return ehci_register(dev, hccr, hcor, &fsl_ehci_ops, 0, USB_INIT_HOST);
 }
 
+static int ehci_fsl_remove(struct udevice *dev)
+{
+	int ret;
+
+	ret = ehci_deregister(dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct udevice_id ehci_usb_ids[] = {
+	{ .compatible = "fsl-usb2-mph", },
+	{ .compatible = "fsl-usb2-dr", },
+	{ }
+};
+
+U_BOOT_DRIVER(ehci_fsl) = {
+	.name	= "ehci_fsl",
+	.id	= UCLASS_USB,
+	.of_match = ehci_usb_ids,
+	.ofdata_to_platdata = ehci_fsl_ofdata_to_platdata,
+	.probe = ehci_fsl_probe,
+	.remove = ehci_fsl_remove,
+	.ops	= &ehci_usb_ops,
+	.platdata_auto_alloc_size = sizeof(struct usb_platdata),
+	.priv_auto_alloc_size = sizeof(struct ehci_fsl_priv),
+	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
+};
+#else
 /*
  * Create the appropriate control structures to manage
  * a new EHCI host controller.
@@ -47,9 +158,49 @@
 		struct ehci_hccr **hccr, struct ehci_hcor **hcor)
 {
 	struct usb_ehci *ehci = NULL;
+
+	switch (index) {
+	case 0:
+		ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB1_ADDR;
+		break;
+	case 1:
+		ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB2_ADDR;
+		break;
+	default:
+		printf("ERROR: wrong controller index!!\n");
+		return -EINVAL;
+	};
+
+	*hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
+	*hcor = (struct ehci_hcor *)((uint32_t) *hccr +
+			HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
+
+	return ehci_fsl_init(index, ehci, *hccr, *hcor);
+}
+
+/*
+ * Destroy the appropriate control structures corresponding
+ * the the EHCI host controller.
+ */
+int ehci_hcd_stop(int index)
+{
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_DM_USB
+static int ehci_fsl_init(struct ehci_fsl_priv *priv, struct usb_ehci *ehci,
+		  struct ehci_hccr *hccr, struct ehci_hcor *hcor)
+#else
+static int ehci_fsl_init(int index, struct usb_ehci *ehci,
+			 struct ehci_hccr *hccr, struct ehci_hcor *hcor)
+#endif
+{
 	const char *phy_type = NULL;
+#ifndef CONFIG_DM_USB
 	size_t len;
 	char current_usb_controller[5];
+#endif
 #ifdef CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
 	char usb_phy[5];
 
@@ -64,25 +215,6 @@
 		 */
 		mdelay(5);
 	}
-	memset(current_usb_controller, '\0', 5);
-	snprintf(current_usb_controller, sizeof(current_usb_controller),
-		 "usb%d", index+1);
-
-	switch (index) {
-	case 0:
-		ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB1_ADDR;
-		break;
-	case 1:
-		ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB2_ADDR;
-		break;
-	default:
-		printf("ERROR: wrong controller index!!\n");
-		return -EINVAL;
-	};
-
-	*hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
-	*hcor = (struct ehci_hcor *)((uint32_t) *hccr +
-			HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
 
 	/* Set to Host mode */
 	setbits_le32(&ehci->usbmode, CM_HOST);
@@ -91,9 +223,18 @@
 	out_be32(&ehci->snoop2, 0x80000000 | SNOOP_SIZE_2GB);
 
 	/* Init phy */
+#ifdef CONFIG_DM_USB
+	if (priv->phy_type)
+		phy_type = priv->phy_type;
+#else
+	memset(current_usb_controller, '\0', 5);
+	snprintf(current_usb_controller, sizeof(current_usb_controller),
+		 "usb%d", index+1);
+
 	if (hwconfig_sub(current_usb_controller, "phy_type"))
 		phy_type = hwconfig_subarg(current_usb_controller,
 				"phy_type", &len);
+#endif
 	else
 		phy_type = getenv("usb_phy_type");
 
@@ -116,7 +257,7 @@
 				UTMI_PHY_EN);
 		udelay(1000); /* delay required for PHY Clk to appear */
 #endif
-		out_le32(&(*hcor)->or_portsc[0], PORT_PTS_UTMI);
+		out_le32(&(hcor)->or_portsc[0], PORT_PTS_UTMI);
 		clrsetbits_be32(&ehci->control, CONTROL_REGISTER_W1C_MASK,
 				USB_EN);
 	} else {
@@ -127,7 +268,7 @@
 		udelay(1000); /* delay required for PHY Clk to appear */
 		if (!usb_phy_clk_valid(ehci))
 			return -EINVAL;
-		out_le32(&(*hcor)->or_portsc[0], PORT_PTS_ULPI);
+		out_le32(&(hcor)->or_portsc[0], PORT_PTS_ULPI);
 	}
 
 	out_be32(&ehci->prictrl, 0x0000000c);
@@ -153,15 +294,6 @@
 }
 
 /*
- * Destroy the appropriate control structures corresponding
- * the the EHCI host controller.
- */
-int ehci_hcd_stop(int index)
-{
-	return 0;
-}
-
-/*
  * Setting the value of TXFIFO_THRESH field in TXFILLTUNING register
  * to counter DDR latencies in writing data into Tx buffer.
  * This prevents Tx buffer from getting underrun
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index 069f116..602fec5 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -15,6 +15,7 @@
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/clock.h>
 #include <asm/imx-common/iomux-v3.h>
+#include <dm.h>
 
 #include "ehci.h"
 
@@ -49,7 +50,7 @@
 #define USBNC_OFFSET		0x200
 #define USBNC_PHYSTATUS_ID_DIG	(1 << 4) /* otg_id status */
 #define USBNC_PHYCFG2_ACAENB	(1 << 4) /* otg_id detection enable */
-#define UCTRL_PM                (1 << 9) /* OTG Power Mask */
+#define UCTRL_PWR_POL		(1 << 9) /* OTG Polarity of Power Pin */
 #define UCTRL_OVER_CUR_POL	(1 << 8) /* OTG Polarity of Overcurrent */
 #define UCTRL_OVER_CUR_DIS	(1 << 7) /* Disable OTG Overcurrent Detection */
 
@@ -207,12 +208,20 @@
 	struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
 			(0x10000 * index) + USBNC_OFFSET);
 	void __iomem *phy_cfg2 = (void __iomem *)(&usbnc->phy_cfg2);
+	void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl1);
 
 	/*
 	 * Clear the ACAENB to enable usb_otg_id detection,
 	 * otherwise it is the ACA detection enabled.
 	 */
 	clrbits_le32(phy_cfg2, USBNC_PHYCFG2_ACAENB);
+
+	/* Set power polarity to high active */
+#ifdef CONFIG_MXC_USB_OTG_HACTIVE
+	setbits_le32(ctrl, UCTRL_PWR_POL);
+#else
+	clrbits_le32(ctrl, UCTRL_PWR_POL);
+#endif
 }
 
 int usb_phy_mode(int port)
@@ -250,11 +259,7 @@
 	setbits_le32(ctrl, UCTRL_OVER_CUR_POL);
 #endif
 
-#if defined(CONFIG_MX6)
 	setbits_le32(ctrl, UCTRL_OVER_CUR_DIS);
-#elif defined(CONFIG_MX7)
-	setbits_le32(ctrl, UCTRL_OVER_CUR_DIS | UCTRL_PM);
-#endif
 }
 
 /**
@@ -303,6 +308,30 @@
 	return 0;
 }
 
+int ehci_mx6_common_init(struct usb_ehci *ehci, int index)
+{
+	int ret;
+
+	enable_usboh3_clk(1);
+	mdelay(1);
+
+	/* Do board specific initialization */
+	ret = board_ehci_hcd_init(index);
+	if (ret)
+		return ret;
+
+	usb_power_config(index);
+	usb_oc_config(index);
+
+#if defined(CONFIG_MX6)
+	usb_internal_phy_clock_gate(index, 1);
+	usb_phy_enable(index, ehci);
+#endif
+
+	return 0;
+}
+
+#ifndef CONFIG_DM_USB
 int ehci_hcd_init(int index, enum usb_init_type init,
 		struct ehci_hccr **hccr, struct ehci_hcor **hcor)
 {
@@ -318,26 +347,18 @@
 
 	if (index > 3)
 		return -EINVAL;
-	enable_usboh3_clk(1);
-	mdelay(1);
 
-	/* Do board specific initialization */
-	ret = board_ehci_hcd_init(index);
+	ret = ehci_mx6_common_init(ehci, index);
 	if (ret)
 		return ret;
 
-	usb_power_config(index);
-	usb_oc_config(index);
-
-#if defined(CONFIG_MX6)
-	usb_internal_phy_clock_gate(index, 1);
-	usb_phy_enable(index, ehci);
-#endif
 	type = board_usb_phy_mode(index);
 
-	*hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
-	*hcor = (struct ehci_hcor *)((uint32_t)*hccr +
-			HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
+	if (hccr && hcor) {
+		*hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
+		*hcor = (struct ehci_hcor *)((uint32_t)*hccr +
+				HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
+	}
 
 	if ((type == init) || (type == USB_INIT_DEVICE))
 		board_ehci_power(index, (type == USB_INIT_DEVICE) ? 0 : 1);
@@ -359,3 +380,102 @@
 {
 	return 0;
 }
+#else
+struct ehci_mx6_priv_data {
+	struct ehci_ctrl ctrl;
+	struct usb_ehci *ehci;
+	enum usb_init_type init_type;
+	int portnr;
+};
+
+static int mx6_init_after_reset(struct ehci_ctrl *dev)
+{
+	struct ehci_mx6_priv_data *priv = dev->priv;
+	enum usb_init_type type = priv->init_type;
+	struct usb_ehci *ehci = priv->ehci;
+	int ret;
+
+	ret = ehci_mx6_common_init(priv->ehci, priv->portnr);
+	if (ret)
+		return ret;
+
+	board_ehci_power(priv->portnr, (type == USB_INIT_DEVICE) ? 0 : 1);
+
+	if (type == USB_INIT_DEVICE)
+		return 0;
+
+	setbits_le32(&ehci->usbmode, CM_HOST);
+	writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
+	setbits_le32(&ehci->portsc, USB_EN);
+
+	mdelay(10);
+
+	return 0;
+}
+
+static const struct ehci_ops mx6_ehci_ops = {
+	.init_after_reset = mx6_init_after_reset
+};
+
+static int ehci_usb_probe(struct udevice *dev)
+{
+	struct usb_platdata *plat = dev_get_platdata(dev);
+	struct usb_ehci *ehci = (struct usb_ehci *)dev_get_addr(dev);
+	struct ehci_mx6_priv_data *priv = dev_get_priv(dev);
+	struct ehci_hccr *hccr;
+	struct ehci_hcor *hcor;
+	int ret;
+
+	priv->ehci = ehci;
+	priv->portnr = dev->seq;
+	priv->init_type = plat->init_type;
+
+	ret = ehci_mx6_common_init(ehci, priv->portnr);
+	if (ret)
+		return ret;
+
+	board_ehci_power(priv->portnr, (priv->init_type == USB_INIT_DEVICE) ? 0 : 1);
+
+	if (priv->init_type == USB_INIT_HOST) {
+		setbits_le32(&ehci->usbmode, CM_HOST);
+		writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
+		setbits_le32(&ehci->portsc, USB_EN);
+	}
+
+	mdelay(10);
+
+	hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
+	hcor = (struct ehci_hcor *)((uint32_t)hccr +
+			HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
+
+	return ehci_register(dev, hccr, hcor, &mx6_ehci_ops, 0, priv->init_type);
+}
+
+static int ehci_usb_remove(struct udevice *dev)
+{
+	int ret;
+
+	ret = ehci_deregister(dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct udevice_id mx6_usb_ids[] = {
+	{ .compatible = "fsl,imx27-usb" },
+	{ }
+};
+
+U_BOOT_DRIVER(usb_mx6) = {
+	.name	= "ehci_mx6",
+	.id	= UCLASS_USB,
+	.of_match = mx6_usb_ids,
+	.probe	= ehci_usb_probe,
+	.remove = ehci_usb_remove,
+	.ops	= &ehci_usb_ops,
+	.platdata_auto_alloc_size = sizeof(struct usb_platdata),
+	.priv_auto_alloc_size = sizeof(struct ehci_mx6_priv_data),
+	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
+};
+#endif
diff --git a/drivers/usb/host/ehci-zynq.c b/drivers/usb/host/ehci-zynq.c
index 37a7935..76642cd 100644
--- a/drivers/usb/host/ehci-zynq.c
+++ b/drivers/usb/host/ehci-zynq.c
@@ -7,55 +7,48 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <usb.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/io.h>
-#include <usb.h>
 #include <usb/ehci-ci.h>
 #include <usb/ulpi.h>
 
 #include "ehci.h"
 
-#define ZYNQ_USB_USBCMD_RST			0x0000002
-#define ZYNQ_USB_USBCMD_STOP			0x0000000
-#define ZYNQ_USB_NUM_MIO			12
+struct zynq_ehci_priv {
+	struct ehci_ctrl ehcictrl;
+	struct usb_ehci *ehci;
+};
 
-/*
- * Create the appropriate control structures to manage
- * a new EHCI host controller.
- */
-int ehci_hcd_init(int index,  enum usb_init_type init, struct ehci_hccr **hccr,
-		  struct ehci_hcor **hcor)
+static int ehci_zynq_ofdata_to_platdata(struct udevice *dev)
 {
-	struct usb_ehci *ehci;
+	struct zynq_ehci_priv *priv = dev_get_priv(dev);
+
+	priv->ehci = (struct usb_ehci *)dev_get_addr_ptr(dev);
+	if (!priv->ehci)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int ehci_zynq_probe(struct udevice *dev)
+{
+	struct usb_platdata *plat = dev_get_platdata(dev);
+	struct zynq_ehci_priv *priv = dev_get_priv(dev);
+	struct ehci_hccr *hccr;
+	struct ehci_hcor *hcor;
 	struct ulpi_viewport ulpi_vp;
-	int ret, mio_usb;
 	/* Used for writing the ULPI data address */
 	struct ulpi_regs *ulpi = (struct ulpi_regs *)0;
-
-	if (!index) {
-		mio_usb = zynq_slcr_get_mio_pin_status("usb0");
-		if (mio_usb != ZYNQ_USB_NUM_MIO) {
-			printf("usb0 wrong num MIO: %d, Index %d\n", mio_usb,
-			       index);
-			return -1;
-		}
-		ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR0;
-	} else {
-		mio_usb = zynq_slcr_get_mio_pin_status("usb1");
-		if (mio_usb != ZYNQ_USB_NUM_MIO) {
-			printf("usb1 wrong num MIO: %d, Index %d\n", mio_usb,
-			       index);
-			return -1;
-		}
-		ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR1;
-	}
+	int ret;
 
-	*hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
-	*hcor = (struct ehci_hcor *)((uint32_t) *hccr +
-			HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
+	hccr = (struct ehci_hccr *)((uint32_t)&priv->ehci->caplength);
+	hcor = (struct ehci_hcor *)((uint32_t) hccr +
+			HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
 
-	ulpi_vp.viewport_addr = (u32)&ehci->ulpi_viewpoint;
+	ulpi_vp.viewport_addr = (u32)&priv->ehci->ulpi_viewpoint;
 	ulpi_vp.port_num = 0;
 
 	ret = ulpi_init(&ulpi_vp);
@@ -77,28 +70,34 @@
 	ulpi_write(&ulpi_vp, &ulpi->otg_ctrl_set,
 		   ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
-	return 0;
+	return ehci_register(dev, hccr, hcor, NULL, 0, plat->init_type);
 }
 
-/*
- * Destroy the appropriate control structures corresponding
- * the the EHCI host controller.
- */
-int ehci_hcd_stop(int index)
+static int ehci_zynq_remove(struct udevice *dev)
 {
-	struct usb_ehci *ehci;
+	int ret;
 
-	if (!index)
-		ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR0;
-	else
-		ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR1;
-
-	/* Stop controller */
-	writel(ZYNQ_USB_USBCMD_STOP, &ehci->usbcmd);
-	udelay(1000);
-
-	/* Initiate controller reset */
-	writel(ZYNQ_USB_USBCMD_RST, &ehci->usbcmd);
+	ret = ehci_deregister(dev);
+	if (ret)
+		return ret;
 
 	return 0;
 }
+
+static const struct udevice_id ehci_zynq_ids[] = {
+	{ .compatible = "xlnx,zynq-usb-2.20a" },
+	{ }
+};
+
+U_BOOT_DRIVER(ehci_zynq) = {
+	.name	= "ehci_zynq",
+	.id	= UCLASS_USB,
+	.of_match = ehci_zynq_ids,
+	.ofdata_to_platdata = ehci_zynq_ofdata_to_platdata,
+	.probe = ehci_zynq_probe,
+	.remove = ehci_zynq_remove,
+	.ops	= &ehci_usb_ops,
+	.platdata_auto_alloc_size = sizeof(struct usb_platdata),
+	.priv_auto_alloc_size = sizeof(struct zynq_ehci_priv),
+	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
+};
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c
index 69c9a50..be114fc 100644
--- a/drivers/usb/host/usb-uclass.c
+++ b/drivers/usb/host/usb-uclass.c
@@ -14,7 +14,6 @@
 #include <usb.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
-#include <dm/root.h>
 #include <dm/uclass-internal.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -349,12 +348,6 @@
 }
 #endif
 
-int usb_post_bind(struct udevice *dev)
-{
-	/* Scan the bus for devices */
-	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
-}
-
 int usb_setup_ehci_gadget(struct ehci_ctrl **ctlrp)
 {
 	struct usb_platdata *plat;
@@ -768,7 +761,7 @@
 	.id		= UCLASS_USB,
 	.name		= "usb",
 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
-	.post_bind	= usb_post_bind,
+	.post_bind	= dm_scan_fdt_dev,
 	.priv_auto_alloc_size = sizeof(struct usb_uclass_priv),
 	.per_child_auto_alloc_size = sizeof(struct usb_device),
 	.per_device_auto_alloc_size = sizeof(struct usb_bus_priv),
diff --git a/drivers/usb/host/xhci-fsl.c b/drivers/usb/host/xhci-fsl.c
index c12a189..bdcd4f1 100644
--- a/drivers/usb/host/xhci-fsl.c
+++ b/drivers/usb/host/xhci-fsl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015 Freescale Semiconductor, Inc.
+ * Copyright 2015,2016 Freescale Semiconductor, Inc.
  *
  * FSL USB HOST xHCI Controller
  *
@@ -17,12 +17,21 @@
 #include "xhci.h"
 #include <fsl_errata.h>
 #include <fsl_usb.h>
+#include <dm.h>
 
 /* Declare global data pointer */
 DECLARE_GLOBAL_DATA_PTR;
 
+#ifndef CONFIG_DM_USB
 static struct fsl_xhci fsl_xhci;
 unsigned long ctr_addr[] = FSL_USB_XHCI_ADDR;
+#else
+struct xhci_fsl_priv {
+	struct xhci_ctrl xhci;
+	fdt_addr_t hcd_base;
+	struct fsl_xhci ctx;
+};
+#endif
 
 __weak int __board_usb_init(int index, enum usb_init_type init)
 {
@@ -77,6 +86,77 @@
 	return 0;
 }
 
+#ifdef CONFIG_DM_USB
+static int xhci_fsl_probe(struct udevice *dev)
+{
+	struct xhci_fsl_priv *priv = dev_get_priv(dev);
+	struct xhci_hccr *hccr;
+	struct xhci_hcor *hcor;
+
+	int ret = 0;
+
+	/*
+	 * Get the base address for XHCI controller from the device node
+	 */
+	priv->hcd_base = dev_get_addr(dev);
+	if (priv->hcd_base == FDT_ADDR_T_NONE) {
+		debug("Can't get the XHCI register base address\n");
+		return -ENXIO;
+	}
+	priv->ctx.hcd = (struct xhci_hccr *)priv->hcd_base;
+	priv->ctx.dwc3_reg = (struct dwc3 *)((char *)(priv->hcd_base) +
+			  DWC3_REG_OFFSET);
+
+	fsl_apply_xhci_errata();
+
+	ret = fsl_xhci_core_init(&priv->ctx);
+	if (ret < 0) {
+		puts("Failed to initialize xhci\n");
+		return ret;
+	}
+
+	hccr = (struct xhci_hccr *)(priv->ctx.hcd);
+	hcor = (struct xhci_hcor *)((uintptr_t) hccr
+				+ HC_LENGTH(xhci_readl(&hccr->cr_capbase)));
+
+	debug("xhci-fsl: init hccr %lx and hcor %lx hc_length %lx\n",
+	      (uintptr_t)hccr, (uintptr_t)hcor,
+	      (uintptr_t)HC_LENGTH(xhci_readl(&hccr->cr_capbase)));
+
+	return xhci_register(dev, hccr, hcor);
+}
+
+static int xhci_fsl_remove(struct udevice *dev)
+{
+	struct xhci_fsl_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	fsl_xhci_core_exit(&priv->ctx);
+
+	ret = xhci_deregister(dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct udevice_id xhci_usb_ids[] = {
+	{ .compatible = "fsl,layerscape-dwc3", },
+	{ }
+};
+
+U_BOOT_DRIVER(xhci_fsl) = {
+	.name	= "xhci_fsl",
+	.id	= UCLASS_USB,
+	.of_match = xhci_usb_ids,
+	.probe = xhci_fsl_probe,
+	.remove = xhci_fsl_remove,
+	.ops	= &xhci_usb_ops,
+	.platdata_auto_alloc_size = sizeof(struct usb_platdata),
+	.priv_auto_alloc_size = sizeof(struct xhci_fsl_priv),
+	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
+};
+#else
 int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor)
 {
 	struct fsl_xhci *ctx = &fsl_xhci;
@@ -116,3 +196,4 @@
 
 	fsl_xhci_core_exit(ctx);
 }
+#endif
diff --git a/drivers/usb/musb-new/musb_dsps.c b/drivers/usb/musb-new/musb_dsps.c
index bb7c952..a71db76 100644
--- a/drivers/usb/musb-new/musb_dsps.c
+++ b/drivers/usb/musb-new/musb_dsps.c
@@ -627,7 +627,7 @@
 	/* get memory resource */
 	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!iomem) {
-		dev_err(&pdev->dev, "failed to get usbss mem resourse\n");
+		dev_err(&pdev->dev, "failed to get usbss mem resource\n");
 		ret = -ENODEV;
 		goto err1;
 	}
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index 93d147e..4e548c2 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -7,3 +7,4 @@
 
 obj-$(CONFIG_TWL4030_USB) += twl4030.o
 obj-$(CONFIG_OMAP_USB_PHY) += omap_usb_phy.o
+obj-$(CONFIG_ROCKCHIP_USB2_PHY) += rockchip_usb2_phy.o
diff --git a/drivers/usb/phy/rockchip_usb2_phy.c b/drivers/usb/phy/rockchip_usb2_phy.c
new file mode 100644
index 0000000..1958478
--- /dev/null
+++ b/drivers/usb/phy/rockchip_usb2_phy.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <libfdt.h>
+
+#include "../gadget/dwc2_udc_otg_priv.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define BIT_WRITEABLE_SHIFT	16
+
+struct usb2phy_reg {
+	unsigned int offset;
+	unsigned int bitend;
+	unsigned int bitstart;
+	unsigned int disable;
+	unsigned int enable;
+};
+
+/**
+ * struct rockchip_usb2_phy_cfg: usb-phy port configuration
+ * @port_reset: usb otg per-port reset register
+ * @soft_con: software control usb otg register
+ * @suspend: phy suspend register
+ */
+struct rockchip_usb2_phy_cfg {
+	struct usb2phy_reg port_reset;
+	struct usb2phy_reg soft_con;
+	struct usb2phy_reg suspend;
+};
+
+struct rockchip_usb2_phy_dt_id {
+	char		compatible[128];
+	const void	*data;
+};
+
+static const struct rockchip_usb2_phy_cfg rk3288_pdata = {
+	.port_reset     = {0x00, 12, 12, 0, 1},
+	.soft_con       = {0x08, 2, 2, 0, 1},
+	.suspend	= {0x0c, 5, 0, 0x01, 0x2A},
+};
+
+static struct rockchip_usb2_phy_dt_id rockchip_usb2_phy_dt_ids[] = {
+	{ .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata },
+	{}
+};
+
+static void property_enable(struct dwc2_plat_otg_data *pdata,
+				  const struct usb2phy_reg *reg, bool en)
+{
+	unsigned int val, mask, tmp;
+
+	tmp = en ? reg->enable : reg->disable;
+	mask = GENMASK(reg->bitend, reg->bitstart);
+	val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
+
+	writel(val, pdata->regs_phy + reg->offset);
+}
+
+
+void otg_phy_init(struct dwc2_udc *dev)
+{
+	struct dwc2_plat_otg_data *pdata = dev->pdata;
+	struct rockchip_usb2_phy_cfg *phy_cfg = NULL;
+	struct rockchip_usb2_phy_dt_id *of_id;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(rockchip_usb2_phy_dt_ids); i++) {
+		of_id = &rockchip_usb2_phy_dt_ids[i];
+		if (fdt_node_check_compatible(gd->fdt_blob, pdata->phy_of_node,
+					      of_id->compatible) == 0) {
+			phy_cfg = (struct rockchip_usb2_phy_cfg *)of_id->data;
+			break;
+		}
+	}
+	if (!phy_cfg) {
+		debug("Can't find device platform data\n");
+
+		hang();
+		return;
+	}
+	pdata->priv = phy_cfg;
+	/* disable software control */
+	property_enable(pdata, &phy_cfg->soft_con, false);
+
+	/* reset otg port */
+	property_enable(pdata, &phy_cfg->port_reset, true);
+	mdelay(1);
+	property_enable(pdata, &phy_cfg->port_reset, false);
+	udelay(1);
+}
+
+void otg_phy_off(struct dwc2_udc *dev)
+{
+	struct dwc2_plat_otg_data *pdata = dev->pdata;
+	struct rockchip_usb2_phy_cfg *phy_cfg = pdata->priv;
+
+	/* enable software control */
+	property_enable(pdata, &phy_cfg->soft_con, true);
+	/* enter suspend */
+	property_enable(pdata, &phy_cfg->suspend, true);
+}
diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c
index ef4984b..30b53db 100644
--- a/drivers/video/cfb_console.c
+++ b/drivers/video/cfb_console.c
@@ -1929,10 +1929,10 @@
 static void *video_logo(void)
 {
 	char info[128];
-	int space, len;
 	__maybe_unused int y_off = 0;
 	__maybe_unused ulong addr;
 	__maybe_unused char *s;
+	__maybe_unused int len, space;
 
 	splash_get_pos(&video_logo_xpos, &video_logo_ypos);
 
@@ -1978,6 +1978,7 @@
 
 	sprintf(info, " %s", version_string);
 
+#ifndef CONFIG_HIDE_LOGO_VERSION
 	space = (VIDEO_LINE_LEN / 2 - VIDEO_INFO_X) / VIDEO_FONT_WIDTH;
 	len = strlen(info);
 
@@ -2027,6 +2028,7 @@
 		}
 	}
 #endif
+#endif
 
 	return (video_fb_address + video_logo_height * VIDEO_LINE_LEN);
 }
diff --git a/drivers/video/rockchip/rk_vop.c b/drivers/video/rockchip/rk_vop.c
index cc26f19..c6d88d9 100644
--- a/drivers/video/rockchip/rk_vop.c
+++ b/drivers/video/rockchip/rk_vop.c
@@ -238,7 +238,7 @@
 		return ret;
 	}
 
-	ret = uclass_get_device(UCLASS_CLK, 0, &dev_clk);
+	ret = rockchip_get_clk(&dev_clk);
 	if (!ret) {
 		clk.id = DCLK_VOP0 + remote_vop_id;
 		ret = clk_request(dev_clk, &clk);
diff --git a/drivers/video/tegra.c b/drivers/video/tegra.c
index 217f05f..92214d6 100644
--- a/drivers/video/tegra.c
+++ b/drivers/video/tegra.c
@@ -251,7 +251,7 @@
 /**
  * Register a new display based on device tree configuration.
  *
- * The frame buffer can be positioned by U-Boot or overriden by the fdt.
+ * The frame buffer can be positioned by U-Boot or overridden by the fdt.
  * You should pass in the U-Boot address here, and check the contents of
  * struct tegra_lcd_priv to see what was actually chosen.
  *
diff --git a/drivers/watchdog/imx_watchdog.c b/drivers/watchdog/imx_watchdog.c
index f9f8175..2938d9f 100644
--- a/drivers/watchdog/imx_watchdog.c
+++ b/drivers/watchdog/imx_watchdog.c
@@ -39,7 +39,7 @@
 }
 #endif
 
-void reset_cpu(ulong addr)
+void __attribute__((weak)) reset_cpu(ulong addr)
 {
 	struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
 
diff --git a/dts/Kconfig b/dts/Kconfig
index c56c129..4b7d8b1 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -85,4 +85,25 @@
 	  can be discarded. This option defines the list of properties to
 	  discard.
 
+config SPL_OF_PLATDATA
+	bool "Generate platform data for use in SPL"
+	depends on SPL_OF_CONTROL
+	help
+	  For very constrained SPL environments the overhead of decoding
+	  device tree nodes and converting their contents into platform data
+	  is too large. This overhead includes libfdt code as well as the
+	  device tree contents itself. The latter is fairly compact, but the
+	  former can add 3KB or more to a Thumb 2 Image.
+
+	  This option enables generation of platform data from the device
+	  tree as C code. This code creates devices using U_BOOT_DEVICE()
+	  declarations. The benefit is that it allows driver code to access
+	  the platform data directly in C structures, avoidin the libfdt
+	  overhead.
+
+	  This option works by generating C structure declarations for each
+	  compatible string, then adding platform data and U_BOOT_DEVICE
+	  declarations for each node. See README.platdata for more
+	  information.
+
 endmenu
diff --git a/examples/standalone/stubs.c b/examples/standalone/stubs.c
index 0d62067..a8b7e14 100644
--- a/examples/standalone/stubs.c
+++ b/examples/standalone/stubs.c
@@ -240,6 +240,53 @@
 "	ld	r10, [r10, %1]\n" \
 "	j	[r10]\n" \
 	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r10");
+#elif defined(CONFIG_XTENSA)
+/*
+ * Global data ptr is in global_data, jump table ptr is in jt.
+ * Windowed ABI: Jump just past 'entry' in target and adjust stack frame
+ * (extract stack frame size from target 'entry' instruction).
+ */
+
+static void **jt;
+
+#if defined(__XTENSA_CALL0_ABI__)
+#define EXPORT_FUNC(f, a, x, ...)	\
+	asm volatile (			\
+"	.extern jt\n"			\
+"	.globl " #x "\n"		\
+"	.align 4\n"			\
+#x ":\n"				\
+"	l32i	a8, %0, 0\n"		\
+"	l32i	a8, a8, %1\n"		\
+"	jx	a8\n"			\
+	: : "r"(jt), "i" (FO(x)) : "a8");
+#elif defined(__XTENSA_WINDOWED_ABI__)
+#if XCHAL_HAVE_BE
+# define SFT "8"
+#else
+# define SFT "12"
+#endif
+#define EXPORT_FUNC(f, a, x, ...)	\
+	asm volatile (			\
+"	.extern jt\n"			\
+"	.globl " #x "\n"		\
+"	.align 4\n"			\
+#x ":\n"				\
+"	entry	sp, 16\n"		\
+"	l32i	a8, %0, 0\n"		\
+"	l32i	a8, a8, %1\n"		\
+"	l32i	a9, a8, 0\n"		\
+"	extui	a9, a9, " SFT ", 12\n"	\
+"	subx8	a9, a9, sp\n"		\
+"	movi	a10, 16\n"		\
+"	sub	a9, a10, a9\n"		\
+"	movsp	sp, a9\n"		\
+"	addi	a8, a8, 3\n"		\
+"	jx	a8\n"			\
+	: : "r"(jt), "i" (FO(x)) : "a8", "a9", "a10");
+#else
+#error Unsupported Xtensa ABI
+#endif
 #else
 /*"	addi	$sp, $sp, -24\n"	\
 "	br	$r16\n"			\*/
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c
index 95a48a4..6e1107d 100644
--- a/fs/cbfs/cbfs.c
+++ b/fs/cbfs/cbfs.c
@@ -97,8 +97,8 @@
 		}
 
 		swap_file_header(&header, fileHeader);
-		if (header.offset < sizeof(const struct cbfs_cachenode *) ||
-				header.offset > header.len) {
+		if (header.offset < sizeof(struct cbfs_fileheader) ||
+		    header.offset > header.len) {
 			file_cbfs_result = CBFS_BAD_FILE;
 			return -1;
 		}
@@ -106,9 +106,9 @@
 		newNode->type = header.type;
 		newNode->data = start + header.offset;
 		newNode->data_length = header.len;
-		name_len = header.offset - sizeof(struct cbfs_cachenode *);
+		name_len = header.offset - sizeof(struct cbfs_fileheader);
 		newNode->name = (char *)fileHeader +
-				sizeof(struct cbfs_cachenode *);
+				sizeof(struct cbfs_fileheader);
 		newNode->name_length = name_len;
 		newNode->checksum = header.checksum;
 
diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 40b798a..eb49fce 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -2229,6 +2229,16 @@
 	if (__le16_to_cpu(data->sblock.magic) != EXT2_MAGIC)
 		goto fail;
 
+	/*
+	 * The 64bit feature was enabled when metadata_csum was enabled
+	 * and we do not support metadata_csum (and cannot reliably find
+	 * files when it is set.  Refuse to mount.
+	 */
+	if (data->sblock.feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) {
+		printf("Unsupported feature found (64bit, possibly metadata_csum), not mounting\n");
+		goto fail;
+	}
+
 	if (__le32_to_cpu(data->sblock.revision_level == 0))
 		fs->inodesz = 128;
 	else
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 0abcbe4..a6d1d2a 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -55,20 +55,6 @@
 
 	unsigned long relocaddr;	/* Start address of U-Boot in RAM */
 	phys_size_t ram_size;	/* RAM size */
-#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
-#define MEM_RESERVE_SECURE_SECURED	0x1
-#define MEM_RESERVE_SECURE_MAINTAINED	0x2
-#define MEM_RESERVE_SECURE_ADDR_MASK	(~0x3)
-	/*
-	 * Secure memory addr
-	 * This variable needs maintenance if the RAM base is not zero,
-	 * or if RAM splits into non-consecutive banks. It also has a
-	 * flag indicating the secure memory is marked as secure by MMU.
-	 * Flags used: 0x1 secured
-	 *             0x2 maintained
-	 */
-	phys_addr_t secure_ram;
-#endif
 	unsigned long mon_len;	/* monitor len */
 	unsigned long irq_sp;		/* irq stack pointer */
 	unsigned long start_addr_sp;	/* start_addr_stackpointer */
diff --git a/include/clk.h b/include/clk.h
index 2f31cf7..dc18b03 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -60,6 +60,10 @@
 };
 
 #if CONFIG_IS_ENABLED(OF_CONTROL)
+struct phandle_2_cell;
+int clk_get_by_index_platdata(struct udevice *dev, int index,
+			      struct phandle_2_cell *cells, struct clk *clk);
+
 /**
  * clock_get_by_index - Get/request a clock by integer index.
  *
@@ -100,7 +104,7 @@
 	return -ENOSYS;
 }
 
-static int clk_get_by_name(struct udevice *dev, const char *name,
+static inline int clk_get_by_name(struct udevice *dev, const char *name,
 			   struct clk *clk)
 {
 	return -ENOSYS;
diff --git a/include/common.h b/include/common.h
index 3feaae6..e9f0dea 100644
--- a/include/common.h
+++ b/include/common.h
@@ -101,6 +101,13 @@
 #define _DEBUG	0
 #endif
 
+#ifdef CONFIG_SPL_BUILD
+#define _SPL_BUILD	1
+#else
+#define _SPL_BUILD	0
+#endif
+
+/* Define this at the top of a file to add a prefix to debug messages */
 #ifndef pr_fmt
 #define pr_fmt(fmt) fmt
 #endif
@@ -116,9 +123,14 @@
 			printf(pr_fmt(fmt), ##args);	\
 	} while (0)
 
+/* Show a message if DEBUG is defined in a file */
 #define debug(fmt, args...)			\
 	debug_cond(_DEBUG, fmt, ##args)
 
+/* Show a message if not in SPL */
+#define warn_non_spl(fmt, args...)			\
+	debug_cond(!_SPL_BUILD, fmt, ##args)
+
 /*
  * An assertion is run-time check done in debug mode only. If DEBUG is not
  * defined then it is skipped. If DEBUG is defined and the assertion fails,
diff --git a/include/config_distro_defaults.h b/include/config_distro_defaults.h
index 9244680..b5efab5 100644
--- a/include/config_distro_defaults.h
+++ b/include/config_distro_defaults.h
@@ -20,9 +20,6 @@
 #define CONFIG_BOOTP_PXE
 #define CONFIG_BOOTP_SUBNETMASK
 
-#ifdef CONFIG_ARM64
-#define CONFIG_CMD_BOOTI
-#endif
 #define CONFIG_CMD_PXE
 
 #define CONFIG_CMDLINE_EDITING
diff --git a/include/config_fsl_chain_trust.h b/include/config_fsl_chain_trust.h
index 566fd80..eb45e98 100644
--- a/include/config_fsl_chain_trust.h
+++ b/include/config_fsl_chain_trust.h
@@ -74,23 +74,27 @@
 #ifdef CONFIG_BOOTSCRIPT_COPY_RAM
 #define CONFIG_BS_COPY_ENV \
 	"setenv bs_hdr_ram " __stringify(CONFIG_BS_HDR_ADDR_RAM)";" \
-	"setenv bs_hdr_flash " __stringify(CONFIG_BS_HDR_ADDR_FLASH)";" \
+	"setenv bs_hdr_device " __stringify(CONFIG_BS_HDR_ADDR_DEVICE)";" \
 	"setenv bs_hdr_size " __stringify(CONFIG_BS_HDR_SIZE)";" \
 	"setenv bs_ram " __stringify(CONFIG_BS_ADDR_RAM)";" \
-	"setenv bs_flash " __stringify(CONFIG_BS_ADDR_FLASH)";" \
+	"setenv bs_device " __stringify(CONFIG_BS_ADDR_DEVICE)";" \
 	"setenv bs_size " __stringify(CONFIG_BS_SIZE)";"
 
 /* For secure boot flow, default environment used will be used */
 #if defined(CONFIG_SYS_RAMBOOT)
 #if defined(CONFIG_RAMBOOT_NAND)
 #define CONFIG_BS_COPY_CMD \
-	"nand read $bs_hdr_ram $bs_hdr_flash $bs_hdr_size ;" \
-	"nand read $bs_ram $bs_flash $bs_size ;"
+	"nand read $bs_hdr_ram $bs_hdr_device $bs_hdr_size ;" \
+	"nand read $bs_ram $bs_device $bs_size ;"
 #endif /* CONFIG_RAMBOOT_NAND */
-#else
+#elif defined(CONFIG_SD_BOOT)
+#define CONFIG_BS_COPY_CMD \
+	"mmc read $bs_hdr_ram $bs_hdr_device $bs_hdr_size ;" \
+	"mmc read $bs_ram $bs_device $bs_size ;"
+#else /* CONFIG_SD_BOOT */
 #define CONFIG_BS_COPY_CMD \
-	"cp.b $bs_hdr_flash $bs_hdr_ram  $bs_hdr_size ;" \
-	"cp.b $bs_flash $bs_ram  $bs_size ;"
+	"cp.b $bs_hdr_device $bs_hdr_ram  $bs_hdr_size ;" \
+	"cp.b $bs_device $bs_ram  $bs_size ;"
 #endif
 #endif /* CONFIG_BOOTSCRIPT_COPY_RAM */
 
diff --git a/include/configs/B4860QDS.h b/include/configs/B4860QDS.h
index 2c3c4ac..7d9619e 100644
--- a/include/configs/B4860QDS.h
+++ b/include/configs/B4860QDS.h
@@ -13,7 +13,6 @@
  * B4860 QDS board configuration file
  */
 #define CONFIG_B4860QDS
-#define CONFIG_PHYS_64BIT
 
 #ifdef CONFIG_RAMBOOT_PBL
 #define CONFIG_SYS_FSL_PBL_PBI	$(SRCTREE)/board/freescale/b4860qds/b4_pbi.cfg
@@ -830,7 +829,7 @@
 	"consoledev=ttyS0\0"					\
 	"ramdiskaddr=2000000\0"					\
 	"ramdiskfile=b4860qds/ramdisk.uboot\0"			\
-	"fdtaddr=c00000\0"					\
+	"fdtaddr=1e00000\0"					\
 	"fdtfile=b4860qds/b4860qds.dtb\0"				\
 	"bdev=sda3\0"
 
@@ -868,7 +867,7 @@
  "setenv bootargs root=/dev/ram rw "		\
  "console=$consoledev,$baudrate $othbootargs;"	\
  "setenv ramdiskaddr 0x02000000;"		\
- "setenv fdtaddr 0x00c00000;"			\
+ "setenv fdtaddr 0x01e00000;"			\
  "setenv loadaddr 0x1000000;"			\
  "bootm $loadaddr $ramdiskaddr $fdtaddr"
 
diff --git a/include/configs/BSC9131RDB.h b/include/configs/BSC9131RDB.h
index 0a9d8a6..f2a7c69 100644
--- a/include/configs/BSC9131RDB.h
+++ b/include/configs/BSC9131RDB.h
@@ -403,7 +403,7 @@
 	"consoledev=ttyS0\0"				\
 	"ramdiskaddr=2000000\0"			\
 	"ramdiskfile=rootfs.ext2.gz.uboot\0"		\
-	"fdtaddr=c00000\0"				\
+	"fdtaddr=1e00000\0"				\
 	"fdtfile=bsc9131rdb.dtb\0"		\
 	"bdev=sda1\0"	\
 	"hwconfig=usb1:dr_mode=host,phy_type=ulpi\0"	\
diff --git a/include/configs/BSC9132QDS.h b/include/configs/BSC9132QDS.h
index 756beec..4744f08 100644
--- a/include/configs/BSC9132QDS.h
+++ b/include/configs/BSC9132QDS.h
@@ -647,7 +647,7 @@
 	"consoledev=ttyS0\0"				\
 	"ramdiskaddr=2000000\0"			\
 	"ramdiskfile=rootfs.ext2.gz.uboot\0"		\
-	"fdtaddr=c00000\0"				\
+	"fdtaddr=1e00000\0"				\
 	"fdtfile=bsc9132qds.dtb\0"		\
 	"bdev=sda1\0"	\
 	CONFIG_DEF_HWCONFIG\
diff --git a/include/configs/C29XPCIE.h b/include/configs/C29XPCIE.h
index 69a9798..f75919d 100644
--- a/include/configs/C29XPCIE.h
+++ b/include/configs/C29XPCIE.h
@@ -11,7 +11,6 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
-#define CONFIG_PHYS_64BIT
 #define CONFIG_DISPLAY_BOARDINFO
 
 #ifdef CONFIG_C29XPCIE
@@ -530,7 +529,7 @@
 	"consoledev=ttyS0\0"				\
 	"ramdiskaddr=2000000\0"				\
 	"ramdiskfile=rootfs.ext2.gz.uboot\0"		\
-	"fdtaddr=c00000\0"				\
+	"fdtaddr=1e00000\0"				\
 	"fdtfile=name/of/device-tree.dtb\0"			\
 	"othbootargs=ramdisk_size=600000\0"		\
 
diff --git a/include/configs/MPC8308RDB.h b/include/configs/MPC8308RDB.h
index 578325c..5b80464 100644
--- a/include/configs/MPC8308RDB.h
+++ b/include/configs/MPC8308RDB.h
@@ -203,7 +203,7 @@
  */
 #define CONFIG_SYS_MONITOR_BASE	CONFIG_SYS_TEXT_BASE /* start of monitor */
 
-#define CONFIG_SYS_MONITOR_LEN	(384 * 1024) /* Reserve 384 kB for Mon */
+#define CONFIG_SYS_MONITOR_LEN	(512 * 1024) /* Reserve 512 kB for Mon */
 #define CONFIG_SYS_MALLOC_LEN	(512 * 1024) /* Reserved for malloc */
 
 /*
@@ -452,6 +452,7 @@
  * the maximum mapped by the Linux kernel during initialization.
  */
 #define CONFIG_SYS_BOOTMAPSZ	(256 << 20) /* Initial Memory map for Linux */
+#define CONFIG_SYS_BOOTM_LEN	(64 << 20)	/* Increase max gunzip size */
 
 /*
  * Core HID Setup
diff --git a/include/configs/MPC8313ERDB.h b/include/configs/MPC8313ERDB.h
index 5613a4a..1c4e082 100644
--- a/include/configs/MPC8313ERDB.h
+++ b/include/configs/MPC8313ERDB.h
@@ -241,7 +241,7 @@
 #define CONFIG_SYS_INIT_SP_OFFSET	CONFIG_SYS_GBL_DATA_OFFSET
 
 /* CONFIG_SYS_MONITOR_LEN must be a multiple of CONFIG_ENV_SECT_SIZE */
-#define CONFIG_SYS_MONITOR_LEN	(384 * 1024)	/* Reserve 384 kB for Mon */
+#define CONFIG_SYS_MONITOR_LEN	(512 * 1024)	/* Reserve 512 kB for Mon */
 #define CONFIG_SYS_MALLOC_LEN	(512 * 1024)	/* Reserved for malloc */
 
 /*
@@ -268,7 +268,7 @@
 #define CONFIG_CMD_MTDPARTS
 #define MTDIDS_DEFAULT			"nand0=e2800000.flash"
 #define MTDPARTS_DEFAULT		\
-	"mtdparts=e2800000.flash:512k(uboot),128k(env),3m@1m(kernel),-(fs)"
+	"mtdparts=e2800000.flash:512k(uboot),128k(env),6m@1m(kernel),-(fs)"
 
 #define CONFIG_SYS_MAX_NAND_DEVICE	1
 #define CONFIG_CMD_NAND 1
@@ -502,6 +502,7 @@
  */
 				/* Initial Memory map for Linux*/
 #define CONFIG_SYS_BOOTMAPSZ	(256 << 20)
+#define CONFIG_SYS_BOOTM_LEN	(64 << 20)	/* Increase max gunzip size */
 
 #define CONFIG_SYS_RCWH_PCIHOST 0x80000000	/* PCIHOST  */
 
diff --git a/include/configs/MPC8315ERDB.h b/include/configs/MPC8315ERDB.h
index 7ce5f59..23a2e34 100644
--- a/include/configs/MPC8315ERDB.h
+++ b/include/configs/MPC8315ERDB.h
@@ -169,7 +169,7 @@
 /*
  * The reserved memory
  */
-#define CONFIG_SYS_MONITOR_LEN	(384 * 1024) /* Reserve 384 kB for Mon */
+#define CONFIG_SYS_MONITOR_LEN	(512 * 1024) /* Reserve 512 kB for Mon */
 #define CONFIG_SYS_MALLOC_LEN	(512 * 1024) /* Reserved for malloc */
 
 /*
@@ -241,7 +241,7 @@
 #define CONFIG_CMD_MTDPARTS
 #define MTDIDS_DEFAULT			"nand0=e0600000.flash"
 #define MTDPARTS_DEFAULT		\
-	"mtdparts=e0600000.flash:512k(uboot),128k(env),3m@1m(kernel),-(fs)"
+	"mtdparts=e0600000.flash:512k(uboot),128k(env),6m@1m(kernel),-(fs)"
 
 #define CONFIG_SYS_MAX_NAND_DEVICE	1
 #define CONFIG_CMD_NAND			1
@@ -489,6 +489,7 @@
  * the maximum mapped by the Linux kernel during initialization.
  */
 #define CONFIG_SYS_BOOTMAPSZ	(256 << 20) /* Initial Memory map for Linux */
+#define CONFIG_SYS_BOOTM_LEN	(64 << 20)	/* Increase max gunzip size */
 
 /*
  * Core HID Setup
diff --git a/include/configs/MPC8323ERDB.h b/include/configs/MPC8323ERDB.h
index 13f954d..095c0d8 100644
--- a/include/configs/MPC8323ERDB.h
+++ b/include/configs/MPC8323ERDB.h
@@ -156,7 +156,7 @@
 #endif
 
 /* CONFIG_SYS_MONITOR_LEN must be a multiple of CONFIG_ENV_SECT_SIZE */
-#define CONFIG_SYS_MONITOR_LEN	(384 * 1024)	/* Reserve 384 kB for Mon */
+#define CONFIG_SYS_MONITOR_LEN	(512 * 1024)	/* Reserve 512 kB for Mon */
 #define CONFIG_SYS_MALLOC_LEN	(256 * 1024)	/* Reserved for malloc */
 
 /*
@@ -359,6 +359,7 @@
  */
 					/* Initial Memory map for Linux */
 #define CONFIG_SYS_BOOTMAPSZ		(256 << 20)
+#define CONFIG_SYS_BOOTM_LEN	(64 << 20)	/* Increase max gunzip size */
 
 /*
  * Core HID Setup
diff --git a/include/configs/MPC832XEMDS.h b/include/configs/MPC832XEMDS.h
index fd48260..18418e3 100644
--- a/include/configs/MPC832XEMDS.h
+++ b/include/configs/MPC832XEMDS.h
@@ -168,7 +168,7 @@
 #endif
 
 /* CONFIG_SYS_MONITOR_LEN must be a multiple of CONFIG_ENV_SECT_SIZE */
-#define CONFIG_SYS_MONITOR_LEN	(384 * 1024)	/* Reserve 384 kB for Mon */
+#define CONFIG_SYS_MONITOR_LEN	(512 * 1024)	/* Reserve 512 kB for Mon */
 #define CONFIG_SYS_MALLOC_LEN	(256 * 1024)	/* Reserved for malloc */
 
 /*
@@ -441,6 +441,7 @@
  */
 					/* Initial Memory map for Linux */
 #define CONFIG_SYS_BOOTMAPSZ		(256 << 20)
+#define CONFIG_SYS_BOOTM_LEN	(64 << 20)	/* Increase max gunzip size */
 
 /*
  * Core HID Setup
diff --git a/include/configs/MPC8349EMDS.h b/include/configs/MPC8349EMDS.h
index 288b126..a2fa783 100644
--- a/include/configs/MPC8349EMDS.h
+++ b/include/configs/MPC8349EMDS.h
@@ -225,7 +225,7 @@
 			(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
 #define CONFIG_SYS_INIT_SP_OFFSET	CONFIG_SYS_GBL_DATA_OFFSET
 
-#define CONFIG_SYS_MONITOR_LEN	(384 * 1024)	/* Reserve 384 kB for Mon */
+#define CONFIG_SYS_MONITOR_LEN	(512 * 1024)	/* Reserve 512 kB for Mon */
 #define CONFIG_SYS_MALLOC_LEN	(256 * 1024)	/* Reserved for malloc */
 
 /*
@@ -508,6 +508,7 @@
  */
 				/* Initial Memory map for Linux*/
 #define CONFIG_SYS_BOOTMAPSZ	(256 << 20)
+#define CONFIG_SYS_BOOTM_LEN	(64 << 20)	/* Increase max gunzip size */
 
 #define CONFIG_SYS_RCWH_PCIHOST 0x80000000 /* PCIHOST  */
 
diff --git a/include/configs/MPC8349ITX.h b/include/configs/MPC8349ITX.h
index 2721255..c11c0cf 100644
--- a/include/configs/MPC8349ITX.h
+++ b/include/configs/MPC8349ITX.h
@@ -330,7 +330,7 @@
 #define CONFIG_SYS_INIT_SP_OFFSET	CONFIG_SYS_GBL_DATA_OFFSET
 
 /* CONFIG_SYS_MONITOR_LEN must be a multiple of CONFIG_ENV_SECT_SIZE */
-#define CONFIG_SYS_MONITOR_LEN	(384 * 1024) /* Reserve 384 kB for Mon */
+#define CONFIG_SYS_MONITOR_LEN	(512 * 1024) /* Reserve 512 kB for Mon */
 #define CONFIG_SYS_MALLOC_LEN	(256 * 1024) /* Reserved for malloc */
 
 /*
@@ -544,6 +544,7 @@
  */
 				/* Initial Memory map for Linux*/
 #define CONFIG_SYS_BOOTMAPSZ	(256 << 20)
+#define CONFIG_SYS_BOOTM_LEN	(64 << 20)	/* Increase max gunzip size */
 
 #define CONFIG_SYS_HRCW_LOW (\
 	HRCWL_LCL_BUS_TO_SCB_CLK_1X1 |\
diff --git a/include/configs/MPC837XEMDS.h b/include/configs/MPC837XEMDS.h
index 921d5f3..b2dc189 100644
--- a/include/configs/MPC837XEMDS.h
+++ b/include/configs/MPC837XEMDS.h
@@ -200,7 +200,7 @@
 #endif
 
 /* CONFIG_SYS_MONITOR_LEN must be a multiple of CONFIG_ENV_SECT_SIZE */
-#define CONFIG_SYS_MONITOR_LEN	(384 * 1024) /* Reserve 384 kB for Mon */
+#define CONFIG_SYS_MONITOR_LEN	(512 * 1024) /* Reserve 512 kB for Mon */
 #define CONFIG_SYS_MALLOC_LEN	(512 * 1024) /* Reserved for malloc */
 
 /*
@@ -522,6 +522,7 @@
  * the maximum mapped by the Linux kernel during initialization.
  */
 #define CONFIG_SYS_BOOTMAPSZ	(256 << 20) /* Initial Memory map for Linux */
+#define CONFIG_SYS_BOOTM_LEN	(64 << 20)	/* Increase max gunzip size */
 
 /*
  * Core HID Setup
diff --git a/include/configs/MPC837XERDB.h b/include/configs/MPC837XERDB.h
index bb06e89..8eb87eb 100644
--- a/include/configs/MPC837XERDB.h
+++ b/include/configs/MPC837XERDB.h
@@ -225,7 +225,7 @@
 #undef	CONFIG_SYS_RAMBOOT
 #endif
 
-#define CONFIG_SYS_MONITOR_LEN	(384 * 1024) /* Reserve 384 kB for Mon */
+#define CONFIG_SYS_MONITOR_LEN	(512 * 1024) /* Reserve 512 kB for Mon */
 #define CONFIG_SYS_MALLOC_LEN	(512 * 1024) /* Reserved for malloc */
 
 /*
@@ -533,6 +533,7 @@
  * the maximum mapped by the Linux kernel during initialization.
  */
 #define CONFIG_SYS_BOOTMAPSZ	(256 << 20) /* Initial Memory map for Linux */
+#define CONFIG_SYS_BOOTM_LEN	(64 << 20)	/* Increase max gunzip size */
 
 /*
  * Core HID Setup
diff --git a/include/configs/MPC8536DS.h b/include/configs/MPC8536DS.h
index 7c19ff8..b536f67 100644
--- a/include/configs/MPC8536DS.h
+++ b/include/configs/MPC8536DS.h
@@ -14,10 +14,6 @@
 #define CONFIG_DISPLAY_BOARDINFO
 #include "../board/freescale/common/ics307_clk.h"
 
-#ifdef CONFIG_36BIT
-#define CONFIG_PHYS_64BIT	1
-#endif
-
 #ifdef CONFIG_SDCARD
 #define CONFIG_RAMBOOT_SDCARD		1
 #define CONFIG_SYS_TEXT_BASE	0xf8f40000
@@ -727,7 +723,7 @@
 "consoledev=ttyS0\0"				\
 "ramdiskaddr=2000000\0"			\
 "ramdiskfile=8536ds/ramdisk.uboot\0"		\
-"fdtaddr=c00000\0"				\
+"fdtaddr=1e00000\0"				\
 "fdtfile=8536ds/mpc8536ds.dtb\0"		\
 "bdev=sda3\0"					\
 "hwconfig=usb1:dr_mode=host,phy_type=ulpi\0"
diff --git a/include/configs/MPC8544DS.h b/include/configs/MPC8544DS.h
index b9d97c1..cd10432 100644
--- a/include/configs/MPC8544DS.h
+++ b/include/configs/MPC8544DS.h
@@ -209,7 +209,7 @@
 #define CONFIG_SYS_I2C_FSL
 #define CONFIG_SYS_FSL_I2C_SPEED	400000
 #define CONFIG_SYS_FSL_I2C_SLAVE	0x7F
-#define CONFIG_SYS_FSL_I2C_OFFSET	0x3000
+#define CONFIG_SYS_FSL_I2C_OFFSET	0x3100
 #define CONFIG_SYS_I2C_NOPROBES		{ {0, 0x69} }
 #define CONFIG_SYS_I2C_EEPROM_ADDR	0x57
 
@@ -462,7 +462,7 @@
 "consoledev=ttyS0\0"				\
 "ramdiskaddr=2000000\0"			\
 "ramdiskfile=8544ds/ramdisk.uboot\0"		\
-"fdtaddr=c00000\0"				\
+"fdtaddr=1e00000\0"				\
 "fdtfile=8544ds/mpc8544ds.dtb\0"		\
 "bdev=sda3\0"
 
diff --git a/include/configs/MPC8548CDS.h b/include/configs/MPC8548CDS.h
index e73be48..789c62b 100644
--- a/include/configs/MPC8548CDS.h
+++ b/include/configs/MPC8548CDS.h
@@ -15,10 +15,6 @@
 
 #define CONFIG_DISPLAY_BOARDINFO
 
-#ifdef CONFIG_36BIT
-#define CONFIG_PHYS_64BIT
-#endif
-
 /* High Level Configuration Options */
 #define CONFIG_BOOKE		1	/* BOOKE */
 #define CONFIG_E500		1	/* BOOKE e500 family */
@@ -562,7 +558,7 @@
 	"consoledev=ttyS1\0"			\
 	"ramdiskaddr=2000000\0"			\
 	"ramdiskfile=ramdisk.uboot\0"		\
-	"fdtaddr=c00000\0"			\
+	"fdtaddr=1e00000\0"			\
 	"fdtfile=mpc8548cds.dtb\0"
 
 #define CONFIG_NFSBOOTCOMMAND						\
diff --git a/include/configs/MPC8572DS.h b/include/configs/MPC8572DS.h
index 2e6989f..26cf8d6 100644
--- a/include/configs/MPC8572DS.h
+++ b/include/configs/MPC8572DS.h
@@ -15,10 +15,6 @@
 
 #include "../board/freescale/common/ics307_clk.h"
 
-#ifdef CONFIG_36BIT
-#define CONFIG_PHYS_64BIT
-#endif
-
 #ifndef CONFIG_SYS_TEXT_BASE
 #define CONFIG_SYS_TEXT_BASE	0xeff40000
 #endif
@@ -668,7 +664,7 @@
 "consoledev=ttyS0\0"				\
 "ramdiskaddr=2000000\0"			\
 "ramdiskfile=8572ds/ramdisk.uboot\0"		\
-"fdtaddr=c00000\0"				\
+"fdtaddr=1e00000\0"				\
 "fdtfile=8572ds/mpc8572ds.dtb\0"		\
 "bdev=sda3\0"
 
diff --git a/include/configs/MPC8610HPCD.h b/include/configs/MPC8610HPCD.h
index 8159493..c1b9b6e 100644
--- a/include/configs/MPC8610HPCD.h
+++ b/include/configs/MPC8610HPCD.h
@@ -477,7 +477,8 @@
  * have to be in the first 8 MB of memory, since this is
  * the maximum mapped by the Linux kernel during initialization.
  */
-#define CONFIG_SYS_BOOTMAPSZ	(8 << 20)	/* Initial Memory map for Linux*/
+#define CONFIG_SYS_BOOTMAPSZ	(256 << 20)	/* Initial Memory map for Linux*/
+#define CONFIG_SYS_BOOTM_LEN	(256 << 20)	/* Increase max gunzip size */
 
 #if defined(CONFIG_CMD_KGDB)
 #define CONFIG_KGDB_BAUDRATE	230400	/* speed to run kgdb serial port */
@@ -498,7 +499,7 @@
 #define CONFIG_NETMASK		255.255.255.0
 
 /* default location for tftp and bootm */
-#define CONFIG_LOADADDR		1000000
+#define CONFIG_LOADADDR		0x10000000
 
 #undef	CONFIG_BOOTARGS		/* the boot command will set bootargs */
 
@@ -566,9 +567,9 @@
 	"cmp.b $loadaddr " __stringify(CONFIG_SYS_TEXT_BASE)	\
 		" $filesize\0"	\
 "consoledev=ttyS0\0"						\
-"ramdiskaddr=2000000\0"					\
+"ramdiskaddr=0x18000000\0"					\
 "ramdiskfile=8610hpcd/ramdisk.uboot\0"				\
-"fdtaddr=c00000\0"						\
+"fdtaddr=0x17c00000\0"						\
 "fdtfile=8610hpcd/mpc8610_hpcd.dtb\0"				\
 "bdev=sda3\0"					\
 "en-wd=mw.b f8100010 0x08; echo -expect:- 08; md.b f8100010 1\0" \
@@ -604,9 +605,9 @@
 	"netdev=eth0\0"						\
 	"uboot=" __stringify(CONFIG_UBOOTPATH) "\0"		\
 	"consoledev=ttyS0\0"					\
-	"ramdiskaddr=2000000\0"					\
+	"ramdiskaddr=0x18000000\0"				\
 	"ramdiskfile=8610hpcd/ramdisk.uboot\0"			\
-	"fdtaddr=c00000\0"					\
+	"fdtaddr=0x17c00000\0"					\
 	"fdtfile=8610hpcd/mpc8610_hpcd.dtb\0"			\
 	"bdev=sda3\0"
 #endif
diff --git a/include/configs/MPC8641HPCN.h b/include/configs/MPC8641HPCN.h
index f90f7f2..1885124 100644
--- a/include/configs/MPC8641HPCN.h
+++ b/include/configs/MPC8641HPCN.h
@@ -23,7 +23,6 @@
 #define CONFIG_MPC8641HPCN	1	/* MPC8641HPCN board specific */
 #define CONFIG_MP		1	/* support multiple processors */
 #define CONFIG_LINUX_RESET_VEC	0x100	/* Reset vector used by Linux */
-/*#define CONFIG_PHYS_64BIT	1*/	/* Place devices in 36-bit space */
 #define CONFIG_ADDR_MAP		1	/* Use addr map */
 
 /*
@@ -637,7 +636,8 @@
  * have to be in the first 8 MB of memory, since this is
  * the maximum mapped by the Linux kernel during initialization.
  */
-#define CONFIG_SYS_BOOTMAPSZ	(8 << 20)	/* Initial Memory map for Linux*/
+#define CONFIG_SYS_BOOTMAPSZ	(256 << 20)	/* Initial Memory map for Linux*/
+#define CONFIG_SYS_BOOTM_LEN	(256 << 20)	/* Increase max gunzip size */
 
 #if defined(CONFIG_CMD_KGDB)
     #define CONFIG_KGDB_BAUDRATE	230400	/* speed to run kgdb serial port */
@@ -664,7 +664,7 @@
 #define CONFIG_NETMASK		255.255.255.0
 
 /* default location for tftp and bootm */
-#define CONFIG_LOADADDR		1000000
+#define CONFIG_LOADADDR		0x10000000
 
 #undef	CONFIG_BOOTARGS		/* the boot command will set bootargs */
 
@@ -685,9 +685,9 @@
 		"cmp.b $loadaddr " __stringify(CONFIG_SYS_TEXT_BASE)	\
 			" $filesize\0"	\
 	"consoledev=ttyS0\0"						\
-	"ramdiskaddr=2000000\0"						\
+	"ramdiskaddr=0x18000000\0"						\
 	"ramdiskfile=your.ramdisk.u-boot\0"				\
-	"fdtaddr=c00000\0"						\
+	"fdtaddr=0x17c00000\0"						\
 	"fdtfile=mpc8641_hpcn.dtb\0"					\
 	"en-wd=mw.b ffdf0010 0x08; echo -expect:- 08; md.b ffdf0010 1\0"			\
 	"dis-wd=mw.b ffdf0010 0x00; echo -expect:- 00; md.b ffdf0010 1\0" \
diff --git a/include/configs/P1010RDB.h b/include/configs/P1010RDB.h
index 5384584..5ab6602 100644
--- a/include/configs/P1010RDB.h
+++ b/include/configs/P1010RDB.h
@@ -11,9 +11,6 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
-#ifdef CONFIG_36BIT
-#define CONFIG_PHYS_64BIT
-#endif
 #define	CONFIG_DISPLAY_BOARDINFO
 
 #define CONFIG_P1010
@@ -862,7 +859,7 @@
 	"consoledev=ttyS0\0"				\
 	"ramdiskaddr=2000000\0"			\
 	"ramdiskfile=rootfs.ext2.gz.uboot\0"		\
-	"fdtaddr=c00000\0"				\
+	"fdtaddr=1e00000\0"				\
 	"fdtfile=p1010rdb.dtb\0"		\
 	"bdev=sda1\0"	\
 	"hwconfig=usb1:dr_mode=host,phy_type=utmi\0"	\
diff --git a/include/configs/P1022DS.h b/include/configs/P1022DS.h
index bdf0323..5d572b4 100644
--- a/include/configs/P1022DS.h
+++ b/include/configs/P1022DS.h
@@ -13,10 +13,6 @@
 
 #define CONFIG_DISPLAY_BOARDINFO
 
-#ifdef CONFIG_36BIT
-#define CONFIG_PHYS_64BIT
-#endif
-
 #ifdef CONFIG_SDCARD
 #define CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT
 #define CONFIG_SPL_ENV_SUPPORT
@@ -731,7 +727,7 @@
 	"consoledev=ttyS0\0"					\
 	"ramdiskaddr=2000000\0"					\
 	"ramdiskfile=rootfs.ext2.gz.uboot\0"			\
-	"fdtaddr=c00000\0"	  			      	\
+	"fdtaddr=1e00000\0"	  			      	\
 	"fdtfile=p1022ds.dtb\0"	  				\
 	"bdev=sda3\0"		  			      	\
 	"hwconfig=esdhc;audclk:12\0"
diff --git a/include/configs/P1023RDB.h b/include/configs/P1023RDB.h
index 07a594d..d044c7b 100644
--- a/include/configs/P1023RDB.h
+++ b/include/configs/P1023RDB.h
@@ -375,7 +375,7 @@
 	"consoledev=ttyS0\0"					\
 	"ramdiskaddr=2000000\0"					\
 	"ramdiskfile=rootfs.ext2.gz.uboot\0"			\
-	"fdtaddr=c00000\0"					\
+	"fdtaddr=1e00000\0"					\
 	"fdtfile=p1023rdb.dtb\0"				\
 	"othbootargs=ramdisk_size=600000\0"			\
 	"bdev=sda1\0"						\
diff --git a/include/configs/P2041RDB.h b/include/configs/P2041RDB.h
index 24e5431..e6057f9 100644
--- a/include/configs/P2041RDB.h
+++ b/include/configs/P2041RDB.h
@@ -12,7 +12,6 @@
 #define __CONFIG_H
 
 #define CONFIG_P2041RDB
-#define CONFIG_PHYS_64BIT
 #define CONFIG_DISPLAY_BOARDINFO
 #define CONFIG_PPC_P2041
 
@@ -698,7 +697,7 @@
 	"usb_dr_mode=host\0"					\
 	"ramdiskaddr=2000000\0"					\
 	"ramdiskfile=p2041rdb/ramdisk.uboot\0"			\
-	"fdtaddr=c00000\0"					\
+	"fdtaddr=1e00000\0"					\
 	"fdtfile=p2041rdb/p2041rdb.dtb\0"			\
 	"bdev=sda3\0"
 
diff --git a/include/configs/P3041DS.h b/include/configs/P3041DS.h
index e05dd75..c901fe2 100644
--- a/include/configs/P3041DS.h
+++ b/include/configs/P3041DS.h
@@ -9,7 +9,6 @@
  *
  */
 #define CONFIG_P3041DS
-#define CONFIG_PHYS_64BIT
 #define CONFIG_PPC_P3041
 
 #define CONFIG_FSL_NGPIXIS		/* use common ngPIXIS code */
diff --git a/include/configs/P4080DS.h b/include/configs/P4080DS.h
index 2f89008..0d44c00 100644
--- a/include/configs/P4080DS.h
+++ b/include/configs/P4080DS.h
@@ -9,7 +9,6 @@
  * Also supports P4040 DS
  */
 #define CONFIG_P4080DS
-#define CONFIG_PHYS_64BIT
 #define CONFIG_PPC_P4080
 
 #define CONFIG_FSL_NGPIXIS		/* use common ngPIXIS code */
diff --git a/include/configs/P5020DS.h b/include/configs/P5020DS.h
index 588df80..d2cedfe 100644
--- a/include/configs/P5020DS.h
+++ b/include/configs/P5020DS.h
@@ -9,7 +9,6 @@
  * Also supports P5010 DS
  */
 #define CONFIG_P5020DS
-#define CONFIG_PHYS_64BIT
 #define CONFIG_PPC_P5020
 
 #define CONFIG_FSL_NGPIXIS		/* use common ngPIXIS code */
diff --git a/include/configs/P5040DS.h b/include/configs/P5040DS.h
index e4a031a..dc82721 100644
--- a/include/configs/P5040DS.h
+++ b/include/configs/P5040DS.h
@@ -9,7 +9,6 @@
  *
  */
 #define CONFIG_P5040DS
-#define CONFIG_PHYS_64BIT
 #define CONFIG_PPC_P5040
 
 #define CONFIG_FSL_NGPIXIS		/* use common ngPIXIS code */
diff --git a/include/configs/T102xQDS.h b/include/configs/T102xQDS.h
index b151963..2f18f52 100644
--- a/include/configs/T102xQDS.h
+++ b/include/configs/T102xQDS.h
@@ -18,7 +18,6 @@
 #define CONFIG_E500MC			/* BOOKE e500mc family */
 #define CONFIG_SYS_BOOK3E_HV		/* Category E.HV supported */
 #define CONFIG_MP			/* support multiple processors */
-#define CONFIG_PHYS_64BIT
 #define CONFIG_ENABLE_36BIT_PHYS
 
 #ifdef CONFIG_PHYS_64BIT
diff --git a/include/configs/T102xRDB.h b/include/configs/T102xRDB.h
index 06d1d0f..8029ca8 100644
--- a/include/configs/T102xRDB.h
+++ b/include/configs/T102xRDB.h
@@ -18,7 +18,6 @@
 #define CONFIG_E500MC			/* BOOKE e500mc family */
 #define CONFIG_SYS_BOOK3E_HV		/* Category E.HV supported */
 #define CONFIG_MP			/* support multiple processors */
-#define CONFIG_PHYS_64BIT
 #define CONFIG_ENABLE_36BIT_PHYS
 
 #ifdef CONFIG_PHYS_64BIT
@@ -897,7 +896,7 @@
 	"cmp.b $loadaddr $ubootaddr $filesize\0"		\
 	"consoledev=ttyS0\0"					\
 	"ramdiskaddr=2000000\0"					\
-	"fdtaddr=c00000\0"					\
+	"fdtaddr=1e00000\0"					\
 	"bdev=sda3\0"
 
 #define CONFIG_LINUX					\
diff --git a/include/configs/T1040QDS.h b/include/configs/T1040QDS.h
index 9f5063c..b8c6e89 100644
--- a/include/configs/T1040QDS.h
+++ b/include/configs/T1040QDS.h
@@ -27,7 +27,6 @@
  * T1040 QDS board configuration file
  */
 #define CONFIG_T1040QDS
-#define CONFIG_PHYS_64BIT
 #define CONFIG_DISPLAY_BOARDINFO
 
 #ifdef CONFIG_RAMBOOT_PBL
@@ -770,7 +769,7 @@
 	"consoledev=ttyS0\0"					\
 	"ramdiskaddr=2000000\0"					\
 	"ramdiskfile=t1040qds/ramdisk.uboot\0"			\
-	"fdtaddr=c00000\0"					\
+	"fdtaddr=1e00000\0"					\
 	"fdtfile=t1040qds/t1040qds.dtb\0"			\
 	"bdev=sda3\0"
 
diff --git a/include/configs/T104xRDB.h b/include/configs/T104xRDB.h
index a8f4f74..e583def 100644
--- a/include/configs/T104xRDB.h
+++ b/include/configs/T104xRDB.h
@@ -11,14 +11,20 @@
  * T104x RDB board configuration file
  */
 #define CONFIG_T104xRDB
-#define CONFIG_PHYS_64BIT
 #define CONFIG_DISPLAY_BOARDINFO
 
 #define CONFIG_E500			/* BOOKE e500 family */
 #include <asm/config_mpc85xx.h>
 
 #ifdef CONFIG_RAMBOOT_PBL
+
+#ifndef CONFIG_SECURE_BOOT
 #define CONFIG_SYS_FSL_PBL_PBI $(SRCTREE)/board/freescale/t104xrdb/t104x_pbi.cfg
+#else
+#define CONFIG_SYS_FSL_PBL_PBI \
+		$(SRCTREE)/board/freescale/t104xrdb/t104x_pbi_sb.cfg
+#endif
+
 #ifdef CONFIG_T1040RDB
 #define CONFIG_SYS_FSL_PBL_RCW $(SRCTREE)/board/freescale/t104xrdb/t1040_rcw.cfg
 #endif
@@ -62,7 +68,17 @@
 
 #ifdef CONFIG_NAND
 #define CONFIG_SPL_NAND_SUPPORT
+#ifdef CONFIG_SECURE_BOOT
+#define CONFIG_U_BOOT_HDR_SIZE		(16 << 10)
+/*
+ * HDR would be appended at end of image and copied to DDR along
+ * with U-Boot image.
+ */
+#define CONFIG_SYS_NAND_U_BOOT_SIZE	((768 << 10) + \
+					 CONFIG_U_BOOT_HDR_SIZE)
+#else
 #define CONFIG_SYS_NAND_U_BOOT_SIZE	(768 << 10)
+#endif
 #define CONFIG_SYS_NAND_U_BOOT_DST	0x30000000
 #define CONFIG_SYS_NAND_U_BOOT_START	0x30000000
 #define CONFIG_SYS_NAND_U_BOOT_OFFS	(256 << 10)
@@ -161,6 +177,10 @@
 #define CONFIG_ENV_SIZE			0x2000
 #define CONFIG_ENV_OFFSET		(512 * 0x800)
 #elif defined(CONFIG_NAND)
+#ifdef CONFIG_SECURE_BOOT
+#define CONFIG_RAMBOOT_NAND
+#define CONFIG_BOOTSCRIPT_COPY_RAM
+#endif
 #define CONFIG_SYS_EXTRA_ENV_RELOC
 #define CONFIG_ENV_IS_IN_NAND
 #define CONFIG_ENV_SIZE			0x2000
@@ -202,8 +222,14 @@
  *  Config the L3 Cache as L3 SRAM
  */
 #define CONFIG_SYS_INIT_L3_ADDR		0xFFFC0000
+/*
+ * For Secure Boot CONFIG_SYS_INIT_L3_ADDR will be redefined and hence
+ * Physical address (CONFIG_SYS_INIT_L3_ADDR) and virtual address
+ * (CONFIG_SYS_INIT_L3_VADDR) will be different.
+ */
+#define CONFIG_SYS_INIT_L3_VADDR	0xFFFC0000
 #define CONFIG_SYS_L3_SIZE		256 << 10
-#define CONFIG_SPL_GD_ADDR		(CONFIG_SYS_INIT_L3_ADDR + 32 * 1024)
+#define CONFIG_SPL_GD_ADDR		(CONFIG_SYS_INIT_L3_VADDR + 32 * 1024)
 #ifdef CONFIG_RAMBOOT_PBL
 #define CONFIG_ENV_ADDR			(CONFIG_SPL_GD_ADDR + 4 * 1024)
 #endif
@@ -873,7 +899,7 @@
 	"consoledev=ttyS0\0"					\
 	"ramdiskaddr=2000000\0"					\
 	"ramdiskfile=" __stringify(RAMDISKFILE) "\0"		\
-	"fdtaddr=c00000\0"					\
+	"fdtaddr=1e00000\0"					\
 	"fdtfile=" __stringify(FDTFILE) "\0"			\
 	"bdev=sda3\0"
 
diff --git a/include/configs/T208xQDS.h b/include/configs/T208xQDS.h
index 1f07a83..3f28549 100644
--- a/include/configs/T208xQDS.h
+++ b/include/configs/T208xQDS.h
@@ -26,7 +26,6 @@
 #endif
 
 /* High Level Configuration Options */
-#define CONFIG_PHYS_64BIT
 #define CONFIG_BOOKE
 #define CONFIG_E500		/* BOOKE e500 family */
 #define CONFIG_E500MC		/* BOOKE e500mc family */
@@ -840,7 +839,7 @@
 	"consoledev=ttyS0\0"					\
 	"ramdiskaddr=2000000\0"					\
 	"ramdiskfile=t2080qds/ramdisk.uboot\0"			\
-	"fdtaddr=c00000\0"					\
+	"fdtaddr=1e00000\0"					\
 	"fdtfile=t2080qds/t2080qds.dtb\0"			\
 	"bdev=sda3\0"
 
diff --git a/include/configs/T208xRDB.h b/include/configs/T208xRDB.h
index 0ded41e..37d16ae 100644
--- a/include/configs/T208xRDB.h
+++ b/include/configs/T208xRDB.h
@@ -19,7 +19,6 @@
 #define CONFIG_FSL_SATA_V2
 
 /* High Level Configuration Options */
-#define CONFIG_PHYS_64BIT
 #define CONFIG_BOOKE
 #define CONFIG_E500		/* BOOKE e500 family */
 #define CONFIG_E500MC		/* BOOKE e500mc family */
@@ -792,7 +791,7 @@
 	"consoledev=ttyS0\0"					\
 	"ramdiskaddr=2000000\0"					\
 	"ramdiskfile=t2080rdb/ramdisk.uboot\0"			\
-	"fdtaddr=c00000\0"					\
+	"fdtaddr=1e00000\0"					\
 	"fdtfile=t2080rdb/t2080rdb.dtb\0"			\
 	"bdev=sda3\0"
 
diff --git a/include/configs/T4240QDS.h b/include/configs/T4240QDS.h
index f075dfb..8fffffe 100644
--- a/include/configs/T4240QDS.h
+++ b/include/configs/T4240QDS.h
@@ -11,7 +11,6 @@
 #define __CONFIG_H
 
 #define CONFIG_T4240QDS
-#define CONFIG_PHYS_64BIT
 
 #define CONFIG_FSL_SATA_V2
 #define CONFIG_PCIE4
@@ -577,7 +576,7 @@
 	"consoledev=ttyS0\0"					\
 	"ramdiskaddr=2000000\0"					\
 	"ramdiskfile=t4240qds/ramdisk.uboot\0"			\
-	"fdtaddr=c00000\0"					\
+	"fdtaddr=1e00000\0"					\
 	"fdtfile=t4240qds/t4240qds.dtb\0"				\
 	"bdev=sda3\0"
 
diff --git a/include/configs/T4240RDB.h b/include/configs/T4240RDB.h
index 9ba69a1..15b8219 100644
--- a/include/configs/T4240RDB.h
+++ b/include/configs/T4240RDB.h
@@ -11,7 +11,6 @@
 #define __CONFIG_H
 
 #define CONFIG_T4240RDB
-#define CONFIG_PHYS_64BIT
 #define CONFIG_DISPLAY_BOARDINFO
 
 #define CONFIG_FSL_SATA_V2
@@ -770,7 +769,7 @@
 	"consoledev=ttyS0\0"					\
 	"ramdiskaddr=2000000\0"					\
 	"ramdiskfile=t4240rdb/ramdisk.uboot\0"			\
-	"fdtaddr=c00000\0"					\
+	"fdtaddr=1e00000\0"					\
 	"fdtfile=t4240rdb/t4240rdb.dtb\0"			\
 	"bdev=sda3\0"
 
diff --git a/include/configs/a3m071.h b/include/configs/a3m071.h
index 8f17dd1..ab2477c 100644
--- a/include/configs/a3m071.h
+++ b/include/configs/a3m071.h
@@ -334,6 +334,7 @@
 
 #define CONFIG_SYS_OS_BASE	0xfc200000
 #define CONFIG_SYS_FDT_BASE	0xfc1e0000
+#define CONFIG_SYS_FDT_SIZE	(16<<10)
 
 #define	CONFIG_EXTRA_ENV_SETTINGS					\
 	"netdev=eth0\0"							\
diff --git a/include/configs/am43xx_evm.h b/include/configs/am43xx_evm.h
index 361704b..0467953 100644
--- a/include/configs/am43xx_evm.h
+++ b/include/configs/am43xx_evm.h
@@ -98,7 +98,6 @@
 
 #if defined(CONFIG_SPL_USB_HOST_SUPPORT) || !defined(CONFIG_SPL_BUILD)
 #define CONFIG_SYS_USB_FAT_BOOT_PARTITION		1
-#define CONFIG_USB_HOST
 #define CONFIG_USB_XHCI_OMAP
 #define CONFIG_USB_STORAGE
 #define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2
diff --git a/include/configs/am57xx_evm.h b/include/configs/am57xx_evm.h
index 2db199d..46e8d4c 100644
--- a/include/configs/am57xx_evm.h
+++ b/include/configs/am57xx_evm.h
@@ -63,7 +63,6 @@
 #define CONFIG_SUPPORT_EMMC_BOOT
 
 /* USB xHCI HOST */
-#define CONFIG_USB_HOST
 #define CONFIG_USB_XHCI_OMAP
 #define CONFIG_USB_STORAGE
 #define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2
@@ -86,4 +85,40 @@
 #define CONFIG_EEPROM_CHIP_ADDRESS 0x50
 #define CONFIG_EEPROM_BUS_ADDRESS 0
 
+/*
+ * Default to using SPI for environment, etc.
+ * 0x000000 - 0x040000 : QSPI.SPL (256KiB)
+ * 0x040000 - 0x140000 : QSPI.u-boot (1MiB)
+ * 0x140000 - 0x1C0000 : QSPI.u-boot-spl-os (512KiB)
+ * 0x1C0000 - 0x1D0000 : QSPI.u-boot-env (64KiB)
+ * 0x1D0000 - 0x1E0000 : QSPI.u-boot-env.backup1 (64KiB)
+ * 0x1E0000 - 0x9E0000 : QSPI.kernel (8MiB)
+ * 0x9E0000 - 0x2000000 : USERLAND
+ */
+#define CONFIG_SYS_SPI_KERNEL_OFFS      0x1E0000
+#define CONFIG_SYS_SPI_ARGS_OFFS        0x140000
+#define CONFIG_SYS_SPI_ARGS_SIZE        0x80000
+
+#ifdef CONFIG_SPL_BUILD
+#undef CONFIG_DM_SPI
+#undef CONFIG_DM_SPI_FLASH
+#undef CONFIG_SPL_MAX_SIZE
+#define CONFIG_SPL_MAX_SIZE             (256 << 10) /* 256 KiB */
+#endif
+
+/* SPI SPL */
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_DMA_SUPPORT
+#define CONFIG_TI_EDMA3
+#define CONFIG_SPL_SPI_LOAD
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SYS_SPI_U_BOOT_OFFS     0x40000
+
+/* SPI */
+#undef	CONFIG_OMAP3_SPI
+#define CONFIG_TI_SPI_MMAP
+#define CONFIG_SF_DEFAULT_SPEED                76800000
+#define CONFIG_SF_DEFAULT_MODE                 SPI_MODE_0
+#define CONFIG_QSPI_QUAD_SUPPORT
+
 #endif /* __CONFIG_AM57XX_EVM_H */
diff --git a/include/configs/aristainetos-common.h b/include/configs/aristainetos-common.h
index d87d40c..640227b 100644
--- a/include/configs/aristainetos-common.h
+++ b/include/configs/aristainetos-common.h
@@ -17,7 +17,6 @@
 
 #define CONFIG_MACH_TYPE	4501
 #define CONFIG_MMCROOT		"/dev/mmcblk0p1"
-#define PHYS_SDRAM_SIZE		(1u * 1024 * 1024 * 1024)
 
 /* Size of malloc() pool */
 #define CONFIG_SYS_MALLOC_LEN		(64 * SZ_1M)
diff --git a/include/configs/arndale.h b/include/configs/arndale.h
index b08f341..18e59fc 100644
--- a/include/configs/arndale.h
+++ b/include/configs/arndale.h
@@ -45,6 +45,7 @@
 
 #define CONFIG_S5P_PA_SYSRAM	0x02020000
 #define CONFIG_SMP_PEN_ADDR	CONFIG_S5P_PA_SYSRAM
+#define CONFIG_ARMV7_PSCI_NR_CPUS	4
 
 /* The PERIPHBASE in the CBAR register is wrong on the Arndale, so override it */
 #define CONFIG_ARM_GIC_BASE_ADDRESS	0x10480000
diff --git a/include/configs/axs101.h b/include/configs/axs10x.h
similarity index 87%
rename from include/configs/axs101.h
rename to include/configs/axs10x.h
index c0b68e2..b99248e 100644
--- a/include/configs/axs101.h
+++ b/include/configs/axs10x.h
@@ -1,12 +1,13 @@
 /*
- * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ * Copyright (C) 2013-2016 Synopsys, Inc. All rights reserved.
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#ifndef _CONFIG_AXS101_H_
-#define _CONFIG_AXS101_H_
+#ifndef _CONFIG_AXS10X_H_
+#define _CONFIG_AXS10X_H_
 
+#include <linux/sizes.h>
 /*
  *  CPU configuration
  */
@@ -24,13 +25,13 @@
 
 #define CONFIG_SYS_DDR_SDRAM_BASE	0x80000000
 #define CONFIG_SYS_SDRAM_BASE		CONFIG_SYS_DDR_SDRAM_BASE
-#define CONFIG_SYS_SDRAM_SIZE		0x20000000	/* 512 Mb */
+#define CONFIG_SYS_SDRAM_SIZE		SZ_512M
 
 #define CONFIG_SYS_INIT_SP_ADDR		\
 	(CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE)
 
-#define CONFIG_SYS_MALLOC_LEN		0x200000	/* 2 MB */
-#define CONFIG_SYS_BOOTM_LEN		0x2000000	/* 32 MB */
+#define CONFIG_SYS_MALLOC_LEN		SZ_2M
+#define CONFIG_SYS_BOOTM_LEN		SZ_32M
 #define CONFIG_SYS_LOAD_ADDR		0x82000000
 
 /*
@@ -113,7 +114,7 @@
  * Environment settings
  */
 #define CONFIG_ENV_IS_IN_EEPROM
-#define CONFIG_ENV_SIZE			0x00200		/* 512 bytes */
+#define CONFIG_ENV_SIZE			SZ_512
 #define CONFIG_ENV_OFFSET		0
 
 /*
@@ -127,7 +128,7 @@
  * Console configuration
  */
 #define CONFIG_SYS_LONGHELP
-#define CONFIG_SYS_CBSIZE		256
+#define CONFIG_SYS_CBSIZE		SZ_256
 #define CONFIG_SYS_BARGSIZE		CONFIG_SYS_CBSIZE
 #define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE + \
 						sizeof(CONFIG_SYS_PROMPT) + 16)
@@ -137,4 +138,4 @@
  */
 #define CONFIG_BOUNCE_BUFFER
 
-#endif /* _CONFIG_AXS101_H_ */
+#endif /* _CONFIG_AXS10X_H_ */
diff --git a/include/configs/bcm23550_w1d.h b/include/configs/bcm23550_w1d.h
index 8d041ed..770dd87 100644
--- a/include/configs/bcm23550_w1d.h
+++ b/include/configs/bcm23550_w1d.h
@@ -127,17 +127,9 @@
 /* Commands */
 #define CONFIG_FAT_WRITE
 
-/* Fastboot and USB OTG */
-#define CONFIG_USB_FUNCTION_FASTBOOT
-#define CONFIG_CMD_FASTBOOT
-#define CONFIG_FASTBOOT_FLASH
-#define CONFIG_FASTBOOT_FLASH_MMC_DEV	0
 #define CONFIG_SYS_CACHELINE_SIZE	64
-#define CONFIG_FASTBOOT_BUF_SIZE	0x1d000000
-#define CONFIG_FASTBOOT_BUF_ADDR	CONFIG_SYS_SDRAM_BASE
 #undef CONFIG_USB_GADGET_VBUS_DRAW
 #define CONFIG_USB_GADGET_VBUS_DRAW	0
-#define CONFIG_USB_GADGET_BCM_UDC_OTG_PHY
 #define CONFIG_USBID_ADDR		0x34052c46
 
 #define CONFIG_SYS_ICACHE_OFF
diff --git a/include/configs/bcm28155_ap.h b/include/configs/bcm28155_ap.h
index 889e5db..df0b2ba 100644
--- a/include/configs/bcm28155_ap.h
+++ b/include/configs/bcm28155_ap.h
@@ -126,15 +126,7 @@
 /* Commands */
 #define CONFIG_FAT_WRITE
 
-/* Fastboot and USB OTG */
-#define CONFIG_USB_FUNCTION_FASTBOOT
-#define CONFIG_CMD_FASTBOOT
-#define CONFIG_FASTBOOT_FLASH
-#define CONFIG_FASTBOOT_FLASH_MMC_DEV	0
 #define CONFIG_SYS_CACHELINE_SIZE	64
-#define CONFIG_FASTBOOT_BUF_SIZE	(CONFIG_SYS_SDRAM_SIZE - SZ_1M)
-#define CONFIG_FASTBOOT_BUF_ADDR	CONFIG_SYS_SDRAM_BASE
-#define CONFIG_USB_GADGET_BCM_UDC_OTG_PHY
 #define CONFIG_USBID_ADDR		0x34052c46
 
 #endif /* __BCM28155_AP_H */
diff --git a/include/configs/bcm_ep_board.h b/include/configs/bcm_ep_board.h
index d5888e8..50cd743 100644
--- a/include/configs/bcm_ep_board.h
+++ b/include/configs/bcm_ep_board.h
@@ -93,5 +93,6 @@
 /* Misc utility code */
 #define CONFIG_BOUNCE_BUFFER
 #define CONFIG_CRC32_VERIFY
+#define CONFIG_ARMV7_PSCI_NR_CPUS	4
 
 #endif /* __BCM_EP_BOARD_H */
diff --git a/include/configs/cgtqmx6eval.h b/include/configs/cgtqmx6eval.h
index dd03936..127a28a 100644
--- a/include/configs/cgtqmx6eval.h
+++ b/include/configs/cgtqmx6eval.h
@@ -251,7 +251,6 @@
 /* Physical Memory Map */
 #define CONFIG_NR_DRAM_BANKS	       1
 #define PHYS_SDRAM		       MMDC0_ARB_BASE_ADDR
-#define PHYS_SDRAM_SIZE			       (1u * 1024 * 1024 * 1024)
 
 #define CONFIG_SYS_SDRAM_BASE	       PHYS_SDRAM
 #define CONFIG_SYS_INIT_RAM_ADDR       IRAM_BASE_ADDR
diff --git a/include/configs/cm_fx6.h b/include/configs/cm_fx6.h
index 1f20ec3..c839b03 100644
--- a/include/configs/cm_fx6.h
+++ b/include/configs/cm_fx6.h
@@ -18,6 +18,7 @@
 #define CONFIG_MACH_TYPE		4273
 
 /* CMD */
+#define CONFIG_CMD_MTDPARTS
 
 /* MMC */
 #define CONFIG_SYS_FSL_USDHC_NUM	3
@@ -53,6 +54,20 @@
 #define CONFIG_SF_DEFAULT_SPEED		25000000
 #define CONFIG_SF_DEFAULT_MODE		(SPI_MODE_0)
 
+/* MTD support */
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_FDT_FIXUP_PARTITIONS
+#define CONFIG_MTD_DEVICE
+#define CONFIG_MTD_PARTITIONS
+#define CONFIG_SPI_FLASH_MTD
+#endif
+
+#define MTDIDS_DEFAULT		"nor0=spi0.0"
+#define MTDPARTS_DEFAULT	"mtdparts=spi0.0:" \
+				"768k(uboot)," \
+				"256k(uboot-environment)," \
+				"-(reserved)"
+
 /* Environment */
 #define CONFIG_ENV_IS_IN_SPI_FLASH
 #define CONFIG_ENV_SPI_MAX_HZ		CONFIG_SF_DEFAULT_SPEED
@@ -69,6 +84,8 @@
 	"stderr=serial,vga\0" \
 	"panel=HDMI\0" \
 	"autoload=no\0" \
+	"uImage=uImage-cm-fx6\0" \
+	"zImage=zImage-cm-fx6\0" \
 	"kernel=uImage-cm-fx6\0" \
 	"script=boot.scr\0" \
 	"dtb=cm-fx6.dtb\0" \
@@ -81,10 +98,12 @@
 	"video_dvi=mxcfb0:dev=dvi,1280x800M-32@50,if=RGB32\0" \
 	"doboot=bootm ${loadaddr}\0" \
 	"doloadfdt=false\0" \
-	"setboottypez=setenv kernel zImage-cm-fx6;" \
+	"mtdids=" MTDIDS_DEFAULT "\0" \
+	"mtdparts=" MTDPARTS_DEFAULT "\0" \
+	"setboottypez=setenv kernel ${zImage};" \
 		"setenv doboot bootz ${loadaddr} - ${fdtaddr};" \
 		"setenv doloadfdt true;\0" \
-	"setboottypem=setenv kernel uImage-cm-fx6;" \
+	"setboottypem=setenv kernel ${uImage};" \
 		"setenv doboot bootm ${loadaddr};" \
 		"setenv doloadfdt false;\0"\
 	"mmcroot=/dev/mmcblk0p2 rw rootwait\0" \
@@ -92,13 +111,13 @@
 	"nandroot=/dev/mtdblock4 rw\0" \
 	"nandrootfstype=ubifs\0" \
 	"mmcargs=setenv bootargs console=${console} root=${mmcroot} " \
-		"${video}\0" \
+		"${video} ${extrabootargs}\0" \
 	"sataargs=setenv bootargs console=${console} root=${sataroot} " \
-		"${video}\0" \
+		"${video} ${extrabootargs}\0" \
 	"nandargs=setenv bootargs console=${console} " \
 		"root=${nandroot} " \
 		"rootfstype=${nandrootfstype} " \
-		"${video}\0" \
+		"${video} ${extrabootargs}\0" \
 	"nandboot=if run nandloadkernel; then " \
 			"run nandloadfdt;" \
 			"run setboottypem;" \
@@ -155,7 +174,7 @@
 	"run setupnandboot;" \
 	"run nandboot;"
 
-#define CONFIG_PREBOOT		"usb start"
+#define CONFIG_PREBOOT		"usb start;sf probe"
 
 /* SPI */
 #define CONFIG_SPI
diff --git a/include/configs/cm_t43.h b/include/configs/cm_t43.h
index 9bb975a..5d94f13 100644
--- a/include/configs/cm_t43.h
+++ b/include/configs/cm_t43.h
@@ -60,7 +60,6 @@
 #define CONFIG_SYS_RX_ETH_BUFFER	64
 
 /* USB support */
-#define CONFIG_USB_HOST
 #define CONFIG_USB_XHCI_OMAP
 #define CONFIG_USB_STORAGE
 #define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2
diff --git a/include/configs/cm_t54.h b/include/configs/cm_t54.h
index 68851ee..8e9444e 100644
--- a/include/configs/cm_t54.h
+++ b/include/configs/cm_t54.h
@@ -69,7 +69,6 @@
 #define CONFIG_SYS_SCSI_MAX_DEVICE	(CONFIG_SYS_SCSI_MAX_SCSI_ID * \
 						CONFIG_SYS_SCSI_MAX_LUN)
 /* USB UHH support options */
-#define CONFIG_USB_HOST
 #define CONFIG_USB_EHCI
 #define CONFIG_USB_EHCI_OMAP
 #define CONFIG_USB_STORAGE
diff --git a/include/configs/colibri_imx7.h b/include/configs/colibri_imx7.h
new file mode 100644
index 0000000..9da219c
--- /dev/null
+++ b/include/configs/colibri_imx7.h
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2016 Toradex AG
+ *
+ * Configuration settings for the Colibri iMX7 module.
+ *
+ * based on mx7dsabresd.h:
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __COLIBRI_IMX7_CONFIG_H
+#define __COLIBRI_IMX7_CONFIG_H
+
+#include "mx7_common.h"
+
+#define CONFIG_SYS_THUMB_BUILD
+#define CONFIG_USE_ARCH_MEMCPY
+#define CONFIG_USE_ARCH_MEMSET
+
+/*#define CONFIG_DBG_MONITOR*/
+#define PHYS_SDRAM_SIZE			SZ_512M
+
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_BOARD_LATE_INIT
+
+#define CONFIG_DISPLAY_BOARDINFO_LATE
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN		(32 * SZ_1M)
+
+/* Uncomment to enable secure boot support */
+/* #define CONFIG_SECURE_BOOT */
+#define CONFIG_CSF_SIZE			0x4000
+
+#define CONFIG_CMD_BMODE
+
+/* Network */
+#define CONFIG_FEC_MXC
+#define CONFIG_MII
+#define CONFIG_FEC_XCV_TYPE             RMII
+#define CONFIG_ETHPRIME                 "FEC"
+#define CONFIG_FEC_MXC_PHYADDR          0
+
+#define CONFIG_PHYLIB
+#define CONFIG_PHY_MICREL
+#define CONFIG_TFTP_TSIZE
+#define CONFIG_IP_DEFRAG
+#define CONFIG_TFTP_BLOCKSIZE		16384
+
+/* ENET1 */
+#define IMX_FEC_BASE			ENET_IPS_BASE_ADDR
+
+/* MMC Config*/
+#define CONFIG_SYS_FSL_ESDHC_ADDR	0
+#define CONFIG_SYS_FSL_USDHC_NUM	1
+
+#undef CONFIG_BOOTM_PLAN9
+#undef CONFIG_BOOTM_RTEMS
+
+/* I2C configs */
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_I2C_MXC_I2C1		/* enable I2C bus 1 */
+#define CONFIG_SYS_I2C_SPEED		100000
+
+#define CONFIG_IPADDR			192.168.10.2
+#define CONFIG_NETMASK			255.255.255.0
+#define CONFIG_SERVERIP			192.168.10.1
+
+#define MEM_LAYOUT_ENV_SETTINGS \
+	"fdt_addr_r=0x82000000\0" \
+	"fdt_high=0xffffffff\0" \
+	"initrd_high=0xffffffff\0" \
+	"kernel_addr_r=0x81000000\0" \
+	"ramdisk_addr_r=0x82100000\0"
+
+#define SD_BOOTCMD \
+	"sdargs=root=/dev/mmcblk0p2 rw rootwait\0"	\
+	"sdboot=run setup; setenv bootargs ${defargs} ${sdargs} " \
+	"${setupargs} ${vidargs}; echo Booting from MMC/SD card...; " \
+	"run m4boot && " \
+	"load mmc 0:1 ${kernel_addr_r} ${kernel_file} && " \
+	"load mmc 0:1 ${fdt_addr_r} ${soc}-colibri-${fdt_board}.dtb && " \
+	"run fdt_fixup && bootz ${kernel_addr_r} - ${fdt_addr_r}\0" \
+
+#define NFS_BOOTCMD \
+	"nfsargs=ip=:::::eth0: root=/dev/nfs\0"	\
+	"nfsboot=run setup; " \
+		"setenv bootargs ${defargs} ${nfsargs} " \
+		"${setupargs} ${vidargs}; echo Booting from NFS...;" \
+		"dhcp ${kernel_addr_r} && "	\
+		"tftp ${fdt_addr_r} ${soc}-colibri-${fdt_board}.dtb && " \
+		"run fdt_fixup && bootz ${kernel_addr_r} - ${fdt_addr_r}\0" \
+
+#define UBI_BOOTCMD	\
+	"ubiargs=ubi.mtd=ubi root=ubi0:rootfs rootfstype=ubifs " \
+		"ubi.fm_autoconvert=1\0" \
+	"ubiboot=run setup; " \
+		"setenv bootargs ${defargs} ${ubiargs} " \
+		"${setupargs} ${vidargs}; echo Booting from NAND...; " \
+		"ubi part ubi && run m4boot && " \
+		"ubi read ${kernel_addr_r} kernel && " \
+		"ubi read ${fdt_addr_r} dtb && " \
+		"run fdt_fixup && bootz ${kernel_addr_r} - ${fdt_addr_r}\0" \
+
+#define CONFIG_BOOTCOMMAND "run ubiboot; run sdboot; run nfsboot"
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	MEM_LAYOUT_ENV_SETTINGS \
+	NFS_BOOTCMD \
+	SD_BOOTCMD \
+	UBI_BOOTCMD \
+	"console=ttymxc0\0" \
+	"defargs=\0" \
+	"fdt_board=eval-v3\0" \
+	"fdt_fixup=;\0" \
+	"m4boot=;\0" \
+	"ip_dyn=yes\0" \
+	"kernel_file=zImage\0" \
+	"mtdparts=" MTDPARTS_DEFAULT "\0" \
+	"setethupdate=if env exists ethaddr; then; else setenv ethaddr " \
+		"00:14:2d:00:00:00; fi; tftpboot ${loadaddr} " \
+		"${board}/flash_eth.img && source ${loadaddr}\0" \
+	"setsdupdate=mmc rescan && setenv interface mmc && " \
+		"fatload ${interface} 0:1 ${loadaddr} " \
+		"${board}/flash_blk.img && source ${loadaddr}\0" \
+	"setup=setenv setupargs " \
+		"console=tty1 console=${console}" \
+		",${baudrate}n8 ${memargs} consoleblank=0 ${mtdparts}\0" \
+	"setupdate=run setsdupdate || run setusbupdate || run setethupdate\0" \
+	"setusbupdate=usb start && setenv interface usb && " \
+		"fatload ${interface} 0:1 ${loadaddr} " \
+		"${board}/flash_blk.img && source ${loadaddr}\0" \
+	"splashpos=m,m\0" \
+	"videomode=video=ctfb:x:640,y:480,depth:18,pclk:39722,le:48,ri:16,up:33,lo:10,hs:96,vs:2,sync:0,vmode:0\0" \
+
+/* Miscellaneous configurable options */
+#define CONFIG_SYS_LONGHELP
+
+#define CONFIG_SYS_MEMTEST_START	0x80000000
+#define CONFIG_SYS_MEMTEST_END		(CONFIG_SYS_MEMTEST_START + 0x0c000000)
+
+#define CONFIG_SYS_LOAD_ADDR		CONFIG_LOADADDR
+#define CONFIG_SYS_HZ			1000
+
+#define CONFIG_STACKSIZE		SZ_128K
+
+/* Physical Memory Map */
+#define CONFIG_NR_DRAM_BANKS		1
+#define PHYS_SDRAM			MMDC0_ARB_BASE_ADDR
+
+#define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM
+#define CONFIG_SYS_INIT_RAM_ADDR	IRAM_BASE_ADDR
+#define CONFIG_SYS_INIT_RAM_SIZE	IRAM_SIZE
+
+#define CONFIG_SYS_INIT_SP_OFFSET \
+	(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR \
+	(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
+
+/* FLASH and environment organization */
+#define CONFIG_SYS_NO_FLASH
+#define CONFIG_ENV_IS_IN_NAND
+
+#if defined(CONFIG_ENV_IS_IN_MMC)
+#define CONFIG_SYS_MMC_ENV_DEV		0   /* USDHC1 */
+#define CONFIG_SYS_MMC_ENV_PART		0	/* user area */
+#define CONFIG_MMCROOT			"/dev/mmcblk0p2"  /* USDHC1 */
+#define CONFIG_ENV_OFFSET		(8 * SZ_64K)
+#elif defined(CONFIG_ENV_IS_IN_NAND)
+#define CONFIG_ENV_OFFSET		(4 * 1024 * 1024)
+#define CONFIG_ENV_SECT_SIZE		(128 * 1024)
+#define CONFIG_ENV_SIZE			CONFIG_ENV_SECT_SIZE
+#endif
+
+#define CONFIG_NAND_MXS
+#define CONFIG_CMD_NAND_TRIMFFS
+
+/* NAND stuff */
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define CONFIG_SYS_NAND_BASE		0x40000000
+#define CONFIG_SYS_NAND_5_ADDR_CYCLE
+#define CONFIG_SYS_NAND_ONFI_DETECTION
+#define CONFIG_SYS_NAND_MX7_GPMI_62_ECC_BYTES
+#define CONFIG_CMD_NAND_TORTURE
+
+/* UBI stuff */
+#define CONFIG_RBTREE
+#define CONFIG_LZO
+#define CONFIG_CMD_UBI
+#define CONFIG_MTD_UBI_FASTMAP
+#define CONFIG_CMD_UBIFS	/* increases size by almost 60 KB */
+
+/* Dynamic MTD partition support */
+#define CONFIG_CMD_MTDPARTS	/* Enable 'mtdparts' command line support */
+#define CONFIG_MTD_PARTITIONS
+#define CONFIG_MTD_DEVICE	/* needed for mtdparts commands */
+#define MTDIDS_DEFAULT		"nand0=gpmi-nand"
+#define MTDPARTS_DEFAULT	"mtdparts=gpmi-nand:"		\
+				"512k(mx7-bcb),"		\
+				"3584k(u-boot)ro,"		\
+				"512k(u-boot-env),"		\
+				"-(ubi)"
+
+/* DMA stuff, needed for GPMI/MXS NAND support */
+#define CONFIG_APBH_DMA
+#define CONFIG_APBH_DMA_BURST
+#define CONFIG_APBH_DMA_BURST8
+
+/* USB Configs */
+#define CONFIG_USB_STORAGE
+#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
+
+#define CONFIG_MXC_USB_PORTSC		(PORT_PTS_UTMI | PORT_PTS_PTW)
+#define CONFIG_MXC_USB_FLAGS		0
+#define CONFIG_USB_MAX_CONTROLLER_COUNT 2
+
+#define CONFIG_IMX_THERMAL
+
+#define CONFIG_USBD_HS
+
+#define CONFIG_USB_FUNCTION_MASS_STORAGE
+
+/* USB Device Firmware Update support */
+#define CONFIG_USB_FUNCTION_DFU
+#define CONFIG_DFU_MMC
+#define CONFIG_SYS_DFU_DATA_BUF_SIZE	SZ_16M
+#define DFU_DEFAULT_POLL_TIMEOUT	300
+
+#define CONFIG_VIDEO
+#ifdef CONFIG_VIDEO
+#define CONFIG_CFB_CONSOLE
+#define CONFIG_VIDEO_MXS
+#define CONFIG_VIDEO_LOGO
+#define CONFIG_VIDEO_SW_CURSOR
+#define CONFIG_VGA_AS_SINGLE_DEVICE
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+#define CONFIG_SPLASH_SCREEN
+#define CONFIG_SPLASH_SCREEN_ALIGN
+#define CONFIG_CMD_BMP
+#define CONFIG_BMP_16BPP
+#define CONFIG_VIDEO_BMP_RLE8
+#define CONFIG_VIDEO_BMP_LOGO
+#endif
+
+#endif
diff --git a/include/configs/conga-qeval20-qa3-e3845.h b/include/configs/conga-qeval20-qa3-e3845.h
index 4c37d5e..652e073 100644
--- a/include/configs/conga-qeval20-qa3-e3845.h
+++ b/include/configs/conga-qeval20-qa3-e3845.h
@@ -15,6 +15,7 @@
 
 #define CONFIG_SYS_MONITOR_LEN		(1 << 20)
 #define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_BOARD_LATE_INIT
 #define CONFIG_ARCH_EARLY_INIT_R
 #define CONFIG_ARCH_MISC_INIT
 
@@ -41,23 +42,24 @@
 #define CONFIG_CMD_BMP
 
 #define CONFIG_ENV_SECT_SIZE		0x1000
-#define CONFIG_ENV_OFFSET		0x007fe000
+#define CONFIG_ENV_OFFSET		0x006ef000
 
 #undef CONFIG_BOOTARGS
 #undef CONFIG_BOOTCOMMAND
 
 #define CONFIG_BOOTARGS		\
-	"root=/dev/sda1 ro quiet"
+	"root=/dev/sda2 ro quiet"
 #define CONFIG_BOOTCOMMAND	\
-	"load scsi 0:1 03000000 /boot/vmlinuz-4.2.0-26-generic;" \
-	"load scsi 0:1 04000000 /boot/initrd.img-4.2.0-26-generic;" \
+	"load scsi 0:2 03000000 /boot/vmlinuz-${kernel-ver}-generic;"	\
+	"load scsi 0:2 04000000 /boot/initrd.img-${kernel-ver}-generic;" \
 	"run boot"
 
 #undef CONFIG_EXTRA_ENV_SETTINGS
 #define CONFIG_EXTRA_ENV_SETTINGS				\
+	"kernel-ver=4.4.0-22\0"					\
 	"boot=zboot 03000000 0 04000000 ${filesize}\0"		\
 	"upd_uboot=tftp 100000 conga/u-boot.rom;"		\
-		"sf probe;sf update 100000 0 7fe000\0"
+		"sf probe;sf update 100000 0 800000;saveenv\0"
 
 #define CONFIG_PREBOOT
 
diff --git a/include/configs/controlcenterd.h b/include/configs/controlcenterd.h
index 30c2831..1a63d03 100644
--- a/include/configs/controlcenterd.h
+++ b/include/configs/controlcenterd.h
@@ -26,10 +26,6 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
-#ifdef CONFIG_36BIT
-#define CONFIG_PHYS_64BIT
-#endif
-
 #ifdef CONFIG_SDCARD
 #define CONFIG_RAMBOOT_SDCARD
 #endif
@@ -447,7 +443,7 @@
 	"consoledev=ttyS1\0"					\
 	"ramdiskaddr=2000000\0"					\
 	"ramdiskfile=rootfs.ext2.gz.uboot\0"			\
-	"fdtaddr=c00000\0"					\
+	"fdtaddr=1e00000\0"					\
 	"fdtfile=controlcenterd.dtb\0"				\
 	"bdev=sda3\0"
 
diff --git a/include/configs/corenet_ds.h b/include/configs/corenet_ds.h
index 4a770b0..0c99e9f 100644
--- a/include/configs/corenet_ds.h
+++ b/include/configs/corenet_ds.h
@@ -708,7 +708,7 @@
 	"consoledev=ttyS0\0"					\
 	"ramdiskaddr=2000000\0"					\
 	"ramdiskfile=p4080ds/ramdisk.uboot\0"			\
-	"fdtaddr=c00000\0"					\
+	"fdtaddr=1e00000\0"					\
 	"fdtfile=p4080ds/p4080ds.dtb\0"				\
 	"bdev=sda3\0"
 
diff --git a/include/configs/corvus.h b/include/configs/corvus.h
index e6a811a..28ea15b 100644
--- a/include/configs/corvus.h
+++ b/include/configs/corvus.h
@@ -95,6 +95,7 @@
 
 /* Ethernet */
 #define CONFIG_MACB
+#define CONFIG_PHYLIB
 #define CONFIG_RMII
 #define CONFIG_NET_RETRY_COUNT		20
 #define CONFIG_AT91_WANTS_COMMON_PHY
diff --git a/include/configs/cyrus.h b/include/configs/cyrus.h
index 708d5f7..8e0ed06 100644
--- a/include/configs/cyrus.h
+++ b/include/configs/cyrus.h
@@ -11,8 +11,6 @@
 
 #define CONFIG_CYRUS
 
-#define CONFIG_PHYS_64BIT
-
 #if !defined(CONFIG_PPC_P5020) && !defined(CONFIG_PPC_P5040)
 #error Must call Cyrus CONFIG with a specific CPU enabled.
 #endif
@@ -520,7 +518,7 @@
 "ubootaddr=" __stringify(CONFIG_SYS_TEXT_BASE) "\0"			\
 "consoledev=ttyS0\0"					\
 "ramdiskaddr=2000000\0"					\
-"fdtaddr=c00000\0"					\
+"fdtaddr=1e00000\0"					\
 "bdev=sda3\0"
 
 #define CONFIG_HDBOOT					\
diff --git a/include/configs/dfi-bt700.h b/include/configs/dfi-bt700.h
new file mode 100644
index 0000000..23d8a0a
--- /dev/null
+++ b/include/configs/dfi-bt700.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <configs/x86-common.h>
+
+#define CONFIG_SYS_MONITOR_LEN		(1 << 20)
+#define CONFIG_BOARD_EARLY_INIT_F
+
+#ifndef CONFIG_INTERNAL_UART
+/* Use BayTrail internal HS UART which is memory-mapped */
+#undef  CONFIG_SYS_NS16550_PORT_MAPPED
+#endif
+
+#define CONFIG_PCI_PNP
+
+#define CONFIG_STD_DEVICES_SETTINGS     "stdin=serial\0" \
+					"stdout=serial\0" \
+					"stderr=serial\0"
+
+#define CONFIG_SCSI_DEV_LIST		\
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SATA}, \
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SATA_ALT}
+
+#define CONFIG_MMC
+#define CONFIG_SDHCI
+#define CONFIG_GENERIC_MMC
+#define CONFIG_MMC_SDMA
+
+#undef CONFIG_USB_MAX_CONTROLLER_COUNT
+#define CONFIG_USB_MAX_CONTROLLER_COUNT		1
+
+#define CONFIG_USB_HOST_ETHER
+#define CONFIG_USB_ETHER_ASIX
+#define CONFIG_USB_ETHER_SMSC95XX
+#define CONFIG_USB_ETHER_MCS7830
+#define CONFIG_USB_ETHER_RTL8152
+
+#define VIDEO_IO_OFFSET				0
+#define CONFIG_X86EMU_RAW_IO
+#define CONFIG_CMD_BMP
+
+#define CONFIG_ENV_SECT_SIZE		0x1000
+#define CONFIG_ENV_OFFSET		0x006ef000
+
+#undef CONFIG_BOOTARGS
+#undef CONFIG_BOOTCOMMAND
+
+#define CONFIG_BOOTARGS		\
+	"root=/dev/sda1 ro quiet"
+#define CONFIG_BOOTCOMMAND	\
+	"load scsi 0:1 03000000 /boot/vmlinuz-${kernel-ver}-generic;"	\
+	"load scsi 0:1 04000000 /boot/initrd.img-${kernel-ver}-generic;" \
+	"run boot"
+
+#undef CONFIG_EXTRA_ENV_SETTINGS
+#define CONFIG_EXTRA_ENV_SETTINGS				\
+	"kernel-ver=4.4.0-24\0"					\
+	"boot=zboot 03000000 0 04000000 ${filesize}\0"		\
+	"upd_uboot=usb reset;tftp 100000 dfi/u-boot.rom;"	\
+		"sf probe;sf update 100000 0 800000;saveenv\0"
+
+#define CONFIG_PREBOOT
+
+#endif	/* __CONFIG_H */
diff --git a/include/configs/dra7xx_evm.h b/include/configs/dra7xx_evm.h
index 0d51aeb..b66949f 100644
--- a/include/configs/dra7xx_evm.h
+++ b/include/configs/dra7xx_evm.h
@@ -20,7 +20,6 @@
 #endif
 
 #define CONFIG_VERY_BIG_RAM
-#define CONFIG_PHYS_64BIT
 #define CONFIG_NR_DRAM_BANKS		2
 #define CONFIG_MAX_MEM_MAPPED		0x80000000
 
@@ -157,7 +156,7 @@
 /* SPI */
 #undef	CONFIG_OMAP3_SPI
 #define CONFIG_TI_SPI_MMAP
-#define CONFIG_SF_DEFAULT_SPEED                64000000
+#define CONFIG_SF_DEFAULT_SPEED                76800000
 #define CONFIG_SF_DEFAULT_MODE                 SPI_MODE_0
 #define CONFIG_QSPI_QUAD_SUPPORT
 
@@ -210,7 +209,6 @@
 #define CONFIG_SUPPORT_EMMC_BOOT
 
 /* USB xHCI HOST */
-#define CONFIG_USB_HOST
 #define CONFIG_USB_XHCI_OMAP
 #define CONFIG_USB_STORAGE
 #define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2
diff --git a/include/configs/dragonboard410c.h b/include/configs/dragonboard410c.h
index 4b00922..1dbe219 100644
--- a/include/configs/dragonboard410c.h
+++ b/include/configs/dragonboard410c.h
@@ -84,8 +84,8 @@
 
 #define BOOT_TARGET_DEVICES(func) \
 	func(USB, usb, 0) \
-	func(MMC, mmc, 0) \
 	func(MMC, mmc, 1) \
+	func(MMC, mmc, 0) \
 	func(DHCP, dhcp, na)
 
 #include <config_distro_bootcmd.h>
@@ -126,6 +126,8 @@
 	"fdtfile=apq8016-sbc.dtb\0" \
 	"fdt_addr_r=0x83000000\0"\
 	"ramdisk_addr_r=0x84000000\0"\
+	"scriptaddr=0x90000000\0"\
+	"pxefile_addr_r=0x90100000\0"\
 	BOOTENV
 
 #define CONFIG_ENV_IS_NOWHERE
diff --git a/include/configs/duovero.h b/include/configs/duovero.h
index 98afe27..299c0d5 100644
--- a/include/configs/duovero.h
+++ b/include/configs/duovero.h
@@ -29,7 +29,6 @@
 #define CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS
 
 /* USB UHH support options */
-#define CONFIG_USB_HOST
 #define CONFIG_USB_EHCI
 #define CONFIG_USB_EHCI_OMAP
 #define CONFIG_USB_STORAGE
diff --git a/include/configs/el6x_common.h b/include/configs/el6x_common.h
new file mode 100644
index 0000000..55ef612
--- /dev/null
+++ b/include/configs/el6x_common.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) Stefano Babic <sbabic@denx.de>
+ *
+ * Configuration settings for the E+L i.MX6Q DO82 board.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __EL6Q_COMMON_CONFIG_H
+#define __EL6Q_COMMON_CONFIG_H
+
+#define CONFIG_BOARD_NAME		EL6Q
+
+#include <config_distro_defaults.h>
+#include "mx6_common.h"
+
+#define CONFIG_IMX_THERMAL
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN		(10 * SZ_1M)
+
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_BOARD_LATE_INIT
+
+#define CONFIG_MXC_UART
+
+#ifdef CONFIG_SPL
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_MMC_SUPPORT
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	(64 * 1024)
+#define CONFIG_SPL_SPI_LOAD
+#include "imx6_spl.h"
+#endif
+
+/* MMC Configs */
+#define CONFIG_SYS_FSL_ESDHC_ADDR	0
+#define CONFIG_SYS_FSL_USDHC_NUM	2
+
+/* I2C config */
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_I2C_MXC_I2C1		/* enable I2C bus 1 */
+#define CONFIG_SYS_I2C_MXC_I2C2		/* enable I2C bus 2 */
+#define CONFIG_SYS_I2C_MXC_I2C3		/* enable I2C bus 3 */
+#define CONFIG_SYS_I2C_SPEED			100000
+
+/* PMIC */
+#define CONFIG_POWER
+#define CONFIG_POWER_I2C
+#define CONFIG_POWER_PFUZE100
+#define CONFIG_POWER_PFUZE100_I2C_ADDR	0x08
+
+/* Commands */
+#define CONFIG_MXC_SPI
+#define CONFIG_SF_DEFAULT_BUS		3
+#define CONFIG_SF_DEFAULT_CS		0
+#define CONFIG_SF_DEFAULT_SPEED		20000000
+#define CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+#define CONFIG_MXC_UART_BASE	UART2_BASE
+#define CONFIG_BAUDRATE             115200
+
+/* Command definition */
+
+#define CONFIG_CMD_BMODE
+#define CONFIG_CMD_BOOTZ
+#undef CONFIG_CMD_IMLS
+
+#define CONFIG_BOARD_NAME	EL6Q
+
+#define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+#define CONFIG_EXTRA_ENV_SETTINGS                                               \
+	"board="__stringify(CONFIG_BOARD_NAME)"\0"                              \
+	"cma_size="__stringify(EL6Q_CMA_SIZE)"\0"                               \
+	"chp_size="__stringify(EL6Q_COHERENT_POOL_SIZE)"\0"                     \
+	"console=" CONFIG_CONSOLE_DEV "\0" 					\
+	"fdtfile=undefined\0" \
+	"fdt_high=0xffffffff\0" \
+	"fdt_addr_r=0x18000000\0" \
+	"fdt_addr=0x18000000\0" \
+	"findfdt=setenv fdtfile " CONFIG_DEFAULT_FDT_FILE "\0"                  \
+	"kernel_addr_r=" __stringify(CONFIG_LOADADDR) "\0" \
+	"scriptaddr=" __stringify(CONFIG_LOADADDR) "\0" \
+	"pxefile_addr_r=" __stringify(CONFIG_LOADADDR) "\0" \
+	BOOTENV
+
+#define BOOT_TARGET_DEVICES(func) \
+	func(MMC, mmc, 0) \
+	func(MMC, mmc, 1) \
+	func(PXE, PXE, na) \
+	func(DHCP, dhcp, na)
+
+#define CONFIG_BOOTCOMMAND \
+	   "run findfdt; " \
+	   "run distro_bootcmd"
+
+#include <config_distro_bootcmd.h>
+
+#define CONFIG_ARP_TIMEOUT     200UL
+
+#define CONFIG_CMD_MEMTEST
+
+#define CONFIG_SYS_MEMTEST_START       0x10000000
+#define CONFIG_SYS_MEMTEST_END         0x10800000
+#define CONFIG_SYS_MEMTEST_SCRATCH     0x10800000
+
+#define CONFIG_STACKSIZE               (128 * 1024)
+
+/* Physical Memory Map */
+#define CONFIG_NR_DRAM_BANKS           1
+#define PHYS_SDRAM                     MMDC0_ARB_BASE_ADDR
+
+#define CONFIG_SYS_SDRAM_BASE          PHYS_SDRAM
+#define CONFIG_SYS_INIT_RAM_ADDR       IRAM_BASE_ADDR
+#define CONFIG_SYS_INIT_RAM_SIZE       IRAM_SIZE
+
+#define CONFIG_SYS_INIT_SP_OFFSET \
+	(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR \
+	(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
+
+/* FLASH and environment organization */
+#define CONFIG_SYS_NO_FLASH
+
+#define CONFIG_ENV_SIZE			(8 * 1024)
+
+#define CONFIG_ENV_IS_IN_MMC
+
+#if defined(CONFIG_ENV_IS_IN_MMC)
+#define CONFIG_SYS_MMC_ENV_DEV		1
+#define CONFIG_SYS_MMC_ENV_PART		2
+#define CONFIG_ENV_OFFSET		0x0
+#endif
+
+#endif                         /* __EL6Q_COMMON_CONFIG_H */
diff --git a/include/configs/evb_rk3288.h b/include/configs/evb_rk3288.h
new file mode 100644
index 0000000..342557f
--- /dev/null
+++ b/include/configs/evb_rk3288.h
@@ -0,0 +1,26 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define ROCKCHIP_DEVICE_SETTINGS
+#include <configs/rk3288_common.h>
+
+#define CONFIG_SPL_MMC_SUPPORT
+
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_SYS_MMC_ENV_DEV 1
+/* SPL @ 32k for ~36k
+ * ENV @ 96k
+ * u-boot @ 128K
+ */
+#define CONFIG_ENV_OFFSET (96 * 1024)
+
+#define CONFIG_SYS_WHITE_ON_BLACK
+#define CONFIG_CONSOLE_SCROLL_LINES		10
+
+#endif
diff --git a/include/configs/evb_rk3399.h b/include/configs/evb_rk3399.h
new file mode 100644
index 0000000..047850a
--- /dev/null
+++ b/include/configs/evb_rk3399.h
@@ -0,0 +1,26 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __EVB_RK3399_H
+#define __EVB_RK3399_H
+
+#include <configs/rk3399_common.h>
+
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_SYS_MMC_ENV_DEV 0
+/*
+ * SPL @ 32k for ~36k
+ * ENV @ 96k
+ * u-boot @ 128K
+ */
+#define CONFIG_ENV_OFFSET (96 * 1024)
+
+#define SDRAM_BANK_SIZE			(2UL << 30)
+
+#define CONFIG_SYS_WHITE_ON_BLACK
+#define CONFIG_CONSOLE_SCROLL_LINES		10
+
+#endif
diff --git a/include/configs/fennec_rk3288.h b/include/configs/fennec_rk3288.h
new file mode 100644
index 0000000..342557f
--- /dev/null
+++ b/include/configs/fennec_rk3288.h
@@ -0,0 +1,26 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define ROCKCHIP_DEVICE_SETTINGS
+#include <configs/rk3288_common.h>
+
+#define CONFIG_SPL_MMC_SUPPORT
+
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_SYS_MMC_ENV_DEV 1
+/* SPL @ 32k for ~36k
+ * ENV @ 96k
+ * u-boot @ 128K
+ */
+#define CONFIG_ENV_OFFSET (96 * 1024)
+
+#define CONFIG_SYS_WHITE_ON_BLACK
+#define CONFIG_CONSOLE_SCROLL_LINES		10
+
+#endif
diff --git a/include/configs/ge_bx50v3.h b/include/configs/ge_bx50v3.h
index 4de2460..7a54546 100644
--- a/include/configs/ge_bx50v3.h
+++ b/include/configs/ge_bx50v3.h
@@ -32,8 +32,6 @@
 #define CONFIG_MXC_UART_BASE	UART3_BASE
 #define CONFIG_CONSOLE_DEV	"ttymxc2"
 
-#define PHYS_SDRAM_SIZE		(2u * 1024 * 1024 * 1024)
-
 #define CONFIG_SUPPORT_EMMC_BOOT
 
 
diff --git a/include/configs/gw_ventana.h b/include/configs/gw_ventana.h
index 982ddba..1bd13fe 100644
--- a/include/configs/gw_ventana.h
+++ b/include/configs/gw_ventana.h
@@ -33,6 +33,8 @@
 #include "imx6_spl.h"                  /* common IMX6 SPL configuration */
 #include "mx6_common.h"
 #undef CONFIG_SPL_EXT_SUPPORT
+#undef CONFIG_DISPLAY_BOARDINFO
+#define CONFIG_DISPLAY_BOARDINFO_LATE
 
 #define CONFIG_MACH_TYPE	4520   /* Gateworks Ventana Platform */
 
@@ -269,15 +271,13 @@
 /* Environment */
 #define CONFIG_IPADDR             192.168.1.1
 #define CONFIG_SERVERIP           192.168.1.146
-#define HWCONFIG_DEFAULT \
-	"hwconfig=rs232;" \
-	"dio0:mode=gpio;dio1:mode=gpio;dio2:mode=gpio;dio3:mode=gpio\0" \
 
 #define CONFIG_EXTRA_ENV_SETTINGS_COMMON \
+	"pcidisable=1\0" \
 	"usb_pgood_delay=2000\0" \
 	"console=ttymxc1\0" \
 	"bootdevs=usb mmc sata flash\0" \
-	HWCONFIG_DEFAULT \
+	"hwconfig=_UNKNOWN_\0" \
 	"video=\0" \
 	\
 	"mtdparts=" MTDPARTS_DEFAULT "\0" \
diff --git a/include/configs/jetson-tk1.h b/include/configs/jetson-tk1.h
index 953c088..2b172a5 100644
--- a/include/configs/jetson-tk1.h
+++ b/include/configs/jetson-tk1.h
@@ -61,6 +61,7 @@
 #include "tegra-common-post.h"
 
 #define CONFIG_ARMV7_PSCI			1
+#define CONFIG_ARMV7_PSCI_NR_CPUS		4
 /* Reserve top 1M for secure RAM */
 #define CONFIG_ARMV7_SECURE_BASE		0xfff00000
 #define CONFIG_ARMV7_SECURE_RESERVE_SIZE	0x00100000
diff --git a/include/configs/k2g_evm.h b/include/configs/k2g_evm.h
index f8bba67..71b0037 100644
--- a/include/configs/k2g_evm.h
+++ b/include/configs/k2g_evm.h
@@ -73,4 +73,10 @@
 #define CONFIG_SF_DEFAULT_BUS		1
 #define CONFIG_SF_DEFAULT_CS		0
 
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_CADENCE_QSPI
+#define CONFIG_CQSPI_REF_CLK 384000000
+#define CONFIG_CQSPI_DECODER 0x0
+#endif
+
 #endif /* __CONFIG_K2G_EVM_H */
diff --git a/include/configs/katmai.h b/include/configs/katmai.h
index 9513c6d..e3fede5 100644
--- a/include/configs/katmai.h
+++ b/include/configs/katmai.h
@@ -29,7 +29,6 @@
 /*
  * Enable this board for more than 2GB of SDRAM
  */
-#define CONFIG_PHYS_64BIT
 #define	CONFIG_VERY_BIG_RAM
 
 /*
diff --git a/include/configs/km/kmp204x-common.h b/include/configs/km/kmp204x-common.h
index 5bdda22..8166c86 100644
--- a/include/configs/km/kmp204x-common.h
+++ b/include/configs/km/kmp204x-common.h
@@ -8,7 +8,6 @@
 #ifndef _CONFIG_KMP204X_H
 #define _CONFIG_KMP204X_H
 
-#define CONFIG_PHYS_64BIT
 #define CONFIG_PPC_P2041
 
 #define CONFIG_SYS_TEXT_BASE	0xfff40000
diff --git a/include/configs/kylin_rk3036.h b/include/configs/kylin_rk3036.h
index b16c03f..e8ca76d 100644
--- a/include/configs/kylin_rk3036.h
+++ b/include/configs/kylin_rk3036.h
@@ -26,7 +26,6 @@
 /* Enable gpt partition table */
 #define CONFIG_CMD_GPT
 #define CONFIG_RANDOM_UUID
-#define CONFIG_EFI_PARTITION
 #define PARTS_DEFAULT \
 	"uuid_disk=${uuid_gpt_disk};" \
 	"name=loader,start=32K,size=4000K,uuid=${uuid_gpt_loader};" \
diff --git a/include/configs/ls1012aqds.h b/include/configs/ls1012aqds.h
index fcf402c..6e31ca0 100644
--- a/include/configs/ls1012aqds.h
+++ b/include/configs/ls1012aqds.h
@@ -28,11 +28,11 @@
 #define CONFIG_SYS_I2C_FPGA_ADDR	0x66
 #define QIXIS_LBMAP_BRDCFG_REG		0x04
 #define QIXIS_LBMAP_SWITCH		6
-#define QIXIS_LBMAP_MASK		0xf7
+#define QIXIS_LBMAP_MASK		0x08
 #define QIXIS_LBMAP_SHIFT		0
 #define QIXIS_LBMAP_DFLTBANK		0x00
 #define QIXIS_LBMAP_ALTBANK		0x08
-#define QIXIS_RST_CTL_RESET		0x41
+#define QIXIS_RST_CTL_RESET		0x31
 #define QIXIS_RCFG_CTL_RECONFIG_IDLE	0x20
 #define QIXIS_RCFG_CTL_RECONFIG_START	0x21
 #define QIXIS_RCFG_CTL_WATCHDOG_ENBLE	0x08
diff --git a/include/configs/ls1021aqds.h b/include/configs/ls1021aqds.h
index db684d2..47180f9 100644
--- a/include/configs/ls1021aqds.h
+++ b/include/configs/ls1021aqds.h
@@ -10,6 +10,10 @@
 #define CONFIG_LS102XA
 
 #define CONFIG_ARMV7_PSCI
+#define CONFIG_ARMV7_PSCI_1_0
+#define CONFIG_ARMV7_PSCI_NR_CPUS	CONFIG_MAX_CPUS
+
+#define CONFIG_ARMV7_SECURE_BASE	OCRAM_BASE_S_ADDR
 
 #define CONFIG_SYS_FSL_CLK
 
@@ -279,6 +283,8 @@
 #define QIXIS_LBMAP_SHIFT		0
 #define QIXIS_LBMAP_DFLTBANK		0x00
 #define QIXIS_LBMAP_ALTBANK		0x04
+#define QIXIS_PWR_CTL			0x21
+#define QIXIS_PWR_CTL_POWEROFF		0x80
 #define QIXIS_RST_CTL_RESET		0x44
 #define QIXIS_RCFG_CTL_RECONFIG_IDLE	0x20
 #define QIXIS_RCFG_CTL_RECONFIG_START	0x21
diff --git a/include/configs/ls1021atwr.h b/include/configs/ls1021atwr.h
index 0fb28ef..2f19950 100644
--- a/include/configs/ls1021atwr.h
+++ b/include/configs/ls1021atwr.h
@@ -10,6 +10,10 @@
 #define CONFIG_LS102XA
 
 #define CONFIG_ARMV7_PSCI
+#define CONFIG_ARMV7_PSCI_1_0
+#define CONFIG_ARMV7_PSCI_NR_CPUS	CONFIG_MAX_CPUS
+
+#define CONFIG_ARMV7_SECURE_BASE	OCRAM_BASE_S_ADDR
 
 #define CONFIG_SYS_FSL_CLK
 
@@ -123,7 +127,18 @@
 #define CONFIG_SPL_SERIAL_SUPPORT
 #define CONFIG_SPL_MMC_SUPPORT
 #define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR		0xe8
+
+#ifdef CONFIG_SECURE_BOOT
+#define CONFIG_U_BOOT_HDR_SIZE				(16 << 10)
+/*
+ * HDR would be appended at end of image and copied to DDR along
+ * with U-Boot image.
+ */
+#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS		(0x400 + \
+		(CONFIG_U_BOOT_HDR_SIZE / 512)
+#else
 #define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS		0x400
+#endif /* ifdef CONFIG_SECURE_BOOT */
 
 #define CONFIG_SPL_TEXT_BASE		0x10000000
 #define CONFIG_SPL_MAX_SIZE		0x1a000
@@ -136,7 +151,18 @@
 #define CONFIG_SYS_SPL_MALLOC_SIZE	0x100000
 #define CONFIG_SPL_BSS_START_ADDR	0x80100000
 #define CONFIG_SPL_BSS_MAX_SIZE		0x80000
+
+#ifdef CONFIG_U_BOOT_HDR_SIZE
+/*
+ * HDR would be appended at end of image and copied to DDR along
+ * with U-Boot image. Here u-boot max. size is 512K. So if binary
+ * size increases then increase this size in case of secure boot as
+ * it uses raw u-boot image instead of fit image.
+ */
+#define CONFIG_SYS_MONITOR_LEN		(0x80000 + CONFIG_U_BOOT_HDR_SIZE)
+#else
 #define CONFIG_SYS_MONITOR_LEN		0x80000
+#endif /* ifdef CONFIG_U_BOOT_HDR_SIZE */
 #endif
 
 #ifdef CONFIG_QSPI_BOOT
diff --git a/include/configs/ls1043a_common.h b/include/configs/ls1043a_common.h
index b0d4a8d..e55fcb2 100644
--- a/include/configs/ls1043a_common.h
+++ b/include/configs/ls1043a_common.h
@@ -175,6 +175,8 @@
 
 /* Command line configuration */
 #define CONFIG_CMD_ENV
+#define CONFIG_MENU
+#define CONFIG_CMD_PXE
 
 /*  MMC  */
 #define CONFIG_MMC
@@ -241,22 +243,37 @@
 #define CONFIG_HWCONFIG
 #define HWCONFIG_BUFFER_SIZE		128
 
+#if defined(CONFIG_QSPI_BOOT) || defined(CONFIG_SD_BOOT_QSPI)
+#define MTDPARTS_DEFAULT "mtdparts=spi0.0:1m(uboot)," \
+			"5m(kernel),1m(dtb),9m(file_system)"
+#else
+#define MTDPARTS_DEFAULT "mtdparts=60000000.nor:1m(nor_bank0_rcw)," \
+			"1m(nor_bank0_uboot),1m(nor_bank0_uboot_env)," \
+			"1m(nor_bank0_fman_uconde),40m(nor_bank0_fit)," \
+			"1m(nor_bank4_rcw),1m(nor_bank4_uboot)," \
+			"1m(nor_bank4_uboot_env),1m(nor_bank4_fman_ucode)," \
+			"40m(nor_bank4_fit);7e800000.flash:" \
+			"1m(nand_uboot),1m(nand_uboot_env)," \
+			"20m(nand_fit);spi0.0:1m(uboot)," \
+			"5m(kernel),1m(dtb),9m(file_system)"
+#endif
+
 /* Initial environment variables */
 #define CONFIG_EXTRA_ENV_SETTINGS		\
 	"hwconfig=fsl_ddr:bank_intlv=auto\0"	\
 	"loadaddr=0x80100000\0"			\
-	"kernel_addr=0x100000\0"		\
-	"ramdisk_addr=0x800000\0"		\
-	"ramdisk_size=0x2000000\0"		\
 	"fdt_high=0xffffffffffffffff\0"		\
 	"initrd_high=0xffffffffffffffff\0"	\
 	"kernel_start=0x61100000\0"		\
 	"kernel_load=0xa0000000\0"		\
 	"kernel_size=0x2800000\0"		\
-	"console=ttyAMA0,38400n8\0"
+	"console=ttyS0,115200\0"                \
+	"mtdparts=" MTDPARTS_DEFAULT "\0"
 
 #define CONFIG_BOOTARGS			"console=ttyS0,115200 root=/dev/ram0 " \
-					"earlycon=uart8250,mmio,0x21c0500"
+					"earlycon=uart8250,mmio,0x21c0500 "    \
+					MTDPARTS_DEFAULT
+
 #if defined(CONFIG_QSPI_BOOT) || defined(CONFIG_SD_BOOT_QSPI)
 #define CONFIG_BOOTCOMMAND		"sf probe && sf read $kernel_load "    \
 					"e0000 f00000 && bootm $kernel_load"
diff --git a/include/configs/ls1043ardb.h b/include/configs/ls1043ardb.h
index 94ddfb1..857ad7b 100644
--- a/include/configs/ls1043ardb.h
+++ b/include/configs/ls1043ardb.h
@@ -9,6 +9,17 @@
 
 #include "ls1043a_common.h"
 
+#if defined(CONFIG_FSL_LS_PPA)
+#define CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
+#define SEC_FIRMWARE_ERET_ADDR_REVERT
+#define CONFIG_ARMV8_PSCI
+
+#define CONFIG_SYS_LS_PPA_FW_IN_XIP
+#ifdef CONFIG_SYS_LS_PPA_FW_IN_XIP
+#define	CONFIG_SYS_LS_PPA_FW_ADDR	0x60500000
+#endif
+#endif
+
 #define CONFIG_DISPLAY_CPUINFO
 #define CONFIG_DISPLAY_BOARDINFO
 
diff --git a/include/configs/microblaze-generic.h b/include/configs/microblaze-generic.h
index 93fb166..e5bf700 100644
--- a/include/configs/microblaze-generic.h
+++ b/include/configs/microblaze-generic.h
@@ -175,10 +175,6 @@
 #define CONFIG_CMD_IRQ
 #define CONFIG_CMD_MFSL
 
-#if defined(CONFIG_DCACHE) || defined(CONFIG_ICACHE)
-#else
-#endif
-
 #if defined(FLASH)
 # define CONFIG_CMD_JFFS2
 # define CONFIG_CMD_UBI
@@ -309,6 +305,7 @@
 					 0x60000)
 #define CONFIG_SYS_FDT_BASE		(CONFIG_SYS_FLASH_BASE + \
 					 0x40000)
+#define CONFIG_SYS_FDT_SIZE		(16<<10)
 #define CONFIG_SYS_SPL_ARGS_ADDR	(CONFIG_SYS_TEXT_BASE + \
 					 0x1000000)
 
diff --git a/include/configs/miniarm_rk3288.h b/include/configs/miniarm_rk3288.h
new file mode 100644
index 0000000..342557f
--- /dev/null
+++ b/include/configs/miniarm_rk3288.h
@@ -0,0 +1,26 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define ROCKCHIP_DEVICE_SETTINGS
+#include <configs/rk3288_common.h>
+
+#define CONFIG_SPL_MMC_SUPPORT
+
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_SYS_MMC_ENV_DEV 1
+/* SPL @ 32k for ~36k
+ * ENV @ 96k
+ * u-boot @ 128K
+ */
+#define CONFIG_ENV_OFFSET (96 * 1024)
+
+#define CONFIG_SYS_WHITE_ON_BLACK
+#define CONFIG_CONSOLE_SCROLL_LINES		10
+
+#endif
diff --git a/include/configs/mx6qsabreauto.h b/include/configs/mx6qsabreauto.h
index 6039fc4..200e468 100644
--- a/include/configs/mx6qsabreauto.h
+++ b/include/configs/mx6qsabreauto.h
@@ -13,7 +13,6 @@
 #define CONFIG_MXC_UART_BASE	UART4_BASE
 #define CONFIG_CONSOLE_DEV		"ttymxc3"
 #define CONFIG_MMCROOT			"/dev/mmcblk0p2"
-#define PHYS_SDRAM_SIZE		(2u * 1024 * 1024 * 1024)
 
 /* USB Configs */
 #define CONFIG_USB_EHCI
diff --git a/include/configs/mx6slevk.h b/include/configs/mx6slevk.h
index d53e416..375aa0e 100644
--- a/include/configs/mx6slevk.h
+++ b/include/configs/mx6slevk.h
@@ -137,7 +137,6 @@
 /* Physical Memory Map */
 #define CONFIG_NR_DRAM_BANKS		1
 #define PHYS_SDRAM			MMDC0_ARB_BASE_ADDR
-#define PHYS_SDRAM_SIZE			SZ_1G
 
 #define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM
 #define CONFIG_SYS_INIT_RAM_ADDR	IRAM_BASE_ADDR
diff --git a/include/configs/mx6sxsabreauto.h b/include/configs/mx6sxsabreauto.h
index d771f9d..439579d 100644
--- a/include/configs/mx6sxsabreauto.h
+++ b/include/configs/mx6sxsabreauto.h
@@ -103,7 +103,6 @@
 /* Physical Memory Map */
 #define CONFIG_NR_DRAM_BANKS		1
 #define PHYS_SDRAM			MMDC0_ARB_BASE_ADDR
-#define PHYS_SDRAM_SIZE			SZ_2G
 
 #define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM
 #define CONFIG_SYS_INIT_RAM_ADDR	IRAM_BASE_ADDR
diff --git a/include/configs/mx6sxsabresd.h b/include/configs/mx6sxsabresd.h
index 183a759..9281fee 100644
--- a/include/configs/mx6sxsabresd.h
+++ b/include/configs/mx6sxsabresd.h
@@ -132,7 +132,6 @@
 /* Physical Memory Map */
 #define CONFIG_NR_DRAM_BANKS		1
 #define PHYS_SDRAM			MMDC0_ARB_BASE_ADDR
-#define PHYS_SDRAM_SIZE			SZ_1G
 
 #define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM
 #define CONFIG_SYS_INIT_RAM_ADDR	IRAM_BASE_ADDR
diff --git a/include/configs/mx7_common.h b/include/configs/mx7_common.h
index fbc6de6..7295fa6 100644
--- a/include/configs/mx7_common.h
+++ b/include/configs/mx7_common.h
@@ -21,6 +21,7 @@
 #define CONFIG_MXC_GPT_HCLK
 #define CONFIG_SYSCOUNTER_TIMER
 #define CONFIG_SC_TIMER_CLK 8000000 /* 8Mhz */
+#define CONFIG_TIMER_CLK_FREQ CONFIG_SC_TIMER_CLK
 #define CONFIG_SYS_FSL_CLK
 
 #define CONFIG_SYS_BOOTM_LEN	0x1000000
@@ -28,8 +29,9 @@
 /* Enable iomux-lpsr support */
 #define CONFIG_IOMUX_LPSR
 
+#define CONFIG_ARCH_MISC_INIT
+
 #define CONFIG_DISPLAY_CPUINFO
-#define CONFIG_DISPLAY_BOARDINFO
 
 #define CONFIG_LOADADDR                 0x80800000
 #define CONFIG_SYS_TEXT_BASE            0x87800000
@@ -70,15 +72,8 @@
 #define CONFIG_CMD_FUSE
 #define CONFIG_MXC_OCOTP
 
-/*
- * Default boot linux kernel in no secure mode.
- * If want to boot kernel in secure mode, please define CONFIG_MX7_SEC
- */
-#ifndef CONFIG_MX7_SEC
-#define CONFIG_ARMV7_NONSEC
 #define CONFIG_ARMV7_PSCI
 #define CONFIG_ARMV7_PSCI_NR_CPUS	2
 #define CONFIG_ARMV7_SECURE_BASE	0x00900000
-#endif
 
 #endif
diff --git a/include/configs/mx7dsabresd.h b/include/configs/mx7dsabresd.h
index ece8a03..822d81f 100644
--- a/include/configs/mx7dsabresd.h
+++ b/include/configs/mx7dsabresd.h
@@ -22,6 +22,8 @@
 #define CONFIG_BOARD_EARLY_INIT_F
 #define CONFIG_BOARD_LATE_INIT
 
+#define CONFIG_DISPLAY_BOARDINFO
+
 /* Uncomment to enable secure boot support */
 /* #define CONFIG_SECURE_BOOT */
 #define CONFIG_CSF_SIZE			0x4000
@@ -237,8 +239,6 @@
 #define CONFIG_MMCROOT			"/dev/mmcblk0p2"  /* USDHC1 */
 
 /* USB Configs */
-#define CONFIG_USB_EHCI
-#define CONFIG_USB_EHCI_MX7
 #define CONFIG_USB_STORAGE
 #define CONFIG_EHCI_HCD_INIT_AFTER_RESET
 #define CONFIG_USB_HOST_ETHER
diff --git a/include/configs/mxs.h b/include/configs/mxs.h
index 0882d5d..238b16d 100644
--- a/include/configs/mxs.h
+++ b/include/configs/mxs.h
@@ -120,7 +120,7 @@
 #define CONFIG_PL011_CLOCK		24000000
 #define CONFIG_PL01x_PORTS		{ (void *)MXS_UARTDBG_BASE }
 #define CONFIG_CONS_INDEX		0
-/* Default baudrate can be overriden by board! */
+/* Default baudrate can be overridden by board! */
 #ifndef CONFIG_BAUDRATE
 #define CONFIG_BAUDRATE			115200
 #endif
diff --git a/include/configs/novena.h b/include/configs/novena.h
index 2382951..57d8c3e 100644
--- a/include/configs/novena.h
+++ b/include/configs/novena.h
@@ -57,7 +57,6 @@
 /* Physical Memory Map */
 #define CONFIG_NR_DRAM_BANKS		1
 #define PHYS_SDRAM			MMDC0_ARB_BASE_ADDR
-#define PHYS_SDRAM_SIZE			0xF0000000
 
 #define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM
 #define CONFIG_SYS_INIT_RAM_ADDR	IRAM_BASE_ADDR
diff --git a/include/configs/arcangel4.h b/include/configs/nsim.h
similarity index 74%
rename from include/configs/arcangel4.h
rename to include/configs/nsim.h
index d608104..1edc560 100644
--- a/include/configs/arcangel4.h
+++ b/include/configs/nsim.h
@@ -1,11 +1,13 @@
 /*
- * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ * Copyright (C) 2013-2016 Synopsys, Inc. All rights reserved.
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#ifndef _CONFIG_ARCANGEL4_H_
-#define _CONFIG_ARCANGEL4_H_
+#ifndef _CONFIG_NSIM_H_
+#define _CONFIG_NSIM_H_
+
+#include <linux/sizes.h>
 
 /*
  *  CPU configuration
@@ -19,13 +21,13 @@
 
 #define CONFIG_SYS_DDR_SDRAM_BASE	0x80000000
 #define CONFIG_SYS_SDRAM_BASE		CONFIG_SYS_DDR_SDRAM_BASE
-#define CONFIG_SYS_SDRAM_SIZE		0x10000000	/* 256 Mb */
+#define CONFIG_SYS_SDRAM_SIZE		SZ_256M
 
 #define CONFIG_SYS_INIT_SP_ADDR		\
 	(CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE)
 
-#define CONFIG_SYS_MALLOC_LEN		0x200000	/* 2 MB */
-#define CONFIG_SYS_BOOTM_LEN		0x2000000	/* 32 MB */
+#define CONFIG_SYS_MALLOC_LEN		SZ_2M
+#define CONFIG_SYS_BOOTM_LEN		SZ_32M
 #define CONFIG_SYS_LOAD_ADDR		0x82000000
 
 #define CONFIG_SYS_NO_FLASH
@@ -48,7 +50,7 @@
  * Environment settings
  */
 #define CONFIG_ENV_IS_NOWHERE
-#define CONFIG_ENV_SIZE			0x00200		/* 512 bytes */
+#define CONFIG_ENV_SIZE			SZ_512
 #define CONFIG_ENV_OFFSET		0
 
 /*
@@ -62,9 +64,9 @@
  * Console configuration
  */
 #define CONFIG_SYS_LONGHELP
-#define CONFIG_SYS_CBSIZE		256
+#define CONFIG_SYS_CBSIZE		SZ_256
 #define CONFIG_SYS_BARGSIZE		CONFIG_SYS_CBSIZE
 #define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE + \
 						sizeof(CONFIG_SYS_PROMPT) + 16)
 
-#endif /* _CONFIG_ARCANGEL4_H_ */
+#endif /* _CONFIG_NSIM_H_ */
diff --git a/include/configs/omap3_evm.h b/include/configs/omap3_evm.h
index 1726a3e..52a24d3 100644
--- a/include/configs/omap3_evm.h
+++ b/include/configs/omap3_evm.h
@@ -96,11 +96,279 @@
 #define CONFIG_SYS_NAND_U_BOOT_START   CONFIG_SYS_TEXT_BASE
 #define CONFIG_SYS_NAND_U_BOOT_OFFS	0x80000
 
+/*
+ * High level configuration options
+ */
+#define CONFIG_OMAP			/* This is TI OMAP core */
+#define CONFIG_OMAP_GPIO
+#define CONFIG_OMAP_COMMON
+/* Common ARM Erratas */
+#define CONFIG_ARM_ERRATA_454179
+#define CONFIG_ARM_ERRATA_430973
+#define CONFIG_ARM_ERRATA_621766
+
+#define CONFIG_SDRC			/* The chip has SDRC controller */
+
+#define CONFIG_OMAP3_EVM		/* This is a OMAP3 EVM */
+#define CONFIG_TWL4030_POWER		/* with TWL4030 PMIC */
+
+/*
+ * Clock related definitions
+ */
+#define V_OSCK			26000000	/* Clock output from T2 */
+#define V_SCLK			(V_OSCK >> 1)
+
+/*
+ * OMAP3 has 12 GP timers, they can be driven by the system clock
+ * (12/13/16.8/19.2/38.4MHz) or by 32KHz clock. We use 13MHz (V_SCLK).
+ * This rate is divided by a local divisor.
+ */
+#define CONFIG_SYS_TIMERBASE		OMAP34XX_GPT2
+#define CONFIG_SYS_PTV			2	/* Divisor: 2^(PTV+1) => 8 */
+
+/* Size of environment - 128KB */
+#define CONFIG_ENV_SIZE			(128 << 10)
+
+/* Size of malloc pool */
+#define CONFIG_SYS_MALLOC_LEN		(CONFIG_ENV_SIZE + (128 << 10))
+
+/*
+ * Physical Memory Map
+ * Note 1: CS1 may or may not be populated
+ * Note 2: SDRAM size is expected to be at least 32MB
+ */
+#define CONFIG_NR_DRAM_BANKS		2
+#define PHYS_SDRAM_1			OMAP34XX_SDRC_CS0
+#define PHYS_SDRAM_2			OMAP34XX_SDRC_CS1
+
+/* Limits for memtest */
+#define CONFIG_SYS_MEMTEST_START	(OMAP34XX_SDRC_CS0)
+#define CONFIG_SYS_MEMTEST_END		(OMAP34XX_SDRC_CS0 + \
+						0x01F00000) /* 31MB */
+
+/* Default load address */
+#define CONFIG_SYS_LOAD_ADDR		(OMAP34XX_SDRC_CS0)
+
+/* -----------------------------------------------------------------------------
+ * Hardware drivers
+ * -----------------------------------------------------------------------------
+ */
+
+/*
+ * NS16550 Configuration
+ */
+#define V_NS16550_CLK			48000000	/* 48MHz (APLL96/2) */
+
+#define CONFIG_SYS_NS16550_SERIAL
+#define CONFIG_SYS_NS16550_REG_SIZE	(-4)
+#define CONFIG_SYS_NS16550_CLK		V_NS16550_CLK
+
+/*
+ * select serial console configuration
+ */
+#define CONFIG_CONS_INDEX		1
+#define CONFIG_SERIAL1			1	/* UART1 on OMAP3 EVM */
+#define CONFIG_SYS_NS16550_COM1		OMAP34XX_UART1
+#define CONFIG_BAUDRATE			115200
+#define CONFIG_SYS_BAUDRATE_TABLE	{4800, 9600, 19200, 38400, 57600,\
+					115200}
+
+/*
+ * I2C
+ */
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_OMAP24_I2C_SPEED	100000
+#define CONFIG_SYS_OMAP24_I2C_SLAVE	1
+#define CONFIG_SYS_I2C_OMAP34XX
+
+/*
+ * PISMO support
+ */
+/* Monitor at start of flash - Reserve 2 sectors */
+#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_FLASH_BASE
+
+#define CONFIG_SYS_MONITOR_LEN		(256 << 10)
+
+/* Start location & size of environment */
+#define ONENAND_ENV_OFFSET		0x260000
+#define SMNAND_ENV_OFFSET		0x260000
+
+#define CONFIG_SYS_ENV_SECT_SIZE	(128 << 10)	/* 128 KiB */
+
+/*
+ * NAND
+ */
+/* Physical address to access NAND */
+#define CONFIG_SYS_NAND_ADDR		NAND_BASE
+
+/* Physical address to access NAND at CS0 */
+#define CONFIG_SYS_NAND_BASE		NAND_BASE
+
+/* Max number of NAND devices */
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define CONFIG_SYS_NAND_BUSWIDTH_16BIT
+/* Timeout values (in ticks) */
+#define CONFIG_SYS_FLASH_ERASE_TOUT	(100 * CONFIG_SYS_HZ)
+#define CONFIG_SYS_FLASH_WRITE_TOUT	(100 * CONFIG_SYS_HZ)
+
+/* Flash banks JFFS2 should use */
+#define CONFIG_SYS_MAX_MTD_BANKS	(CONFIG_SYS_MAX_FLASH_BANKS + \
+						CONFIG_SYS_MAX_NAND_DEVICE)
+
+#define CONFIG_SYS_JFFS2_MEM_NAND
+#define CONFIG_SYS_JFFS2_FIRST_BANK	CONFIG_SYS_MAX_FLASH_BANKS
+#define CONFIG_SYS_JFFS2_NUM_BANKS	1
+
+#define CONFIG_JFFS2_NAND
+/* nand device jffs2 lives on */
+#define CONFIG_JFFS2_DEV		"nand0"
+/* Start of jffs2 partition */
+#define CONFIG_JFFS2_PART_OFFSET	0x680000
+/* Size of jffs2 partition */
+#define CONFIG_JFFS2_PART_SIZE		0xf980000
+
+/*
+ * USB
+ */
+#ifdef CONFIG_USB_OMAP3
+
+#ifdef CONFIG_USB_MUSB_HCD
+
+#define CONFIG_USB_STORAGE
+#define CONGIG_CMD_STORAGE
+
+#ifdef CONFIG_USB_KEYBOARD
+#define CONFIG_SYS_USB_EVENT_POLL
+#define CONFIG_PREBOOT			"usb start"
+#endif /* CONFIG_USB_KEYBOARD */
+
+#endif /* CONFIG_USB_MUSB_HCD */
+
+#ifdef CONFIG_USB_MUSB_UDC
+/* USB device configuration */
+#define CONFIG_USB_DEVICE
+#define CONFIG_USB_TTY
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+
+/* Change these to suit your needs */
+#define CONFIG_USBD_VENDORID		0x0451
+#define CONFIG_USBD_PRODUCTID		0x5678
+#define CONFIG_USBD_MANUFACTURER	"Texas Instruments"
+#define CONFIG_USBD_PRODUCT_NAME	"EVM"
+#endif /* CONFIG_USB_MUSB_UDC */
+
+#endif /* CONFIG_USB_OMAP3 */
+
+/* ----------------------------------------------------------------------------
+ * U-Boot features
+ * ----------------------------------------------------------------------------
+ */
+#define CONFIG_SYS_MAXARGS		16	/* max args for a command */
+
+#define CONFIG_MISC_INIT_R
+
+#define CONFIG_CMDLINE_TAG			/* enable passing of ATAGs */
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_INITRD_TAG
+#define CONFIG_REVISION_TAG
+
+/* Size of Console IO buffer */
+#define CONFIG_SYS_CBSIZE		512
+
+/* Size of print buffer */
+#define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE + \
+						sizeof(CONFIG_SYS_PROMPT) + 16)
+
+/* Size of bootarg buffer */
+#define CONFIG_SYS_BARGSIZE		(CONFIG_SYS_CBSIZE)
+
+#define CONFIG_BOOTFILE			"uImage"
+
+/*
+ * NAND / OneNAND
+ */
+#if defined(CONFIG_CMD_NAND)
+#define CONFIG_SYS_FLASH_BASE		NAND_BASE
+
+#define CONFIG_NAND_OMAP_GPMC
+#define CONFIG_ENV_OFFSET		SMNAND_ENV_OFFSET
+#elif defined(CONFIG_CMD_ONENAND)
+#define CONFIG_SYS_FLASH_BASE		ONENAND_MAP
+#define CONFIG_SYS_ONENAND_BASE		ONENAND_MAP
+#endif
+
+#if !defined(CONFIG_ENV_IS_NOWHERE)
+#if defined(CONFIG_CMD_NAND)
+#define CONFIG_ENV_IS_IN_NAND
+#elif defined(CONFIG_CMD_ONENAND)
+#define CONFIG_ENV_IS_IN_ONENAND
+#define CONFIG_ENV_OFFSET		ONENAND_ENV_OFFSET
+#endif
+#endif /* CONFIG_ENV_IS_NOWHERE */
+
+#define CONFIG_ENV_ADDR			CONFIG_ENV_OFFSET
+
+#if defined(CONFIG_CMD_NET)
+
+/* Ethernet (SMSC9115 from SMSC9118 family) */
+#define CONFIG_SMC911X
+#define CONFIG_SMC911X_32_BIT
+#define CONFIG_SMC911X_BASE		0x2C000000
+
+/* BOOTP fields */
+#define CONFIG_BOOTP_SUBNETMASK		0x00000001
+#define CONFIG_BOOTP_GATEWAY		0x00000002
+#define CONFIG_BOOTP_HOSTNAME		0x00000004
+#define CONFIG_BOOTP_BOOTPATH		0x00000010
+
+#endif /* CONFIG_CMD_NET */
+
+/* Support for relocation */
+#define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
+#define CONFIG_SYS_INIT_RAM_ADDR	0x4020f800
+#define CONFIG_SYS_INIT_RAM_SIZE	0x800
+#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_INIT_RAM_ADDR + \
+					 CONFIG_SYS_INIT_RAM_SIZE - \
+					 GENERATED_GBL_DATA_SIZE)
+
 /* -----------------------------------------------------------------------------
- * Include common board configuration
+ * Board specific
  * -----------------------------------------------------------------------------
  */
-#include "omap3_evm_common.h"
+#define CONFIG_SYS_NO_FLASH
+
+/* Uncomment to define the board revision statically */
+/* #define CONFIG_STATIC_BOARD_REV	OMAP3EVM_BOARD_GEN_2 */
+
+#define CONFIG_SYS_CACHELINE_SIZE	64
+
+/* Defines for SPL */
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_TEXT_BASE		0x40200800
+#define CONFIG_SPL_MAX_SIZE		(54 * 1024)	/* 8 KB for stack */
+
+#define CONFIG_SPL_BSS_START_ADDR	0x80000000
+#define CONFIG_SPL_BSS_MAX_SIZE		0x80000		/* 512 KB */
+
+#define CONFIG_SPL_BOARD_INIT
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBDISK_SUPPORT
+#define CONFIG_SPL_I2C_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_POWER_SUPPORT
+#define CONFIG_SPL_OMAP3_ID_NAND
+#define CONFIG_SPL_LDSCRIPT		"$(CPUDIR)/omap-common/u-boot-spl.lds"
+
+/*
+ * 1MB into the SDRAM to allow for SPL's bss at the beginning of SDRAM
+ * 64 bytes before this address should be set aside for u-boot.img's
+ * header. That is 0x800FFFC0--0x80100000 should not be used for any
+ * other needs.
+ */
+#define CONFIG_SYS_TEXT_BASE		0x80100000
+#define CONFIG_SYS_SPL_MALLOC_START	0x80208000
+#define CONFIG_SYS_SPL_MALLOC_SIZE	0x100000
 
 /* -----------------------------------------------------------------------------
  * Default environment
diff --git a/include/configs/omap3_evm_common.h b/include/configs/omap3_evm_common.h
deleted file mode 100644
index 01336ff..0000000
--- a/include/configs/omap3_evm_common.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Common configuration settings for the TI OMAP3 EVM board.
- *
- * Copyright (C) 2006-2011 Texas Instruments Incorporated - http://www.ti.com/
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef __OMAP3_EVM_COMMON_H
-#define __OMAP3_EVM_COMMON_H
-
-/*
- * High level configuration options
- */
-#define CONFIG_OMAP			/* This is TI OMAP core */
-#define CONFIG_OMAP_GPIO
-#define CONFIG_OMAP_COMMON
-/* Common ARM Erratas */
-#define CONFIG_ARM_ERRATA_454179
-#define CONFIG_ARM_ERRATA_430973
-#define CONFIG_ARM_ERRATA_621766
-
-#define CONFIG_SDRC			/* The chip has SDRC controller */
-
-#define CONFIG_OMAP3_EVM		/* This is a OMAP3 EVM */
-#define CONFIG_TWL4030_POWER		/* with TWL4030 PMIC */
-
-/*
- * Clock related definitions
- */
-#define V_OSCK			26000000	/* Clock output from T2 */
-#define V_SCLK			(V_OSCK >> 1)
-
-/*
- * OMAP3 has 12 GP timers, they can be driven by the system clock
- * (12/13/16.8/19.2/38.4MHz) or by 32KHz clock. We use 13MHz (V_SCLK).
- * This rate is divided by a local divisor.
- */
-#define CONFIG_SYS_TIMERBASE		OMAP34XX_GPT2
-#define CONFIG_SYS_PTV			2	/* Divisor: 2^(PTV+1) => 8 */
-
-/* Size of environment - 128KB */
-#define CONFIG_ENV_SIZE			(128 << 10)
-
-/* Size of malloc pool */
-#define CONFIG_SYS_MALLOC_LEN		(CONFIG_ENV_SIZE + (128 << 10))
-
-/*
- * Physical Memory Map
- * Note 1: CS1 may or may not be populated
- * Note 2: SDRAM size is expected to be at least 32MB
- */
-#define CONFIG_NR_DRAM_BANKS		2
-#define PHYS_SDRAM_1			OMAP34XX_SDRC_CS0
-#define PHYS_SDRAM_2			OMAP34XX_SDRC_CS1
-
-/* Limits for memtest */
-#define CONFIG_SYS_MEMTEST_START	(OMAP34XX_SDRC_CS0)
-#define CONFIG_SYS_MEMTEST_END		(OMAP34XX_SDRC_CS0 + \
-						0x01F00000) /* 31MB */
-
-/* Default load address */
-#define CONFIG_SYS_LOAD_ADDR		(OMAP34XX_SDRC_CS0)
-
-/* -----------------------------------------------------------------------------
- * Hardware drivers
- * -----------------------------------------------------------------------------
- */
-
-/*
- * NS16550 Configuration
- */
-#define V_NS16550_CLK			48000000	/* 48MHz (APLL96/2) */
-
-#define CONFIG_SYS_NS16550_SERIAL
-#define CONFIG_SYS_NS16550_REG_SIZE	(-4)
-#define CONFIG_SYS_NS16550_CLK		V_NS16550_CLK
-
-/*
- * select serial console configuration
- */
-#define CONFIG_CONS_INDEX		1
-#define CONFIG_SERIAL1			1	/* UART1 on OMAP3 EVM */
-#define CONFIG_SYS_NS16550_COM1		OMAP34XX_UART1
-#define CONFIG_BAUDRATE			115200
-#define CONFIG_SYS_BAUDRATE_TABLE	{4800, 9600, 19200, 38400, 57600,\
-					115200}
-
-/*
- * I2C
- */
-#define CONFIG_SYS_I2C
-#define CONFIG_SYS_OMAP24_I2C_SPEED	100000
-#define CONFIG_SYS_OMAP24_I2C_SLAVE	1
-#define CONFIG_SYS_I2C_OMAP34XX
-
-/*
- * PISMO support
- */
-/* Monitor at start of flash - Reserve 2 sectors */
-#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_FLASH_BASE
-
-#define CONFIG_SYS_MONITOR_LEN		(256 << 10)
-
-/* Start location & size of environment */
-#define ONENAND_ENV_OFFSET		0x260000
-#define SMNAND_ENV_OFFSET		0x260000
-
-#define CONFIG_SYS_ENV_SECT_SIZE	(128 << 10)	/* 128 KiB */
-
-/*
- * NAND
- */
-/* Physical address to access NAND */
-#define CONFIG_SYS_NAND_ADDR		NAND_BASE
-
-/* Physical address to access NAND at CS0 */
-#define CONFIG_SYS_NAND_BASE		NAND_BASE
-
-/* Max number of NAND devices */
-#define CONFIG_SYS_MAX_NAND_DEVICE	1
-#define CONFIG_SYS_NAND_BUSWIDTH_16BIT
-/* Timeout values (in ticks) */
-#define CONFIG_SYS_FLASH_ERASE_TOUT	(100 * CONFIG_SYS_HZ)
-#define CONFIG_SYS_FLASH_WRITE_TOUT	(100 * CONFIG_SYS_HZ)
-
-/* Flash banks JFFS2 should use */
-#define CONFIG_SYS_MAX_MTD_BANKS	(CONFIG_SYS_MAX_FLASH_BANKS + \
-						CONFIG_SYS_MAX_NAND_DEVICE)
-
-#define CONFIG_SYS_JFFS2_MEM_NAND
-#define CONFIG_SYS_JFFS2_FIRST_BANK	CONFIG_SYS_MAX_FLASH_BANKS
-#define CONFIG_SYS_JFFS2_NUM_BANKS	1
-
-#define CONFIG_JFFS2_NAND
-/* nand device jffs2 lives on */
-#define CONFIG_JFFS2_DEV		"nand0"
-/* Start of jffs2 partition */
-#define CONFIG_JFFS2_PART_OFFSET	0x680000
-/* Size of jffs2 partition */
-#define CONFIG_JFFS2_PART_SIZE		0xf980000
-
-/*
- * USB
- */
-#ifdef CONFIG_USB_OMAP3
-
-#ifdef CONFIG_USB_MUSB_HCD
-
-#define CONFIG_USB_STORAGE
-#define CONGIG_CMD_STORAGE
-
-#ifdef CONFIG_USB_KEYBOARD
-#define CONFIG_SYS_USB_EVENT_POLL
-#define CONFIG_PREBOOT			"usb start"
-#endif /* CONFIG_USB_KEYBOARD */
-
-#endif /* CONFIG_USB_MUSB_HCD */
-
-#ifdef CONFIG_USB_MUSB_UDC
-/* USB device configuration */
-#define CONFIG_USB_DEVICE
-#define CONFIG_USB_TTY
-#define CONFIG_SYS_CONSOLE_IS_IN_ENV
-
-/* Change these to suit your needs */
-#define CONFIG_USBD_VENDORID		0x0451
-#define CONFIG_USBD_PRODUCTID		0x5678
-#define CONFIG_USBD_MANUFACTURER	"Texas Instruments"
-#define CONFIG_USBD_PRODUCT_NAME	"EVM"
-#endif /* CONFIG_USB_MUSB_UDC */
-
-#endif /* CONFIG_USB_OMAP3 */
-
-/* ----------------------------------------------------------------------------
- * U-Boot features
- * ----------------------------------------------------------------------------
- */
-#define CONFIG_SYS_MAXARGS		16	/* max args for a command */
-
-#define CONFIG_MISC_INIT_R
-
-#define CONFIG_CMDLINE_TAG			/* enable passing of ATAGs */
-#define CONFIG_SETUP_MEMORY_TAGS
-#define CONFIG_INITRD_TAG
-#define CONFIG_REVISION_TAG
-
-/* Size of Console IO buffer */
-#define CONFIG_SYS_CBSIZE		512
-
-/* Size of print buffer */
-#define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE + \
-						sizeof(CONFIG_SYS_PROMPT) + 16)
-
-/* Size of bootarg buffer */
-#define CONFIG_SYS_BARGSIZE		(CONFIG_SYS_CBSIZE)
-
-#define CONFIG_BOOTFILE			"uImage"
-
-/*
- * NAND / OneNAND
- */
-#if defined(CONFIG_CMD_NAND)
-#define CONFIG_SYS_FLASH_BASE		NAND_BASE
-
-#define CONFIG_NAND_OMAP_GPMC
-#define CONFIG_ENV_OFFSET		SMNAND_ENV_OFFSET
-#elif defined(CONFIG_CMD_ONENAND)
-#define CONFIG_SYS_FLASH_BASE		ONENAND_MAP
-#define CONFIG_SYS_ONENAND_BASE		ONENAND_MAP
-#endif
-
-#if !defined(CONFIG_ENV_IS_NOWHERE)
-#if defined(CONFIG_CMD_NAND)
-#define CONFIG_ENV_IS_IN_NAND
-#elif defined(CONFIG_CMD_ONENAND)
-#define CONFIG_ENV_IS_IN_ONENAND
-#define CONFIG_ENV_OFFSET		ONENAND_ENV_OFFSET
-#endif
-#endif /* CONFIG_ENV_IS_NOWHERE */
-
-#define CONFIG_ENV_ADDR			CONFIG_ENV_OFFSET
-
-#if defined(CONFIG_CMD_NET)
-
-/* Ethernet (SMSC9115 from SMSC9118 family) */
-#define CONFIG_SMC911X
-#define CONFIG_SMC911X_32_BIT
-#define CONFIG_SMC911X_BASE		0x2C000000
-
-/* BOOTP fields */
-#define CONFIG_BOOTP_SUBNETMASK		0x00000001
-#define CONFIG_BOOTP_GATEWAY		0x00000002
-#define CONFIG_BOOTP_HOSTNAME		0x00000004
-#define CONFIG_BOOTP_BOOTPATH		0x00000010
-
-#endif /* CONFIG_CMD_NET */
-
-/* Support for relocation */
-#define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
-#define CONFIG_SYS_INIT_RAM_ADDR	0x4020f800
-#define CONFIG_SYS_INIT_RAM_SIZE	0x800
-#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_INIT_RAM_ADDR + \
-					 CONFIG_SYS_INIT_RAM_SIZE - \
-					 GENERATED_GBL_DATA_SIZE)
-
-/* -----------------------------------------------------------------------------
- * Board specific
- * -----------------------------------------------------------------------------
- */
-#define CONFIG_SYS_NO_FLASH
-
-/* Uncomment to define the board revision statically */
-/* #define CONFIG_STATIC_BOARD_REV	OMAP3EVM_BOARD_GEN_2 */
-
-#define CONFIG_SYS_CACHELINE_SIZE	64
-
-/* Defines for SPL */
-#define CONFIG_SPL_FRAMEWORK
-#define CONFIG_SPL_TEXT_BASE		0x40200800
-#define CONFIG_SPL_MAX_SIZE		(54 * 1024)	/* 8 KB for stack */
-
-#define CONFIG_SPL_BSS_START_ADDR	0x80000000
-#define CONFIG_SPL_BSS_MAX_SIZE		0x80000		/* 512 KB */
-
-#define CONFIG_SPL_BOARD_INIT
-#define CONFIG_SPL_LIBCOMMON_SUPPORT
-#define CONFIG_SPL_LIBDISK_SUPPORT
-#define CONFIG_SPL_I2C_SUPPORT
-#define CONFIG_SPL_LIBGENERIC_SUPPORT
-#define CONFIG_SPL_SERIAL_SUPPORT
-#define CONFIG_SPL_POWER_SUPPORT
-#define CONFIG_SPL_OMAP3_ID_NAND
-#define CONFIG_SPL_LDSCRIPT		"$(CPUDIR)/omap-common/u-boot-spl.lds"
-
-/*
- * 1MB into the SDRAM to allow for SPL's bss at the beginning of SDRAM
- * 64 bytes before this address should be set aside for u-boot.img's
- * header. That is 0x800FFFC0--0x80100000 should not be used for any
- * other needs.
- */
-#define CONFIG_SYS_TEXT_BASE		0x80100000
-#define CONFIG_SYS_SPL_MALLOC_START	0x80208000
-#define CONFIG_SYS_SPL_MALLOC_SIZE	0x100000
-
-#endif /* __OMAP3_EVM_COMMON_H */
diff --git a/include/configs/omap3_evm_quick_mmc.h b/include/configs/omap3_evm_quick_mmc.h
deleted file mode 100644
index b7d8765..0000000
--- a/include/configs/omap3_evm_quick_mmc.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Configuration settings for quick boot from MMC on OMAP3 EVM.
- *
- * Copyright (C) 2006-2010 Texas Instruments Incorporated - http://www.ti.com/
- *
- * Author :
- *     Sanjeev Premi <premi@ti.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef __OMAP3_EVM_QUICK_MMC_H
-#define __OMAP3_EVM_QUICK_MMC_H
-
-#include <asm/arch/cpu.h>
-#include <asm/arch/omap.h>
-
-/* ----------------------------------------------------------------------------
- * Supported U-Boot commands
- * ----------------------------------------------------------------------------
- */
-
-/*
- * Board revision is detected by probing the Ethernet chip.
- *
- * When revision is statically configured via CONFIG_STATIC_BOARD_REV,
- * this option can be removed. Generated binary is leaner by ~16Kbytes.
- */
-
-/* ----------------------------------------------------------------------------
- * Supported U-Boot features
- * ----------------------------------------------------------------------------
- */
-#define CONFIG_SILENT_CONSOLE
-#define CONFIG_ENV_IS_NOWHERE
-
-/* ----------------------------------------------------------------------------
- * Supported hardware
- * ----------------------------------------------------------------------------
- */
-
-/* MMC */
-#define CONFIG_MMC
-#define CONFIG_GENERIC_MMC
-#define CONFIG_OMAP_HSMMC
-#define CONFIG_DOS_PARTITION
-
-/* -----------------------------------------------------------------------------
- * Include common board configuration
- * -----------------------------------------------------------------------------
- */
-#include "omap3_evm_common.h"
-
-/* -----------------------------------------------------------------------------
- * Default environment
- * -----------------------------------------------------------------------------
- */
-
-#define CONFIG_EXTRA_ENV_SETTINGS	\
-	"verify=no\0"			\
-	"silent=1"
-
-#define CONFIG_BOOTCOMMAND			\
-	"mmc rescan 0; "			\
-	"fatload mmc 0 0x82000000 uImage; "	\
-	"bootm 0x82000000;"
-
-/*
- * Update the bootargs as necessary e.g. size of memory, partition and fstype
- */
-#define CONFIG_BOOTARGS			\
-	"quiet "			\
-	"console=ttyO0,115200n8 "	\
-	"mem=128M "			\
-	"noinitrd "			\
-	"root=/dev/mmcblk0p2 rw "	\
-	"rootfstype=ext3 rootwait"
-
-/*
- * SPL
- */
-#define CONFIG_SPL_MMC_SUPPORT
-#define CONFIG_SPL_FAT_SUPPORT
-#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR	0x300 /* address 0x60000 */
-#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS	0x200 /* 256 KB */
-#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
-#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME	"u-boot.img"
-
-#endif /* __OMAP3_EVM_QUICK_MMC_H */
diff --git a/include/configs/omap3_evm_quick_nand.h b/include/configs/omap3_evm_quick_nand.h
deleted file mode 100644
index da5d325..0000000
--- a/include/configs/omap3_evm_quick_nand.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Configuration settings for quick boot from NAND on OMAP3 EVM.
- *
- * Copyright (C) 2006-2010 Texas Instruments Incorporated - http://www.ti.com/
- *
- * Author :
- *     Sanjeev Premi <premi@ti.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef __OMAP3_EVM_QUICK_NAND_H
-#define __OMAP3_EVM_QUICK_NAND_H
-
-#include <asm/arch/cpu.h>
-#include <asm/arch/omap.h>
-
-/* ----------------------------------------------------------------------------
- * Supported U-Boot commands
- * ----------------------------------------------------------------------------
- */
-#define CONFIG_CMD_NAND
-
-/*
- * Board revision is detected by probing the Ethernet chip.
- *
- * When revision is statically configured via CONFIG_STATIC_BOARD_REV,
- * this option can be removed. Generated binary is leaner by ~16Kbytes.
- */
-
-/* ----------------------------------------------------------------------------
- * Supported U-Boot features
- * ----------------------------------------------------------------------------
- */
-#define CONFIG_SILENT_CONSOLE
-#define CONFIG_ENV_IS_NOWHERE
-
-/* -----------------------------------------------------------------------------
- * Include common board configuration
- * -----------------------------------------------------------------------------
- */
-#include "omap3_evm_common.h"
-
-/* -----------------------------------------------------------------------------
- * Default environment
- * -----------------------------------------------------------------------------
- */
-
-#define CONFIG_EXTRA_ENV_SETTINGS	\
-	"verify=no\0"			\
-	"silent=1"
-
-#define CONFIG_BOOTCOMMAND				\
-	"nandecc hw; "	\
-	"nand read.i 0x80000000 280000 300000; "	\
-	"bootm 0x80000000;"
-
-/*
- * Update the bootargs as necessary e.g. size of memory, partition and fstype
- */
-#define CONFIG_BOOTARGS				\
-	"quiet "			\
-	"console=ttyO0,115200n8 "	\
-	"mem=128M "			\
-	"noinitrd "			\
-	"root=/dev/mtdblock4 rw "	\
-	"rootfstype=jffs2 "
-
-/*
- * SPL
- */
-#define CONFIG_SPL_NAND_SIMPLE
-#define CONFIG_SPL_NAND_SUPPORT
-#define CONFIG_SPL_NAND_BASE
-#define CONFIG_SPL_NAND_DRIVERS
-#define CONFIG_SPL_NAND_ECC
-#define CONFIG_SYS_NAND_5_ADDR_CYCLE
-#define CONFIG_SYS_NAND_PAGE_COUNT	64
-#define CONFIG_SYS_NAND_PAGE_SIZE	2048
-#define CONFIG_SYS_NAND_OOBSIZE		64
-#define CONFIG_SYS_NAND_BLOCK_SIZE	(128*1024)
-#define CONFIG_SYS_NAND_BAD_BLOCK_POS	0
-#define CONFIG_SYS_NAND_ECCPOS		{2, 3, 4, 5, 6, 7, 8, 9,\
-						10, 11, 12, 13}
-#define CONFIG_SYS_NAND_ECCSIZE		512
-#define CONFIG_SYS_NAND_ECCBYTES	3
-#define CONFIG_NAND_OMAP_ECCSCHEME	OMAP_ECC_HAM1_CODE_HW
-#define CONFIG_SYS_NAND_U_BOOT_START   CONFIG_SYS_TEXT_BASE
-#define CONFIG_SYS_NAND_U_BOOT_OFFS	0x80000
-
-#endif /* __OMAP3_EVM_QUICK_NAND_H */
diff --git a/include/configs/omap3_igep00x0.h b/include/configs/omap3_igep00x0.h
index 9bd8915..e0d2593 100644
--- a/include/configs/omap3_igep00x0.h
+++ b/include/configs/omap3_igep00x0.h
@@ -10,11 +10,8 @@
 #ifndef __IGEP00X0_H
 #define __IGEP00X0_H
 
-#ifdef CONFIG_BOOT_NAND
-#define CONFIG_NAND
-#endif
-
 #define CONFIG_NR_DRAM_BANKS            2
+#define CONFIG_NAND
 
 #include <configs/ti_omap3_common.h>
 #include <asm/mach-types.h>
@@ -76,9 +73,9 @@
 #define CONFIG_USBD_MANUFACTURER	"Texas Instruments"
 #define CONFIG_USBD_PRODUCT_NAME	"IGEP"
 
-#ifdef CONFIG_BOOT_ONENAND
-#define CONFIG_CMD_ONENAND	/* ONENAND support		*/
-#endif
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_CMD_ONENAND
+#define CONFIG_CMD_UBI
 
 #ifndef CONFIG_SPL_BUILD
 
@@ -106,27 +103,6 @@
 #endif
 
 /*
- * FLASH and environment organization
- */
-
-#ifdef CONFIG_BOOT_ONENAND
-#define CONFIG_SYS_ONENAND_BASE		ONENAND_MAP
-
-#define ONENAND_ENV_OFFSET		0x260000 /* environment starts here */
-
-#define CONFIG_ENV_IS_IN_ONENAND	1
-#define CONFIG_ENV_SIZE			(512 << 10) /* Total Size Environment */
-#define CONFIG_ENV_ADDR			ONENAND_ENV_OFFSET
-#endif
-
-#ifdef CONFIG_NAND
-#define CONFIG_ENV_OFFSET		0x260000 /* environment starts here */
-#define CONFIG_ENV_IS_IN_NAND	        1
-#define CONFIG_ENV_SIZE			(512 << 10) /* Total Size Environment */
-#define CONFIG_ENV_ADDR			NAND_ENV_OFFSET
-#endif
-
-/*
  * SMSC911x Ethernet
  */
 #if defined(CONFIG_CMD_NET)
@@ -135,19 +111,19 @@
 #define CONFIG_SMC911X_BASE		0x2C000000
 #endif /* (CONFIG_CMD_NET) */
 
-/* OneNAND boot config */
-#ifdef CONFIG_BOOT_ONENAND
-#define CONFIG_SPL_ONENAND_SUPPORT
-#define CONFIG_SYS_ONENAND_U_BOOT_OFFS  0x80000
-#define CONFIG_SYS_ONENAND_PAGE_SIZE	2048
-#define CONFIG_SPL_ONENAND_LOAD_ADDR    0x80000
-#define CONFIG_SPL_ONENAND_LOAD_SIZE    \
-	(512 * 1024 - CONFIG_SPL_ONENAND_LOAD_ADDR)
+#define CONFIG_RBTREE
+#define CONFIG_MTD_PARTITIONS
+#define CONFIG_SYS_MTDPARTS_RUNTIME
 
-#endif
+/* OneNAND config */
+#define CONFIG_SPL_ONENAND_SUPPORT
+#define CONFIG_USE_ONENAND_BOARD_INIT
+#define CONFIG_SYS_ONENAND_BASE		ONENAND_MAP
+#define CONFIG_SYS_ONENAND_BLOCK_SIZE	(128*1024)
 
-/* NAND boot config */
-#ifdef CONFIG_NAND
+/* NAND config */
+#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_OMAP3_ID_NAND
 #define CONFIG_SYS_NAND_BUSWIDTH_16BIT
 #define CONFIG_SYS_NAND_5_ADDR_CYCLE
 #define CONFIG_SYS_NAND_PAGE_COUNT	64
@@ -168,13 +144,29 @@
 #define CONFIG_NAND_OMAP_GPMC
 #define CONFIG_BCH
 
-#define CONFIG_SYS_NAND_U_BOOT_OFFS	0x80000
-/* NAND: SPL falcon mode configs */
-#ifdef CONFIG_SPL_OS_BOOT
-#define CONFIG_CMD_SPL_NAND_OFS		0x240000
-#define CONFIG_SYS_NAND_SPL_KERNEL_OFFS	0x280000
-#define CONFIG_CMD_SPL_WRITE_SIZE	0x2000
-#endif
-#endif
+/* UBI configuration */
+#define CONFIG_SPL_UBI			1
+#define CONFIG_SPL_UBI_MAX_VOL_LEBS	256
+#define CONFIG_SPL_UBI_MAX_PEB_SIZE	(256*1024)
+#define CONFIG_SPL_UBI_MAX_PEBS		4096
+#define CONFIG_SPL_UBI_VOL_IDS		8
+#define CONFIG_SPL_UBI_LOAD_MONITOR_ID	0
+#define CONFIG_SPL_UBI_LOAD_KERNEL_ID	3
+#define CONFIG_SPL_UBI_LOAD_ARGS_ID	4
+#define CONFIG_SPL_UBI_PEB_OFFSET	4
+#define CONFIG_SPL_UBI_VID_OFFSET	512
+#define CONFIG_SPL_UBI_LEB_START	2048
+#define CONFIG_SPL_UBI_INFO_ADDR	0x88080000
+
+/* environment organization */
+#define CONFIG_ENV_IS_IN_UBI		1
+#define CONFIG_ENV_UBI_PART		"UBI"
+#define CONFIG_ENV_UBI_VOLUME		"config"
+#define CONFIG_ENV_UBI_VOLUME_REDUND	"config_r"
+#define CONFIG_UBI_SILENCE_MSG		1
+#define CONFIG_UBIFS_SILENCE_MSG	1
+#define CONFIG_ENV_SIZE			(32*1024)
+
+#undef CONFIG_SPL_EXT_SUPPORT
 
 #endif /* __IGEP00X0_H */
diff --git a/include/configs/omap4_panda.h b/include/configs/omap4_panda.h
index 0d62ccd..ffa22c3 100644
--- a/include/configs/omap4_panda.h
+++ b/include/configs/omap4_panda.h
@@ -17,7 +17,6 @@
  */
 
 /* USB UHH support options */
-#define CONFIG_USB_HOST
 #define CONFIG_USB_EHCI
 #define CONFIG_USB_EHCI_OMAP
 #define CONFIG_USB_STORAGE
diff --git a/include/configs/omap5_uevm.h b/include/configs/omap5_uevm.h
index 4ddc492..2bf955a 100644
--- a/include/configs/omap5_uevm.h
+++ b/include/configs/omap5_uevm.h
@@ -88,7 +88,6 @@
 #define CONFIG_SYS_I2C_TCA642X_ADDR 0x22
 
 /* USB UHH support options */
-#define CONFIG_USB_HOST
 #define CONFIG_USB_EHCI
 #define CONFIG_USB_EHCI_OMAP
 #define CONFIG_USB_STORAGE
diff --git a/include/configs/omapl138_lcdk.h b/include/configs/omapl138_lcdk.h
index 1f36d36..d00cf50 100644
--- a/include/configs/omapl138_lcdk.h
+++ b/include/configs/omapl138_lcdk.h
@@ -203,7 +203,7 @@
 #define CONFIG_REVISION_TAG
 #define CONFIG_SETUP_MEMORY_TAGS
 #define CONFIG_BOOTARGS		"console=ttyS2,115200n8 root=/dev/mmcblk0p2 rw rootwait ip=off"
-#define CONFIG_BOOTCOMMAND	"if mmc rescan 0; then if fatload mmc 0 0xc0600000 boot.scr; then source 0xc0600000; else fatload mmc 0 0xc0700000 uImage; bootm c0700000; fi; else sf probe 0; sf read 0xc0700000 0x80000 0x220000; bootm 0xc0700000; fi"
+#define CONFIG_BOOTCOMMAND	"if mmc rescan; then if fatload mmc 0 0xc0600000 boot.scr; then source 0xc0600000; else fatload mmc 0 0xc0700000 uImage; bootm c0700000; fi; else sf probe 0; sf read 0xc0700000 0x80000 0x220000; bootm 0xc0700000; fi"
 
 /*
  * U-Boot commands
diff --git a/include/configs/openrisc-generic.h b/include/configs/openrisc-generic.h
index 913256a..227c0ca 100644
--- a/include/configs/openrisc-generic.h
+++ b/include/configs/openrisc-generic.h
@@ -44,7 +44,6 @@
 /*
  * Ethernet
  */
-#define CONFIG_ETHOC
 #define CONFIG_SYS_ETHOC_BASE		0x92000000
 
 #define CONFIG_BOOTFILE			"boot.img"
diff --git a/include/configs/p1_p2_rdb_pc.h b/include/configs/p1_p2_rdb_pc.h
index 4f22d12..5d0a570 100644
--- a/include/configs/p1_p2_rdb_pc.h
+++ b/include/configs/p1_p2_rdb_pc.h
@@ -12,10 +12,6 @@
 
 #define CONFIG_DISPLAY_BOARDINFO
 
-#ifdef CONFIG_36BIT
-#define CONFIG_PHYS_64BIT
-#endif
-
 #if defined(CONFIG_P1020MBG)
 #define CONFIG_BOARDNAME "P1020MBG-PC"
 #define CONFIG_P1020
@@ -989,7 +985,7 @@
 "consoledev=ttyS0\0"	\
 "ramdiskaddr=2000000\0"	\
 "ramdiskfile=rootfs.ext2.gz.uboot\0"	\
-"fdtaddr=c00000\0"	\
+"fdtaddr=1e00000\0"	\
 "bdev=sda1\0" \
 "jffs2nor=mtdblock3\0"	\
 "norbootaddr=ef080000\0"	\
diff --git a/include/configs/p1_twr.h b/include/configs/p1_twr.h
index 30bfbf4..79e4991 100644
--- a/include/configs/p1_twr.h
+++ b/include/configs/p1_twr.h
@@ -513,7 +513,7 @@
 "consoledev=ttyS0\0"	\
 "ramdiskaddr=2000000\0"	\
 "ramdiskfile=rootfs.ext2.gz.uboot\0"	\
-"fdtaddr=c00000\0"	\
+"fdtaddr=1e00000\0"	\
 "bdev=sda1\0"	\
 "norbootaddr=ef080000\0"	\
 "norfdtaddr=ef040000\0"	\
diff --git a/include/configs/p2771-0000.h b/include/configs/p2771-0000.h
index 257283f..1f64405 100644
--- a/include/configs/p2771-0000.h
+++ b/include/configs/p2771-0000.h
@@ -14,6 +14,9 @@
 /* High-level configuration options */
 #define CONFIG_TEGRA_BOARD_STRING	"NVIDIA P2771-0000"
 
+/* I2C */
+#define CONFIG_SYS_I2C_TEGRA
+
 /* SD/MMC */
 #define CONFIG_MMC
 #define CONFIG_GENERIC_MMC
@@ -25,6 +28,11 @@
 #define CONFIG_SYS_MMC_ENV_PART		2
 #define CONFIG_ENV_OFFSET		(-CONFIG_ENV_SIZE)
 
+/* PCI host support */
+#define CONFIG_PCI
+#define CONFIG_PCI_PNP
+#define CONFIG_CMD_PCI
+
 #include "tegra-common-post.h"
 
 /* Crystal is 38.4MHz. clk_m runs at half that rate */
diff --git a/include/configs/pcm058.h b/include/configs/pcm058.h
new file mode 100644
index 0000000..97cbeba
--- /dev/null
+++ b/include/configs/pcm058.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) Stefano Babic <sbabic@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+
+#ifndef __PCM058_CONFIG_H
+#define __PCM058_CONFIG_H
+
+#include <config_distro_defaults.h>
+
+#ifdef CONFIG_SPL
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_YMODEM_SUPPORT
+#define CONFIG_SPL_MMC_SUPPORT
+#define CONFIG_SPL_DMA_SUPPORT
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SPL_SPI_LOAD
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	(64 * 1024)
+#include "imx6_spl.h"
+#endif
+
+#include "mx6_common.h"
+
+/* Thermal */
+#define CONFIG_IMX_THERMAL
+
+/* Serial */
+#define CONFIG_MXC_UART
+#define CONFIG_MXC_UART_BASE	       UART2_BASE
+#define CONFIG_CONSOLE_DEV		"ttymxc1"
+
+#define PHYS_SDRAM_SIZE		(1u * 1024 * 1024 * 1024)
+
+/* Early setup */
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_BOARD_LATE_INIT
+#define CONFIG_DISPLAY_BOARDINFO_LATE
+
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN		(8 * SZ_1M)
+
+/* Ethernet */
+#define CONFIG_FEC_MXC
+#define CONFIG_MII
+#define IMX_FEC_BASE			ENET_BASE_ADDR
+#define CONFIG_FEC_XCV_TYPE		RGMII
+#define CONFIG_ETHPRIME			"FEC"
+#define CONFIG_FEC_MXC_PHYADDR		3
+
+#define CONFIG_PHYLIB
+#define CONFIG_PHY_MICREL
+#define CONFIG_PHY_KSZ9031
+
+/* SPI Flash */
+#define CONFIG_MXC_SPI
+#define CONFIG_SF_DEFAULT_BUS		0
+#define CONFIG_SF_DEFAULT_CS		0
+#define CONFIG_SF_DEFAULT_SPEED		20000000
+#define CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
+
+/* I2C Configs */
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_I2C_MXC_I2C3		/* enable I2C bus 2 */
+#define CONFIG_SYS_I2C_SPEED		  100000
+
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_CMD_NAND
+/* Enable NAND support */
+#define CONFIG_CMD_NAND_TRIMFFS
+#define CONFIG_NAND_MXS
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define CONFIG_SYS_NAND_BASE		0x40000000
+#define CONFIG_SYS_NAND_5_ADDR_CYCLE
+#define CONFIG_SYS_NAND_ONFI_DETECTION
+#endif
+
+/* DMA stuff, needed for GPMI/MXS NAND support */
+#define CONFIG_APBH_DMA
+#define CONFIG_APBH_DMA_BURST
+#define CONFIG_APBH_DMA_BURST8
+
+/* Filesystem support */
+#define CONFIG_LZO
+#define CONFIG_CMD_UBIFS
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_PARTITIONS
+#define CONFIG_MTD_DEVICE
+#define MTDIDS_DEFAULT    "nand0=nand"
+#define MTDPARTS_DEFAULT  "mtdparts=nand:16m(uboot),1m(env),-(rootfs)"
+
+/* Various command support */
+#define CONFIG_CMD_BMODE         /* set eFUSE shadow for a boot dev and reset */
+#define CONFIG_CMD_HDMIDETECT    /* detect HDMI output device */
+#define CONFIG_CMD_GSC
+#define CONFIG_CMD_EECONFIG      /* Gateworks EEPROM config cmd */
+#define CONFIG_CMD_UBI
+#define CONFIG_RBTREE
+
+/* Physical Memory Map */
+#define CONFIG_NR_DRAM_BANKS           1
+#define PHYS_SDRAM                     MMDC0_ARB_BASE_ADDR
+
+#define CONFIG_SYS_SDRAM_BASE          PHYS_SDRAM
+#define CONFIG_SYS_INIT_RAM_ADDR       IRAM_BASE_ADDR
+#define CONFIG_SYS_INIT_RAM_SIZE       IRAM_SIZE
+
+#define CONFIG_SYS_INIT_SP_OFFSET \
+	(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR \
+	(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
+
+/* MMC Configs */
+#define CONFIG_SYS_FSL_ESDHC_ADDR	0
+#define CONFIG_SYS_FSL_USDHC_NUM	1
+
+/* Environment organization */
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_SIZE                (16 * 1024)
+#define CONFIG_ENV_OFFSET		(1024 * SZ_1K)
+#define CONFIG_ENV_SECT_SIZE		(64 * SZ_1K)
+#define CONFIG_ENV_SPI_BUS             CONFIG_SF_DEFAULT_BUS
+#define CONFIG_ENV_SPI_CS              CONFIG_SF_DEFAULT_CS
+#define CONFIG_ENV_SPI_MODE            CONFIG_SF_DEFAULT_MODE
+#define CONFIG_ENV_SPI_MAX_HZ          CONFIG_SF_DEFAULT_SPEED
+#define CONFIG_SYS_REDUNDAND_ENVIRONMENT
+#define CONFIG_ENV_OFFSET_REDUND       (CONFIG_ENV_OFFSET + \
+						CONFIG_ENV_SECT_SIZE)
+#define CONFIG_ENV_SIZE_REDUND         CONFIG_ENV_SIZE
+
+#ifdef CONFIG_ENV_IS_IN_NAND
+#define CONFIG_ENV_OFFSET              (0x1E0000)
+#define CONFIG_ENV_SECT_SIZE           (128 * SZ_1K)
+#endif
+
+#endif
diff --git a/include/configs/pico-imx6ul.h b/include/configs/pico-imx6ul.h
index d848ead..ca3c30b 100644
--- a/include/configs/pico-imx6ul.h
+++ b/include/configs/pico-imx6ul.h
@@ -17,8 +17,18 @@
 #define CONFIG_DISPLAY_CPUINFO
 #define CONFIG_DISPLAY_BOARDINFO
 
+/* Network support */
+
+#define CONFIG_FEC_MXC
+#define CONFIG_MII
+#define IMX_FEC_BASE			ENET2_BASE_ADDR
+#define CONFIG_FEC_MXC_PHYADDR		0x1
+#define CONFIG_FEC_XCV_TYPE		RMII
+#define CONFIG_PHYLIB
+#define CONFIG_PHY_MICREL
+
 /* Size of malloc() pool */
-#define CONFIG_SYS_MALLOC_LEN		(16 * SZ_1M)
+#define CONFIG_SYS_MALLOC_LEN		(35 * SZ_1M) /* Increase due to DFU */
 
 #define CONFIG_BOARD_EARLY_INIT_F
 
@@ -42,24 +52,17 @@
 #define CONFIG_EHCI_HCD_INIT_AFTER_RESET
 #define CONFIG_MXC_USB_PORTSC		(PORT_PTS_UTMI | PORT_PTS_PTW)
 #define CONFIG_MXC_USB_FLAGS		0
-#define CONFIG_USB_MAX_CONTROLLER_COUNT	1 /* Only OTG1 port enabled */
+#define CONFIG_USB_MAX_CONTROLLER_COUNT	2
 
-#define CONFIG_CI_UDC
 #define CONFIG_USBD_HS
-#define CONFIG_USB_GADGET_DUALSPEED
-#define CONFIG_USB_GADGET
 
 #define CONFIG_USB_FUNCTION_MASS_STORAGE
-#define CONFIG_USB_GADGET_DOWNLOAD
 #define CONFIG_USB_GADGET_VBUS_DRAW	2
 
-#define CONFIG_G_DNL_VENDOR_NUM		0x0525
-#define CONFIG_G_DNL_PRODUCT_NUM	0xa4a5
-#define CONFIG_G_DNL_MANUFACTURER	"FSL"
-
-#define CONFIG_G_DNL_VENDOR_NUM		0x0525
-#define CONFIG_G_DNL_PRODUCT_NUM	0xa4a5
-#define CONFIG_G_DNL_MANUFACTURER	"FSL"
+#define CONFIG_USB_FUNCTION_DFU
+#define CONFIG_DFU_MMC
+#define CONFIG_SYS_DFU_DATA_BUF_SIZE SZ_16M
+#define DFU_DEFAULT_POLL_TIMEOUT 300
 
 #define CONFIG_DEFAULT_FDT_FILE		"imx6ul-pico-hobbit.dtb"
 
@@ -76,6 +79,7 @@
 	"mmcpart=" __stringify(CONFIG_SYS_MMC_IMG_LOAD_PART) "\0" \
 	"mmcroot=" CONFIG_MMCROOT " rootwait rw\0" \
 	"mmcautodetect=yes\0" \
+	"dfu_alt_info=boot raw 0x2 0x400 mmcpart 1\0" \
 	"mmcargs=setenv bootargs console=${console},${baudrate} " \
 		"root=${mmcroot}\0" \
 	"loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}\0" \
@@ -86,7 +90,31 @@
 			"bootz ${loadaddr} - ${fdt_addr}; " \
 		"else " \
 			"echo WARN: Cannot load the DT; " \
-		"fi;\0"
+		"fi;\0" \
+	"netargs=setenv bootargs console=${console},${baudrate} " \
+		"root=/dev/nfs " \
+	"ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0" \
+		"netboot=echo Booting from net ...; " \
+		"run netargs; " \
+		"if test ${ip_dyn} = yes; then " \
+			"setenv get_cmd dhcp; " \
+		"else " \
+			"setenv get_cmd tftp; " \
+		"fi; " \
+		"${get_cmd} ${image}; " \
+		"if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
+			"if ${get_cmd} ${fdt_addr} ${fdt_file}; then " \
+				"bootz ${loadaddr} - ${fdt_addr}; " \
+			"else " \
+				"if test ${boot_fdt} = try; then " \
+					"bootz; " \
+				"else " \
+					"echo WARN: Cannot load the DT; " \
+				"fi; " \
+			"fi; " \
+		"else " \
+			"bootz; " \
+		"fi;\0" \
 
 #define CONFIG_BOOTCOMMAND \
 	   "if mmc rescan; then " \
@@ -118,6 +146,18 @@
 #define CONFIG_SYS_INIT_SP_ADDR \
 	(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
 
+/* I2C configs */
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_I2C_MXC_I2C1
+#define CONFIG_SYS_I2C_SPEED		100000
+
+/* PMIC */
+#define CONFIG_POWER
+#define CONFIG_POWER_I2C
+#define CONFIG_POWER_PFUZE3000
+#define CONFIG_POWER_PFUZE3000_I2C_ADDR	0x08
+
 /* FLASH and environment organization */
 #define CONFIG_SYS_NO_FLASH
 
diff --git a/include/configs/popmetal_rk3288.h b/include/configs/popmetal_rk3288.h
new file mode 100644
index 0000000..342557f
--- /dev/null
+++ b/include/configs/popmetal_rk3288.h
@@ -0,0 +1,26 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define ROCKCHIP_DEVICE_SETTINGS
+#include <configs/rk3288_common.h>
+
+#define CONFIG_SPL_MMC_SUPPORT
+
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_SYS_MMC_ENV_DEV 1
+/* SPL @ 32k for ~36k
+ * ENV @ 96k
+ * u-boot @ 128K
+ */
+#define CONFIG_ENV_OFFSET (96 * 1024)
+
+#define CONFIG_SYS_WHITE_ON_BLACK
+#define CONFIG_CONSOLE_SCROLL_LINES		10
+
+#endif
diff --git a/include/configs/qemu-ppce500.h b/include/configs/qemu-ppce500.h
index 0b86402..072859e 100644
--- a/include/configs/qemu-ppce500.h
+++ b/include/configs/qemu-ppce500.h
@@ -56,8 +56,6 @@
 #define CONFIG_SYS_CCSRBAR_PHYS_LOW CONFIG_SYS_CCSRBAR
 #endif
 
-#define CONFIG_PHYS_64BIT
-
 /* Virtual address range for PCI region maps */
 #define CONFIG_SYS_PCI_MAP_START	0x80000000
 #define CONFIG_SYS_PCI_MAP_END		0xe8000000
diff --git a/include/configs/rcar-gen3-common.h b/include/configs/rcar-gen3-common.h
index 89cde20..f9e5f59 100644
--- a/include/configs/rcar-gen3-common.h
+++ b/include/configs/rcar-gen3-common.h
@@ -12,7 +12,6 @@
 
 #include <asm/arch/rmobile.h>
 
-#define CONFIG_CMD_BOOTI
 #define CONFIG_CMD_DFL
 #define CONFIG_CMD_SDRAM
 #define CONFIG_CMD_FAT
diff --git a/include/configs/rk3036_common.h b/include/configs/rk3036_common.h
index 1bdcf9d..21d4683 100644
--- a/include/configs/rk3036_common.h
+++ b/include/configs/rk3036_common.h
@@ -6,7 +6,7 @@
 #ifndef __CONFIG_RK3036_COMMON_H
 #define __CONFIG_RK3036_COMMON_H
 
-#define CONFIG_SYS_CACHELINE_SIZE	32
+#define CONFIG_SYS_CACHELINE_SIZE	64
 
 #include <asm/arch/hardware.h>
 
@@ -40,16 +40,12 @@
 #define CONFIG_ROCKCHIP_MAX_INIT_SIZE	(4 << 10)
 #define CONFIG_ROCKCHIP_CHIP_TAG	"RK30"
 
-#define CONFIG_ROCKCHIP_COMMON
-
 /* MMC/SD IP block */
 #define CONFIG_MMC
 #define CONFIG_GENERIC_MMC
-#define CONFIG_SDHCI
 #define CONFIG_DWMMC
 #define CONFIG_BOUNCE_BUFFER
 
-#define CONFIG_DOS_PARTITION
 #define CONFIG_FAT_WRITE
 #define CONFIG_PARTITION_UUIDS
 #define CONFIG_CMD_PART
@@ -64,6 +60,25 @@
 #define CONFIG_SF_DEFAULT_SPEED 20000000
 
 #ifndef CONFIG_SPL_BUILD
+/* usb otg */
+#define CONFIG_USB_GADGET
+#define CONFIG_USB_GADGET_DUALSPEED
+#define CONFIG_USB_GADGET_DWC2_OTG
+#define CONFIG_USB_GADGET_VBUS_DRAW	0
+
+/* fastboot  */
+#define CONFIG_CMD_FASTBOOT
+#define CONFIG_USB_FUNCTION_FASTBOOT
+#define CONFIG_FASTBOOT_FLASH
+#define CONFIG_FASTBOOT_FLASH_MMC_DEV	0
+#define CONFIG_FASTBOOT_BUF_ADDR	CONFIG_SYS_LOAD_ADDR
+#define CONFIG_FASTBOOT_BUF_SIZE	0x08000000
+
+#define CONFIG_USB_GADGET_DOWNLOAD
+#define CONFIG_G_DNL_MANUFACTURER	"Rockchip"
+#define CONFIG_G_DNL_VENDOR_NUM		0x2207
+#define CONFIG_G_DNL_PRODUCT_NUM	0x310a
+
 #include <config_distro_defaults.h>
 
 #define ENV_MEM_LAYOUT_SETTINGS \
diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h
index 9d50d83..d3d4c68 100644
--- a/include/configs/rk3288_common.h
+++ b/include/configs/rk3288_common.h
@@ -33,15 +33,17 @@
 #define CONFIG_SYS_NS16550_MEM32
 #define CONFIG_SPL_BOARD_INIT
 
+#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+/* Bootrom will load u-boot binary to 0x0 once return from SPL */
+#define CONFIG_SYS_TEXT_BASE		0x00000000
+#else
 #define CONFIG_SYS_TEXT_BASE		0x00100000
+#endif
 #define CONFIG_SYS_INIT_SP_ADDR		0x00100000
 #define CONFIG_SYS_LOAD_ADDR		0x00800800
 #define CONFIG_SPL_STACK		0xff718000
 #define CONFIG_SPL_TEXT_BASE		0xff704004
 
-#define CONFIG_ROCKCHIP_COMMON
-#define CONFIG_SPL_ROCKCHIP_COMMON
-
 #define CONFIG_SILENT_CONSOLE
 #ifndef CONFIG_SPL_BUILD
 # define CONFIG_SYS_CONSOLE_IS_IN_ENV
@@ -51,11 +53,9 @@
 /* MMC/SD IP block */
 #define CONFIG_MMC
 #define CONFIG_GENERIC_MMC
-#define CONFIG_SDHCI
 #define CONFIG_DWMMC
 #define CONFIG_BOUNCE_BUFFER
 
-#define CONFIG_DOS_PARTITION
 #define CONFIG_FAT_WRITE
 #define CONFIG_PARTITION_UUIDS
 #define CONFIG_CMD_PART
@@ -81,6 +81,33 @@
 #define CONFIG_SF_DEFAULT_SPEED 20000000
 
 #ifndef CONFIG_SPL_BUILD
+/* usb otg */
+#define CONFIG_USB_GADGET
+#define CONFIG_USB_GADGET_DUALSPEED
+#define CONFIG_USB_GADGET_DWC2_OTG
+#define CONFIG_ROCKCHIP_USB2_PHY
+#define CONFIG_USB_GADGET_VBUS_DRAW	0
+
+/* fastboot  */
+#define CONFIG_CMD_FASTBOOT
+#define CONFIG_USB_FUNCTION_FASTBOOT
+#define CONFIG_FASTBOOT_FLASH
+#define CONFIG_FASTBOOT_FLASH_MMC_DEV	1	/* eMMC */
+#define CONFIG_FASTBOOT_BUF_ADDR	CONFIG_SYS_LOAD_ADDR
+#define CONFIG_FASTBOOT_BUF_SIZE	0x08000000
+
+/* usb mass storage */
+#define CONFIG_USB_FUNCTION_MASS_STORAGE
+#define CONFIG_CMD_USB_MASS_STORAGE
+
+#define CONFIG_USB_GADGET_DOWNLOAD
+#define CONFIG_G_DNL_MANUFACTURER	"Rockchip"
+#define CONFIG_G_DNL_VENDOR_NUM		0x2207
+#define CONFIG_G_DNL_PRODUCT_NUM	0x320a
+
+/* Enable gpt partition table */
+#define CONFIG_CMD_GPT
+
 #include <config_distro_defaults.h>
 
 #define ENV_MEM_LAYOUT_SETTINGS \
@@ -90,6 +117,12 @@
 	"kernel_addr_r=0x02000000\0" \
 	"ramdisk_addr_r=0x04000000\0"
 
+#define CONFIG_RANDOM_UUID
+#define PARTS_DEFAULT \
+	"uuid_disk=${uuid_gpt_disk};" \
+	"name=boot,start=8M,size=64M,bootable,uuid=${uuid_gpt_boot};" \
+	"name=rootfs,size=-,uuid=${uuid_gpt_rootfs};\0" \
+
 /* First try to boot from SD (index 0), then eMMC (index 1 */
 #define BOOT_TARGET_DEVICES(func) \
 	func(MMC, mmc, 0) \
@@ -102,6 +135,7 @@
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	"fdt_high=0x1fffffff\0" \
 	"initrd_high=0x1fffffff\0" \
+	"partitions=" PARTS_DEFAULT \
 	ENV_MEM_LAYOUT_SETTINGS \
 	ROCKCHIP_DEVICE_SETTINGS \
 	BOOTENV
diff --git a/include/configs/rk3399_common.h b/include/configs/rk3399_common.h
new file mode 100644
index 0000000..6875308
--- /dev/null
+++ b/include/configs/rk3399_common.h
@@ -0,0 +1,88 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __CONFIG_RK3399_COMMON_H
+#define __CONFIG_RK3399_COMMON_H
+
+#define CONFIG_SYS_CACHELINE_SIZE	64
+
+#define CONFIG_SYS_NO_FLASH
+#define CONFIG_NR_DRAM_BANKS		1
+#define CONFIG_ENV_SIZE			0x2000
+#define CONFIG_SYS_MAXARGS		16
+#define CONFIG_BAUDRATE			1500000
+#define CONFIG_SYS_MALLOC_LEN		(32 << 20)
+#define CONFIG_SYS_CBSIZE		1024
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_DISPLAY_BOARDINFO
+
+#define CONFIG_SYS_NS16550_MEM32
+
+#define CONFIG_SYS_TEXT_BASE		0x00200000
+#define CONFIG_SYS_INIT_SP_ADDR		0x00300000
+#define CONFIG_SYS_LOAD_ADDR		0x00800800
+
+#define CONFIG_SYS_BOOTM_LEN	(64 << 20)	/* 64M */
+
+/* MMC/SD IP block */
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_DWMMC
+#define CONFIG_SDHCI
+#define CONFIG_BOUNCE_BUFFER
+#define CONFIG_ROCKCHIP_SDHCI_MAX_FREQ	200000000
+
+#define CONFIG_SUPPORT_VFAT
+#define CONFIG_FS_FAT
+#define CONFIG_FAT_WRITE
+#define CONFIG_FS_EXT4
+#define CONFIG_CMD_PART
+
+/* RAW SD card / eMMC locations. */
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR	256
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	(128 << 10)
+
+/* FAT sd card locations. */
+#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
+#define CONFIG_SYS_SDRAM_BASE		0
+#define CONFIG_NR_DRAM_BANKS		1
+
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI
+#define CONFIG_SF_DEFAULT_SPEED 20000000
+
+#ifndef CONFIG_SPL_BUILD
+#include <config_distro_defaults.h>
+
+#define ENV_MEM_LAYOUT_SETTINGS \
+	"scriptaddr=0x00000000\0" \
+	"pxefile_addr_r=0x00100000\0" \
+	"fdt_addr_r=0x01f00000\0" \
+	"kernel_addr_r=0x02000000\0" \
+	"ramdisk_addr_r=0x04000000\0"
+
+#define CONFIG_CMD_GPT
+#define CONFIG_RANDOM_UUID
+#define CONFIG_PARTITION_UUIDS
+#define PARTS_DEFAULT \
+	"uuid_disk=${uuid_gpt_disk};" \
+	"name=boot,start=16M,size=32M,bootable;" \
+	"name=rootfs,size=-,uuid=${uuid_gpt_rootfs};\0" \
+
+/* First try to boot from SD (index 0), then eMMC (index 1) */
+#define BOOT_TARGET_DEVICES(func) \
+	func(MMC, mmc, 0) \
+	func(MMC, mmc, 1)
+
+#include <config_distro_bootcmd.h>
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	ENV_MEM_LAYOUT_SETTINGS \
+	"partitions=" PARTS_DEFAULT \
+	BOOTENV
+
+#endif
+
+#endif
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 23a0c40..94e024b 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -16,8 +16,10 @@
 
 #endif
 
+#ifndef CONFIG_SPL_BUILD
 #define CONFIG_IO_TRACE
 #define CONFIG_CMD_IOTRACE
+#endif
 
 #ifndef CONFIG_TIMER
 #define CONFIG_SYS_TIMER_RATE		1000000
@@ -25,7 +27,10 @@
 
 #define CONFIG_SYS_STDIO_DEREGISTER
 
-/* Number of bits in a C 'long' on this architecture */
+/*
+ * Number of bits in a C 'long' on this architecture. Set this to 32 when
+ * building on a 32-bit machine.
+ */
 #define CONFIG_SANDBOX_BITS_PER_LONG	64
 
 #define CONFIG_LMB
@@ -80,7 +85,6 @@
 #define CONFIG_CMD_SF_TEST
 
 #define CONFIG_I2C_EDID
-#define CONFIG_I2C_EEPROM
 
 /* Memory things - we don't really want a memory test */
 #define CONFIG_SYS_LOAD_ADDR		0x00000000
@@ -192,6 +196,7 @@
 #define CONFIG_CMD_LZMADEC
 #define CONFIG_CMD_DATE
 
+#ifndef CONFIG_SPL_BUILD
 #define CONFIG_CMD_IDE
 #define CONFIG_SYS_IDE_MAXBUS		1
 #define CONFIG_SYS_ATA_IDE0_OFFSET	0
@@ -201,6 +206,7 @@
 #define CONFIG_SYS_ATA_REG_OFFSET	1
 #define CONFIG_SYS_ATA_ALT_OFFSET	2
 #define CONFIG_SYS_ATA_STRIDE		4
+#endif
 
 #define CONFIG_SCSI
 #define CONFIG_SCSI_AHCI_PLAT
diff --git a/include/configs/sandbox_spl.h b/include/configs/sandbox_spl.h
new file mode 100644
index 0000000..ffc3098
--- /dev/null
+++ b/include/configs/sandbox_spl.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __SANDBOX_SPL_CONFIG_H
+#define __SANDBOX_SPL_CONFIG_H
+
+#include <configs/sandbox.h>
+
+#define CONFIG_SPL_BOARD_INIT
+
+#define CONFIG_SPL_DRIVERS_MISC_SUPPORT
+#define CONFIG_SPL_ENV_SUPPORT
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+
+#endif
diff --git a/include/configs/sbc8548.h b/include/configs/sbc8548.h
index 46766a6..ec9ad45 100644
--- a/include/configs/sbc8548.h
+++ b/include/configs/sbc8548.h
@@ -595,7 +595,7 @@
 "consoledev=ttyS0\0"				\
 "ramdiskaddr=2000000\0"			\
 "ramdiskfile=uRamdisk\0"			\
-"fdtaddr=c00000\0"				\
+"fdtaddr=1e00000\0"				\
 "fdtfile=sbc8548.dtb\0"
 
 #define CONFIG_NFSBOOTCOMMAND						\
diff --git a/include/configs/smartweb.h b/include/configs/smartweb.h
index 6add391..076a5ce 100644
--- a/include/configs/smartweb.h
+++ b/include/configs/smartweb.h
@@ -122,6 +122,7 @@
  *
  */
 #define CONFIG_MACB
+#define CONFIG_PHYLIB
 #define CONFIG_USB_HOST_ETHER
 #define CONFIG_USB_ETHER_ASIX
 #define CONFIG_USB_ETHER_MCS7830
diff --git a/include/configs/snapper9g45.h b/include/configs/snapper9g45.h
index fd6c70e..c91ab71 100644
--- a/include/configs/snapper9g45.h
+++ b/include/configs/snapper9g45.h
@@ -56,6 +56,7 @@
 
 /* Ethernet */
 #define CONFIG_MACB
+#define CONFIG_PHYLIB
 #define CONFIG_RMII
 #define CONFIG_NET_RETRY_COUNT		20
 #define CONFIG_RESET_PHY_R
diff --git a/include/configs/som-db5800-som-6867.h b/include/configs/som-db5800-som-6867.h
new file mode 100644
index 0000000..a4b343e
--- /dev/null
+++ b/include/configs/som-db5800-som-6867.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <configs/x86-common.h>
+
+#define CONFIG_SYS_MONITOR_LEN		(1 << 20)
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_ARCH_EARLY_INIT_R
+#define CONFIG_ARCH_MISC_INIT
+
+#define CONFIG_PCI_PNP
+#define CONFIG_STD_DEVICES_SETTINGS     "stdin=serial,usbkbd,vga\0" \
+					"stdout=serial,vga\0" \
+					"stderr=serial,vga\0"
+
+#define CONFIG_SCSI_DEV_LIST		\
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SATA}, \
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SATA_ALT}
+
+#define VIDEO_IO_OFFSET				0
+#define CONFIG_X86EMU_RAW_IO
+
+#define CONFIG_ENV_SECT_SIZE		0x1000
+#define CONFIG_ENV_OFFSET		0x006ef000
+
+#endif	/* __CONFIG_H */
diff --git a/include/configs/stm32f746-disco.h b/include/configs/stm32f746-disco.h
index e544a21..4391bff 100644
--- a/include/configs/stm32f746-disco.h
+++ b/include/configs/stm32f746-disco.h
@@ -24,13 +24,13 @@
  * Configuration of the external SDRAM memory
  */
 #define CONFIG_NR_DRAM_BANKS		1
-#define CONFIG_SYS_RAM_SIZE		((64 + 192) << 10)
+#define CONFIG_SYS_RAM_SIZE		(8 * 1024 * 1024)
 #define CONFIG_SYS_RAM_CS		1
 #define CONFIG_SYS_RAM_FREQ_DIV		2
-#define CONFIG_SYS_RAM_BASE		0x20000000
+#define CONFIG_SYS_RAM_BASE		0xC0000000
 #define CONFIG_SYS_SDRAM_BASE		CONFIG_SYS_RAM_BASE
-#define CONFIG_SYS_LOAD_ADDR		0x20000000
-#define CONFIG_LOADADDR			0x20000000
+#define CONFIG_SYS_LOAD_ADDR		0xC0400000
+#define CONFIG_LOADADDR			0xC0400000
 
 #define CONFIG_SYS_MAX_FLASH_SECT	8
 #define CONFIG_SYS_MAX_FLASH_BANKS	1
@@ -42,7 +42,8 @@
 #define CONFIG_STM32_FLASH
 #define CONFIG_STM32X7_SERIAL
 
-#define CONFIG_SYS_CLK_FREQ		16*1000*1000 /* 180 MHz */
+#define CONFIG_STM32_HSE_HZ		25000000
+#define CONFIG_SYS_CLK_FREQ		200000000 /* 200 MHz */
 #define CONFIG_SYS_HZ_CLOCK		1000000	/* Timer is clocked at 1MHz */
 
 #define CONFIG_CMDLINE_TAG
diff --git a/include/configs/sun6i.h b/include/configs/sun6i.h
index 95ccc35..0625502 100644
--- a/include/configs/sun6i.h
+++ b/include/configs/sun6i.h
@@ -25,6 +25,7 @@
 #define CONFIG_ARMV7_PSCI		1
 #define CONFIG_ARMV7_PSCI_NR_CPUS	4
 #define CONFIG_ARMV7_SECURE_BASE	SUNXI_SRAM_B_BASE
+#define CONFIG_ARMV7_SECURE_MAX_SIZE    (64 * 1024) /* 64 KB */
 
 /*
  * Include common sunxi configuration where most the settings are
diff --git a/include/configs/sun7i.h b/include/configs/sun7i.h
index 0dd2902..e9074d5 100644
--- a/include/configs/sun7i.h
+++ b/include/configs/sun7i.h
@@ -21,7 +21,9 @@
 #define CONFIG_SUNXI_USB_PHYS	3
 
 #define CONFIG_ARMV7_PSCI		1
+#define CONFIG_ARMV7_PSCI_NR_CPUS	2
 #define CONFIG_ARMV7_SECURE_BASE	SUNXI_SRAM_B_BASE
+#define CONFIG_ARMV7_SECURE_MAX_SIZE	(64 * 1024) /* 64 KB */
 
 /*
  * Include common sunxi configuration where most the settings are
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index 94275a7..b9aa62b 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -134,7 +134,15 @@
 #define CONFIG_SERIAL_TAG
 
 #ifdef CONFIG_NAND_SUNXI
+#define CONFIG_SYS_NAND_MAX_ECCPOS 1664
 #define CONFIG_SPL_NAND_SUPPORT 1
+#define CONFIG_SYS_NAND_ONFI_DETECTION
+#define CONFIG_SYS_MAX_NAND_DEVICE 8
+#endif
+
+#ifdef CONFIG_SPL_SPI_SUNXI
+#define CONFIG_SPL_SPI_FLASH_SUPPORT	1
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	0x8000
 #endif
 
 /* mmc config */
diff --git a/include/configs/taurus.h b/include/configs/taurus.h
index 882a4e5..2d091db 100644
--- a/include/configs/taurus.h
+++ b/include/configs/taurus.h
@@ -99,6 +99,7 @@
 
 /* Ethernet */
 #define CONFIG_MACB
+#define CONFIG_PHYLIB
 #define CONFIG_RMII
 #define CONFIG_AT91_WANTS_COMMON_PHY
 
diff --git a/include/configs/ti_armv7_common.h b/include/configs/ti_armv7_common.h
index ba7cf15..9f947ee 100644
--- a/include/configs/ti_armv7_common.h
+++ b/include/configs/ti_armv7_common.h
@@ -108,9 +108,25 @@
 /* Timer information. */
 #define CONFIG_SYS_PTV			2	/* Divisor: 2^(PTV+1) => 8 */
 
+/*
+ * Disable DM_* for SPL build and can be re-enabled after adding
+ * DM support in SPL
+ */
+#ifdef CONFIG_SPL_BUILD
+#undef CONFIG_DM_I2C
+#endif
+
 /* I2C IP block */
 #define CONFIG_I2C
+#ifndef CONFIG_DM_I2C
 #define CONFIG_SYS_I2C
+#else
+/*
+ * Enable CONFIG_DM_I2C_COMPAT temporarily until all the i2c client
+ * devices are adopted to DM
+ */
+#define CONFIG_DM_I2C_COMPAT
+#endif
 
 /* MMC/SD IP block */
 #define CONFIG_MMC
diff --git a/include/configs/ti_armv7_keystone2.h b/include/configs/ti_armv7_keystone2.h
index 2ee26c4..4aa262e 100644
--- a/include/configs/ti_armv7_keystone2.h
+++ b/include/configs/ti_armv7_keystone2.h
@@ -89,6 +89,10 @@
 #define CONFIG_SYS_SPI2
 #define CONFIG_SYS_SPI2_BASE		KS2_SPI2_BASE
 #define CONFIG_SYS_SPI2_NUM_CS		4
+#ifdef CONFIG_SPL_BUILD
+#undef CONFIG_DM_SPI
+#undef CONFIG_DM_SPI_FLASH
+#endif
 
 /* Network Configuration */
 #define CONFIG_PHYLIB
diff --git a/include/configs/trimslice.h b/include/configs/trimslice.h
index b761640..9d49f63 100644
--- a/include/configs/trimslice.h
+++ b/include/configs/trimslice.h
@@ -37,7 +37,8 @@
 #define CONFIG_ENV_SPI_MAX_HZ		48000000
 #define CONFIG_ENV_SPI_MODE		SPI_MODE_0
 #define CONFIG_ENV_SECT_SIZE		CONFIG_ENV_SIZE
-#define CONFIG_ENV_OFFSET		(512 * 1024)
+/* 1MiB flash, environment located as high as possible */
+#define CONFIG_ENV_OFFSET		(SZ_1M - CONFIG_ENV_SIZE)
 
 /* USB Host support */
 #define CONFIG_USB_EHCI
diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h
index 4ebaf84..0f5b20f 100644
--- a/include/configs/uniphier.h
+++ b/include/configs/uniphier.h
@@ -1,5 +1,7 @@
 /*
- * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2012-2015 Panasonic Corporation
+ * Copyright (C) 2015-2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -9,7 +11,9 @@
 #ifndef __CONFIG_UNIPHIER_COMMON_H__
 #define __CONFIG_UNIPHIER_COMMON_H__
 
-#define CONFIG_I2C_EEPROM
+#define CONFIG_ARMV7_PSCI
+#define CONFIG_ARMV7_PSCI_NR_CPUS   4
+
 #define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS  10
 
 #define CONFIG_SMC911X
@@ -26,10 +30,11 @@
 /* #define CONFIG_SYS_ICACHE_OFF */
 /* #define CONFIG_SYS_DCACHE_OFF */
 
+#ifdef CONFIG_CACHE_UNIPHIER
+#define CONFIG_SYS_CACHELINE_SIZE	128
+#else
 #define CONFIG_SYS_CACHELINE_SIZE	32
-
-/* Comment out the following to disable L2 cache */
-#define CONFIG_UNIPHIER_L2CACHE_ON
+#endif
 
 #define CONFIG_DISPLAY_CPUINFO
 #define CONFIG_DISPLAY_BOARDINFO
@@ -184,7 +189,6 @@
 	"__nfsboot=run tftpboot\0"
 #else
 #ifdef CONFIG_ARM64
-#define CONFIG_CMD_BOOTI
 #define CONFIG_BOOTFILE			"Image"
 #define LINUXBOOT_CMD			"booti"
 #define KERNEL_ADDR_R			"kernel_addr_r=0x80080000\0"
@@ -226,7 +230,6 @@
 		"run boot_common\0" \
 	"__nfsboot=tftpboot $kernel_addr_r $bootfile &&" \
 		"tftpboot $fdt_addr_r $fdt_file &&" \
-		"tftpboot $fdt_addr_r $fdt_file &&" \
 		"setenv ramdisk_addr_r - &&" \
 		"run boot_common\0"
 #endif
diff --git a/include/configs/usbarmory.h b/include/configs/usbarmory.h
index 8568663..5484204 100644
--- a/include/configs/usbarmory.h
+++ b/include/configs/usbarmory.h
@@ -17,16 +17,13 @@
 #define CONFIG_SYS_FSL_CLK
 #define CONFIG_BOARD_EARLY_INIT_F
 #define CONFIG_MXC_GPIO
+#define CONFIG_SYS_NO_FLASH
 
 #include <asm/arch/imx-regs.h>
 
 #include <config_distro_defaults.h>
 
-/* U-Boot commands */
-
 /* U-Boot environment */
-#define CONFIG_ENV_OVERWRITE
-#define CONFIG_SYS_NO_FLASH
 #define CONFIG_ENV_OFFSET	(6 * 64 * 1024)
 #define CONFIG_ENV_SIZE		(8 * 1024)
 #define CONFIG_ENV_IS_IN_MMC
@@ -69,17 +66,19 @@
 #define CONFIG_CMD_FUSE
 #define CONFIG_FSL_IIM
 
-/* Linux boot */
+/* U-Boot memory offsets */
 #define CONFIG_LOADADDR		0x72000000
 #define CONFIG_SYS_TEXT_BASE	0x77800000
 #define CONFIG_SYS_LOAD_ADDR	CONFIG_LOADADDR
+
+/* Linux boot */
 #define CONFIG_HOSTNAME		usbarmory
 #define CONFIG_BOOTCOMMAND						\
 	"run distro_bootcmd; "						\
 	"setenv bootargs console=${console} ${bootargs_default}; "	\
-	"ext2load mmc 0:1 ${kernel_addr_r} /boot/uImage; "		\
+	"ext2load mmc 0:1 ${kernel_addr_r} /boot/zImage; "		\
 	"ext2load mmc 0:1 ${fdt_addr_r} /boot/${fdtfile}; "		\
-	"bootm ${kernel_addr_r} - ${fdt_addr_r}"
+	"bootz ${kernel_addr_r} - ${fdt_addr_r}"
 
 #define BOOT_TARGET_DEVICES(func) func(MMC, mmc, 0)
 
@@ -99,6 +98,12 @@
 	"console=ttymxc0,115200\0"				\
 	BOOTENV
 
+#ifndef CONFIG_CMDLINE
+#define CONFIG_BOOTARGS "console=ttymxc0,115200 root=/dev/mmcblk0p1 rootwait rw"
+#define USBARMORY_FIT_PATH	"/boot/usbarmory.itb"
+#define USBARMORY_FIT_ADDR	"0x70800000"
+#endif
+
 /* Physical Memory Map */
 #define CONFIG_NR_DRAM_BANKS		1
 #define PHYS_SDRAM			CSD0_BASE_ADDR
diff --git a/include/configs/v38b.h b/include/configs/v38b.h
index 28c748d..5ebdf5b 100644
--- a/include/configs/v38b.h
+++ b/include/configs/v38b.h
@@ -55,7 +55,7 @@
 #define SDRAM_TAPDELAY		0x10000000
 
 /*
- * PCI - no suport
+ * PCI - no support
  */
 #undef CONFIG_PCI
 
diff --git a/include/configs/vexpress_aemv8a.h b/include/configs/vexpress_aemv8a.h
index 46cf83b..9aca393 100644
--- a/include/configs/vexpress_aemv8a.h
+++ b/include/configs/vexpress_aemv8a.h
@@ -133,7 +133,6 @@
 /* Command line configuration */
 #define CONFIG_MENU
 /*#define CONFIG_MENU_SHOW*/
-#define CONFIG_CMD_BOOTI
 #define CONFIG_CMD_UNZIP
 #define CONFIG_CMD_PXE
 #define CONFIG_CMD_ENV
diff --git a/include/configs/vexpress_ca15_tc2.h b/include/configs/vexpress_ca15_tc2.h
index b509a9c..9583e8c 100644
--- a/include/configs/vexpress_ca15_tc2.h
+++ b/include/configs/vexpress_ca15_tc2.h
@@ -16,5 +16,6 @@
 
 #define CONFIG_SYSFLAGS_ADDR	0x1c010030
 #define CONFIG_SMP_PEN_ADDR	CONFIG_SYSFLAGS_ADDR
+#define CONFIG_ARMV7_PSCI_NR_CPUS	4
 
 #endif
diff --git a/include/configs/wandboard.h b/include/configs/wandboard.h
index 99f5c0c..2a00ff4 100644
--- a/include/configs/wandboard.h
+++ b/include/configs/wandboard.h
@@ -28,6 +28,18 @@
 #define CONFIG_MXC_UART
 #define CONFIG_MXC_UART_BASE		UART1_BASE
 
+/* SATA Configs */
+
+#define CONFIG_CMD_SATA
+#ifdef CONFIG_CMD_SATA
+#define CONFIG_DWC_AHSATA
+#define CONFIG_SYS_SATA_MAX_DEVICE	1
+#define CONFIG_DWC_AHSATA_PORT_ID	0
+#define CONFIG_DWC_AHSATA_BASE_ADDR	SATA_ARB_BASE_ADDR
+#define CONFIG_LBA48
+#define CONFIG_LIBATA
+#endif
+
 /* Command definition */
 #define CONFIG_CMD_BMODE
 
@@ -181,7 +193,7 @@
 #define CONFIG_ENV_SIZE			(8 * 1024)
 
 #define CONFIG_ENV_IS_IN_MMC
-#define CONFIG_ENV_OFFSET		(6 * 64 * 1024)
+#define CONFIG_ENV_OFFSET		(768 * 1024)
 #define CONFIG_SYS_MMC_ENV_DEV		0
 
 #endif			       /* __CONFIG_H * */
diff --git a/include/configs/warp.h b/include/configs/warp.h
index 4a8e270..12c7c38 100644
--- a/include/configs/warp.h
+++ b/include/configs/warp.h
@@ -43,7 +43,6 @@
 /* Physical Memory Map */
 #define CONFIG_NR_DRAM_BANKS		1
 #define PHYS_SDRAM			MMDC0_ARB_BASE_ADDR
-#define PHYS_SDRAM_SIZE			SZ_512M
 
 #define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM
 #define CONFIG_SYS_INIT_RAM_ADDR	IRAM_BASE_ADDR
diff --git a/include/configs/warp7.h b/include/configs/warp7.h
index fc0e51a..e59b16c 100644
--- a/include/configs/warp7.h
+++ b/include/configs/warp7.h
@@ -21,6 +21,8 @@
 #define CONFIG_BOARD_EARLY_INIT_F
 #define CONFIG_BOARD_LATE_INIT
 
+#define CONFIG_DISPLAY_BOARDINFO
+
 /* MMC Config*/
 #define CONFIG_SYS_FSL_ESDHC_ADDR       USDHC3_BASE_ADDR
 #define CONFIG_SUPPORT_EMMC_BOOT
@@ -114,8 +116,6 @@
 #define CONFIG_MMCROOT			"/dev/mmcblk2p2"
 
 /* USB Configs */
-#define CONFIG_USB_EHCI
-#define CONFIG_USB_EHCI_MX7
 #define CONFIG_USB_STORAGE
 #define CONFIG_EHCI_HCD_INIT_AFTER_RESET
 
@@ -125,18 +125,9 @@
 
 #define CONFIG_IMX_THERMAL
 
-#define CONFIG_CI_UDC
 #define CONFIG_USBD_HS
-#define CONFIG_USB_GADGET_DUALSPEED
 
-#define CONFIG_USB_GADGET
 #define CONFIG_USB_FUNCTION_MASS_STORAGE
-#define CONFIG_USB_GADGET_DOWNLOAD
-#define CONFIG_USB_GADGET_VBUS_DRAW	2
-
-#define CONFIG_G_DNL_VENDOR_NUM		0x0525
-#define CONFIG_G_DNL_PRODUCT_NUM	0xa4a5
-#define CONFIG_G_DNL_MANUFACTURER	"FSL"
 
 /* USB Device Firmware Update support */
 #define CONFIG_USB_FUNCTION_DFU
diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h
index e776e32..ca60e5d 100644
--- a/include/configs/xilinx_zynqmp.h
+++ b/include/configs/xilinx_zynqmp.h
@@ -41,7 +41,7 @@
 # define CONFIG_IDENT_STRING		" Xilinx ZynqMP"
 #endif
 
-#define CONFIG_SYS_INIT_SP_ADDR		0xfffffffc
+#define CONFIG_SYS_INIT_SP_ADDR		CONFIG_SYS_TEXT_BASE
 
 /* Generic Timer Definitions - setup in EL3. Setup by ATF for other cases */
 #if !defined(COUNTER_FREQUENCY)
@@ -117,7 +117,6 @@
 #if defined(CONFIG_ZYNQMP_USB)
 #define CONFIG_USB_MAX_CONTROLLER_COUNT         1
 #define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS      2
-#define CONFIG_USB_STORAGE
 #define CONFIG_USB_XHCI_ZYNQMP
 
 #define CONFIG_SYS_DFU_DATA_BUF_SIZE	0x1800000
@@ -206,7 +205,6 @@
 
 #define CONFIG_SYS_BOOTM_LEN	(60 * 1024 * 1024)
 
-#define CONFIG_CMD_BOOTI
 #define CONFIG_CMD_UNZIP
 
 #define CONFIG_BOARD_EARLY_INIT_R
@@ -257,6 +255,7 @@
 #endif
 
 #define CONFIG_SPL_TEXT_BASE		0xfffc0000
+#define CONFIG_SPL_STACK		0xfffffffc
 #define CONFIG_SPL_MAX_SIZE		0x20000
 
 /* Just random location in OCM */
diff --git a/include/configs/xilinx_zynqmp_ep.h b/include/configs/xilinx_zynqmp_ep.h
index c5bd5da..44434aa 100644
--- a/include/configs/xilinx_zynqmp_ep.h
+++ b/include/configs/xilinx_zynqmp_ep.h
@@ -17,6 +17,7 @@
 #define CONFIG_ZYNQ_SDHCI_MIN_FREQ	(CONFIG_ZYNQ_SDHCI_MAX_FREQ << 9)
 #define CONFIG_ZYNQ_EEPROM
 #define CONFIG_AHCI
+#define CONFIG_SATA_CEVA
 #define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB0_XHCI_BASEADDR, \
 				 ZYNQMP_USB1_XHCI_BASEADDR}
 
diff --git a/include/configs/xpedite1000.h b/include/configs/xpedite1000.h
index 73c8d5b..bc91714 100644
--- a/include/configs/xpedite1000.h
+++ b/include/configs/xpedite1000.h
@@ -304,7 +304,7 @@
 	"osfile=/home/user/board.uImage\0"				\
 	"fdtfile=/home/user/board.dtb\0"				\
 	"ubootfile=/home/user/u-boot.bin\0"				\
-	"fdtaddr=c00000\0"						\
+	"fdtaddr=0x1e00000\0"						\
 	"osaddr=0x1000000\0"						\
 	"loadaddr=0x1000000\0"						\
 	"prog_uboot="CONFIG_PROG_UBOOT"\0"				\
diff --git a/include/configs/xpedite517x.h b/include/configs/xpedite517x.h
index 9f3158d..eaea33b 100644
--- a/include/configs/xpedite517x.h
+++ b/include/configs/xpedite517x.h
@@ -699,7 +699,7 @@
 	"osfile=/home/user/board.uImage\0"				\
 	"fdtfile=/home/user/board.dtb\0"				\
 	"ubootfile=/home/user/u-boot.bin\0"				\
-	"fdtaddr=c00000\0"						\
+	"fdtaddr=0x1e00000\0"						\
 	"osaddr=0x1000000\0"						\
 	"loadaddr=0x1000000\0"						\
 	"prog_uboot1="CONFIG_PROG_UBOOT1"\0"				\
diff --git a/include/configs/xpedite520x.h b/include/configs/xpedite520x.h
index a418fc5..f7cfc9e 100644
--- a/include/configs/xpedite520x.h
+++ b/include/configs/xpedite520x.h
@@ -483,7 +483,7 @@
 	"osfile=/home/user/board.uImage\0"				\
 	"fdtfile=/home/user/board.dtb\0"				\
 	"ubootfile=/home/user/u-boot.bin\0"				\
-	"fdtaddr=c00000\0"						\
+	"fdtaddr=0x1e00000\0"						\
 	"osaddr=0x1000000\0"						\
 	"loadaddr=0x1000000\0"						\
 	"prog_uboot1="CONFIG_PROG_UBOOT1"\0"				\
diff --git a/include/configs/xpedite537x.h b/include/configs/xpedite537x.h
index 36df668..3306e44a 100644
--- a/include/configs/xpedite537x.h
+++ b/include/configs/xpedite537x.h
@@ -554,7 +554,7 @@
 	"osfile=/home/user/board.uImage\0"				\
 	"fdtfile=/home/user/board.dtb\0"				\
 	"ubootfile=/home/user/u-boot.bin\0"				\
-	"fdtaddr=c00000\0"						\
+	"fdtaddr=0x1e00000\0"						\
 	"osaddr=0x1000000\0"						\
 	"loadaddr=0x1000000\0"						\
 	"prog_uboot1="CONFIG_PROG_UBOOT1"\0"				\
diff --git a/include/configs/xpedite550x.h b/include/configs/xpedite550x.h
index 1794ba1..276dde7 100644
--- a/include/configs/xpedite550x.h
+++ b/include/configs/xpedite550x.h
@@ -538,7 +538,7 @@
 	"osfile=/home/user/board.uImage\0"				\
 	"fdtfile=/home/user/board.dtb\0"				\
 	"ubootfile=/home/user/u-boot.bin\0"				\
-	"fdtaddr=c00000\0"						\
+	"fdtaddr=0x1e00000\0"						\
 	"osaddr=0x1000000\0"						\
 	"loadaddr=0x1000000\0"						\
 	"prog_uboot1="CONFIG_PROG_UBOOT1"\0"				\
diff --git a/include/configs/xtfpga.h b/include/configs/xtfpga.h
new file mode 100644
index 0000000..c5b06e3
--- /dev/null
+++ b/include/configs/xtfpga.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2007-2013 Tensilica, Inc.
+ * Copyright (C) 2014 - 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <asm/arch/core.h>
+#include <asm/addrspace.h>
+#include <asm/config.h>
+
+/*
+ * The 'xtfpga' board describes a set of very similar boards with only minimal
+ * differences.
+ */
+
+/*=====================*/
+/* Board and Processor */
+/*=====================*/
+
+#define CONFIG_XTFPGA
+
+/* FPGA CPU freq after init */
+#define CONFIG_SYS_CLK_FREQ		(gd->cpu_clk)
+
+/*===================*/
+/* RAM Layout        */
+/*===================*/
+
+#if XCHAL_HAVE_PTP_MMU
+#define CONFIG_SYS_MEMORY_BASE		\
+	(XCHAL_VECBASE_RESET_VADDR - XCHAL_VECBASE_RESET_PADDR)
+#define CONFIG_SYS_IO_BASE		0xf0000000
+#else
+#define CONFIG_SYS_MEMORY_BASE		0x60000000
+#define CONFIG_SYS_IO_BASE		0x90000000
+#define CONFIG_MAX_MEM_MAPPED		0x10000000
+#endif
+
+/* Onboard RAM sizes:
+ *
+ * LX60		0x04000000		  64 MB
+ * LX110	0x03000000		  48 MB
+ * LX200	0x06000000		  96 MB
+ * ML605	0x18000000		 384 MB
+ * KC705	0x38000000		 896 MB
+ *
+ * noMMU configurations can only see first 256MB of onboard memory.
+ */
+
+#if XCHAL_HAVE_PTP_MMU || CONFIG_BOARD_SDRAM_SIZE < 0x10000000
+#define CONFIG_SYS_SDRAM_SIZE		CONFIG_BOARD_SDRAM_SIZE
+#else
+#define CONFIG_SYS_SDRAM_SIZE		0x10000000
+#endif
+
+#define CONFIG_SYS_SDRAM_BASE		MEMADDR(0x00000000)
+
+/* Lx60 can only map 128kb memory (instead of 256kb) when running under OCD */
+#ifdef CONFIG_XTFPGA_LX60
+# define CONFIG_SYS_MONITOR_LEN		0x00020000	/* 128KB */
+#else
+# define CONFIG_SYS_MONITOR_LEN		0x00040000	/* 256KB */
+#endif
+
+#define CONFIG_SYS_STACKSIZE		(512 << 10)	/* stack 512KB */
+#define CONFIG_SYS_MALLOC_LEN		(256 << 10)	/* heap  256KB */
+
+/* Linux boot param area in RAM (used only when booting linux) */
+#define CONFIG_SYS_BOOTPARAMS_LEN	(64  << 10)
+
+/* Memory test is destructive so default must not overlap vectors or U-Boot*/
+#define CONFIG_SYS_MEMTEST_START	MEMADDR(0x01000000)
+#define CONFIG_SYS_MEMTEST_END		MEMADDR(0x02000000)
+
+/* Load address for stand-alone applications.
+ * MEMADDR cannot be used here, because the definition needs to be
+ * a plain number as it's used as -Ttext argument for ld in standalone
+ * example makefile.
+ * Handle noMMU vs MMUv2 vs MMUv3 distinction here manually.
+ */
+#if XCHAL_HAVE_PTP_MMU
+#if XCHAL_VECBASE_RESET_VADDR == XCHAL_VECBASE_RESET_PADDR
+#define CONFIG_STANDALONE_LOAD_ADDR	0x00800000
+#else
+#define CONFIG_STANDALONE_LOAD_ADDR	0xd0800000
+#endif
+#else
+#define CONFIG_STANDALONE_LOAD_ADDR	0x60800000
+#endif
+
+#if defined(CONFIG_MAX_MEM_MAPPED) && \
+	CONFIG_MAX_MEM_MAPPED < CONFIG_SYS_SDRAM_SIZE
+#define CONFIG_SYS_MEMORY_SIZE		CONFIG_MAX_MEM_MAPPED
+#else
+#define CONFIG_SYS_MEMORY_SIZE		CONFIG_SYS_SDRAM_SIZE
+#endif
+
+#define CONFIG_SYS_MEMORY_TOP		MEMADDR(CONFIG_SYS_MEMORY_SIZE)
+#define CONFIG_SYS_TEXT_ADDR		\
+	(CONFIG_SYS_MEMORY_TOP - CONFIG_SYS_MONITOR_LEN)
+
+/* Used by tftpboot; env var 'loadaddr' */
+#define CONFIG_SYS_LOAD_ADDR		MEMADDR(0x02000000)
+
+/*==============================*/
+/* U-Boot general configuration */
+/*==============================*/
+
+#undef	CONFIG_USE_IRQ			/* Keep it simple, poll only */
+#define CONFIG_BOARD_POSTCLK_INIT
+#define CONFIG_DISPLAY_CPUINFO
+#define CONFIG_DISPLAY_BOARDINFO
+#define CONFIG_MISC_INIT_R
+
+#define CONFIG_BOOTFILE			"uImage"
+	/* Console I/O Buffer Size  */
+#define CONFIG_SYS_CBSIZE		1024
+	/* Prt buf */
+#define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE + \
+					 sizeof(CONFIG_SYS_PROMPT) + 16)
+	/* max number of command args */
+#define CONFIG_SYS_MAXARGS		16
+	/* Boot Argument Buffer Size */
+#define CONFIG_SYS_BARGSIZE		CONFIG_SYS_CBSIZE
+
+/*=================*/
+/* U-Boot commands */
+/*=================*/
+
+#define CONFIG_CMD_DIAG
+#define CONFIG_CMD_SAVES
+
+/*==============================*/
+/* U-Boot autoboot configuration */
+/*==============================*/
+
+#define CONFIG_BOOT_RETRY_TIME		60	/* retry after 60 secs */
+
+#define CONFIG_VERSION_VARIABLE
+#define CONFIG_AUTO_COMPLETE			/* Support tab autocompletion */
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_CRC32_VERIFY
+#define CONFIG_MX_CYCLIC
+#define CONFIG_SHOW_BOOT_PROGRESS
+
+#ifdef DEBUG
+#define CONFIG_PANIC_HANG		1	/* Require manual reboot */
+#endif
+
+
+/*=========================================*/
+/* FPGA Registers (board info and control) */
+/*=========================================*/
+
+/*
+ * These assume FPGA bitstreams from Tensilica release RB and up. Earlier
+ * releases may not provide any/all of these registers or at these offsets.
+ * Some of the FPGA registers are broken down into bitfields described by
+ * SHIFT left amount and field WIDTH (bits), and also by a bitMASK.
+ */
+
+/* Date of FPGA bitstream build in binary coded decimal (BCD) */
+#define CONFIG_SYS_FPGAREG_DATE		IOADDR(0x0D020000)
+#define FPGAREG_MTH_SHIFT		24		/* BCD month 1..12 */
+#define FPGAREG_MTH_WIDTH		8
+#define FPGAREG_MTH_MASK		0xFF000000
+#define FPGAREG_DAY_SHIFT		16		/* BCD day 1..31 */
+#define FPGAREG_DAY_WIDTH		8
+#define FPGAREG_DAY_MASK		0x00FF0000
+#define FPGAREG_YEAR_SHIFT		0		/* BCD year 2001..9999*/
+#define FPGAREG_YEAR_WIDTH		16
+#define FPGAREG_YEAR_MASK		0x0000FFFF
+
+/* FPGA core clock frequency in Hz (also input to UART) */
+#define CONFIG_SYS_FPGAREG_FREQ	IOADDR(0x0D020004)	/* CPU clock frequency*/
+
+/*
+ * DIP switch (left=sw1=lsb=bit0, right=sw8=msb=bit7; off=0, on=1):
+ *   Bits 0..5 set the lower 6 bits of the default ethernet MAC.
+ *   Bit 6 is reserved for future use by Tensilica.
+ *   Bit 7 maps the first 128KB of ROM address space at CONFIG_SYS_ROM_BASE to
+ *   the base of flash * (when on/1) or to the base of RAM (when off/0).
+ */
+#define CONFIG_SYS_FPGAREG_DIPSW	IOADDR(0x0D02000C)
+#define FPGAREG_MAC_SHIFT		0	/* Ethernet MAC bits 0..5 */
+#define FPGAREG_MAC_WIDTH		6
+#define FPGAREG_MAC_MASK		0x3f
+#define FPGAREG_BOOT_SHIFT		7	/* Boot ROM addr mapping */
+#define FPGAREG_BOOT_WIDTH		1
+#define FPGAREG_BOOT_MASK		0x80
+#define FPGAREG_BOOT_RAM		0
+#define FPGAREG_BOOT_FLASH		(1<<FPGAREG_BOOT_SHIFT)
+
+/* Force hard reset of board by writing a code to this register */
+#define CONFIG_SYS_FPGAREG_RESET	IOADDR(0x0D020010) /* Reset board .. */
+#define CONFIG_SYS_FPGAREG_RESET_CODE	0x0000DEAD   /*  by writing this code */
+
+/*====================*/
+/* Serial Driver Info */
+/*====================*/
+
+#define CONFIG_SYS_NS16550_SERIAL
+#define CONFIG_SYS_NS16550_REG_SIZE	(-4)
+#define CONFIG_SYS_NS16550_COM1		IOADDR(0x0D050020) /* Base address */
+
+/* Input clk to NS16550 (in Hz; the SYS_CLK_FREQ is in kHz) */
+#define CONFIG_SYS_NS16550_CLK		CONFIG_SYS_CLK_FREQ
+#define CONFIG_CONS_INDEX		1	/* use UART0 for console */
+#define CONFIG_BAUDRATE			115200	/* Default baud rate */
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/*======================*/
+/* Ethernet Driver Info */
+/*======================*/
+
+#define CONFIG_ETHBASE			00:50:C2:13:6f:00
+#define CONFIG_SYS_ETHOC_BASE		IOADDR(0x0d030000)
+#define CONFIG_SYS_ETHOC_BUFFER_ADDR	IOADDR(0x0D800000)
+
+/*=====================*/
+/* Flash & Environment */
+/*=====================*/
+
+#define CONFIG_SYS_FLASH_CFI
+#define CONFIG_FLASH_CFI_DRIVER			/* use generic CFI driver */
+#define CONFIG_SYS_FLASH_CFI_WIDTH	FLASH_CFI_16BIT
+#define CONFIG_SYS_MAX_FLASH_BANKS	1
+#ifdef CONFIG_XTFPGA_LX60
+# define CONFIG_SYS_FLASH_SIZE		0x0040000	/* 4MB */
+# define CONFIG_SYS_FLASH_SECT_SZ	0x10000		/* block size 64KB */
+# define CONFIG_SYS_FLASH_PARMSECT_SZ	0x2000		/* param size  8KB */
+# define CONFIG_SYS_FLASH_BASE		IOADDR(0x08000000)
+# define CONFIG_SYS_MONITOR_BASE	CONFIG_SYS_FLASH_BASE
+#elif defined(CONFIG_XTFPGA_KC705)
+# define CONFIG_SYS_FLASH_SIZE		0x8000000	/* 128MB */
+# define CONFIG_SYS_FLASH_SECT_SZ	0x20000		/* block size 128KB */
+# define CONFIG_SYS_FLASH_PARMSECT_SZ	0x8000		/* param size 32KB */
+# define CONFIG_SYS_FLASH_BASE		IOADDR(0x00000000)
+# define CONFIG_SYS_MONITOR_BASE	IOADDR(0x06000000)
+#else
+# define CONFIG_SYS_FLASH_SIZE		0x1000000	/* 16MB */
+# define CONFIG_SYS_FLASH_SECT_SZ	0x20000		/* block size 128KB */
+# define CONFIG_SYS_FLASH_PARMSECT_SZ	0x8000		/* param size 32KB */
+# define CONFIG_SYS_FLASH_BASE		IOADDR(0x08000000)
+# define CONFIG_SYS_MONITOR_BASE	CONFIG_SYS_FLASH_BASE
+#endif
+#define CONFIG_SYS_MAX_FLASH_SECT	\
+	(CONFIG_SYS_FLASH_SECT_SZ/CONFIG_SYS_FLASH_PARMSECT_SZ + \
+	 CONFIG_SYS_FLASH_SIZE/CONFIG_SYS_FLASH_SECT_SZ - 1)
+#define CONFIG_SYS_FLASH_PROTECTION		/* hw flash protection */
+
+/*
+ * Put environment in top block (64kB)
+ * Another option would be to put env. in 2nd param block offs 8KB, size 8KB
+ */
+#define CONFIG_ENV_IS_IN_FLASH
+#define CONFIG_ENV_OFFSET    (CONFIG_SYS_FLASH_SIZE - CONFIG_SYS_FLASH_SECT_SZ)
+#define CONFIG_ENV_SIZE	     CONFIG_SYS_FLASH_SECT_SZ
+
+/* print 'E' for empty sector on flinfo */
+#define CONFIG_SYS_FLASH_EMPTY_INFO
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/zc5202.h b/include/configs/zc5202.h
new file mode 100644
index 0000000..073a42c
--- /dev/null
+++ b/include/configs/zc5202.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Stefano Babic <sbabic@denx.de>
+ *
+ * Configuration settings for the E+L i.MX6Q DO82 board.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __EL_ZC5202_H
+#define __EL_ZC5202_H
+
+#define CONFIG_MXC_UART_BASE	UART2_BASE
+#define CONFIG_CONSOLE_DEV		"ttymxc1"
+#define CONFIG_MMCROOT			"/dev/mmcblk0p2"
+
+#define CONFIG_DEFAULT_FDT_FILE	"imx6q-zc5202.dtb"
+
+#define CONFIG_SUPPORT_EMMC_BOOT /* eMMC specific */
+
+#include "el6x_common.h"
+
+/* Ethernet */
+#define CONFIG_FEC_MXC
+#define CONFIG_MII
+#define IMX_FEC_BASE				ENET_BASE_ADDR
+#define CONFIG_FEC_XCV_TYPE			MII100
+#define CONFIG_ETHPRIME				"FEC"
+#define CONFIG_FEC_MXC_PHYADDR			0
+#define CONFIG_MV88E6352_SWITCH
+
+#define CONFIG_CMD_PCI
+#define CONFIG_PCI
+#define CONFIG_PCI_PNP
+#define CONFIG_PCI_SCAN_SHOW
+#define CONFIG_PCIE_IMX
+
+#endif                         /*__EL6Q_CONFIG_H */
diff --git a/include/configs/zc5601.h b/include/configs/zc5601.h
new file mode 100644
index 0000000..28b9c6b
--- /dev/null
+++ b/include/configs/zc5601.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Stefano Babic <sbabic@denx.de>
+ *
+ * Configuration settings for the E+L i.MX6Q DO82 board.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __EL_ZC5601_H
+#define __EL_ZC5601_H
+
+
+#define CONFIG_MXC_UART_BASE	UART2_BASE
+#define CONFIG_CONSOLE_DEV		"ttymxc1"
+#define CONFIG_MMCROOT			"/dev/mmcblk0p1"
+
+#define CONFIG_DEFAULT_FDT_FILE	"imx6q-zc5601.dtb"
+
+#define CONFIG_SUPPORT_EMMC_BOOT /* eMMC specific */
+
+#include "el6x_common.h"
+
+/* Ethernet */
+#define CONFIG_FEC_MXC
+#define CONFIG_MII
+#define IMX_FEC_BASE				ENET_BASE_ADDR
+#define CONFIG_FEC_XCV_TYPE			RGMII
+#define CONFIG_ETHPRIME				"FEC"
+#define CONFIG_FEC_MXC_PHYADDR			0x10
+#define CONFIG_PHYLIB
+#define CONFIG_FEC_FIXED_SPEED			1000 /* No autoneg, fix Gb */
+
+#endif                         /*__EL6Q_CONFIG_H */
diff --git a/include/configs/zynq-common.h b/include/configs/zynq-common.h
index 8dbac87..e59e412 100644
--- a/include/configs/zynq-common.h
+++ b/include/configs/zynq-common.h
@@ -86,10 +86,7 @@
 # define CONFIG_ZYNQ_SDHCI_MAX_FREQ	52000000
 #endif
 
-#ifdef CONFIG_ZYNQ_USB
-# define CONFIG_USB_EHCI
-# define CONFIG_USB_STORAGE
-# define CONFIG_USB_EHCI_ZYNQ
+#ifdef CONFIG_USB_EHCI_ZYNQ
 # define CONFIG_EHCI_IS_TDI
 # define CONFIG_USB_MAX_CONTROLLER_COUNT	2
 
diff --git a/include/configs/zynq_microzed.h b/include/configs/zynq_microzed.h
deleted file mode 100644
index ec7bb1c..0000000
--- a/include/configs/zynq_microzed.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * (C) Copyright 2013 Xilinx, Inc.
- *
- * Configuration for Micro Zynq Evaluation and Development Board - MicroZedBoard
- * See zynq-common.h for Zynq common configs
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef __CONFIG_ZYNQ_MICROZED_H
-#define __CONFIG_ZYNQ_MICROZED_H
-
-#define CONFIG_SYS_NO_FLASH
-
-#define CONFIG_ZYNQ_USB
-
-#include <configs/zynq-common.h>
-
-#endif /* __CONFIG_ZYNQ_MICROZED_H */
diff --git a/include/configs/zynq_picozed.h b/include/configs/zynq_picozed.h
deleted file mode 100644
index adc4d0f..0000000
--- a/include/configs/zynq_picozed.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * (C) Copyright 2015 Xilinx, Inc.
- *
- * Configuration for PicoZed
- * See zynq-common.h for Zynq common configs
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef __CONFIG_ZYNQ_PICOZED_H
-#define __CONFIG_ZYNQ_PICOZED_H
-
-#define CONFIG_SYS_NO_FLASH
-
-#define CONFIG_ZYNQ_USB
-
-#include <configs/zynq-common.h>
-
-#endif /* __CONFIG_ZYNQ_PICOZED_H */
diff --git a/include/configs/zynq_zc70x.h b/include/configs/zynq_zc70x.h
index 8a04590..fc46fec 100644
--- a/include/configs/zynq_zc70x.h
+++ b/include/configs/zynq_zc70x.h
@@ -10,9 +10,6 @@
 #ifndef __CONFIG_ZYNQ_ZC70X_H
 #define __CONFIG_ZYNQ_ZC70X_H
 
-#define CONFIG_SYS_NO_FLASH
-
-#define CONFIG_ZYNQ_USB
 #define CONFIG_ZYNQ_I2C0
 #define CONFIG_ZYNQ_EEPROM
 
diff --git a/include/configs/zynq_zc770.h b/include/configs/zynq_zc770.h
deleted file mode 100644
index 35622ae..0000000
--- a/include/configs/zynq_zc770.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * (C) Copyright 2013 Xilinx, Inc.
- *
- * Configuration settings for the Xilinx Zynq ZC770 board.
- * See zynq-common.h for Zynq common configs
- *
- * SPDX-License-Identifier:     GPL-2.0+
- */
-
-#ifndef __CONFIG_ZYNQ_ZC770_H
-#define __CONFIG_ZYNQ_ZC770_H
-
-#define CONFIG_SYS_NO_FLASH
-
-#if defined(CONFIG_ZC770_XM012)
-# undef CONFIG_SYS_NO_FLASH
-
-#endif
-
-#include <configs/zynq-common.h>
-
-#endif /* __CONFIG_ZYNQ_ZC770_H */
diff --git a/include/configs/zynq_zed.h b/include/configs/zynq_zed.h
deleted file mode 100644
index 150cb4a..0000000
--- a/include/configs/zynq_zed.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * (C) Copyright 2013 Xilinx, Inc.
- *
- * Configuration for Zynq Evaluation and Development Board - ZedBoard
- * See zynq-common.h for Zynq common configs
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef __CONFIG_ZYNQ_ZED_H
-#define __CONFIG_ZYNQ_ZED_H
-
-#define CONFIG_SYS_NO_FLASH
-
-#define CONFIG_ZYNQ_USB
-
-#include <configs/zynq-common.h>
-
-#endif /* __CONFIG_ZYNQ_ZED_H */
diff --git a/include/configs/zynq_zybo.h b/include/configs/zynq_zybo.h
index 637b1c5..b9ff391 100644
--- a/include/configs/zynq_zybo.h
+++ b/include/configs/zynq_zybo.h
@@ -11,9 +11,6 @@
 #ifndef __CONFIG_ZYNQ_ZYBO_H
 #define __CONFIG_ZYNQ_ZYBO_H
 
-#define CONFIG_SYS_NO_FLASH
-
-#define CONFIG_ZYNQ_USB
 #define CONFIG_ZYNQ_I2C0
 #define CONFIG_ZYNQ_I2C1
 #define CONFIG_SYS_I2C_EEPROM_ADDR_LEN	1
diff --git a/include/dm/device.h b/include/dm/device.h
index f03bcd3..babf8ac 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -42,7 +42,9 @@
 #define DM_FLAG_BOUND			(1 << 6)
 
 /* Device name is allocated and should be freed on unbind() */
-#define DM_NAME_ALLOCED			(1 << 7)
+#define DM_FLAG_NAME_ALLOCED		(1 << 7)
+
+#define DM_FLAG_OF_PLATDATA		(1 << 8)
 
 /**
  * struct udevice - An instance of a driver
@@ -205,6 +207,10 @@
 #define U_BOOT_DRIVER(__name)						\
 	ll_entry_declare(struct driver, __name, driver)
 
+/* Get a pointer to a given driver */
+#define DM_GET_DRIVER(__name)						\
+	ll_entry_get(struct driver, __name, driver)
+
 /**
  * dev_get_platdata() - Get the platform data for a device
  *
@@ -467,6 +473,19 @@
 void *dev_get_addr_ptr(struct udevice *dev);
 
 /**
+ * dev_map_physmem() - Read device address from reg property of the
+ *                     device node and map the address into CPU address
+ *                     space.
+ *
+ * @dev: Pointer to device
+ * @size: size of the memory to map
+ *
+ * @return  mapped address, or NULL if the device does not have reg
+ *          property.
+ */
+void *dev_map_physmem(struct udevice *dev, unsigned long size);
+
+/**
  * dev_get_addr_index() - Get the indexed reg property of a device
  *
  * @dev: Pointer to a device
@@ -540,7 +559,7 @@
 /**
  * device_set_name_alloced() - note that a device name is allocated
  *
- * This sets the DM_NAME_ALLOCED flag for the device, so that when it is
+ * This sets the DM_FLAG_NAME_ALLOCED flag for the device, so that when it is
  * unbound the name will be freed. This avoids memory leaks.
  *
  * @dev:	Device to update
@@ -593,6 +612,22 @@
 #define device_foreach_child_safe(pos, next, parent)	\
 	list_for_each_entry_safe(pos, next, &parent->child_head, sibling_node)
 
+/**
+ * dm_scan_fdt_dev() - Bind child device in a the device tree
+ *
+ * This handles device which have sub-nodes in the device tree. It scans all
+ * sub-nodes and binds drivers for each node where a driver can be found.
+ *
+ * If this is called prior to relocation, only pre-relocation devices will be
+ * bound (those marked with u-boot,dm-pre-reloc in the device tree, or where
+ * the driver has the DM_FLAG_PRE_RELOC flag set). Otherwise, all devices will
+ * be bound.
+ *
+ * @dev:	Device to scan
+ * @return 0 if OK, -ve on error
+ */
+int dm_scan_fdt_dev(struct udevice *dev);
+
 /* device resource management */
 typedef void (*dr_release_t)(struct udevice *dev, void *res);
 typedef int (*dr_match_t)(struct udevice *dev, void *res, void *match_data);
diff --git a/include/dm/platdata.h b/include/dm/platdata.h
index 6f4f001..488b2ab 100644
--- a/include/dm/platdata.h
+++ b/include/dm/platdata.h
@@ -22,10 +22,15 @@
  *
  * @name:	Driver name
  * @platdata:	Driver-specific platform data
+ * @platdata_size: Size of platform data structure
+ * @flags:	Platform data flags (DM_FLAG_...)
  */
 struct driver_info {
 	const char *name;
 	const void *platdata;
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	uint platdata_size;
+#endif
 };
 
 /**
diff --git a/include/dm/platform_data/net_ethoc.h b/include/dm/platform_data/net_ethoc.h
new file mode 100644
index 0000000..3f94bde
--- /dev/null
+++ b/include/dm/platform_data/net_ethoc.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ETHOC_H
+#define _ETHOC_H
+
+#include <net.h>
+
+#ifdef CONFIG_DM_ETH
+
+struct ethoc_eth_pdata {
+	struct eth_pdata eth_pdata;
+	phys_addr_t packet_base;
+};
+
+#endif
+
+#endif /* _ETHOC_H */
diff --git a/include/dm/platform_data/serial_mxc.h b/include/dm/platform_data/serial_mxc.h
index 7d3ace2..7bcd280 100644
--- a/include/dm/platform_data/serial_mxc.h
+++ b/include/dm/platform_data/serial_mxc.h
@@ -9,6 +9,7 @@
 /* Information about a serial port */
 struct mxc_serial_platdata {
 	struct mxc_uart *reg;  /* address of registers in physical memory */
+	bool use_dte;
 };
 
 #endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index b768660..eb78c4d 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -33,7 +33,6 @@
 	UCLASS_CROS_EC,		/* Chrome OS EC */
 	UCLASS_DISPLAY,		/* Display (e.g. DisplayPort, HDMI) */
 	UCLASS_DMA,		/* Direct Memory Access */
-	UCLASS_RAM,		/* RAM controller */
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_GPIO,		/* Bank of general-purpose I/O pins */
 	UCLASS_I2C,		/* I2C bus */
@@ -56,11 +55,13 @@
 	UCLASS_PCH,		/* x86 platform controller hub */
 	UCLASS_PCI,		/* PCI bus */
 	UCLASS_PCI_GENERIC,	/* Generic PCI bus device */
-	UCLASS_PINCTRL,		/* Pinctrl (pin muxing/configuration) device */
 	UCLASS_PINCONFIG,	/* Pin configuration node device */
+	UCLASS_PINCTRL,		/* Pinctrl (pin muxing/configuration) device */
 	UCLASS_PMIC,		/* PMIC I/O device */
 	UCLASS_PWM,		/* Pulse-width modulator */
+	UCLASS_POWER_DOMAIN,	/* (SoC) Power domains */
 	UCLASS_PWRSEQ,		/* Power sequence device */
+	UCLASS_RAM,		/* RAM controller */
 	UCLASS_REGULATOR,	/* Regulator device */
 	UCLASS_REMOTEPROC,	/* Remote Processor device */
 	UCLASS_RESET,		/* Reset controller device */
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index fd368b6..84f05bc 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -38,6 +38,7 @@
 	struct list_head sibling_node;
 };
 
+struct driver;
 struct udevice;
 
 /* Members of this uclass sequence themselves with aliases */
@@ -194,6 +195,23 @@
 				 const char *name, struct udevice **devp);
 
 /**
+ * uclass_get_device_by_driver() - Get a uclass device for a driver
+ *
+ * This searches the devices in the uclass for one that uses the given
+ * driver. Use DM_GET_DRIVER(name) for the @drv argument, where 'name' is
+ * the driver name - as used in U_BOOT_DRIVER(name).
+ *
+ * The device is probed to activate it ready for use.
+ *
+ * @id: ID to look up
+ * @drv: Driver to look for
+ * @devp: Returns pointer to the first device with that driver
+ * @return 0 if OK, -ve on error
+ */
+int uclass_get_device_by_driver(enum uclass_id id, const struct driver *drv,
+				struct udevice **devp);
+
+/**
  * uclass_first_device() - Get the first device in a uclass
  *
  * The device returned is probed if necessary, and ready for use
diff --git a/include/dt-bindings/clock/rk3399-cru.h b/include/dt-bindings/clock/rk3399-cru.h
new file mode 100644
index 0000000..0a86aec
--- /dev/null
+++ b/include/dt-bindings/clock/rk3399-cru.h
@@ -0,0 +1,746 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3399_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3399_H
+
+/* core clocks */
+#define PLL_APLLL			1
+#define PLL_APLLB			2
+#define PLL_DPLL			3
+#define PLL_CPLL			4
+#define PLL_GPLL			5
+#define PLL_NPLL			6
+#define PLL_VPLL			7
+#define ARMCLKL				8
+#define ARMCLKB				9
+
+/* sclk gates (special clocks) */
+#define SCLK_I2C1			65
+#define SCLK_I2C2			66
+#define SCLK_I2C3			67
+#define SCLK_I2C5			68
+#define SCLK_I2C6			69
+#define SCLK_I2C7			70
+#define SCLK_SPI0			71
+#define SCLK_SPI1			72
+#define SCLK_SPI2			73
+#define SCLK_SPI4			74
+#define SCLK_SPI5			75
+#define SCLK_SDMMC			76
+#define SCLK_SDIO			77
+#define SCLK_EMMC			78
+#define SCLK_TSADC			79
+#define SCLK_SARADC			80
+#define SCLK_UART0			81
+#define SCLK_UART1			82
+#define SCLK_UART2			83
+#define SCLK_UART3			84
+#define SCLK_SPDIF_8CH			85
+#define SCLK_I2S0_8CH			86
+#define SCLK_I2S1_8CH			87
+#define SCLK_I2S2_8CH			88
+#define SCLK_I2S_8CH_OUT		89
+#define SCLK_TIMER00			90
+#define SCLK_TIMER01			91
+#define SCLK_TIMER02			92
+#define SCLK_TIMER03			93
+#define SCLK_TIMER04			94
+#define SCLK_TIMER05			95
+#define SCLK_TIMER06			96
+#define SCLK_TIMER07			97
+#define SCLK_TIMER08			98
+#define SCLK_TIMER09			99
+#define SCLK_TIMER10			100
+#define SCLK_TIMER11			101
+#define SCLK_MACREF			102
+#define SCLK_MAC_RX			103
+#define SCLK_MAC_TX			104
+#define SCLK_MAC			105
+#define SCLK_MACREF_OUT			106
+#define SCLK_VOP0_PWM			107
+#define SCLK_VOP1_PWM			108
+#define SCLK_RGA_CORE			109
+#define SCLK_ISP0			110
+#define SCLK_ISP1			111
+#define SCLK_HDMI_CEC			112
+#define SCLK_HDMI_SFR			113
+#define SCLK_DP_CORE			114
+#define SCLK_PVTM_CORE_L		115
+#define SCLK_PVTM_CORE_B		116
+#define SCLK_PVTM_GPU			117
+#define SCLK_PVTM_DDR			118
+#define SCLK_MIPIDPHY_REF		119
+#define SCLK_MIPIDPHY_CFG		120
+#define SCLK_HSICPHY			121
+#define SCLK_USBPHY480M			122
+#define SCLK_USB2PHY0_REF		123
+#define SCLK_USB2PHY1_REF		124
+#define SCLK_UPHY0_TCPDPHY_REF		125
+#define SCLK_UPHY0_TCPDCORE		126
+#define SCLK_UPHY1_TCPDPHY_REF		127
+#define SCLK_UPHY1_TCPDCORE		128
+#define SCLK_USB3OTG0_REF		129
+#define SCLK_USB3OTG1_REF		130
+#define SCLK_USB3OTG0_SUSPEND		131
+#define SCLK_USB3OTG1_SUSPEND		132
+#define SCLK_CRYPTO0			133
+#define SCLK_CRYPTO1			134
+#define SCLK_CCI_TRACE			135
+#define SCLK_CS				136
+#define SCLK_CIF_OUT			137
+#define SCLK_PCIEPHY_REF		138
+#define SCLK_PCIE_CORE			139
+#define SCLK_M0_PERILP			140
+#define SCLK_M0_PERILP_DEC		141
+#define SCLK_CM0S			142
+#define SCLK_DBG_NOC			143
+#define SCLK_DBG_PD_CORE_B		144
+#define SCLK_DBG_PD_CORE_L		145
+#define SCLK_DFIMON0_TIMER		146
+#define SCLK_DFIMON1_TIMER		147
+#define SCLK_INTMEM0			148
+#define SCLK_INTMEM1			149
+#define SCLK_INTMEM2			150
+#define SCLK_INTMEM3			151
+#define SCLK_INTMEM4			152
+#define SCLK_INTMEM5			153
+#define SCLK_SDMMC_DRV			154
+#define SCLK_SDMMC_SAMPLE		155
+#define SCLK_SDIO_DRV			156
+#define SCLK_SDIO_SAMPLE		157
+#define SCLK_VDU_CORE			158
+#define SCLK_VDU_CA			159
+#define SCLK_PCIE_PM			160
+#define SCLK_SPDIF_REC_DPTX		161
+#define SCLK_DPHY_PLL			162
+#define SCLK_DPHY_TX0_CFG		163
+#define SCLK_DPHY_TX1RX1_CFG		164
+#define SCLK_DPHY_RX0_CFG		165
+#define SCLK_RMII_SRC			166
+#define SCLK_PCIEPHY_REF100M		167
+
+#define DCLK_VOP0			180
+#define DCLK_VOP1			181
+#define DCLK_VOP0_DIV			182
+#define DCLK_VOP1_DIV			183
+#define DCLK_M0_PERILP			184
+
+#define FCLK_CM0S			190
+
+/* aclk gates */
+#define ACLK_PERIHP			192
+#define ACLK_PERIHP_NOC			193
+#define ACLK_PERILP0			194
+#define ACLK_PERILP0_NOC		195
+#define ACLK_PERF_PCIE			196
+#define ACLK_PCIE			197
+#define ACLK_INTMEM			198
+#define ACLK_TZMA			199
+#define ACLK_DCF			200
+#define ACLK_CCI			201
+#define ACLK_CCI_NOC0			202
+#define ACLK_CCI_NOC1			203
+#define ACLK_CCI_GRF			204
+#define ACLK_CENTER			205
+#define ACLK_CENTER_MAIN_NOC		206
+#define ACLK_CENTER_PERI_NOC		207
+#define ACLK_GPU			208
+#define ACLK_PERF_GPU			209
+#define ACLK_GPU_GRF			210
+#define ACLK_DMAC0_PERILP		211
+#define ACLK_DMAC1_PERILP		212
+#define ACLK_GMAC			213
+#define ACLK_GMAC_NOC			214
+#define ACLK_PERF_GMAC			215
+#define ACLK_VOP0_NOC			216
+#define ACLK_VOP0			217
+#define ACLK_VOP1_NOC			218
+#define ACLK_VOP1			219
+#define ACLK_RGA			220
+#define ACLK_RGA_NOC			221
+#define ACLK_HDCP			222
+#define ACLK_HDCP_NOC			223
+#define ACLK_HDCP22			224
+#define ACLK_IEP			225
+#define ACLK_IEP_NOC			226
+#define ACLK_VIO			227
+#define ACLK_VIO_NOC			228
+#define ACLK_ISP0			229
+#define ACLK_ISP1			230
+#define ACLK_ISP0_NOC			231
+#define ACLK_ISP1_NOC			232
+#define ACLK_ISP0_WRAPPER		233
+#define ACLK_ISP1_WRAPPER		234
+#define ACLK_VCODEC			235
+#define ACLK_VCODEC_NOC			236
+#define ACLK_VDU			237
+#define ACLK_VDU_NOC			238
+#define ACLK_PERI			239
+#define ACLK_EMMC			240
+#define ACLK_EMMC_CORE			241
+#define ACLK_EMMC_NOC			242
+#define ACLK_EMMC_GRF			243
+#define ACLK_USB3			244
+#define ACLK_USB3_NOC			245
+#define ACLK_USB3OTG0			246
+#define ACLK_USB3OTG1			247
+#define ACLK_USB3_RKSOC_AXI_PERF	248
+#define ACLK_USB3_GRF			249
+#define ACLK_GIC			250
+#define ACLK_GIC_NOC			251
+#define ACLK_GIC_ADB400_CORE_L_2_GIC	252
+#define ACLK_GIC_ADB400_CORE_B_2_GIC	253
+#define ACLK_GIC_ADB400_GIC_2_CORE_L	254
+#define ACLK_GIC_ADB400_GIC_2_CORE_B	255
+#define ACLK_CORE_ADB400_CORE_L_2_CCI500 256
+#define ACLK_CORE_ADB400_CORE_B_2_CCI500 257
+#define ACLK_ADB400M_PD_CORE_L		258
+#define ACLK_ADB400M_PD_CORE_B		259
+#define ACLK_PERF_CORE_L		260
+#define ACLK_PERF_CORE_B		261
+#define ACLK_GIC_PRE			262
+#define ACLK_VOP0_PRE			263
+#define ACLK_VOP1_PRE			264
+
+/* pclk gates */
+#define PCLK_PERIHP			320
+#define PCLK_PERIHP_NOC			321
+#define PCLK_PERILP0			322
+#define PCLK_PERILP1			323
+#define PCLK_PERILP1_NOC		324
+#define PCLK_PERILP_SGRF		325
+#define PCLK_PERIHP_GRF			326
+#define PCLK_PCIE			327
+#define PCLK_SGRF			328
+#define PCLK_INTR_ARB			329
+#define PCLK_CENTER_MAIN_NOC		330
+#define PCLK_CIC			331
+#define PCLK_COREDBG_B			332
+#define PCLK_COREDBG_L			333
+#define PCLK_DBG_CXCS_PD_CORE_B		334
+#define PCLK_DCF			335
+#define PCLK_GPIO2			336
+#define PCLK_GPIO3			337
+#define PCLK_GPIO4			338
+#define PCLK_GRF			339
+#define PCLK_HSICPHY			340
+#define PCLK_I2C1			341
+#define PCLK_I2C2			342
+#define PCLK_I2C3			343
+#define PCLK_I2C5			344
+#define PCLK_I2C6			345
+#define PCLK_I2C7			346
+#define PCLK_SPI0			347
+#define PCLK_SPI1			348
+#define PCLK_SPI2			349
+#define PCLK_SPI4			350
+#define PCLK_SPI5			351
+#define PCLK_UART0			352
+#define PCLK_UART1			353
+#define PCLK_UART2			354
+#define PCLK_UART3			355
+#define PCLK_TSADC			356
+#define PCLK_SARADC			357
+#define PCLK_GMAC			358
+#define PCLK_GMAC_NOC			359
+#define PCLK_TIMER0			360
+#define PCLK_TIMER1			361
+#define PCLK_EDP			362
+#define PCLK_EDP_NOC			363
+#define PCLK_EDP_CTRL			364
+#define PCLK_VIO			365
+#define PCLK_VIO_NOC			366
+#define PCLK_VIO_GRF			367
+#define PCLK_MIPI_DSI0			368
+#define PCLK_MIPI_DSI1			369
+#define PCLK_HDCP			370
+#define PCLK_HDCP_NOC			371
+#define PCLK_HDMI_CTRL			372
+#define PCLK_DP_CTRL			373
+#define PCLK_HDCP22			374
+#define PCLK_GASKET			375
+#define PCLK_DDR			376
+#define PCLK_DDR_MON			377
+#define PCLK_DDR_SGRF			378
+#define PCLK_ISP1_WRAPPER		379
+#define PCLK_WDT			380
+#define PCLK_EFUSE1024NS		381
+#define PCLK_EFUSE1024S			382
+#define PCLK_PMU_INTR_ARB		383
+#define PCLK_MAILBOX0			384
+#define PCLK_USBPHY_MUX_G		385
+#define PCLK_UPHY0_TCPHY_G		386
+#define PCLK_UPHY0_TCPD_G		387
+#define PCLK_UPHY1_TCPHY_G		388
+#define PCLK_UPHY1_TCPD_G		389
+#define PCLK_ALIVE			390
+
+/* hclk gates */
+#define HCLK_PERIHP			448
+#define HCLK_PERILP0			449
+#define HCLK_PERILP1			450
+#define HCLK_PERILP0_NOC		451
+#define HCLK_PERILP1_NOC		452
+#define HCLK_M0_PERILP			453
+#define HCLK_M0_PERILP_NOC		454
+#define HCLK_AHB1TOM			455
+#define HCLK_HOST0			456
+#define HCLK_HOST0_ARB			457
+#define HCLK_HOST1			458
+#define HCLK_HOST1_ARB			459
+#define HCLK_HSIC			460
+#define HCLK_SD				461
+#define HCLK_SDMMC			462
+#define HCLK_SDMMC_NOC			463
+#define HCLK_M_CRYPTO0			464
+#define HCLK_M_CRYPTO1			465
+#define HCLK_S_CRYPTO0			466
+#define HCLK_S_CRYPTO1			467
+#define HCLK_I2S0_8CH			468
+#define HCLK_I2S1_8CH			469
+#define HCLK_I2S2_8CH			470
+#define HCLK_SPDIF			471
+#define HCLK_VOP0_NOC			472
+#define HCLK_VOP0			473
+#define HCLK_VOP1_NOC			474
+#define HCLK_VOP1			475
+#define HCLK_ROM			476
+#define HCLK_IEP			477
+#define HCLK_IEP_NOC			478
+#define HCLK_ISP0			479
+#define HCLK_ISP1			480
+#define HCLK_ISP0_NOC			481
+#define HCLK_ISP1_NOC			482
+#define HCLK_ISP0_WRAPPER		483
+#define HCLK_ISP1_WRAPPER		484
+#define HCLK_RGA			485
+#define HCLK_RGA_NOC			486
+#define HCLK_HDCP			487
+#define HCLK_HDCP_NOC			488
+#define HCLK_HDCP22			489
+#define HCLK_VCODEC			490
+#define HCLK_VCODEC_NOC			491
+#define HCLK_VDU			492
+#define HCLK_VDU_NOC			493
+#define HCLK_SDIO			494
+#define HCLK_SDIO_NOC			495
+#define HCLK_SDIOAUDIO_NOC		496
+
+#define CLK_NR_CLKS			(HCLK_SDIOAUDIO_NOC + 1)
+
+/* pmu-clocks indices */
+
+#define PLL_PPLL			1
+
+#define SCLK_32K_SUSPEND_PMU		2
+#define SCLK_SPI3_PMU			3
+#define SCLK_TIMER12_PMU		4
+#define SCLK_TIMER13_PMU		5
+#define SCLK_UART4_PMU			6
+#define SCLK_PVTM_PMU			7
+#define SCLK_WIFI_PMU			8
+#define SCLK_I2C0_PMU			9
+#define SCLK_I2C4_PMU			10
+#define SCLK_I2C8_PMU			11
+
+#define PCLK_SRC_PMU			19
+#define PCLK_PMU			20
+#define PCLK_PMUGRF_PMU			21
+#define PCLK_INTMEM1_PMU		22
+#define PCLK_GPIO0_PMU			23
+#define PCLK_GPIO1_PMU			24
+#define PCLK_SGRF_PMU			25
+#define PCLK_NOC_PMU			26
+#define PCLK_I2C0_PMU			27
+#define PCLK_I2C4_PMU			28
+#define PCLK_I2C8_PMU			29
+#define PCLK_RKPWM_PMU			30
+#define PCLK_SPI3_PMU			31
+#define PCLK_TIMER_PMU			32
+#define PCLK_MAILBOX_PMU		33
+#define PCLK_UART4_PMU			34
+#define PCLK_WDT_M0_PMU			35
+
+#define FCLK_CM0S_SRC_PMU		44
+#define FCLK_CM0S_PMU			45
+#define SCLK_CM0S_PMU			46
+#define HCLK_CM0S_PMU			47
+#define DCLK_CM0S_PMU			48
+#define PCLK_INTR_ARB_PMU		49
+#define HCLK_NOC_PMU			50
+
+#define CLKPMU_NR_CLKS			(HCLK_NOC_PMU + 1)
+
+/* soft-reset indices */
+
+/* cru_softrst_con0 */
+#define SRST_CORE_L0			0
+#define SRST_CORE_B0			1
+#define SRST_CORE_PO_L0			2
+#define SRST_CORE_PO_B0			3
+#define SRST_L2_L			4
+#define SRST_L2_B			5
+#define SRST_ADB_L			6
+#define SRST_ADB_B			7
+#define SRST_A_CCI			8
+#define SRST_A_CCIM0_NOC		9
+#define SRST_A_CCIM1_NOC		10
+#define SRST_DBG_NOC			11
+
+/* cru_softrst_con1 */
+#define SRST_CORE_L0_T			16
+#define SRST_CORE_L1			17
+#define SRST_CORE_L2			18
+#define SRST_CORE_L3			19
+#define SRST_CORE_PO_L0_T		20
+#define SRST_CORE_PO_L1			21
+#define SRST_CORE_PO_L2			22
+#define SRST_CORE_PO_L3			23
+#define SRST_A_ADB400_GIC2COREL		24
+#define SRST_A_ADB400_COREL2GIC		25
+#define SRST_P_DBG_L			26
+#define SRST_L2_L_T			28
+#define SRST_ADB_L_T			29
+#define SRST_A_RKPERF_L			30
+#define SRST_PVTM_CORE_L		31
+
+/* cru_softrst_con2 */
+#define SRST_CORE_B0_T			32
+#define SRST_CORE_B1			33
+#define SRST_CORE_PO_B0_T		36
+#define SRST_CORE_PO_B1			37
+#define SRST_A_ADB400_GIC2COREB		40
+#define SRST_A_ADB400_COREB2GIC		41
+#define SRST_P_DBG_B			42
+#define SRST_L2_B_T			43
+#define SRST_ADB_B_T			45
+#define SRST_A_RKPERF_B			46
+#define SRST_PVTM_CORE_B		47
+
+/* cru_softrst_con3 */
+#define SRST_A_CCI_T			50
+#define SRST_A_CCIM0_NOC_T		51
+#define SRST_A_CCIM1_NOC_T		52
+#define SRST_A_ADB400M_PD_CORE_B_T	53
+#define SRST_A_ADB400M_PD_CORE_L_T	54
+#define SRST_DBG_NOC_T			55
+#define SRST_DBG_CXCS			56
+#define SRST_CCI_TRACE			57
+#define SRST_P_CCI_GRF			58
+
+/* cru_softrst_con4 */
+#define SRST_A_CENTER_MAIN_NOC		64
+#define SRST_A_CENTER_PERI_NOC		65
+#define SRST_P_CENTER_MAIN		66
+#define SRST_P_DDRMON			67
+#define SRST_P_CIC			68
+#define SRST_P_CENTER_SGRF		69
+#define SRST_DDR0_MSCH			70
+#define SRST_DDRCFG0_MSCH		71
+#define SRST_DDR0			72
+#define SRST_DDRPHY0			73
+#define SRST_DDR1_MSCH			74
+#define SRST_DDRCFG1_MSCH		75
+#define SRST_DDR1			76
+#define SRST_DDRPHY1			77
+#define SRST_DDR_CIC			78
+#define SRST_PVTM_DDR			79
+
+/* cru_softrst_con5 */
+#define SRST_A_VCODEC_NOC		80
+#define SRST_A_VCODEC			81
+#define SRST_H_VCODEC_NOC		82
+#define SRST_H_VCODEC			83
+#define SRST_A_VDU_NOC			88
+#define SRST_A_VDU			89
+#define SRST_H_VDU_NOC			90
+#define SRST_H_VDU			91
+#define SRST_VDU_CORE			92
+#define SRST_VDU_CA			93
+
+/* cru_softrst_con6 */
+#define SRST_A_IEP_NOC			96
+#define SRST_A_VOP_IEP			97
+#define SRST_A_IEP			98
+#define SRST_H_IEP_NOC			99
+#define SRST_H_IEP			100
+#define SRST_A_RGA_NOC			102
+#define SRST_A_RGA			103
+#define SRST_H_RGA_NOC			104
+#define SRST_H_RGA			105
+#define SRST_RGA_CORE			106
+#define SRST_EMMC_NOC			108
+#define SRST_EMMC			109
+#define SRST_EMMC_GRF			110
+
+/* cru_softrst_con7 */
+#define SRST_A_PERIHP_NOC		112
+#define SRST_P_PERIHP_GRF		113
+#define SRST_H_PERIHP_NOC		114
+#define SRST_USBHOST0			115
+#define SRST_HOSTC0_AUX			116
+#define SRST_HOST0_ARB			117
+#define SRST_USBHOST1			118
+#define SRST_HOSTC1_AUX			119
+#define SRST_HOST1_ARB			120
+#define SRST_SDIO0			121
+#define SRST_SDMMC			122
+#define SRST_HSIC			123
+#define SRST_HSIC_AUX			124
+#define SRST_AHB1TOM			125
+#define SRST_P_PERIHP_NOC		126
+#define SRST_HSICPHY			127
+
+/* cru_softrst_con8 */
+#define SRST_A_PCIE			128
+#define SRST_P_PCIE			129
+#define SRST_PCIE_CORE			130
+#define SRST_PCIE_MGMT			131
+#define SRST_PCIE_MGMT_STICKY		132
+#define SRST_PCIE_PIPE			133
+#define SRST_PCIE_PM			134
+#define SRST_PCIEPHY			135
+#define SRST_A_GMAC_NOC			136
+#define SRST_A_GMAC			137
+#define SRST_P_GMAC_NOC			138
+#define SRST_P_GMAC_GRF			140
+#define SRST_HSICPHY_POR		142
+#define SRST_HSICPHY_UTMI		143
+
+/* cru_softrst_con9 */
+#define SRST_USB2PHY0_POR		144
+#define SRST_USB2PHY0_UTMI_PORT0	145
+#define SRST_USB2PHY0_UTMI_PORT1	146
+#define SRST_USB2PHY0_EHCIPHY		147
+#define SRST_UPHY0_PIPE_L00		148
+#define SRST_UPHY0			149
+#define SRST_UPHY0_TCPDPWRUP		150
+#define SRST_USB2PHY1_POR		152
+#define SRST_USB2PHY1_UTMI_PORT0	153
+#define SRST_USB2PHY1_UTMI_PORT1	154
+#define SRST_USB2PHY1_EHCIPHY		155
+#define SRST_UPHY1_PIPE_L00		156
+#define SRST_UPHY1			157
+#define SRST_UPHY1_TCPDPWRUP		158
+
+/* cru_softrst_con10 */
+#define SRST_A_PERILP0_NOC		160
+#define SRST_A_DCF			161
+#define SRST_GIC500			162
+#define SRST_DMAC0_PERILP0		163
+#define SRST_DMAC1_PERILP0		164
+#define SRST_TZMA			165
+#define SRST_INTMEM			166
+#define SRST_ADB400_MST0		167
+#define SRST_ADB400_MST1		168
+#define SRST_ADB400_SLV0		169
+#define SRST_ADB400_SLV1		170
+#define SRST_H_PERILP0			171
+#define SRST_H_PERILP0_NOC		172
+#define SRST_ROM			173
+#define SRST_CRYPTO_S			174
+#define SRST_CRYPTO_M			175
+
+/* cru_softrst_con11 */
+#define SRST_P_DCF			176
+#define SRST_CM0S_NOC			177
+#define SRST_CM0S			178
+#define SRST_CM0S_DBG			179
+#define SRST_CM0S_PO			180
+#define SRST_CRYPTO			181
+#define SRST_P_PERILP1_SGRF		182
+#define SRST_P_PERILP1_GRF		183
+#define SRST_CRYPTO1_S			184
+#define SRST_CRYPTO1_M			185
+#define SRST_CRYPTO1			186
+#define SRST_GIC_NOC			188
+#define SRST_SD_NOC			189
+#define SRST_SDIOAUDIO_BRG		190
+
+/* cru_softrst_con12 */
+#define SRST_H_PERILP1			192
+#define SRST_H_PERILP1_NOC		193
+#define SRST_H_I2S0_8CH			194
+#define SRST_H_I2S1_8CH			195
+#define SRST_H_I2S2_8CH			196
+#define SRST_H_SPDIF_8CH		197
+#define SRST_P_PERILP1_NOC		198
+#define SRST_P_EFUSE_1024		199
+#define SRST_P_EFUSE_1024S		200
+#define SRST_P_I2C0			201
+#define SRST_P_I2C1			202
+#define SRST_P_I2C2			203
+#define SRST_P_I2C3			204
+#define SRST_P_I2C4			205
+#define SRST_P_I2C5			206
+#define SRST_P_MAILBOX0			207
+
+/* cru_softrst_con13 */
+#define SRST_P_UART0			208
+#define SRST_P_UART1			209
+#define SRST_P_UART2			210
+#define SRST_P_UART3			211
+#define SRST_P_SARADC			212
+#define SRST_P_TSADC			213
+#define SRST_P_SPI0			214
+#define SRST_P_SPI1			215
+#define SRST_P_SPI2			216
+#define SRST_P_SPI3			217
+#define SRST_P_SPI4			218
+#define SRST_SPI0			219
+#define SRST_SPI1			220
+#define SRST_SPI2			221
+#define SRST_SPI3			222
+#define SRST_SPI4			223
+
+/* cru_softrst_con14 */
+#define SRST_I2S0_8CH			224
+#define SRST_I2S1_8CH			225
+#define SRST_I2S2_8CH			226
+#define SRST_SPDIF_8CH			227
+#define SRST_UART0			228
+#define SRST_UART1			229
+#define SRST_UART2			230
+#define SRST_UART3			231
+#define SRST_TSADC			232
+#define SRST_I2C0			233
+#define SRST_I2C1			234
+#define SRST_I2C2			235
+#define SRST_I2C3			236
+#define SRST_I2C4			237
+#define SRST_I2C5			238
+#define SRST_SDIOAUDIO_NOC		239
+
+/* cru_softrst_con15 */
+#define SRST_A_VIO_NOC			240
+#define SRST_A_HDCP_NOC			241
+#define SRST_A_HDCP			242
+#define SRST_H_HDCP_NOC			243
+#define SRST_H_HDCP			244
+#define SRST_P_HDCP_NOC			245
+#define SRST_P_HDCP			246
+#define SRST_P_HDMI_CTRL		247
+#define SRST_P_DP_CTRL			248
+#define SRST_S_DP_CTRL			249
+#define SRST_C_DP_CTRL			250
+#define SRST_P_MIPI_DSI0		251
+#define SRST_P_MIPI_DSI1		252
+#define SRST_DP_CORE			253
+#define SRST_DP_I2S			254
+
+/* cru_softrst_con16 */
+#define SRST_GASKET			256
+#define SRST_VIO_GRF			258
+#define SRST_DPTX_SPDIF_REC		259
+#define SRST_HDMI_CTRL			260
+#define SRST_HDCP_CTRL			261
+#define SRST_A_ISP0_NOC			262
+#define SRST_A_ISP1_NOC			263
+#define SRST_H_ISP0_NOC			266
+#define SRST_H_ISP1_NOC			267
+#define SRST_H_ISP0			268
+#define SRST_H_ISP1			269
+#define SRST_ISP0			270
+#define SRST_ISP1			271
+
+/* cru_softrst_con17 */
+#define SRST_A_VOP0_NOC			272
+#define SRST_A_VOP1_NOC			273
+#define SRST_A_VOP0			274
+#define SRST_A_VOP1			275
+#define SRST_H_VOP0_NOC			276
+#define SRST_H_VOP1_NOC			277
+#define SRST_H_VOP0			278
+#define SRST_H_VOP1			279
+#define SRST_D_VOP0			280
+#define SRST_D_VOP1			281
+#define SRST_VOP0_PWM			282
+#define SRST_VOP1_PWM			283
+#define SRST_P_EDP_NOC			284
+#define SRST_P_EDP_CTRL			285
+
+/* cru_softrst_con18 */
+#define SRST_A_GPU			288
+#define SRST_A_GPU_NOC			289
+#define SRST_A_GPU_GRF			290
+#define SRST_PVTM_GPU			291
+#define SRST_A_USB3_NOC			292
+#define SRST_A_USB3_OTG0		293
+#define SRST_A_USB3_OTG1		294
+#define SRST_A_USB3_GRF			295
+#define SRST_PMU			296
+
+/* cru_softrst_con19 */
+#define SRST_P_TIMER0_5			304
+#define SRST_TIMER0			305
+#define SRST_TIMER1			306
+#define SRST_TIMER2			307
+#define SRST_TIMER3			308
+#define SRST_TIMER4			309
+#define SRST_TIMER5			310
+#define SRST_P_TIMER6_11		311
+#define SRST_TIMER6			312
+#define SRST_TIMER7			313
+#define SRST_TIMER8			314
+#define SRST_TIMER9			315
+#define SRST_TIMER10			316
+#define SRST_TIMER11			317
+#define SRST_P_INTR_ARB_PMU		318
+#define SRST_P_ALIVE_SGRF		319
+
+/* cru_softrst_con20 */
+#define SRST_P_GPIO2			320
+#define SRST_P_GPIO3			321
+#define SRST_P_GPIO4			322
+#define SRST_P_GRF			323
+#define SRST_P_ALIVE_NOC		324
+#define SRST_P_WDT0			325
+#define SRST_P_WDT1			326
+#define SRST_P_INTR_ARB			327
+#define SRST_P_UPHY0_DPTX		328
+#define SRST_P_UPHY0_APB		330
+#define SRST_P_UPHY0_TCPHY		332
+#define SRST_P_UPHY1_TCPHY		333
+#define SRST_P_UPHY0_TCPDCTRL		334
+#define SRST_P_UPHY1_TCPDCTRL		335
+
+/* pmu soft-reset indices */
+
+/* pmu_cru_softrst_con0 */
+#define SRST_P_NOC			0
+#define SRST_P_INTMEM			1
+#define SRST_H_CM0S			2
+#define SRST_H_CM0S_NOC			3
+#define SRST_DBG_CM0S			4
+#define SRST_PO_CM0S			5
+#define SRST_P_SPI6			6
+#define SRST_SPI6			7
+#define SRST_P_TIMER_0_1		8
+#define SRST_P_TIMER_0			9
+#define SRST_P_TIMER_1			10
+#define SRST_P_UART4			11
+#define SRST_UART4			12
+#define SRST_P_WDT			13
+
+/* pmu_cru_softrst_con1 */
+#define SRST_P_I2C6			16
+#define SRST_P_I2C7			17
+#define SRST_P_I2C8			18
+#define SRST_P_MAILBOX			19
+#define SRST_P_RKPWM			20
+#define SRST_P_PMUGRF			21
+#define SRST_P_SGRF			22
+#define SRST_P_GPIO0			23
+#define SRST_P_GPIO1			24
+#define SRST_P_CRU			25
+#define SRST_P_INTR			26
+#define SRST_PVTM			27
+#define SRST_I2C6			28
+#define SRST_I2C7			29
+#define SRST_I2C8			30
+
+#endif
diff --git a/include/dt-bindings/clock/tegra186-clock.h b/include/dt-bindings/clock/tegra186-clock.h
new file mode 100644
index 0000000..f73d320
--- /dev/null
+++ b/include/dt-bindings/clock/tegra186-clock.h
@@ -0,0 +1,940 @@
+/** @file */
+
+#ifndef _MACH_T186_CLK_T186_H
+#define _MACH_T186_CLK_T186_H
+
+/**
+ * @defgroup clock_ids Clock Identifiers
+ * @{
+ *   @defgroup extern_input external input clocks
+ *   @{
+ *     @def TEGRA186_CLK_OSC
+ *     @def TEGRA186_CLK_CLK_32K
+ *     @def TEGRA186_CLK_DTV_INPUT
+ *     @def TEGRA186_CLK_SOR0_PAD_CLKOUT
+ *     @def TEGRA186_CLK_SOR1_PAD_CLKOUT
+ *     @def TEGRA186_CLK_I2S1_SYNC_INPUT
+ *     @def TEGRA186_CLK_I2S2_SYNC_INPUT
+ *     @def TEGRA186_CLK_I2S3_SYNC_INPUT
+ *     @def TEGRA186_CLK_I2S4_SYNC_INPUT
+ *     @def TEGRA186_CLK_I2S5_SYNC_INPUT
+ *     @def TEGRA186_CLK_I2S6_SYNC_INPUT
+ *     @def TEGRA186_CLK_SPDIFIN_SYNC_INPUT
+ *   @}
+ *
+ *   @defgroup extern_output external output clocks
+ *   @{
+ *     @def TEGRA186_CLK_EXTPERIPH1
+ *     @def TEGRA186_CLK_EXTPERIPH2
+ *     @def TEGRA186_CLK_EXTPERIPH3
+ *     @def TEGRA186_CLK_EXTPERIPH4
+ *   @}
+ *
+ *   @defgroup display_clks display related clocks
+ *   @{
+ *     @def TEGRA186_CLK_CEC
+ *     @def TEGRA186_CLK_DSIC
+ *     @def TEGRA186_CLK_DSIC_LP
+ *     @def TEGRA186_CLK_DSID
+ *     @def TEGRA186_CLK_DSID_LP
+ *     @def TEGRA186_CLK_DPAUX1
+ *     @def TEGRA186_CLK_DPAUX
+ *     @def TEGRA186_CLK_HDA2HDMICODEC
+ *     @def TEGRA186_CLK_NVDISPLAY_DISP
+ *     @def TEGRA186_CLK_NVDISPLAY_DSC
+ *     @def TEGRA186_CLK_NVDISPLAY_P0
+ *     @def TEGRA186_CLK_NVDISPLAY_P1
+ *     @def TEGRA186_CLK_NVDISPLAY_P2
+ *     @def TEGRA186_CLK_NVDISPLAYHUB
+ *     @def TEGRA186_CLK_SOR_SAFE
+ *     @def TEGRA186_CLK_SOR0
+ *     @def TEGRA186_CLK_SOR0_OUT
+ *     @def TEGRA186_CLK_SOR1
+ *     @def TEGRA186_CLK_SOR1_OUT
+ *     @def TEGRA186_CLK_DSI
+ *     @def TEGRA186_CLK_MIPI_CAL
+ *     @def TEGRA186_CLK_DSIA_LP
+ *     @def TEGRA186_CLK_DSIB
+ *     @def TEGRA186_CLK_DSIB_LP
+ *   @}
+ *
+ *   @defgroup camera_clks camera related clocks
+ *   @{
+ *     @def TEGRA186_CLK_NVCSI
+ *     @def TEGRA186_CLK_NVCSILP
+ *     @def TEGRA186_CLK_VI
+ *   @}
+ *
+ *   @defgroup audio_clks audio related clocks
+ *   @{
+ *     @def TEGRA186_CLK_ACLK
+ *     @def TEGRA186_CLK_ADSP
+ *     @def TEGRA186_CLK_ADSPNEON
+ *     @def TEGRA186_CLK_AHUB
+ *     @def TEGRA186_CLK_APE
+ *     @def TEGRA186_CLK_APB2APE
+ *     @def TEGRA186_CLK_AUD_MCLK
+ *     @def TEGRA186_CLK_DMIC1
+ *     @def TEGRA186_CLK_DMIC2
+ *     @def TEGRA186_CLK_DMIC3
+ *     @def TEGRA186_CLK_DMIC4
+ *     @def TEGRA186_CLK_DSPK1
+ *     @def TEGRA186_CLK_DSPK2
+ *     @def TEGRA186_CLK_HDA
+ *     @def TEGRA186_CLK_HDA2CODEC_2X
+ *     @def TEGRA186_CLK_I2S1
+ *     @def TEGRA186_CLK_I2S2
+ *     @def TEGRA186_CLK_I2S3
+ *     @def TEGRA186_CLK_I2S4
+ *     @def TEGRA186_CLK_I2S5
+ *     @def TEGRA186_CLK_I2S6
+ *     @def TEGRA186_CLK_MAUD
+ *     @def TEGRA186_CLK_PLL_A_OUT0
+ *     @def TEGRA186_CLK_SPDIF_DOUBLER
+ *     @def TEGRA186_CLK_SPDIF_IN
+ *     @def TEGRA186_CLK_SPDIF_OUT
+ *     @def TEGRA186_CLK_SYNC_DMIC1
+ *     @def TEGRA186_CLK_SYNC_DMIC2
+ *     @def TEGRA186_CLK_SYNC_DMIC3
+ *     @def TEGRA186_CLK_SYNC_DMIC4
+ *     @def TEGRA186_CLK_SYNC_DMIC5
+ *     @def TEGRA186_CLK_SYNC_DSPK1
+ *     @def TEGRA186_CLK_SYNC_DSPK2
+ *     @def TEGRA186_CLK_SYNC_I2S1
+ *     @def TEGRA186_CLK_SYNC_I2S2
+ *     @def TEGRA186_CLK_SYNC_I2S3
+ *     @def TEGRA186_CLK_SYNC_I2S4
+ *     @def TEGRA186_CLK_SYNC_I2S5
+ *     @def TEGRA186_CLK_SYNC_I2S6
+ *     @def TEGRA186_CLK_SYNC_SPDIF
+ *   @}
+ *
+ *   @defgroup uart_clks UART clocks
+ *   @{
+ *     @def TEGRA186_CLK_AON_UART_FST_MIPI_CAL
+ *     @def TEGRA186_CLK_UARTA
+ *     @def TEGRA186_CLK_UARTB
+ *     @def TEGRA186_CLK_UARTC
+ *     @def TEGRA186_CLK_UARTD
+ *     @def TEGRA186_CLK_UARTE
+ *     @def TEGRA186_CLK_UARTF
+ *     @def TEGRA186_CLK_UARTG
+ *     @def TEGRA186_CLK_UART_FST_MIPI_CAL
+ *   @}
+ *
+ *   @defgroup i2c_clks I2C clocks
+ *   @{
+ *     @def TEGRA186_CLK_AON_I2C_SLOW
+ *     @def TEGRA186_CLK_I2C1
+ *     @def TEGRA186_CLK_I2C2
+ *     @def TEGRA186_CLK_I2C3
+ *     @def TEGRA186_CLK_I2C4
+ *     @def TEGRA186_CLK_I2C5
+ *     @def TEGRA186_CLK_I2C6
+ *     @def TEGRA186_CLK_I2C8
+ *     @def TEGRA186_CLK_I2C9
+ *     @def TEGRA186_CLK_I2C1
+ *     @def TEGRA186_CLK_I2C12
+ *     @def TEGRA186_CLK_I2C13
+ *     @def TEGRA186_CLK_I2C14
+ *     @def TEGRA186_CLK_I2C_SLOW
+ *     @def TEGRA186_CLK_VI_I2C
+ *   @}
+ *
+ *   @defgroup spi_clks SPI clocks
+ *   @{
+ *     @def TEGRA186_CLK_SPI1
+ *     @def TEGRA186_CLK_SPI2
+ *     @def TEGRA186_CLK_SPI3
+ *     @def TEGRA186_CLK_SPI4
+ *   @}
+ *
+ *   @defgroup storage storage related clocks
+ *   @{
+ *     @def TEGRA186_CLK_SATA
+ *     @def TEGRA186_CLK_SATA_OOB
+ *     @def TEGRA186_CLK_SATA_IOBIST
+ *     @def TEGRA186_CLK_SDMMC_LEGACY_TM
+ *     @def TEGRA186_CLK_SDMMC1
+ *     @def TEGRA186_CLK_SDMMC2
+ *     @def TEGRA186_CLK_SDMMC3
+ *     @def TEGRA186_CLK_SDMMC4
+ *     @def TEGRA186_CLK_QSPI
+ *     @def TEGRA186_CLK_QSPI_OUT
+ *     @def TEGRA186_CLK_UFSDEV_REF
+ *     @def TEGRA186_CLK_UFSHC
+ *   @}
+ *
+ *   @defgroup pwm_clks PWM clocks
+ *   @{
+ *     @def TEGRA186_CLK_PWM1
+ *     @def TEGRA186_CLK_PWM2
+ *     @def TEGRA186_CLK_PWM3
+ *     @def TEGRA186_CLK_PWM4
+ *     @def TEGRA186_CLK_PWM5
+ *     @def TEGRA186_CLK_PWM6
+ *     @def TEGRA186_CLK_PWM7
+ *     @def TEGRA186_CLK_PWM8
+ *   @}
+ *
+ *   @defgroup plls PLLs and related clocks
+ *   @{
+ *     @def TEGRA186_CLK_PLLREFE_OUT_GATED
+ *     @def TEGRA186_CLK_PLLREFE_OUT1
+ *     @def TEGRA186_CLK_PLLD_OUT1
+ *     @def TEGRA186_CLK_PLLP_OUT0
+ *     @def TEGRA186_CLK_PLLP_OUT5
+ *     @def TEGRA186_CLK_PLLA
+ *     @def TEGRA186_CLK_PLLE_PWRSEQ
+ *     @def TEGRA186_CLK_PLLA_OUT1
+ *     @def TEGRA186_CLK_PLLREFE_REF
+ *     @def TEGRA186_CLK_UPHY_PLL0_PWRSEQ
+ *     @def TEGRA186_CLK_UPHY_PLL1_PWRSEQ
+ *     @def TEGRA186_CLK_PLLREFE_PLLE_PASSTHROUGH
+ *     @def TEGRA186_CLK_PLLREFE_PEX
+ *     @def TEGRA186_CLK_PLLREFE_IDDQ
+ *     @def TEGRA186_CLK_PLLC_OUT_AON
+ *     @def TEGRA186_CLK_PLLC_OUT_ISP
+ *     @def TEGRA186_CLK_PLLC_OUT_VE
+ *     @def TEGRA186_CLK_PLLC4_OUT
+ *     @def TEGRA186_CLK_PLLREFE_OUT
+ *     @def TEGRA186_CLK_PLLREFE_PLL_REF
+ *     @def TEGRA186_CLK_PLLE
+ *     @def TEGRA186_CLK_PLLC
+ *     @def TEGRA186_CLK_PLLP
+ *     @def TEGRA186_CLK_PLLD
+ *     @def TEGRA186_CLK_PLLD2
+ *     @def TEGRA186_CLK_PLLREFE_VCO
+ *     @def TEGRA186_CLK_PLLC2
+ *     @def TEGRA186_CLK_PLLC3
+ *     @def TEGRA186_CLK_PLLDP
+ *     @def TEGRA186_CLK_PLLC4_VCO
+ *     @def TEGRA186_CLK_PLLA1
+ *     @def TEGRA186_CLK_PLLNVCSI
+ *     @def TEGRA186_CLK_PLLDISPHUB
+ *     @def TEGRA186_CLK_PLLD3
+ *     @def TEGRA186_CLK_PLLBPMPCAM
+ *     @def TEGRA186_CLK_PLLAON
+ *     @def TEGRA186_CLK_PLLU
+ *     @def TEGRA186_CLK_PLLC4_VCO_DIV2
+ *     @def TEGRA186_CLK_PLL_REF
+ *     @def TEGRA186_CLK_PLLREFE_OUT1_DIV5
+ *     @def TEGRA186_CLK_UTMIP_PLL_PWRSEQ
+ *     @def TEGRA186_CLK_PLL_U_48M
+ *     @def TEGRA186_CLK_PLL_U_480M
+ *     @def TEGRA186_CLK_PLLC4_OUT0
+ *     @def TEGRA186_CLK_PLLC4_OUT1
+ *     @def TEGRA186_CLK_PLLC4_OUT2
+ *     @def TEGRA186_CLK_PLLC4_OUT_MUX
+ *     @def TEGRA186_CLK_DFLLDISP_DIV
+ *     @def TEGRA186_CLK_PLLDISPHUB_DIV
+ *     @def TEGRA186_CLK_PLLP_DIV8
+ *   @}
+ *
+ *   @defgroup nafll_clks NAFLL clock sources
+ *   @{
+ *     @def TEGRA186_CLK_NAFLL_AXI_CBB
+ *     @def TEGRA186_CLK_NAFLL_BCPU
+ *     @def TEGRA186_CLK_NAFLL_BPMP
+ *     @def TEGRA186_CLK_NAFLL_DISP
+ *     @def TEGRA186_CLK_NAFLL_GPU
+ *     @def TEGRA186_CLK_NAFLL_ISP
+ *     @def TEGRA186_CLK_NAFLL_MCPU
+ *     @def TEGRA186_CLK_NAFLL_NVDEC
+ *     @def TEGRA186_CLK_NAFLL_NVENC
+ *     @def TEGRA186_CLK_NAFLL_NVJPG
+ *     @def TEGRA186_CLK_NAFLL_SCE
+ *     @def TEGRA186_CLK_NAFLL_SE
+ *     @def TEGRA186_CLK_NAFLL_TSEC
+ *     @def TEGRA186_CLK_NAFLL_TSECB
+ *     @def TEGRA186_CLK_NAFLL_VI
+ *     @def TEGRA186_CLK_NAFLL_VIC
+ *   @}
+ *
+ *   @defgroup mphy MPHY related clocks
+ *   @{
+ *     @def TEGRA186_CLK_MPHY_L0_RX_SYMB
+ *     @def TEGRA186_CLK_MPHY_L0_RX_LS_BIT
+ *     @def TEGRA186_CLK_MPHY_L0_TX_SYMB
+ *     @def TEGRA186_CLK_MPHY_L0_TX_LS_3XBIT
+ *     @def TEGRA186_CLK_MPHY_L0_RX_ANA
+ *     @def TEGRA186_CLK_MPHY_L1_RX_ANA
+ *     @def TEGRA186_CLK_MPHY_IOBIST
+ *     @def TEGRA186_CLK_MPHY_TX_1MHZ_REF
+ *     @def TEGRA186_CLK_MPHY_CORE_PLL_FIXED
+ *   @}
+ *
+ *   @defgroup eavb EAVB related clocks
+ *   @{
+ *     @def TEGRA186_CLK_EQOS_AXI
+ *     @def TEGRA186_CLK_EQOS_PTP_REF
+ *     @def TEGRA186_CLK_EQOS_RX
+ *     @def TEGRA186_CLK_EQOS_RX_INPUT
+ *     @def TEGRA186_CLK_EQOS_TX
+ *   @}
+ *
+ *   @defgroup usb USB related clocks
+ *   @{
+ *     @def TEGRA186_CLK_PEX_USB_PAD0_MGMT
+ *     @def TEGRA186_CLK_PEX_USB_PAD1_MGMT
+ *     @def TEGRA186_CLK_HSIC_TRK
+ *     @def TEGRA186_CLK_USB2_TRK
+ *     @def TEGRA186_CLK_USB2_HSIC_TRK
+ *     @def TEGRA186_CLK_XUSB_CORE_SS
+ *     @def TEGRA186_CLK_XUSB_CORE_DEV
+ *     @def TEGRA186_CLK_XUSB_FALCON
+ *     @def TEGRA186_CLK_XUSB_FS
+ *     @def TEGRA186_CLK_XUSB
+ *     @def TEGRA186_CLK_XUSB_DEV
+ *     @def TEGRA186_CLK_XUSB_HOST
+ *     @def TEGRA186_CLK_XUSB_SS
+ *   @}
+ *
+ *   @defgroup bigblock compute block related clocks
+ *   @{
+ *     @def TEGRA186_CLK_GPCCLK
+ *     @def TEGRA186_CLK_GPC2CLK
+ *     @def TEGRA186_CLK_GPU
+ *     @def TEGRA186_CLK_HOST1X
+ *     @def TEGRA186_CLK_ISP
+ *     @def TEGRA186_CLK_NVDEC
+ *     @def TEGRA186_CLK_NVENC
+ *     @def TEGRA186_CLK_NVJPG
+ *     @def TEGRA186_CLK_SE
+ *     @def TEGRA186_CLK_TSEC
+ *     @def TEGRA186_CLK_TSECB
+ *     @def TEGRA186_CLK_VIC
+ *   @}
+ *
+ *   @defgroup can CAN bus related clocks
+ *   @{
+ *     @def TEGRA186_CLK_CAN1
+ *     @def TEGRA186_CLK_CAN1_HOST
+ *     @def TEGRA186_CLK_CAN2
+ *     @def TEGRA186_CLK_CAN2_HOST
+ *   @}
+ *
+ *   @defgroup system basic system clocks
+ *   @{
+ *     @def TEGRA186_CLK_ACTMON
+ *     @def TEGRA186_CLK_AON_APB
+ *     @def TEGRA186_CLK_AON_CPU_NIC
+ *     @def TEGRA186_CLK_AON_NIC
+ *     @def TEGRA186_CLK_AXI_CBB
+ *     @def TEGRA186_CLK_BPMP_APB
+ *     @def TEGRA186_CLK_BPMP_CPU_NIC
+ *     @def TEGRA186_CLK_BPMP_NIC_RATE
+ *     @def TEGRA186_CLK_CLK_M
+ *     @def TEGRA186_CLK_EMC
+ *     @def TEGRA186_CLK_MSS_ENCRYPT
+ *     @def TEGRA186_CLK_SCE_APB
+ *     @def TEGRA186_CLK_SCE_CPU_NIC
+ *     @def TEGRA186_CLK_SCE_NIC
+ *     @def TEGRA186_CLK_TSC
+ *   @}
+ *
+ *   @defgroup pcie_clks PCIe related clocks
+ *   @{
+ *     @def TEGRA186_CLK_AFI
+ *     @def TEGRA186_CLK_PCIE
+ *     @def TEGRA186_CLK_PCIE2_IOBIST
+ *     @def TEGRA186_CLK_PCIERX0
+ *     @def TEGRA186_CLK_PCIERX1
+ *     @def TEGRA186_CLK_PCIERX2
+ *     @def TEGRA186_CLK_PCIERX3
+ *     @def TEGRA186_CLK_PCIERX4
+ *   @}
+ */
+
+/** @brief output of gate CLK_ENB_FUSE */
+#define TEGRA186_CLK_FUSE 0
+/**
+ * @brief It's not what you think
+ * @details output of gate CLK_ENB_GPU. This output connects to the GPU
+ * pwrclk. @warning: This is almost certainly not the clock you think
+ * it is. If you're looking for the clock of the graphics engine, see
+ * TEGRA186_GPCCLK
+ */
+#define TEGRA186_CLK_GPU 1
+/** @brief output of gate CLK_ENB_PCIE */
+#define TEGRA186_CLK_PCIE 3
+/** @brief output of the divider IPFS_CLK_DIVISOR */
+#define TEGRA186_CLK_AFI 4
+/** @brief output of gate CLK_ENB_PCIE2_IOBIST */
+#define TEGRA186_CLK_PCIE2_IOBIST 5
+/** @brief output of gate CLK_ENB_PCIERX0*/
+#define TEGRA186_CLK_PCIERX0 6
+/** @brief output of gate CLK_ENB_PCIERX1*/
+#define TEGRA186_CLK_PCIERX1 7
+/** @brief output of gate CLK_ENB_PCIERX2*/
+#define TEGRA186_CLK_PCIERX2 8
+/** @brief output of gate CLK_ENB_PCIERX3*/
+#define TEGRA186_CLK_PCIERX3 9
+/** @brief output of gate CLK_ENB_PCIERX4*/
+#define TEGRA186_CLK_PCIERX4 10
+/** @brief output branch of PLL_C for ISP, controlled by gate CLK_ENB_PLLC_OUT_ISP */
+#define TEGRA186_CLK_PLLC_OUT_ISP 11
+/** @brief output branch of PLL_C for VI, controlled by gate CLK_ENB_PLLC_OUT_VE */
+#define TEGRA186_CLK_PLLC_OUT_VE 12
+/** @brief output branch of PLL_C for AON domain, controlled by gate CLK_ENB_PLLC_OUT_AON */
+#define TEGRA186_CLK_PLLC_OUT_AON 13
+/** @brief output of gate CLK_ENB_SOR_SAFE */
+#define TEGRA186_CLK_SOR_SAFE 39
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2S2 */
+#define TEGRA186_CLK_I2S2 42
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2S3 */
+#define TEGRA186_CLK_I2S3 43
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SPDF_IN */
+#define TEGRA186_CLK_SPDIF_IN 44
+/** @brief output of gate CLK_ENB_SPDIF_DOUBLER */
+#define TEGRA186_CLK_SPDIF_DOUBLER 45
+/**  @clkdesc{spi_clks, out, mux, CLK_RST_CONTROLLER_CLK_SOURCE_SPI3} */
+#define TEGRA186_CLK_SPI3 46
+/** @clkdesc{i2c_clks, out, mux, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1} */
+#define TEGRA186_CLK_I2C1 47
+/** @clkdesc{i2c_clks, out, mux, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5} */
+#define TEGRA186_CLK_I2C5 48
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SPI1 */
+#define TEGRA186_CLK_SPI1 49
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_ISP */
+#define TEGRA186_CLK_ISP 50
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_VI */
+#define TEGRA186_CLK_VI 51
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1 */
+#define TEGRA186_CLK_SDMMC1 52
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2 */
+#define TEGRA186_CLK_SDMMC2 53
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4 */
+#define TEGRA186_CLK_SDMMC4 54
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTA */
+#define TEGRA186_CLK_UARTA 55
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTB */
+#define TEGRA186_CLK_UARTB 56
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X */
+#define TEGRA186_CLK_HOST1X 57
+/**
+ * @brief controls the EMC clock frequency.
+ * @details Doing a clk_set_rate on this clock will select the
+ * appropriate clock source, program the source rate and execute a
+ * specific sequence to switch to the new clock source for both memory
+ * controllers. This can be used to control the balance between memory
+ * throughput and memory controller power.
+ */
+#define TEGRA186_CLK_EMC 58
+/* @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH4 */
+#define TEGRA186_CLK_EXTPERIPH4 73
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SPI4 */
+#define TEGRA186_CLK_SPI4 74
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C3 */
+#define TEGRA186_CLK_I2C3 75
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3 */
+#define TEGRA186_CLK_SDMMC3 76
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTD */
+#define TEGRA186_CLK_UARTD 77
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2S1 */
+#define TEGRA186_CLK_I2S1 79
+/** output of gate CLK_ENB_DTV */
+#define TEGRA186_CLK_DTV 80
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_TSEC */
+#define TEGRA186_CLK_TSEC 81
+/** @brief output of gate CLK_ENB_DP2 */
+#define TEGRA186_CLK_DP2 82
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2S4 */
+#define TEGRA186_CLK_I2S4 84
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2S5 */
+#define TEGRA186_CLK_I2S5 85
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C4 */
+#define TEGRA186_CLK_I2C4 86
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AHUB */
+#define TEGRA186_CLK_AHUB 87
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_HDA2CODEC_2X */
+#define TEGRA186_CLK_HDA2CODEC_2X 88
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1 */
+#define TEGRA186_CLK_EXTPERIPH1 89
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH2 */
+#define TEGRA186_CLK_EXTPERIPH2 90
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH3 */
+#define TEGRA186_CLK_EXTPERIPH3 91
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C_SLOW */
+#define TEGRA186_CLK_I2C_SLOW 92
+/** @brief output of the SOR1_CLK_SRC mux in CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 */
+#define TEGRA186_CLK_SOR1 93
+/** @brief output of gate CLK_ENB_CEC */
+#define TEGRA186_CLK_CEC 94
+/** @brief output of gate CLK_ENB_DPAUX1 */
+#define TEGRA186_CLK_DPAUX1 95
+/** @brief output of gate CLK_ENB_DPAUX */
+#define TEGRA186_CLK_DPAUX 96
+/** @brief output of the SOR0_CLK_SRC mux in CLK_RST_CONTROLLER_CLK_SOURCE_SOR0 */
+#define TEGRA186_CLK_SOR0 97
+/** @brief output of gate CLK_ENB_HDA2HDMICODEC */
+#define TEGRA186_CLK_HDA2HDMICODEC 98
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SATA */
+#define TEGRA186_CLK_SATA 99
+/** @brief output of gate CLK_ENB_SATA_OOB */
+#define TEGRA186_CLK_SATA_OOB 100
+/** @brief output of gate CLK_ENB_SATA_IOBIST */
+#define TEGRA186_CLK_SATA_IOBIST 101
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_HDA */
+#define TEGRA186_CLK_HDA 102
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SE */
+#define TEGRA186_CLK_SE 103
+/** @brief output of gate CLK_ENB_APB2APE */
+#define TEGRA186_CLK_APB2APE 104
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_APE */
+#define TEGRA186_CLK_APE 105
+/** @brief output of gate CLK_ENB_IQC1 */
+#define TEGRA186_CLK_IQC1 106
+/** @brief output of gate CLK_ENB_IQC2 */
+#define TEGRA186_CLK_IQC2 107
+/** divide by 2 version of TEGRA186_CLK_PLLREFE_VCO */
+#define TEGRA186_CLK_PLLREFE_OUT 108
+/** @brief output of gate CLK_ENB_PLLREFE_PLL_REF */
+#define TEGRA186_CLK_PLLREFE_PLL_REF 109
+/** @brief output of gate CLK_ENB_PLLC4_OUT */
+#define TEGRA186_CLK_PLLC4_OUT 110
+/** @brief output of mux xusb_core_clk_switch on page 67 of T186_Clocks_IAS.doc */
+#define TEGRA186_CLK_XUSB 111
+/** controls xusb_dev_ce signal on page 66 and 67 of T186_Clocks_IAS.doc */
+#define TEGRA186_CLK_XUSB_DEV 112
+/** controls xusb_host_ce signal on page 67 of T186_Clocks_IAS.doc */
+#define TEGRA186_CLK_XUSB_HOST 113
+/** controls xusb_ss_ce signal on page 67 of T186_Clocks_IAS.doc */
+#define TEGRA186_CLK_XUSB_SS 114
+/** @brief output of gate CLK_ENB_DSI */
+#define TEGRA186_CLK_DSI 115
+/** @brief output of gate CLK_ENB_MIPI_CAL */
+#define TEGRA186_CLK_MIPI_CAL 116
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP */
+#define TEGRA186_CLK_DSIA_LP 117
+/** @brief output of gate CLK_ENB_DSIB */
+#define TEGRA186_CLK_DSIB 118
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSIB_LP */
+#define TEGRA186_CLK_DSIB_LP 119
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DMIC1 */
+#define TEGRA186_CLK_DMIC1 122
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DMIC2 */
+#define TEGRA186_CLK_DMIC2 123
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AUD_MCLK */
+#define TEGRA186_CLK_AUD_MCLK 124
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 */
+#define TEGRA186_CLK_I2C6 125
+/**output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL */
+#define TEGRA186_CLK_UART_FST_MIPI_CAL 126
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_VIC */
+#define TEGRA186_CLK_VIC 127
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM */
+#define TEGRA186_CLK_SDMMC_LEGACY_TM 128
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVDEC */
+#define TEGRA186_CLK_NVDEC 129
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVJPG */
+#define TEGRA186_CLK_NVJPG 130
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVENC */
+#define TEGRA186_CLK_NVENC 131
+/** @brief output of the QSPI_CLK_SRC mux in CLK_RST_CONTROLLER_CLK_SOURCE_QSPI */
+#define TEGRA186_CLK_QSPI 132
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_VI_I2C */
+#define TEGRA186_CLK_VI_I2C 133
+/** @brief output of gate CLK_ENB_HSIC_TRK */
+#define TEGRA186_CLK_HSIC_TRK 134
+/** @brief output of gate CLK_ENB_USB2_TRK */
+#define TEGRA186_CLK_USB2_TRK 135
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_MAUD */
+#define TEGRA186_CLK_MAUD 136
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_TSECB */
+#define TEGRA186_CLK_TSECB 137
+/** @brief output of gate CLK_ENB_ADSP */
+#define TEGRA186_CLK_ADSP 138
+/** @brief output of gate CLK_ENB_ADSPNEON */
+#define TEGRA186_CLK_ADSPNEON 139
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_MPHY_L0_RX_LS_SYMB */
+#define TEGRA186_CLK_MPHY_L0_RX_SYMB 140
+/** @brief output of gate CLK_ENB_MPHY_L0_RX_LS_BIT */
+#define TEGRA186_CLK_MPHY_L0_RX_LS_BIT 141
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_MPHY_L0_TX_LS_SYMB */
+#define TEGRA186_CLK_MPHY_L0_TX_SYMB 142
+/** @brief output of gate CLK_ENB_MPHY_L0_TX_LS_3XBIT */
+#define TEGRA186_CLK_MPHY_L0_TX_LS_3XBIT 143
+/** @brief output of gate CLK_ENB_MPHY_L0_RX_ANA */
+#define TEGRA186_CLK_MPHY_L0_RX_ANA 144
+/** @brief output of gate CLK_ENB_MPHY_L1_RX_ANA */
+#define TEGRA186_CLK_MPHY_L1_RX_ANA 145
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_MPHY_IOBIST */
+#define TEGRA186_CLK_MPHY_IOBIST 146
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_MPHY_TX_1MHZ_REF */
+#define TEGRA186_CLK_MPHY_TX_1MHZ_REF 147
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_MPHY_CORE_PLL_FIXED */
+#define TEGRA186_CLK_MPHY_CORE_PLL_FIXED 148
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AXI_CBB */
+#define TEGRA186_CLK_AXI_CBB 149
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DMIC3 */
+#define TEGRA186_CLK_DMIC3 150
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DMIC4 */
+#define TEGRA186_CLK_DMIC4 151
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSPK1 */
+#define TEGRA186_CLK_DSPK1 152
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSPK2 */
+#define TEGRA186_CLK_DSPK2 153
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 */
+#define TEGRA186_CLK_I2S6 154
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_P0 */
+#define TEGRA186_CLK_NVDISPLAY_P0 155
+/** @brief output of the NVDISPLAY_DISP_CLK_SRC mux in CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_DISP */
+#define TEGRA186_CLK_NVDISPLAY_DISP 156
+/** @brief output of gate CLK_ENB_NVDISPLAY_DSC */
+#define TEGRA186_CLK_NVDISPLAY_DSC 157
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAYHUB */
+#define TEGRA186_CLK_NVDISPLAYHUB 158
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_P1 */
+#define TEGRA186_CLK_NVDISPLAY_P1 159
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_P2 */
+#define TEGRA186_CLK_NVDISPLAY_P2 160
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_TACH */
+#define TEGRA186_CLK_TACH 166
+/** @brief output of gate CLK_ENB_EQOS */
+#define TEGRA186_CLK_EQOS_AXI 167
+/** @brief output of gate CLK_ENB_EQOS_RX */
+#define TEGRA186_CLK_EQOS_RX 168
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UFSHC_CG_SYS */
+#define TEGRA186_CLK_UFSHC 178
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UFSDEV_REF */
+#define TEGRA186_CLK_UFSDEV_REF 179
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVCSI */
+#define TEGRA186_CLK_NVCSI 180
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVCSILP */
+#define TEGRA186_CLK_NVCSILP 181
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C7 */
+#define TEGRA186_CLK_I2C7 182
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C9 */
+#define TEGRA186_CLK_I2C9 183
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C12 */
+#define TEGRA186_CLK_I2C12 184
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C13 */
+#define TEGRA186_CLK_I2C13 185
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C14 */
+#define TEGRA186_CLK_I2C14 186
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM1 */
+#define TEGRA186_CLK_PWM1 187
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM2 */
+#define TEGRA186_CLK_PWM2 188
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM3 */
+#define TEGRA186_CLK_PWM3 189
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM5 */
+#define TEGRA186_CLK_PWM5 190
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM6 */
+#define TEGRA186_CLK_PWM6 191
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM7 */
+#define TEGRA186_CLK_PWM7 192
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM8 */
+#define TEGRA186_CLK_PWM8 193
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTE */
+#define TEGRA186_CLK_UARTE 194
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTF */
+#define TEGRA186_CLK_UARTF 195
+/** @deprecated */
+#define TEGRA186_CLK_DBGAPB 196
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_BPMP_CPU_NIC */
+#define TEGRA186_CLK_BPMP_CPU_NIC 197
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_BPMP_APB */
+#define TEGRA186_CLK_BPMP_APB 199
+/** @brief output of mux controlled by TEGRA186_CLK_SOC_ACTMON */
+#define TEGRA186_CLK_ACTMON 201
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AON_CPU_NIC */
+#define TEGRA186_CLK_AON_CPU_NIC 208
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_CAN1 */
+#define TEGRA186_CLK_CAN1 210
+/** @brief output of gate CLK_ENB_CAN1_HOST */
+#define TEGRA186_CLK_CAN1_HOST 211
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_CAN2 */
+#define TEGRA186_CLK_CAN2 212
+/** @brief output of gate CLK_ENB_CAN2_HOST */
+#define TEGRA186_CLK_CAN2_HOST 213
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AON_APB */
+#define TEGRA186_CLK_AON_APB 214
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTC */
+#define TEGRA186_CLK_UARTC 215
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTG */
+#define TEGRA186_CLK_UARTG 216
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AON_UART_FST_MIPI_CAL */
+#define TEGRA186_CLK_AON_UART_FST_MIPI_CAL 217
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C2 */
+#define TEGRA186_CLK_I2C2 218
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C8 */
+#define TEGRA186_CLK_I2C8 219
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C10 */
+#define TEGRA186_CLK_I2C10 220
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AON_I2C_SLOW */
+#define TEGRA186_CLK_AON_I2C_SLOW 221
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SPI2 */
+#define TEGRA186_CLK_SPI2 222
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DMIC5 */
+#define TEGRA186_CLK_DMIC5 223
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AON_TOUCH */
+#define TEGRA186_CLK_AON_TOUCH 224
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM4 */
+#define TEGRA186_CLK_PWM4 225
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_TSC. This clock object is read only and is used for all timers in the system. */
+#define TEGRA186_CLK_TSC 226
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_MSS_ENCRYPT */
+#define TEGRA186_CLK_MSS_ENCRYPT 227
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SCE_CPU_NIC */
+#define TEGRA186_CLK_SCE_CPU_NIC 228
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SCE_APB */
+#define TEGRA186_CLK_SCE_APB 230
+/** @brief output of gate CLK_ENB_DSIC */
+#define TEGRA186_CLK_DSIC 231
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSIC_LP */
+#define TEGRA186_CLK_DSIC_LP 232
+/** @brief output of gate CLK_ENB_DSID */
+#define TEGRA186_CLK_DSID 233
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSID_LP */
+#define TEGRA186_CLK_DSID_LP 234
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_PEX_SATA_USB_RX_BYP */
+#define TEGRA186_CLK_PEX_SATA_USB_RX_BYP 236
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SPDIF_OUT */
+#define TEGRA186_CLK_SPDIF_OUT 238
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_EQOS_PTP_REF_CLK_0 */
+#define TEGRA186_CLK_EQOS_PTP_REF 239
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_EQOS_TX_CLK */
+#define TEGRA186_CLK_EQOS_TX 240
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK */
+#define TEGRA186_CLK_USB2_HSIC_TRK 241
+/** @brief output of mux xusb_ss_clk_switch on page 66 of T186_Clocks_IAS.doc */
+#define TEGRA186_CLK_XUSB_CORE_SS 242
+/** @brief output of mux xusb_core_dev_clk_switch on page 67 of T186_Clocks_IAS.doc */
+#define TEGRA186_CLK_XUSB_CORE_DEV 243
+/** @brief output of mux xusb_core_falcon_clk_switch on page 67 of T186_Clocks_IAS.doc */
+#define TEGRA186_CLK_XUSB_FALCON 244
+/** @brief output of mux xusb_fs_clk_switch on page 66 of T186_Clocks_IAS.doc */
+#define TEGRA186_CLK_XUSB_FS 245
+/** @brief output of the divider CLK_RST_CONTROLLER_PLLA_OUT */
+#define TEGRA186_CLK_PLL_A_OUT0 246
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S1 */
+#define TEGRA186_CLK_SYNC_I2S1 247
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S2 */
+#define TEGRA186_CLK_SYNC_I2S2 248
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S3 */
+#define TEGRA186_CLK_SYNC_I2S3 249
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S4 */
+#define TEGRA186_CLK_SYNC_I2S4 250
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S5 */
+#define TEGRA186_CLK_SYNC_I2S5 251
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S6 */
+#define TEGRA186_CLK_SYNC_I2S6 252
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DSPK1 */
+#define TEGRA186_CLK_SYNC_DSPK1 253
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DSPK2 */
+#define TEGRA186_CLK_SYNC_DSPK2 254
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DMIC1 */
+#define TEGRA186_CLK_SYNC_DMIC1 255
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DMIC2 */
+#define TEGRA186_CLK_SYNC_DMIC2 256
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DMIC3 */
+#define TEGRA186_CLK_SYNC_DMIC3 257
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DMIC4 */
+#define TEGRA186_CLK_SYNC_DMIC4 259
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_SPDIF */
+#define TEGRA186_CLK_SYNC_SPDIF 260
+/** @brief output of gate CLK_ENB_PLLREFE_OUT */
+#define TEGRA186_CLK_PLLREFE_OUT_GATED 261
+/** @brief output of the divider PLLREFE_DIVP in CLK_RST_CONTROLLER_PLLREFE_BASE. PLLREFE has 2 outputs:
+  *      * VCO/pdiv defined by this clock object
+  *      * VCO/2 defined by TEGRA186_CLK_PLLREFE_OUT
+  */
+#define TEGRA186_CLK_PLLREFE_OUT1 262
+#define TEGRA186_CLK_PLLD_OUT1 267
+/** @brief output of the divider PLLP_DIVP in CLK_RST_CONTROLLER_PLLP_BASE */
+#define TEGRA186_CLK_PLLP_OUT0 269
+/** @brief output of the divider CLK_RST_CONTROLLER_PLLP_OUTC */
+#define TEGRA186_CLK_PLLP_OUT5 270
+/** PLL controlled by CLK_RST_CONTROLLER_PLLA_BASE for use by audio clocks */
+#define TEGRA186_CLK_PLLA 271
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_ACLK_BURST_POLICY divided by the divider controlled by ACLK_CLK_DIVISOR in CLK_RST_CONTROLLER_SUPER_ACLK_DIVIDER */
+#define TEGRA186_CLK_ACLK 273
+/** fixed 48MHz clock divided down from TEGRA186_CLK_PLL_U */
+#define TEGRA186_CLK_PLL_U_48M 274
+/** fixed 480MHz clock divided down from TEGRA186_CLK_PLL_U */
+#define TEGRA186_CLK_PLL_U_480M 275
+/** @brief output of the divider PLLC4_DIVP in CLK_RST_CONTROLLER_PLLC4_BASE. Output frequency is TEGRA186_CLK_PLLC4_VCO/PLLC4_DIVP */
+#define TEGRA186_CLK_PLLC4_OUT0 276
+/** fixed /3 divider. Output frequency of this clock is TEGRA186_CLK_PLLC4_VCO/3 */
+#define TEGRA186_CLK_PLLC4_OUT1 277
+/** fixed /5 divider. Output frequency of this clock is TEGRA186_CLK_PLLC4_VCO/5 */
+#define TEGRA186_CLK_PLLC4_OUT2 278
+/** @brief output of mux controlled by PLLC4_CLK_SEL in CLK_RST_CONTROLLER_PLLC4_MISC1 */
+#define TEGRA186_CLK_PLLC4_OUT_MUX 279
+/** @brief output of divider NVDISPLAY_DISP_CLK_DIVISOR in CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_DISP when DFLLDISP_DIV is selected in NVDISPLAY_DISP_CLK_SRC */
+#define TEGRA186_CLK_DFLLDISP_DIV 284
+/** @brief output of divider NVDISPLAY_DISP_CLK_DIVISOR in CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_DISP when PLLDISPHUB_DIV is selected in NVDISPLAY_DISP_CLK_SRC */
+#define TEGRA186_CLK_PLLDISPHUB_DIV 285
+/** fixed /8 divider which is used as the input for TEGRA186_CLK_SOR_SAFE */
+#define TEGRA186_CLK_PLLP_DIV8 286
+/** @brief output of divider CLK_RST_CONTROLLER_BPMP_NIC_RATE */
+#define TEGRA186_CLK_BPMP_NIC 287
+/** @brief output of the divider CLK_RST_CONTROLLER_PLLA1_OUT1 */
+#define TEGRA186_CLK_PLL_A_OUT1 288
+/** @deprecated */
+#define TEGRA186_CLK_GPC2CLK 289
+/** A fake clock which must be enabled during KFUSE read operations to ensure adequate VDD_CORE voltage. */
+#define TEGRA186_CLK_KFUSE 293
+/**
+ * @brief controls the PLLE hardware sequencer.
+ * @details This clock only has enable and disable methods. When the
+ * PLLE hw sequencer is enabled, PLLE, will be enabled or disabled by
+ * hw based on the control signals from the PCIe, SATA and XUSB
+ * clocks. When the PLLE hw sequencer is disabled, the state of PLLE
+ * is controlled by sw using clk_enable/clk_disable on
+ * TEGRA186_CLK_PLLE.
+ */
+#define TEGRA186_CLK_PLLE_PWRSEQ 294
+/** fixed 60MHz clock divided down from, TEGRA186_CLK_PLL_U */
+#define TEGRA186_CLK_PLLREFE_REF 295
+/** @brief output of mux controlled by SOR0_CLK_SEL0 and SOR0_CLK_SEL1 in CLK_RST_CONTROLLER_CLK_SOURCE_SOR0 */
+#define TEGRA186_CLK_SOR0_OUT 296
+/** @brief output of mux controlled by SOR1_CLK_SEL0 and SOR1_CLK_SEL1 in CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 */
+#define TEGRA186_CLK_SOR1_OUT 297
+/** @brief fixed /5 divider.  Output frequency of this clock is TEGRA186_CLK_PLLREFE_OUT1/5. Used as input for TEGRA186_CLK_EQOS_AXI */
+#define TEGRA186_CLK_PLLREFE_OUT1_DIV5 298
+/** @brief controls the UTMIP_PLL (aka PLLU) hardware sqeuencer */
+#define TEGRA186_CLK_UTMIP_PLL_PWRSEQ 301
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_PEX_USB_PAD_PLL0_MGMT */
+#define TEGRA186_CLK_PEX_USB_PAD0_MGMT 302
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_PEX_USB_PAD_PLL1_MGMT */
+#define TEGRA186_CLK_PEX_USB_PAD1_MGMT 303
+/** @brief controls the UPHY_PLL0 hardware sqeuencer */
+#define TEGRA186_CLK_UPHY_PLL0_PWRSEQ 304
+/** @brief controls the UPHY_PLL1 hardware sqeuencer */
+#define TEGRA186_CLK_UPHY_PLL1_PWRSEQ 305
+/** @brief control for PLLREFE_IDDQ in CLK_RST_CONTROLLER_PLLREFE_MISC so the bypass output even be used when the PLL is disabled */
+#define TEGRA186_CLK_PLLREFE_PLLE_PASSTHROUGH 306
+/** @brief output of the mux controlled by PLLREFE_SEL_CLKIN_PEX in CLK_RST_CONTROLLER_PLLREFE_MISC */
+#define TEGRA186_CLK_PLLREFE_PEX 307
+/** @brief control for PLLREFE_IDDQ in CLK_RST_CONTROLLER_PLLREFE_MISC to turn on the PLL when enabled */
+#define TEGRA186_CLK_PLLREFE_IDDQ 308
+/** @brief output of the divider QSPI_CLK_DIV2_SEL in CLK_RST_CONTROLLER_CLK_SOURCE_QSPI */
+#define TEGRA186_CLK_QSPI_OUT 309
+/**
+ * @brief GPC2CLK-div-2
+ * @details fixed /2 divider. Output frequency is
+ * TEGRA186_CLK_GPC2CLK/2. The frequency of this clock is the
+ * frequency at which the GPU graphics engine runs. */
+#define TEGRA186_CLK_GPCCLK 310
+/** @brief output of divider CLK_RST_CONTROLLER_AON_NIC_RATE */
+#define TEGRA186_CLK_AON_NIC 450
+/** @brief output of divider CLK_RST_CONTROLLER_SCE_NIC_RATE */
+#define TEGRA186_CLK_SCE_NIC 451
+/** Fixed 100MHz PLL for PCIe, SATA and superspeed USB */
+#define TEGRA186_CLK_PLLE 512
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLC_BASE */
+#define TEGRA186_CLK_PLLC 513
+/** Fixed 408MHz PLL for use by peripheral clocks */
+#define TEGRA186_CLK_PLLP 516
+/** @deprecated */
+#define TEGRA186_CLK_PLL_P TEGRA186_CLK_PLLP
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLD_BASE for use by DSI */
+#define TEGRA186_CLK_PLLD 518
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLD2_BASE for use by HDMI or DP */
+#define TEGRA186_CLK_PLLD2 519
+/**
+ * @brief PLL controlled by CLK_RST_CONTROLLER_PLLREFE_BASE.
+ * @details Note that this clock only controls the VCO output, before
+ * the post-divider. See TEGRA186_CLK_PLLREFE_OUT1 for more
+ * information.
+ */
+#define TEGRA186_CLK_PLLREFE_VCO 520
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLC2_BASE */
+#define TEGRA186_CLK_PLLC2 521
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLC3_BASE */
+#define TEGRA186_CLK_PLLC3 522
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLDP_BASE for use as the DP link clock */
+#define TEGRA186_CLK_PLLDP 523
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLC4_BASE */
+#define TEGRA186_CLK_PLLC4_VCO 524
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLA1_BASE for use by audio clocks */
+#define TEGRA186_CLK_PLLA1 525
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLNVCSI_BASE */
+#define TEGRA186_CLK_PLLNVCSI 526
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLDISPHUB_BASE */
+#define TEGRA186_CLK_PLLDISPHUB 527
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLD3_BASE for use by HDMI or DP */
+#define TEGRA186_CLK_PLLD3 528
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLBPMPCAM_BASE */
+#define TEGRA186_CLK_PLLBPMPCAM 531
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLAON_BASE for use by IP blocks in the AON domain */
+#define TEGRA186_CLK_PLLAON 532
+/** Fixed frequency 960MHz PLL for USB and EAVB */
+#define TEGRA186_CLK_PLLU 533
+/** fixed /2 divider. Output frequency is TEGRA186_CLK_PLLC4_VCO/2 */
+#define TEGRA186_CLK_PLLC4_VCO_DIV2 535
+/** @brief NAFLL clock source for AXI_CBB */
+#define TEGRA186_CLK_NAFLL_AXI_CBB 564
+/** @brief NAFLL clock source for BPMP */
+#define TEGRA186_CLK_NAFLL_BPMP 565
+/** @brief NAFLL clock source for ISP */
+#define TEGRA186_CLK_NAFLL_ISP 566
+/** @brief NAFLL clock source for NVDEC */
+#define TEGRA186_CLK_NAFLL_NVDEC 567
+/** @brief NAFLL clock source for NVENC */
+#define TEGRA186_CLK_NAFLL_NVENC 568
+/** @brief NAFLL clock source for NVJPG */
+#define TEGRA186_CLK_NAFLL_NVJPG 569
+/** @brief NAFLL clock source for SCE */
+#define TEGRA186_CLK_NAFLL_SCE 570
+/** @brief NAFLL clock source for SE */
+#define TEGRA186_CLK_NAFLL_SE 571
+/** @brief NAFLL clock source for TSEC */
+#define TEGRA186_CLK_NAFLL_TSEC 572
+/** @brief NAFLL clock source for TSECB */
+#define TEGRA186_CLK_NAFLL_TSECB 573
+/** @brief NAFLL clock source for VI */
+#define TEGRA186_CLK_NAFLL_VI 574
+/** @brief NAFLL clock source for VIC */
+#define TEGRA186_CLK_NAFLL_VIC 575
+/** @brief NAFLL clock source for DISP */
+#define TEGRA186_CLK_NAFLL_DISP 576
+/** @brief NAFLL clock source for GPU */
+#define TEGRA186_CLK_NAFLL_GPU 577
+/** @brief NAFLL clock source for M-CPU cluster */
+#define TEGRA186_CLK_NAFLL_MCPU 578
+/** @brief NAFLL clock source for B-CPU cluster */
+#define TEGRA186_CLK_NAFLL_BCPU 579
+/** @brief input from Tegra's CLK_32K_IN pad */
+#define TEGRA186_CLK_CLK_32K 608
+/** @brief output of divider CLK_RST_CONTROLLER_CLK_M_DIVIDE */
+#define TEGRA186_CLK_CLK_M 609
+/** @brief output of divider PLL_REF_DIV in CLK_RST_CONTROLLER_OSC_CTRL */
+#define TEGRA186_CLK_PLL_REF 610
+/** @brief input from Tegra's XTAL_IN */
+#define TEGRA186_CLK_OSC 612
+/** @brief clock recovered from EAVB input */
+#define TEGRA186_CLK_EQOS_RX_INPUT 613
+/** @brief clock recovered from DTV input */
+#define TEGRA186_CLK_DTV_INPUT 614
+/** @brief SOR0 brick output which feeds into SOR0_CLK_SEL mux in CLK_RST_CONTROLLER_CLK_SOURCE_SOR0*/
+#define TEGRA186_CLK_SOR0_PAD_CLKOUT 615
+/** @brief SOR1 brick output which feeds into SOR1_CLK_SEL mux in CLK_RST_CONTROLLER_CLK_SOURCE_SOR1*/
+#define TEGRA186_CLK_SOR1_PAD_CLKOUT 616
+/** @brief clock recovered from I2S1 input */
+#define TEGRA186_CLK_I2S1_SYNC_INPUT 617
+/** @brief clock recovered from I2S2 input */
+#define TEGRA186_CLK_I2S2_SYNC_INPUT 618
+/** @brief clock recovered from I2S3 input */
+#define TEGRA186_CLK_I2S3_SYNC_INPUT 619
+/** @brief clock recovered from I2S4 input */
+#define TEGRA186_CLK_I2S4_SYNC_INPUT 620
+/** @brief clock recovered from I2S5 input */
+#define TEGRA186_CLK_I2S5_SYNC_INPUT 621
+/** @brief clock recovered from I2S6 input */
+#define TEGRA186_CLK_I2S6_SYNC_INPUT 622
+/** @brief clock recovered from SPDIFIN input */
+#define TEGRA186_CLK_SPDIFIN_SYNC_INPUT 623
+
+/**
+ * @brief subject to change
+ * @details maximum clock identifier value plus one.
+ */
+#define TEGRA186_CLK_CLK_MAX 624
+
+/** @} */
+
+#endif
diff --git a/include/dt-bindings/mailbox/tegra-hsp.h b/include/dt-bindings/mailbox/tegra-hsp.h
deleted file mode 100644
index e8c23fa..0000000
--- a/include/dt-bindings/mailbox/tegra-hsp.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * This header provides constants for binding nvidia,tegra186-hsp.
- *
- * The number with TEGRA_HSP_MASTER prefix indicates the bit that is
- * associated with a master ID in the doorbell registers.
- */
-
-#ifndef _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H
-#define _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H
-
-#define TEGRA_HSP_MASTER_CCPLEX		17
-#define TEGRA_HSP_MASTER_BPMP		19
-
-#endif
diff --git a/include/dt-bindings/mailbox/tegra186-hsp.h b/include/dt-bindings/mailbox/tegra186-hsp.h
new file mode 100644
index 0000000..b486432
--- /dev/null
+++ b/include/dt-bindings/mailbox/tegra186-hsp.h
@@ -0,0 +1,19 @@
+/*
+ * This header provides constants for binding nvidia,tegra186-hsp.
+ *
+ * The number with HSP_DB_MASTER prefix indicates the bit that is
+ * associated with a master ID in the doorbell registers.
+ */
+
+#ifndef _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H
+#define _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H
+
+#define HSP_MBOX_TYPE_DB 0x0
+#define HSP_MBOX_TYPE_SM 0x1
+#define HSP_MBOX_TYPE_SS 0x2
+#define HSP_MBOX_TYPE_AS 0x3
+
+#define HSP_DB_MASTER_CCPLEX 17
+#define HSP_DB_MASTER_BPMP 19
+
+#endif
diff --git a/include/dt-bindings/power/tegra186-powergate.h b/include/dt-bindings/power/tegra186-powergate.h
new file mode 100644
index 0000000..70630c6
--- /dev/null
+++ b/include/dt-bindings/power/tegra186-powergate.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015-2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _DT_BINDINGS_POWER_TEGRA186_POWERGATE_H
+#define _DT_BINDINGS_POWER_TEGRA186_POWERGATE_H
+
+#define TEGRA186_POWER_DOMAIN_AUD	0
+#define TEGRA186_POWER_DOMAIN_DFD	1
+#define TEGRA186_POWER_DOMAIN_DISP	2
+#define TEGRA186_POWER_DOMAIN_DISPB	3
+#define TEGRA186_POWER_DOMAIN_DISPC	4
+#define TEGRA186_POWER_DOMAIN_ISPA	5
+#define TEGRA186_POWER_DOMAIN_NVDEC	6
+#define TEGRA186_POWER_DOMAIN_NVJPG	7
+#define TEGRA186_POWER_DOMAIN_MPE	8
+#define TEGRA186_POWER_DOMAIN_PCX	9
+#define TEGRA186_POWER_DOMAIN_SAX	10
+#define TEGRA186_POWER_DOMAIN_VE	11
+#define TEGRA186_POWER_DOMAIN_VIC	12
+#define TEGRA186_POWER_DOMAIN_XUSBA	13
+#define TEGRA186_POWER_DOMAIN_XUSBB	14
+#define TEGRA186_POWER_DOMAIN_XUSBC	15
+#define TEGRA186_POWER_DOMAIN_GPU	43
+#define TEGRA186_POWER_DOMAIN_MAX	44
+
+#endif
diff --git a/include/dt-bindings/reset/tegra186-reset.h b/include/dt-bindings/reset/tegra186-reset.h
new file mode 100644
index 0000000..26b4ba9
--- /dev/null
+++ b/include/dt-bindings/reset/tegra186-reset.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2015, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _ABI_MACH_T186_RESET_T186_H_
+#define _ABI_MACH_T186_RESET_T186_H_
+
+#define TEGRA186_RESET_ACTMON			0
+#define TEGRA186_RESET_AFI			1
+#define TEGRA186_RESET_CEC			2
+#define TEGRA186_RESET_CSITE			3
+#define TEGRA186_RESET_DP2			4
+#define TEGRA186_RESET_DPAUX			5
+#define TEGRA186_RESET_DSI			6
+#define TEGRA186_RESET_DSIB			7
+#define TEGRA186_RESET_DTV			8
+#define TEGRA186_RESET_DVFS			9
+#define TEGRA186_RESET_ENTROPY			10
+#define TEGRA186_RESET_EXTPERIPH1		11
+#define TEGRA186_RESET_EXTPERIPH2		12
+#define TEGRA186_RESET_EXTPERIPH3		13
+#define TEGRA186_RESET_GPU			14
+#define TEGRA186_RESET_HDA			15
+#define TEGRA186_RESET_HDA2CODEC_2X		16
+#define TEGRA186_RESET_HDA2HDMICODEC		17
+#define TEGRA186_RESET_HOST1X			18
+#define TEGRA186_RESET_I2C1			19
+#define TEGRA186_RESET_I2C2			20
+#define TEGRA186_RESET_I2C3			21
+#define TEGRA186_RESET_I2C4			22
+#define TEGRA186_RESET_I2C5			23
+#define TEGRA186_RESET_I2C6			24
+#define TEGRA186_RESET_ISP			25
+#define TEGRA186_RESET_KFUSE			26
+#define TEGRA186_RESET_LA			27
+#define TEGRA186_RESET_MIPI_CAL			28
+#define TEGRA186_RESET_PCIE			29
+#define TEGRA186_RESET_PCIEXCLK			30
+#define TEGRA186_RESET_SATA			31
+#define TEGRA186_RESET_SATACOLD			32
+#define TEGRA186_RESET_SDMMC1			33
+#define TEGRA186_RESET_SDMMC2			34
+#define TEGRA186_RESET_SDMMC3			35
+#define TEGRA186_RESET_SDMMC4			36
+#define TEGRA186_RESET_SE			37
+#define TEGRA186_RESET_SOC_THERM		38
+#define TEGRA186_RESET_SOR0			39
+#define TEGRA186_RESET_SPI1			40
+#define TEGRA186_RESET_SPI2			41
+#define TEGRA186_RESET_SPI3			42
+#define TEGRA186_RESET_SPI4			43
+#define TEGRA186_RESET_TMR			44
+#define TEGRA186_RESET_TRIG_SYS			45
+#define TEGRA186_RESET_TSEC			46
+#define TEGRA186_RESET_UARTA			47
+#define TEGRA186_RESET_UARTB			48
+#define TEGRA186_RESET_UARTC			49
+#define TEGRA186_RESET_UARTD			50
+#define TEGRA186_RESET_VI			51
+#define TEGRA186_RESET_VIC			52
+#define TEGRA186_RESET_XUSB_DEV			53
+#define TEGRA186_RESET_XUSB_HOST		54
+#define TEGRA186_RESET_XUSB_PADCTL		55
+#define TEGRA186_RESET_XUSB_SS			56
+#define TEGRA186_RESET_AON_APB			57
+#define TEGRA186_RESET_AXI_CBB			58
+#define TEGRA186_RESET_BPMP_APB			59
+#define TEGRA186_RESET_CAN1			60
+#define TEGRA186_RESET_CAN2			61
+#define TEGRA186_RESET_DMIC5			62
+#define TEGRA186_RESET_DSIC			63
+#define TEGRA186_RESET_DSID			64
+#define TEGRA186_RESET_EMC_EMC			65
+#define TEGRA186_RESET_EMC_MEM			66
+#define TEGRA186_RESET_EMCSB_EMC		67
+#define TEGRA186_RESET_EMCSB_MEM		68
+#define TEGRA186_RESET_EQOS			69
+#define TEGRA186_RESET_GPCDMA			70
+#define TEGRA186_RESET_GPIO_CTL0		71
+#define TEGRA186_RESET_GPIO_CTL1		72
+#define TEGRA186_RESET_GPIO_CTL2		73
+#define TEGRA186_RESET_GPIO_CTL3		74
+#define TEGRA186_RESET_GPIO_CTL4		75
+#define TEGRA186_RESET_GPIO_CTL5		76
+#define TEGRA186_RESET_I2C10			77
+#define TEGRA186_RESET_I2C12			78
+#define TEGRA186_RESET_I2C13			79
+#define TEGRA186_RESET_I2C14			80
+#define TEGRA186_RESET_I2C7			81
+#define TEGRA186_RESET_I2C8			82
+#define TEGRA186_RESET_I2C9			83
+#define TEGRA186_RESET_JTAG2AXI			84
+#define TEGRA186_RESET_MPHY_IOBIST		85
+#define TEGRA186_RESET_MPHY_L0_RX		86
+#define TEGRA186_RESET_MPHY_L0_TX		87
+#define TEGRA186_RESET_NVCSI			88
+#define TEGRA186_RESET_NVDISPLAY0_HEAD0		89
+#define TEGRA186_RESET_NVDISPLAY0_HEAD1		90
+#define TEGRA186_RESET_NVDISPLAY0_HEAD2		91
+#define TEGRA186_RESET_NVDISPLAY0_MISC		92
+#define TEGRA186_RESET_NVDISPLAY0_WGRP0		93
+#define TEGRA186_RESET_NVDISPLAY0_WGRP1		94
+#define TEGRA186_RESET_NVDISPLAY0_WGRP2		95
+#define TEGRA186_RESET_NVDISPLAY0_WGRP3		96
+#define TEGRA186_RESET_NVDISPLAY0_WGRP4		97
+#define TEGRA186_RESET_NVDISPLAY0_WGRP5		98
+#define TEGRA186_RESET_PWM1			99
+#define TEGRA186_RESET_PWM2			100
+#define TEGRA186_RESET_PWM3			101
+#define TEGRA186_RESET_PWM4			102
+#define TEGRA186_RESET_PWM5			103
+#define TEGRA186_RESET_PWM6			104
+#define TEGRA186_RESET_PWM7			105
+#define TEGRA186_RESET_PWM8			106
+#define TEGRA186_RESET_SCE_APB			107
+#define TEGRA186_RESET_SOR1			108
+#define TEGRA186_RESET_TACH			109
+#define TEGRA186_RESET_TSC			110
+#define TEGRA186_RESET_UARTF			111
+#define TEGRA186_RESET_UARTG			112
+#define TEGRA186_RESET_UFSHC			113
+#define TEGRA186_RESET_UFSHC_AXI_M		114
+#define TEGRA186_RESET_UPHY			115
+#define TEGRA186_RESET_ADSP			116
+#define TEGRA186_RESET_ADSPDBG			117
+#define TEGRA186_RESET_ADSPINTF			118
+#define TEGRA186_RESET_ADSPNEON			119
+#define TEGRA186_RESET_ADSPPERIPH		120
+#define TEGRA186_RESET_ADSPSCU			121
+#define TEGRA186_RESET_ADSPWDT			122
+#define TEGRA186_RESET_APE			123
+#define TEGRA186_RESET_DPAUX1			124
+#define TEGRA186_RESET_NVDEC			125
+#define TEGRA186_RESET_NVENC			126
+#define TEGRA186_RESET_NVJPG			127
+#define TEGRA186_RESET_PEX_USB_UPHY		128
+#define TEGRA186_RESET_QSPI			129
+#define TEGRA186_RESET_TSECB			130
+#define TEGRA186_RESET_VI_I2C			131
+#define TEGRA186_RESET_UARTE			132
+#define TEGRA186_RESET_TOP_GTE			133
+#define TEGRA186_RESET_SHSP			134
+#define TEGRA186_RESET_PEX_USB_UPHY_L5		135
+#define TEGRA186_RESET_PEX_USB_UPHY_L4		136
+#define TEGRA186_RESET_PEX_USB_UPHY_L3		137
+#define TEGRA186_RESET_PEX_USB_UPHY_L2		138
+#define TEGRA186_RESET_PEX_USB_UPHY_L1		139
+#define TEGRA186_RESET_PEX_USB_UPHY_L0		140
+#define TEGRA186_RESET_PEX_USB_UPHY_PLL1	141
+#define TEGRA186_RESET_PEX_USB_UPHY_PLL0	142
+#define TEGRA186_RESET_TSCTNVI			143
+#define TEGRA186_RESET_EXTPERIPH4		144
+#define TEGRA186_RESET_DSIPADCTL		145
+#define TEGRA186_RESET_AUD_MCLK			146
+#define TEGRA186_RESET_MPHY_CLK_CTL		147
+#define TEGRA186_RESET_MPHY_L1_RX		148
+#define TEGRA186_RESET_MPHY_L1_TX		149
+#define TEGRA186_RESET_UFSHC_LP			150
+#define TEGRA186_RESET_BPMP_NIC			151
+#define TEGRA186_RESET_BPMP_NSYSPORESET		152
+#define TEGRA186_RESET_BPMP_NRESET		153
+#define TEGRA186_RESET_BPMP_DBGRESETN		154
+#define TEGRA186_RESET_BPMP_PRESETDBGN		155
+#define TEGRA186_RESET_BPMP_PM			156
+#define TEGRA186_RESET_BPMP_CVC			157
+#define TEGRA186_RESET_BPMP_DMA			158
+#define TEGRA186_RESET_BPMP_HSP			159
+#define TEGRA186_RESET_TSCTNBPMP		160
+#define TEGRA186_RESET_BPMP_TKE			161
+#define TEGRA186_RESET_BPMP_GTE			162
+#define TEGRA186_RESET_BPMP_PM_ACTMON		163
+#define TEGRA186_RESET_AON_NIC			164
+#define TEGRA186_RESET_AON_NSYSPORESET		165
+#define TEGRA186_RESET_AON_NRESET		166
+#define TEGRA186_RESET_AON_DBGRESETN		167
+#define TEGRA186_RESET_AON_PRESETDBGN		168
+#define TEGRA186_RESET_AON_ACTMON		169
+#define TEGRA186_RESET_AOPM			170
+#define TEGRA186_RESET_AOVC			171
+#define TEGRA186_RESET_AON_DMA			172
+#define TEGRA186_RESET_AON_GPIO			173
+#define TEGRA186_RESET_AON_HSP			174
+#define TEGRA186_RESET_TSCTNAON			175
+#define TEGRA186_RESET_AON_TKE			176
+#define TEGRA186_RESET_AON_GTE			177
+#define TEGRA186_RESET_SCE_NIC			178
+#define TEGRA186_RESET_SCE_NSYSPORESET		179
+#define TEGRA186_RESET_SCE_NRESET		180
+#define TEGRA186_RESET_SCE_DBGRESETN		181
+#define TEGRA186_RESET_SCE_PRESETDBGN		182
+#define TEGRA186_RESET_SCE_ACTMON		183
+#define TEGRA186_RESET_SCE_PM			184
+#define TEGRA186_RESET_SCE_DMA			185
+#define TEGRA186_RESET_SCE_HSP			186
+#define TEGRA186_RESET_TSCTNSCE			187
+#define TEGRA186_RESET_SCE_TKE			188
+#define TEGRA186_RESET_SCE_GTE			189
+#define TEGRA186_RESET_SCE_CFG			190
+#define TEGRA186_RESET_ADSP_ALL			191
+/** @brief controls the power up/down sequence of UFSHC PSW partition. Controls LP_PWR_READY, LP_ISOL_EN, and LP_RESET_N signals */
+#define TEGRA186_RESET_UFSHC_LP_SEQ		192
+#define TEGRA186_RESET_SIZE			193
+
+#endif
diff --git a/include/dt-structs.h b/include/dt-structs.h
new file mode 100644
index 0000000..e13afa6
--- /dev/null
+++ b/include/dt-structs.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_STTUCTS
+#define __DT_STTUCTS
+
+/* These structures may only be used in SPL */
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+struct phandle_2_cell {
+	const void *node;
+	int id;
+};
+#include <generated/dt-structs.h>
+#endif
+
+#endif
diff --git a/include/dwmmc.h b/include/dwmmc.h
index 335af51..5b9602c 100644
--- a/include/dwmmc.h
+++ b/include/dwmmc.h
@@ -105,7 +105,7 @@
 
 /* Status Register */
 #define DWMCI_BUSY		(1 << 9)
-#define DWMCI_FIFO_MASK		0x1ff
+#define DWMCI_FIFO_MASK		0x1fff
 #define DWMCI_FIFO_SHIFT	17
 
 /* FIFOTH Register */
@@ -224,9 +224,79 @@
 	return readb(host->ioaddr + reg);
 }
 
+#ifdef CONFIG_BLK
+/**
+ * dwmci_setup_cfg() - Set up the configuration for DWMMC
+ *
+ * This is used to set up a DWMMC device when you are using CONFIG_BLK.
+ *
+ * This should be called from your MMC driver's probe() method once you have
+ * the information required.
+ *
+ * Generally your driver will have a platform data structure which holds both
+ * the configuration (struct mmc_config) and the MMC device info (struct mmc).
+ * For example:
+ *
+ * struct rockchip_mmc_plat {
+ *	struct mmc_config cfg;
+ *	struct mmc mmc;
+ * };
+ *
+ * ...
+ *
+ * Inside U_BOOT_DRIVER():
+ *	.platdata_auto_alloc_size = sizeof(struct rockchip_mmc_plat),
+ *
+ * To access platform data:
+ *	struct rockchip_mmc_plat *plat = dev_get_platdata(dev);
+ *
+ * See rockchip_dw_mmc.c for an example.
+ *
+ * @cfg:	Configuration structure to fill in (generally &plat->mmc)
+ * @name:	Device name (normally dev->name)
+ * @buswidth:	Bus width (in bits, such as 4 or 8)
+ * @caps:	Host capabilities (MMC_MODE_...)
+ * @max_clk:	Maximum supported clock speed in HZ (e.g. 150000000)
+ * @min_clk:	Minimum supported clock speed in HZ (e.g. 400000)
+ */
 void dwmci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth,
 		     uint caps, u32 max_clk, u32 min_clk);
+
+/**
+ * dwmci_bind() - Set up a new MMC block device
+ *
+ * This is used to set up a DWMMC block device when you are using CONFIG_BLK.
+ * It should be called from your driver's bind() method.
+ *
+ * See rockchip_dw_mmc.c for an example.
+ *
+ * @dev:	Device to set up
+ * @mmc:	Pointer to mmc structure (normally &plat->mmc)
+ * @cfg:	Empty configuration structure (generally &plat->cfg). This is
+ *		normally all zeroes at this point. The only purpose of passing
+ *		this in is to set mmc->cfg to it.
+ * @return 0 if OK, -ve if the block device could not be created
+ */
 int dwmci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg);
 
+#else
+/**
+ * add_dwmci() - Add a new DWMMC interface
+ *
+ * This is used when you are not using CONFIG_BLK. Convert your driver over!
+ *
+ * @host:	DWMMC host structure
+ * @max_clk:	Maximum supported clock speed in HZ (e.g. 150000000)
+ * @min_clk:	Minimum supported clock speed in HZ (e.g. 400000)
+ * @return 0 if OK, -ve on error
+ */
 int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk);
+#endif /* !CONFIG_BLK */
+
+#ifdef CONFIG_DM_MMC_OPS
+/* Export the operations to drivers */
+int dwmci_probe(struct udevice *dev);
+extern const struct dm_mmc_ops dm_dwmci_ops;
+#endif
+
 #endif	/* __DWMMC_HW_H */
diff --git a/include/ext4fs.h b/include/ext4fs.h
index cc765ae..13d2c56 100644
--- a/include/ext4fs.h
+++ b/include/ext4fs.h
@@ -32,6 +32,7 @@
 #define EXT4_EXT_MAGIC			0xf30a
 #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM	0x0010
 #define EXT4_FEATURE_INCOMPAT_EXTENTS	0x0040
+#define EXT4_FEATURE_INCOMPAT_64BIT	0x0080
 #define EXT4_INDIRECT_BLOCKS		12
 
 #define EXT4_BG_INODE_UNINIT		0x0001
diff --git a/include/fdt_support.h b/include/fdt_support.h
index d34e959..e9f3497 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -172,9 +172,16 @@
 
 int fdt_fixup_nor_flash_size(void *blob);
 
+#if defined(CONFIG_FDT_FIXUP_PARTITIONS)
 void fdt_fixup_mtdparts(void *fdt, void *node_info, int node_info_size);
+#else
+static inline void fdt_fixup_mtdparts(void *fdt, void *node_info,
+					int node_info_size) {}
+#endif
+
 void fdt_del_node_and_alias(void *blob, const char *alias);
-u64 fdt_translate_address(void *blob, int node_offset, const __be32 *in_addr);
+u64 fdt_translate_address(const void *blob, int node_offset,
+			  const __be32 *in_addr);
 int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
 					phys_addr_t compat_off);
 int fdt_alloc_phandle(void *blob);
@@ -233,7 +240,7 @@
 	return r;
 }
 
-void of_bus_default_count_cells(void *blob, int parentoffset,
+void of_bus_default_count_cells(const void *blob, int parentoffset,
 					int *addrc, int *sizec);
 int ft_verify_fdt(void *fdt);
 int arch_fixup_memory_node(void *blob);
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 05d70c4..aeb6bab 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -134,13 +134,10 @@
 	COMPAT_SAMSUNG_S3C2440_I2C,	/* Exynos I2C Controller */
 	COMPAT_SAMSUNG_EXYNOS5_SOUND,	/* Exynos Sound */
 	COMPAT_WOLFSON_WM8994_CODEC,	/* Wolfson WM8994 Sound Codec */
-	COMPAT_GOOGLE_CROS_EC_KEYB,	/* Google CROS_EC Keyboard */
 	COMPAT_SAMSUNG_EXYNOS_USB_PHY,	/* Exynos phy controller for usb2.0 */
 	COMPAT_SAMSUNG_EXYNOS5_USB3_PHY,/* Exynos phy controller for usb3.0 */
 	COMPAT_SAMSUNG_EXYNOS_TMU,	/* Exynos TMU */
-	COMPAT_SAMSUNG_EXYNOS_FIMD,	/* Exynos Display controller */
 	COMPAT_SAMSUNG_EXYNOS_MIPI_DSI,	/* Exynos mipi dsi */
-	COMPAT_SAMSUNG_EXYNOS5_DP,	/* Exynos Display port controller */
 	COMPAT_SAMSUNG_EXYNOS_DWMMC,	/* Exynos DWMMC controller */
 	COMPAT_SAMSUNG_EXYNOS_MMC,	/* Exynos MMC controller */
 	COMPAT_MAXIM_MAX77686_PMIC,	/* MAX77686 PMIC */
@@ -149,20 +146,16 @@
 	COMPAT_SAMSUNG_EXYNOS5_I2C,	/* Exynos5 High Speed I2C Controller */
 	COMPAT_SAMSUNG_EXYNOS_SYSMMU,	/* Exynos sysmmu */
 	COMPAT_INTEL_MICROCODE,		/* Intel microcode update */
-	COMPAT_INTEL_PANTHERPOINT_AHCI,	/* Intel Pantherpoint AHCI */
-	COMPAT_INTEL_MODEL_206AX,	/* Intel Model 206AX CPU */
-	COMPAT_INTEL_GMA,		/* Intel Graphics Media Accelerator */
 	COMPAT_AMS_AS3722,		/* AMS AS3722 PMIC */
-	COMPAT_INTEL_ICH_SPI,		/* Intel ICH7/9 SPI controller */
 	COMPAT_INTEL_QRK_MRC,		/* Intel Quark MRC */
 	COMPAT_SOCIONEXT_XHCI,		/* Socionext UniPhier xHCI */
-	COMPAT_INTEL_PCH,		/* Intel PCH */
 	COMPAT_ALTERA_SOCFPGA_DWMAC,	/* SoCFPGA Ethernet controller */
 	COMPAT_ALTERA_SOCFPGA_DWMMC,	/* SoCFPGA DWMMC controller */
 	COMPAT_ALTERA_SOCFPGA_DWC2USB,	/* SoCFPGA DWC2 USB controller */
 	COMPAT_INTEL_BAYTRAIL_FSP,	/* Intel Bay Trail FSP */
 	COMPAT_INTEL_BAYTRAIL_FSP_MDP,	/* Intel FSP memory-down params */
 	COMPAT_INTEL_IVYBRIDGE_FSP,	/* Intel Ivy Bridge FSP */
+	COMPAT_SUNXI_NAND,		/* SUNXI NAND controller */
 
 	COMPAT_COUNT,
 };
@@ -304,11 +297,13 @@
  * @param na	the number of cells used to represent an address
  * @param ns	the number of cells used to represent a size
  * @param sizep	a pointer to store the size into. Use NULL if not required
+ * @param translate	Indicates whether to translate the returned value
+ *			using the parent node's ranges property.
  * @return address, if found, or FDT_ADDR_T_NONE if not
  */
 fdt_addr_t fdtdec_get_addr_size_fixed(const void *blob, int node,
 		const char *prop_name, int index, int na, int ns,
-		fdt_size_t *sizep);
+		fdt_size_t *sizep, bool translate);
 
 /*
  * Look up an address property in a node and return the parsed address, and
@@ -324,10 +319,13 @@
  * @param prop_name	name of property to find
  * @param index	which address to retrieve from a list of addresses. Often 0.
  * @param sizep	a pointer to store the size into. Use NULL if not required
+ * @param translate	Indicates whether to translate the returned value
+ *			using the parent node's ranges property.
  * @return address, if found, or FDT_ADDR_T_NONE if not
  */
 fdt_addr_t fdtdec_get_addr_size_auto_parent(const void *blob, int parent,
-		int node, const char *prop_name, int index, fdt_size_t *sizep);
+		int node, const char *prop_name, int index, fdt_size_t *sizep,
+		bool translate);
 
 /*
  * Look up an address property in a node and return the parsed address, and
@@ -347,10 +345,13 @@
  * @param prop_name	name of property to find
  * @param index	which address to retrieve from a list of addresses. Often 0.
  * @param sizep	a pointer to store the size into. Use NULL if not required
+ * @param translate	Indicates whether to translate the returned value
+ *			using the parent node's ranges property.
  * @return address, if found, or FDT_ADDR_T_NONE if not
  */
 fdt_addr_t fdtdec_get_addr_size_auto_noparent(const void *blob, int node,
-		const char *prop_name, int index, fdt_size_t *sizep);
+		const char *prop_name, int index, fdt_size_t *sizep,
+		bool translate);
 
 /*
  * Look up an address property in a node and return the parsed address.
diff --git a/include/fsl_mmdc.h b/include/fsl_mmdc.h
index 281a819..a939d89 100644
--- a/include/fsl_mmdc.h
+++ b/include/fsl_mmdc.h
@@ -12,7 +12,7 @@
 #define CONFIG_SYS_MMDC_CORE_TIMING_CFG_1	0xff328f64
 #define CONFIG_SYS_MMDC_CORE_TIMING_CFG_2	0x01ff00db
 
-#define CONFIG_SYS_MMDC_CORE_MISC		0x00000680
+#define CONFIG_SYS_MMDC_CORE_MISC		0x00001680
 #define CONFIG_SYS_MMDC_PHY_MEASURE_UNIT	0x00000800
 #define CONFIG_SYS_MMDC_CORE_RDWR_CMD_DELAY	0x00002000
 #define CONFIG_SYS_MMDC_PHY_ODT_CTRL		0x0000022a
@@ -43,7 +43,7 @@
 
 #define CONFIG_SYS_MMDC_CORE_PWR_SAV_CTRL_STAT	0x00001067
 
-#define CONFIG_SYS_MMDC_CORE_REFRESH_CTL	0x103e8000
+#define CONFIG_SYS_MMDC_CORE_REFRESH_CTL	0x0f3c8000
 
 #define START_REFRESH				0x00000001
 
diff --git a/include/fsl_validate.h b/include/fsl_validate.h
index a71e1ce..c350938 100644
--- a/include/fsl_validate.h
+++ b/include/fsl_validate.h
@@ -254,4 +254,11 @@
 
 int fsl_check_boot_mode_secure(void);
 int fsl_setenv_chain_of_trust(void);
+
+/*
+ * This function is used to validate the main U-boot binary from
+ * SPL just before passing control to it using QorIQ Trust
+ * Architecture header (appended to U-boot image).
+ */
+void spl_validate_uboot(uint32_t hdr_addr, uintptr_t img_addr);
 #endif
diff --git a/include/gdsys_fpga.h b/include/gdsys_fpga.h
index e1b9c64..bb8e144 100644
--- a/include/gdsys_fpga.h
+++ b/include/gdsys_fpga.h
@@ -17,7 +17,6 @@
 };
 
 int get_fpga_state(unsigned dev);
-void print_fpga_state(unsigned dev);
 
 int fpga_set_reg(u32 fpga, u16 *reg, off_t regoff, u16 data);
 int fpga_get_reg(u32 fpga, u16 *reg, off_t regoff, u16 *data);
diff --git a/include/i2c_eeprom.h b/include/i2c_eeprom.h
index ea6c962..0452892 100644
--- a/include/i2c_eeprom.h
+++ b/include/i2c_eeprom.h
@@ -14,6 +14,10 @@
 };
 
 struct i2c_eeprom {
+	/* The EEPROM's page size in byte */
+	unsigned long pagesize;
+	/* The EEPROM's page width in bits (pagesize = 2^pagewidth) */
+	unsigned pagewidth;
 };
 
 #endif
diff --git a/include/image.h b/include/image.h
index d788c26..64da722 100644
--- a/include/image.h
+++ b/include/image.h
@@ -123,62 +123,87 @@
 # define IMAGE_OF_SYSTEM_SETUP	0
 #endif
 
+enum ih_category {
+	IH_ARCH,
+	IH_COMP,
+	IH_OS,
+	IH_TYPE,
+
+	IH_COUNT,
+};
+
 /*
  * Operating System Codes
+ *
+ * The following are exposed to uImage header.
+ * Do not change values for backward compatibility.
  */
-#define IH_OS_INVALID		0	/* Invalid OS	*/
-#define IH_OS_OPENBSD		1	/* OpenBSD	*/
-#define IH_OS_NETBSD		2	/* NetBSD	*/
-#define IH_OS_FREEBSD		3	/* FreeBSD	*/
-#define IH_OS_4_4BSD		4	/* 4.4BSD	*/
-#define IH_OS_LINUX		5	/* Linux	*/
-#define IH_OS_SVR4		6	/* SVR4		*/
-#define IH_OS_ESIX		7	/* Esix		*/
-#define IH_OS_SOLARIS		8	/* Solaris	*/
-#define IH_OS_IRIX		9	/* Irix		*/
-#define IH_OS_SCO		10	/* SCO		*/
-#define IH_OS_DELL		11	/* Dell		*/
-#define IH_OS_NCR		12	/* NCR		*/
-#define IH_OS_LYNXOS		13	/* LynxOS	*/
-#define IH_OS_VXWORKS		14	/* VxWorks	*/
-#define IH_OS_PSOS		15	/* pSOS		*/
-#define IH_OS_QNX		16	/* QNX		*/
-#define IH_OS_U_BOOT		17	/* Firmware	*/
-#define IH_OS_RTEMS		18	/* RTEMS	*/
-#define IH_OS_ARTOS		19	/* ARTOS	*/
-#define IH_OS_UNITY		20	/* Unity OS	*/
-#define IH_OS_INTEGRITY		21	/* INTEGRITY	*/
-#define IH_OS_OSE		22	/* OSE		*/
-#define IH_OS_PLAN9		23	/* Plan 9	*/
-#define IH_OS_OPENRTOS		24	/* OpenRTOS	*/
+enum {
+	IH_OS_INVALID		= 0,	/* Invalid OS	*/
+	IH_OS_OPENBSD,			/* OpenBSD	*/
+	IH_OS_NETBSD,			/* NetBSD	*/
+	IH_OS_FREEBSD,			/* FreeBSD	*/
+	IH_OS_4_4BSD,			/* 4.4BSD	*/
+	IH_OS_LINUX,			/* Linux	*/
+	IH_OS_SVR4,			/* SVR4		*/
+	IH_OS_ESIX,			/* Esix		*/
+	IH_OS_SOLARIS,			/* Solaris	*/
+	IH_OS_IRIX,			/* Irix		*/
+	IH_OS_SCO,			/* SCO		*/
+	IH_OS_DELL,			/* Dell		*/
+	IH_OS_NCR,			/* NCR		*/
+	IH_OS_LYNXOS,			/* LynxOS	*/
+	IH_OS_VXWORKS,			/* VxWorks	*/
+	IH_OS_PSOS,			/* pSOS		*/
+	IH_OS_QNX,			/* QNX		*/
+	IH_OS_U_BOOT,			/* Firmware	*/
+	IH_OS_RTEMS,			/* RTEMS	*/
+	IH_OS_ARTOS,			/* ARTOS	*/
+	IH_OS_UNITY,			/* Unity OS	*/
+	IH_OS_INTEGRITY,		/* INTEGRITY	*/
+	IH_OS_OSE,			/* OSE		*/
+	IH_OS_PLAN9,			/* Plan 9	*/
+	IH_OS_OPENRTOS,		/* OpenRTOS	*/
+
+	IH_OS_COUNT,
+};
 
 /*
  * CPU Architecture Codes (supported by Linux)
+ *
+ * The following are exposed to uImage header.
+ * Do not change values for backward compatibility.
  */
-#define IH_ARCH_INVALID		0	/* Invalid CPU	*/
-#define IH_ARCH_ALPHA		1	/* Alpha	*/
-#define IH_ARCH_ARM		2	/* ARM		*/
-#define IH_ARCH_I386		3	/* Intel x86	*/
-#define IH_ARCH_IA64		4	/* IA64		*/
-#define IH_ARCH_MIPS		5	/* MIPS		*/
-#define IH_ARCH_MIPS64		6	/* MIPS	 64 Bit */
-#define IH_ARCH_PPC		7	/* PowerPC	*/
-#define IH_ARCH_S390		8	/* IBM S390	*/
-#define IH_ARCH_SH		9	/* SuperH	*/
-#define IH_ARCH_SPARC		10	/* Sparc	*/
-#define IH_ARCH_SPARC64		11	/* Sparc 64 Bit */
-#define IH_ARCH_M68K		12	/* M68K		*/
-#define IH_ARCH_MICROBLAZE	14	/* MicroBlaze   */
-#define IH_ARCH_NIOS2		15	/* Nios-II	*/
-#define IH_ARCH_BLACKFIN	16	/* Blackfin	*/
-#define IH_ARCH_AVR32		17	/* AVR32	*/
-#define IH_ARCH_ST200	        18	/* STMicroelectronics ST200  */
-#define IH_ARCH_SANDBOX		19	/* Sandbox architecture (test only) */
-#define IH_ARCH_NDS32	        20	/* ANDES Technology - NDS32  */
-#define IH_ARCH_OPENRISC        21	/* OpenRISC 1000  */
-#define IH_ARCH_ARM64		22	/* ARM64	*/
-#define IH_ARCH_ARC		23	/* Synopsys DesignWare ARC */
-#define IH_ARCH_X86_64		24	/* AMD x86_64, Intel and Via */
+enum {
+	IH_ARCH_INVALID		= 0,	/* Invalid CPU	*/
+	IH_ARCH_ALPHA,			/* Alpha	*/
+	IH_ARCH_ARM,			/* ARM		*/
+	IH_ARCH_I386,			/* Intel x86	*/
+	IH_ARCH_IA64,			/* IA64		*/
+	IH_ARCH_MIPS,			/* MIPS		*/
+	IH_ARCH_MIPS64,			/* MIPS	 64 Bit */
+	IH_ARCH_PPC,			/* PowerPC	*/
+	IH_ARCH_S390,			/* IBM S390	*/
+	IH_ARCH_SH,			/* SuperH	*/
+	IH_ARCH_SPARC,			/* Sparc	*/
+	IH_ARCH_SPARC64,		/* Sparc 64 Bit */
+	IH_ARCH_M68K,			/* M68K		*/
+	IH_ARCH_NIOS,			/* Nios-32	*/
+	IH_ARCH_MICROBLAZE,		/* MicroBlaze   */
+	IH_ARCH_NIOS2,			/* Nios-II	*/
+	IH_ARCH_BLACKFIN,		/* Blackfin	*/
+	IH_ARCH_AVR32,			/* AVR32	*/
+	IH_ARCH_ST200,			/* STMicroelectronics ST200  */
+	IH_ARCH_SANDBOX,		/* Sandbox architecture (test only) */
+	IH_ARCH_NDS32,			/* ANDES Technology - NDS32  */
+	IH_ARCH_OPENRISC,		/* OpenRISC 1000  */
+	IH_ARCH_ARM64,			/* ARM64	*/
+	IH_ARCH_ARC,			/* Synopsys DesignWare ARC */
+	IH_ARCH_X86_64,			/* AMD x86_64, Intel and Via */
+	IH_ARCH_XTENSA,			/* Xtensa	*/
+
+	IH_ARCH_COUNT,
+};
 
 /*
  * Image Types
@@ -217,49 +242,62 @@
  *	U-Boot's command interpreter; this feature is especially
  *	useful when you configure U-Boot to use a real shell (hush)
  *	as command interpreter (=> Shell Scripts).
+ *
+ * The following are exposed to uImage header.
+ * Do not change values for backward compatibility.
  */
 
-#define IH_TYPE_INVALID		0	/* Invalid Image		*/
-#define IH_TYPE_STANDALONE	1	/* Standalone Program		*/
-#define IH_TYPE_KERNEL		2	/* OS Kernel Image		*/
-#define IH_TYPE_RAMDISK		3	/* RAMDisk Image		*/
-#define IH_TYPE_MULTI		4	/* Multi-File Image		*/
-#define IH_TYPE_FIRMWARE	5	/* Firmware Image		*/
-#define IH_TYPE_SCRIPT		6	/* Script file			*/
-#define IH_TYPE_FILESYSTEM	7	/* Filesystem Image (any type)	*/
-#define IH_TYPE_FLATDT		8	/* Binary Flat Device Tree Blob	*/
-#define IH_TYPE_KWBIMAGE	9	/* Kirkwood Boot Image		*/
-#define IH_TYPE_IMXIMAGE	10	/* Freescale IMXBoot Image	*/
-#define IH_TYPE_UBLIMAGE	11	/* Davinci UBL Image		*/
-#define IH_TYPE_OMAPIMAGE	12	/* TI OMAP Config Header Image	*/
-#define IH_TYPE_AISIMAGE	13	/* TI Davinci AIS Image		*/
-#define IH_TYPE_KERNEL_NOLOAD	14	/* OS Kernel Image, can run from any load address */
-#define IH_TYPE_PBLIMAGE	15	/* Freescale PBL Boot Image	*/
-#define IH_TYPE_MXSIMAGE	16	/* Freescale MXSBoot Image	*/
-#define IH_TYPE_GPIMAGE		17	/* TI Keystone GPHeader Image	*/
-#define IH_TYPE_ATMELIMAGE	18	/* ATMEL ROM bootable Image	*/
-#define IH_TYPE_SOCFPGAIMAGE	19	/* Altera SOCFPGA Preloader	*/
-#define IH_TYPE_X86_SETUP	20	/* x86 setup.bin Image		*/
-#define IH_TYPE_LPC32XXIMAGE	21	/* x86 setup.bin Image		*/
-#define IH_TYPE_LOADABLE	22	/* A list of typeless images	*/
-#define IH_TYPE_RKIMAGE		23	/* Rockchip Boot Image		*/
-#define IH_TYPE_RKSD		24	/* Rockchip SD card		*/
-#define IH_TYPE_RKSPI		25	/* Rockchip SPI image		*/
-#define IH_TYPE_ZYNQIMAGE	26	/* Xilinx Zynq Boot Image */
-#define IH_TYPE_ZYNQMPIMAGE	27	/* Xilinx ZynqMP Boot Image */
-#define IH_TYPE_FPGA		28	/* FPGA Image */
+enum {
+	IH_TYPE_INVALID		= 0,	/* Invalid Image		*/
+	IH_TYPE_STANDALONE,		/* Standalone Program		*/
+	IH_TYPE_KERNEL,			/* OS Kernel Image		*/
+	IH_TYPE_RAMDISK,		/* RAMDisk Image		*/
+	IH_TYPE_MULTI,			/* Multi-File Image		*/
+	IH_TYPE_FIRMWARE,		/* Firmware Image		*/
+	IH_TYPE_SCRIPT,			/* Script file			*/
+	IH_TYPE_FILESYSTEM,		/* Filesystem Image (any type)	*/
+	IH_TYPE_FLATDT,			/* Binary Flat Device Tree Blob	*/
+	IH_TYPE_KWBIMAGE,		/* Kirkwood Boot Image		*/
+	IH_TYPE_IMXIMAGE,		/* Freescale IMXBoot Image	*/
+	IH_TYPE_UBLIMAGE,		/* Davinci UBL Image		*/
+	IH_TYPE_OMAPIMAGE,		/* TI OMAP Config Header Image	*/
+	IH_TYPE_AISIMAGE,		/* TI Davinci AIS Image		*/
+	/* OS Kernel Image, can run from any load address */
+	IH_TYPE_KERNEL_NOLOAD,
+	IH_TYPE_PBLIMAGE,		/* Freescale PBL Boot Image	*/
+	IH_TYPE_MXSIMAGE,		/* Freescale MXSBoot Image	*/
+	IH_TYPE_GPIMAGE,		/* TI Keystone GPHeader Image	*/
+	IH_TYPE_ATMELIMAGE,		/* ATMEL ROM bootable Image	*/
+	IH_TYPE_SOCFPGAIMAGE,		/* Altera SOCFPGA Preloader	*/
+	IH_TYPE_X86_SETUP,		/* x86 setup.bin Image		*/
+	IH_TYPE_LPC32XXIMAGE,		/* x86 setup.bin Image		*/
+	IH_TYPE_LOADABLE,		/* A list of typeless images	*/
+	IH_TYPE_RKIMAGE,		/* Rockchip Boot Image		*/
+	IH_TYPE_RKSD,			/* Rockchip SD card		*/
+	IH_TYPE_RKSPI,			/* Rockchip SPI image		*/
+	IH_TYPE_ZYNQIMAGE,		/* Xilinx Zynq Boot Image */
+	IH_TYPE_ZYNQMPIMAGE,		/* Xilinx ZynqMP Boot Image */
+	IH_TYPE_FPGA,			/* FPGA Image */
 
-#define IH_TYPE_COUNT		29	/* Number of image types */
+	IH_TYPE_COUNT,			/* Number of image types */
+};
 
 /*
  * Compression Types
+ *
+ * The following are exposed to uImage header.
+ * Do not change values for backward compatibility.
  */
-#define IH_COMP_NONE		0	/*  No	 Compression Used	*/
-#define IH_COMP_GZIP		1	/* gzip	 Compression Used	*/
-#define IH_COMP_BZIP2		2	/* bzip2 Compression Used	*/
-#define IH_COMP_LZMA		3	/* lzma  Compression Used	*/
-#define IH_COMP_LZO		4	/* lzo   Compression Used	*/
-#define IH_COMP_LZ4		5	/* lz4   Compression Used	*/
+enum {
+	IH_COMP_NONE		= 0,	/*  No	 Compression Used	*/
+	IH_COMP_GZIP,			/* gzip	 Compression Used	*/
+	IH_COMP_BZIP2,			/* bzip2 Compression Used	*/
+	IH_COMP_LZMA,			/* lzma  Compression Used	*/
+	IH_COMP_LZO,			/* lzo   Compression Used	*/
+	IH_COMP_LZ4,			/* lz4   Compression Used	*/
+
+	IH_COMP_COUNT,
+};
 
 #define IH_MAGIC	0x27051956	/* Image Magic Number		*/
 #define IH_NMLEN		32	/* Image Name Length		*/
@@ -454,6 +492,40 @@
  */
 const char *genimg_get_comp_short_name(uint8_t comp);
 
+/**
+ * genimg_get_cat_name() - Get the name of an item in a category
+ *
+ * @category:	Category of item
+ * @id:		Item ID
+ * @return name of item, or "Unknown ..." if unknown
+ */
+const char *genimg_get_cat_name(enum ih_category category, uint id);
+
+/**
+ * genimg_get_cat_short_name() - Get the short name of an item in a category
+ *
+ * @category:	Category of item
+ * @id:		Item ID
+ * @return short name of item, or "Unknown ..." if unknown
+ */
+const char *genimg_get_cat_short_name(enum ih_category category, uint id);
+
+/**
+ * genimg_get_cat_count() - Get the number of items in a category
+ *
+ * @category:	Category to check
+ * @return the number of items in the category (IH_xxx_COUNT)
+ */
+int genimg_get_cat_count(enum ih_category category);
+
+/**
+ * genimg_get_cat_desc() - Get the description of a category
+ *
+ * @return the description of a category, e.g. "architecture". This
+ * effectively converts the enum to a string.
+ */
+const char *genimg_get_cat_desc(enum ih_category category);
+
 int genimg_get_os_id(const char *name);
 int genimg_get_arch_id(const char *name);
 int genimg_get_type_id(const char *name);
@@ -1173,4 +1245,21 @@
  */
 int board_fit_config_name_match(const char *name);
 
+#ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS
+/**
+ * board_fit_image_post_process() - Do any post-process on FIT binary data
+ *
+ * This is used to do any sort of image manipulation, verification, decryption
+ * etc. in a platform or board specific way. Obviously, anything done here would
+ * need to be comprehended in how the images were prepared before being injected
+ * into the FIT creation (i.e. the binary blobs would have been pre-processed
+ * before being added to the FIT image).
+ *
+ * @image: pointer to the image start pointer
+ * @size: pointer to the image size
+ * @return no return value (failure should be handled internally)
+ */
+void board_fit_image_post_process(void **p_image, size_t *p_size);
+#endif /* CONFIG_SPL_FIT_IMAGE_POST_PROCESS */
+
 #endif	/* __IMAGE_H__ */
diff --git a/include/libfdt.h b/include/libfdt.h
index 74b1d14..b6a400a 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -284,6 +284,19 @@
 const char *fdt_string(const void *fdt, int stroffset);
 
 /**
+ * fdt_get_max_phandle - retrieves the highest phandle in a tree
+ * @fdt: pointer to the device tree blob
+ *
+ * fdt_get_max_phandle retrieves the highest phandle in the given
+ * device tree
+ *
+ * returns:
+ *      the highest phandle on success
+ *      0, if an error occurred
+ */
+uint32_t fdt_get_max_phandle(const void *fdt);
+
+/**
  * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
  * @fdt: pointer to the device tree blob
  *
@@ -353,6 +366,17 @@
 int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
 
 /**
+ * fdt_path_offset_namelen - find a tree node based on substring
+ * @fdt: pointer to the device tree blob
+ * @path: full path of the node to locate
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_path_offset(), but only examine the first
+ * namelen characters of path for matching the node path.
+ */
+int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
+
+/**
  * fdt_path_offset - find a tree node by its full path
  * @fdt: pointer to the device tree blob
  * @path: full path of the node to locate
@@ -374,7 +398,10 @@
  *	-FDT_ERR_BADSTRUCTURE,
  *	-FDT_ERR_TRUNCATED, standard meanings.
  */
-int fdt_path_offset(const void *fdt, const char *path);
+static inline int fdt_path_offset(const void *fdt, const char *path)
+{
+	return fdt_path_offset_namelen(fdt, path, strlen(path));
+}
 
 /**
  * fdt_get_name - retrieve the name of a given node
@@ -441,6 +468,30 @@
 int fdt_next_property_offset(const void *fdt, int offset);
 
 /**
+ * fdt_for_each_property - iterate over all properties of a node
+ * @property_offset:	property offset (int)
+ * @fdt:		FDT blob (const void *)
+ * @node:		node offset (int)
+ *
+ * This is actually a wrapper around a for loop and would be used like so:
+ *
+ *	fdt_for_each_property(fdt, node, property) {
+ *		...
+ *		use property
+ *		...
+ *	}
+ *
+ * Note that this is implemented as a macro and property is used as
+ * iterator in the loop. It should therefore be a locally allocated
+ * variable. The node variable on the other hand is never modified, so
+ * it can be constant or even a literal.
+ */
+#define fdt_for_each_property_offset(property, fdt, node)	\
+	for (property = fdt_first_property_offset(fdt, node);	\
+	     property >= 0;					\
+	     property = fdt_next_property_offset(fdt, property))
+
+/**
  * fdt_get_property_by_offset - retrieve the property at a given offset
  * @fdt: pointer to the device tree blob
  * @offset: offset of the property to retrieve
@@ -568,6 +619,13 @@
  */
 const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
 				const char *name, int namelen, int *lenp);
+static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
+					  const char *name, int namelen,
+					  int *lenp)
+{
+	return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
+						      namelen, lenp);
+}
 
 /**
  * fdt_getprop - retrieve the value of a given property
@@ -996,6 +1054,27 @@
 /**********************************************************************/
 
 /**
+ * fdt_setprop_inplace_namelen_partial - change a property's value,
+ *                                       but not its size
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @namelen: number of characters of name to consider
+ * @index: index of the property to change in the array
+ * @val: pointer to data to replace the property value with
+ * @len: length of the property value
+ *
+ * Identical to fdt_setprop_inplace(), but modifies the given property
+ * starting from the given index, and using only the first characters
+ * of the name. It is useful when you want to manipulate only one value of
+ * an array and you have a string that doesn't end with \0.
+ */
+int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
+					const char *name, int namelen,
+					uint32_t index, const void *val,
+					int len);
+
+/**
  * fdt_setprop_inplace - change a property's value, but not its size
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to change
@@ -1661,6 +1740,36 @@
  */
 int fdt_del_node(void *fdt, int nodeoffset);
 
+/**
+ * fdt_overlay_apply - Applies a DT overlay on a base DT
+ * @fdt: pointer to the base device tree blob
+ * @fdto: pointer to the device tree overlay blob
+ *
+ * fdt_overlay_apply() will apply the given device tree overlay on the
+ * given base device tree.
+ *
+ * Expect the base device tree to be modified, even if the function
+ * returns an error.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there's not enough space in the base device tree
+ *	-FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or
+ *		properties in the base DT
+ *	-FDT_ERR_BADPHANDLE, the phandles in the overlay do not have the right
+ *		magic
+ *	-FDT_ERR_INTERNAL,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADOFFSET,
+ *	-FDT_ERR_BADPATH,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_overlay_apply(void *fdt, void *fdto);
+
 /**********************************************************************/
 /* Debugging / informational functions                                */
 /**********************************************************************/
diff --git a/include/libfdt_env.h b/include/libfdt_env.h
index 273b5d3..6c6845f 100644
--- a/include/libfdt_env.h
+++ b/include/libfdt_env.h
@@ -23,6 +23,12 @@
 #define fdt64_to_cpu(x)		be64_to_cpu(x)
 #define cpu_to_fdt64(x)		cpu_to_be64(x)
 
+#ifdef __UBOOT__
+#include <vsprintf.h>
+
+#define strtoul(cp, endp, base)	simple_strtoul(cp, endp, base)
+#endif
+
 /* adding a ramdisk needs 0x44 bytes in version 2008.10 */
 #define FDT_RAMDISK_OVERHEAD	0x80
 
diff --git a/include/linux/io.h b/include/linux/io.h
index 1b36a22..a104b7e 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -5,6 +5,22 @@
 #ifndef _LINUX_IO_H
 #define _LINUX_IO_H
 
+#include <linux/compiler.h>
+#include <linux/types.h>
 #include <asm/io.h>
 
+#ifndef CONFIG_HAVE_ARCH_IOREMAP
+static inline void __iomem *ioremap(resource_size_t offset,
+				    resource_size_t size)
+{
+	return (void __iomem *)(unsigned long)offset;
+}
+
+static inline void iounmap(void __iomem *addr)
+{
+}
+
+#define devm_ioremap(dev, offset, size)		ioremap(offset, size)
+#endif
+
 #endif /* _LINUX_IO_H */
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index cf20674..779eea0 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -500,5 +500,10 @@
 int mtd_arg_off_size(int argc, char *const argv[], int *idx, loff_t *off,
 		     loff_t *size, loff_t *maxsize, int devtype,
 		     uint64_t chipsize);
+
+/* drivers/mtd/mtdcore.c */
+void mtd_get_len_incl_bad(struct mtd_info *mtd, uint64_t offset,
+			  const uint64_t length, uint64_t *len_incl_bad,
+			  int *truncated);
 #endif
 #endif /* __MTD_MTD_H__ */
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index b5a02c3..87d72db 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -48,7 +48,7 @@
  * is supported now. If you add a chip with bigger oobsize/page
  * adjust this accordingly.
  */
-#define NAND_MAX_OOBSIZE       1216
+#define NAND_MAX_OOBSIZE       1664
 #define NAND_MAX_PAGESIZE      16384
 
 /*
@@ -590,6 +590,7 @@
  *			flash device
  * @IO_ADDR_W:		[BOARDSPECIFIC] address to write the 8 I/O lines of the
  *			flash device.
+ * @flash_node:		[BOARDSPECIFIC] device node describing this instance
  * @read_byte:		[REPLACEABLE] read one byte from the chip
  * @read_word:		[REPLACEABLE] read one word from the chip
  * @write_byte:		[REPLACEABLE] write a single byte to the chip on the
@@ -689,6 +690,8 @@
 	void __iomem *IO_ADDR_R;
 	void __iomem *IO_ADDR_W;
 
+	int flash_node;
+
 	uint8_t (*read_byte)(struct mtd_info *mtd);
 	u16 (*read_word)(struct mtd_info *mtd);
 	void (*write_byte)(struct mtd_info *mtd, uint8_t byte);
diff --git a/include/linux/mtd/omap_gpmc.h b/include/linux/mtd/omap_gpmc.h
index 3a75674..be3ce9d 100644
--- a/include/linux/mtd/omap_gpmc.h
+++ b/include/linux/mtd/omap_gpmc.h
@@ -92,6 +92,7 @@
 };
 
 /* Used for board specific gpmc initialization */
-extern struct gpmc *gpmc_cfg;
+extern const struct gpmc *gpmc_cfg;
+extern char gpmc_cs0_flash;
 
 #endif /* __ASM_OMAP_GPMC_H */
diff --git a/include/linux/stat.h b/include/linux/stat.h
index cef6369..1af0876 100644
--- a/include/linux/stat.h
+++ b/include/linux/stat.h
@@ -126,7 +126,7 @@
 
 #endif	/* __MIPS__ */
 
-#if defined(__AVR32__) || defined(__SH__)
+#if defined(__AVR32__) || defined(__SH__) || defined(__XTENSA__)
 
 struct stat {
 	unsigned long st_dev;
@@ -149,7 +149,7 @@
 	unsigned long  __unused5;
 };
 
-#endif /* __AVR32__ || __SH__ */
+#endif /* __AVR32__ || __SH__  || __XTENSA__ */
 
 #ifdef __cplusplus
 }
diff --git a/include/linux/types.h b/include/linux/types.h
index 6f75be4..416fa66 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -124,6 +124,10 @@
 typedef		__INT64_TYPE__		int64_t;
 #endif
 
+#ifdef __KERNEL__
+typedef phys_addr_t resource_size_t;
+#endif
+
 /*
  * Below are truly Linux-specific types that should never collide with
  * any application/library that wants linux/types.h.
diff --git a/include/linux/usb/xhci-fsl.h b/include/linux/usb/xhci-fsl.h
index 253eddf..199f366 100644
--- a/include/linux/usb/xhci-fsl.h
+++ b/include/linux/usb/xhci-fsl.h
@@ -51,22 +51,18 @@
 	struct dwc3 *dwc3_reg;
 };
 
-#if defined(CONFIG_LS102XA)
-#define CONFIG_SYS_FSL_XHCI_USB1_ADDR CONFIG_SYS_LS102XA_XHCI_USB1_ADDR
+#if defined(CONFIG_LS102XA) || defined(CONFIG_LS1012A)
+#define CONFIG_SYS_FSL_XHCI_USB1_ADDR CONFIG_SYS_XHCI_USB1_ADDR
 #define CONFIG_SYS_FSL_XHCI_USB2_ADDR 0
 #define CONFIG_SYS_FSL_XHCI_USB3_ADDR 0
 #elif defined(CONFIG_LS2080A)
-#define CONFIG_SYS_FSL_XHCI_USB1_ADDR CONFIG_SYS_LS2080A_XHCI_USB1_ADDR
-#define CONFIG_SYS_FSL_XHCI_USB2_ADDR CONFIG_SYS_LS2080A_XHCI_USB2_ADDR
-#define CONFIG_SYS_FSL_XHCI_USB3_ADDR 0
-#elif defined(CONFIG_LS1043A) || defined(CONFIG_LS1012A)
-#define CONFIG_SYS_FSL_XHCI_USB1_ADDR CONFIG_SYS_LS1043A_XHCI_USB1_ADDR
-#define CONFIG_SYS_FSL_XHCI_USB2_ADDR CONFIG_SYS_LS1043A_XHCI_USB2_ADDR
-#define CONFIG_SYS_FSL_XHCI_USB3_ADDR CONFIG_SYS_LS1043A_XHCI_USB3_ADDR
-#elif defined(CONFIG_LS1012A)
-#define CONFIG_SYS_FSL_XHCI_USB1_ADDR CONFIG_SYS_LS1043A_XHCI_USB1_ADDR
-#define CONFIG_SYS_FSL_XHCI_USB2_ADDR 0
+#define CONFIG_SYS_FSL_XHCI_USB1_ADDR CONFIG_SYS_XHCI_USB1_ADDR
+#define CONFIG_SYS_FSL_XHCI_USB2_ADDR CONFIG_SYS_XHCI_USB2_ADDR
 #define CONFIG_SYS_FSL_XHCI_USB3_ADDR 0
+#elif defined(CONFIG_LS1043A)
+#define CONFIG_SYS_FSL_XHCI_USB1_ADDR CONFIG_SYS_XHCI_USB1_ADDR
+#define CONFIG_SYS_FSL_XHCI_USB2_ADDR CONFIG_SYS_XHCI_USB2_ADDR
+#define CONFIG_SYS_FSL_XHCI_USB3_ADDR CONFIG_SYS_XHCI_USB3_ADDR
 #endif
 
 #define FSL_USB_XHCI_ADDR	{CONFIG_SYS_FSL_XHCI_USB1_ADDR, \
diff --git a/include/miiphy.h b/include/miiphy.h
index af12274..83141b4 100644
--- a/include/miiphy.h
+++ b/include/miiphy.h
@@ -21,13 +21,6 @@
 #include <net.h>
 #include <phy.h>
 
-struct legacy_mii_dev {
-	int (*read)(const char *devname, unsigned char addr,
-		     unsigned char reg, unsigned short *value);
-	int (*write)(const char *devname, unsigned char addr,
-		      unsigned char reg, unsigned short value);
-};
-
 int miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
 		 unsigned short *value);
 int miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
@@ -44,12 +37,6 @@
 
 void miiphy_init(void);
 
-void miiphy_register(const char *devname,
-		      int (*read)(const char *devname, unsigned char addr,
-				   unsigned char reg, unsigned short *value),
-		      int (*write)(const char *devname, unsigned char addr,
-				    unsigned char reg, unsigned short value));
-
 int miiphy_set_current_dev(const char *devname);
 const char *miiphy_get_current_dev(void);
 struct mii_dev *mdio_get_current_dev(void);
@@ -86,10 +73,9 @@
 extern int bb_miiphy_buses_num;
 
 void bb_miiphy_init(void);
-int bb_miiphy_read(const char *devname, unsigned char addr,
-		    unsigned char reg, unsigned short *value);
-int bb_miiphy_write(const char *devname, unsigned char addr,
-		     unsigned char reg, unsigned short value);
+int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg);
+int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg,
+		    u16 value);
 #endif
 
 /* phy seed setup */
diff --git a/include/misc.h b/include/misc.h
index 2b78814..03ef55c 100644
--- a/include/misc.h
+++ b/include/misc.h
@@ -38,6 +38,27 @@
 int misc_ioctl(struct udevice *dev, unsigned long request, void *buf);
 
 /*
+ * Send a message to the device and wait for a response.
+ *
+ * The caller provides the message type/ID and payload to be sent.
+ * The callee constructs any message header required, transmits it to the
+ * target, waits for a response, checks any error code in the response,
+ * strips any message header from the response, and returns the error code
+ * (or a parsed version of it) and the response message payload.
+ *
+ * @dev: the device.
+ * @msgid: the message ID/number to send.
+ * tx_msg: the request/transmit message payload.
+ * tx_size: the size of the buffer pointed at by tx_msg.
+ * rx_msg: the buffer to receive the response message payload. May be NULL if
+ *         the caller only cares about the error code.
+ * rx_size: the size of the buffer pointed at by rx_msg.
+ * @return the response message size if OK, -ve on error
+ */
+int misc_call(struct udevice *dev, int msgid, void *tx_msg, int tx_size,
+	      void *rx_msg, int rx_size);
+
+/*
  * struct misc_ops - Driver model Misc operations
  *
  * The uclass interface is implemented by all miscellaneous devices which
@@ -74,6 +95,20 @@
 	 * @return: 0 if OK, -ve on error
 	 */
 	int (*ioctl)(struct udevice *dev, unsigned long request, void *buf);
+	/*
+	 * Send a message to the device and wait for a response.
+	 *
+	 * @dev: the device
+	 * @msgid: the message ID/number to send
+	 * tx_msg: the request/transmit message payload
+	 * tx_size: the size of the buffer pointed at by tx_msg
+	 * rx_msg: the buffer to receive the response message payload. May be
+	 *         NULL if the caller only cares about the error code.
+	 * rx_size: the size of the buffer pointed at by rx_msg
+	 * @return the response message size if OK, -ve on error
+	 */
+	int (*call)(struct udevice *dev, int msgid, void *tx_msg, int tx_size,
+		    void *rx_msg, int rx_size);
 };
 
 #endif	/* _MISC_H_ */
diff --git a/include/mmc.h b/include/mmc.h
index f383925..aa6d5d1 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -66,12 +66,6 @@
 #define MMC_DATA_READ		1
 #define MMC_DATA_WRITE		2
 
-#define NO_CARD_ERR		-16 /* No SD/MMC card inserted */
-#define UNUSABLE_ERR		-17 /* Unusable Card */
-#define COMM_ERR		-18 /* Communications Error */
-#define TIMEOUT			-19
-#define SWITCH_ERR		-20 /* Card reports failure to switch mode */
-
 #define MMC_CMD_GO_IDLE_STATE		0
 #define MMC_CMD_SEND_OP_COND		1
 #define MMC_CMD_ALL_SEND_CID		2
@@ -323,6 +317,58 @@
 /* forward decl. */
 struct mmc;
 
+#ifdef CONFIG_DM_MMC_OPS
+struct dm_mmc_ops {
+	/**
+	 * send_cmd() - Send a command to the MMC device
+	 *
+	 * @dev:	Device to receive the command
+	 * @cmd:	Command to send
+	 * @data:	Additional data to send/receive
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*send_cmd)(struct udevice *dev, struct mmc_cmd *cmd,
+			struct mmc_data *data);
+
+	/**
+	 * set_ios() - Set the I/O speed/width for an MMC device
+	 *
+	 * @dev:	Device to update
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*set_ios)(struct udevice *dev);
+
+	/**
+	 * get_cd() - See whether a card is present
+	 *
+	 * @dev:	Device to check
+	 * @return 0 if not present, 1 if present, -ve on error
+	 */
+	int (*get_cd)(struct udevice *dev);
+
+	/**
+	 * get_wp() - See whether a card has write-protect enabled
+	 *
+	 * @dev:	Device to check
+	 * @return 0 if write-enabled, 1 if write-protected, -ve on error
+	 */
+	int (*get_wp)(struct udevice *dev);
+};
+
+#define mmc_get_ops(dev)        ((struct dm_mmc_ops *)(dev)->driver->ops)
+
+int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+		    struct mmc_data *data);
+int dm_mmc_set_ios(struct udevice *dev);
+int dm_mmc_get_cd(struct udevice *dev);
+int dm_mmc_get_wp(struct udevice *dev);
+
+/* Transition functions for compatibility */
+int mmc_set_ios(struct mmc *mmc);
+int mmc_getcd(struct mmc *mmc);
+int mmc_getwp(struct mmc *mmc);
+
+#else
 struct mmc_ops {
 	int (*send_cmd)(struct mmc *mmc,
 			struct mmc_cmd *cmd, struct mmc_data *data);
@@ -331,10 +377,13 @@
 	int (*getcd)(struct mmc *mmc);
 	int (*getwp)(struct mmc *mmc);
 };
+#endif
 
 struct mmc_config {
 	const char *name;
+#ifndef CONFIG_DM_MMC_OPS
 	const struct mmc_ops *ops;
+#endif
 	uint host_caps;
 	uint voltages;
 	uint f_min;
@@ -343,7 +392,12 @@
 	unsigned char part_type;
 };
 
-/* TODO struct mmc should be in mmc_private but it's hard to fix right now */
+/*
+ * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device
+ * with mmc_get_mmc_dev().
+ *
+ * TODO struct mmc should be in mmc_private but it's hard to fix right now
+ */
 struct mmc {
 #ifndef CONFIG_BLK
 	struct list_head link;
@@ -443,13 +497,23 @@
 struct mmc *find_mmc_device(int dev_num);
 int mmc_set_dev(int dev_num);
 void print_mmc_devices(char separator);
+
+/**
+ * get_mmc_num() - get the total MMC device number
+ *
+ * @return 0 if there is no MMC device, else the number of devices
+ */
 int get_mmc_num(void);
 int mmc_hwpart_config(struct mmc *mmc, const struct mmc_hwpart_conf *conf,
 		      enum mmc_hwpart_conf_mode mode);
+
+#ifndef CONFIG_DM_MMC_OPS
 int mmc_getcd(struct mmc *mmc);
 int board_mmc_getcd(struct mmc *mmc);
 int mmc_getwp(struct mmc *mmc);
 int board_mmc_getwp(struct mmc *mmc);
+#endif
+
 int mmc_set_dsr(struct mmc *mmc, u16 val);
 /* Function to change the size of boot partition and rpmb partitions */
 int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
diff --git a/include/nand.h b/include/nand.h
index a4f0f92..b6eb223 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -122,6 +122,7 @@
 int nand_get_lock_status(struct mtd_info *mtd, loff_t offset);
 
 int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst);
+int nand_spl_read_block(int block, int offset, int len, void *dst);
 void nand_deselect(void);
 
 #ifdef CONFIG_SYS_NAND_SELECT_DEVICE
@@ -141,3 +142,6 @@
 int get_nand_env_oob(struct mtd_info *mtd, unsigned long *result);
 #endif
 int spl_nand_erase_one(int block, int page);
+
+/* platform specific init functions */
+void sunxi_nand_init(void);
diff --git a/include/net.h b/include/net.h
index 5ee5929..06320c6 100644
--- a/include/net.h
+++ b/include/net.h
@@ -238,7 +238,7 @@
 int eth_setenv_enetaddr(const char *name, const uchar *enetaddr);
 
 /**
- * eth_setenv_enetaddr_by_index() - set the MAC address envrionment variable
+ * eth_setenv_enetaddr_by_index() - set the MAC address environment variable
  *
  * This sets up an environment variable with the given MAC address (@enetaddr).
  * The environment variable to be set is defined by <@base_name><@index>addr.
diff --git a/include/nuvoton_nct6102d.h b/include/nuvoton_nct6102d.h
new file mode 100644
index 0000000..a122550
--- /dev/null
+++ b/include/nuvoton_nct6102d.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _NUVOTON_NCT6102D_H_
+#define _NUVOTON_NCT6102D_H_
+
+/* I/O address of Nuvoton Super IO chip */
+#define NCT6102D_IO_PORT	0x4e
+
+/* Extended Function Enable Registers */
+#define NCT_EFER (NCT6102D_IO_PORT + 0)
+/* Extended Function Index Register (same as EFER) */
+#define NCT_EFIR (NCT6102D_IO_PORT + 0)
+/* Extended Function Data Register */
+#define NCT_EFDR (NCT_EFIR + 1)
+
+#define NCT_LD_SELECT_REG	0x07
+
+/* Logical device number */
+#define NCT6102D_LD_UARTA	0x02
+#define NCT6102D_LD_WDT		0x08
+
+#define NCT6102D_UARTA_ENABLE	0x30
+#define NCT6102D_WDT_TIMEOUT	0xf1
+
+#define NCT_ENTRY_KEY		0x87
+#define NCT_EXIT_KEY		0xaa
+
+int nct6102d_wdt_disable(void);
+
+#endif /* _NUVOTON_NCT6102D_H_ */
diff --git a/include/onenand_uboot.h b/include/onenand_uboot.h
index fd01040..995f0aa 100644
--- a/include/onenand_uboot.h
+++ b/include/onenand_uboot.h
@@ -26,7 +26,7 @@
 extern struct onenand_chip onenand_chip;
 
 /* board */
-extern void onenand_board_init(struct mtd_info *);
+extern int onenand_board_init(struct mtd_info *);
 
 /* Functions */
 extern void onenand_init(void);
@@ -49,6 +49,7 @@
 					int boundary, int lock);
 
 /* SPL */
+int onenand_spl_read_block(int block, int offset, int len, void *dst);
 void onenand_spl_load_image(uint32_t offs, uint32_t size, void *dst);
 
 #endif /* __UBOOT_ONENAND_H */
diff --git a/include/os.h b/include/os.h
index 954a48c..1782e50 100644
--- a/include/os.h
+++ b/include/os.h
@@ -287,6 +287,31 @@
 int os_jump_to_image(const void *dest, int size);
 
 /**
+ * os_find_u_boot() - Determine the path to U-Boot proper
+ *
+ * This function is intended to be called from within sandbox SPL. It uses
+ * a few heuristics to find U-Boot proper. Normally it is either in the same
+ * directory, or the directory above (since u-boot-spl is normally in an
+ * spl/ subdirectory when built).
+ *
+ * @fname:	Place to put full path to U-Boot
+ * @maxlen:	Maximum size of @fname
+ * @return 0 if OK, -NOSPC if the filename is too large, -ENOENT if not found
+ */
+int os_find_u_boot(char *fname, int maxlen);
+
+/**
+ * os_spl_to_uboot() - Run U-Boot proper
+ *
+ * When called from SPL, this runs U-Boot proper. The filename is obtained by
+ * calling os_find_u_boot().
+ *
+ * @fname:	Full pathname to U-Boot executable
+ * @return 0 if OK, -ve on error
+ */
+int os_spl_to_uboot(const char *fname);
+
+/**
  * Read the current system time
  *
  * This reads the current Local Time and places it into the provided
diff --git a/include/power-domain-uclass.h b/include/power-domain-uclass.h
new file mode 100644
index 0000000..5878021
--- /dev/null
+++ b/include/power-domain-uclass.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _POWER_DOMAIN_UCLASS_H
+#define _POWER_DOMAIN_UCLASS_H
+
+/* See power-domain.h for background documentation. */
+
+#include <power-domain.h>
+
+struct udevice;
+
+/**
+ * struct power_domain_ops - The functions that a power domain controller driver
+ * must implement.
+ */
+struct power_domain_ops {
+	/**
+	 * of_xlate - Translate a client's device-tree (OF) power domain
+	 * specifier.
+	 *
+	 * The power domain core calls this function as the first step in
+	 * implementing a client's power_domain_get() call.
+	 *
+	 * If this function pointer is set to NULL, the power domain core will
+	 * use a default implementation, which assumes #power-domain-cells =
+	 * <1>, and that the DT cell contains a simple integer power domain ID.
+	 *
+	 * At present, the power domain API solely supports device-tree. If
+	 * this changes, other xxx_xlate() functions may be added to support
+	 * those other mechanisms.
+	 *
+	 * @power_domain:	The power domain struct to hold the
+	 *			translation result.
+	 * @args:		The power domain specifier values from device
+	 *			tree.
+	 * @return 0 if OK, or a negative error code.
+	 */
+	int (*of_xlate)(struct power_domain *power_domain,
+			struct fdtdec_phandle_args *args);
+	/**
+	 * request - Request a translated power domain.
+	 *
+	 * The power domain core calls this function as the second step in
+	 * implementing a client's power_domain_get() call, following a
+	 * successful xxx_xlate() call.
+	 *
+	 * @power_domain:	The power domain to request; this has been
+	 *			filled in by a previous xxx_xlate() function
+	 *			call.
+	 * @return 0 if OK, or a negative error code.
+	 */
+	int (*request)(struct power_domain *power_domain);
+	/**
+	 * free - Free a previously requested power domain.
+	 *
+	 * This is the implementation of the client power_domain_free() API.
+	 *
+	 * @power_domain:	The power domain to free.
+	 * @return 0 if OK, or a negative error code.
+	 */
+	int (*free)(struct power_domain *power_domain);
+	/**
+	 * on - Power on a power domain.
+	 *
+	 * @power_domain:	The power domain to turn on.
+	 * @return 0 if OK, or a negative error code.
+	 */
+	int (*on)(struct power_domain *power_domain);
+	/**
+	 * off - Power off a power domain.
+	 *
+	 * @power_domain:	The power domain to turn off.
+	 * @return 0 if OK, or a negative error code.
+	 */
+	int (*off)(struct power_domain *power_domain);
+};
+
+#endif
diff --git a/include/power-domain.h b/include/power-domain.h
new file mode 100644
index 0000000..1099979
--- /dev/null
+++ b/include/power-domain.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _POWER_DOMAIN_H
+#define _POWER_DOMAIN_H
+
+/**
+ * A power domain is a portion of an SoC or chip that is powered by a
+ * switchable source of power. In many cases, software has control over the
+ * power domain, and can turn the power source on or off. This is typically
+ * done to save power by powering off unused devices, or to enable software
+ * sequencing of initial powerup at boot. This API provides a means for
+ * drivers to turn power domains on and off.
+ *
+ * A driver that implements UCLASS_POWER_DOMAIN is a power domain controller or
+ * provider. A controller will often implement multiple separate power domains,
+ * since the hardware it manages often has this capability.
+ * power-domain-uclass.h describes the interface which power domain controllers
+ * must implement.
+ *
+ * Depending on the power domain controller hardware, changing the state of a
+ * power domain may require performing related operations on other resources.
+ * For example, some power domains may require certain clocks to be enabled
+ * whenever the power domain is powered on, or during the time when the power
+ * domain is transitioning state. These details are implementation-specific
+ * and should ideally be encapsulated entirely within the provider driver, or
+ * configured through mechanisms (e.g. device tree) that do not require client
+ * drivers to provide extra configuration information.
+ *
+ * Power domain consumers/clients are the drivers for HW modules within the
+ * power domain. This header file describes the API used by those drivers.
+ *
+ * In many cases, a single complex IO controller (e.g. a PCIe controller) will
+ * be the sole logic contained within a power domain. In such cases, it is
+ * logical for the relevant device driver to directly control that power
+ * domain. In other cases, multiple controllers, each with their own driver,
+ * may be contained in a single power domain. Any logic require to co-ordinate
+ * between drivers for these multiple controllers is beyond the scope of this
+ * API at present. Equally, this API does not define or implement any policy
+ * by which power domains are managed.
+ */
+
+struct udevice;
+
+/**
+ * struct power_domain - A handle to (allowing control of) a single power domain.
+ *
+ * Clients provide storage for power domain handles. The content of the
+ * structure is managed solely by the power domain API and power domain
+ * drivers. A power domain struct is initialized by "get"ing the power domain
+ * struct. The power domain struct is passed to all other power domain APIs to
+ * identify which power domain to operate upon.
+ *
+ * @dev: The device which implements the power domain.
+ * @id: The power domain ID within the provider.
+ *
+ * Currently, the power domain API assumes that a single integer ID is enough
+ * to identify and configure any power domain for any power domain provider. If
+ * this assumption becomes invalid in the future, the struct could be expanded
+ * to either (a) add more fields to allow power domain providers to store
+ * additional information, or (b) replace the id field with an opaque pointer,
+ * which the provider would dynamically allocate during its .of_xlate op, and
+ * process during is .request op. This may require the addition of an extra op
+ * to clean up the allocation.
+ */
+struct power_domain {
+	struct udevice *dev;
+	/*
+	 * Written by of_xlate. We assume a single id is enough for now. In the
+	 * future, we might add more fields here.
+	 */
+	unsigned long id;
+};
+
+/**
+ * power_domain_get - Get/request the power domain for a device.
+ *
+ * This looks up and requests a power domain. Each device is assumed to have
+ * a single (or, at least one) power domain associated with it somehow, and
+ * that domain, or the first/default domain. The mapping of client device to
+ * provider power domain may be via device-tree properties, board-provided
+ * mapping tables, or some other mechanism.
+ *
+ * @dev:	The client device.
+ * @power_domain	A pointer to a power domain struct to initialize.
+ * @return 0 if OK, or a negative error code.
+ */
+int power_domain_get(struct udevice *dev, struct power_domain *power_domain);
+
+/**
+ * power_domain_free - Free a previously requested power domain.
+ *
+ * @power_domain:	A power domain struct that was previously successfully
+ *		requested by power_domain_get().
+ * @return 0 if OK, or a negative error code.
+ */
+int power_domain_free(struct power_domain *power_domain);
+
+/**
+ * power_domain_on - Enable power to a power domain.
+ *
+ * @power_domain:	A power domain struct that was previously successfully
+ *		requested by power_domain_get().
+ * @return 0 if OK, or a negative error code.
+ */
+int power_domain_on(struct power_domain *power_domain);
+
+/**
+ * power_domain_off - Disable power ot a power domain.
+ *
+ * @power_domain:	A power domain struct that was previously successfully
+ *		requested by power_domain_get().
+ * @return 0 if OK, or a negative error code.
+ */
+int power_domain_off(struct power_domain *power_domain);
+
+#endif
diff --git a/include/power/regulator.h b/include/power/regulator.h
index 63c0814..9bcd728 100644
--- a/include/power/regulator.h
+++ b/include/power/regulator.h
@@ -54,7 +54,7 @@
  * which does the scan on the device node, for the 'regulator-name' constraint.
  * If the parent is not a PMIC device, and the child is not bind by function:
  * 'pmic_bind_childs()', then it's recommended to bind the device by call to
- * dm_scan_fdt_node() - this is usually done automatically for bus devices,
+ * dm_scan_fdt_dev() - this is usually done automatically for bus devices,
  * as a post bind method.
  *
  * Regulator get:
diff --git a/include/regmap.h b/include/regmap.h
index eccf770..1eed94e 100644
--- a/include/regmap.h
+++ b/include/regmap.h
@@ -57,6 +57,22 @@
 int regmap_init_mem(struct udevice *dev, struct regmap **mapp);
 
 /**
+ * regmap_init_mem_platdata() - Set up a new memory register map for of-platdata
+ *
+ * This creates a new regmap with a list of regions passed in, rather than
+ * using the device tree. It only supports 32-bit machines.
+ *
+ * Use regmap_uninit() to free it.
+ *
+ * @dev:	Device that uses this map
+ * @reg:	List of address, size pairs
+ * @count:	Number of pairs (e.g. 1 if the regmap has a single entry)
+ * @mapp:	Returns allocated map
+ */
+int regmap_init_mem_platdata(struct udevice *dev, u32 *reg, int count,
+			     struct regmap **mapp);
+
+/**
  * regmap_get_range() - Obtain the base memory address of a regmap range
  *
  * @map:	Regmap to query
diff --git a/include/sdhci.h b/include/sdhci.h
index e0f6667..6844c73 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -166,6 +166,8 @@
 #define  SDHCI_CAN_64BIT	0x10000000
 
 #define SDHCI_CAPABILITIES_1	0x44
+#define  SDHCI_CLOCK_MUL_MASK	0x00FF0000
+#define  SDHCI_CLOCK_MUL_SHIFT	16
 
 #define SDHCI_MAX_CURRENT	0x48
 
@@ -338,5 +340,78 @@
 }
 #endif
 
+#ifdef CONFIG_BLK
+/**
+ * sdhci_setup_cfg() - Set up the configuration for DWMMC
+ *
+ * This is used to set up an SDHCI device when you are using CONFIG_BLK.
+ *
+ * This should be called from your MMC driver's probe() method once you have
+ * the information required.
+ *
+ * Generally your driver will have a platform data structure which holds both
+ * the configuration (struct mmc_config) and the MMC device info (struct mmc).
+ * For example:
+ *
+ * struct msm_sdhc_plat {
+ *	struct mmc_config cfg;
+ *	struct mmc mmc;
+ * };
+ *
+ * ...
+ *
+ * Inside U_BOOT_DRIVER():
+ *	.platdata_auto_alloc_size = sizeof(struct msm_sdhc_plat),
+ *
+ * To access platform data:
+ *	struct msm_sdhc_plat *plat = dev_get_platdata(dev);
+ *
+ * See msm_sdhci.c for an example.
+ *
+ * @cfg:	Configuration structure to fill in (generally &plat->mmc)
+ * @host:	SDHCI host structure
+ * @max_clk:	Maximum supported clock speed in HZ (0 for default)
+ * @min_clk:	Minimum supported clock speed in HZ (0 for default)
+ */
+int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
+		    u32 max_clk, u32 min_clk);
+
+/**
+ * sdhci_bind() - Set up a new MMC block device
+ *
+ * This is used to set up an SDHCI block device when you are using CONFIG_BLK.
+ * It should be called from your driver's bind() method.
+ *
+ * See msm_sdhci.c for an example.
+ *
+ * @dev:	Device to set up
+ * @mmc:	Pointer to mmc structure (normally &plat->mmc)
+ * @cfg:	Empty configuration structure (generally &plat->cfg). This is
+ *		normally all zeroes at this point. The only purpose of passing
+ *		this in is to set mmc->cfg to it.
+ * @return 0 if OK, -ve if the block device could not be created
+ */
+int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg);
+#else
+
+/**
+ * add_sdhci() - Add a new SDHCI interface
+ *
+ * This is used when you are not using CONFIG_BLK. Convert your driver over!
+ *
+ * @host:	SDHCI host structure
+ * @max_clk:	Maximum supported clock speed in HZ (0 for default)
+ * @min_clk:	Minimum supported clock speed in HZ (0 for default)
+ * @return 0 if OK, -ve on error
+ */
 int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk);
+#endif /* !CONFIG_BLK */
+
+#ifdef CONFIG_DM_MMC_OPS
+/* Export the operations to drivers */
+int sdhci_probe(struct udevice *dev);
+extern const struct dm_mmc_ops sdhci_ops;
+#else
+#endif
+
 #endif /* __SDHCI_HW_H */
diff --git a/include/spl.h b/include/spl.h
index 2360466..8afa085 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -71,6 +71,7 @@
 int spl_parse_image_header(const struct image_header *header);
 void spl_board_prepare_for_linux(void);
 void spl_board_prepare_for_boot(void);
+int spl_board_ubi_load_image(u32 boot_device);
 void __noreturn jump_to_image_linux(void *arg);
 int spl_start_uboot(void);
 void spl_display_print(void);
@@ -84,6 +85,9 @@
 /* NOR SPL functions */
 int spl_nor_load_image(void);
 
+/* UBI SPL functions */
+int spl_ubi_load_image(u32 boot_device);
+
 /* MMC SPL functions */
 int spl_mmc_load_image(u32 boot_device);
 
diff --git a/include/splash.h b/include/splash.h
index 25df1cf..136eac7 100644
--- a/include/splash.h
+++ b/include/splash.h
@@ -47,7 +47,16 @@
 	char *ubivol;	/* UBI volume-name for ubifsmount */
 };
 
+#ifdef CONFIG_SPLASH_SOURCE
 int splash_source_load(struct splash_location *locations, uint size);
+#else
+static inline int splash_source_load(struct splash_location *locations,
+				     uint size)
+{
+	return 0;
+}
+#endif
+
 int splash_screen_prepare(void);
 
 #ifdef CONFIG_SPLASH_SCREEN_ALIGN
diff --git a/include/syscon.h b/include/syscon.h
index 4593b6e..34842aa 100644
--- a/include/syscon.h
+++ b/include/syscon.h
@@ -23,6 +23,17 @@
 
 #define syscon_get_ops(dev)        ((struct syscon_ops *)(dev)->driver->ops)
 
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+/*
+ * We don't support 64-bit machines. If they are so resource-contrained that
+ * they need to use OF_PLATDATA, something is horribly wrong with the
+ * education of our hardware engineers.
+ */
+struct syscon_base_platdata {
+	u32 reg[2];
+};
+#endif
+
 /**
  * syscon_get_regmap() - Get access to a register map
  *
diff --git a/include/test/overlay.h b/include/test/overlay.h
new file mode 100644
index 0000000..392f28f
--- /dev/null
+++ b/include/test/overlay.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __TEST_OVERLAY_H__
+#define __TEST_OVERLAY_H__
+
+#include <test/test.h>
+
+/* Declare a new environment test */
+#define OVERLAY_TEST(_name, _flags)	UNIT_TEST(_name, _flags, overlay_test)
+
+#endif /* __TEST_OVERLAY_H__ */
diff --git a/include/test/suites.h b/include/test/suites.h
index f579033..0e94feb 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -10,6 +10,7 @@
 
 int do_ut_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_time(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 
 #endif /* __TEST_SUITES_H__ */
diff --git a/include/ubispl.h b/include/ubispl.h
new file mode 100644
index 0000000..944653e
--- /dev/null
+++ b/include/ubispl.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) Thomas Gleixner <tglx@linutronix.de>
+ *
+ * SPDX-License-Identifier: GPL 2.0+ BSD-3-Clause
+ */
+#ifndef __UBOOT_UBISPL_H
+#define __UBOOT_UBISPL_H
+
+/*
+ * The following CONFIG options are relevant for UBISPL
+ *
+ * #define CONFIG_SPL_UBI_MAX_VOL_LEBS		256
+ *
+ * Defines the maximum number of logical erase blocks per loadable
+ * (static) volume to size the ubispl internal arrays.
+ *
+ * #define CONFIG_SPL_UBI_MAX_PEB_SIZE		(256*1024)
+ *
+ * Defines the maximum physical erase block size to size the fastmap
+ * buffer for ubispl.
+ *
+ * #define CONFIG_SPL_UBI_MAX_PEBS		4096
+ *
+ * Define the maximum number of physical erase blocks to size the
+ * ubispl internal arrays.
+ *
+ * #define CONFIG_SPL_UBI_VOL_IDS		8
+ *
+ * Defines the maximum number of volumes in which UBISPL is
+ * interested. Limits the amount of memory for the scan data and
+ * speeds up the scan process as we simply ignore stuff which we dont
+ * want to load from the SPL anyway. So the volumes which can be
+ * loaded in the above example are ids 0 - 7
+ */
+
+/*
+ * The struct definition is in drivers/mtd/ubispl/ubispl.h. It does
+ * not fit into the BSS due to the large buffer requirement of the
+ * upstream fastmap code. So the caller of ubispl_load_volumes needs
+ * to hand in a pointer to a free memory area where ubispl will place
+ * its data. The area is not required to be initialized.
+ */
+struct ubi_scan_info;
+
+typedef int (*ubispl_read_flash)(int pnum, int offset, int len, void *dst);
+
+/**
+ * struct ubispl_info - description structure for fast ubi scan
+ * @ubi:		Pointer to memory space for ubi scan info structure
+ * @peb_size:		Physical erase block size
+ * @vid_offset:		Offset of the VID header
+ * @leb_start:		Start of the logical erase block, i.e. offset of data
+ * @peb_count:		Number of physical erase blocks in the UBI FLASH area
+ *			aka MTD partition.
+ * @peb_offset:		Offset of PEB0 in the UBI FLASH area (aka MTD partition)
+ *			to the real start of the FLASH in erase blocks.
+ * @fastmap:		Enable fastmap attachment
+ * @read:		Read function to access the flash
+ */
+struct ubispl_info {
+	struct ubi_scan_info	*ubi;
+	u32			peb_size;
+	u32			vid_offset;
+	u32			leb_start;
+	u32			peb_count;
+	u32			peb_offset;
+	int			fastmap;
+	ubispl_read_flash	read;
+};
+
+/**
+ * struct ubispl_load - structure to describe a volume to load
+ * @vol_id:	Volume id
+ * @load_addr:	Load address of the volume
+ */
+struct ubispl_load {
+	int		vol_id;
+	void		*load_addr;
+};
+
+/**
+ * ubispl_load_volumes - Scan flash and load volumes
+ * @info:	Pointer to the ubi scan info structure
+ * @lovls:	Pointer to array of volumes to load
+ * @nrvols:	Array size of @lovls
+ */
+int ubispl_load_volumes(struct ubispl_info *info,
+			struct ubispl_load *lvols, int nrvols);
+
+#endif
diff --git a/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h
index 302e9a3..7324d8a 100644
--- a/include/usb/dwc2_udc.h
+++ b/include/usb/dwc2_udc.h
@@ -12,12 +12,17 @@
 #define PHY0_SLEEP              (1 << 5)
 
 struct dwc2_plat_otg_data {
+	void		*priv;
+	int		phy_of_node;
 	int		(*phy_control)(int on);
 	unsigned int	regs_phy;
 	unsigned int	regs_otg;
 	unsigned int    usb_phy_ctrl;
 	unsigned int    usb_flags;
 	unsigned int	usb_gusbcfg;
+	unsigned int	rx_fifo_sz;
+	unsigned int	np_tx_fifo_sz;
+	unsigned int	tx_fifo_sz;
 };
 
 int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata);
diff --git a/include/usb/ehci-ci.h b/include/usb/ehci-ci.h
index 586d32a..882aed4 100644
--- a/include/usb/ehci-ci.h
+++ b/include/usb/ehci-ci.h
@@ -160,7 +160,7 @@
 #define CONFIG_SYS_FSL_USB1_ADDR CONFIG_SYS_MPC512x_USB1_ADDR
 #define CONFIG_SYS_FSL_USB2_ADDR	0
 #elif defined(CONFIG_LS102XA)
-#define CONFIG_SYS_FSL_USB1_ADDR CONFIG_SYS_LS102XA_USB1_ADDR
+#define CONFIG_SYS_FSL_USB1_ADDR CONFIG_SYS_EHCI_USB1_ADDR
 #define CONFIG_SYS_FSL_USB2_ADDR        0
 #endif
 
diff --git a/include/vsprintf.h b/include/vsprintf.h
index 376f5dd..60e91d1 100644
--- a/include/vsprintf.h
+++ b/include/vsprintf.h
@@ -8,6 +8,8 @@
 #ifndef __VSPRINTF_H
 #define __VSPRINTF_H
 
+#include <stdarg.h>
+
 ulong simple_strtoul(const char *cp, char **endp, unsigned int base);
 
 /**
diff --git a/lib/Kconfig b/lib/Kconfig
index 02ca405..16ff01a 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -139,6 +139,11 @@
 	  particular compatible nodes. The library operates on a flattened
 	  version of the device tree.
 
+config OF_LIBFDT_OVERLAY
+	bool "Enable the FDT library overlay support"
+	help
+	  This enables the FDT library (libfdt) overlay support.
+
 config SPL_OF_LIBFDT
 	bool "Enable the FDT library for SPL"
 	default y if SPL_OF_CONTROL
diff --git a/lib/Makefile b/lib/Makefile
index f48d901..f6a8ba1 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -48,11 +48,10 @@
 obj-$(CONFIG_$(SPL_)SHA256) += sha256.o
 
 obj-$(CONFIG_$(SPL_)OF_LIBFDT) += libfdt/
-ifdef CONFIG_SPL_OF_CONTROL
-obj-$(CONFIG_OF_LIBFDT) += libfdt/
-endif
+ifneq ($(CONFIG_SPL_BUILD)$(CONFIG_SPL_OF_PLATDATA),yy)
 obj-$(CONFIG_$(SPL_)OF_CONTROL) += fdtdec_common.o
 obj-$(CONFIG_$(SPL_)OF_CONTROL) += fdtdec.o
+endif
 
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16.o
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index c434c92..d8ddcc9 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -31,6 +31,8 @@
 	struct efi_device_path_file_path *dp;
 	/* Offset into disk for simple partitions */
 	lbaint_t offset;
+	/* Internal block device */
+	const struct blk_desc *desc;
 };
 
 static efi_status_t efi_disk_open_block(void *handle, efi_guid_t *protocol,
@@ -78,8 +80,7 @@
 	unsigned long n;
 
 	diskobj = container_of(this, struct efi_disk_obj, ops);
-	if (!(desc = blk_get_dev(diskobj->ifname, diskobj->dev_index)))
-		return EFI_EXIT(EFI_DEVICE_ERROR);
+	desc = (struct blk_desc *) diskobj->desc;
 	blksz = desc->blksz;
 	blocks = buffer_size / blksz;
 	lba += diskobj->offset;
@@ -201,6 +202,10 @@
 	struct efi_device_path_file_path *dp;
 	int objlen = sizeof(*diskobj) + (sizeof(*dp) * 2);
 
+	/* Don't add empty devices */
+	if (!desc->lba)
+		return;
+
 	diskobj = calloc(1, objlen);
 
 	/* Fill in object data */
@@ -213,13 +218,14 @@
 	diskobj->ifname = if_typename;
 	diskobj->dev_index = dev_index;
 	diskobj->offset = offset;
+	diskobj->desc = desc;
 
 	/* Fill in EFI IO Media info (for read/write callbacks) */
 	diskobj->media.removable_media = desc->removable;
 	diskobj->media.media_present = 1;
 	diskobj->media.block_size = desc->blksz;
 	diskobj->media.io_align = desc->blksz;
-	diskobj->media.last_block = desc->lba;
+	diskobj->media.last_block = desc->lba - offset;
 	diskobj->ops.media = &diskobj->media;
 
 	/* Fill in device path */
@@ -240,7 +246,8 @@
 
 static int efi_disk_create_eltorito(struct blk_desc *desc,
 				    const char *if_typename,
-				    int diskid)
+				    int diskid,
+				    const char *pdevname)
 {
 	int disks = 0;
 #ifdef CONFIG_ISO_PARTITION
@@ -252,8 +259,8 @@
 		return 0;
 
 	while (!part_get_info(desc, part, &info)) {
-		snprintf(devname, sizeof(devname), "%s%d:%d", if_typename,
-			 diskid, part);
+		snprintf(devname, sizeof(devname), "%s:%d", pdevname,
+			 part);
 		efi_disk_add_dev(devname, if_typename, desc, diskid,
 				 info.start);
 		part++;
@@ -296,7 +303,7 @@
 		* so let's create them here
 		*/
 		disks += efi_disk_create_eltorito(desc, if_typename,
-						  desc->devnum);
+						  desc->devnum, dev->name);
 	}
 #else
 	int i, if_type;
@@ -331,7 +338,8 @@
 			 * El Torito images show up as block devices
 			 * in an EFI world, so let's create them here
 			 */
-			disks += efi_disk_create_eltorito(desc, if_typename, i);
+			disks += efi_disk_create_eltorito(desc, if_typename,
+							  i, devname);
 		}
 	}
 #endif
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index 574b204..5165377 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -37,7 +37,7 @@
 		const uint16_t *relocs = (const uint16_t *)(rel + 1);
 		i = (rel->SizeOfBlock - sizeof(*rel)) / sizeof(uint16_t);
 		while (i--) {
-			uint16_t offset = (*relocs & 0xfff) +
+			uint32_t offset = (uint32_t)(*relocs & 0xfff) +
 					  rel->VirtualAddress;
 			int type = *relocs >> EFI_PAGE_SHIFT;
 			unsigned long delta = (unsigned long)efi_reloc;
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index df2381e..df3547c 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -130,6 +130,9 @@
 	bool carve_again;
 	uint64_t carved_pages = 0;
 
+	debug("%s: 0x%" PRIx64 " 0x%" PRIx64 " %d %s\n", __func__,
+	      start, pages, memory_type, overlap_only_ram ? "yes" : "no");
+
 	if (!pages)
 		return start;
 
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 0534c0b..e638ca5 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -9,6 +9,7 @@
 #include <errno.h>
 #include <serial.h>
 #include <libfdt.h>
+#include <fdt_support.h>
 #include <fdtdec.h>
 #include <asm/sections.h>
 #include <linux/ctype.h>
@@ -19,6 +20,11 @@
  * Here are the type we know about. One day we might allow drivers to
  * register. For now we just put them here. The COMPAT macro allows us to
  * turn this into a sparse list later, and keeps the ID with the name.
+ *
+ * NOTE: This list is basically a TODO list for things that need to be
+ * converted to driver model. So don't add new things here unless there is a
+ * good reason why driver-model conversion is infeasible. Examples include
+ * things which are used before driver model is available.
  */
 #define COMPAT(id, name) name
 static const char * const compat_names[COMPAT_COUNT] = {
@@ -39,13 +45,10 @@
 	COMPAT(SAMSUNG_S3C2440_I2C, "samsung,s3c2440-i2c"),
 	COMPAT(SAMSUNG_EXYNOS5_SOUND, "samsung,exynos-sound"),
 	COMPAT(WOLFSON_WM8994_CODEC, "wolfson,wm8994-codec"),
-	COMPAT(GOOGLE_CROS_EC_KEYB, "google,cros-ec-keyb"),
 	COMPAT(SAMSUNG_EXYNOS_USB_PHY, "samsung,exynos-usb-phy"),
 	COMPAT(SAMSUNG_EXYNOS5_USB3_PHY, "samsung,exynos5250-usb3-phy"),
 	COMPAT(SAMSUNG_EXYNOS_TMU, "samsung,exynos-tmu"),
-	COMPAT(SAMSUNG_EXYNOS_FIMD, "samsung,exynos-fimd"),
 	COMPAT(SAMSUNG_EXYNOS_MIPI_DSI, "samsung,exynos-mipi-dsi"),
-	COMPAT(SAMSUNG_EXYNOS5_DP, "samsung,exynos5-dp"),
 	COMPAT(SAMSUNG_EXYNOS_DWMMC, "samsung,exynos-dwmmc"),
 	COMPAT(SAMSUNG_EXYNOS_MMC, "samsung,exynos-mmc"),
 	COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686"),
@@ -54,20 +57,16 @@
 	COMPAT(SAMSUNG_EXYNOS5_I2C, "samsung,exynos5-hsi2c"),
 	COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"),
 	COMPAT(INTEL_MICROCODE, "intel,microcode"),
-	COMPAT(INTEL_PANTHERPOINT_AHCI, "intel,pantherpoint-ahci"),
-	COMPAT(INTEL_MODEL_206AX, "intel,model-206ax"),
-	COMPAT(INTEL_GMA, "intel,gma"),
 	COMPAT(AMS_AS3722, "ams,as3722"),
-	COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
 	COMPAT(INTEL_QRK_MRC, "intel,quark-mrc"),
 	COMPAT(SOCIONEXT_XHCI, "socionext,uniphier-xhci"),
-	COMPAT(COMPAT_INTEL_PCH, "intel,bd82x6x"),
 	COMPAT(ALTERA_SOCFPGA_DWMAC, "altr,socfpga-stmmac"),
 	COMPAT(ALTERA_SOCFPGA_DWMMC, "altr,socfpga-dw-mshc"),
 	COMPAT(ALTERA_SOCFPGA_DWC2USB, "snps,dwc2"),
-	COMPAT(COMPAT_INTEL_BAYTRAIL_FSP, "intel,baytrail-fsp"),
-	COMPAT(COMPAT_INTEL_BAYTRAIL_FSP_MDP, "intel,baytrail-fsp-mdp"),
-	COMPAT(COMPAT_INTEL_IVYBRIDGE_FSP, "intel,ivybridge-fsp"),
+	COMPAT(INTEL_BAYTRAIL_FSP, "intel,baytrail-fsp"),
+	COMPAT(INTEL_BAYTRAIL_FSP_MDP, "intel,baytrail-fsp-mdp"),
+	COMPAT(INTEL_IVYBRIDGE_FSP, "intel,ivybridge-fsp"),
+	COMPAT(COMPAT_SUNXI_NAND, "allwinner,sun4i-a10-nand"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
@@ -79,7 +78,7 @@
 
 fdt_addr_t fdtdec_get_addr_size_fixed(const void *blob, int node,
 		const char *prop_name, int index, int na, int ns,
-		fdt_size_t *sizep)
+		fdt_size_t *sizep, bool translate)
 {
 	const fdt32_t *prop, *prop_end;
 	const fdt32_t *prop_addr, *prop_size, *prop_after_size;
@@ -114,7 +113,12 @@
 		return FDT_ADDR_T_NONE;
 	}
 
-	addr = fdtdec_get_number(prop_addr, na);
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_OF_LIBFDT)
+	if (translate)
+		addr = fdt_translate_address(blob, node, prop_addr);
+	else
+#endif
+		addr = fdtdec_get_number(prop_addr, na);
 
 	if (sizep) {
 		*sizep = fdtdec_get_number(prop_size, ns);
@@ -128,7 +132,8 @@
 }
 
 fdt_addr_t fdtdec_get_addr_size_auto_parent(const void *blob, int parent,
-		int node, const char *prop_name, int index, fdt_size_t *sizep)
+		int node, const char *prop_name, int index, fdt_size_t *sizep,
+		bool translate)
 {
 	int na, ns;
 
@@ -149,11 +154,12 @@
 	debug("na=%d, ns=%d, ", na, ns);
 
 	return fdtdec_get_addr_size_fixed(blob, node, prop_name, index, na,
-					  ns, sizep);
+					  ns, sizep, translate);
 }
 
 fdt_addr_t fdtdec_get_addr_size_auto_noparent(const void *blob, int node,
-		const char *prop_name, int index, fdt_size_t *sizep)
+		const char *prop_name, int index, fdt_size_t *sizep,
+		bool translate)
 {
 	int parent;
 
@@ -166,7 +172,7 @@
 	}
 
 	return fdtdec_get_addr_size_auto_parent(blob, parent, node, prop_name,
-						index, sizep);
+						index, sizep, translate);
 }
 
 fdt_addr_t fdtdec_get_addr_size(const void *blob, int node,
@@ -176,7 +182,7 @@
 
 	return fdtdec_get_addr_size_fixed(blob, node, prop_name, 0,
 					  sizeof(fdt_addr_t) / sizeof(fdt32_t),
-					  ns, sizep);
+					  ns, sizep, false);
 }
 
 fdt_addr_t fdtdec_get_addr(const void *blob, int node,
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 02b4105..4e52b36 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -602,8 +602,8 @@
 		return (-1);
 	}
 
-	debug("EXPORT  table = %p, htab.size = %d, htab.filled = %d, "
-		"size = %zu\n", htab, htab->size, htab->filled, size);
+	debug("EXPORT  table = %p, htab.size = %d, htab.filled = %d, size = %lu\n",
+	      htab, htab->size, htab->filled, (ulong)size);
 	/*
 	 * Pass 1:
 	 * search used entries,
@@ -657,8 +657,8 @@
 	/* Check if the user supplied buffer size is sufficient */
 	if (size) {
 		if (size < totlen + 1) {	/* provided buffer too small */
-			printf("Env export buffer too small: %zu, "
-				"but need %zu\n", size, totlen + 1);
+			printf("Env export buffer too small: %lu, but need %lu\n",
+			       (ulong)size, (ulong)totlen + 1);
 			__set_errno(ENOMEM);
 			return (-1);
 		}
@@ -790,7 +790,7 @@
 
 	/* we allocate new space to make sure we can write to the array */
 	if ((data = malloc(size + 1)) == NULL) {
-		debug("himport_r: can't malloc %zu bytes\n", size + 1);
+		debug("himport_r: can't malloc %lu bytes\n", (ulong)size + 1);
 		__set_errno(ENOMEM);
 		return 0;
 	}
@@ -822,7 +822,7 @@
 	 * (CONFIG_ENV_SIZE).  This heuristics will result in
 	 * unreasonably large numbers (and thus memory footprint) for
 	 * big flash environments (>8,000 entries for 64 KB
-	 * envrionment size), so we clip it to a reasonable value.
+	 * environment size), so we clip it to a reasonable value.
 	 * On the other hand we need to add some more entries for free
 	 * space when importing very small buffers. Both boundaries can
 	 * be overwritten in the board config file if needed.
diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile
index 8b86c15..6ef8290 100644
--- a/lib/libfdt/Makefile
+++ b/lib/libfdt/Makefile
@@ -15,3 +15,5 @@
 	fdt_empty_tree.o \
 	fdt_addresses.o \
 	fdt_region.o
+
+obj-$(CONFIG_OF_LIBFDT_OVERLAY) += fdt_overlay.o
diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c
new file mode 100644
index 0000000..40b6d27
--- /dev/null
+++ b/lib/libfdt/fdt_overlay.c
@@ -0,0 +1,618 @@
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+/**
+ * overlay_get_target_phandle - retrieves the target phandle of a fragment
+ * @fdto: pointer to the device tree overlay blob
+ * @fragment: node offset of the fragment in the overlay
+ *
+ * overlay_get_target_phandle() retrieves the target phandle of an
+ * overlay fragment when that fragment uses a phandle (target
+ * property) instead of a path (target-path property).
+ *
+ * returns:
+ *      the phandle pointed by the target property
+ *      0, if the phandle was not found
+ *	-1, if the phandle was malformed
+ */
+static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
+{
+	const uint32_t *val;
+	int len;
+
+	val = fdt_getprop(fdto, fragment, "target", &len);
+	if (!val)
+		return 0;
+
+	if ((*val == (uint32_t)-1) || (len != sizeof(*val)))
+		return (uint32_t)-1;
+
+	return fdt32_to_cpu(*val);
+}
+
+/**
+ * overlay_get_target - retrieves the target phandle of a fragment
+ * @fdt: Base device tree blob
+ * @fdto: Device tree overlay blob
+ * @fragment: node offset of the fragment in the overlay
+ *
+ * overlay_get_target() retrieves the target phandle in the base
+ * device tree of a fragment, no matter how the actual targetting is
+ * done (through a phandle or a path)
+ *
+ * returns:
+ *      the targetted node offset in the base device tree
+ *      Negative error code on error
+ */
+static int overlay_get_target(const void *fdt, const void *fdto,
+			      int fragment)
+{
+	uint32_t phandle;
+	const char *path;
+
+	/* Try first to do a phandle based lookup */
+	phandle = overlay_get_target_phandle(fdto, fragment);
+	if (phandle == (uint32_t)-1)
+		return -FDT_ERR_BADPHANDLE;
+
+	if (phandle)
+		return fdt_node_offset_by_phandle(fdt, phandle);
+
+	/* And then a path based lookup */
+	path = fdt_getprop(fdto, fragment, "target-path", NULL);
+	if (!path)
+		return -FDT_ERR_NOTFOUND;
+
+	return fdt_path_offset(fdt, path);
+}
+
+/**
+ * overlay_phandle_add_offset - Increases a phandle by an offset
+ * @fdt: Base device tree blob
+ * @node: Device tree overlay blob
+ * @name: Name of the property to modify (phandle or linux,phandle)
+ * @delta: offset to apply
+ *
+ * overlay_phandle_add_offset() increments a node phandle by a given
+ * offset.
+ *
+ * returns:
+ *      0 on success.
+ *      Negative error code on error
+ */
+static int overlay_phandle_add_offset(void *fdt, int node,
+				      const char *name, uint32_t delta)
+{
+	const uint32_t *val;
+	uint32_t adj_val;
+	int len;
+
+	val = fdt_getprop(fdt, node, name, &len);
+	if (!val)
+		return len;
+
+	if (len != sizeof(*val))
+		return -FDT_ERR_BADSTRUCTURE;
+
+	adj_val = fdt32_to_cpu(*val);
+	if ((adj_val + delta) < adj_val)
+		return -FDT_ERR_BADPHANDLE;
+
+	adj_val += delta;
+	return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
+}
+
+/**
+ * overlay_adjust_node_phandles - Offsets the phandles of a node
+ * @fdto: Device tree overlay blob
+ * @node: Offset of the node we want to adjust
+ * @delta: Offset to shift the phandles of
+ *
+ * overlay_adjust_node_phandles() adds a constant to all the phandles
+ * of a given node. This is mainly use as part of the overlay
+ * application process, when we want to update all the overlay
+ * phandles to not conflict with the overlays of the base device tree.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_adjust_node_phandles(void *fdto, int node,
+					uint32_t delta)
+{
+	bool found = false;
+	int child;
+	int ret;
+
+	ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
+	if (ret && ret != -FDT_ERR_NOTFOUND)
+		return ret;
+
+	if (!ret)
+		found = true;
+
+	ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
+	if (ret && ret != -FDT_ERR_NOTFOUND)
+		return ret;
+
+	/*
+	 * If neither phandle nor linux,phandle have been found return
+	 * an error.
+	 */
+	if (!found && !ret)
+		return ret;
+
+	fdt_for_each_subnode(fdto, child, node)
+		overlay_adjust_node_phandles(fdto, child, delta);
+
+	return 0;
+}
+
+/**
+ * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay
+ * @fdto: Device tree overlay blob
+ * @delta: Offset to shift the phandles of
+ *
+ * overlay_adjust_local_phandles() adds a constant to all the
+ * phandles of an overlay. This is mainly use as part of the overlay
+ * application process, when we want to update all the overlay
+ * phandles to not conflict with the overlays of the base device tree.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
+{
+	/*
+	 * Start adjusting the phandles from the overlay root
+	 */
+	return overlay_adjust_node_phandles(fdto, 0, delta);
+}
+
+/**
+ * overlay_update_local_node_references - Adjust the overlay references
+ * @fdto: Device tree overlay blob
+ * @tree_node: Node offset of the node to operate on
+ * @fixup_node: Node offset of the matching local fixups node
+ * @delta: Offset to shift the phandles of
+ *
+ * overlay_update_local_nodes_references() update the phandles
+ * pointing to a node within the device tree overlay by adding a
+ * constant delta.
+ *
+ * This is mainly used as part of a device tree application process,
+ * where you want the device tree overlays phandles to not conflict
+ * with the ones from the base device tree before merging them.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_update_local_node_references(void *fdto,
+						int tree_node,
+						int fixup_node,
+						uint32_t delta)
+{
+	int fixup_prop;
+	int fixup_child;
+	int ret;
+
+	fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
+		const unsigned char *fixup_val, *tree_val;
+		const char *name;
+		int fixup_len;
+		int tree_len;
+		int i;
+
+		fixup_val = fdt_getprop_by_offset(fdto, fixup_prop,
+						  &name, &fixup_len);
+		if (!fixup_val)
+			return fixup_len;
+
+		tree_val = fdt_getprop(fdto, tree_node, name, &tree_len);
+		if (!tree_val)
+			return tree_len;
+
+		for (i = 0; i < fixup_len; i += sizeof(uint32_t)) {
+			uint32_t adj_val, index;
+
+			index = *(uint32_t *)(fixup_val + i);
+			index = fdt32_to_cpu(index);
+
+			/*
+			 * phandles to fixup can be unaligned.
+			 *
+			 * Use a memcpy for the architectures that do
+			 * not support unaligned accesses.
+			 */
+			memcpy(&adj_val, tree_val + index, sizeof(uint32_t));
+
+			adj_val = fdt32_to_cpu(adj_val);
+			adj_val += delta;
+			adj_val = cpu_to_fdt32(adj_val);
+
+			ret = fdt_setprop_inplace_namelen_partial(fdto,
+								  tree_node,
+								  name,
+								  strlen(name),
+								  index,
+								  &adj_val,
+								  sizeof(adj_val));
+			if (ret)
+				return ret;
+		}
+	}
+
+	fdt_for_each_subnode(fdto, fixup_child, fixup_node) {
+		const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
+							    NULL);
+		int tree_child;
+
+		tree_child = fdt_subnode_offset(fdto, tree_node,
+						fixup_child_name);
+		if (tree_child < 0)
+			return tree_child;
+
+		ret = overlay_update_local_node_references(fdto,
+							   tree_child,
+							   fixup_child,
+							   delta);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * overlay_update_local_references - Adjust the overlay references
+ * @fdto: Device tree overlay blob
+ * @delta: Offset to shift the phandles of
+ *
+ * overlay_update_local_references() update all the phandles pointing
+ * to a node within the device tree overlay by adding a constant
+ * delta to not conflict with the base overlay.
+ *
+ * This is mainly used as part of a device tree application process,
+ * where you want the device tree overlays phandles to not conflict
+ * with the ones from the base device tree before merging them.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_update_local_references(void *fdto, uint32_t delta)
+{
+	int fixups;
+
+	fixups = fdt_path_offset(fdto, "/__local_fixups__");
+	if (fixups < 0) {
+		/* There's no local phandles to adjust, bail out */
+		if (fixups == -FDT_ERR_NOTFOUND)
+			return 0;
+
+		return fixups;
+	}
+
+	/*
+	 * Update our local references from the root of the tree
+	 */
+	return overlay_update_local_node_references(fdto, 0, fixups,
+						    delta);
+}
+
+/**
+ * overlay_fixup_one_phandle - Set an overlay phandle to the base one
+ * @fdt: Base Device Tree blob
+ * @fdto: Device tree overlay blob
+ * @symbols_off: Node offset of the symbols node in the base device tree
+ * @path: Path to a node holding a phandle in the overlay
+ * @path_len: number of path characters to consider
+ * @name: Name of the property holding the phandle reference in the overlay
+ * @name_len: number of name characters to consider
+ * @index: Index in the overlay property where the phandle is stored
+ * @label: Label of the node referenced by the phandle
+ *
+ * overlay_fixup_one_phandle() resolves an overlay phandle pointing to
+ * a node in the base device tree.
+ *
+ * This is part of the device tree overlay application process, when
+ * you want all the phandles in the overlay to point to the actual
+ * base dt nodes.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_fixup_one_phandle(void *fdt, void *fdto,
+				     int symbols_off,
+				     const char *path, uint32_t path_len,
+				     const char *name, uint32_t name_len,
+				     int index, const char *label)
+{
+	const char *symbol_path;
+	uint32_t phandle;
+	int symbol_off, fixup_off;
+	int prop_len;
+
+	symbol_path = fdt_getprop(fdt, symbols_off, label,
+				  &prop_len);
+	if (!symbol_path)
+		return -FDT_ERR_NOTFOUND;
+
+	symbol_off = fdt_path_offset(fdt, symbol_path);
+	if (symbol_off < 0)
+		return symbol_off;
+
+	phandle = fdt_get_phandle(fdt, symbol_off);
+	if (!phandle)
+		return -FDT_ERR_NOTFOUND;
+
+	fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
+	if (fixup_off < 0)
+		return fixup_off;
+
+	phandle = cpu_to_fdt32(phandle);
+	return fdt_setprop_inplace_namelen_partial(fdto, fixup_off,
+						   name, name_len, index,
+						   &phandle, sizeof(phandle));
+};
+
+/**
+ * overlay_fixup_phandle - Set an overlay phandle to the base one
+ * @fdt: Base Device Tree blob
+ * @fdto: Device tree overlay blob
+ * @symbols_off: Node offset of the symbols node in the base device tree
+ * @property: Property offset in the overlay holding the list of fixups
+ *
+ * overlay_fixup_phandle() resolves all the overlay phandles pointed
+ * to in a __local_fixup__ property, and updates them to match the
+ * phandles in use in the base device tree.
+ *
+ * This is part of the device tree overlay application process, when
+ * you want all the phandles in the overlay to point to the actual
+ * base dt nodes.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
+				 int property)
+{
+	const char *value;
+	const char *label;
+	int len;
+
+	value = fdt_getprop_by_offset(fdto, property,
+				      &label, &len);
+	if (!value)
+		return len;
+
+	do {
+		const char *prop_string = value;
+		const char *path, *name;
+		uint32_t prop_len = strlen(value);
+		uint32_t path_len, name_len;
+		char *sep, *endptr;
+		int index;
+		int ret;
+
+		path = prop_string;
+		sep = memchr(prop_string, ':', prop_len);
+		if (*sep != ':')
+			return -FDT_ERR_BADSTRUCTURE;
+		path_len = sep - path;
+
+		name = sep + 1;
+		sep = memchr(name, ':', prop_len);
+		if (*sep != ':')
+			return -FDT_ERR_BADSTRUCTURE;
+		name_len = sep - name;
+
+		index = strtoul(sep + 1, &endptr, 10);
+		if ((*endptr != '\0') || (endptr <= (sep + 1)))
+			return -FDT_ERR_BADSTRUCTURE;
+
+		len -= prop_len + 1;
+		value += prop_len + 1;
+
+		ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
+						path, path_len, name, name_len,
+						index, label);
+		if (ret)
+			return ret;
+	} while (len > 0);
+
+	return 0;
+}
+
+/**
+ * overlay_fixup_phandles - Resolve the overlay phandles to the base
+ *                          device tree
+ * @fdt: Base Device Tree blob
+ * @fdto: Device tree overlay blob
+ *
+ * overlay_fixup_phandles() resolves all the overlay phandles pointing
+ * to nodes in the base device tree.
+ *
+ * This is one of the steps of the device tree overlay application
+ * process, when you want all the phandles in the overlay to point to
+ * the actual base dt nodes.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_fixup_phandles(void *fdt, void *fdto)
+{
+	int fixups_off, symbols_off;
+	int property;
+
+	symbols_off = fdt_path_offset(fdt, "/__symbols__");
+	fixups_off = fdt_path_offset(fdto, "/__fixups__");
+
+	fdt_for_each_property_offset(property, fdto, fixups_off) {
+		int ret;
+
+		ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * overlay_apply_node - Merge an overlay fragment into the base device tree
+ * @fdt: Base Device Tree blob
+ * @target: Node offset in the base device tree to apply the fragment to
+ * @fdto: Device tree overlay blob
+ * @fragment: Node offset in the overlay holding the changes to merge
+ *
+ * overlay_apply_node() merges an overlay fragment into a target base
+ * device tree node pointed.
+ *
+ * This is part of the final step in the device tree overlay
+ * application process, when all the phandles have been adjusted and
+ * resolved and you just have to merge overlay into the base device
+ * tree.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_apply_node(void *fdt, int target,
+			      void *fdto, int fragment)
+{
+	int property;
+	int node;
+
+	fdt_for_each_property_offset(property, fdto, fragment) {
+		const char *name;
+		const void *prop;
+		int prop_len;
+		int ret;
+
+		prop = fdt_getprop_by_offset(fdto, property, &name,
+					     &prop_len);
+		if (prop_len == -FDT_ERR_NOTFOUND)
+			return -FDT_ERR_INTERNAL;
+		if (prop_len < 0)
+			return prop_len;
+
+		ret = fdt_setprop(fdt, target, name, prop, prop_len);
+		if (ret)
+			return ret;
+	}
+
+	fdt_for_each_subnode(fdto, node, fragment) {
+		const char *name = fdt_get_name(fdto, node, NULL);
+		int nnode;
+		int ret;
+
+		nnode = fdt_add_subnode(fdt, target, name);
+		if (nnode == -FDT_ERR_EXISTS)
+			nnode = fdt_subnode_offset(fdt, target, name);
+
+		if (nnode < 0)
+			return nnode;
+
+		ret = overlay_apply_node(fdt, nnode, fdto, node);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * overlay_merge - Merge an overlay into its base device tree
+ * @fdt: Base Device Tree blob
+ * @fdto: Device tree overlay blob
+ *
+ * overlay_merge() merges an overlay into its base device tree.
+ *
+ * This is the final step in the device tree overlay application
+ * process, when all the phandles have been adjusted and resolved and
+ * you just have to merge overlay into the base device tree.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_merge(void *dt, void *dto)
+{
+	int fragment;
+
+	fdt_for_each_subnode(dto, fragment, 0) {
+		int overlay;
+		int target;
+		int ret;
+
+		target = overlay_get_target(dt, dto, fragment);
+		if (target < 0)
+			continue;
+
+		overlay = fdt_subnode_offset(dto, fragment, "__overlay__");
+		if (overlay < 0)
+			return overlay;
+
+		ret = overlay_apply_node(dt, target, dto, overlay);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+int fdt_overlay_apply(void *fdt, void *fdto)
+{
+	uint32_t delta = fdt_get_max_phandle(fdt) + 1;
+	int ret;
+
+	FDT_CHECK_HEADER(fdt);
+	FDT_CHECK_HEADER(fdto);
+
+	ret = overlay_adjust_local_phandles(fdto, delta);
+	if (ret)
+		goto err;
+
+	ret = overlay_update_local_references(fdto, delta);
+	if (ret)
+		goto err;
+
+	ret = overlay_fixup_phandles(fdt, fdto);
+	if (ret)
+		goto err;
+
+	ret = overlay_merge(fdt, fdto);
+	if (ret)
+		goto err;
+
+	/*
+	 * The overlay has been damaged, erase its magic.
+	 */
+	fdt_set_magic(fdto, ~0);
+
+	return 0;
+
+err:
+	/*
+	 * The overlay might have been damaged, erase its magic.
+	 */
+	fdt_set_magic(fdto, ~0);
+
+	/*
+	 * The base device tree might have been damaged, erase its
+	 * magic.
+	 */
+	fdt_set_magic(fdt, ~0);
+
+	return ret;
+}
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index 12214c2..9cc98db 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -47,6 +47,32 @@
 	return (strnlen(p, len + 1) == len) && (memcmp(p, s, len) == 0);
 }
 
+uint32_t fdt_get_max_phandle(const void *fdt)
+{
+	uint32_t max_phandle = 0;
+	int offset;
+
+	for (offset = fdt_next_node(fdt, -1, NULL);;
+	     offset = fdt_next_node(fdt, offset, NULL)) {
+		uint32_t phandle;
+
+		if (offset == -FDT_ERR_NOTFOUND)
+			return max_phandle;
+
+		if (offset < 0)
+			return 0;
+
+		phandle = fdt_get_phandle(fdt, offset);
+		if (phandle == (uint32_t)-1)
+			return 0;
+
+		if (phandle > max_phandle)
+			max_phandle = phandle;
+	}
+
+	return 0;
+}
+
 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
 {
 	FDT_CHECK_HEADER(fdt);
@@ -114,15 +140,15 @@
 }
 
 /*
- * Find the next of path seperator, note we need to search for both '/' and ':'
+ * Find the next of path separator, note we need to search for both '/' and ':'
  * and then take the first one so that we do the right thing for e.g.
  * "foo/bar:option" and "bar:option/otheroption", both of which happen, so
  * first searching for either ':' or '/' does not work.
  */
-static const char *fdt_path_next_seperator(const char *path)
+static const char *fdt_path_next_separator(const char *path, int len)
 {
-	const char *sep1 = strchr(path, '/');
-	const char *sep2 = strchr(path, ':');
+	const void *sep1 = memchr(path, '/', len);
+	const void *sep2 = memchr(path, ':', len);
 
 	if (sep1 && sep2)
 		return (sep1 < sep2) ? sep1 : sep2;
@@ -132,9 +158,9 @@
 		return sep2;
 }
 
-int fdt_path_offset(const void *fdt, const char *path)
+int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
 {
-	const char *end = path + strlen(path);
+	const char *end = path + namelen;
 	const char *p = path;
 	int offset = 0;
 
@@ -142,7 +168,7 @@
 
 	/* see if we have an alias */
 	if (*path != '/') {
-		const char *q = fdt_path_next_seperator(path);
+		const char *q = fdt_path_next_separator(path, namelen);
 
 		if (!q)
 			q = end;
@@ -155,14 +181,16 @@
 		p = q;
 	}
 
-	while (*p) {
+	while (*p && (p < end)) {
 		const char *q;
 
 		while (*p == '/')
 			p++;
+
 		if (*p == '\0' || *p == ':')
 			return offset;
-		q = fdt_path_next_seperator(p);
+
+		q = fdt_path_next_separator(p, end - p);
 		if (!q)
 			q = end;
 
diff --git a/lib/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c
index 9fe9886..216c512 100644
--- a/lib/libfdt/fdt_wip.c
+++ b/lib/libfdt/fdt_wip.c
@@ -14,21 +14,42 @@
 
 #include "libfdt_internal.h"
 
+int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
+					const char *name, int namelen,
+					uint32_t index, const void *val,
+					int len)
+{
+	void *propval;
+	int proplen;
+
+	propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen,
+					&proplen);
+	if (!propval)
+		return proplen;
+
+	if (proplen < (len + index))
+		return -FDT_ERR_NOSPACE;
+
+	memcpy(propval + index, val, len);
+	return 0;
+}
+
 int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
 			const void *val, int len)
 {
-	void *propval;
+	const void *propval;
 	int proplen;
 
-	propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
+	propval = fdt_getprop(fdt, nodeoffset, name, &proplen);
 	if (!propval)
 		return proplen;
 
 	if (proplen != len)
 		return -FDT_ERR_NOSPACE;
 
-	memcpy(propval, val, len);
-	return 0;
+	return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name,
+						   strlen(name), 0,
+						   val, len);
 }
 
 static void _fdt_nop_region(void *start, int len)
diff --git a/lib/libfdt/libfdt.swig b/lib/libfdt/libfdt.swig
new file mode 100644
index 0000000..14f583d
--- /dev/null
+++ b/lib/libfdt/libfdt.swig
@@ -0,0 +1,89 @@
+/* File: libfdt.i */
+%module libfdt
+
+%{
+#define SWIG_FILE_WITH_INIT
+#include "libfdt.h"
+%}
+
+%pythoncode %{
+def Raise(errnum):
+    raise ValueError('Error %s' % fdt_strerror(errnum))
+
+def Name(fdt, offset):
+    name, len = fdt_get_name(fdt, offset)
+    return name
+
+def String(fdt, offset):
+    offset = fdt32_to_cpu(offset)
+    name = fdt_string(fdt, offset)
+    return name
+
+def swap32(x):
+    return (((x << 24) & 0xFF000000) |
+            ((x <<  8) & 0x00FF0000) |
+            ((x >>  8) & 0x0000FF00) |
+            ((x >> 24) & 0x000000FF))
+
+def fdt32_to_cpu(x):
+    return swap32(x)
+
+def Data(prop):
+    set_prop(prop)
+    return get_prop_data()
+%}
+
+%include "typemaps.i"
+%include "cstring.i"
+
+%typemap(in) void* = char*;
+
+typedef int fdt32_t;
+
+struct fdt_property {
+        fdt32_t tag;
+        fdt32_t len;
+        fdt32_t nameoff;
+        char data[0];
+};
+
+/*
+ * This is a work-around since I'm not sure of a better way to copy out the
+ * contents of a string. This is used in dtoc/GetProps(). The intent is to
+ * pass in a pointer to a property and access the data field at the end of
+ * it. Ideally the Data() function above would be able to do this directly,
+ * but I'm not sure how to do that.
+ */
+#pragma SWIG nowarn=454
+%inline %{
+    static struct fdt_property *cur_prop;
+
+    void set_prop(struct fdt_property *prop) {
+        cur_prop = prop;
+    }
+%}
+
+%cstring_output_allocate_size(char **s, int *sz, free(*$1));
+%inline %{
+    void get_prop_data(char **s, int *sz) {
+        *sz = fdt32_to_cpu(cur_prop->len);
+        *s = (char *)malloc(*sz);
+        if (!*s)
+            *sz = 0;
+        else
+            memcpy(*s, cur_prop + 1, *sz);
+    }
+%}
+
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
+int fdt_path_offset(const void *fdt, const char *path);
+int fdt_first_property_offset(const void *fdt, int nodeoffset);
+int fdt_next_property_offset(const void *fdt, int offset);
+const char *fdt_strerror(int errval);
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+                                                      int offset,
+                                                      int *OUTPUT);
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *OUTPUT);
+const char *fdt_string(const void *fdt, int stroffset);
+int fdt_first_subnode(const void *fdt, int offset);
+int fdt_next_subnode(const void *fdt, int offset);
diff --git a/lib/libfdt/setup.py b/lib/libfdt/setup.py
new file mode 100644
index 0000000..62e7bcc
--- /dev/null
+++ b/lib/libfdt/setup.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+setup.py file for SWIG libfdt
+"""
+
+from distutils.core import setup, Extension
+import os
+import sys
+
+# Don't cross-compile - always use the host compiler.
+del os.environ['CROSS_COMPILE']
+del os.environ['CC']
+
+progname = sys.argv[0]
+cflags = sys.argv[1]
+files = sys.argv[2:]
+
+if cflags:
+    cflags = [flag for flag in cflags.split(' ') if flag]
+else:
+    cflags = None
+
+libfdt_module = Extension(
+    '_libfdt',
+    sources = files,
+    extra_compile_args =  cflags
+)
+
+sys.argv = [progname, '--quiet', 'build_ext', '--inplace']
+
+setup (name = 'libfdt',
+       version = '0.1',
+       author      = "SWIG Docs",
+       description = """Simple swig libfdt from docs""",
+       ext_modules = [libfdt_module],
+       py_modules = ["libfdt"],
+       )
diff --git a/lib/libfdt/test_libfdt.py b/lib/libfdt/test_libfdt.py
new file mode 100644
index 0000000..14d0da4
--- /dev/null
+++ b/lib/libfdt/test_libfdt.py
@@ -0,0 +1,14 @@
+#!/usr/bin/python
+
+import os
+import sys
+
+our_path = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(our_path, '../../b/sandbox_spl/tools'))
+
+import libfdt
+
+with open('b/sandbox_spl/u-boot.dtb') as fd:
+    fdt = fd.read()
+
+print libfdt.fdt_path_offset(fdt, "/aliases")
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
index 5d9716f..c26f741 100644
--- a/lib/rsa/rsa-sign.c
+++ b/lib/rsa/rsa-sign.c
@@ -420,11 +420,13 @@
 		BN_rshift(num, num, 32); /*  N = N/B */
 	}
 
+	/*
+	 * We try signing with successively increasing size values, so this
+	 * might fail several times
+	 */
 	ret = fdt_setprop(blob, noffset, prop_name, buf, size);
-	if (ret) {
-		fprintf(stderr, "Failed to write public key to FIT\n");
-		return -ENOSPC;
-	}
+	if (ret)
+		return -FDT_ERR_NOSPACE;
 	free(buf);
 	BN_free(tmp);
 	BN_free(big2);
@@ -508,7 +510,7 @@
 		ret = fdt_setprop_string(keydest, node, FIT_ALGO_PROP,
 					 info->algo->name);
 	}
-	if (info->require_keys) {
+	if (!ret && info->require_keys) {
 		ret = fdt_setprop_string(keydest, node, "required",
 					 info->require_keys);
 	}
diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c
index b334f05..30ac759 100644
--- a/lib/tiny-printf.c
+++ b/lib/tiny-printf.c
@@ -13,29 +13,33 @@
 #include <stdarg.h>
 #include <serial.h>
 
-/*
- * This code in here may execute before the DRAM is initialised, so
- * we should make sure that it doesn't touch BSS, which some boards
- * put in DRAM.
- */
-static char *bf __attribute__ ((section(".data")));
-static char zs __attribute__ ((section(".data")));
+struct printf_info {
+	char *bf;	/* Digit buffer */
+	char zs;	/* non-zero if a digit has been written */
+	char *outstr;	/* Next output position for sprintf() */
 
-/* Current position in sprintf() output string */
-static char *outstr __attribute__ ((section(".data")));
+	/* Output a character */
+	void (*putc)(struct printf_info *info, char ch);
+};
 
-static void out(char c)
+void putc_normal(struct printf_info *info, char ch)
 {
-	*bf++ = c;
+	putc(ch);
 }
 
-static void out_dgt(char dgt)
+static void out(struct printf_info *info, char c)
 {
-	out(dgt + (dgt < 10 ? '0' : 'a' - 10));
-	zs = 1;
+	*info->bf++ = c;
 }
 
-static void div_out(unsigned int *num, unsigned int div)
+static void out_dgt(struct printf_info *info, char dgt)
+{
+	out(info, dgt + (dgt < 10 ? '0' : 'a' - 10));
+	info->zs = 1;
+}
+
+static void div_out(struct printf_info *info, unsigned int *num,
+		    unsigned int div)
 {
 	unsigned char dgt = 0;
 
@@ -44,11 +48,11 @@
 		dgt++;
 	}
 
-	if (zs || dgt > 0)
-		out_dgt(dgt);
+	if (info->zs || dgt > 0)
+		out_dgt(info, dgt);
 }
 
-int _vprintf(const char *fmt, va_list va, void (*putc)(const char ch))
+int _vprintf(struct printf_info *info, const char *fmt, va_list va)
 {
 	char ch;
 	char *p;
@@ -58,7 +62,7 @@
 
 	while ((ch = *(fmt++))) {
 		if (ch != '%') {
-			putc(ch);
+			info->putc(info, ch);
 		} else {
 			bool lz = false;
 			int width = 0;
@@ -76,9 +80,9 @@
 					ch = *fmt++;
 				}
 			}
-			bf = buf;
-			p = bf;
-			zs = 0;
+			info->bf = buf;
+			p = info->bf;
+			info->zs = 0;
 
 			switch (ch) {
 			case '\0':
@@ -88,45 +92,45 @@
 				num = va_arg(va, unsigned int);
 				if (ch == 'd' && (int)num < 0) {
 					num = -(int)num;
-					out('-');
+					out(info, '-');
 				}
 				if (!num) {
-					out_dgt(0);
+					out_dgt(info, 0);
 				} else {
 					for (div = 1000000000; div; div /= 10)
-						div_out(&num, div);
+						div_out(info, &num, div);
 				}
 				break;
 			case 'x':
 				num = va_arg(va, unsigned int);
 				if (!num) {
-					out_dgt(0);
+					out_dgt(info, 0);
 				} else {
 					for (div = 0x10000000; div; div /= 0x10)
-						div_out(&num, div);
+						div_out(info, &num, div);
 				}
 				break;
 			case 'c':
-				out((char)(va_arg(va, int)));
+				out(info, (char)(va_arg(va, int)));
 				break;
 			case 's':
 				p = va_arg(va, char*);
 				break;
 			case '%':
-				out('%');
+				out(info, '%');
 			default:
 				break;
 			}
 
-			*bf = 0;
-			bf = p;
-			while (*bf++ && width > 0)
+			*info->bf = 0;
+			info->bf = p;
+			while (*info->bf++ && width > 0)
 				width--;
 			while (width-- > 0)
-				putc(lz ? '0' : ' ');
+				info->putc(info, lz ? '0' : ' ');
 			if (p) {
 				while ((ch = *p++))
-					putc(ch);
+					info->putc(info, ch);
 			}
 		}
 	}
@@ -137,36 +141,44 @@
 
 int vprintf(const char *fmt, va_list va)
 {
-	return _vprintf(fmt, va, putc);
+	struct printf_info info;
+
+	info.putc = putc_normal;
+	return _vprintf(&info, fmt, va);
 }
 
 int printf(const char *fmt, ...)
 {
+	struct printf_info info;
+
 	va_list va;
 	int ret;
 
+	info.putc = putc_normal;
 	va_start(va, fmt);
-	ret = _vprintf(fmt, va, putc);
+	ret = _vprintf(&info, fmt, va);
 	va_end(va);
 
 	return ret;
 }
 
-static void putc_outstr(char ch)
+static void putc_outstr(struct printf_info *info, char ch)
 {
-	*outstr++ = ch;
+	*info->outstr++ = ch;
 }
 
 int sprintf(char *buf, const char *fmt, ...)
 {
+	struct printf_info info;
 	va_list va;
 	int ret;
 
 	va_start(va, fmt);
-	outstr = buf;
-	ret = _vprintf(fmt, va, putc_outstr);
+	info.outstr = buf;
+	info.putc = putc_outstr;
+	ret = _vprintf(&info, fmt, va);
 	va_end(va);
-	*outstr = '\0';
+	*info.outstr = '\0';
 
 	return ret;
 }
@@ -174,14 +186,25 @@
 /* Note that size is ignored */
 int snprintf(char *buf, size_t size, const char *fmt, ...)
 {
+	struct printf_info info;
 	va_list va;
 	int ret;
 
 	va_start(va, fmt);
-	outstr = buf;
-	ret = _vprintf(fmt, va, putc_outstr);
+	info.outstr = buf;
+	info.putc = putc_outstr;
+	ret = _vprintf(&info, fmt, va);
 	va_end(va);
-	*outstr = '\0';
+	*info.outstr = '\0';
 
 	return ret;
 }
+
+void __assert_fail(const char *assertion, const char *file, unsigned line,
+		   const char *function)
+{
+	/* This will not return */
+	printf("%s:%u: %s: Assertion `%s' failed.", file, line, function,
+	       assertion);
+	hang();
+}
diff --git a/net/eth_internal.h b/net/eth_internal.h
index 6e4753c..a14b208 100644
--- a/net/eth_internal.h
+++ b/net/eth_internal.h
@@ -13,7 +13,7 @@
 void eth_common_init(void);
 
 /**
- * eth_setenv_enetaddr_by_index() - set the MAC address envrionment variable
+ * eth_setenv_enetaddr_by_index() - set the MAC address environment variable
  *
  * This sets up an environment variable with the given MAC address (@enetaddr).
  * The environment variable to be set is defined by <@base_name><@index>addr.
diff --git a/post/cpu/ppc4xx/ether.c b/post/cpu/ppc4xx/ether.c
index 4c9a39b..8a4c56b 100644
--- a/post/cpu/ppc4xx/ether.c
+++ b/post/cpu/ppc4xx/ether.c
@@ -21,7 +21,7 @@
  *   CONFIG_SYS_POST_ETH_LOOPS - Number of test loops. Each loop
  *     is tested with a different frame length. Starting with
  *     MAX_PACKET_LENGTH and going down to MIN_PACKET_LENGTH.
- *     Defaults to 10 and can be overriden in the board config header.
+ *     Defaults to 10 and can be overridden in the board config header.
  */
 
 #include <post.h>
diff --git a/scripts/Makefile.host b/scripts/Makefile.host
index bff8b5b..763a699 100644
--- a/scripts/Makefile.host
+++ b/scripts/Makefile.host
@@ -28,12 +28,16 @@
 # C code
 # Executables compiled from a single .c file
 host-csingle	:= $(foreach m,$(__hostprogs), \
-			$(if $($(m)-objs)$($(m)-cxxobjs),,$(m)))
+			$(if $($(m)-objs)$($(m)-cxxobjs)$($(m)-sharedobjs),,$(m)))
 
 # C executables linked based on several .o files
 host-cmulti	:= $(foreach m,$(__hostprogs),\
 		   $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))
 
+# Shared object libraries
+host-shared	:= $(foreach m,$(__hostprogs),\
+		   $(if $($(m)-sharedobjs),$(m))))
+
 # Object (.o) files compiled from .c files
 host-cobjs	:= $(sort $(foreach m,$(__hostprogs),$($(m)-objs)))
 
@@ -59,6 +63,7 @@
 host-cobjs	:= $(addprefix $(obj)/,$(host-cobjs))
 host-cxxmulti	:= $(addprefix $(obj)/,$(host-cxxmulti))
 host-cxxobjs	:= $(addprefix $(obj)/,$(host-cxxobjs))
+host-shared	:= $(addprefix $(obj)/,$(host-shared))
 host-objdirs    := $(addprefix $(obj)/,$(host-objdirs))
 
 obj-dirs += $(host-objdirs)
@@ -128,4 +133,4 @@
 	$(call if_changed_dep,host-cxxobjs)
 
 targets += $(host-csingle)  $(host-cmulti) $(host-cobjs)\
-	   $(host-cxxmulti) $(host-cxxobjs)
+	   $(host-cxxmulti) $(host-cxxobjs) $(host-shared)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index e720562..45a0e1d 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -275,11 +275,11 @@
 (							\
 	echo '.section .dtb.init.rodata,"a"';		\
 	echo '.balign 16';				\
-	echo '.global __dtb_$(*F)_begin';		\
-	echo '__dtb_$(*F)_begin:';			\
+	echo '.global __dtb_$(subst -,_,$(*F))_begin';	\
+	echo '__dtb_$(subst -,_,$(*F))_begin:';		\
 	echo '.incbin "$<" ';				\
-	echo '__dtb_$(*F)_end:';			\
-	echo '.global __dtb_$(*F)_end';			\
+	echo '__dtb_$(subst -,_,$(*F))_end:';		\
+	echo '.global __dtb_$(subst -,_,$(*F))_end';	\
 	echo '.balign 16';				\
 ) > $@
 
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index 0997fd9..3ba9742 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -45,6 +45,7 @@
 # FIX ME
 cpp_flags := $(KBUILD_CPPFLAGS) $(PLATFORM_CPPFLAGS) $(UBOOTINCLUDE) \
 							$(NOSTDINC_FLAGS)
+c_flags := $(KBUILD_CFLAGS) $(cpp_flags)
 
 HAVE_VENDOR_COMMON_LIB = $(if $(wildcard $(srctree)/board/$(VENDOR)/common/Makefile),y,n)
 
@@ -76,6 +77,9 @@
 
 u-boot-spl-init := $(head-y)
 u-boot-spl-main := $(libs-y)
+ifdef CONFIG_SPL_OF_PLATDATA
+u-boot-spl-platdata := $(obj)/dts/dt-platdata.o
+endif
 
 # Linker Script
 ifdef CONFIG_SPL_LDSCRIPT
@@ -169,7 +173,7 @@
 quiet_cmd_copy = COPY    $@
       cmd_copy = cp $< $@
 
-ifeq ($(CONFIG_SPL_OF_CONTROL)$(CONFIG_OF_SEPARATE),yy)
+ifeq ($(CONFIG_SPL_OF_CONTROL)$(CONFIG_OF_SEPARATE)$(CONFIG_SPL_OF_PLATDATA),yy)
 $(obj)/$(SPL_BIN)-dtb.bin: $(obj)/$(SPL_BIN)-nodtb.bin $(obj)/$(SPL_BIN)-pad.bin \
 		$(obj)/$(SPL_BIN).dtb FORCE
 	$(call if_changed,cat)
@@ -207,6 +211,32 @@
 $(obj)/$(SPL_BIN).cfg:	include/config.h FORCE
 	$(call if_changed,cpp_cfg)
 
+pythonpath = PYTHONPATH=tools
+
+quiet_cmd_dtocc = DTOC C  $@
+cmd_dtocc = $(pythonpath) $(srctree)/tools/dtoc/dtoc -d $(obj)/$(SPL_BIN).dtb -o $@ platdata
+
+quiet_cmd_dtoch = DTOC H  $@
+cmd_dtoch = $(pythonpath) $(srctree)/tools/dtoc/dtoc -d $(obj)/$(SPL_BIN).dtb -o $@ struct
+
+quiet_cmd_plat = PLAT    $@
+cmd_plat = $(CC) $(c_flags) -c $< -o $@
+
+$(obj)/dts/dt-platdata.o: $(obj)/dts/dt-platdata.c include/generated/dt-structs.h
+	$(call if_changed,plat)
+
+PHONY += dts_dir
+dts_dir:
+	$(shell [ -d $(obj)/dts ] || mkdir -p $(obj)/dts)
+
+include/generated/dt-structs.h: $(obj)/$(SPL_BIN).dtb dts_dir dtoc
+	$(call if_changed,dtoch)
+
+$(obj)/dts/dt-platdata.c: $(obj)/$(SPL_BIN).dtb dts_dir dtoc
+	$(call if_changed,dtocc)
+
+dtoc: #$(objtree)/tools/_libfdt.so
+
 ifdef CONFIG_SAMSUNG
 ifdef CONFIG_VAR_SIZE_SPL
 VAR_SIZE_PARAM = --vs
@@ -241,19 +271,24 @@
 $(obj)/sunxi-spl.bin: $(obj)/$(SPL_BIN).bin FORCE
 	$(call if_changed,mksunxiboot)
 
-quiet_cmd_u-boot-spl = LD      $@
-      cmd_u-boot-spl = (cd $(obj) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) \
+# Rule to link u-boot-spl
+# May be overridden by arch/$(ARCH)/config.mk
+quiet_cmd_u-boot-spl ?= LD      $@
+      cmd_u-boot-spl ?= (cd $(obj) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) \
 		       $(patsubst $(obj)/%,%,$(u-boot-spl-init)) --start-group \
-		       $(patsubst $(obj)/%,%,$(u-boot-spl-main)) --end-group \
+		       $(patsubst $(obj)/%,%,$(u-boot-spl-main))  \
+		       $(patsubst $(obj)/%,%,$(u-boot-spl-platdata)) \
+		       --end-group \
 		       $(PLATFORM_LIBS) -Map $(SPL_BIN).map -o $(SPL_BIN))
 
-$(obj)/$(SPL_BIN): $(u-boot-spl-init) $(u-boot-spl-main) $(obj)/u-boot-spl.lds FORCE
+$(obj)/$(SPL_BIN): $(u-boot-spl-platdata) $(u-boot-spl-init) \
+		$(u-boot-spl-main) $(obj)/u-boot-spl.lds FORCE
 	$(call if_changed,u-boot-spl)
 
 $(sort $(u-boot-spl-init) $(u-boot-spl-main)): $(u-boot-spl-dirs) ;
 
 PHONY += $(u-boot-spl-dirs)
-$(u-boot-spl-dirs):
+$(u-boot-spl-dirs): $(u-boot-spl-platdata)
 	$(Q)$(MAKE) $(build)=$@
 
 quiet_cmd_cpp_lds = LDS     $@
diff --git a/scripts/coccinelle/net/mdio_register.cocci b/scripts/coccinelle/net/mdio_register.cocci
new file mode 100644
index 0000000..100f102
--- /dev/null
+++ b/scripts/coccinelle/net/mdio_register.cocci
@@ -0,0 +1,142 @@
+/// Use mdio_alloc and mdio_register instead of miiphy_register
+///
+//# Stop using the oldest mii interface in drivers
+//
+// Confidence: High
+// Copyright: (C) 2016 Joe Hershberger.  GPLv2.
+// Comments:
+// Options: --include-headers --recursive-includes --local-includes -I include
+
+@ mii_reg @
+expression devname;
+identifier readfunc, writefunc;
+@@
+
++ int retval;
+- miiphy_register(devname, readfunc, writefunc);
++ struct mii_dev *mdiodev = mdio_alloc();
++ if (!mdiodev) return -ENOMEM;
++ strncpy(mdiodev->name, devname, MDIO_NAME_LEN);
++ mdiodev->read = readfunc;
++ mdiodev->write = writefunc;
++ 
++ retval = mdio_register(mdiodev);
++ if (retval < 0) return retval;
+
+@ update_read_sig @
+identifier mii_reg.readfunc;
+identifier name0, addr0, reg0, output;
+type addrT, outputT;
+@@
+
+- readfunc (
+- 	const char *name0,
+- 	addrT addr0,
+- 	addrT reg0,
+- 	outputT *output
+- )
++ readfunc (
++ 	struct mii_dev *bus,
++ 	int addr0,
++ 	int devad,
++ 	int reg0
++ )
+  {
+  ...
+  }
+
+@ update_read_impl @
+identifier mii_reg.readfunc;
+identifier update_read_sig.output;
+type update_read_sig.outputT;
+constant c;
+identifier retvar;
+expression E;
+@@
+
+  readfunc (...)
+  {
++ outputT output = 0;
+  ...
+(
+- return 0;
++ return *output;
+|
+  return c;
+|
+- return retvar;
++ if (retvar < 0)
++ 	return retvar;
++ return *output;
+|
+- return E;
++ int retval = E;
++ if (retval < 0)
++ 	return retval;
++ return *output;
+)
+  }
+
+@ update_read_impl2 @
+identifier mii_reg.readfunc;
+identifier update_read_sig.output;
+@@
+
+  readfunc (...)
+  {
+  <...
+(
+- *output
++ output
+|
+- output
++ &output
+)
+  ...>
+  }
+
+@ update_read_name @
+identifier mii_reg.readfunc;
+identifier update_read_sig.name0;
+@@
+  readfunc (...) {
+  <...
+- name0
++ bus->name
+  ...>
+  }
+
+@ update_write_sig @
+identifier mii_reg.writefunc;
+identifier name0, addr0, reg0, value0;
+type addrT, valueT;
+typedef u16;
+@@
+
+- writefunc (
+- 	const char *name0,
+- 	addrT addr0,
+- 	addrT reg0,
+- 	valueT value0
+- )
++ writefunc (
++ 	struct mii_dev *bus,
++ 	int addr0,
++ 	int devad,
++ 	int reg0,
++ 	u16 value0
++ )
+  {
+  ...
+  }
+
+@ update_write_name @
+identifier mii_reg.writefunc;
+identifier update_write_sig.name0;
+@@
+  writefunc (...) {
+  <...
+- name0
++ bus->name
+  ...>
+  }
diff --git a/test/Kconfig b/test/Kconfig
index d71c332..3643761 100644
--- a/test/Kconfig
+++ b/test/Kconfig
@@ -17,3 +17,4 @@
 
 source "test/dm/Kconfig"
 source "test/env/Kconfig"
+source "test/overlay/Kconfig"
diff --git a/test/README b/test/README
new file mode 100644
index 0000000..1142e9c
--- /dev/null
+++ b/test/README
@@ -0,0 +1,92 @@
+Testing in U-Boot
+=================
+
+U-Boot has a large amount of code. This file describes how this code is
+tested and what tests you should write when adding a new feature.
+
+
+Running tests
+-------------
+
+To run most tests on sandbox, type this:
+
+    test/run
+
+in the U-Boot directory. Note that only the pytest suite is run using this
+command.
+
+
+Sandbox
+-------
+U-Boot can be built as a user-space application (e.g. for Linux). This
+allows test to be executed without needing target hardware. The 'sandbox'
+target provides this feature and it is widely used in tests.
+
+
+Pytest Suite
+------------
+
+Many tests are available using the pytest suite, in test/py. This can run
+either on sandbox or on real hardware. It relies on the U-Boot console to
+inject test commands and check the result. It is slower to run than C code,
+but provides the ability to unify lots of tests and summarise their results.
+
+You can run the tests on sandbox with:
+
+	./test/py/test.py --bd sandbox --build
+
+This will produce HTML output in build-sandbox/test-log.html
+
+See test/py/README.md for more information about the pytest suite.
+
+
+tbot
+----
+
+Tbot provides a way to execute tests on target hardware. It is intended for
+trying out both U-Boot and Linux (and potentially other software) on a
+number of boards automatically. It can be used to create a continuous test
+environment. See tools/tbot/README for more information.
+
+
+Ad-hoc tests
+------------
+
+There are several ad-hoc tests which run outside the pytest environment:
+
+   test/fs	- File system test (shell script)
+   test/image	- FIT and legacy image tests (shell script and Python)
+   test/stdint	- A test that stdint.h can be used in U-Boot (shell script)
+   trace	- Test for the tracing feature (shell script)
+
+TODO: Move these into pytest.
+
+
+When to write tests
+-------------------
+
+If you add code to U-Boot without a test you are taking a risk. Even if you
+perform thorough manual testing at the time of submission, it may break when
+future changes are made to U-Boot. It may even break when applied to mainline,
+if other changes interact with it. A good mindset is that untested code
+probably doesn't work and should be deleted.
+
+You can assume that the Pytest suite will be run before patches are accepted
+to mainline, so this provides protection against future breakage.
+
+On the other hand there is quite a bit of code that is not covered with tests,
+or is covered sparingly. So here are some suggestions:
+
+- If you are adding a new uclass, add a sandbox driver and a test that uses it
+- If you are modifying code covered by an existing test, add a new test case
+  to cover your changes
+- If the code you are modifying has not tests, consider writing one. Even a
+  very basic test is useful, and may be picked up and enhanced by others. It
+  is much easier to add onto a test - writing a new large test can seem
+  daunting to most contributors.
+
+
+Future work
+-----------
+
+Converting existing shell scripts into pytest tests.
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index f6e1f41..1433342 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -19,6 +19,9 @@
 #if defined(CONFIG_UT_ENV)
 	U_BOOT_CMD_MKENT(env, CONFIG_SYS_MAXARGS, 1, do_ut_env, "", ""),
 #endif
+#ifdef CONFIG_UT_OVERLAY
+	U_BOOT_CMD_MKENT(overlay, CONFIG_SYS_MAXARGS, 1, do_ut_overlay, "", ""),
+#endif
 #ifdef CONFIG_UT_TIME
 	U_BOOT_CMD_MKENT(time, CONFIG_SYS_MAXARGS, 1, do_ut_time, "", ""),
 #endif
@@ -68,6 +71,9 @@
 #ifdef CONFIG_UT_ENV
 	"ut env [test-name]\n"
 #endif
+#ifdef CONFIG_UT_OVERLAY
+	"ut overlay [test-name]\n"
+#endif
 #ifdef CONFIG_UT_TIME
 	"ut time - Very basic test of time functions\n"
 #endif
diff --git a/test/dm/Makefile b/test/dm/Makefile
index cad3374..1885e17 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -24,6 +24,7 @@
 obj-$(CONFIG_DM_MAILBOX) += mailbox.o
 obj-$(CONFIG_DM_MMC) += mmc.o
 obj-$(CONFIG_DM_PCI) += pci.o
+obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
 obj-$(CONFIG_REMOTEPROC) += remoteproc.o
diff --git a/test/dm/bus.c b/test/dm/bus.c
index 3b5a23b..d94dcf7 100644
--- a/test/dm/bus.c
+++ b/test/dm/bus.c
@@ -7,7 +7,6 @@
 #include <common.h>
 #include <dm.h>
 #include <dm/device-internal.h>
-#include <dm/root.h>
 #include <dm/test.h>
 #include <dm/uclass-internal.h>
 #include <dm/util.h>
@@ -30,7 +29,7 @@
 
 static int testbus_drv_probe(struct udevice *dev)
 {
-	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+	return dm_scan_fdt_dev(dev);
 }
 
 static int testbus_child_post_bind(struct udevice *dev)
diff --git a/test/dm/i2c.c b/test/dm/i2c.c
index 23d612e..e2688bf 100644
--- a/test/dm/i2c.c
+++ b/test/dm/i2c.c
@@ -31,8 +31,8 @@
 						       false, &bus));
 
 	/*
-	 * i2c_post_bind() will bind devices to chip selects. Check this then
-	 * remove the emulation and the slave device.
+	 * The post_bind() method will bind devices to chip selects. Check
+	 * this then remove the emulation and the slave device.
 	 */
 	ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
 	ut_assertok(dm_i2c_probe(bus, chip, 0, &dev));
diff --git a/test/dm/power-domain.c b/test/dm/power-domain.c
new file mode 100644
index 0000000..379a8fa
--- /dev/null
+++ b/test/dm/power-domain.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <asm/power-domain.h>
+#include <test/ut.h>
+
+/* This must match the specifier for power-domains in the DT node */
+#define TEST_POWER_DOMAIN 2
+
+static int dm_test_power_domain(struct unit_test_state *uts)
+{
+	struct udevice *dev_power_domain;
+	struct udevice *dev_test;
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_POWER_DOMAIN,
+					      "power-domain",
+					      &dev_power_domain));
+	ut_asserteq(0, sandbox_power_domain_query(dev_power_domain, 0));
+	ut_asserteq(0, sandbox_power_domain_query(dev_power_domain,
+						  TEST_POWER_DOMAIN));
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "power-domain-test",
+					      &dev_test));
+	ut_assertok(sandbox_power_domain_test_get(dev_test));
+
+	ut_assertok(sandbox_power_domain_test_on(dev_test));
+	ut_asserteq(0, sandbox_power_domain_query(dev_power_domain, 0));
+	ut_asserteq(1, sandbox_power_domain_query(dev_power_domain,
+						  TEST_POWER_DOMAIN));
+
+	ut_assertok(sandbox_power_domain_test_off(dev_test));
+	ut_asserteq(0, sandbox_power_domain_query(dev_power_domain, 0));
+	ut_asserteq(0, sandbox_power_domain_query(dev_power_domain,
+						  TEST_POWER_DOMAIN));
+
+	ut_assertok(sandbox_power_domain_test_free(dev_test));
+
+	return 0;
+}
+DM_TEST(dm_test_power_domain, DM_TESTF_SCAN_FDT);
diff --git a/test/dm/spi.c b/test/dm/spi.c
index 2e27da7..5733096 100644
--- a/test/dm/spi.c
+++ b/test/dm/spi.c
@@ -30,8 +30,8 @@
 						       false, &bus));
 
 	/*
-	 * spi_post_bind() will bind devices to chip selects. Check this then
-	 * remove the emulation and the slave device.
+	 * The post_bind() method will bind devices to chip selects. Check
+	 * this then remove the emulation and the slave device.
 	 */
 	ut_asserteq(0, uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus));
 	ut_assertok(spi_cs_info(bus, cs, &info));
diff --git a/test/overlay/Kconfig b/test/overlay/Kconfig
new file mode 100644
index 0000000..13c8542
--- /dev/null
+++ b/test/overlay/Kconfig
@@ -0,0 +1,11 @@
+config UT_OVERLAY
+	bool "Enable Device Tree Overlays Unit Tests"
+	depends on OF_LIBFDT_OVERLAY
+	depends on UNIT_TEST
+	help
+	  This enables the 'ut overlay' command which runs a series of unit
+	  tests on the fdt overlay code.
+	  If all is well then all tests pass although there will be a few
+	  messages printed along the way.
+	  Be warned that it requires an out-of-tree dtc compiler with patches
+	  to support the DT overlays, otherwise it will fail.
diff --git a/test/overlay/Makefile b/test/overlay/Makefile
new file mode 100644
index 0000000..907f085
--- /dev/null
+++ b/test/overlay/Makefile
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2016 NextThing Co
+# Copyright (c) 2016 Free Electrons
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+# Test files
+obj-y += cmd_ut_overlay.o
+
+DTC_FLAGS += -@
+
+# DT overlays
+obj-y += test-fdt-base.dtb.o
+obj-y += test-fdt-overlay.dtb.o
diff --git a/test/overlay/cmd_ut_overlay.c b/test/overlay/cmd_ut_overlay.c
new file mode 100644
index 0000000..87dc932
--- /dev/null
+++ b/test/overlay/cmd_ut_overlay.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <errno.h>
+#include <malloc.h>
+
+#include <linux/sizes.h>
+
+#include <test/ut.h>
+#include <test/overlay.h>
+
+/* 4k ought to be enough for anybody */
+#define FDT_COPY_SIZE	(4 * SZ_1K)
+
+extern u32 __dtb_test_fdt_base_begin;
+extern u32 __dtb_test_fdt_overlay_begin;
+
+static int fdt_getprop_u32_by_index(void *fdt, const char *path,
+				    const char *name, int index,
+				    u32 *out)
+{
+	const fdt32_t *val;
+	int node_off;
+	int len;
+
+	node_off = fdt_path_offset(fdt, path);
+	if (node_off < 0)
+		return node_off;
+
+	val = fdt_getprop(fdt, node_off, name, &len);
+	if (!val || (len < (sizeof(uint32_t) * (index + 1))))
+		return -FDT_ERR_NOTFOUND;
+
+	*out = fdt32_to_cpu(*(val + index));
+
+	return 0;
+}
+
+static int fdt_getprop_u32(void *fdt, const char *path, const char *name,
+			   u32 *out)
+{
+	return fdt_getprop_u32_by_index(fdt, path, name, 0, out);
+}
+
+static int fdt_getprop_str(void *fdt, const char *path, const char *name,
+			   const char **out)
+{
+	int node_off;
+
+	node_off = fdt_path_offset(fdt, path);
+	if (node_off < 0)
+		return node_off;
+
+	return fdt_get_string(fdt, node_off, name, out);
+}
+
+static int fdt_overlay_change_int_property(struct unit_test_state *uts)
+{
+	void *fdt = uts->priv;
+	u32 val = 0;
+
+	ut_assertok(fdt_getprop_u32(fdt, "/test-node", "test-int-property",
+				    &val));
+	ut_asserteq(43, val);
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_change_int_property, 0);
+
+static int fdt_overlay_change_str_property(struct unit_test_state *uts)
+{
+	void *fdt = uts->priv;
+	const char *val = NULL;
+
+	ut_assertok(fdt_getprop_str(fdt, "/test-node", "test-str-property",
+				    &val));
+	ut_asserteq_str("foobar", val);
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_change_str_property, 0);
+
+static int fdt_overlay_add_str_property(struct unit_test_state *uts)
+{
+	void *fdt = uts->priv;
+	const char *val = NULL;
+
+	ut_assertok(fdt_getprop_str(fdt, "/test-node", "test-str-property-2",
+				    &val));
+	ut_asserteq_str("foobar2", val);
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_add_str_property, 0);
+
+static int fdt_overlay_add_node_by_phandle(struct unit_test_state *uts)
+{
+	void *fdt = uts->priv;
+	int off;
+
+	off = fdt_path_offset(fdt, "/test-node/new-node");
+	ut_assert(off >= 0);
+
+	ut_assertnonnull(fdt_getprop(fdt, off, "new-property", NULL));
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_add_node_by_phandle, 0);
+
+static int fdt_overlay_add_node_by_path(struct unit_test_state *uts)
+{
+	void *fdt = uts->priv;
+	int off;
+
+	off = fdt_path_offset(fdt, "/new-node");
+	ut_assert(off >= 0);
+
+	ut_assertnonnull(fdt_getprop(fdt, off, "new-property", NULL));
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_add_node_by_path, 0);
+
+static int fdt_overlay_add_subnode_property(struct unit_test_state *uts)
+{
+	void *fdt = uts->priv;
+	int off;
+
+	off = fdt_path_offset(fdt, "/test-node/sub-test-node");
+	ut_assert(off >= 0);
+
+	ut_assertnonnull(fdt_getprop(fdt, off, "sub-test-property", NULL));
+	ut_assertnonnull(fdt_getprop(fdt, off, "new-sub-test-property", NULL));
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_add_subnode_property, 0);
+
+static int fdt_overlay_local_phandle(struct unit_test_state *uts)
+{
+	uint32_t local_phandle;
+	void *fdt = uts->priv;
+	u32 val = 0;
+	int off;
+
+	off = fdt_path_offset(fdt, "/new-local-node");
+	ut_assert(off >= 0);
+
+	local_phandle = fdt_get_phandle(fdt, off);
+	ut_assert(local_phandle);
+
+	ut_assertok(fdt_getprop_u32_by_index(fdt, "/", "test-several-phandle",
+					     0, &val));
+	ut_asserteq(local_phandle, val);
+
+	ut_assertok(fdt_getprop_u32_by_index(fdt, "/", "test-several-phandle",
+					     1, &val));
+	ut_asserteq(local_phandle, val);
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_local_phandle, 0);
+
+static int fdt_overlay_local_phandles(struct unit_test_state *uts)
+{
+	uint32_t local_phandle, test_phandle;
+	void *fdt = uts->priv;
+	u32 val = 0;
+	int off;
+
+	off = fdt_path_offset(fdt, "/new-local-node");
+	ut_assert(off >= 0);
+
+	local_phandle = fdt_get_phandle(fdt, off);
+	ut_assert(local_phandle);
+
+	off = fdt_path_offset(fdt, "/test-node");
+	ut_assert(off >= 0);
+
+	test_phandle = fdt_get_phandle(fdt, off);
+	ut_assert(test_phandle);
+
+	ut_assertok(fdt_getprop_u32_by_index(fdt, "/", "test-phandle", 0,
+					     &val));
+	ut_asserteq(test_phandle, val);
+
+	ut_assertok(fdt_getprop_u32_by_index(fdt, "/", "test-phandle", 1,
+					     &val));
+	ut_asserteq(local_phandle, val);
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_local_phandles, 0);
+
+int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	struct unit_test *tests = ll_entry_start(struct unit_test,
+						 overlay_test);
+	const int n_ents = ll_entry_count(struct unit_test, overlay_test);
+	struct unit_test_state *uts;
+	struct unit_test *test;
+	void *fdt_base = &__dtb_test_fdt_base_begin;
+	void *fdt_overlay = &__dtb_test_fdt_overlay_begin;
+	void *fdt_base_copy, *fdt_overlay_copy;
+
+	uts = calloc(1, sizeof(*uts));
+	if (!uts)
+		return -ENOMEM;
+
+	ut_assertok(fdt_check_header(fdt_base));
+	ut_assertok(fdt_check_header(fdt_overlay));
+
+	fdt_base_copy = malloc(FDT_COPY_SIZE);
+	if (!fdt_base_copy)
+		return -ENOMEM;
+	uts->priv = fdt_base_copy;
+
+	fdt_overlay_copy = malloc(FDT_COPY_SIZE);
+	if (!fdt_overlay_copy)
+		return -ENOMEM;
+
+	/*
+	 * Resize the FDT to 4k so that we have room to operate on
+	 *
+	 * (and relocate it since the memory might be mapped
+	 * read-only)
+	 */
+	ut_assertok(fdt_open_into(fdt_base, fdt_base_copy, FDT_COPY_SIZE));
+
+	/*
+	 * Resize the overlay to 4k so that we have room to operate on
+	 *
+	 * (and relocate it since the memory might be mapped
+	 * read-only)
+	 */
+	ut_assertok(fdt_open_into(fdt_overlay, fdt_overlay_copy,
+				  FDT_COPY_SIZE));
+
+	/* Apply the overlay */
+	ut_assertok(fdt_overlay_apply(fdt_base_copy, fdt_overlay_copy));
+
+	if (argc == 1)
+		printf("Running %d environment tests\n", n_ents);
+
+	for (test = tests; test < tests + n_ents; test++) {
+		if (argc > 1 && strcmp(argv[1], test->name))
+			continue;
+		printf("Test: %s\n", test->name);
+
+		uts->start = mallinfo();
+
+		test->func(uts);
+	}
+
+	printf("Failures: %d\n", uts->fail_count);
+
+	free(fdt_overlay_copy);
+	free(fdt_base_copy);
+	free(uts);
+
+	return uts->fail_count ? CMD_RET_FAILURE : 0;
+}
diff --git a/test/overlay/test-fdt-base.dts b/test/overlay/test-fdt-base.dts
new file mode 100644
index 0000000..2603adb
--- /dev/null
+++ b/test/overlay/test-fdt-base.dts
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+
+/ {
+	test: test-node {
+		test-int-property = <42>;
+		test-str-property = "foo";
+
+		subtest: sub-test-node {
+			sub-test-property;
+		};
+	};
+};
+
+
diff --git a/test/overlay/test-fdt-overlay.dts b/test/overlay/test-fdt-overlay.dts
new file mode 100644
index 0000000..d30ecdf
--- /dev/null
+++ b/test/overlay/test-fdt-overlay.dts
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+/plugin/;
+
+/ {
+	/* Test that we can change an int by another */
+	fragment@0 {
+		target = <&test>;
+
+		__overlay__ {
+			test-int-property = <43>;
+		};
+	};
+
+	/* Test that we can replace a string by a longer one */
+	fragment@1 {
+		target = <&test>;
+
+		__overlay__ {
+			test-str-property = "foobar";
+		};
+	};
+
+	/* Test that we add a new property */
+	fragment@2 {
+		target = <&test>;
+
+		__overlay__ {
+			test-str-property-2 = "foobar2";
+		};
+	};
+
+	/* Test that we add a new node (by phandle) */
+	fragment@3 {
+		target = <&test>;
+
+		__overlay__ {
+			new-node {
+				new-property;
+			};
+		};
+	};
+
+	/* Test that we add a new node (by path) */
+	fragment@4 {
+		target-path = "/";
+
+		__overlay__ {
+			new-node {
+				new-property;
+			};
+		};
+	};
+
+	fragment@5 {
+		target-path = "/";
+
+		__overlay__ {
+			local: new-local-node {
+				new-property;
+			};
+		};
+	};
+
+	fragment@6 {
+		target-path = "/";
+
+		__overlay__ {
+			test-phandle = <&test>, <&local>;
+		};
+	};
+
+	fragment@7 {
+		target-path = "/";
+
+		__overlay__ {
+			test-several-phandle = <&local>, <&local>;
+		};
+	};
+
+	fragment@8 {
+		target = <&test>;
+
+		__overlay__ {
+			sub-test-node {
+				new-sub-test-property;
+			};
+		};
+	};
+};
diff --git a/test/py/conftest.py b/test/py/conftest.py
index 449f98b..5b3a923 100644
--- a/test/py/conftest.py
+++ b/test/py/conftest.py
@@ -179,6 +179,7 @@
     ubconfig.board_type = board_type
     ubconfig.board_identity = board_identity
     ubconfig.gdbserver = gdbserver
+    ubconfig.dtb = build_dir + '/arch/sandbox/dts/test.dtb'
 
     env_vars = (
         'board_type',
@@ -192,7 +193,7 @@
     for v in env_vars:
         os.environ['U_BOOT_' + v.upper()] = getattr(ubconfig, v)
 
-    if board_type == 'sandbox':
+    if board_type.startswith('sandbox'):
         import u_boot_console_sandbox
         console = u_boot_console_sandbox.ConsoleSandbox(log, ubconfig)
     else:
diff --git a/test/py/multiplexed_log.py b/test/py/multiplexed_log.py
index 68917eb..bf926c3 100644
--- a/test/py/multiplexed_log.py
+++ b/test/py/multiplexed_log.py
@@ -101,6 +101,8 @@
         self.logfile = logfile
         self.name = name
         self.chained_file = chained_file
+        self.output = None
+        self.exit_status = None
 
     def close(self):
         """Clean up any resources managed by this object."""
@@ -109,6 +111,9 @@
     def run(self, cmd, cwd=None, ignore_errors=False):
         """Run a command as a sub-process, and log the results.
 
+        The output is available at self.output which can be useful if there is
+        an exception.
+
         Args:
             cmd: The command to execute.
             cwd: The directory to run the command in. Can be None to use the
@@ -119,7 +124,7 @@
                 raised if such problems occur.
 
         Returns:
-            Nothing.
+            The output as a string.
         """
 
         msg = '+' + ' '.join(cmd) + '\n'
@@ -159,8 +164,13 @@
         self.logfile.write(self, output)
         if self.chained_file:
             self.chained_file.write(output)
+
+        # Store the output so it can be accessed if we raise an exception.
+        self.output = output
+        self.exit_status = exit_status
         if exception:
             raise exception
+        return output
 
 class SectionCtxMgr(object):
     """A context manager for Python's "with" statement, which allows a certain
diff --git a/test/py/tests/test_ofplatdata.py b/test/py/tests/test_ofplatdata.py
new file mode 100644
index 0000000..457c405
--- /dev/null
+++ b/test/py/tests/test_ofplatdata.py
@@ -0,0 +1,42 @@
+# Copyright (c) 2016 Google, Inc
+#
+# SPDX-License-Identifier: GPL-2.0+
+
+import pytest
+
+OF_PLATDATA_OUTPUT = '''
+of-platdata probe:
+bool 1
+byte 05
+bytearray 06 00 00
+int 1
+intarray 2 3 4 0
+longbytearray 09 0a 0b 0c 0d 0e 0f 10 11
+string message
+stringarray "multi-word" "message" ""
+of-platdata probe:
+bool 0
+byte 08
+bytearray 01 23 34
+int 3
+intarray 5 0 0 0
+longbytearray 09 00 00 00 00 00 00 00 00
+string message2
+stringarray "another" "multi-word" "message"
+of-platdata probe:
+bool 0
+byte 00
+bytearray 00 00 00
+int 0
+intarray 0 0 0 0
+longbytearray 00 00 00 00 00 00 00 00 00
+string <NULL>
+stringarray "one" "" ""
+'''
+
+@pytest.mark.buildconfigspec('spl_of_platdata')
+def test_ofplatdata(u_boot_console):
+    """Test that of-platdata can be generated and used in sandbox"""
+    cons = u_boot_console
+    output = cons.get_spawn_output().replace('\r', '')
+    assert OF_PLATDATA_OUTPUT in output
diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py
new file mode 100644
index 0000000..021892b
--- /dev/null
+++ b/test/py/tests/test_vboot.py
@@ -0,0 +1,194 @@
+# Copyright (c) 2016, Google Inc.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+# U-Boot Verified Boot Test
+
+"""
+This tests verified boot in the following ways:
+
+For image verification:
+- Create FIT (unsigned) with mkimage
+- Check that verification shows that no keys are verified
+- Sign image
+- Check that verification shows that a key is now verified
+
+For configuration verification:
+- Corrupt signature and check for failure
+- Create FIT (with unsigned configuration) with mkimage
+- Check that image verification works
+- Sign the FIT and mark the key as 'required' for verification
+- Check that image verification works
+- Corrupt the signature
+- Check that image verification no-longer works
+
+Tests run with both SHA1 and SHA256 hashing.
+"""
+
+import pytest
+import sys
+import u_boot_utils as util
+
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('fit_signature')
+def test_vboot(u_boot_console):
+    """Test verified boot signing with mkimage and verification with 'bootm'.
+
+    This works using sandbox only as it needs to update the device tree used
+    by U-Boot to hold public keys from the signing process.
+
+    The SHA1 and SHA256 tests are combined into a single test since the
+    key-generation process is quite slow and we want to avoid doing it twice.
+    """
+    def dtc(dts):
+        """Run the device tree compiler to compile a .dts file
+
+        The output file will be the same as the input file but with a .dtb
+        extension.
+
+        Args:
+            dts: Device tree file to compile.
+        """
+        dtb = dts.replace('.dts', '.dtb')
+        util.run_and_log(cons, 'dtc %s %s%s -O dtb '
+                         '-o %s%s' % (dtc_args, datadir, dts, tmpdir, dtb))
+
+    def run_bootm(sha_algo, test_type, expect_string):
+        """Run a 'bootm' command U-Boot.
+
+        This always starts a fresh U-Boot instance since the device tree may
+        contain a new public key.
+
+        Args:
+            test_type: A string identifying the test type.
+            expect_string: A string which is expected in the output.
+            sha_algo: Either 'sha1' or 'sha256', to select the algorithm to
+                    use.
+        """
+        cons.restart_uboot()
+        with cons.log.section('Verified boot %s %s' % (sha_algo, test_type)):
+            output = cons.run_command_list(
+                ['sb load hostfs - 100 %stest.fit' % tmpdir,
+                'fdt addr 100',
+                'bootm 100'])
+        assert(expect_string in ''.join(output))
+
+    def make_fit(its):
+        """Make a new FIT from the .its source file.
+
+        This runs 'mkimage -f' to create a new FIT.
+
+        Args:
+            its: Filename containing .its source.
+        """
+        util.run_and_log(cons, [mkimage, '-D', dtc_args, '-f',
+                                '%s%s' % (datadir, its), fit])
+
+    def sign_fit(sha_algo):
+        """Sign the FIT
+
+        Signs the FIT and writes the signature into it. It also writes the
+        public key into the dtb.
+
+        Args:
+            sha_algo: Either 'sha1' or 'sha256', to select the algorithm to
+                    use.
+        """
+        cons.log.action('%s: Sign images' % sha_algo)
+        util.run_and_log(cons, [mkimage, '-F', '-k', tmpdir, '-K', dtb,
+                                '-r', fit])
+
+    def test_with_algo(sha_algo):
+        """Test verified boot with the given hash algorithm.
+
+        This is the main part of the test code. The same procedure is followed
+        for both hashing algorithms.
+
+        Args:
+            sha_algo: Either 'sha1' or 'sha256', to select the algorithm to
+                    use.
+        """
+        # Compile our device tree files for kernel and U-Boot. These are
+        # regenerated here since mkimage will modify them (by adding a
+        # public key) below.
+        dtc('sandbox-kernel.dts')
+        dtc('sandbox-u-boot.dts')
+
+        # Build the FIT, but don't sign anything yet
+        cons.log.action('%s: Test FIT with signed images' % sha_algo)
+        make_fit('sign-images-%s.its' % sha_algo)
+        run_bootm(sha_algo, 'unsigned images', 'dev-')
+
+        # Sign images with our dev keys
+        sign_fit(sha_algo)
+        run_bootm(sha_algo, 'signed images', 'dev+')
+
+        # Create a fresh .dtb without the public keys
+        dtc('sandbox-u-boot.dts')
+
+        cons.log.action('%s: Test FIT with signed configuration' % sha_algo)
+        make_fit('sign-configs-%s.its' % sha_algo)
+        run_bootm(sha_algo, 'unsigned config', '%s+ OK' % sha_algo)
+
+        # Sign images with our dev keys
+        sign_fit(sha_algo)
+        run_bootm(sha_algo, 'signed config', 'dev+')
+
+        cons.log.action('%s: Check signed config on the host' % sha_algo)
+
+        util.run_and_log(cons, [fit_check_sign, '-f', fit, '-k', tmpdir,
+                                '-k', dtb])
+
+        # Increment the first byte of the signature, which should cause failure
+        sig = util.run_and_log(cons, 'fdtget -t bx %s %s value' %
+                               (fit, sig_node))
+        byte_list = sig.split()
+        byte = int(byte_list[0], 16)
+        byte_list[0] = '%x' % (byte + 1)
+        sig = ' '.join(byte_list)
+        util.run_and_log(cons, 'fdtput -t bx %s %s value %s' %
+                         (fit, sig_node, sig))
+
+        run_bootm(sha_algo, 'Signed config with bad hash', 'Bad Data Hash')
+
+        cons.log.action('%s: Check bad config on the host' % sha_algo)
+        util.run_and_log_expect_exception(cons, [fit_check_sign, '-f', fit,
+                '-k', dtb], 1, 'Failed to verify required signature')
+
+    cons = u_boot_console
+    tmpdir = cons.config.result_dir + '/'
+    tmp = tmpdir + 'vboot.tmp'
+    datadir = cons.config.source_dir + '/test/py/tests/vboot/'
+    fit = '%stest.fit' % tmpdir
+    mkimage = cons.config.build_dir + '/tools/mkimage'
+    fit_check_sign = cons.config.build_dir + '/tools/fit_check_sign'
+    dtc_args = '-I dts -O dtb -i %s' % tmpdir
+    dtb = '%ssandbox-u-boot.dtb' % tmpdir
+    sig_node = '/configurations/conf@1/signature@1'
+
+    # Create an RSA key pair
+    public_exponent = 65537
+    util.run_and_log(cons, 'openssl genpkey -algorithm RSA -out %sdev.key '
+                     '-pkeyopt rsa_keygen_bits:2048 '
+                     '-pkeyopt rsa_keygen_pubexp:%d '
+                     '2>/dev/null'  % (tmpdir, public_exponent))
+
+    # Create a certificate containing the public key
+    util.run_and_log(cons, 'openssl req -batch -new -x509 -key %sdev.key -out '
+                     '%sdev.crt' % (tmpdir, tmpdir))
+
+    # Create a number kernel image with zeroes
+    with open('%stest-kernel.bin' % tmpdir, 'w') as fd:
+        fd.write(5000 * chr(0))
+
+    try:
+        # We need to use our own device tree file. Remember to restore it
+        # afterwards.
+        old_dtb = cons.config.dtb
+        cons.config.dtb = dtb
+        test_with_algo('sha1')
+        test_with_algo('sha256')
+    finally:
+        # Go back to the original U-Boot with the correct dtb.
+        cons.config.dtb = old_dtb
+        cons.restart_uboot()
diff --git a/test/vboot/sandbox-kernel.dts b/test/py/tests/vboot/sandbox-kernel.dts
similarity index 100%
rename from test/vboot/sandbox-kernel.dts
rename to test/py/tests/vboot/sandbox-kernel.dts
diff --git a/test/vboot/sandbox-u-boot.dts b/test/py/tests/vboot/sandbox-u-boot.dts
similarity index 100%
rename from test/vboot/sandbox-u-boot.dts
rename to test/py/tests/vboot/sandbox-u-boot.dts
diff --git a/test/vboot/sign-configs-sha1.its b/test/py/tests/vboot/sign-configs-sha1.its
similarity index 100%
rename from test/vboot/sign-configs-sha1.its
rename to test/py/tests/vboot/sign-configs-sha1.its
diff --git a/test/vboot/sign-configs-sha256.its b/test/py/tests/vboot/sign-configs-sha256.its
similarity index 100%
rename from test/vboot/sign-configs-sha256.its
rename to test/py/tests/vboot/sign-configs-sha256.its
diff --git a/test/vboot/sign-images-sha1.its b/test/py/tests/vboot/sign-images-sha1.its
similarity index 100%
rename from test/vboot/sign-images-sha1.its
rename to test/py/tests/vboot/sign-images-sha1.its
diff --git a/test/vboot/sign-images-sha256.its b/test/py/tests/vboot/sign-images-sha256.its
similarity index 100%
rename from test/vboot/sign-images-sha256.its
rename to test/py/tests/vboot/sign-images-sha256.its
diff --git a/test/py/u_boot_console_base.py b/test/py/u_boot_console_base.py
index 815fa64..b1f4742 100644
--- a/test/py/u_boot_console_base.py
+++ b/test/py/u_boot_console_base.py
@@ -106,7 +106,7 @@
 
         # Array slice removes leading/trailing quotes
         self.prompt = self.config.buildconfig['config_sys_prompt'][1:-1]
-        self.prompt_escaped = re.escape(self.prompt)
+        self.prompt_compiled = re.compile('^' + re.escape(self.prompt), re.MULTILINE)
         self.p = None
         self.disable_check_count = {pat[PAT_ID]: 0 for pat in bad_pattern_defs}
         self.eval_bad_patterns()
@@ -201,7 +201,7 @@
                                     self.bad_pattern_ids[m - 1])
             if not wait_for_prompt:
                 return
-            m = self.p.expect([self.prompt_escaped] + self.bad_patterns)
+            m = self.p.expect([self.prompt_compiled] + self.bad_patterns)
             if m != 0:
                 self.at_prompt = False
                 raise Exception('Bad pattern found on console: ' +
@@ -216,6 +216,23 @@
             self.cleanup_spawn()
             raise
 
+    def run_command_list(self, cmds):
+        """Run a list of commands.
+
+        This is a helper function to call run_command() with default arguments
+        for each command in a list.
+
+        Args:
+            cmd: List of commands (each a string).
+        Returns:
+            A list of output strings from each command, one element for each
+            command.
+        """
+        output = []
+        for cmd in cmds:
+            output.append(self.run_command(cmd))
+        return output
+
     def ctrlc(self):
         """Send a CTRL-C character to U-Boot.
 
@@ -329,7 +346,7 @@
                 m = self.p.expect([pattern_u_boot_spl_signon] +
                                   self.bad_patterns)
                 if m != 0:
-                    raise Exception('Bad pattern found on console: ' +
+                    raise Exception('Bad pattern found on SPL console: ' +
                                     self.bad_pattern_ids[m - 1])
             m = self.p.expect([pattern_u_boot_main_signon] + self.bad_patterns)
             if m != 0:
@@ -337,7 +354,7 @@
                                 self.bad_pattern_ids[m - 1])
             self.u_boot_version_string = self.p.after
             while True:
-                m = self.p.expect([self.prompt_escaped,
+                m = self.p.expect([self.prompt_compiled,
                     pattern_stop_autoboot_prompt] + self.bad_patterns)
                 if m == 0:
                     break
@@ -377,6 +394,21 @@
             pass
         self.p = None
 
+    def restart_uboot(self):
+        """Shut down and restart U-Boot."""
+        self.cleanup_spawn()
+        self.ensure_spawned()
+
+    def get_spawn_output(self):
+        """Return the start-up output from U-Boot
+
+        Returns:
+            The output produced by ensure_spawed(), as a string.
+        """
+        if self.p:
+            return self.p.get_expect_output()
+        return None
+
     def validate_version_string_in_text(self, text):
         """Assert that a command's output includes the U-Boot signon message.
 
diff --git a/test/py/u_boot_console_sandbox.py b/test/py/u_boot_console_sandbox.py
index 04654ae..647e1f8 100644
--- a/test/py/u_boot_console_sandbox.py
+++ b/test/py/u_boot_console_sandbox.py
@@ -39,14 +39,18 @@
             A u_boot_spawn.Spawn object that is attached to U-Boot.
         """
 
+        bcfg = self.config.buildconfig
+        config_spl = bcfg.get('config_spl', 'n') == 'y'
+        fname = '/spl/u-boot-spl' if config_spl else '/u-boot'
+        print fname
         cmd = []
         if self.config.gdbserver:
             cmd += ['gdbserver', self.config.gdbserver]
         cmd += [
-            self.config.build_dir + '/u-boot',
+            self.config.build_dir + fname,
             '-v',
             '-d',
-            self.config.build_dir + '/arch/sandbox/dts/test.dtb'
+            self.config.dtb
         ]
         return Spawn(cmd, cwd=self.config.source_dir)
 
diff --git a/test/py/u_boot_spawn.py b/test/py/u_boot_spawn.py
index a5f4a8e..3a0fbfa 100644
--- a/test/py/u_boot_spawn.py
+++ b/test/py/u_boot_spawn.py
@@ -18,6 +18,9 @@
 class Spawn(object):
     """Represents the stdio of a freshly created sub-process. Commands may be
     sent to the process, and responses waited for.
+
+    Members:
+        output: accumulated output from expect()
     """
 
     def __init__(self, args, cwd=None):
@@ -34,10 +37,16 @@
 
         self.waited = False
         self.buf = ''
+        self.output = ''
         self.logfile_read = None
         self.before = ''
         self.after = ''
         self.timeout = None
+        # http://stackoverflow.com/questions/7857352/python-regex-to-match-vt100-escape-sequences
+        # Note that re.I doesn't seem to work with this regex (or perhaps the
+        # version of Python in Ubuntu 14.04), hence the inclusion of a-z inside
+        # [] instead.
+        self.re_vt100 = re.compile('(\x1b\[|\x9b)[^@-_a-z]*[@-_a-z]|\x1b[@-_a-z]')
 
         (self.pid, self.fd) = pty.fork()
         if self.pid == 0:
@@ -149,6 +158,7 @@
                     posafter = earliest_m.end()
                     self.before = self.buf[:pos]
                     self.after = self.buf[pos:posafter]
+                    self.output += self.buf[:posafter]
                     self.buf = self.buf[posafter:]
                     return earliest_pi
                 tnow_s = time.time()
@@ -168,6 +178,10 @@
                 if self.logfile_read:
                     self.logfile_read.write(c)
                 self.buf += c
+                # count=0 is supposed to be the default, which indicates
+                # unlimited substitutions, but in practice the version of
+                # Python in Ubuntu 14.04 appears to default to count=2!
+                self.buf = self.re_vt100.sub('', self.buf, count=1000000)
         finally:
             if self.logfile_read:
                 self.logfile_read.flush()
@@ -189,3 +203,11 @@
             if not self.isalive():
                 break
             time.sleep(0.1)
+
+    def get_expect_output(self):
+        """Return the output read by expect()
+
+        Returns:
+            The output processed by expect(), as a string.
+        """
+        return self.output
diff --git a/test/py/u_boot_utils.py b/test/py/u_boot_utils.py
index 6a6b2ec..2ba4bae 100644
--- a/test/py/u_boot_utils.py
+++ b/test/py/u_boot_utils.py
@@ -158,19 +158,47 @@
 
     Args:
         u_boot_console: A console connection to U-Boot.
-        cmd: The command to run, as an array of argv[].
+        cmd: The command to run, as an array of argv[], or a string.
+            If a string, note that it is split up so that quoted spaces
+            will not be preserved. E.g. "fred and" becomes ['"fred', 'and"']
         ignore_errors: Indicate whether to ignore errors. If True, the function
             will simply return if the command cannot be executed or exits with
             an error code, otherwise an exception will be raised if such
             problems occur.
 
     Returns:
-        Nothing.
+        The output as a string.
     """
-
+    if isinstance(cmd, str):
+        cmd = cmd.split()
     runner = u_boot_console.log.get_runner(cmd[0], sys.stdout)
-    runner.run(cmd, ignore_errors=ignore_errors)
+    output = runner.run(cmd, ignore_errors=ignore_errors)
     runner.close()
+    return output
+
+def run_and_log_expect_exception(u_boot_console, cmd, retcode, msg):
+    """Run a command that is expected to fail.
+
+    This runs a command and checks that it fails with the expected return code
+    and exception method. If not, an exception is raised.
+
+    Args:
+        u_boot_console: A console connection to U-Boot.
+        cmd: The command to run, as an array of argv[].
+        retcode: Expected non-zero return code from the command.
+        msg: String that should be contained within the command's output.
+    """
+    try:
+        runner = u_boot_console.log.get_runner(cmd[0], sys.stdout)
+        runner.run(cmd)
+    except Exception as e:
+        assert(retcode == runner.exit_status)
+        assert(msg in runner.output)
+    else:
+        raise Exception("Expected an exception with retcode %d message '%s',"
+                        "but it was not raised" % (retcode, msg))
+    finally:
+        runner.close()
 
 ram_base = None
 def find_ram_base(u_boot_console):
@@ -201,7 +229,7 @@
     with u_boot_console.log.section('find_ram_base'):
         response = u_boot_console.run_command('bdinfo')
         for l in response.split('\n'):
-            if '-> start' in l:
+            if '-> start' in l or 'memstart    =' in l:
                 ram_base = int(l.split('=')[1].strip(), 16)
                 break
         if ram_base is None:
diff --git a/test/run b/test/run
new file mode 100755
index 0000000..a6dcf8f
--- /dev/null
+++ b/test/run
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+# Run all tests
+./test/py/test.py --bd sandbox --build
diff --git a/test/vboot/.gitignore b/test/vboot/.gitignore
deleted file mode 100644
index 4631242..0000000
--- a/test/vboot/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-/*.dtb
-/test.fit
-/dev-keys
diff --git a/test/vboot/vboot_test.sh b/test/vboot/vboot_test.sh
deleted file mode 100755
index 6d7abb8..0000000
--- a/test/vboot/vboot_test.sh
+++ /dev/null
@@ -1,151 +0,0 @@
-#!/bin/bash
-#
-# Copyright (c) 2013, Google Inc.
-#
-# Simple Verified Boot Test Script
-#
-# SPDX-License-Identifier:	GPL-2.0+
-
-set -e
-
-# Run U-Boot and report the result
-# Args:
-#	$1:	Test message
-run_uboot() {
-	echo -n "Test Verified Boot Run: $1: "
-	${uboot} -d sandbox-u-boot.dtb >${tmp} -c '
-sb load hostfs - 100 test.fit;
-fdt addr 100;
-bootm 100;
-reset'
-	if ! grep -q "$2" ${tmp}; then
-		echo
-		echo "Verified boot key check failed, output follows:"
-		cat ${tmp}
-		false
-	else
-		echo "OK"
-	fi
-}
-
-echo "Simple Verified Boot Test"
-echo "========================="
-echo
-echo "Please see doc/uImage.FIT/verified-boot.txt for more information"
-echo
-
-err=0
-tmp=/tmp/vboot_test.$$
-
-dir=$(dirname $0)
-
-if [ -z ${O} ]; then
-	O=.
-fi
-O=$(readlink -f ${O})
-
-dtc="-I dts -O dtb -p 2000"
-uboot="${O}/u-boot"
-mkimage="${O}/tools/mkimage"
-fit_check_sign="${O}/tools/fit_check_sign"
-keys="${dir}/dev-keys"
-echo ${mkimage} -D "${dtc}"
-
-echo "Build keys"
-mkdir -p ${keys}
-
-PUBLIC_EXPONENT=${1}
-
-if [ -z "${PUBLIC_EXPONENT}" ]; then
-	PUBLIC_EXPONENT=65537
-fi
-
-# Create an RSA key pair
-openssl genpkey -algorithm RSA -out ${keys}/dev.key \
-    -pkeyopt rsa_keygen_bits:2048 \
-    -pkeyopt rsa_keygen_pubexp:${PUBLIC_EXPONENT} 2>/dev/null
-
-# Create a certificate containing the public key
-openssl req -batch -new -x509 -key ${keys}/dev.key -out ${keys}/dev.crt
-
-pushd ${dir} >/dev/null
-
-function do_test {
-	echo do $sha test
-	# Compile our device tree files for kernel and U-Boot
-	dtc -p 0x1000 sandbox-kernel.dts -O dtb -o sandbox-kernel.dtb
-	dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb
-
-	# Create a number kernel image with zeroes
-	head -c 5000 /dev/zero >test-kernel.bin
-
-	# Build the FIT, but don't sign anything yet
-	echo Build FIT with signed images
-	${mkimage} -D "${dtc}" -f sign-images-$sha.its test.fit >${tmp}
-
-	run_uboot "unsigned signatures:" "dev-"
-
-	# Sign images with our dev keys
-	echo Sign images
-	${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb \
-		-r test.fit >${tmp}
-
-	run_uboot "signed images" "dev+"
-
-
-	# Create a fresh .dtb without the public keys
-	dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb
-
-	echo Build FIT with signed configuration
-	${mkimage} -D "${dtc}" -f sign-configs-$sha.its test.fit >${tmp}
-
-	run_uboot "unsigned config" $sha"+ OK"
-
-	# Sign images with our dev keys
-	echo Sign images
-	${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb \
-		-r test.fit >${tmp}
-
-	run_uboot "signed config" "dev+"
-
-	echo check signed config on the host
-	if ! ${fit_check_sign} -f test.fit -k sandbox-u-boot.dtb >${tmp}; then
-		echo
-		echo "Verified boot key check on host failed, output follows:"
-		cat ${tmp}
-		false
-	else
-		if ! grep -q "dev+" ${tmp}; then
-			echo
-			echo "Verified boot key check failed, output follows:"
-			cat ${tmp}
-			false
-		else
-			echo "OK"
-		fi
-	fi
-
-	run_uboot "signed config" "dev+"
-
-	# Increment the first byte of the signature, which should cause failure
-	sig=$(fdtget -t bx test.fit /configurations/conf@1/signature@1 value)
-	newbyte=$(printf %x $((0x${sig:0:2} + 1)))
-	sig="${newbyte} ${sig:2}"
-	fdtput -t bx test.fit /configurations/conf@1/signature@1 value ${sig}
-
-	run_uboot "signed config with bad hash" "Bad Data Hash"
-}
-
-sha=sha1
-do_test
-sha=sha256
-do_test
-
-popd >/dev/null
-
-echo
-if ${ok}; then
-	echo "Test passed"
-else
-	echo "Test failed"
-fi
diff --git a/tools/Makefile b/tools/Makefile
index 63355aa..421414b 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -76,8 +76,6 @@
 			lib/fdtdec.o \
 			fit_common.o \
 			fit_image.o \
-			gpimage.o \
-			gpimage-common.o \
 			common/image-fit.o \
 			image-host.o \
 			common/image.o \
@@ -100,6 +98,8 @@
 			zynqimage.o \
 			zynqmpimage.o \
 			$(LIBFDT_OBJS) \
+			gpimage.o \
+			gpimage-common.o \
 			$(RSA_OBJS-y)
 
 dumpimage-objs := $(dumpimage-mkimage-objs) dumpimage.o
@@ -107,6 +107,20 @@
 fit_info-objs   := $(dumpimage-mkimage-objs) fit_info.o
 fit_check_sign-objs   := $(dumpimage-mkimage-objs) fit_check_sign.o
 
+# Build a libfdt Python module if swig is available
+# Use 'sudo apt-get install swig libpython-dev' to enable this
+hostprogs-$(CONFIG_SPL_OF_PLATDATA) += \
+	$(if $(shell which swig),_libfdt.so)
+_libfdt.so-sharedobjs += $(LIBFDT_OBJS)
+libfdt:
+
+tools/_libfdt.so: $(patsubst %.o,%.c,$(LIBFDT_OBJS)) tools/libfdt_wrap.c
+	python $(srctree)/lib/libfdt/setup.py "$(_hostc_flags)" $^
+	mv _libfdt.so $@
+
+tools/libfdt_wrap.c: $(srctree)/lib/libfdt/libfdt.swig
+	swig -python -o $@ $<
+
 # TODO(sjg@chromium.org): Is this correct on Mac OS?
 
 ifneq ($(CONFIG_MX23)$(CONFIG_MX28),)
diff --git a/tools/buildman/README b/tools/buildman/README
index 26755c5..8c5f861 100644
--- a/tools/buildman/README
+++ b/tools/buildman/README
@@ -5,6 +5,20 @@
 
 (Please read 'How to change from MAKEALL' if you are used to that tool)
 
+Quick-start
+===========
+
+If you just want to quickly set up buildman so you can build something (for
+example Raspberry Pi 2):
+
+   cd /path/to/u-boot
+   PATH=$PATH:`pwd`/tools/buildman
+   buildman --fetch-arch arm
+   buildman -k rpi_2
+   ls ../current/rpi_2
+   # u-boot.bin is the output image
+
+
 What is this?
 =============
 
@@ -22,16 +36,14 @@
 Caveats
 =======
 
-Buildman is still in its infancy. It is already a very useful tool, but
-expect to find problems and send patches.
-
 Buildman can be stopped and restarted, in which case it will continue
 where it left off. This should happen cleanly and without side-effects.
 If not, it is a bug, for which a patch would be welcome.
 
 Buildman gets so tied up in its work that it can ignore the outside world.
 You may need to press Ctrl-C several times to quit it. Also it will print
-out various exceptions when stopped.
+out various exceptions when stopped. You may have to kill it since the
+Ctrl-C handling is somewhat broken.
 
 
 Theory of Operation
@@ -46,6 +58,13 @@
 directories, which you can look at while the build is progressing, or when
 it is finished.
 
+Buildman is designed to build entire git branches, i.e. muliple commits. It
+can be run repeatedly on the same branch. In this case it will automatically
+rebuild commits which have changed (and remove its old results for that
+commit). It is possible to build a branch for one board, then later build it
+for another board. If you want buildman to re-build a commit it has already
+built (e.g. because of a toolchain update), use the -f flag.
+
 Buildman produces a concise summary of which boards succeeded and failed.
 It shows which commit introduced which board failure using a simple
 red/green colour coding. Full error information can be requested, in which
@@ -420,10 +439,7 @@
 
 Or download them all from kernel.org and move them to /toolchains directory,
 
-$ for i in aarch64 arm avr32 i386 m68k microblaze mips or32 powerpc sparc
-  do
-  ./tools/buildman/buildman --fetch-arch $i
-  done
+$ ./tools/buildman/buildman --fetch-arch all
 $ sudo mkdir -p /toolchains
 $ sudo mv ~/.buildman-toolchains/*/* /toolchains/
 
@@ -440,8 +456,8 @@
 sh: http://sourcery.mentor.com/public/gnu_toolchain/sh-linux-gnu/
     renesas-4.4-200-sh-linux-gnu-i686-pc-linux-gnu.tar.bz2
 
-Note openrisc kernel.org toolchain is out of date, download latest one from
-http://opencores.org/or1k/OpenRISC_GNU_tool_chain#Prebuilt_versions, eg:
+Note openrisc kernel.org toolchain is out of date. Download the latest one from
+http://opencores.org/or1k/OpenRISC_GNU_tool_chain#Prebuilt_versions - eg:
 ftp://ocuser:ocuser@openrisc.opencores.org/toolchain/gcc-or1k-elf-4.8.1-x86.tar.bz2.
 
 Buildman should now be set up to use your new toolchain.
@@ -521,7 +537,7 @@
 This means that it is building 19062 board/commit combinations. So far it
 has managed to successfully build 528. Another 36 have built with warnings,
 and 124 more didn't build at all. Buildman expects to complete the process
-in an hour and 15 minutes. Use this time to buy a faster computer.
+in around an hour and a quarter. Use this time to buy a faster computer.
 
 
 To find out how the build went, ask for a summary with -s. You can do this
@@ -556,7 +572,8 @@
 see which ones). But still we can see a few failures. The galaxy5200_LOWBOOT
 never builds correctly. This could be a problem with our toolchain, or it
 could be a bug in the upstream. The good news is that we probably don't need
-to blame our commits. The bad news is it isn't tested on that board.
+to blame our commits. The bad news is that our commits are not tested on that
+board.
 
 Commit 12 broke lubbock. That's what the '+ lubbock' means. The failure
 is never fixed by a later commit, or you would see lubbock again, in green,
@@ -585,19 +602,20 @@
 should be enough to work out what that commit is doing to break these
 boards. (In this case pxa did not have cache operations defined).
 
-If you see error lines marked with - that means that the errors were fixed
+If you see error lines marked with '-', that means that the errors were fixed
 by that commit. Sometimes commits can be in the wrong order, so that a
 breakage is introduced for a few commits and fixed by later commits. This
 shows up clearly with buildman. You can then reorder the commits and try
 again.
 
-At commit 16, the error moves - you can see that the old error at line 120
+At commit 16, the error moves: you can see that the old error at line 120
 is fixed, but there is a new one at line 126. This is probably only because
 we added some code and moved the broken line further down the file.
 
 If many boards have the same error, then -e will display the error only
 once. This makes the output as concise as possible. To see which boards have
-each error, use -l.
+each error, use -l. So it is safe to omit the board name - you will not get
+lots of repeated output for every board.
 
 Buildman tries to distinguish warnings from errors, and shows warning lines
 separately with a 'w' prefix.
@@ -619,8 +637,8 @@
 
    sizes: Shows image size information.
 
-It is possible to get the build output there also. Use the -k option for
-this. In that case you will also see some output files, like:
+It is possible to get the build binary output there also. Use the -k option
+for this. In that case you will also see some output files, like:
 
    System.map  toolchain  u-boot  u-boot.bin  u-boot.map  autoconf.mk
    (also SPL versions u-boot-spl and u-boot-spl.bin if available)
@@ -631,7 +649,7 @@
 
 A key requirement for U-Boot is that you keep code/data size to a minimum.
 Where a new feature increases this noticeably it should normally be put
-behind a CONFIG flag so that boards can leave it off and keep the image
+behind a CONFIG flag so that boards can leave it disabled and keep the image
 size more or less the same with each new release.
 
 To check the impact of your commits on image size, use -S. For example:
@@ -670,12 +688,13 @@
 --step 2 will show the image sizes for only every 2nd commit (so it will
 compare the image sizes of the 1st, 3rd, 5th... commits). You can also use
 --step 0 which will compare only the first and last commits. This is useful
-for an overview of how your entire series affects code size.
+for an overview of how your entire series affects code size. It will build
+only the upstream commit and your final branch commit.
 
 You can also use -d to see a detailed size breakdown for each board. This
 list is sorted in order from largest growth to largest reduction.
 
-It is possible to go a little further with the -B option (--bloat). This
+It is even possible to go a little further with the -B option (--bloat). This
 shows where U-Boot has bloated, breaking the size change down to the function
 level. Example output is below:
 
@@ -798,9 +817,9 @@
 ...
 
 
-This shows that commit 19 has increased text size for arm (although only one
-board was built) and by 96 bytes for powerpc. This increase was offset in both
-cases by reductions in rodata and data/bss.
+This shows that commit 19 has reduced codesize for arm slightly and increased
+it for powerpc. This increase was offset in by reductions in rodata and
+data/bss.
 
 Shown below the summary lines are the sizes for each board. Below each board
 are the sizes for each function. This information starts with:
@@ -1063,6 +1082,8 @@
 problems, perhaps by building a few boards for each arch, or checking
 commits for changed files and building only boards which use those files.
 
+A specific problem to fix is that Ctrl-C does not exit buildman cleanly when
+multiple builder threads are active.
 
 Credits
 =======
diff --git a/tools/buildman/bsettings.py b/tools/buildman/bsettings.py
index b361469..892cfa0 100644
--- a/tools/buildman/bsettings.py
+++ b/tools/buildman/bsettings.py
@@ -22,6 +22,10 @@
         config_fname = fname
         if config_fname == '':
             config_fname = '%s/.buildman' % os.getenv('HOME')
+        if not os.path.exists(config_fname):
+            print 'No config file found ~/.buildman\nCreating one...\n'
+            CreateBuildmanConfigFile(config_fname)
+            print 'To install tool chains, please use the --fetch-arch option'
         if config_fname:
             settings.read(config_fname)
 
@@ -53,3 +57,43 @@
     if config_fname is not None:
         with open(config_fname, 'w') as fd:
             settings.write(fd)
+
+def CreateBuildmanConfigFile(config_fname):
+    """Creates a new config file with no tool chain information.
+
+    Args:
+        config_fname: Config filename to create
+
+    Returns:
+        None
+    """
+    try:
+        f = open(config_fname, 'w')
+    except IOError:
+        print "Couldn't create buildman config file '%s'\n" % config_fname
+        raise
+
+    print >>f, '''[toolchain]
+# name = path
+# e.g. x86 = /opt/gcc-4.6.3-nolibc/x86_64-linux
+
+[toolchain-prefix]
+# name = path to prefix
+# e.g. x86 = /opt/gcc-4.6.3-nolibc/x86_64-linux/bin/x86_64-linux-
+
+[toolchain-alias]
+# arch = alias
+# Indicates which toolchain should be used to build for that arch
+x86 = i386
+blackfin = bfin
+nds32 = nds32le
+openrisc = or1k
+
+[make-flags]
+# Special flags to pass to 'make' for certain boards, e.g. to pass a test
+# flag and build tag to snapper boards:
+# snapper-boards=ENABLE_AT91_TEST=1
+# snapper9260=${snapper-boards} BUILD_TAG=442
+# snapper9g45=${snapper-boards} BUILD_TAG=443
+'''
+    f.close();
diff --git a/tools/buildman/control.py b/tools/buildman/control.py
index aeb128a..b86d7b3 100644
--- a/tools/buildman/control.py
+++ b/tools/buildman/control.py
@@ -107,38 +107,44 @@
         return 0
 
     gitutil.Setup()
+    col = terminal.Color()
 
     options.git_dir = os.path.join(options.git, '.git')
 
-    if not toolchains:
+    no_toolchains = toolchains is None
+    if no_toolchains:
         toolchains = toolchain.Toolchains()
-        toolchains.GetSettings()
-        toolchains.Scan(options.list_tool_chains)
-    if options.list_tool_chains:
-        toolchains.List()
-        print
-        return 0
 
     if options.fetch_arch:
         if options.fetch_arch == 'list':
             sorted_list = toolchains.ListArchs()
-            print 'Available architectures: %s\n' % ' '.join(sorted_list)
+            print col.Color(col.BLUE, 'Available architectures: %s\n' %
+                            ' '.join(sorted_list))
             return 0
         else:
             fetch_arch = options.fetch_arch
             if fetch_arch == 'all':
                 fetch_arch = ','.join(toolchains.ListArchs())
-                print 'Downloading toolchains: %s\n' % fetch_arch
+                print col.Color(col.CYAN, '\nDownloading toolchains: %s' %
+                                fetch_arch)
             for arch in fetch_arch.split(','):
+                print
                 ret = toolchains.FetchAndInstall(arch)
                 if ret:
                     return ret
             return 0
 
+    if no_toolchains:
+        toolchains.GetSettings()
+        toolchains.Scan(options.list_tool_chains)
+    if options.list_tool_chains:
+        toolchains.List()
+        print
+        return 0
+
     # Work out how many commits to build. We want to build everything on the
     # branch. We also build the upstream commit as a control so we can see
     # problems introduced by the first commit on the branch.
-    col = terminal.Color()
     count = options.count
     has_range = options.branch and '..' in options.branch
     if count == -1:
diff --git a/tools/buildman/func_test.py b/tools/buildman/func_test.py
index a0bd46c..d439e17 100644
--- a/tools/buildman/func_test.py
+++ b/tools/buildman/func_test.py
@@ -180,7 +180,7 @@
         self._base_dir = tempfile.mkdtemp()
         self._git_dir = os.path.join(self._base_dir, 'src')
         self._buildman_pathname = sys.argv[0]
-        self._buildman_dir = os.path.dirname(sys.argv[0])
+        self._buildman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
         command.test_result = self._HandleCommand
         self.setupToolchains()
         self._toolchains.Add('arm-gcc', test=False)
diff --git a/tools/buildman/toolchain.py b/tools/buildman/toolchain.py
index 3993db3..41e4e4c 100644
--- a/tools/buildman/toolchain.py
+++ b/tools/buildman/toolchain.py
@@ -13,6 +13,7 @@
 
 import bsettings
 import command
+import terminal
 
 (PRIORITY_FULL_PREFIX, PRIORITY_PREFIX_GCC, PRIORITY_PREFIX_GCC_PATH,
     PRIORITY_CALC) = range(4)
@@ -167,18 +168,23 @@
         self.paths = []
         self._make_flags = dict(bsettings.GetItems('make-flags'))
 
-    def GetPathList(self):
+    def GetPathList(self, show_warning=True):
         """Get a list of available toolchain paths
 
+        Args:
+            show_warning: True to show a warning if there are no tool chains.
+
         Returns:
             List of strings, each a path to a toolchain mentioned in the
             [toolchain] section of the settings file.
         """
         toolchains = bsettings.GetItems('toolchain')
-        if not toolchains:
-            print ('Warning: No tool chains - please add a [toolchain] section'
-                 ' to your buildman config file %s. See README for details' %
-                 bsettings.config_fname)
+        if show_warning and not toolchains:
+            print ("Warning: No tool chains. Please run 'buildman "
+                   "--fetch-arch all' to download all available toolchains, or "
+                   "add a [toolchain] section to your buildman config file "
+                   "%s. See README for details" %
+                   bsettings.config_fname)
 
         paths = []
         for name, value in toolchains:
@@ -188,9 +194,14 @@
                 paths.append(value)
         return paths
 
-    def GetSettings(self):
-      self.prefixes = bsettings.GetItems('toolchain-prefix')
-      self.paths += self.GetPathList()
+    def GetSettings(self, show_warning=True):
+        """Get toolchain settings from the settings file.
+
+        Args:
+            show_warning: True to show a warning if there are no tool chains.
+        """
+        self.prefixes = bsettings.GetItems('toolchain-prefix')
+        self.paths += self.GetPathList(show_warning)
 
     def Add(self, fname, test=True, verbose=False, priority=PRIORITY_CALC,
             arch=None):
@@ -286,7 +297,9 @@
 
     def List(self):
         """List out the selected toolchains for each architecture"""
-        print 'List of available toolchains (%d):' % len(self.toolchains)
+        col = terminal.Color()
+        print col.Color(col.BLUE, 'List of available toolchains (%d):' %
+                        len(self.toolchains))
         if len(self.toolchains):
             for key, value in sorted(self.toolchains.iteritems()):
                 print '%-10s: %s' % (key, value.gcc)
@@ -474,12 +487,12 @@
         return stdout.splitlines()[0][:-1]
 
     def TestSettingsHasPath(self, path):
-        """Check if builmand will find this toolchain
+        """Check if buildman will find this toolchain
 
         Returns:
             True if the path is in settings, False if not
         """
-        paths = self.GetPathList()
+        paths = self.GetPathList(False)
         return path in paths
 
     def ListArchs(self):
@@ -501,6 +514,8 @@
             Architecture to fetch, or 'list' to list
         """
         # Fist get the URL for this architecture
+        col = terminal.Color()
+        print col.Color(col.BLUE, "Downloading toolchain for arch '%s'" % arch)
         url = self.LocateArchUrl(arch)
         if not url:
             print ("Cannot find toolchain for arch '%s' - use 'list' to list" %
@@ -515,7 +530,7 @@
         tmpdir, tarfile = self.Download(url)
         if not tarfile:
             return 1
-        print 'Unpacking to: %s' % dest,
+        print col.Color(col.GREEN, 'Unpacking to: %s' % dest),
         sys.stdout.flush()
         path = self.Unpack(tarfile, dest)
         os.remove(tarfile)
@@ -523,22 +538,20 @@
         print
 
         # Check that the toolchain works
-        print 'Testing'
+        print col.Color(col.GREEN, 'Testing')
         dirpath = os.path.join(dest, path)
         compiler_fname_list = self.ScanPath(dirpath, True)
         if not compiler_fname_list:
             print 'Could not locate C compiler - fetch failed.'
             return 1
         if len(compiler_fname_list) != 1:
-            print ('Internal error, ambiguous toolchains: %s' %
-                   (', '.join(compiler_fname)))
-            return 1
+            print col.Color(col.RED, 'Warning, ambiguous toolchains: %s' %
+                            ', '.join(compiler_fname_list))
         toolchain = Toolchain(compiler_fname_list[0], True, True)
 
         # Make sure that it will be found by buildman
         if not self.TestSettingsHasPath(dirpath):
             print ("Adding 'download' to config file '%s'" %
                    bsettings.config_fname)
-            tools_dir = os.path.dirname(dirpath)
-            bsettings.SetItem('toolchain', 'download', '%s/*' % tools_dir)
+            bsettings.SetItem('toolchain', 'download', '%s/*/*' % dest)
         return 0
diff --git a/tools/dtoc/.gitignore b/tools/dtoc/.gitignore
new file mode 100644
index 0000000..0d20b64
--- /dev/null
+++ b/tools/dtoc/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/tools/dtoc/dtoc b/tools/dtoc/dtoc
new file mode 120000
index 0000000..896ca44
--- /dev/null
+++ b/tools/dtoc/dtoc
@@ -0,0 +1 @@
+dtoc.py
\ No newline at end of file
diff --git a/tools/dtoc/dtoc.py b/tools/dtoc/dtoc.py
new file mode 100755
index 0000000..ec80abe
--- /dev/null
+++ b/tools/dtoc/dtoc.py
@@ -0,0 +1,394 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+import copy
+from optparse import OptionError, OptionParser
+import os
+import sys
+
+import fdt_util
+
+# Bring in the patman libraries
+our_path = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(our_path, '../patman'))
+
+# Bring in either the normal fdt library (which relies on libfdt) or the
+# fallback one (which uses fdtget and is slower). Both provide the same
+# interfface for this file to use.
+try:
+    from fdt import Fdt
+    import fdt
+    have_libfdt = True
+except ImportError:
+    have_libfdt = False
+    from fdt_fallback import Fdt
+    import fdt_fallback as fdt
+
+import struct
+
+# When we see these properties we ignore them - i.e. do not create a structure member
+PROP_IGNORE_LIST = [
+    '#address-cells',
+    '#gpio-cells',
+    '#size-cells',
+    'compatible',
+    'linux,phandle',
+    "status",
+    'phandle',
+    'u-boot,dm-pre-reloc',
+]
+
+# C type declarations for the tyues we support
+TYPE_NAMES = {
+    fdt_util.TYPE_INT: 'fdt32_t',
+    fdt_util.TYPE_BYTE: 'unsigned char',
+    fdt_util.TYPE_STRING: 'const char *',
+    fdt_util.TYPE_BOOL: 'bool',
+};
+
+STRUCT_PREFIX = 'dtd_'
+VAL_PREFIX = 'dtv_'
+
+def Conv_name_to_c(name):
+    """Convert a device-tree name to a C identifier
+
+    Args:
+        name:   Name to convert
+    Return:
+        String containing the C version of this name
+    """
+    str = name.replace('@', '_at_')
+    str = str.replace('-', '_')
+    str = str.replace(',', '_')
+    str = str.replace('/', '__')
+    return str
+
+def TabTo(num_tabs, str):
+    if len(str) >= num_tabs * 8:
+        return str + ' '
+    return str + '\t' * (num_tabs - len(str) / 8)
+
+class DtbPlatdata:
+    """Provide a means to convert device tree binary data to platform data
+
+    The output of this process is C structures which can be used in space-
+    constrained encvironments where the ~3KB code overhead of device tree
+    code is not affordable.
+
+    Properties:
+        fdt: Fdt object, referencing the device tree
+        _dtb_fname: Filename of the input device tree binary file
+        _valid_nodes: A list of Node object with compatible strings
+        _options: Command-line options
+        _phandle_node: A dict of nodes indexed by phandle number (1, 2...)
+        _outfile: The current output file (sys.stdout or a real file)
+        _lines: Stashed list of output lines for outputting in the future
+        _phandle_node: A dict of Nodes indexed by phandle (an integer)
+    """
+    def __init__(self, dtb_fname, options):
+        self._dtb_fname = dtb_fname
+        self._valid_nodes = None
+        self._options = options
+        self._phandle_node = {}
+        self._outfile = None
+        self._lines = []
+
+    def SetupOutput(self, fname):
+        """Set up the output destination
+
+        Once this is done, future calls to self.Out() will output to this
+        file.
+
+        Args:
+            fname: Filename to send output to, or '-' for stdout
+        """
+        if fname == '-':
+            self._outfile = sys.stdout
+        else:
+            self._outfile = open(fname, 'w')
+
+    def Out(self, str):
+        """Output a string to the output file
+
+        Args:
+            str: String to output
+        """
+        self._outfile.write(str)
+
+    def Buf(self, str):
+        """Buffer up a string to send later
+
+        Args:
+            str: String to add to our 'buffer' list
+        """
+        self._lines.append(str)
+
+    def GetBuf(self):
+        """Get the contents of the output buffer, and clear it
+
+        Returns:
+            The output buffer, which is then cleared for future use
+        """
+        lines = self._lines
+        self._lines = []
+        return lines
+
+    def GetValue(self, type, value):
+        """Get a value as a C expression
+
+        For integers this returns a byte-swapped (little-endian) hex string
+        For bytes this returns a hex string, e.g. 0x12
+        For strings this returns a literal string enclosed in quotes
+        For booleans this return 'true'
+
+        Args:
+            type: Data type (fdt_util)
+            value: Data value, as a string of bytes
+        """
+        if type == fdt_util.TYPE_INT:
+            return '%#x' % fdt_util.fdt32_to_cpu(value)
+        elif type == fdt_util.TYPE_BYTE:
+            return '%#x' % ord(value[0])
+        elif type == fdt_util.TYPE_STRING:
+            return '"%s"' % value
+        elif type == fdt_util.TYPE_BOOL:
+            return 'true'
+
+    def GetCompatName(self, node):
+        """Get a node's first compatible string as a C identifier
+
+        Args:
+            node: Node object to check
+        Return:
+            C identifier for the first compatible string
+        """
+        compat = node.props['compatible'].value
+        if type(compat) == list:
+            compat = compat[0]
+        return Conv_name_to_c(compat)
+
+    def ScanDtb(self):
+        """Scan the device tree to obtain a tree of notes and properties
+
+        Once this is done, self.fdt.GetRoot() can be called to obtain the
+        device tree root node, and progress from there.
+        """
+        self.fdt = Fdt(self._dtb_fname)
+        self.fdt.Scan()
+
+    def ScanTree(self):
+        """Scan the device tree for useful information
+
+        This fills in the following properties:
+            _phandle_node: A dict of Nodes indexed by phandle (an integer)
+            _valid_nodes: A list of nodes we wish to consider include in the
+                platform data
+        """
+        node_list = []
+        self._phandle_node = {}
+        for node in self.fdt.GetRoot().subnodes:
+            if 'compatible' in node.props:
+                status = node.props.get('status')
+                if (not options.include_disabled and not status or
+                    status.value != 'disabled'):
+                    node_list.append(node)
+                    phandle_prop = node.props.get('phandle')
+                    if phandle_prop:
+                        phandle = phandle_prop.GetPhandle()
+                        self._phandle_node[phandle] = node
+
+        self._valid_nodes = node_list
+
+    def IsPhandle(self, prop):
+        """Check if a node contains phandles
+
+        We have no reliable way of detecting whether a node uses a phandle
+        or not. As an interim measure, use a list of known property names.
+
+        Args:
+            prop: Prop object to check
+        Return:
+            True if the object value contains phandles, else False
+        """
+        if prop.name in ['clocks']:
+            return True
+        return False
+
+    def ScanStructs(self):
+        """Scan the device tree building up the C structures we will use.
+
+        Build a dict keyed by C struct name containing a dict of Prop
+        object for each struct field (keyed by property name). Where the
+        same struct appears multiple times, try to use the 'widest'
+        property, i.e. the one with a type which can express all others.
+
+        Once the widest property is determined, all other properties are
+        updated to match that width.
+        """
+        structs = {}
+        for node in self._valid_nodes:
+            node_name = self.GetCompatName(node)
+            fields = {}
+
+            # Get a list of all the valid properties in this node.
+            for name, prop in node.props.iteritems():
+                if name not in PROP_IGNORE_LIST and name[0] != '#':
+                    fields[name] = copy.deepcopy(prop)
+
+            # If we've seen this node_name before, update the existing struct.
+            if node_name in structs:
+                struct = structs[node_name]
+                for name, prop in fields.iteritems():
+                    oldprop = struct.get(name)
+                    if oldprop:
+                        oldprop.Widen(prop)
+                    else:
+                        struct[name] = prop
+
+            # Otherwise store this as a new struct.
+            else:
+                structs[node_name] = fields
+
+        upto = 0
+        for node in self._valid_nodes:
+            node_name = self.GetCompatName(node)
+            struct = structs[node_name]
+            for name, prop in node.props.iteritems():
+                if name not in PROP_IGNORE_LIST and name[0] != '#':
+                    prop.Widen(struct[name])
+            upto += 1
+        return structs
+
+    def GenerateStructs(self, structs):
+        """Generate struct defintions for the platform data
+
+        This writes out the body of a header file consisting of structure
+        definitions for node in self._valid_nodes. See the documentation in
+        README.of-plat for more information.
+        """
+        self.Out('#include <stdbool.h>\n')
+        self.Out('#include <libfdt.h>\n')
+
+        # Output the struct definition
+        for name in sorted(structs):
+            self.Out('struct %s%s {\n' % (STRUCT_PREFIX, name));
+            for pname in sorted(structs[name]):
+                prop = structs[name][pname]
+                if self.IsPhandle(prop):
+                    # For phandles, include a reference to the target
+                    self.Out('\t%s%s[%d]' % (TabTo(2, 'struct phandle_2_cell'),
+                                             Conv_name_to_c(prop.name),
+                                             len(prop.value) / 2))
+                else:
+                    ptype = TYPE_NAMES[prop.type]
+                    self.Out('\t%s%s' % (TabTo(2, ptype),
+                                         Conv_name_to_c(prop.name)))
+                    if type(prop.value) == list:
+                        self.Out('[%d]' % len(prop.value))
+                self.Out(';\n')
+            self.Out('};\n')
+
+    def GenerateTables(self):
+        """Generate device defintions for the platform data
+
+        This writes out C platform data initialisation data and
+        U_BOOT_DEVICE() declarations for each valid node. See the
+        documentation in README.of-plat for more information.
+        """
+        self.Out('#include <common.h>\n')
+        self.Out('#include <dm.h>\n')
+        self.Out('#include <dt-structs.h>\n')
+        self.Out('\n')
+        node_txt_list = []
+        for node in self._valid_nodes:
+            struct_name = self.GetCompatName(node)
+            var_name = Conv_name_to_c(node.name)
+            self.Buf('static struct %s%s %s%s = {\n' %
+                (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
+            for pname, prop in node.props.iteritems():
+                if pname in PROP_IGNORE_LIST or pname[0] == '#':
+                    continue
+                ptype = TYPE_NAMES[prop.type]
+                member_name = Conv_name_to_c(prop.name)
+                self.Buf('\t%s= ' % TabTo(3, '.' + member_name))
+
+                # Special handling for lists
+                if type(prop.value) == list:
+                    self.Buf('{')
+                    vals = []
+                    # For phandles, output a reference to the platform data
+                    # of the target node.
+                    if self.IsPhandle(prop):
+                        # Process the list as pairs of (phandle, id)
+                        it = iter(prop.value)
+                        for phandle_cell, id_cell in zip(it, it):
+                            phandle = fdt_util.fdt32_to_cpu(phandle_cell)
+                            id = fdt_util.fdt32_to_cpu(id_cell)
+                            target_node = self._phandle_node[phandle]
+                            name = Conv_name_to_c(target_node.name)
+                            vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id))
+                    else:
+                        for val in prop.value:
+                            vals.append(self.GetValue(prop.type, val))
+                    self.Buf(', '.join(vals))
+                    self.Buf('}')
+                else:
+                    self.Buf(self.GetValue(prop.type, prop.value))
+                self.Buf(',\n')
+            self.Buf('};\n')
+
+            # Add a device declaration
+            self.Buf('U_BOOT_DEVICE(%s) = {\n' % var_name)
+            self.Buf('\t.name\t\t= "%s",\n' % struct_name)
+            self.Buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name))
+            self.Buf('\t.platdata_size\t= sizeof(%s%s),\n' %
+                     (VAL_PREFIX, var_name))
+            self.Buf('};\n')
+            self.Buf('\n')
+
+            # Output phandle target nodes first, since they may be referenced
+            # by others
+            if 'phandle' in node.props:
+                self.Out(''.join(self.GetBuf()))
+            else:
+                node_txt_list.append(self.GetBuf())
+
+        # Output all the nodes which are not phandle targets themselves, but
+        # may reference them. This avoids the need for forward declarations.
+        for node_txt in node_txt_list:
+            self.Out(''.join(node_txt))
+
+
+if __name__ != "__main__":
+    pass
+
+parser = OptionParser()
+parser.add_option('-d', '--dtb-file', action='store',
+                  help='Specify the .dtb input file')
+parser.add_option('--include-disabled', action='store_true',
+                  help='Include disabled nodes')
+parser.add_option('-o', '--output', action='store', default='-',
+                  help='Select output filename')
+(options, args) = parser.parse_args()
+
+if not args:
+    raise ValueError('Please specify a command: struct, platdata')
+
+plat = DtbPlatdata(options.dtb_file, options)
+plat.ScanDtb()
+plat.ScanTree()
+plat.SetupOutput(options.output)
+structs = plat.ScanStructs()
+
+for cmd in args[0].split(','):
+    if cmd == 'struct':
+        plat.GenerateStructs(structs)
+    elif cmd == 'platdata':
+        plat.GenerateTables()
+    else:
+        raise ValueError("Unknown command '%s': (use: struct, platdata)" % cmd)
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
new file mode 100644
index 0000000..1d913a9
--- /dev/null
+++ b/tools/dtoc/fdt.py
@@ -0,0 +1,180 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+import fdt_util
+import libfdt
+import sys
+
+# This deals with a device tree, presenting it as a list of Node and Prop
+# objects, representing nodes and properties, respectively.
+#
+# This implementation uses a libfdt Python library to access the device tree,
+# so it is fairly efficient.
+
+class Prop:
+    """A device tree property
+
+    Properties:
+        name: Property name (as per the device tree)
+        value: Property value as a string of bytes, or a list of strings of
+            bytes
+        type: Value type
+    """
+    def __init__(self, name, bytes):
+        self.name = name
+        self.value = None
+        if not bytes:
+            self.type = fdt_util.TYPE_BOOL
+            self.value = True
+            return
+        self.type, self.value = fdt_util.BytesToValue(bytes)
+
+    def GetPhandle(self):
+        """Get a (single) phandle value from a property
+
+        Gets the phandle valuie from a property and returns it as an integer
+        """
+        return fdt_util.fdt32_to_cpu(self.value[:4])
+
+    def Widen(self, newprop):
+        """Figure out which property type is more general
+
+        Given a current property and a new property, this function returns the
+        one that is less specific as to type. The less specific property will
+        be ble to represent the data in the more specific property. This is
+        used for things like:
+
+            node1 {
+                compatible = "fred";
+                value = <1>;
+            };
+            node1 {
+                compatible = "fred";
+                value = <1 2>;
+            };
+
+        He we want to use an int array for 'value'. The first property
+        suggests that a single int is enough, but the second one shows that
+        it is not. Calling this function with these two propertes would
+        update the current property to be like the second, since it is less
+        specific.
+        """
+        if newprop.type < self.type:
+            self.type = newprop.type
+
+        if type(newprop.value) == list and type(self.value) != list:
+            self.value = [self.value]
+
+        if type(self.value) == list and len(newprop.value) > len(self.value):
+            val = fdt_util.GetEmpty(self.type)
+            while len(self.value) < len(newprop.value):
+                self.value.append(val)
+
+
+class Node:
+    """A device tree node
+
+    Properties:
+        offset: Integer offset in the device tree
+        name: Device tree node tname
+        path: Full path to node, along with the node name itself
+        _fdt: Device tree object
+        subnodes: A list of subnodes for this node, each a Node object
+        props: A dict of properties for this node, each a Prop object.
+            Keyed by property name
+    """
+    def __init__(self, fdt, offset, name, path):
+        self.offset = offset
+        self.name = name
+        self.path = path
+        self._fdt = fdt
+        self.subnodes = []
+        self.props = {}
+
+    def Scan(self):
+        """Scan a node's properties and subnodes
+
+        This fills in the props and subnodes properties, recursively
+        searching into subnodes so that the entire tree is built.
+        """
+        self.props = self._fdt.GetProps(self.path)
+
+        offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self.offset)
+        while offset >= 0:
+            sep = '' if self.path[-1] == '/' else '/'
+            name = libfdt.Name(self._fdt.GetFdt(), offset)
+            path = self.path + sep + name
+            node = Node(self._fdt, offset, name, path)
+            self.subnodes.append(node)
+
+            node.Scan()
+            offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset)
+
+
+class Fdt:
+    """Provides simple access to a flat device tree blob.
+
+    Properties:
+      fname: Filename of fdt
+      _root: Root of device tree (a Node object)
+    """
+
+    def __init__(self, fname):
+        self.fname = fname
+        with open(fname) as fd:
+            self._fdt = fd.read()
+
+    def GetFdt(self):
+        """Get the contents of the FDT
+
+        Returns:
+            The FDT contents as a string of bytes
+        """
+        return self._fdt
+
+    def Scan(self):
+        """Scan a device tree, building up a tree of Node objects
+
+        This fills in the self._root property
+        """
+        self._root = Node(self, 0, '/', '/')
+        self._root.Scan()
+
+    def GetRoot(self):
+        """Get the root Node of the device tree
+
+        Returns:
+            The root Node object
+        """
+        return self._root
+
+    def GetProps(self, node):
+        """Get all properties from a node.
+
+        Args:
+            node: Full path to node name to look in.
+
+        Returns:
+            A dictionary containing all the properties, indexed by node name.
+            The entries are Prop objects.
+
+        Raises:
+            ValueError: if the node does not exist.
+        """
+        offset = libfdt.fdt_path_offset(self._fdt, node)
+        if offset < 0:
+            libfdt.Raise(offset)
+        props_dict = {}
+        poffset = libfdt.fdt_first_property_offset(self._fdt, offset)
+        while poffset >= 0:
+            dprop, plen = libfdt.fdt_get_property_by_offset(self._fdt, poffset)
+            prop = Prop(libfdt.String(self._fdt, dprop.nameoff), libfdt.Data(dprop))
+            props_dict[prop.name] = prop
+
+            poffset = libfdt.fdt_next_property_offset(self._fdt, poffset)
+        return props_dict
diff --git a/tools/dtoc/fdt_fallback.py b/tools/dtoc/fdt_fallback.py
new file mode 100644
index 0000000..9ed11e4
--- /dev/null
+++ b/tools/dtoc/fdt_fallback.py
@@ -0,0 +1,213 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+import command
+import fdt_util
+import sys
+
+# This deals with a device tree, presenting it as a list of Node and Prop
+# objects, representing nodes and properties, respectively.
+#
+# This implementation uses the fdtget tool to access the device tree, so it
+# is not very efficient for larger trees. The tool is called once for each
+# node and property in the tree.
+
+class Prop:
+    """A device tree property
+
+    Properties:
+        name: Property name (as per the device tree)
+        value: Property value as a string of bytes, or a list of strings of
+            bytes
+        type: Value type
+    """
+    def __init__(self, name, byte_list_str):
+        self.name = name
+        self.value = None
+        if not byte_list_str.strip():
+            self.type = fdt_util.TYPE_BOOL
+            return
+        bytes = [chr(int(byte, 16)) for byte in byte_list_str.strip().split(' ')]
+        self.type, self.value = fdt_util.BytesToValue(''.join(bytes))
+
+    def GetPhandle(self):
+        """Get a (single) phandle value from a property
+
+        Gets the phandle valuie from a property and returns it as an integer
+        """
+        return fdt_util.fdt32_to_cpu(self.value[:4])
+
+    def Widen(self, newprop):
+        """Figure out which property type is more general
+
+        Given a current property and a new property, this function returns the
+        one that is less specific as to type. The less specific property will
+        be ble to represent the data in the more specific property. This is
+        used for things like:
+
+            node1 {
+                compatible = "fred";
+                value = <1>;
+            };
+            node1 {
+                compatible = "fred";
+                value = <1 2>;
+            };
+
+        He we want to use an int array for 'value'. The first property
+        suggests that a single int is enough, but the second one shows that
+        it is not. Calling this function with these two propertes would
+        update the current property to be like the second, since it is less
+        specific.
+        """
+        if newprop.type < self.type:
+            self.type = newprop.type
+
+        if type(newprop.value) == list and type(self.value) != list:
+            self.value = newprop.value
+
+        if type(self.value) == list and len(newprop.value) > len(self.value):
+            val = fdt_util.GetEmpty(self.type)
+            while len(self.value) < len(newprop.value):
+                self.value.append(val)
+
+
+class Node:
+    """A device tree node
+
+    Properties:
+        name: Device tree node tname
+        path: Full path to node, along with the node name itself
+        _fdt: Device tree object
+        subnodes: A list of subnodes for this node, each a Node object
+        props: A dict of properties for this node, each a Prop object.
+            Keyed by property name
+    """
+    def __init__(self, fdt, name, path):
+        self.name = name
+        self.path = path
+        self._fdt = fdt
+        self.subnodes = []
+        self.props = {}
+
+    def Scan(self):
+        """Scan a node's properties and subnodes
+
+        This fills in the props and subnodes properties, recursively
+        searching into subnodes so that the entire tree is built.
+        """
+        for name, byte_list_str in self._fdt.GetProps(self.path).iteritems():
+            prop = Prop(name, byte_list_str)
+            self.props[name] = prop
+
+        for name in self._fdt.GetSubNodes(self.path):
+            sep = '' if self.path[-1] == '/' else '/'
+            path = self.path + sep + name
+            node = Node(self._fdt, name, path)
+            self.subnodes.append(node)
+
+            node.Scan()
+
+
+class Fdt:
+    """Provides simple access to a flat device tree blob.
+
+    Properties:
+      fname: Filename of fdt
+      _root: Root of device tree (a Node object)
+    """
+
+    def __init__(self, fname):
+        self.fname = fname
+
+    def Scan(self):
+        """Scan a device tree, building up a tree of Node objects
+
+        This fills in the self._root property
+        """
+        self._root = Node(self, '/', '/')
+        self._root.Scan()
+
+    def GetRoot(self):
+        """Get the root Node of the device tree
+
+        Returns:
+            The root Node object
+        """
+        return self._root
+
+    def GetSubNodes(self, node):
+        """Returns a list of sub-nodes of a given node
+
+        Args:
+            node: Node name to return children from
+
+        Returns:
+            List of children in the node (each a string node name)
+
+        Raises:
+            CmdError: if the node does not exist.
+        """
+        out = command.Output('fdtget', self.fname, '-l', node)
+        return out.strip().splitlines()
+
+    def GetProps(self, node, convert_dashes=False):
+        """Get all properties from a node
+
+        Args:
+            node: full path to node name to look in
+            convert_dashes: True to convert - to _ in node names
+
+        Returns:
+            A dictionary containing all the properties, indexed by node name.
+            The entries are simply strings - no decoding of lists or numbers
+            is done.
+
+        Raises:
+            CmdError: if the node does not exist.
+        """
+        out = command.Output('fdtget', self.fname, node, '-p')
+        props = out.strip().splitlines()
+        props_dict = {}
+        for prop in props:
+            name = prop
+            if convert_dashes:
+                prop = re.sub('-', '_', prop)
+            props_dict[prop] = self.GetProp(node, name)
+        return props_dict
+
+    def GetProp(self, node, prop, default=None, typespec=None):
+        """Get a property from a device tree.
+
+        This looks up the given node and property, and returns the value as a
+        string,
+
+        If the node or property does not exist, this will return the default
+        value.
+
+        Args:
+            node: Full path to node to look up.
+            prop: Property name to look up.
+            default: Default value to return if nothing is present in the fdt,
+                or None to raise in this case. This will be converted to a
+                string.
+            typespec: Type character to use (None for default, 's' for string)
+
+        Returns:
+            string containing the property value.
+
+        Raises:
+            CmdError: if the property does not exist and no default is provided.
+        """
+        args = [self.fname, node, prop, '-t', 'bx']
+        if default is not None:
+          args += ['-d', str(default)]
+        if typespec is not None:
+          args += ['-t%s' % typespec]
+        out = command.Output('fdtget', *args)
+        return out.strip()
diff --git a/tools/dtoc/fdt_util.py b/tools/dtoc/fdt_util.py
new file mode 100644
index 0000000..929b524
--- /dev/null
+++ b/tools/dtoc/fdt_util.py
@@ -0,0 +1,86 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+import struct
+
+# A list of types we support
+(TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL) = range(4)
+
+def BytesToValue(bytes):
+    """Converts a string of bytes into a type and value
+
+    Args:
+        A string containing bytes
+
+    Return:
+        A tuple:
+            Type of data
+            Data, either a single element or a list of elements. Each element
+            is one of:
+                TYPE_STRING: string value from the property
+                TYPE_INT: a byte-swapped integer stored as a 4-byte string
+                TYPE_BYTE: a byte stored as a single-byte string
+    """
+    size = len(bytes)
+    strings = bytes.split('\0')
+    is_string = True
+    count = len(strings) - 1
+    if count > 0 and not strings[-1]:
+        for string in strings[:-1]:
+            if not string:
+                is_string = False
+                break
+            for ch in string:
+                if ch < ' ' or ch > '~':
+                    is_string = False
+                    break
+    else:
+        is_string = False
+    if is_string:
+        if count == 1:
+            return TYPE_STRING, strings[0]
+        else:
+            return TYPE_STRING, strings[:-1]
+    if size % 4:
+        if size == 1:
+            return TYPE_BYTE, bytes[0]
+        else:
+            return TYPE_BYTE, list(bytes)
+    val = []
+    for i in range(0, size, 4):
+        val.append(bytes[i:i + 4])
+    if size == 4:
+        return TYPE_INT, val[0]
+    else:
+        return TYPE_INT, val
+
+def GetEmpty(type):
+    """Get an empty / zero value of the given type
+
+    Returns:
+        A single value of the given type
+    """
+    if type == TYPE_BYTE:
+        return chr(0)
+    elif type == TYPE_INT:
+        return struct.pack('<I', 0);
+    elif type == TYPE_STRING:
+        return ''
+    else:
+        return True
+
+def fdt32_to_cpu(val):
+    """Convert a device tree cell to an integer
+
+    Args:
+        Value to convert (4-character string representing the cell value)
+
+    Return:
+        A native-endian integer value
+    """
+    return struct.unpack(">I", val)[0]
diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c
index 692abda..d27f57e 100644
--- a/tools/env/fw_env.c
+++ b/tools/env/fw_env.c
@@ -14,6 +14,7 @@
 #include <errno.h>
 #include <env_flags.h>
 #include <fcntl.h>
+#include <linux/fs.h>
 #include <linux/stringify.h>
 #include <ctype.h>
 #include <stdio.h>
@@ -51,7 +52,7 @@
 
 struct envdev_s {
 	const char *devname;		/* Device name */
-	ulong devoff;			/* Device offset */
+	long long devoff;		/* Device offset */
 	ulong env_size;			/* environment size */
 	ulong erase_size;		/* device erase size */
 	ulong env_sectors;		/* number of environment sectors */
@@ -121,7 +122,6 @@
 #include <env_default.h>
 
 static int flash_io (int mode);
-static char *envmatch (char * s1, char * s2);
 static int parse_config(struct env_opts *opts);
 
 #if defined(CONFIG_FILE)
@@ -147,6 +147,24 @@
 }
 
 /*
+ * s1 is either a simple 'name', or a 'name=value' pair.
+ * s2 is a 'name=value' pair.
+ * If the names match, return the value of s2, else NULL.
+ */
+static char *envmatch(char *s1, char *s2)
+{
+	if (s1 == NULL || s2 == NULL)
+		return NULL;
+
+	while (*s1 == *s2++)
+		if (*s1++ == '=')
+			return s2;
+	if (*s1 == '\0' && *(s2 - 1) == '=')
+		return s2;
+	return NULL;
+}
+
+/**
  * Search the environment for a variable.
  * Return the value, if found, or NULL, if not found.
  */
@@ -232,9 +250,14 @@
  */
 int fw_printenv(int argc, char *argv[], int value_only, struct env_opts *opts)
 {
-	char *env, *nxt;
 	int i, rc = 0;
 
+	if (value_only && argc != 1) {
+		fprintf(stderr,
+			"## Error: `-n' option requires exactly one argument\n");
+		return -1;
+	}
+
 	if (!opts)
 		opts = &default_opts;
 
@@ -242,6 +265,7 @@
 		return -1;
 
 	if (argc == 0) {		/* Print all env variables  */
+		char *env, *nxt;
 		for (env = environment.data; *env; env = nxt + 1) {
 			for (nxt = env; *nxt; ++nxt) {
 				if (nxt >= &environment.data[ENV_SIZE]) {
@@ -256,39 +280,23 @@
 		return 0;
 	}
 
-	if (value_only && argc != 1) {
-		fprintf(stderr,
-			"## Error: `-n' option requires exactly one argument\n");
-		return -1;
-	}
-
-	for (i = 0; i < argc; ++i) {	/* print single env variables   */
+	for (i = 0; i < argc; ++i) {	/* print a subset of env variables */
 		char *name = argv[i];
 		char *val = NULL;
 
-		for (env = environment.data; *env; env = nxt + 1) {
-
-			for (nxt = env; *nxt; ++nxt) {
-				if (nxt >= &environment.data[ENV_SIZE]) {
-					fprintf (stderr, "## Error: "
-						"environment not terminated\n");
-					return -1;
-				}
-			}
-			val = envmatch (name, env);
-			if (val) {
-				if (!value_only) {
-					fputs (name, stdout);
-					putc ('=', stdout);
-				}
-				puts (val);
-				break;
-			}
-		}
+		val = fw_getenv(name);
 		if (!val) {
 			fprintf (stderr, "## Error: \"%s\" not defined\n", name);
 			rc = -1;
+			continue;
 		}
+
+		if (value_only) {
+			puts(val);
+			break;
+		}
+
+		printf("%s=%s\n", name, val);
 	}
 
 	return rc;
@@ -483,7 +491,7 @@
 	valc = argc - 1;
 
 	if (env_flags_validate_env_set_params(name, valv, valc) < 0)
-		return 1;
+		return -1;
 
 	len = 0;
 	for (i = 0; i < valc; ++i) {
@@ -653,8 +661,8 @@
 
 		if (badblock) {
 #ifdef DEBUG
-			fprintf (stderr, "Bad block at 0x%llx, "
-				 "skipping\n", *blockstart);
+			fprintf (stderr, "Bad block at 0x%llx, skipping\n",
+				(unsigned long long) *blockstart);
 #endif
 			return badblock;
 		}
@@ -741,7 +749,8 @@
 		}
 #ifdef DEBUG
 		fprintf(stderr, "Read 0x%x bytes at 0x%llx on %s\n",
-			 rc, blockstart + block_seek, DEVNAME(dev));
+			rc, (unsigned long long) blockstart + block_seek,
+			DEVNAME(dev));
 #endif
 		processed += readlen;
 		readlen = min (blocklen, count - processed);
@@ -839,8 +848,9 @@
 		if (block_seek + count != write_total) {
 			if (block_seek != 0)
 				fprintf(stderr, " and ");
-			fprintf(stderr, "0x%lx - 0x%x",
-				block_seek + count, write_total - 1);
+			fprintf(stderr, "0x%lx - 0x%lx",
+				(unsigned long) block_seek + count,
+				(unsigned long) write_total - 1);
 		}
 		fprintf(stderr, "\n");
 #endif
@@ -903,8 +913,9 @@
 		}
 
 #ifdef DEBUG
-		fprintf(stderr, "Write 0x%x bytes at 0x%llx\n", erasesize,
-			blockstart);
+		fprintf(stderr, "Write 0x%llx bytes at 0x%llx\n",
+			(unsigned long long) erasesize,
+			(unsigned long long) blockstart);
 #endif
 		if (write (fd, data + processed, erasesize) != erasesize) {
 			fprintf (stderr, "Write error on %s: %s\n",
@@ -994,7 +1005,7 @@
 	}
 
 #ifdef DEBUG
-	fprintf(stderr, "Writing new environment at 0x%lx on %s\n",
+	fprintf(stderr, "Writing new environment at 0x%llx on %s\n",
 		DEVOFFSET (dev_target), DEVNAME (dev_target));
 #endif
 
@@ -1010,7 +1021,7 @@
 			offsetof (struct env_image_redundant, flags);
 #ifdef DEBUG
 		fprintf(stderr,
-			"Setting obsolete flag in environment at 0x%lx on %s\n",
+			"Setting obsolete flag in environment at 0x%llx on %s\n",
 			DEVOFFSET (dev_current), DEVNAME (dev_current));
 #endif
 		flash_flag_obsolete (dev_current, fd_current, offset);
@@ -1021,41 +1032,10 @@
 
 static int flash_read (int fd)
 {
-	struct mtd_info_user mtdinfo;
-	struct stat st;
 	int rc;
 
-	rc = fstat(fd, &st);
-	if (rc < 0) {
-		fprintf(stderr, "Cannot stat the file %s\n",
-			DEVNAME(dev_current));
-		return -1;
-	}
-
-	if (S_ISCHR(st.st_mode)) {
-		rc = ioctl(fd, MEMGETINFO, &mtdinfo);
-		if (rc < 0) {
-			fprintf(stderr, "Cannot get MTD information for %s\n",
-				DEVNAME(dev_current));
-			return -1;
-		}
-		if (mtdinfo.type != MTD_NORFLASH &&
-		    mtdinfo.type != MTD_NANDFLASH &&
-		    mtdinfo.type != MTD_DATAFLASH &&
-		    mtdinfo.type != MTD_UBIVOLUME) {
-			fprintf (stderr, "Unsupported flash type %u on %s\n",
-				 mtdinfo.type, DEVNAME(dev_current));
-			return -1;
-		}
-	} else {
-		memset(&mtdinfo, 0, sizeof(mtdinfo));
-		mtdinfo.type = MTD_ABSENT;
-	}
-
-	DEVTYPE(dev_current) = mtdinfo.type;
-
 	rc = flash_read_buf(dev_current, fd, environment.image, CUR_ENVSIZE,
-			     DEVOFFSET (dev_current), mtdinfo.type);
+			    DEVOFFSET(dev_current), DEVTYPE(dev_current));
 	if (rc != CUR_ENVSIZE)
 		return -1;
 
@@ -1121,25 +1101,6 @@
 }
 
 /*
- * s1 is either a simple 'name', or a 'name=value' pair.
- * s2 is a 'name=value' pair.
- * If the names match, return the value of s2, else NULL.
- */
-
-static char *envmatch (char * s1, char * s2)
-{
-	if (s1 == NULL || s2 == NULL)
-		return NULL;
-
-	while (*s1 == *s2++)
-		if (*s1++ == '=')
-			return s2;
-	if (*s1 == '\0' && *(s2 - 1) == '=')
-		return s2;
-	return NULL;
-}
-
-/*
  * Prevent confusion if running from erased flash memory
  */
 int fw_env_open(struct env_opts *opts)
@@ -1328,10 +1289,87 @@
 	return 0;
 }
 
+static int check_device_config(int dev)
+{
+	struct stat st;
+	int fd, rc = 0;
+
+	if (DEVOFFSET(dev) % DEVESIZE(dev) != 0) {
+		fprintf(stderr, "Environment does not start on (erase) block boundary\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (ENVSIZE(dev) > ENVSECTORS(dev) * DEVESIZE(dev)) {
+		fprintf(stderr, "Environment does not fit into available sectors\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	fd = open(DEVNAME(dev), O_RDONLY);
+	if (fd < 0) {
+		fprintf(stderr,
+			"Cannot open %s: %s\n",
+			DEVNAME(dev), strerror(errno));
+		return -1;
+	}
+
+	rc = fstat(fd, &st);
+	if (rc < 0) {
+		fprintf(stderr, "Cannot stat the file %s\n",
+			DEVNAME(dev));
+		goto err;
+	}
+
+	if (S_ISCHR(st.st_mode)) {
+		struct mtd_info_user mtdinfo;
+		rc = ioctl(fd, MEMGETINFO, &mtdinfo);
+		if (rc < 0) {
+			fprintf(stderr, "Cannot get MTD information for %s\n",
+				DEVNAME(dev));
+			goto err;
+		}
+		if (mtdinfo.type != MTD_NORFLASH &&
+		    mtdinfo.type != MTD_NANDFLASH &&
+		    mtdinfo.type != MTD_DATAFLASH &&
+		    mtdinfo.type != MTD_UBIVOLUME) {
+			fprintf(stderr, "Unsupported flash type %u on %s\n",
+				mtdinfo.type, DEVNAME(dev));
+			goto err;
+		}
+		DEVTYPE(dev) = mtdinfo.type;
+	} else {
+		uint64_t size;
+		DEVTYPE(dev) = MTD_ABSENT;
+
+		/*
+		 * Check for negative offsets, treat it as backwards offset
+		 * from the end of the block device
+		 */
+		if (DEVOFFSET(dev) < 0) {
+			rc = ioctl(fd, BLKGETSIZE64, &size);
+			if (rc < 0) {
+				fprintf(stderr, "Could not get block device size on %s\n",
+					DEVNAME(dev));
+				goto err;
+			}
+
+			DEVOFFSET(dev) = DEVOFFSET(dev) + size;
+#ifdef DEBUG
+			fprintf(stderr, "Calculated device offset 0x%llx on %s\n",
+				DEVOFFSET(dev), DEVNAME(dev));
+#endif
+		}
+	}
+
+err:
+	close(fd);
+	return rc;
+}
 
 static int parse_config(struct env_opts *opts)
 {
-	struct stat st;
+	int rc;
 
 	if (!opts)
 		opts = &default_opts;
@@ -1375,25 +1413,20 @@
 	HaveRedundEnv = 1;
 #endif
 #endif
-	if (stat (DEVNAME (0), &st)) {
-		fprintf (stderr,
-			"Cannot access MTD device %s: %s\n",
-			DEVNAME (0), strerror (errno));
-		return -1;
-	}
+	rc = check_device_config(0);
+	if (rc < 0)
+		return rc;
 
-	if (HaveRedundEnv && stat (DEVNAME (1), &st)) {
-		fprintf (stderr,
-			"Cannot access MTD device %s: %s\n",
-			DEVNAME (1), strerror (errno));
-		return -1;
-	}
+	if (HaveRedundEnv) {
+		rc = check_device_config(1);
+		if (rc < 0)
+			return rc;
 
-	if (HaveRedundEnv && ENVSIZE(0) != ENVSIZE(1)) {
-		ENVSIZE(0) = ENVSIZE(1) = min(ENVSIZE(0), ENVSIZE(1));
-		fprintf(stderr,
-			"Redundant environments have inequal size, set to 0x%08lx\n",
-			ENVSIZE(1));
+		if (ENVSIZE(0) != ENVSIZE(1)) {
+			fprintf(stderr,
+				"Redundant environments have unequal size");
+			return -1;
+		}
 	}
 
 	usable_envsize = CUR_ENVSIZE - sizeof(uint32_t);
@@ -1424,12 +1457,12 @@
 		if (dump[0] == '#')
 			continue;
 
-		rc = sscanf (dump, "%ms %lx %lx %lx %lx",
-			     &devname,
-			     &DEVOFFSET (i),
-			     &ENVSIZE (i),
-			     &DEVESIZE (i),
-			     &ENVSECTORS (i));
+		rc = sscanf(dump, "%ms %lli %lx %lx %lx",
+			    &devname,
+			    &DEVOFFSET(i),
+			    &ENVSIZE(i),
+			    &DEVESIZE(i),
+			    &ENVSECTORS(i));
 
 		if (rc < 3)
 			continue;
diff --git a/tools/env/fw_env.config b/tools/env/fw_env.config
index 6f216f9..7916ebd 100644
--- a/tools/env/fw_env.config
+++ b/tools/env/fw_env.config
@@ -2,8 +2,9 @@
 # Up to two entries are valid, in this case the redundant
 # environment sector is assumed present.
 # Notice, that the "Number of sectors" is not required on NOR and SPI-dataflash.
-# Futhermore, if the Flash sector size is ommitted, this value is assumed to
+# Futhermore, if the Flash sector size is omitted, this value is assumed to
 # be the same as the Environment size, which is valid for NOR and SPI-dataflash
+# Device offset must be prefixed with 0x to be parsed as a hexadecimal value.
 
 # NOR example
 # MTD device name	Device offset	Env. size	Flash sector size	Number of sectors
@@ -18,8 +19,12 @@
 # NAND example
 #/dev/mtd0		0x4000		0x4000		0x20000			2
 
+# On a block device a negative offset is treated as a backwards offset from the
+# end of the device/partition, rather than a forwards offset from the start.
+
 # Block device example
 #/dev/mmcblk0		0xc0000		0x20000
+#/dev/mmcblk0		-0x20000	0x20000
 
 # VFAT example
 #/boot/uboot.env	0x0000          0x4000
diff --git a/tools/env/fw_env.h b/tools/env/fw_env.h
index dac964d..436eca9 100644
--- a/tools/env/fw_env.h
+++ b/tools/env/fw_env.h
@@ -67,12 +67,125 @@
 
 int parse_aes_key(char *key, uint8_t *bin_key);
 
+/**
+ * fw_printenv() - print one or several environment variables
+ *
+ * @argc: number of variables names to be printed, prints all if 0
+ * @argv: array of variable names to be printed, if argc != 0
+ * @value_only: do not repeat the variable name, print the bare value,
+ *          only one variable allowed with this option, argc must be 1
+ * @opts: encryption key, configuration file, defaults are used if NULL
+ *
+ * Description:
+ *  Uses fw_env_open, fw_getenv
+ *
+ * Return:
+ *  0 on success, -1 on failure (modifies errno)
+ */
 int fw_printenv(int argc, char *argv[], int value_only, struct env_opts *opts);
-char *fw_getenv(char *name);
+
+/**
+ * fw_setenv() - adds or removes one variable to the environment
+ *
+ * @argc: number of strings in argv, argv[0] is variable name,
+ *          argc==1 means erase variable, argc > 1 means add a variable
+ * @argv: argv[0] is variable name, argv[1..argc-1] are concatenated separated
+ *           by single blank and set as the new value of the variable
+ * @opts: how to retrieve environment from flash, defaults are used if NULL
+ *
+ * Description:
+ *  Uses fw_env_open, fw_env_write, fw_env_close
+ *
+ * Return:
+ *  0 on success, -1 on failure (modifies errno)
+ *
+ * ERRORS:
+ *  EROFS - some variables ("ethaddr", "serial#") cannot be modified
+ */
 int fw_setenv(int argc, char *argv[], struct env_opts *opts);
+
+/**
+ * fw_parse_script() - adds or removes multiple variables with a batch script
+ *
+ * @fname: batch script file name
+ * @opts: encryption key, configuration file, defaults are used if NULL
+ *
+ * Description:
+ *  Uses fw_env_open, fw_env_write, fw_env_close
+ *
+ * Return:
+ *  0 success, -1 on failure (modifies errno)
+ *
+ * Script Syntax:
+ *
+ *  key [ [space]+ value]
+ *
+ *  lines starting with '#' treated as comment
+ *
+ *  A variable without value will be deleted. Any number of spaces are allowed
+ *  between key and value. The value starts with the first non-space character
+ *  and ends with newline. No comments allowed on these lines.  Spaces inside
+ *  the value are preserved verbatim.
+ *
+ * Script Example:
+ *
+ *  netdev         eth0
+ *
+ *  kernel_addr    400000
+ *
+ *  foo            spaces           are copied verbatim
+ *
+ *  # delete variable bar
+ *
+ *  bar
+ */
 int fw_parse_script(char *fname, struct env_opts *opts);
+
+
+/**
+ * fw_env_open() - read enviroment from flash into RAM cache
+ *
+ * @opts: encryption key, configuration file, defaults are used if NULL
+ *
+ * Return:
+ *  0 on success, -1 on failure (modifies errno)
+ */
 int fw_env_open(struct env_opts *opts);
+
+/**
+ * fw_getenv() - lookup variable in the RAM cache
+ *
+ * @name: variable to be searched
+ * Return:
+ *  pointer to start of value, NULL if not found
+ */
+char *fw_getenv(char *name);
+
+/**
+ * fw_env_write() - modify a variable held in the RAM cache
+ *
+ * @name: variable
+ * @value: delete variable if NULL, otherwise create or overwrite the variable
+ *
+ * This is called in sequence to update the environment in RAM without updating
+ * the copy in flash after each set
+ *
+ * Return:
+ *  0 on success, -1 on failure (modifies errno)
+ *
+ * ERRORS:
+ *  EROFS - some variables ("ethaddr", "serial#") cannot be modified
+ */
 int fw_env_write(char *name, char *value);
+
+/**
+ * fw_env_close - write the environment from RAM cache back to flash
+ *
+ * @opts: encryption key, configuration file, defaults are used if NULL
+ *
+ * Return:
+ *  0 on success, -1 on failure (modifies errno)
+ */
 int fw_env_close(struct env_opts *opts);
 
 unsigned long crc32(unsigned long, const unsigned char *, unsigned);
diff --git a/tools/fit_image.c b/tools/fit_image.c
index 58aa8e2..10fd6d4 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -195,7 +195,8 @@
 	fdt_begin_node(fdt, str);
 	fdt_property_string(fdt, "description", params->imagename);
 	fdt_property_string(fdt, "type", typename);
-	fdt_property_string(fdt, "arch", genimg_get_arch_name(params->arch));
+	fdt_property_string(fdt, "arch",
+			    genimg_get_arch_short_name(params->arch));
 	fdt_property_string(fdt, "os", genimg_get_os_short_name(params->os));
 	fdt_property_string(fdt, "compression",
 			    genimg_get_comp_short_name(params->comp));
@@ -650,8 +651,8 @@
 	}
 
 	if (ret) {
-		fprintf(stderr, "%s Can't add hashes to FIT blob\n",
-			params->cmdname);
+		fprintf(stderr, "%s Can't add hashes to FIT blob: %d\n",
+			params->cmdname, ret);
 		goto err_system;
 	}
 
diff --git a/tools/image-host.c b/tools/image-host.c
index 7effb6c..1104695 100644
--- a/tools/image-host.c
+++ b/tools/image-host.c
@@ -38,7 +38,7 @@
 		printf("Can't set hash '%s' property for '%s' node(%s)\n",
 		       FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL),
 		       fdt_strerror(ret));
-		return -1;
+		return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
 	}
 
 	return 0;
@@ -64,25 +64,27 @@
 	const char *node_name;
 	int value_len;
 	char *algo;
+	int ret;
 
 	node_name = fit_get_name(fit, noffset, NULL);
 
 	if (fit_image_hash_get_algo(fit, noffset, &algo)) {
 		printf("Can't get hash algo property for '%s' hash node in '%s' image node\n",
 		       node_name, image_name);
-		return -1;
+		return -ENOENT;
 	}
 
 	if (calculate_hash(data, size, algo, value, &value_len)) {
 		printf("Unsupported hash algorithm (%s) for '%s' hash node in '%s' image node\n",
 		       algo, node_name, image_name);
-		return -1;
+		return -EPROTONOSUPPORT;
 	}
 
-	if (fit_set_hash_value(fit, noffset, value, value_len)) {
+	ret = fit_set_hash_value(fit, noffset, value, value_len);
+	if (ret) {
 		printf("Can't set hash value for '%s' hash node in '%s' image node\n",
 		       node_name, image_name);
-		return -1;
+		return ret;
 	}
 
 	return 0;
@@ -236,12 +238,18 @@
 	/* Get keyname again, as FDT has changed and invalidated our pointer */
 	info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
 
-	/* Write the public key into the supplied FDT file */
-	if (keydest && info.algo->add_verify_data(&info, keydest)) {
-		printf("Failed to add verification data for '%s' signature node in '%s' image node\n",
-		       node_name, image_name);
+	if (keydest)
+		ret = info.algo->add_verify_data(&info, keydest);
+	else
 		return -1;
-	}
+
+	/*
+	 * Write the public key into the supplied FDT file; this might fail
+	 * several times, since we try signing with successively increasing
+	 * size values
+	 */
+	if (keydest && ret)
+		return ret;
 
 	return 0;
 }
@@ -322,7 +330,7 @@
 				comment, require_keys);
 		}
 		if (ret)
-			return -1;
+			return ret;
 	}
 
 	return 0;
diff --git a/tools/mkimage.c b/tools/mkimage.c
index ff3024a..3c594a0 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -25,45 +25,47 @@
 	.imagename2 = "",
 };
 
-static int h_compare_image_name(const void *vtype1, const void *vtype2)
+static enum ih_category cur_category;
+
+static int h_compare_category_name(const void *vtype1, const void *vtype2)
 {
 	const int *type1 = vtype1;
 	const int *type2 = vtype2;
-	const char *name1 = genimg_get_type_short_name(*type1);
-	const char *name2 = genimg_get_type_short_name(*type2);
+	const char *name1 = genimg_get_cat_short_name(cur_category, *type1);
+	const char *name2 = genimg_get_cat_short_name(cur_category, *type2);
 
 	return strcmp(name1, name2);
 }
 
-/* Show all image types supported by mkimage */
-static void show_image_types(void)
+static int show_valid_options(enum ih_category category)
 {
-	struct image_type_params *tparams;
-	int order[IH_TYPE_COUNT];
+	int *order;
 	int count;
-	int type;
+	int item;
 	int i;
 
+	count = genimg_get_cat_count(category);
+	order = calloc(count, sizeof(*order));
+	if (!order)
+		return -ENOMEM;
+
 	/* Sort the names in order of short name for easier reading */
-	memset(order, '\0', sizeof(order));
-	for (count = 0, type = 0; type < IH_TYPE_COUNT; type++) {
-		tparams = imagetool_get_type(type);
-		if (tparams)
-			order[count++] = type;
-	}
-	qsort(order, count, sizeof(int), h_compare_image_name);
+	for (item = 0; item < count; item++)
+		order[item] = item;
+	cur_category = category;
+	qsort(order, count, sizeof(int), h_compare_category_name);
 
-	fprintf(stderr, "\nInvalid image type. Supported image types:\n");
+	fprintf(stderr, "\nInvalid %s, supported are:\n",
+		genimg_get_cat_desc(category));
 	for (i = 0; i < count; i++) {
-		type = order[i];
-		tparams = imagetool_get_type(type);
-		if (tparams) {
-			fprintf(stderr, "\t%-15s  %s\n",
-				genimg_get_type_short_name(type),
-				genimg_get_type_name(type));
-		}
+		item = order[i];
+		fprintf(stderr, "\t%-15s  %s\n",
+			genimg_get_cat_short_name(category, item),
+			genimg_get_cat_name(category, item));
 	}
 	fprintf(stderr, "\n");
+
+	return 0;
 }
 
 static void usage(const char *msg)
@@ -138,7 +140,7 @@
 	int opt;
 
 	while ((opt = getopt(argc, argv,
-			     "a:A:b:cC:d:D:e:Ef:Fk:K:ln:p:O:rR:qsT:vVx")) != -1) {
+			     "a:A:b:c:C:d:D:e:Ef:Fk:K:ln:p:O:rR:qsT:vVx")) != -1) {
 		switch (opt) {
 		case 'a':
 			params.addr = strtoull(optarg, &ptr, 16);
@@ -150,8 +152,10 @@
 			break;
 		case 'A':
 			params.arch = genimg_get_arch_id(optarg);
-			if (params.arch < 0)
+			if (params.arch < 0) {
+				show_valid_options(IH_ARCH);
 				usage("Invalid architecture");
+			}
 			break;
 		case 'b':
 			if (add_content(IH_TYPE_FLATDT, optarg)) {
@@ -166,8 +170,10 @@
 			break;
 		case 'C':
 			params.comp = genimg_get_comp_id(optarg);
-			if (params.comp < 0)
+			if (params.comp < 0) {
+				show_valid_options(IH_COMP);
 				usage("Invalid compression type");
+			}
 			break;
 		case 'd':
 			params.datafile = optarg;
@@ -197,7 +203,6 @@
 			 * The flattened image tree (FIT) format
 			 * requires a flattened device tree image type
 			 */
-			params.fit_image_type = params.type;
 			params.type = IH_TYPE_FLATDT;
 			params.fflag = 1;
 			break;
@@ -215,8 +220,10 @@
 			break;
 		case 'O':
 			params.os = genimg_get_os_id(optarg);
-			if (params.os < 0)
+			if (params.os < 0) {
+				show_valid_options(IH_OS);
 				usage("Invalid operating system");
+			}
 			break;
 		case 'p':
 			params.external_offset = strtoull(optarg, &ptr, 16);
@@ -225,6 +232,7 @@
 					params.cmdname, optarg);
 				exit(EXIT_FAILURE);
 			}
+			break;
 		case 'q':
 			params.quiet = 1;
 			break;
@@ -244,7 +252,7 @@
 		case 'T':
 			type = genimg_get_type_id(optarg);
 			if (type < 0) {
-				show_image_types();
+				show_valid_options(IH_TYPE);
 				usage("Invalid image type");
 			}
 			break;
@@ -272,9 +280,12 @@
 	 * will always be IH_TYPE_FLATDT in this case).
 	 */
 	if (params.type == IH_TYPE_FLATDT) {
-		params.fit_image_type = type;
+		params.fit_image_type = type ? type : IH_TYPE_KERNEL;
+		/* For auto_its, datafile is always 'auto' */
 		if (!params.auto_its)
 			params.datafile = datafile;
+		else if (!params.datafile)
+			usage("Missing data file for auto-FIT (use -d)");
 	} else if (type != IH_TYPE_INVALID) {
 		params.type = type;
 	}
@@ -283,7 +294,6 @@
 		usage("Missing output filename");
 }
 
-
 int main(int argc, char **argv)
 {
 	int ifd = -1;
diff --git a/tools/moveconfig.py b/tools/moveconfig.py
index d362923..aaa8e96 100755
--- a/tools/moveconfig.py
+++ b/tools/moveconfig.py
@@ -160,6 +160,8 @@
 
 """
 
+import copy
+import difflib
 import filecmp
 import fnmatch
 import multiprocessing
@@ -264,6 +266,16 @@
         sys.exit('GNU Make not found')
     return ret[0].rstrip()
 
+def get_all_defconfigs():
+    """Get all the defconfig files under the configs/ directory."""
+    defconfigs = []
+    for (dirpath, dirnames, filenames) in os.walk('configs'):
+        dirpath = dirpath[len('configs') + 1:]
+        for filename in fnmatch.filter(filenames, '*_defconfig'):
+            defconfigs.append(os.path.join(dirpath, filename))
+
+    return defconfigs
+
 def color_text(color_enabled, color, string):
     """Return colored string."""
     if color_enabled:
@@ -274,6 +286,28 @@
     else:
         return string
 
+def show_diff(a, b, file_path, color_enabled):
+    """Show unidified diff.
+
+    Arguments:
+      a: A list of lines (before)
+      b: A list of lines (after)
+      file_path: Path to the file
+      color_enabled: Display the diff in color
+    """
+
+    diff = difflib.unified_diff(a, b,
+                                fromfile=os.path.join('a', file_path),
+                                tofile=os.path.join('b', file_path))
+
+    for line in diff:
+        if line[0] == '-' and line[1] != '-':
+            print color_text(color_enabled, COLOR_RED, line),
+        elif line[0] == '+' and line[1] != '+':
+            print color_text(color_enabled, COLOR_GREEN, line),
+        else:
+            print line,
+
 def update_cross_compile(color_enabled):
     """Update per-arch CROSS_COMPILE via environment variables
 
@@ -319,41 +353,123 @@
 
         CROSS_COMPILE[arch] = cross_compile
 
+def extend_matched_lines(lines, matched, pre_patterns, post_patterns, extend_pre,
+                         extend_post):
+    """Extend matched lines if desired patterns are found before/after already
+    matched lines.
+
-def cleanup_one_header(header_path, patterns, dry_run):
+    Arguments:
+      lines: A list of lines handled.
+      matched: A list of line numbers that have been already matched.
+               (will be updated by this function)
+      pre_patterns: A list of regular expression that should be matched as
+                    preamble.
+      post_patterns: A list of regular expression that should be matched as
+                     postamble.
+      extend_pre: Add the line number of matched preamble to the matched list.
+      extend_post: Add the line number of matched postamble to the matched list.
+    """
+    extended_matched = []
+
+    j = matched[0]
+
+    for i in matched:
+        if i == 0 or i < j:
+            continue
+        j = i
+        while j in matched:
+            j += 1
+        if j >= len(lines):
+            break
+
+        for p in pre_patterns:
+            if p.search(lines[i - 1]):
+                break
+        else:
+            # not matched
+            continue
+
+        for p in post_patterns:
+            if p.search(lines[j]):
+                break
+        else:
+            # not matched
+            continue
+
+        if extend_pre:
+            extended_matched.append(i - 1)
+        if extend_post:
+            extended_matched.append(j)
+
+    matched += extended_matched
+    matched.sort()
+
+def cleanup_one_header(header_path, patterns, options):
     """Clean regex-matched lines away from a file.
 
     Arguments:
       header_path: path to the cleaned file.
       patterns: list of regex patterns.  Any lines matching to these
                 patterns are deleted.
-      dry_run: make no changes, but still display log.
+      options: option flags.
     """
     with open(header_path) as f:
         lines = f.readlines()
 
     matched = []
     for i, line in enumerate(lines):
+        if i - 1 in matched and lines[i - 1][-2:] == '\\\n':
+            matched.append(i)
+            continue
         for pattern in patterns:
-            m = pattern.search(line)
-            if m:
-                print '%s: %s: %s' % (header_path, i + 1, line),
+            if pattern.search(line):
                 matched.append(i)
                 break
 
-    if dry_run or not matched:
+    if not matched:
         return
 
+    # remove empty #ifdef ... #endif, successive blank lines
+    pattern_if = re.compile(r'#\s*if(def|ndef)?\W') #  #if, #ifdef, #ifndef
+    pattern_elif = re.compile(r'#\s*el(if|se)\W')   #  #elif, #else
+    pattern_endif = re.compile(r'#\s*endif\W')      #  #endif
+    pattern_blank = re.compile(r'^\s*$')            #  empty line
+
+    while True:
+        old_matched = copy.copy(matched)
+        extend_matched_lines(lines, matched, [pattern_if],
+                             [pattern_endif], True, True)
+        extend_matched_lines(lines, matched, [pattern_elif],
+                             [pattern_elif, pattern_endif], True, False)
+        extend_matched_lines(lines, matched, [pattern_if, pattern_elif],
+                             [pattern_blank], False, True)
+        extend_matched_lines(lines, matched, [pattern_blank],
+                             [pattern_elif, pattern_endif], True, False)
+        extend_matched_lines(lines, matched, [pattern_blank],
+                             [pattern_blank], True, False)
+        if matched == old_matched:
+            break
+
+    tolines = copy.copy(lines)
+
+    for i in reversed(matched):
+        tolines.pop(i)
+
+    show_diff(lines, tolines, header_path, options.color)
+
+    if options.dry_run:
+        return
+
     with open(header_path, 'w') as f:
-        for i, line in enumerate(lines):
-            if not i in matched:
-                f.write(line)
+        for line in tolines:
+            f.write(line)
 
-def cleanup_headers(configs, dry_run):
+def cleanup_headers(configs, options):
     """Delete config defines from board headers.
 
     Arguments:
       configs: A list of CONFIGs to remove.
-      dry_run: make no changes, but still display log.
+      options: option flags.
     """
     while True:
         choice = raw_input('Clean up headers? [y/n]: ').lower()
@@ -371,10 +487,85 @@
 
     for dir in 'include', 'arch', 'board':
         for (dirpath, dirnames, filenames) in os.walk(dir):
+            if dirpath == os.path.join('include', 'generated'):
+                continue
             for filename in filenames:
                 if not fnmatch.fnmatch(filename, '*~'):
                     cleanup_one_header(os.path.join(dirpath, filename),
-                                       patterns, dry_run)
+                                       patterns, options)
+
+def cleanup_one_extra_option(defconfig_path, configs, options):
+    """Delete config defines in CONFIG_SYS_EXTRA_OPTIONS in one defconfig file.
+
+    Arguments:
+      defconfig_path: path to the cleaned defconfig file.
+      configs: A list of CONFIGs to remove.
+      options: option flags.
+    """
+
+    start = 'CONFIG_SYS_EXTRA_OPTIONS="'
+    end = '"\n'
+
+    with open(defconfig_path) as f:
+        lines = f.readlines()
+
+    for i, line in enumerate(lines):
+        if line.startswith(start) and line.endswith(end):
+            break
+    else:
+        # CONFIG_SYS_EXTRA_OPTIONS was not found in this defconfig
+        return
+
+    old_tokens = line[len(start):-len(end)].split(',')
+    new_tokens = []
+
+    for token in old_tokens:
+        pos = token.find('=')
+        if not (token[:pos] if pos >= 0 else token) in configs:
+            new_tokens.append(token)
+
+    if new_tokens == old_tokens:
+        return
+
+    tolines = copy.copy(lines)
+
+    if new_tokens:
+        tolines[i] = start + ','.join(new_tokens) + end
+    else:
+        tolines.pop(i)
+
+    show_diff(lines, tolines, defconfig_path, options.color)
+
+    if options.dry_run:
+        return
+
+    with open(defconfig_path, 'w') as f:
+        for line in tolines:
+            f.write(line)
+
+def cleanup_extra_options(configs, options):
+    """Delete config defines in CONFIG_SYS_EXTRA_OPTIONS in defconfig files.
+
+    Arguments:
+      configs: A list of CONFIGs to remove.
+      options: option flags.
+    """
+    while True:
+        choice = raw_input('Clean up CONFIG_SYS_EXTRA_OPTIONS? [y/n]: ').lower()
+        print choice
+        if choice == 'y' or choice == 'n':
+            break
+
+    if choice == 'n':
+        return
+
+    configs = [ config[len('CONFIG_'):] for config in configs ]
+
+    defconfigs = get_all_defconfigs()
+
+    for defconfig in defconfigs:
+        cleanup_one_extra_option(os.path.join('configs', defconfig), configs,
+                                 options)
 
 ### classes ###
 class Progress:
@@ -971,12 +1162,7 @@
                 sys.exit('%s - defconfig does not exist. Stopping.' %
                          defconfigs[i])
     else:
-        # All the defconfig files to be processed
-        defconfigs = []
-        for (dirpath, dirnames, filenames) in os.walk('configs'):
-            dirpath = dirpath[len('configs') + 1:]
-            for filename in fnmatch.filter(filenames, '*_defconfig'):
-                defconfigs.append(os.path.join(dirpath, filename))
+        defconfigs = get_all_defconfigs()
 
     progress = Progress(len(defconfigs))
     slots = Slots(configs, options, progress, reference_src_dir)
@@ -1040,15 +1226,14 @@
 
     check_top_directory()
 
-    check_clean_directory()
-
-    update_cross_compile(options.color)
-
     if not options.cleanup_headers_only:
+        check_clean_directory()
+        update_cross_compile(options.color)
         move_config(configs, options)
 
     if configs:
-        cleanup_headers(configs, options.dry_run)
+        cleanup_headers(configs, options)
+        cleanup_extra_options(configs, options)
 
 if __name__ == '__main__':
     main()
diff --git a/tools/patman/patchstream.py b/tools/patman/patchstream.py
index 27d031e..69d5cfb 100644
--- a/tools/patman/patchstream.py
+++ b/tools/patman/patchstream.py
@@ -112,6 +112,14 @@
         if self.commit and self.is_log:
             self.series.AddCommit(self.commit)
             self.commit = None
+        # If 'END' is missing in a 'Cover-letter' section, and that section
+        # happens to show up at the very end of the commit message, this is
+        # the chance for us to fix it up.
+        if self.in_section == 'cover' and self.is_log:
+            self.series.cover = self.section
+            self.in_section = None
+            self.skip_blank = True
+            self.section = []
 
     def ProcessLine(self, line):
         """Process a single line of a patch file or commit log
@@ -150,6 +158,7 @@
         # Handle state transition and skipping blank lines
         series_tag_match = re_series_tag.match(line)
         commit_tag_match = re_commit_tag.match(line)
+        cover_match = re_cover.match(line)
         cover_cc_match = re_cover_cc.match(line)
         signoff_match = re_signoff.match(line)
         tag_match = None
@@ -168,6 +177,33 @@
         elif commit_match:
             self.state = STATE_MSG_HEADER
 
+        # If a tag is detected, or a new commit starts
+        if series_tag_match or commit_tag_match or \
+           cover_match or cover_cc_match or signoff_match or \
+           self.state == STATE_MSG_HEADER:
+            # but we are already in a section, this means 'END' is missing
+            # for that section, fix it up.
+            if self.in_section:
+                self.warn.append("Missing 'END' in section '%s'" % self.in_section)
+                if self.in_section == 'cover':
+                    self.series.cover = self.section
+                elif self.in_section == 'notes':
+                    if self.is_log:
+                        self.series.notes += self.section
+                elif self.in_section == 'commit-notes':
+                    if self.is_log:
+                        self.commit.notes += self.section
+                else:
+                    self.warn.append("Unknown section '%s'" % self.in_section)
+                self.in_section = None
+                self.skip_blank = True
+                self.section = []
+            # but we are already in a change list, that means a blank line
+            # is missing, fix it up.
+            if self.in_change:
+                self.warn.append("Missing 'blank line' in section 'Series-changes'")
+                self.in_change = 0
+
         # If we are in a section, keep collecting lines until we see END
         if self.in_section:
             if line == 'END':
@@ -203,7 +239,7 @@
             self.skip_blank = False
 
         # Detect the start of a cover letter section
-        elif re_cover.match(line):
+        elif cover_match:
             self.in_section = 'cover'
             self.skip_blank = False
 
diff --git a/tools/rkcommon.c b/tools/rkcommon.c
index 72621fd..0a072aa 100644
--- a/tools/rkcommon.c
+++ b/tools/rkcommon.c
@@ -56,6 +56,7 @@
 static struct spl_info spl_infos[] = {
 	{ "rk3036", "RK30", 0x1000 },
 	{ "rk3288", "RK32", 0x8000 },
+	{ "rk3399", "RK33", 0x20000 },
 };
 
 static unsigned char rc4_key[16] = {