Merge tag 'fsl-qoriq-for-v2019.04-rc1' of git://git.denx.de/u-boot-fsl-qoriq

Add TFA boot flow for more boards

Add TFA boot defconfig for ls1088a and ls2088a.
Add dts fixup for PCIe endpoint and root complex.
diff --git a/.travis.yml b/.travis.yml
index 321fd79..8dfe4cf 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -63,6 +63,7 @@
     - BUILD_DIR=build
     - HOSTCC="cc"
     - HOSTCXX="c++"
+    - QEMU_VERSION="v3.1.0"
 
 before_script:
   # install toolchains based on TOOLCHAIN} variable
@@ -97,7 +98,7 @@
        git clone git://git.qemu.org/qemu.git /tmp/qemu;
        pushd /tmp/qemu;
        git submodule update --init dtc &&
-       git checkout v3.0.0 &&
+       git checkout ${QEMU_VERSION} &&
        ./configure --prefix=/tmp/qemu-install --target-list=${QEMU_TARGET} &&
        make -j4 all install;
        popd;
@@ -109,16 +110,9 @@
  #
  # From buildman, exit code 129 means warnings only.  If we've been asked to
  # use clang only do one configuration.
- - if [[ "${TOOLCHAIN}" == "clang" ]]; then
+ - if [[ "${BUILDMAN}" != "" ]]; then
      ret=0;
-     make O=../.bm-work/${TEST_PY_BD} HOSTCC=clang-7 CC=clang-7 -j$(nproc)
-       KCFLAGS=-Werror sandbox_config all || ret=$?;
-     if [[ $ret -ne 0 ]]; then
-       exit $ret;
-     fi;
-   elif [[ "${BUILDMAN}" != "" ]]; then
-     ret=0;
-     tools/buildman/buildman -P -E ${BUILDMAN} || ret=$?;
+     tools/buildman/buildman -P -E ${BUILDMAN} ${OVERRIDE}|| ret=$?;
      if [[ $ret -ne 0 && $ret -ne 129 ]]; then
        tools/buildman/buildman -sdeP ${BUILDMAN};
        exit $ret;
@@ -164,7 +158,7 @@
     - name: "buildman arm11 arm7 arm920t arm946es"
       env:
         - BUILDMAN="arm11 arm7 arm920t arm946es"
-    - name: "buildman arm926ejs (non-freescale,siemens,atmel,kirkwood,spear)"
+    - name: "buildman arm926ejs (non-NXP,siemens,atmel,kirkwood,spear)"
       env:
         - JOB="arm926ejs"
           BUILDMAN="arm926ejs -x freescale,siemens,atmel,kirkwood,spear"
@@ -174,19 +168,25 @@
     - name: "buildman boundary engicam toradex"
       env:
         - BUILDMAN="boundary engicam toradex"
-    - name: "buildman Freescale ARM32"
+    - name: "buildman NXP ARM32"
       env:
         - BUILDMAN="freescale -x powerpc,m68k,aarch64"
-    - name: "buildman Freescale AArch64 LS10xx"
+    - name: "buildman NXP AArch64 LS101x"
+      env:
+        - BUILDMAN="freescale&aarch64&ls101"
+    - name: "buildman NXP AArch64 LS104x"
       env:
-        - BUILDMAN="freescale&aarch64&&ls1"
-    - name: "buildman Freescale AArch64 LS20xx"
+        - BUILDMAN="freescale&aarch64&ls104"
+    - name: "buildman NXP AArch64 LS108x"
       env:
-        - BUILDMAN="freescale&aarch64&&ls2"
-    - name: "buildman i.MX6 (non-Freescale)"
+        - BUILDMAN="freescale&aarch64&ls108"
+    - name: "buildman NXP AArch64 LS20xx"
+      env:
+        - BUILDMAN="freescale&aarch64&&ls20"
+    - name: "buildman i.MX6 (non-NXP)"
       env:
         - BUILDMAN="mx6 -x freescale,toradex,boundary,engicam"
-    - name: "buildman i.MX (non-Freescale,i.MX6,toradex)"
+    - name: "buildman i.MX (non-NXP,i.MX6,toradex)"
       env:
         - BUILDMAN="mx -x freescale,mx6,toradex"
     - name: "buildman k2"
@@ -351,7 +351,7 @@
       env:
         - TEST_PY_BD="sandbox"
           BUILDMAN="^sandbox$"
-          TOOLCHAIN="clang"
+          OVERRIDE="clang-7"
     - name: "test/py sandbox_spl"
       env:
         - TEST_PY_BD="sandbox_spl"
@@ -369,6 +369,7 @@
         - TEST_PY_BD="vexpress_ca15_tc2"
           TEST_PY_ID="--id qemu"
           QEMU_TARGET="arm-softmmu"
+          QEMU_VERSION="v3.0.0"
           BUILDMAN="^vexpress_ca15_tc2$"
     - name: "test/py vexpress_ca9x4"
       env:
diff --git a/Kconfig b/Kconfig
index aff7b2e..a078f7b 100644
--- a/Kconfig
+++ b/Kconfig
@@ -213,7 +213,7 @@
 	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.
+	  large physical address extension on 32bit SoCs.
 
 config BUILD_ROM
 	bool "Build U-Boot as BIOS replacement"
diff --git a/MAINTAINERS b/MAINTAINERS
index f86fdf9..399a839 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -176,6 +176,8 @@
 F:	drivers/spi/mtk_qspi.c
 F:	drivers/timer/mtk_timer.c
 F:	drivers/watchdog/mtk_wdt.c
+F:	drivers/net/mtk_eth.c
+F:	drivers/reset/reset-mediatek.c
 F:	tools/mtk_image.c
 F:	tools/mtk_image.h
 N:	mediatek
@@ -521,9 +523,14 @@
 F:	arch/mips/dts/luton*
 F:	arch/mips/dts/mscc*
 F:	arch/mips/dts/ocelot*
+F:	arch/mips/dts/jr2*
+F:	arch/mips/dts/serval*
 F:	board/mscc/
 F:	configs/mscc*
+F:	drivers/gpio/mscc_sgpio.c
+F:	drivers/spi/mscc_bb_spi.c
 F:	include/configs/vcoreiii.h
+F:	drivers/pinctrl/mscc/
 
 MIPS JZ4780
 M:	Ezequiel Garcia <ezequiel@collabora.com>
diff --git a/Makefile b/Makefile
index 6aa0896..cf7b2b1 100644
--- a/Makefile
+++ b/Makefile
@@ -534,7 +534,7 @@
 	@# Otherwise, 'make silentoldconfig' would be invoked twice.
 	$(Q)touch include/config/auto.conf
 
-u-boot.cfg spl/u-boot.cfg tpl/u-boot.cfg: include/config.h FORCE
+u-boot.cfg spl/u-boot.cfg tpl/u-boot.cfg:
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.autoconf $(@)
 
 -include include/autoconf.mk
@@ -893,7 +893,7 @@
 	>$(MKIMAGEOUTPUT) $(if $(KBUILD_VERBOSE:0=), && cat $(MKIMAGEOUTPUT))
 
 quiet_cmd_mkfitimage = MKIMAGE $@
-cmd_mkfitimage = $(objtree)/tools/mkimage $(MKIMAGEFLAGS_$(@F)) -f $(U_BOOT_ITS) -E $@ -p $(CONFIG_FIT_EXTERNAL_OFFSET)\
+cmd_mkfitimage = $(objtree)/tools/mkimage $(MKIMAGEFLAGS_$(@F)) -f $(U_BOOT_ITS) -E -p $(CONFIG_FIT_EXTERNAL_OFFSET) $@\
 	>$(MKIMAGEOUTPUT) $(if $(KBUILD_VERBOSE:0=), && cat $(MKIMAGEOUTPUT))
 
 quiet_cmd_cat = CAT     $@
@@ -910,7 +910,7 @@
 cmd_cfgcheck = $(srctree)/scripts/check-config.sh $2 \
 		$(srctree)/scripts/config_whitelist.txt $(srctree)
 
-all:		$(ALL-y) cfg
+all:		$(ALL-y)
 ifeq ($(CONFIG_DM_I2C_COMPAT)$(CONFIG_SANDBOX),y)
 	@echo >&2 "===================== WARNING ======================"
 	@echo >&2 "This board uses CONFIG_DM_I2C_COMPAT. Please remove"
@@ -1198,6 +1198,7 @@
 u-boot-dtb.img u-boot.img u-boot.kwb u-boot.pbl u-boot-ivt.img: \
 		$(if $(CONFIG_SPL_LOAD_FIT),u-boot-nodtb.bin dts/dt.dtb,u-boot.bin) FORCE
 	$(call if_changed,mkimage)
+	$(BOARD_SIZE_CHECK)
 
 u-boot.itb: u-boot-nodtb.bin dts/dt.dtb $(U_BOOT_ITS) FORCE
 	$(call if_changed,mkfitimage)
@@ -1555,7 +1556,7 @@
 endif
 
 # prepare2 creates a makefile if using a separate output directory
-prepare2: prepare3 outputmakefile
+prepare2: prepare3 outputmakefile cfg
 
 prepare1: prepare2 $(version_h) $(timestamp_h) \
                    include/config/auto.conf
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index dda4e59..b2ca87d 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -193,7 +193,9 @@
 	am335x-pxm50.dtb \
 	am335x-rut.dtb \
 	am335x-pdu001.dtb \
-	am335x-chiliboard.dtb
+	am335x-chiliboard.dtb \
+	am335x-sl50.dtb \
+	am335x-base0033.dtb
 dtb-$(CONFIG_AM43XX) += am437x-gp-evm.dtb am437x-sk-evm.dtb	\
 	am43x-epos-evm.dtb \
 	am437x-idk-evm.dtb \
@@ -522,6 +524,9 @@
 	omap3-beagle-xm.dtb \
 	omap3-beagle.dtb
 
+dtb-$(CONFIG_TARGET_OMAP3_IGEP00X0) += \
+	omap3-igep0020.dtb
+
 dtb-$(CONFIG_TARGET_SAMA5D2_PTC_EK) += \
 	at91-sama5d2_ptc_ek.dtb
 
diff --git a/arch/arm/dts/am335x-base0033.dts b/arch/arm/dts/am335x-base0033.dts
new file mode 100644
index 0000000..29782be
--- /dev/null
+++ b/arch/arm/dts/am335x-base0033.dts
@@ -0,0 +1,95 @@
+/*
+ * am335x-base0033.dts - Device Tree file for IGEP AQUILA EXPANSION
+ *
+ * Copyright (C) 2013 ISEE 2007 SL - http://www.isee.biz
+ *
+ * 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.
+ */
+
+#include "am335x-igep0033.dtsi"
+
+/ {
+	model = "IGEP COM AM335x on AQUILA Expansion";
+	compatible = "isee,am335x-base0033", "isee,am335x-igep0033", "ti,am33xx";
+
+	hdmi {
+		compatible = "ti,tilcdc,slave";
+		i2c = <&i2c0>;
+		pinctrl-names = "default", "off";
+		pinctrl-0 = <&nxp_hdmi_pins>;
+		pinctrl-1 = <&nxp_hdmi_off_pins>;
+		status = "okay";
+	};
+
+	leds_base {
+		pinctrl-names = "default";
+		pinctrl-0 = <&leds_base_pins>;
+
+		compatible = "gpio-leds";
+
+		led0 {
+			label = "base:red:user";
+			gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;	/* gpio1_21 */
+			default-state = "off";
+		};
+
+		led1 {
+			label = "base:green:user";
+			gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>;	/* gpio2_0 */
+			default-state = "off";
+		};
+	};
+};
+
+&am33xx_pinmux {
+	nxp_hdmi_pins: pinmux_nxp_hdmi_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x9b0, PIN_OUTPUT | MUX_MODE3)	/* xdma_event_intr0.clkout1 */
+			AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0)	/* lcd_data0 */
+			AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0)	/* lcd_data1 */
+			AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0)	/* lcd_data2 */
+			AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0)	/* lcd_data3 */
+			AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0)	/* lcd_data4 */
+			AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0)	/* lcd_data5 */
+			AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0)	/* lcd_data6 */
+			AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0)	/* lcd_data7 */
+			AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0)	/* lcd_data8 */
+			AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0)	/* lcd_data9 */
+			AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0)	/* lcd_data10 */
+			AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0)	/* lcd_data11 */
+			AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0)	/* lcd_data12 */
+			AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0)	/* lcd_data13 */
+			AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0)	/* lcd_data14 */
+			AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0)	/* lcd_data15 */
+			AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0)	/* lcd_vsync */
+			AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0)	/* lcd_hsync */
+			AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0)	/* lcd_pclk */
+			AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0)	/* lcd_ac_bias_en */
+		>;
+	};
+	nxp_hdmi_off_pins: pinmux_nxp_hdmi_off_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x9b0, PIN_OUTPUT | MUX_MODE3)	/* xdma_event_intr0.clkout1 */
+		>;
+	};
+
+	leds_base_pins: pinmux_leds_base_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a5.gpio1_21 */
+			AM33XX_IOPAD(0x888, PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_csn3.gpio2_0 */
+		>;
+	};
+};
+
+&lcdc {
+	status = "okay";
+};
+
+&i2c0 {
+	eeprom: eeprom@50 {
+		compatible = "atmel,24c256";
+		reg = <0x50>;
+	};
+};
diff --git a/arch/arm/dts/am335x-igep0033.dtsi b/arch/arm/dts/am335x-igep0033.dtsi
new file mode 100644
index 0000000..a5769a8
--- /dev/null
+++ b/arch/arm/dts/am335x-igep0033.dtsi
@@ -0,0 +1,323 @@
+/*
+ * am335x-igep0033.dtsi - Device Tree file for IGEP COM AQUILA AM335x
+ *
+ * Copyright (C) 2013 ISEE 2007 SL - http://www.isee.biz
+ *
+ * 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.
+ */
+
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vdd1_reg>;
+		};
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	leds {
+		pinctrl-names = "default";
+		pinctrl-0 = <&leds_pins>;
+
+		compatible = "gpio-leds";
+
+		led0 {
+			label = "com:green:user";
+			gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
+			default-state = "on";
+		};
+	};
+
+	vbat: fixedregulator0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+	};
+
+	vmmc: fixedregulator1 {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+};
+
+&am33xx_pinmux {
+	i2c0_pins: pinmux_i2c0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+			AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	nandflash_pins: pinmux_nandflash_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
+			AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad1.gpmc_ad1 */
+			AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad2.gpmc_ad2 */
+			AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad3.gpmc_ad3 */
+			AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad4.gpmc_ad4 */
+			AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad5.gpmc_ad5 */
+			AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad6.gpmc_ad6 */
+			AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad7.gpmc_ad7 */
+			AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_wait0.gpmc_wait0 */
+			AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_wpn.gpio0_30 */
+			AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn0.gpmc_csn0 */
+			AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0)		/* gpmc_advn_ale.gpmc_advn_ale */
+			AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0)		/* gpmc_oen_ren.gpmc_oen_ren */
+			AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0)		/* gpmc_wen.gpmc_wen */
+			AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0)		/* gpmc_be0n_cle.gpmc_be0n_cle */
+		>;
+	};
+
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	leds_pins: pinmux_leds_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x85c, PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a7.gpio1_23 */
+		>;
+	};
+};
+
+&mac {
+	status = "okay";
+};
+
+&davinci_mdio {
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "rmii";
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "rmii";
+};
+
+&phy_sel {
+	rmii-clock-ext;
+};
+
+&elm {
+	status = "okay";
+};
+
+&gpmc {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&nandflash_pins>;
+
+	ranges = <0 0 0x08000000 0x1000000>;	/* CS0: 16MB for NAND */
+
+	nand@0,0 {
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+		interrupt-parent = <&gpmc>;
+		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
+			     <1 IRQ_TYPE_NONE>;	/* termcount */
+		rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
+		nand-bus-width = <8>;
+		ti,nand-ecc-opt = "bch8";
+		gpmc,device-width = <1>;
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <44>;
+		gpmc,cs-wr-off-ns = <44>;
+		gpmc,adv-on-ns = <6>;
+		gpmc,adv-rd-off-ns = <34>;
+		gpmc,adv-wr-off-ns = <44>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <40>;
+		gpmc,oe-on-ns = <0>;
+		gpmc,oe-off-ns = <54>;
+		gpmc,access-ns = <64>;
+		gpmc,rd-cycle-ns = <82>;
+		gpmc,wr-cycle-ns = <82>;
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ti,elm-id = <&elm>;
+
+		/* MTD partition table */
+		partition@0 {
+			label = "SPL";
+			reg = <0x00000000 0x000080000>;
+		};
+
+		partition@1 {
+			label = "U-boot";
+			reg = <0x00080000 0x001e0000>;
+		};
+
+		partition@2 {
+			label = "U-Boot Env";
+			reg = <0x00260000 0x00020000>;
+		};
+
+		partition@3 {
+			label = "Kernel";
+			reg = <0x00280000 0x00500000>;
+		};
+
+		partition@4 {
+			label = "File System";
+			reg = <0x00780000 0x007880000>;
+		};
+	};
+};
+
+&i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	clock-frequency = <400000>;
+
+	tps: tps@2d {
+		reg = <0x2d>;
+	};
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&vmmc>;
+	bus-width = <4>;
+};
+
+&uart0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+};
+
+&usb1 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+#include "tps65910.dtsi"
+
+&tps {
+	vcc1-supply = <&vbat>;
+	vcc2-supply = <&vbat>;
+	vcc3-supply = <&vbat>;
+	vcc4-supply = <&vbat>;
+	vcc5-supply = <&vbat>;
+	vcc6-supply = <&vbat>;
+	vcc7-supply = <&vbat>;
+	vccio-supply = <&vbat>;
+
+	regulators {
+		vrtc_reg: regulator@0 {
+			regulator-always-on;
+		};
+
+		vio_reg: regulator@1 {
+			regulator-always-on;
+		};
+
+		vdd1_reg: regulator@2 {
+			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1312500>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd2_reg: regulator@3 {
+			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd3_reg: regulator@4 {
+			regulator-always-on;
+		};
+
+		vdig1_reg: regulator@5 {
+			regulator-always-on;
+		};
+
+		vdig2_reg: regulator@6 {
+			regulator-always-on;
+		};
+
+		vpll_reg: regulator@7 {
+			regulator-always-on;
+		};
+
+		vdac_reg: regulator@8 {
+			regulator-always-on;
+		};
+
+		vaux1_reg: regulator@9 {
+			regulator-always-on;
+		};
+
+		vaux2_reg: regulator@10 {
+			regulator-always-on;
+		};
+
+		vaux33_reg: regulator@11 {
+			regulator-always-on;
+		};
+
+		vmmc_reg: regulator@12 {
+			regulator-always-on;
+		};
+	};
+};
+
diff --git a/arch/arm/dts/am335x-pdu001.dts b/arch/arm/dts/am335x-pdu001.dts
index 3a5e9526..ae43d61 100644
--- a/arch/arm/dts/am335x-pdu001.dts
+++ b/arch/arm/dts/am335x-pdu001.dts
@@ -1,4 +1,3 @@
-// SPDX-License-Identifier: GPL-2.0+
 /*
  * pdu001.dts
  *
@@ -7,6 +6,8 @@
  * Copyright (C) 2018 EETS GmbH - http://www.eets.ch/
  *
  * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/
+ *
+ * SPDX-License-Identifier:  GPL-2.0+
  */
 
 /dts-v1/;
@@ -17,7 +18,7 @@
 
 / {
 	model = "EETS,PDU001";
-	compatible = "eets,pdu001", "ti,am33xx";
+	compatible = "ti,am33xx";
 
 	chosen {
 		stdout-path = &uart3;
@@ -303,12 +304,12 @@
 	clock-frequency = <100000>;
 
 	board_24aa025e48: board_24aa025e48@50 {
-		compatible = "microchip,24aa025e48";
+		compatible = "atmel,24c02";
 		reg = <0x50>;
 	};
 
 	backplane_24aa025e48: backplane_24aa025e48@53 {
-		compatible = "microchip,24aa025e48";
+		compatible = "atmel,24c02";
 		reg = <0x53>;
 	};
 
@@ -372,8 +373,8 @@
 	ti,pindir-d0-out-d1-in;
 	status = "okay";
 
-	cfaf240320a032t {
-		compatible = "orise,otm3225a";
+	display-controller@0 {
+		compatible = "orisetech,otm3225a";
 		reg = <0>;
 		spi-max-frequency = <1000000>;
 		// SPI mode 3
@@ -532,16 +533,24 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&davinci_mdio_default>;
 	status = "okay";
+
+	ethphy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+
+	ethphy1: ethernet-phy@1 {
+		reg = <1>;
+	};
 };
 
 &cpsw_emac0 {
-	phy_id = <&davinci_mdio>, <0>;
+	phy-handle = <&ethphy0>;
 	phy-mode = "mii";
 	dual_emac_res_vlan = <1>;
 };
 
 &cpsw_emac1 {
-	phy_id = <&davinci_mdio>, <1>;
+	phy-handle = <&ethphy1>;
 	phy-mode = "mii";
 	dual_emac_res_vlan = <2>;
 };
diff --git a/arch/arm/dts/am335x-sl50.dts b/arch/arm/dts/am335x-sl50.dts
new file mode 100644
index 0000000..1bcc604
--- /dev/null
+++ b/arch/arm/dts/am335x-sl50.dts
@@ -0,0 +1,549 @@
+/*
+ * Copyright (C) 2015 Toby Churchill - http://www.toby-churchill.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.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+
+/ {
+	model = "Toby Churchill SL50 Series";
+	compatible = "tcl,am335x-sl50", "ti,am33xx";
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&dcdc2_reg>;
+		};
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>; /* 512 MB */
+	};
+
+	chosen {
+		stdout-path = &uart0;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pins>;
+
+		led0 {
+			label = "sl50:green:usr0";
+			gpios = <&gpio1 21 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		led1 {
+			label = "sl50:red:usr1";
+			gpios = <&gpio1 22 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		led2 {
+			label = "sl50:green:usr2";
+			gpios = <&gpio1 23 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		led3 {
+			label = "sl50:red:usr3";
+			gpios = <&gpio1 24 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+	};
+
+	backlight0: disp0 {
+		compatible = "pwm-backlight";
+		pwms = <&ehrpwm1 0 500000 0>;
+		brightness-levels = <0 10 20 30 40 50 60 70 80 90 99>;
+		default-brightness-level = <6>;
+	};
+
+	backlight1: disp1 {
+		compatible = "pwm-backlight";
+		pwms = <&ehrpwm1 1 500000 0>;
+		brightness-levels = <0 10 20 30 40 50 60 70 80 90 99>;
+		default-brightness-level = <6>;
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		/* audio external oscillator */
+		tlv320aic3x_mclk: oscillator@0 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency  = <24576000>;	/* 24.576MHz */
+		};
+	};
+
+	sound {
+		compatible = "ti,da830-evm-audio";
+		ti,model = "AM335x-SL50";
+		ti,audio-codec = <&audio_codec>;
+		ti,mcasp-controller = <&mcasp0>;
+
+		clocks = <&tlv320aic3x_mclk>;
+		clock-names = "mclk";
+
+		ti,audio-routing =
+			"Headphone Jack",	"HPLOUT",
+			"Headphone Jack",	"HPROUT",
+			"LINE1R",               "Line In",
+			"LINE1L",		"Line In";
+	};
+
+	emmc_pwrseq: pwrseq@0 {
+		compatible = "mmc-pwrseq-emmc";
+		pinctrl-names = "default";
+		pinctrl-0 = <&emmc_pwrseq_pins>;
+		reset-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
+	};
+
+	vmmcsd_fixed: fixedregulator0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmcsd_fixed";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+};
+
+&am33xx_pinmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lwb_pins>;
+
+	led_pins: pinmux_led_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE7)	/* gpmc_a5.gpio1_21 */
+			AM33XX_IOPAD(0x858, PIN_OUTPUT | MUX_MODE7)	/* gpmc_a6.gpio1_22 */
+			AM33XX_IOPAD(0x85c, PIN_OUTPUT | MUX_MODE7)	/* gpmc_a7.gpio1_23 */
+			AM33XX_IOPAD(0x860, PIN_OUTPUT | MUX_MODE7)	/* gpmc_a8.gpio1_24 */
+		>;
+	};
+
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	uart1_pins: pinmux_uart1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart1_rxd.uart1_rxd */
+			AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart1_txd.uart1_txd */
+		>;
+	};
+
+	uart4_pins: pinmux_uart4_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE6)	/* gpmc_wait0.uart4_rxd */
+			AM33XX_IOPAD(0x874, PIN_OUTPUT_PULLDOWN | MUX_MODE6)	/* gpmc_wpn.uart4_txd */
+		>;
+	};
+
+	i2c0_pins: pinmux_i2c0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+			AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	i2c2_pins: pinmux_i2c2_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x978, PIN_INPUT_PULLUP | MUX_MODE3)	/* uart1_ctsn.i2c2_sda */
+			AM33XX_IOPAD(0x97c, PIN_INPUT_PULLUP | MUX_MODE3)	/* uart1_rtsn.i2c2_scl */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxerr.mii1_rxerr */
+			AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txen.mii1_txen */
+			AM33XX_IOPAD(0x918, PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxdv.mii1_rxdv */
+			AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd3.mii1_txd3 */
+			AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd2.mii1_txd2 */
+			AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd1.mii1_txd1 */
+			AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd0.mii1_txd0 */
+			AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_txclk.mii1_txclk */
+			AM33XX_IOPAD(0x930, PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxclk.mii1_rxclk */
+			AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd3.mii1_rxd3 */
+			AM33XX_IOPAD(0x938, PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd2.mii1_rxd2 */
+			AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd1.mii1_rxd1 */
+			AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd0.mii1_rxd0 */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x96c, PIN_INPUT | MUX_MODE7)		/* uart0_rtsn.gpio1_9 */
+		>;
+	};
+
+	emmc_pwrseq_pins: pinmux_emmc_pwrseq_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLUP | MUX_MODE7)	/* gpmc_a4.gpio1_20 */
+		>;
+	};
+
+	emmc_pins: pinmux_emmc_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2)	/* gpmc_csn1.mmc1_clk */
+			AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2)	/* gpmc_csn2.mmc1_cmd */
+			AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad0.mmc1_dat0 */
+			AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad1.mmc1_dat1 */
+			AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad2.mmc1_dat2 */
+			AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad3.mmc1_dat3 */
+			AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad4.mmc1_dat4 */
+			AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1) 	/* gpmc_ad5.mmc1_dat5 */
+			AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad6.mmc1_dat6 */
+			AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad7.mmc1_dat7 */
+		>;
+	};
+
+	audio_pins: pinmux_audio_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* mcasp0_ahcklx.mcasp0_ahclkx */
+			AM33XX_IOPAD(0x994, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* mcasp0_fsx.mcasp0_fsx */
+			AM33XX_IOPAD(0x990, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* mcasp0_aclkx.mcasp0_aclkx */
+			AM33XX_IOPAD(0x998, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* mcasp0_axr0.mcasp0_axr0 */
+			AM33XX_IOPAD(0x99c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mcasp0_ahclkr.mcasp0_axr2 */
+		>;
+	};
+
+	ehrpwm1_pins: pinmux_ehrpwm1a_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x848, PIN_OUTPUT | MUX_MODE6)	/* gpmc_a2.ehrpwm1a */
+			AM33XX_IOPAD(0x84c, PIN_OUTPUT | MUX_MODE6)	/* gpmc_a3.ehrpwm1b */
+		>;
+	};
+
+	spi0_pins: pinmux_spi0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0)	/* SPI0_MOSI - spi0_d0.spi0_d0 */
+			AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0)	/* SPI0_MISO - spi0_d1.spi0_d1 */
+			AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0)	/* SPI0_CLK  - spi0_clk.spi0_clk */
+			AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0)	/* SPI0_CS0 (NBATTSS) - spi0_cs0.spi0_cs0 */
+			AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE0)	/* SPI0_CS1 (FPGA_FLASH_NCS) - spi0_cs1.spi0_cs1 */
+		>;
+	};
+
+	lwb_pins: pinmux_lwb_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x9a4, PIN_OUTPUT | MUX_MODE7)	/* SoundPA_en - mcasp0_fsr.gpio3_19 */
+			AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE7)	/* nKbdOnC - gpmc_ad10.gpio0_26 */
+			AM33XX_IOPAD(0x830, PIN_INPUT_PULLUP | MUX_MODE7)	/* nKbdInt - gpmc_ad12.gpio1_12 */
+			AM33XX_IOPAD(0x834, PIN_INPUT_PULLUP | MUX_MODE7)	/* nKbdReset - gpmc_ad13.gpio1_13 */
+			AM33XX_IOPAD(0x838, PIN_INPUT_PULLUP | MUX_MODE7)	/* nDispReset - gpmc_ad14.gpio1_14 */
+			AM33XX_IOPAD(0x844, PIN_INPUT_PULLUP | MUX_MODE7)	/* USB1_enPower - gpmc_a1.gpio1_17 */
+			/* PDI Bus - Battery system */
+			AM33XX_IOPAD(0x840, PIN_INPUT_PULLUP | MUX_MODE7)	/* nBattReset  gpmc_a0.gpio1_16 */
+			AM33XX_IOPAD(0x83c, PIN_INPUT_PULLUP | MUX_MODE7)	/* BattPDIData gpmc_ad15.gpio1_15 */
+		>;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	clock-frequency = <400000>;
+
+	tps: tps@24 {
+		reg = <0x24>;
+	};
+
+	bq32000: rtc@68 {
+		compatible = "ti,bq32000";
+		trickle-resistor-ohms = <1120>;
+		reg = <0x68>;
+	};
+
+	eeprom: eeprom@50 {
+		compatible = "atmel,24c256";
+		reg = <0x50>;
+	};
+
+	gpio_exp: mcp23017@20 {
+		compatible = "microchip,mcp23017";
+		reg = <0x20>;
+	};
+
+};
+
+&i2c2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins>;
+
+	clock-frequency = <400000>;
+
+	audio_codec: tlv320aic3106@1b {
+		status = "okay";
+		compatible = "ti,tlv320aic3106";
+		reg = <0x1b>;
+
+		AVDD-supply = <&ldo4_reg>;
+		IOVDD-supply = <&ldo4_reg>;
+		DRVDD-supply = <&ldo4_reg>;
+		DVDD-supply = <&ldo3_reg>;
+	};
+
+	/* Ambient Light Sensor */
+	als: isl29023@44 {
+		compatible = "isil,isl29023";
+		reg = <0x44>;
+	};
+};
+
+&rtc {
+	status = "disabled";
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+	dr_mode = "peripheral";
+};
+
+&usb1 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+&mmc1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	bus-width = <4>;
+	cd-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
+	vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_pins>;
+	bus-width = <8>;
+	vmmc-supply = <&vmmcsd_fixed>;
+	mmc-pwrseq = <&emmc_pwrseq>;
+};
+
+&mcasp0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&audio_pins>;
+
+	op-mode = <0>;  /* MCASP_ISS_MODE */
+	tdm-slots = <2>;
+	serial-dir = <
+		2 0 1 0
+		0 0 0 0
+		0 0 0 0
+		0 0 0 0
+	>;
+	tx-num-evt = <1>;
+	rx-num-evt = <1>;
+};
+
+&uart0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+};
+
+&uart1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+};
+
+&uart4 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart4_pins>;
+};
+
+&spi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_pins>;
+
+	flash: n25q032@1 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "micron,n25q032";
+		reg = <1>;
+		spi-max-frequency = <5000000>;
+	};
+};
+
+#include "tps65217.dtsi"
+
+&tps {
+	ti,pmic-shutdown-controller;
+
+	interrupt-parent = <&intc>;
+	interrupts = <7>;	/* NNMI */
+
+	regulators {
+		dcdc1_reg: regulator@0 {
+			/* VDDS_DDR */
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+			regulator-always-on;
+		};
+
+		dcdc2_reg: regulator@1 {
+			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <925000>;
+			regulator-max-microvolt = <1325000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc3_reg: regulator@2 {
+			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <925000>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		ldo1_reg: regulator@3 {
+			/* VRTC / VIO / VDDS*/
+			regulator-always-on;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+		};
+
+		ldo2_reg: regulator@4 {
+			/* VDD_3V3AUX */
+			regulator-always-on;
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+		};
+
+		ldo3_reg: regulator@5 {
+			/* VDD_1V8 */
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			regulator-always-on;
+		};
+
+		ldo4_reg: regulator@6 {
+			/* VDD_3V3A */
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "mii";
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "mii";
+};
+
+&mac {
+	status = "okay";
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+};
+
+&davinci_mdio {
+	status = "okay";
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+};
+
+&sham {
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
+
+&epwmss1 {
+	status = "okay";
+};
+
+&ehrpwm1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&ehrpwm1_pins>;
+};
diff --git a/arch/arm/dts/dragonboard410c-uboot.dtsi b/arch/arm/dts/dragonboard410c-uboot.dtsi
index a07c97e..9c1be25 100644
--- a/arch/arm/dts/dragonboard410c-uboot.dtsi
+++ b/arch/arm/dts/dragonboard410c-uboot.dtsi
@@ -28,8 +28,8 @@
 
 		serial@78b0000 {
 			u-boot,dm-pre-reloc;
-			};
 		};
+	};
 };
 
 
diff --git a/arch/arm/dts/hi6220-hikey-u-boot.dtsi b/arch/arm/dts/hi6220-hikey-u-boot.dtsi
new file mode 100644
index 0000000..3113983
--- /dev/null
+++ b/arch/arm/dts/hi6220-hikey-u-boot.dtsi
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * U-Boot additions
+ *
+ * Copyright (c) 2018 Linaro Ltd.
+ */
+
+&mmc0 {
+	u-boot,dm-pre-reloc;
+};
+
+&mmc1 {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/hi6220-hikey.dts b/arch/arm/dts/hi6220-hikey.dts
index 24f0925..d639293 100644
--- a/arch/arm/dts/hi6220-hikey.dts
+++ b/arch/arm/dts/hi6220-hikey.dts
@@ -40,6 +40,17 @@
 	};
 };
 
+&mmc0 {
+	status = "okay";
+	non-removable;
+	bus-width = <8>;
+};
+
+&mmc1 {
+	status = "okay";
+	bus-width = <4>;
+};
+
 &uart2 {
 	label = "LS-UART0";
 };
diff --git a/arch/arm/dts/hi6220.dtsi b/arch/arm/dts/hi6220.dtsi
index a610ccb..501c890 100644
--- a/arch/arm/dts/hi6220.dtsi
+++ b/arch/arm/dts/hi6220.dtsi
@@ -162,6 +162,24 @@
 			#clock-cells = <1>;
 		};
 
+		mmc0: dwmmc@f723d000 {
+			compatible = "hisilicon,hi6220-dw-mshc";
+			reg = <0x0 0xf723d000 0x0 0x1000>;
+			interrupts = <0x0 0x48 0x4>;
+			clocks = <&sys_ctrl 2>, <&sys_ctrl 1>;
+			clock-names = "ciu", "biu";
+			status = "disabled";
+		};
+
+		mmc1: dwmmc@f723e000 {
+			compatible = "hisilicon,hi6220-dw-mshc";
+			reg = <0x0 0xf723e000 0x0 0x1000>;
+			interrupts = <0x0 0x49 0x4>;
+			clocks = <&sys_ctrl 4>, <&sys_ctrl 3>;
+			clock-names = "ciu", "biu";
+			status = "disabled";
+		};
+
 		uart0: uart@f8015000 {	/* console */
 			compatible = "arm,pl011", "arm,primecell";
 			reg = <0x0 0xf8015000 0x0 0x1000>;
diff --git a/arch/arm/dts/mt7623.dtsi b/arch/arm/dts/mt7623.dtsi
index f50f4ef..448d1d7 100644
--- a/arch/arm/dts/mt7623.dtsi
+++ b/arch/arm/dts/mt7623.dtsi
@@ -10,6 +10,7 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/power/mt7623-power.h>
+#include <dt-bindings/reset/mtk-reset.h>
 #include "skeleton.dtsi"
 
 / {
@@ -248,8 +249,26 @@
 	};
 
 	ethsys: syscon@1b000000 {
-		compatible = "mediatek,mt7623-ethsys";
+		compatible = "mediatek,mt7623-ethsys", "syscon";
 		reg = <0x1b000000 0x1000>;
 		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	eth: ethernet@1b100000 {
+		compatible = "mediatek,mt7623-eth", "syscon";
+		reg = <0x1b100000 0x20000>;
+		clocks = <&topckgen CLK_TOP_ETHIF_SEL>,
+			 <&ethsys CLK_ETHSYS_ESW>,
+			 <&ethsys CLK_ETHSYS_GP1>,
+			 <&ethsys CLK_ETHSYS_GP2>,
+			 <&apmixedsys CLK_APMIXED_TRGPLL>;
+		clock-names = "ethif", "esw", "gp1", "gp2", "trgpll";
+		power-domains = <&scpsys MT7623_POWER_DOMAIN_ETH>;
+		resets = <&ethsys ETHSYS_FE_RST>,
+			 <&ethsys ETHSYS_MCM_RST>;
+		reset-names = "fe", "mcm";
+		mediatek,ethsys = <&ethsys>;
+		status = "disabled";
 	};
 };
diff --git a/arch/arm/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/dts/mt7623n-bananapi-bpi-r2.dts
index 84a77fd..51628bb 100644
--- a/arch/arm/dts/mt7623n-bananapi-bpi-r2.dts
+++ b/arch/arm/dts/mt7623n-bananapi-bpi-r2.dts
@@ -67,6 +67,19 @@
 	};
 };
 
+&eth {
+	status = "okay";
+	mediatek,gmac-id = <0>;
+	phy-mode = "rgmii";
+	mediatek,switch = "mt7530";
+	reset-gpios = <&gpio 33 GPIO_ACTIVE_HIGH>;
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
 &mmc0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc0_pins_default>;
diff --git a/arch/arm/dts/mt7629-rfb.dts b/arch/arm/dts/mt7629-rfb.dts
index a6d28a0..95d10aa 100644
--- a/arch/arm/dts/mt7629-rfb.dts
+++ b/arch/arm/dts/mt7629-rfb.dts
@@ -22,6 +22,17 @@
 	};
 };
 
+&eth {
+	status = "okay";
+	mediatek,gmac-id = <1>;
+	phy-mode = "gmii";
+	phy-handle = <&phy0>;
+
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+};
+
 &pinctrl {
 	qspi_pins: qspi-pins {
 		mux {
diff --git a/arch/arm/dts/mt7629.dtsi b/arch/arm/dts/mt7629.dtsi
index e6052bb..c87115e 100644
--- a/arch/arm/dts/mt7629.dtsi
+++ b/arch/arm/dts/mt7629.dtsi
@@ -10,6 +10,7 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/power/mt7629-power.h>
+#include <dt-bindings/reset/mtk-reset.h>
 #include "skeleton.dtsi"
 
 / {
@@ -228,6 +229,48 @@
 		compatible = "mediatek,mt7629-ethsys", "syscon";
 		reg = <0x1b000000 0x1000>;
 		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	eth: ethernet@1b100000 {
+		compatible = "mediatek,mt7629-eth", "syscon";
+		reg = <0x1b100000 0x20000>;
+		clocks = <&topckgen CLK_TOP_ETH_SEL>,
+			<&topckgen CLK_TOP_F10M_REF_SEL>,
+			<&ethsys CLK_ETH_ESW_EN>,
+			<&ethsys CLK_ETH_GP0_EN>,
+			<&ethsys CLK_ETH_GP1_EN>,
+			<&ethsys CLK_ETH_GP2_EN>,
+			<&ethsys CLK_ETH_FE_EN>,
+			<&sgmiisys0 CLK_SGMII_TX_EN>,
+			<&sgmiisys0 CLK_SGMII_RX_EN>,
+			<&sgmiisys0 CLK_SGMII_CDR_REF>,
+			<&sgmiisys0 CLK_SGMII_CDR_FB>,
+			<&sgmiisys1 CLK_SGMII_TX_EN>,
+			<&sgmiisys1 CLK_SGMII_RX_EN>,
+			<&sgmiisys1 CLK_SGMII_CDR_REF>,
+			<&sgmiisys1 CLK_SGMII_CDR_FB>,
+			<&apmixedsys CLK_APMIXED_SGMIPLL>,
+			<&apmixedsys CLK_APMIXED_ETH2PLL>;
+		clock-names = "ethif", "sgmiitop", "esw", "gp0", "gp1", "gp2",
+				"fe", "sgmii_tx250m", "sgmii_rx250m",
+				"sgmii_cdr_ref", "sgmii_cdr_fb",
+				"sgmii2_tx250m", "sgmii2_rx250m",
+				"sgmii2_cdr_ref", "sgmii2_cdr_fb",
+				"sgmii_ck", "eth2pll";
+		assigned-clocks = <&topckgen CLK_TOP_ETH_SEL>,
+				  <&topckgen CLK_TOP_F10M_REF_SEL>;
+		assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL1_D2>,
+					 <&topckgen CLK_TOP_SGMIIPLL_D2>;
+		power-domains = <&scpsys MT7629_POWER_DOMAIN_ETHSYS>;
+		resets = <&ethsys ETHSYS_FE_RST>;
+		reset-names = "fe";
+		mediatek,ethsys = <&ethsys>;
+		mediatek,sgmiisys = <&sgmiisys0>;
+		mediatek,infracfg = <&infracfg>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
 	};
 
 	sgmiisys0: syscon@1b128000 {
diff --git a/arch/arm/dts/omap3-igep.dtsi b/arch/arm/dts/omap3-igep.dtsi
new file mode 100644
index 0000000..f33cc80
--- /dev/null
+++ b/arch/arm/dts/omap3-igep.dtsi
@@ -0,0 +1,250 @@
+/*
+ * Common device tree for IGEP boards based on AM/DM37x
+ *
+ * Copyright (C) 2012 Javier Martinez Canillas <javier@osg.samsung.com>
+ * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "omap36xx.dtsi"
+
+/ {
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>; /* 512 MB */
+	};
+
+	chosen {
+		stdout-path = &uart3;
+	};
+
+	sound {
+		compatible = "ti,omap-twl4030";
+		ti,model = "igep2";
+		ti,mcbsp = <&mcbsp2>;
+	};
+
+	vdd33: regulator-vdd33 {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd33";
+		regulator-always-on;
+	};
+
+};
+
+&omap3_pmx_core {
+	gpmc_pins: pinmux_gpmc_pins {
+		pinctrl-single,pins = <
+			/* OneNAND seems to require PIN_INPUT on clock. */
+                        OMAP3_CORE1_IOPAD(0x20be, PIN_INPUT | MUX_MODE0)        /* gpmc_clk.gpmc_clk */
+		>;
+	};
+
+	uart1_pins: pinmux_uart1_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | MUX_MODE0)	/* uart1_rx.uart1_rx */
+			OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE0)	/* uart1_tx.uart1_tx */
+		>;
+	};
+
+	uart3_pins: pinmux_uart3_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0)	/* uart3_rx.uart3_rx */
+			OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0)	/* uart3_tx.uart3_tx */
+		>;
+	};
+
+	mcbsp2_pins: pinmux_mcbsp2_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x213c, PIN_INPUT | MUX_MODE0)	/* mcbsp2_fsx.mcbsp2_fsx */
+			OMAP3_CORE1_IOPAD(0x213e, PIN_INPUT | MUX_MODE0)	/* mcbsp2_clkx.mcbsp2_clkx */
+			OMAP3_CORE1_IOPAD(0x2140, PIN_INPUT | MUX_MODE0)	/* mcbsp2_dr.mcbsp2.dr */
+			OMAP3_CORE1_IOPAD(0x2142, PIN_OUTPUT | MUX_MODE0)	/* mcbsp2_dx.mcbsp2_dx */
+		>;
+	};
+
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_clk.sdmmc1_clk */
+			OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_cmd.sdmmc1_cmd */
+			OMAP3_CORE1_IOPAD(0x2148, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat0.sdmmc1_dat0 */
+			OMAP3_CORE1_IOPAD(0x214a, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat1.sdmmc1_dat1 */
+			OMAP3_CORE1_IOPAD(0x214c, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat2.sdmmc1_dat2 */
+			OMAP3_CORE1_IOPAD(0x214e, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat3.sdmmc1_dat3 */
+		>;
+	};
+
+	mmc2_pins: pinmux_mmc2_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_clk.sdmmc2_clk */
+			OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_cmd.sdmmc2_cmd */
+			OMAP3_CORE1_IOPAD(0x215c, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat0.sdmmc2_dat0 */
+			OMAP3_CORE1_IOPAD(0x215e, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_dat1.sdmmc2_dat1 */
+			OMAP3_CORE1_IOPAD(0x2160, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_dat2.sdmmc2_dat2 */
+			OMAP3_CORE1_IOPAD(0x2162, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_dat3.sdmmc2_dat3 */
+		>;
+	};
+
+	i2c1_pins: pinmux_i2c1_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT | MUX_MODE0)	/* i2c1_scl.i2c1_scl */
+			OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT | MUX_MODE0)	/* i2c1_sda.i2c1_sda */
+		>;
+	};
+
+	i2c3_pins: pinmux_i2c3_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT | MUX_MODE0)	/* i2c3_scl.i2c3_scl */
+			OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT | MUX_MODE0)	/* i2c3_sda.i2c3_sda */
+		>;
+	};
+};
+
+&gpmc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&gpmc_pins>;
+
+	nand@0,0 {
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+		interrupt-parent = <&gpmc>;
+		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
+			     <1 IRQ_TYPE_NONE>;	/* termcount */
+		linux,mtd-name= "micron,mt29c4g96maz";
+		nand-bus-width = <16>;
+		gpmc,device-width = <2>;
+		ti,nand-ecc-opt = "bch8";
+
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <44>;
+		gpmc,cs-wr-off-ns = <44>;
+		gpmc,adv-on-ns = <6>;
+		gpmc,adv-rd-off-ns = <34>;
+		gpmc,adv-wr-off-ns = <44>;
+		gpmc,we-off-ns = <40>;
+		gpmc,oe-off-ns = <54>;
+		gpmc,access-ns = <64>;
+		gpmc,rd-cycle-ns = <82>;
+		gpmc,wr-cycle-ns = <82>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		status = "okay";
+	};
+
+	onenand@0,0 {
+		compatible = "ti,omap2-onenand";
+		reg = <0 0 0x20000>;	/* CS0, offset 0, IO size 128K */
+
+		gpmc,sync-read;
+		gpmc,sync-write;
+		gpmc,burst-length = <16>;
+		gpmc,burst-wrap;
+		gpmc,burst-read;
+		gpmc,burst-write;
+		gpmc,device-width = <2>; /* GPMC_DEVWIDTH_16BIT */
+		gpmc,mux-add-data = <2>; /* GPMC_MUX_AD */
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <96>;
+		gpmc,cs-wr-off-ns = <96>;
+		gpmc,adv-on-ns = <0>;
+		gpmc,adv-rd-off-ns = <12>;
+		gpmc,adv-wr-off-ns = <12>;
+		gpmc,oe-on-ns = <18>;
+		gpmc,oe-off-ns = <96>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <96>;
+		gpmc,rd-cycle-ns = <114>;
+		gpmc,wr-cycle-ns = <114>;
+		gpmc,access-ns = <90>;
+		gpmc,page-burst-access-ns = <12>;
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,wait-monitoring-ns = <0>;
+		gpmc,clk-activation-ns = <6>;
+		gpmc,wr-data-mux-bus-ns = <30>;
+		gpmc,wr-access-ns = <90>;
+		gpmc,sync-clk-ps = <12000>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		status = "disabled";
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	clock-frequency = <2600000>;
+
+	twl: twl@48 {
+		reg = <0x48>;
+		interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+		interrupt-parent = <&intc>;
+
+		twl_audio: audio {
+			compatible = "ti,twl4030-audio";
+			codec {
+			};
+		};
+	};
+};
+
+#include "twl4030.dtsi"
+#include "twl4030_omap3.dtsi"
+
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_pins>;
+};
+
+&mcbsp2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcbsp2_pins>;
+	status = "okay";
+};
+
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	vmmc-supply = <&vmmc1>;
+	vmmc_aux-supply = <&vsim>;
+	bus-width = <4>;
+	cd-gpios = <&twl_gpio 0 GPIO_ACTIVE_LOW>;
+};
+
+&mmc3 {
+	status = "disabled";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+};
+
+&twl_gpio {
+	ti,use-leds;
+};
+
+&usb_otg_hs {
+	interface-type = <0>;
+	usb-phy = <&usb2_phy>;
+	phys = <&usb2_phy>;
+	phy-names = "usb2-phy";
+	mode = <3>;
+	power = <50>;
+};
diff --git a/arch/arm/dts/omap3-igep0020-common.dtsi b/arch/arm/dts/omap3-igep0020-common.dtsi
new file mode 100644
index 0000000..ecbec23
--- /dev/null
+++ b/arch/arm/dts/omap3-igep0020-common.dtsi
@@ -0,0 +1,264 @@
+/*
+ * Common Device Tree Source for IGEPv2
+ *
+ * Copyright (C) 2014 Javier Martinez Canillas <javier@osg.samsung.com>
+ * Copyright (C) 2014 Enric Balletbo i Serra <eballetbo@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "omap3-igep.dtsi"
+#include "omap-gpmc-smsc9221.dtsi"
+
+/ {
+
+	leds {
+		pinctrl-names = "default";
+		pinctrl-0 = <&leds_pins>;
+		compatible = "gpio-leds";
+
+		boot {
+			 label = "omap3:green:boot";
+			 gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+			 default-state = "on";
+		};
+
+		user0 {
+			 label = "omap3:red:user0";
+			 gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>;
+			 default-state = "off";
+		};
+
+		user1 {
+			 label = "omap3:red:user1";
+			 gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+			 default-state = "off";
+		};
+
+		user2 {
+			label = "omap3:green:user1";
+			gpios = <&twl_gpio 19 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	/* HS USB Port 1 Power */
+	hsusb1_power: hsusb1_power_reg {
+		compatible = "regulator-fixed";
+		regulator-name = "hsusb1_vbus";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&twl_gpio 18 GPIO_ACTIVE_LOW>;	/* GPIO LEDA */
+		startup-delay-us = <70000>;
+	};
+
+	/* HS USB Host PHY on PORT 1 */
+	hsusb1_phy: hsusb1_phy {
+		compatible = "usb-nop-xceiv";
+		reset-gpios = <&gpio1 24 GPIO_ACTIVE_LOW>; /* gpio_24 */
+		vcc-supply = <&hsusb1_power>;
+		#phy-cells = <0>;
+	};
+
+	tfp410: encoder {
+		compatible = "ti,tfp410";
+		powerdown-gpios = <&gpio6 10 GPIO_ACTIVE_LOW>; /* gpio_170 */
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				tfp410_in: endpoint {
+					remote-endpoint = <&dpi_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+
+				tfp410_out: endpoint {
+					remote-endpoint = <&dvi_connector_in>;
+				};
+			};
+		};
+	};
+
+	dvi0: connector {
+		compatible = "dvi-connector";
+		label = "dvi";
+
+		digital;
+
+		ddc-i2c-bus = <&i2c3>;
+
+		port {
+			dvi_connector_in: endpoint {
+				remote-endpoint = <&tfp410_out>;
+			};
+		};
+	};
+};
+
+&omap3_pmx_core {
+	pinctrl-names = "default";
+	pinctrl-0 = <
+		&tfp410_pins
+		&dss_dpi_pins
+	>;
+
+	tfp410_pins: pinmux_tfp410_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21c6, PIN_OUTPUT | MUX_MODE4)   /* hdq_sio.gpio_170 */
+		>;
+	};
+
+	dss_dpi_pins: pinmux_dss_dpi_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0)   /* dss_pclk.dss_pclk */
+			OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0)   /* dss_hsync.dss_hsync */
+			OMAP3_CORE1_IOPAD(0x20d8, PIN_OUTPUT | MUX_MODE0)   /* dss_vsync.dss_vsync */
+			OMAP3_CORE1_IOPAD(0x20da, PIN_OUTPUT | MUX_MODE0)   /* dss_acbias.dss_acbias */
+			OMAP3_CORE1_IOPAD(0x20dc, PIN_OUTPUT | MUX_MODE0)   /* dss_data0.dss_data0 */
+			OMAP3_CORE1_IOPAD(0x20de, PIN_OUTPUT | MUX_MODE0)   /* dss_data1.dss_data1 */
+			OMAP3_CORE1_IOPAD(0x20e0, PIN_OUTPUT | MUX_MODE0)   /* dss_data2.dss_data2 */
+			OMAP3_CORE1_IOPAD(0x20e2, PIN_OUTPUT | MUX_MODE0)   /* dss_data3.dss_data3 */
+			OMAP3_CORE1_IOPAD(0x20e4, PIN_OUTPUT | MUX_MODE0)   /* dss_data4.dss_data4 */
+			OMAP3_CORE1_IOPAD(0x20e6, PIN_OUTPUT | MUX_MODE0)   /* dss_data5.dss_data5 */
+			OMAP3_CORE1_IOPAD(0x20e8, PIN_OUTPUT | MUX_MODE0)   /* dss_data6.dss_data6 */
+			OMAP3_CORE1_IOPAD(0x20ea, PIN_OUTPUT | MUX_MODE0)   /* dss_data7.dss_data7 */
+			OMAP3_CORE1_IOPAD(0x20ec, PIN_OUTPUT | MUX_MODE0)   /* dss_data8.dss_data8 */
+			OMAP3_CORE1_IOPAD(0x20ee, PIN_OUTPUT | MUX_MODE0)   /* dss_data9.dss_data9 */
+			OMAP3_CORE1_IOPAD(0x20f0, PIN_OUTPUT | MUX_MODE0)   /* dss_data10.dss_data10 */
+			OMAP3_CORE1_IOPAD(0x20f2, PIN_OUTPUT | MUX_MODE0)   /* dss_data11.dss_data11 */
+			OMAP3_CORE1_IOPAD(0x20f4, PIN_OUTPUT | MUX_MODE0)   /* dss_data12.dss_data12 */
+			OMAP3_CORE1_IOPAD(0x20f6, PIN_OUTPUT | MUX_MODE0)   /* dss_data13.dss_data13 */
+			OMAP3_CORE1_IOPAD(0x20f8, PIN_OUTPUT | MUX_MODE0)   /* dss_data14.dss_data14 */
+			OMAP3_CORE1_IOPAD(0x20fa, PIN_OUTPUT | MUX_MODE0)   /* dss_data15.dss_data15 */
+			OMAP3_CORE1_IOPAD(0x20fc, PIN_OUTPUT | MUX_MODE0)   /* dss_data16.dss_data16 */
+			OMAP3_CORE1_IOPAD(0x20fe, PIN_OUTPUT | MUX_MODE0)   /* dss_data17.dss_data17 */
+			OMAP3_CORE1_IOPAD(0x2100, PIN_OUTPUT | MUX_MODE0)   /* dss_data18.dss_data18 */
+			OMAP3_CORE1_IOPAD(0x2102, PIN_OUTPUT | MUX_MODE0)   /* dss_data19.dss_data19 */
+			OMAP3_CORE1_IOPAD(0x2104, PIN_OUTPUT | MUX_MODE0)   /* dss_data20.dss_data20 */
+			OMAP3_CORE1_IOPAD(0x2106, PIN_OUTPUT | MUX_MODE0)   /* dss_data21.dss_data21 */
+			OMAP3_CORE1_IOPAD(0x2108, PIN_OUTPUT | MUX_MODE0)   /* dss_data22.dss_data22 */
+			OMAP3_CORE1_IOPAD(0x210a, PIN_OUTPUT | MUX_MODE0)   /* dss_data23.dss_data23 */
+		>;
+	};
+
+	uart2_pins: pinmux_uart2_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT | MUX_MODE0)	/* uart2_cts.uart2_cts */
+			OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0)	/* uart2_rts .uart2_rts*/
+			OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0)	/* uart2_tx.uart2_tx */
+			OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0)	/* uart2_rx.uart2_rx */
+		>;
+	};
+
+	smsc9221_pins: pinmux_smsc9221_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21d2, PIN_INPUT | MUX_MODE4)	/* mcspi1_cs2.gpio_176 */
+		>;
+	};
+};
+
+&omap3_pmx_core2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <
+		&hsusbb1_pins
+	>;
+
+	hsusbb1_pins: pinmux_hsusbb1_pins {
+		pinctrl-single,pins = <
+			OMAP3630_CORE2_IOPAD(0x25da, PIN_OUTPUT | MUX_MODE3)		/* etk_ctl.hsusb1_clk */
+			OMAP3630_CORE2_IOPAD(0x25d8, PIN_OUTPUT | MUX_MODE3)		/* etk_clk.hsusb1_stp */
+			OMAP3630_CORE2_IOPAD(0x25ec, PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d8.hsusb1_dir */
+			OMAP3630_CORE2_IOPAD(0x25ee, PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d9.hsusb1_nxt */
+			OMAP3630_CORE2_IOPAD(0x25dc, PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d0.hsusb1_data0 */
+			OMAP3630_CORE2_IOPAD(0x25de, PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d1.hsusb1_data1 */
+			OMAP3630_CORE2_IOPAD(0x25e0, PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d2.hsusb1_data2 */
+			OMAP3630_CORE2_IOPAD(0x25e2, PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d3.hsusb1_data7 */
+			OMAP3630_CORE2_IOPAD(0x25e4, PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d4.hsusb1_data4 */
+			OMAP3630_CORE2_IOPAD(0x25e6, PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d5.hsusb1_data5 */
+			OMAP3630_CORE2_IOPAD(0x25e8, PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d6.hsusb1_data6 */
+			OMAP3630_CORE2_IOPAD(0x25ea, PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d7.hsusb1_data3 */
+		>;
+	};
+
+	leds_pins: pinmux_leds_pins {
+		pinctrl-single,pins = <
+			OMAP3630_CORE2_IOPAD(0x25f4, PIN_OUTPUT | MUX_MODE4) /* etk_d12.gpio_26 */
+			OMAP3630_CORE2_IOPAD(0x25f6, PIN_OUTPUT | MUX_MODE4) /* etk_d13.gpio_27 */
+			OMAP3630_CORE2_IOPAD(0x25f8, PIN_OUTPUT | MUX_MODE4) /* etk_d14.gpio_28 */
+		>;
+	};
+
+	mmc1_wp_pins: pinmux_mmc1_cd_pins {
+		pinctrl-single,pins = <
+			OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT | MUX_MODE4)   /* etk_d15.gpio_29 */
+		>;
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+
+	/*
+	 * Display monitor features are burnt in the EEPROM
+	 * as EDID data.
+	 */
+	eeprom@50 {
+		compatible = "ti,eeprom";
+		reg = <0x50>;
+	};
+};
+
+&gpmc {
+	ranges = <0 0 0x30000000 0x01000000>,	/* CS0: 16MB for NAND */
+		 <5 0 0x2c000000 0x01000000>;	/* CS5: 16MB for ethernet */
+
+	ethernet@gpmc {
+		pinctrl-names = "default";
+		pinctrl-0 = <&smsc9221_pins>;
+		reg = <5 0 0xff>;
+		interrupt-parent = <&gpio6>;
+		interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
+	};
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_pins>;
+};
+
+&usbhshost {
+	port1-mode = "ehci-phy";
+};
+
+&usbhsehci {
+	phys = <&hsusb1_phy>;
+};
+
+&vpll2 {
+	/* Needed for DSS */
+	regulator-name = "vdds_dsi";
+};
+
+&dss {
+	status = "ok";
+
+	port {
+		dpi_out: endpoint {
+			remote-endpoint = <&tfp410_in>;
+			data-lines = <24>;
+		};
+	};
+};
+
+&mmc1 {
+	pinctrl-0 = <&mmc1_pins &mmc1_wp_pins>;
+	wp-gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;	/* gpio_29 */
+};
diff --git a/arch/arm/dts/omap3-igep0020-u-boot.dtsi b/arch/arm/dts/omap3-igep0020-u-boot.dtsi
new file mode 100644
index 0000000..41beaf0
--- /dev/null
+++ b/arch/arm/dts/omap3-igep0020-u-boot.dtsi
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * U-Boot additions
+ *
+ * (C) Copyright 2017 Derald D. Woods <woods.technical@gmail.com>
+ */
+
+/ {
+	chosen {
+		stdout-path = &uart3;
+	};
+};
+
+&uart1 {
+	reg-shift = <2>;
+};
+
+&uart2 {
+	reg-shift = <2>;
+};
+
+&uart3 {
+	reg-shift = <2>;
+};
diff --git a/arch/arm/dts/omap3-igep0020.dts b/arch/arm/dts/omap3-igep0020.dts
new file mode 100644
index 0000000..33d6b4e
--- /dev/null
+++ b/arch/arm/dts/omap3-igep0020.dts
@@ -0,0 +1,50 @@
+/*
+ * Device Tree Source for IGEPv2 Rev. C (TI OMAP AM/DM37x)
+ *
+ * Copyright (C) 2012 Javier Martinez Canillas <javier@osg.samsung.com>
+ * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "omap3-igep0020-common.dtsi"
+
+/ {
+	model = "IGEPv2 Rev. C (TI OMAP AM/DM37x)";
+	compatible = "isee,omap3-igep0020", "ti,omap36xx", "ti,omap3";
+
+	vmmcsdio_fixed: fixedregulator-mmcsdio {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmcsdio_fixed";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	mmc2_pwrseq: mmc2_pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&gpio5 11 GPIO_ACTIVE_LOW>,	/* gpio_139 - RESET_N_W */
+			      <&gpio5 10 GPIO_ACTIVE_LOW>;	/* gpio_138 - WIFI_PDN */
+	};
+};
+
+&omap3_pmx_core {
+	lbee1usjyc_pins: pinmux_lbee1usjyc_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x2166, PIN_OUTPUT | MUX_MODE4)	/* sdmmc2_dat5.gpio_137 - RESET_N_W */
+			OMAP3_CORE1_IOPAD(0x2168, PIN_OUTPUT | MUX_MODE4)	/* sdmmc2_dat6.gpio_138 - WIFI_PDN */
+			OMAP3_CORE1_IOPAD(0x216a, PIN_OUTPUT | MUX_MODE4)	/* sdmmc2_dat7.gpio_139 - RST_N_B */
+		>;
+	};
+};
+
+/* On board Wifi module */
+&mmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins &lbee1usjyc_pins>;
+	vmmc-supply = <&vmmcsdio_fixed>;
+	mmc-pwrseq = <&mmc2_pwrseq>;
+	bus-width = <4>;
+	non-removable;
+};
diff --git a/arch/arm/include/asm/arch-hi3798cv200/hi3798cv200.h b/arch/arm/include/asm/arch-hi3798cv200/hi3798cv200.h
index f97b1eb..bb221e1 100644
--- a/arch/arm/include/asm/arch-hi3798cv200/hi3798cv200.h
+++ b/arch/arm/include/asm/arch-hi3798cv200/hi3798cv200.h
@@ -13,11 +13,16 @@
 /* DEVICES */
 #define REG_BASE_MCI			0xF9830000
 #define REG_BASE_UART0			0xF8B00000
+#define HIOTG_BASE_ADDR			0xF98C0000
 
 /* PERI control registers (4KB) */
 	/* USB2 PHY01 configuration register */
 #define PERI_CTRL_USB0			(REG_BASE_PERI_CTRL + 0x120)
 
+	/* USB2 controller configuration register */
+#define PERI_CTRL_USB3			(REG_BASE_PERI_CTRL + 0x12c)
+#define USB2_2P_CHIPID			(1 << 28)
+
 /* PERI CRG registers (4KB) */
 	/* USB2 CTRL0 clock and soft reset */
 #define PERI_CRG46			(REG_BASE_CRG + 0xb8)
diff --git a/arch/arm/include/asm/arch-mediatek/reset.h b/arch/arm/include/asm/arch-mediatek/reset.h
new file mode 100644
index 0000000..9704666
--- /dev/null
+++ b/arch/arm/include/asm/arch-mediatek/reset.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#ifndef __MEDIATEK_RESET_H
+#define __MEDIATEK_RESET_H
+
+#include <dm.h>
+
+int mediatek_reset_bind(struct udevice *pdev, u32 regofs, u32 num_regs);
+
+#endif	/* __MEDIATEK_RESET_H */
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index c3c1d2f..329f20c 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -64,13 +64,15 @@
 	/* adjust sp by 4K to be safe */
 	sp -= 4096;
 	for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
-		if (sp < gd->bd->bi_dram[bank].start)
+		if (!gd->bd->bi_dram[bank].size ||
+		    sp < gd->bd->bi_dram[bank].start)
 			continue;
+		/* Watch out for RAM at end of address space! */
 		bank_end = gd->bd->bi_dram[bank].start +
-			gd->bd->bi_dram[bank].size;
-		if (sp >= bank_end)
+			gd->bd->bi_dram[bank].size - 1;
+		if (sp > bank_end)
 			continue;
-		lmb_reserve(lmb, sp, bank_end - sp);
+		lmb_reserve(lmb, sp, bank_end - sp + 1);
 		break;
 	}
 }
diff --git a/arch/arm/mach-bcm283x/Kconfig b/arch/arm/mach-bcm283x/Kconfig
index 821caed..3eb5a9a 100644
--- a/arch/arm/mach-bcm283x/Kconfig
+++ b/arch/arm/mach-bcm283x/Kconfig
@@ -41,7 +41,7 @@
 	  support BCM2836/BCM2837-based Raspberry Pis such as the RPi 2 and
 	  RPi 3 due to different peripheral address maps.
 
-	  This option creates a build targetting the ARM1176 ISA.
+	  This option creates a build targeting the ARM1176 ISA.
 	select BCM2835
 
 config TARGET_RPI_0_W
@@ -57,7 +57,7 @@
 	  This is required for U-Boot to operate correctly, even if you only
 	  care about the HDMI/usbkbd console.
 
-	  This option creates a build targetting the ARMv7/AArch32 ISA.
+	  This option creates a build targeting the ARMv7/AArch32 ISA.
 	select BCM2835
 
 config TARGET_RPI_2
@@ -80,7 +80,7 @@
 	  arm_loader: emmc clock depends on core clock See:
 	  https://github.com/raspberrypi/firmware/issues/572".
 
-	  This option creates a build targetting the ARMv7/AArch32 ISA.
+	  This option creates a build targeting the ARMv7/AArch32 ISA.
 	select BCM2836
 
 config TARGET_RPI_3_32B
@@ -96,7 +96,7 @@
 	  required for U-Boot to operate correctly, even if you only care
 	  about the HDMI/usbkbd console.
 
-	  This option creates a build targetting the ARMv7/AArch32 ISA.
+	  This option creates a build targeting the ARMv7/AArch32 ISA.
 	select BCM2837_32B
 
 config TARGET_RPI_3
@@ -124,7 +124,7 @@
 	  duplicated here. The VC FW enhancement is tracked in
 	  https://github.com/raspberrypi/firmware/issues/579.
 
-	  This option creates a build targetting the ARMv8/AArch64 ISA.
+	  This option creates a build targeting the ARMv8/AArch64 ISA.
 	select BCM2837_64B
 
 endchoice
diff --git a/arch/arm/mach-snapdragon/pinctrl-apq8016.c b/arch/arm/mach-snapdragon/pinctrl-apq8016.c
index bdb755d..1042b56 100644
--- a/arch/arm/mach-snapdragon/pinctrl-apq8016.c
+++ b/arch/arm/mach-snapdragon/pinctrl-apq8016.c
@@ -39,11 +39,11 @@
 static const char *apq8016_get_pin_name(struct udevice *dev,
 					unsigned int selector)
 {
-	if (selector < 130) {
+	if (selector < 122) {
 		snprintf(pin_name, MAX_PIN_NAME_LEN, "GPIO_%u", selector);
 		return pin_name;
 	} else {
-		return msm_pinctrl_pins[selector - 130];
+		return msm_pinctrl_pins[selector - 122];
 	}
 }
 
@@ -53,7 +53,7 @@
 }
 
 struct msm_pinctrl_data apq8016_data = {
-	.pin_count = 140,
+	.pin_count = 133,
 	.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
 	.get_function_name = apq8016_get_function_name,
 	.get_function_mux = apq8016_get_function_mux,
diff --git a/arch/mips/cpu/u-boot-spl.lds b/arch/mips/cpu/u-boot-spl.lds
index 1273b74..be194d3 100644
--- a/arch/mips/cpu/u-boot-spl.lds
+++ b/arch/mips/cpu/u-boot-spl.lds
@@ -46,43 +46,75 @@
 		__bss_end = .;
 	} > .bss_mem
 
-	.rel.dyn (NOLOAD) : {
-		*(.rel.dyn)
+	/* These mark the ABI of U-Boot for debuggers. */
+	.mdebug.abi32 : {
+		KEEP(*(.mdebug.abi32))
 	}
-
-	.dynsym : {
-		*(.dynsym)
-	}
-
-	.dynbss : {
-		*(.dynbss)
+	.mdebug.abi64 : {
+		KEEP(*(.mdebug.abi64))
 	}
 
-	.dynstr : {
-		*(.dynstr)
-	}
-
-	.dynamic : {
-		*(.dynamic)
-	}
+	/* This is the MIPS specific mdebug section. */
+	.mdebug : { *(.mdebug) }
 
-	.plt : {
-		*(.plt)
-	}
-
-	.interp : {
-		*(.interp)
-	}
-
-	.gnu : {
-		*(.gnu*)
-	}
+	/* Stabs debugging sections.  */
+	.stab 0 : { *(.stab) }
+	.stabstr 0 : { *(.stabstr) }
+	.stab.excl 0 : { *(.stab.excl) }
+	.stab.exclstr 0 : { *(.stab.exclstr) }
+	.stab.index 0 : { *(.stab.index) }
+	.stab.indexstr 0 : { *(.stab.indexstr) }
+	.comment 0 : { *(.comment) }
 
-	.MIPS.stubs : {
-		*(.MIPS.stubs)
+	/*
+	 * DWARF debug sections.
+	 * Symbols in the DWARF debugging sections are relative to
+	 * the beginning of the section so we begin them at 0.
+	 */
+	/* DWARF 1 */
+	.debug 0 : { *(.debug) }
+	.line 0 : { *(.line) }
+	/* GNU DWARF 1 extensions */
+	.debug_srcinfo 0 : { *(.debug_srcinfo) }
+	.debug_sfnames 0 : { *(.debug_sfnames) }
+	/* DWARF 1.1 and DWARF 2 */
+	.debug_aranges 0 : { *(.debug_aranges) }
+	.debug_pubnames 0 : { *(.debug_pubnames) }
+	/* DWARF 2 */
+	.debug_info 0 : {
+		*(.debug_info
+		.gnu.linkonce.wi.*)
 	}
+	.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_pubtypes 0 : { *(.debug_pubtypes) }
+	/* DWARF 3 */
+	.debug_ranges 0 : { *(.debug_ranges) }
+	/* SGI/MIPS DWARF 2 extensions */
+	.debug_weaknames 0 : { *(.debug_weaknames) }
+	.debug_funcnames 0 : { *(.debug_funcnames) }
+	.debug_typenames 0 : { *(.debug_typenames) }
+	.debug_varnames 0 : { *(.debug_varnames) }
+	/* GNU DWARF 2 extensions */
+	.debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) }
+	.debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) }
+	/* DWARF 4 */
+	.debug_types 0 : { *(.debug_types) }
+	/* DWARF 5 */
+	.debug_macro 0 : { *(.debug_macro) }
+	.debug_addr 0 : { *(.debug_addr) }
 
-	.hash : {
-		*(.hash)
+	/DISCARD/ : {
+		/* ABI crap starts here */
+		*(.MIPS.abiflags)
+		*(.MIPS.options)
+		*(.options)
+		*(.pdr)
+		*(.reginfo)
+		*(.eh_frame)
 	}
 }
diff --git a/arch/mips/cpu/u-boot.lds b/arch/mips/cpu/u-boot.lds
index fd0f1b5..8649673 100644
--- a/arch/mips/cpu/u-boot.lds
+++ b/arch/mips/cpu/u-boot.lds
@@ -68,39 +68,75 @@
 		__bss_end = .;
 	}
 
-	.dynsym _end : {
-		*(.dynsym)
+	/* These mark the ABI of U-Boot for debuggers. */
+	.mdebug.abi32 : {
+		KEEP(*(.mdebug.abi32))
 	}
-
-	.dynbss : {
-		*(.dynbss)
+	.mdebug.abi64 : {
+		KEEP(*(.mdebug.abi64))
 	}
 
-	.dynstr : {
-		*(.dynstr)
-	}
+	/* This is the MIPS specific mdebug section. */
+	.mdebug : { *(.mdebug) }
 
-	.dynamic : {
-		*(.dynamic)
-	}
-
-	.plt : {
-		*(.plt)
-	}
+	/* Stabs debugging sections.  */
+	.stab 0 : { *(.stab) }
+	.stabstr 0 : { *(.stabstr) }
+	.stab.excl 0 : { *(.stab.excl) }
+	.stab.exclstr 0 : { *(.stab.exclstr) }
+	.stab.index 0 : { *(.stab.index) }
+	.stab.indexstr 0 : { *(.stab.indexstr) }
+	.comment 0 : { *(.comment) }
 
-	.interp : {
-		*(.interp)
+	/*
+	 * DWARF debug sections.
+	 * Symbols in the DWARF debugging sections are relative to
+	 * the beginning of the section so we begin them at 0.
+	 */
+	/* DWARF 1 */
+	.debug 0 : { *(.debug) }
+	.line 0 : { *(.line) }
+	/* GNU DWARF 1 extensions */
+	.debug_srcinfo 0 : { *(.debug_srcinfo) }
+	.debug_sfnames 0 : { *(.debug_sfnames) }
+	/* DWARF 1.1 and DWARF 2 */
+	.debug_aranges 0 : { *(.debug_aranges) }
+	.debug_pubnames 0 : { *(.debug_pubnames) }
+	/* DWARF 2 */
+	.debug_info 0 : {
+		*(.debug_info
+		.gnu.linkonce.wi.*)
 	}
-
-	.gnu : {
-		*(.gnu*)
-	}
-
-	.MIPS.stubs : {
-		*(.MIPS.stubs)
-	}
+	.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_pubtypes 0 : { *(.debug_pubtypes) }
+	/* DWARF 3 */
+	.debug_ranges 0 : { *(.debug_ranges) }
+	/* SGI/MIPS DWARF 2 extensions */
+	.debug_weaknames 0 : { *(.debug_weaknames) }
+	.debug_funcnames 0 : { *(.debug_funcnames) }
+	.debug_typenames 0 : { *(.debug_typenames) }
+	.debug_varnames 0 : { *(.debug_varnames) }
+	/* GNU DWARF 2 extensions */
+	.debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) }
+	.debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) }
+	/* DWARF 4 */
+	.debug_types 0 : { *(.debug_types) }
+	/* DWARF 5 */
+	.debug_macro 0 : { *(.debug_macro) }
+	.debug_addr 0 : { *(.debug_addr) }
 
-	.hash : {
-		*(.hash)
+	/DISCARD/ : {
+		/* ABI crap starts here */
+		*(.MIPS.abiflags)
+		*(.MIPS.options)
+		*(.options)
+		*(.pdr)
+		*(.reginfo)
+		*(.eh_frame)
 	}
 }
diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile
index 647d2bf..1484db9 100644
--- a/arch/mips/dts/Makefile
+++ b/arch/mips/dts/Makefile
@@ -17,6 +17,9 @@
 dtb-$(CONFIG_BOARD_SAGEM_FAST1704) += sagem,f@st1704.dtb
 dtb-$(CONFIG_BOARD_TPLINK_WDR4300) += tplink_wdr4300.dtb
 dtb-$(CONFIG_TARGET_JZ4780_CI20) += ci20.dtb
+dtb-$(CONFIG_SOC_LUTON) += luton_pcb090.dtb luton_pcb091.dtb
+dtb-$(CONFIG_SOC_OCELOT) += ocelot_pcb120.dtb ocelot_pcb123.dtb
+dtb-$(CONFIG_SOC_JR2) += jr2_pcb110.dtb jr2_pcb111.dtb serval2_pcb112.dtb
 
 targets += $(dtb-y)
 
diff --git a/arch/mips/dts/gardena-smart-gateway-mt7688.dts b/arch/mips/dts/gardena-smart-gateway-mt7688.dts
index d8d8868..75f6037 100644
--- a/arch/mips/dts/gardena-smart-gateway-mt7688.dts
+++ b/arch/mips/dts/gardena-smart-gateway-mt7688.dts
@@ -34,7 +34,7 @@
 		power_green {
 			label = "smartgw:power:green";
 			gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>;
-			default-state = "off";
+			default-state = "on";
 		};
 
 		power_red {
diff --git a/arch/mips/dts/jr2_pcb110.dts b/arch/mips/dts/jr2_pcb110.dts
new file mode 100644
index 0000000..ddc30ff
--- /dev/null
+++ b/arch/mips/dts/jr2_pcb110.dts
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+/dts-v1/;
+#include "mscc,jr2.dtsi"
+
+/ {
+	model = "Jaguar2 Cu8-Sfp16 PCB110 Reference Board";
+	compatible = "mscc,jr2-pcb110", "mscc,jr2";
+
+	aliases {
+		spi0 = &spi0;
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		status_green {
+			label = "pcb110:green:status";
+			gpios = <&gpio 12 0>;
+			default-state = "on";
+		};
+
+		status_red {
+			label = "pcb110:red:status";
+			gpios = <&gpio 13 0>;
+			default-state = "off";
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi0 {
+	status = "okay";
+	spi-flash@0 {
+		compatible = "spi-flash";
+		spi-max-frequency = <18000000>; /* input clock */
+		reg = <0>; /* CS0 */
+	};
+};
+
+&gpio {
+	/* SPIO only use DO, CLK, no inputs */
+	sgpio1_pins: sgpio1-pins {
+		pins = "GPIO_4", "GPIO_5";
+		function = "sg1";
+	};
+};
+
+&sgpio {
+	status = "okay";
+	sgpio-ports = <0x00ffffff>;
+};
+
+&sgpio1 {
+	status = "okay";
+	sgpio-ports = <0x00ff0000>;
+};
+
+&sgpio2 {
+	status = "okay";
+	sgpio-ports = <0x3f00ffff>;
+	gpio-ranges = <&sgpio2 0 0 96>;
+};
diff --git a/arch/mips/dts/jr2_pcb111.dts b/arch/mips/dts/jr2_pcb111.dts
new file mode 100644
index 0000000..4d411b6
--- /dev/null
+++ b/arch/mips/dts/jr2_pcb111.dts
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+/dts-v1/;
+#include "mscc,jr2.dtsi"
+
+/ {
+	model = "Jaguar2 Cu48 PCB111 Reference Board";
+	compatible = "mscc,jr2-pcb111", "mscc,jr2";
+
+	aliases {
+		spi0 = &spi0;
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		status_green {
+			label = "pcb111:green:status";
+			gpios = <&gpio 12 0>;
+			default-state = "on";
+		};
+
+		status_red {
+			label = "pcb111:red:status";
+			gpios = <&gpio 13 0>;
+			default-state = "off";
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi0 {
+	status = "okay";
+	spi-flash@0 {
+		compatible = "spi-flash";
+		spi-max-frequency = <18000000>; /* input clock */
+		reg = <0>; /* CS0 */
+	};
+};
+
+&gpio {
+	/* SPIO only use DO, CLK, no inputs */
+	sgpio1_pins: sgpio1-pins {
+		pins = "GPIO_4", "GPIO_5";
+		function = "sg1";
+	};
+};
+
+&sgpio {
+	status = "okay";
+	sgpio-ports = <0xffffffff>;
+};
+
+&sgpio1 {
+	status = "okay";
+	sgpio-ports = <0x001effff>;
+};
+
+&sgpio2 {
+	status = "okay";
+	sgpio-ports = <0xff000000>;
+	gpio-ranges = <&sgpio2 0 0 96>;
+};
diff --git a/arch/mips/dts/luton_pcb090.dts b/arch/mips/dts/luton_pcb090.dts
new file mode 100644
index 0000000..951d8da
--- /dev/null
+++ b/arch/mips/dts/luton_pcb090.dts
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+/dts-v1/;
+#include "mscc,luton.dtsi"
+
+/ {
+	model = "Luton26 PCB090 Reference Board";
+	compatible = "mscc,luton-pcb090", "mscc,luton";
+
+	aliases {
+		serial0 = &uart0;
+		spi0 = &spi0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		status_green {
+			label = "pcb090:green:status";
+			gpios = <&sgpio 64 GPIO_ACTIVE_HIGH>; /* p0.2 */
+			default-state = "on";
+		};
+
+		status_red {
+			label = "pcb090:red:status";
+			gpios = <&sgpio 65 GPIO_ACTIVE_HIGH>; /* p1.2 */
+			default-state = "off";
+		};
+	};
+};
+
+&sgpio {
+	status = "okay";
+	gpio-ranges = <&sgpio 0 0 96>;
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi0 {
+	status = "okay";
+	spi-flash@0 {
+		compatible = "spi-flash";
+		spi-max-frequency = <18000000>; /* input clock */
+		reg = <0>; /* CS0 */
+		spi-cs-high;
+	};
+};
+
diff --git a/arch/mips/dts/luton_pcb091.dts b/arch/mips/dts/luton_pcb091.dts
index 74f9274..bf638b2 100644
--- a/arch/mips/dts/luton_pcb091.dts
+++ b/arch/mips/dts/luton_pcb091.dts
@@ -18,6 +18,33 @@
 	chosen {
 		stdout-path = "serial0:115200n8";
 	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		top_dimmer {
+			label = "pcb091:top:dimmer";
+			gpios = <&gpio 29 GPIO_ACTIVE_LOW>;
+			default-state = "on";
+		};
+
+		status_green {
+			label = "pcb091:green:status";
+			gpios = <&sgpio 26 GPIO_ACTIVE_HIGH>; /* p26.0 */
+			default-state = "on";
+		};
+
+		status_red {
+			label = "pcb091:red:status";
+			gpios = <&sgpio 58 GPIO_ACTIVE_HIGH>; /* p26.1 */
+			default-state = "off";
+		};
+	};
+};
+
+&sgpio {
+	status = "okay";
+	mscc,sgpio-ports = <0xFFF000FF>;
 };
 
 &uart0 {
diff --git a/arch/mips/dts/mscc,jr2.dtsi b/arch/mips/dts/mscc,jr2.dtsi
new file mode 100644
index 0000000..0900926
--- /dev/null
+++ b/arch/mips/dts/mscc,jr2.dtsi
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "mscc,jr2";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "mips,mips24KEc";
+			device_type = "cpu";
+			clocks = <&cpu_clk>;
+			reg = <0>;
+		};
+	};
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	cpuintc: interrupt-controller@0 {
+		#address-cells = <0>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		compatible = "mti,cpu-interrupt-controller";
+	};
+
+	cpu_clk: cpu-clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <500000000>;
+	};
+
+	ahb_clk: ahb-clk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <250000000>;
+	};
+
+	ahb {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x70000000 0x2000000>;
+
+		interrupt-parent = <&intc>;
+
+		cpu_ctrl: syscon@0 {
+			compatible = "mscc,jr2-cpu-syscon", "syscon";
+			reg = <0x0 0x2c>;
+		};
+
+		intc: interrupt-controller@70 {
+			compatible = "mscc,jr2-icpu-intr";
+			reg = <0x70 0x94>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			interrupt-parent = <&cpuintc>;
+			interrupts = <2>;
+		};
+
+		uart0: serial@100000 {
+			pinctrl-0 = <&uart_pins>;
+			pinctrl-names = "default";
+			compatible = "ns16550a";
+			reg = <0x100000 0x20>;
+			interrupts = <6>;
+			clocks = <&ahb_clk>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+
+			status = "disabled";
+		};
+
+		uart2: serial@100800 {
+			pinctrl-0 = <&uart2_pins>;
+			pinctrl-names = "default";
+			compatible = "ns16550a";
+			reg = <0x100800 0x20>;
+			interrupts = <7>;
+			clocks = <&ahb_clk>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+
+			status = "disabled";
+		};
+
+		spi0: spi-master@101000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "snps,dw-apb-ssi";
+			reg = <0x101000 0x40>;
+			num-chipselect = <4>;
+			bus-num = <0>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			spi-max-frequency = <18000000>; /* input clock */
+			clocks = <&ahb_clk>;
+
+			status = "disabled";
+		};
+
+		reset@1010008 {
+			compatible = "mscc,jr2-chip-reset";
+			reg = <0x1010008 0x4>;
+		};
+
+		gpio: pinctrl@1070034 {
+			compatible = "mscc,jaguar2-pinctrl";
+			reg = <0x1010038 0x90>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&gpio 0 0 64>;
+
+			sgpio_pins: sgpio-pins {
+				pins = "GPIO_0", "GPIO_1", "GPIO_2", "GPIO_3";
+				function = "sg0";
+			};
+
+			sgpio1_pins: sgpio1-pins {
+				pins = "GPIO_4", "GPIO_5", "GPIO_12", "GPIO_13";
+				function = "sg1";
+			};
+
+			sgpio2_pins: sgpio2-pins {
+				pins = "GPIO_30", "GPIO_31",
+				       "GPIO_32", "GPIO_33";
+				function = "sg2";
+			};
+
+			uart_pins: uart-pins {
+				pins = "GPIO_10", "GPIO_11";
+				function = "uart";
+			};
+
+			uart2_pins: uart2-pins {
+				pins = "GPIO_24", "GPIO_25";
+				function = "uart2";
+			};
+		};
+
+		sgpio: gpio@1010150 {
+			compatible = "mscc,ocelot-sgpio";
+			status = "disabled";
+			pinctrl-0 = <&sgpio_pins>;
+			pinctrl-names = "default";
+			reg = <0x1010150 0x100>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&sgpio 0 0 64>;
+			gpio-bank-name = "sgpio0_";
+			sgpio-clock = <0x14>;
+		};
+
+		sgpio1: gpio@101025c {
+			compatible = "mscc,ocelot-sgpio";
+			status = "disabled";
+			pinctrl-0 = <&sgpio1_pins>;
+			pinctrl-names = "default";
+			reg = <0x101025c 0x100>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&sgpio1 0 0 64>;
+			gpio-bank-name = "sgpio1_";
+			sgpio-clock = <0x14>;
+		};
+
+		sgpio2: gpio@1010368 {
+			compatible = "mscc,ocelot-sgpio";
+			status = "disabled";
+			pinctrl-0 = <&sgpio2_pins>;
+			pinctrl-names = "default";
+			reg = <0x1010368 0x100>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&sgpio2 0 0 64>;
+			gpio-bank-name = "sgpio2_";
+			sgpio-clock = <0x14>;
+		};
+	};
+};
diff --git a/arch/mips/dts/mscc,luton.dtsi b/arch/mips/dts/mscc,luton.dtsi
index 6a4ad2a..d11ec48 100644
--- a/arch/mips/dts/mscc,luton.dtsi
+++ b/arch/mips/dts/mscc,luton.dtsi
@@ -25,6 +25,11 @@
 		serial0 = &uart0;
 	};
 
+	sys_clk: sys-clk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <250000000>;
+	};
 	ahb_clk: ahb-clk {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
@@ -57,28 +62,32 @@
 			#gpio-cells = <2>;
 			gpio-ranges = <&gpio 0 0 32>;
 
+			sgpio_pins: sgpio-pins {
+				pins = "GPIO_0", "GPIO_1", "GPIO_2", "GPIO_3";
+				function = "sio";
+			};
 			uart_pins: uart-pins {
 				pins = "GPIO_30", "GPIO_31";
 				function = "uart";
 			};
-
 		};
 
-		gpio_spi_bitbang: gpio@10000064 {
-			compatible = "mscc,spi-bitbang-gpio";
-			reg = <0x10000064 0x4>;
+		sgpio: gpio@70130 {
+			compatible = "mscc,luton-sgpio";
+			status = "disabled";
+			clocks = <&sys_clk>;
+			pinctrl-0 = <&sgpio_pins>;
+			pinctrl-names = "default";
+			reg = <0x0070130 0x100>;
 			gpio-controller;
 			#gpio-cells = <2>;
-
+			gpio-ranges = <&sgpio 0 0 64>;
 		};
 
 		spi0: spi-bitbang {
-			compatible = "spi-gpio";
+			compatible = "mscc,luton-bb-spi";
 			status = "okay";
-			gpio-sck = <&gpio_spi_bitbang 6 0>;
-			gpio-miso = <&gpio_spi_bitbang 0 0>;
-			gpio-mosi = <&gpio_spi_bitbang 5 0>;
-			cs-gpios = <&gpio_spi_bitbang 1 0>;
+			reg = <0x10000064 0x4>;
 			num-chipselects = <1>;
 			#address-cells = <1>;
 			#size-cells = <0>;
diff --git a/arch/mips/dts/mscc,ocelot.dtsi b/arch/mips/dts/mscc,ocelot.dtsi
index 87b4736..2592003 100644
--- a/arch/mips/dts/mscc,ocelot.dtsi
+++ b/arch/mips/dts/mscc,ocelot.dtsi
@@ -37,6 +37,12 @@
 		clock-frequency = <500000000>;
 	};
 
+	sys_clk: sys-clk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <250000000>;
+	};
+
 	ahb_clk: ahb-clk {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
@@ -118,6 +124,11 @@
 			#gpio-cells = <2>;
 			gpio-ranges = <&gpio 0 0 22>;
 
+			sgpio_pins: sgpio-pins {
+				pins = "GPIO_0", "GPIO_1", "GPIO_2", "GPIO_3";
+				function = "sg0";
+			};
+
 			uart_pins: uart-pins {
 				pins = "GPIO_6", "GPIO_7";
 				function = "uart";
@@ -148,5 +159,17 @@
 				function = "si";
 			};
 		};
+
+		sgpio: gpio@10700f8 {
+			compatible = "mscc,ocelot-sgpio";
+			status = "disabled";
+			clocks = <&sys_clk>;
+			pinctrl-0 = <&sgpio_pins>;
+			pinctrl-names = "default";
+			reg = <0x10700f8 0x100>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&sgpio 0 0 64>;
+		};
 	};
 };
diff --git a/arch/mips/dts/ocelot_pcb120.dts b/arch/mips/dts/ocelot_pcb120.dts
index 47d305a..658719e 100644
--- a/arch/mips/dts/ocelot_pcb120.dts
+++ b/arch/mips/dts/ocelot_pcb120.dts
@@ -9,4 +9,80 @@
 / {
 	model = "Ocelot PCB120 Reference Board";
 	compatible = "mscc,ocelot-pcb120", "mscc,ocelot";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		poe_green {
+			label = "pcb120:green:poe";
+			gpios = <&sgpio 44 1>; /* p12.1 */
+			default-state = "off";
+		};
+
+		poe_red {
+			label = "pcb120:red:poe";
+			gpios = <&sgpio 12 1>; /* p12.0 */
+			default-state = "off";
+		};
+
+		alarm_green {
+			label = "pcb120:green:alarm";
+			gpios = <&sgpio 45 1>; /* p13.1 */
+			default-state = "off";
+		};
+
+		alarm_red {
+			label = "pcb120:red:alarm";
+			gpios = <&sgpio 13 1>; /* p13.0 */
+			default-state = "off";
+		};
+
+		dc_a_green {
+			label = "pcb120:green:dc_a";
+			gpios = <&sgpio 46 1>; /* p14.1 */
+			default-state = "off";
+		};
+
+		dc_a_red {
+			label = "pcb120:red:dc_a";
+			gpios = <&sgpio 14 1>; /* p14.0 */
+			default-state = "off";
+		};
+
+		dc_b_green {
+			label = "pcb120:green:dc_b";
+			gpios = <&sgpio 47 1>; /* p15.1 */
+			default-state = "off";
+		};
+
+		dc_b_red {
+			label = "pcb120:red:dc_b";
+			gpios = <&sgpio 15 1>; /* p15.0 */
+			default-state = "off";
+		};
+
+		status_green {
+			label = "pcb120:green:status";
+			gpios = <&sgpio 48 1>; /* p16.1 */
+			default-state = "on";
+		};
+
+		status_red {
+			label = "pcb120:red:alarm";
+			gpios = <&sgpio 16 1>; /* p16.0 */
+			default-state = "off";
+		};
+
+	};
+
+};
+
+&sgpio {
+	status = "okay";
+	mscc,sgpio-ports = <0x000FFFFF>;
 };
+
diff --git a/arch/mips/dts/ocelot_pcb123.dts b/arch/mips/dts/ocelot_pcb123.dts
index 17d8d32..c4cb7a1 100644
--- a/arch/mips/dts/ocelot_pcb123.dts
+++ b/arch/mips/dts/ocelot_pcb123.dts
@@ -9,4 +9,29 @@
 / {
 	model = "Ocelot PCB123 Reference Board";
 	compatible = "mscc,ocelot-pcb123", "mscc,ocelot";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		status_green {
+			label = "pcb123:green:status";
+			gpios = <&sgpio 43 1>; /* p11.1 */
+			default-state = "on";
+		};
+
+		status_red {
+			label = "pcb123:red:status";
+			gpios = <&sgpio 11 1>; /* p11.0 */
+			default-state = "off";
+		};
+	};
+};
+
+&sgpio {
+	status = "okay";
+	mscc,sgpio-ports = <0x00FFFFFF>;
 };
diff --git a/arch/mips/dts/serval2_pcb112.dts b/arch/mips/dts/serval2_pcb112.dts
new file mode 100644
index 0000000..fe025f4
--- /dev/null
+++ b/arch/mips/dts/serval2_pcb112.dts
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+/dts-v1/;
+#include "mscc,jr2.dtsi"
+
+/ {
+	model = "Serval2 NID PCB112 Reference Board";
+	compatible = "mscc,serval2-pcb110", "mscc,jr2";
+
+	aliases {
+		spi0 = &spi0;
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		status_green {
+			label = "pcb110:green:status";
+			gpios = <&gpio 12 0>;
+			default-state = "on";
+		};
+
+		status_red {
+			label = "pcb110:red:status";
+			gpios = <&gpio 13 0>;
+			default-state = "off";
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi0 {
+	status = "okay";
+	spi-flash@0 {
+		compatible = "spi-flash";
+		spi-max-frequency = <18000000>; /* input clock */
+		reg = <0>; /* CS0 */
+	};
+};
+
+&sgpio {
+	status = "okay";
+	sgpio-ports = <0x0000ffff>;
+};
+
+&sgpio2 {
+	status = "okay";
+	sgpio-ports = <0x3fe0ffff>;
+};
diff --git a/arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds b/arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds
deleted file mode 100644
index 347cabc..0000000
--- a/arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds
+++ /dev/null
@@ -1,50 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-
-MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\
-		LENGTH = CONFIG_SPL_MAX_SIZE }
-MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
-		LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
-
-OUTPUT_ARCH(mips)
-ENTRY(_start)
-SECTIONS
-{
-	.text :
-	{
-		__image_copy_start = .;
-		arch/mips/mach-jz47xx/start.o	(.text*)
-		*(.text*)
-	} >.sram
-
-	. = ALIGN(4);
-	.rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
-
-	. = ALIGN(4);
-	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
-
-	. = ALIGN(4);
-	__image_copy_end = .;
-
-	.bss : {
-		. = ALIGN(4);
-		__bss_start = .;
-		*(.sbss.*)
-		*(.bss.*)
-		*(COMMON)
-		. = ALIGN(4);
-		__bss_end = .;
-	} >.sdram
-
-	/DISCARD/ : {
-		*(.dynbss)
-		*(.dynstr)
-		*(.dynamic)
-		*(.interp)
-		*(.hash)
-		*(.gnu.*)
-		*(.plt)
-		*(.got.plt)
-		*(.rel.plt)
-		*(.rel.dyn)
-	}
-}
diff --git a/arch/mips/mach-mscc/Kconfig b/arch/mips/mach-mscc/Kconfig
index 0e35b77..fc6aa03 100644
--- a/arch/mips/mach-mscc/Kconfig
+++ b/arch/mips/mach-mscc/Kconfig
@@ -15,47 +15,36 @@
 config SYS_SOC
 	default "mscc"
 
+choice
+
+	prompt "SOC Family Variant"
+
 config SOC_OCELOT
-	bool
+	bool "Ocelot SOC Family"
 	select SOC_VCOREIII
+	select DESIGNWARE_SPI
 	help
 	  This supports MSCC Ocelot family of SOCs.
 
 config SOC_LUTON
-	bool
+	bool "Luton SOC Family"
 	select SOC_VCOREIII
+	select MSCC_BITBANG_SPI_GPIO
 	help
 	  This supports MSCC Luton family of SOCs.
 
-config SYS_CONFIG_NAME
-	default "vcoreiii"
-
-choice
-	prompt "Board select"
-
-config TARGET_OCELOT_PCB120
-	bool "MSCC PCB120 Reference Board (aka VSC5635EV)"
-	select SOC_OCELOT
-	help
-	  When selected, CONFIG_DEFAULT_DEVICE_TREE should be set to
-	  ocelot_pcb120
-
-config TARGET_OCELOT_PCB123
-	bool "MSCC PCB123 Reference Board (aka VSC7514EV))"
-	select SOC_OCELOT
+config SOC_JR2
+	bool "Jaguar2 SOC Family"
+	select SOC_VCOREIII
+	select DESIGNWARE_SPI
 	help
-	  When selected, CONFIG_DEFAULT_DEVICE_TREE should be set to
-	  ocelot_pcb123
+	  This supports MSCC Jaguar2 family of SOCs.
 
-config TARGET_LUTON_PCB091
-	bool "MSCC PCB091 Reference Board"
-	select SOC_LUTON
-	select MSCC_BITBANG_SPI_GPIO
-	help
-	  When selected, CONFIG_DEFAULT_DEVICE_TREE should be set to
-	  luton_pcb091
 endchoice
 
+config SYS_CONFIG_NAME
+	default "vcoreiii"
+
 choice
 	prompt "DDR type"
 
@@ -83,4 +72,6 @@
 
 source "board/mscc/luton/Kconfig"
 
+source "board/mscc/jr2/Kconfig"
+
 endmenu
diff --git a/arch/mips/mach-mscc/Makefile b/arch/mips/mach-mscc/Makefile
index 6c60f26..f5b6968 100644
--- a/arch/mips/mach-mscc/Makefile
+++ b/arch/mips/mach-mscc/Makefile
@@ -2,5 +2,6 @@
 
 CFLAGS_cpu.o += -finline-limit=64000
 
-obj-y += cpu.o dram.o reset.o lowlevel_init.o
-obj-$(CONFIG_SOC_LUTON) += lowlevel_init_luton.o
+obj-y += cpu.o dram.o reset.o phy.o lowlevel_init.o
+obj-$(CONFIG_SOC_LUTON) += lowlevel_init_luton.o gpio.o
+obj-$(CONFIG_SOC_OCELOT) += gpio.o
diff --git a/arch/mips/mach-mscc/cpu.c b/arch/mips/mach-mscc/cpu.c
index 5be8ff6..4729b7a 100644
--- a/arch/mips/mach-mscc/cpu.c
+++ b/arch/mips/mach-mscc/cpu.c
@@ -87,8 +87,15 @@
 	       ICPU_SPI_MST_CFG_CS_DESELECT_TIME(0x19) +
 	       ICPU_SPI_MST_CFG_CLK_DIV(9), BASE_CFG + ICPU_SPI_MST_CFG);
 #else
+#ifdef CONFIG_SOC_OCELOT
 	writel(ICPU_SPI_MST_CFG_CS_DESELECT_TIME(0x19) +
 	       ICPU_SPI_MST_CFG_CLK_DIV(9), BASE_CFG + ICPU_SPI_MST_CFG);
+#endif
+#ifdef CONFIG_SOC_JR2
+	writel(ICPU_SPI_MST_CFG_FAST_READ_ENA +
+	       ICPU_SPI_MST_CFG_CS_DESELECT_TIME(0x19) +
+	       ICPU_SPI_MST_CFG_CLK_DIV(14), BASE_CFG + ICPU_SPI_MST_CFG);
+#endif
 	/*
 	 * Legacy and mainline linux kernel expect that the
 	 * interruption map was set as it was done by redboot.
diff --git a/arch/mips/mach-mscc/dram.c b/arch/mips/mach-mscc/dram.c
index 309007c..8002e07 100644
--- a/arch/mips/mach-mscc/dram.c
+++ b/arch/mips/mach-mscc/dram.c
@@ -19,7 +19,7 @@
 
 	ret = hal_vcoreiii_train_bytelane(0);
 
-#ifdef CONFIG_SOC_OCELOT
+#if defined(CONFIG_SOC_OCELOT) || defined(CONFIG_SOC_JR2)
 	if (ret)
 		return ret;
 	ret = hal_vcoreiii_train_bytelane(1);
diff --git a/arch/mips/mach-mscc/gpio.c b/arch/mips/mach-mscc/gpio.c
new file mode 100644
index 0000000..5e3a533
--- /dev/null
+++ b/arch/mips/mach-mscc/gpio.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+void mscc_gpio_set_alternate(int gpio, int mode)
+{
+	u32 mask = BIT(gpio);
+	u32 val0, val1;
+
+	val0 = readl(BASE_DEVCPU_GCB + GPIO_ALT(0));
+	val1 = readl(BASE_DEVCPU_GCB + GPIO_ALT(1));
+
+	if (mode == 1) {
+		val0 |= mask;
+		val1 &= ~mask;
+	} else if (mode == 2) {
+		val0 &= ~mask;
+		val1 |= mask;
+	} else if (mode == 3) {
+		val0 |= mask;
+		val1 |= mask;
+	} else {
+		val0 &= ~mask;
+		val1 &= ~mask;
+	}
+
+	writel(val0, BASE_DEVCPU_GCB + GPIO_ALT(0));
+	writel(val1, BASE_DEVCPU_GCB + GPIO_ALT(1));
+}
diff --git a/arch/mips/mach-mscc/include/mach/common.h b/arch/mips/mach-mscc/include/mach/common.h
index 931ecd7..b9e0939 100644
--- a/arch/mips/mach-mscc/include/mach/common.h
+++ b/arch/mips/mach-mscc/include/mach/common.h
@@ -9,11 +9,18 @@
 #if defined(CONFIG_SOC_OCELOT)
 #include <mach/ocelot/ocelot.h>
 #include <mach/ocelot/ocelot_devcpu_gcb.h>
+#include <mach/ocelot/ocelot_devcpu_gcb_miim_regs.h>
 #include <mach/ocelot/ocelot_icpu_cfg.h>
 #elif defined(CONFIG_SOC_LUTON)
 #include <mach/luton/luton.h>
 #include <mach/luton/luton_devcpu_gcb.h>
+#include <mach/luton/luton_devcpu_gcb_miim_regs.h>
 #include <mach/luton/luton_icpu_cfg.h>
+#elif defined(CONFIG_SOC_JR2)
+#include <mach/jr2/jr2.h>
+#include <mach/jr2/jr2_devcpu_gcb.h>
+#include <mach/jr2/jr2_devcpu_gcb_miim_regs.h>
+#include <mach/jr2/jr2_icpu_cfg.h>
 #else
 #error Unsupported platform
 #endif
@@ -25,4 +32,62 @@
 
 #define VCOREIII_TIMER_DIVIDER 25	/* Clock tick ~ 0.1 us */
 
+/* Common utility functions */
+
+/*
+ * Perform a number of NOP instructions, blocks of 8 instructions.
+ * The (inlined) function will not affect cache or processor state.
+ */
+static inline void mscc_vcoreiii_nop_delay(int delay)
+{
+	while (delay > 0) {
+#define DELAY_8_NOPS() asm volatile("nop; nop; nop; nop; nop; nop; nop; nop;")
+		switch (delay) {
+		case 8:
+			DELAY_8_NOPS();
+			/* fallthrough */
+		case 7:
+			DELAY_8_NOPS();
+			/* fallthrough */
+		case 6:
+			DELAY_8_NOPS();
+			/* fallthrough */
+		case 5:
+			DELAY_8_NOPS();
+			/* fallthrough */
+		case 4:
+			DELAY_8_NOPS();
+			/* fallthrough */
+		case 3:
+			DELAY_8_NOPS();
+			/* fallthrough */
+		case 2:
+			DELAY_8_NOPS();
+			/* fallthrough */
+		case 1:
+			DELAY_8_NOPS();
+		}
+		delay -= 8;
+#undef DELAY_8_NOPS
+	}
+}
+
+int mscc_phy_rd_wr(u8 read,
+		   u32 miim_controller,
+		   u8 miim_addr,
+		   u8 addr,
+		   u16 *value);
+
+int mscc_phy_rd(u32 miim_controller,
+		u8 miim_addr,
+		u8 addr,
+		u16 *value);
+
+int mscc_phy_wr(u32 miim_controller,
+		u8 miim_addr,
+		u8 addr,
+		u16 value);
+
+void mscc_gpio_set_alternate(int gpio, int mode);
+
 #endif				/* __ASM_MACH_COMMON_H */
diff --git a/arch/mips/mach-mscc/include/mach/ddr.h b/arch/mips/mach-mscc/include/mach/ddr.h
index f445e63..7552acb 100644
--- a/arch/mips/mach-mscc/include/mach/ddr.h
+++ b/arch/mips/mach-mscc/include/mach/ddr.h
@@ -161,7 +161,7 @@
 
 #endif
 
-#ifdef CONFIG_SOC_OCELOT
+#if defined(CONFIG_SOC_OCELOT) || defined(CONFIG_SOC_JR2)
 #define MIPS_VCOREIII_MEMORY_16BIT 1
 #endif
 
@@ -239,7 +239,7 @@
 	ICPU_MEMCTRL_CFG_MSB_ROW_ADDR(VC3_MPAR_row_addr_cnt - 1) |	\
 	ICPU_MEMCTRL_CFG_MSB_COL_ADDR(VC3_MPAR_col_addr_cnt - 1)
 
-#ifdef CONFIG_SOC_OCELOT
+#if defined(CONFIG_SOC_OCELOT) || defined(CONFIG_SOC_JR2)
 #define MSCC_MEMPARM_PERIOD					\
 	ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF(8) |		\
 	ICPU_MEMCTRL_REF_PERIOD_REF_PERIOD(VC3_MPAR_tREFI)
@@ -378,7 +378,7 @@
 	PAUSE();
 }
 
-#ifdef CONFIG_SOC_OCELOT
+#if defined(CONFIG_SOC_OCELOT) || defined(CONFIG_SOC_JR2)
 static u8 training_data[] = { 0xfe, 0x11, 0x33, 0x55, 0x77, 0x99, 0xbb, 0xdd };
 
 static inline void sleep_100ns(u32 val)
@@ -398,6 +398,7 @@
 		;
 }
 
+#if defined(CONFIG_SOC_OCELOT)
 static inline void hal_vcoreiii_ddr_reset_assert(void)
 {
 	/* DDR has reset pin on GPIO 19 toggle Low-High to release */
@@ -448,6 +449,26 @@
 
 	panic("DDR init failed\n");
 }
+#else				/* JR2 */
+static inline void hal_vcoreiii_ddr_reset_assert(void)
+{
+	/* Ensure the memory controller physical iface is forced reset */
+	writel(readl(BASE_CFG + ICPU_MEMPHY_CFG) |
+	       ICPU_MEMPHY_CFG_PHY_RST, BASE_CFG + ICPU_MEMPHY_CFG);
+
+	/* Ensure the memory controller is forced reset */
+	writel(readl(BASE_CFG + ICPU_RESET) |
+	       ICPU_RESET_MEM_RST_FORCE, BASE_CFG + ICPU_RESET);
+}
+
+static inline void hal_vcoreiii_ddr_failed(void)
+{
+	writel(0, BASE_CFG + ICPU_RESET);
+	writel(PERF_SOFT_RST_SOFT_CHIP_RST, BASE_CFG + PERF_SOFT_RST);
+
+	panic("DDR init failed\n");
+}
+#endif
 
 /*
  * DDR memory sanity checking done, possibly enable ECC.
@@ -738,7 +759,7 @@
 	/* Wait for ZCAL to clear */
 	while (readl(BASE_CFG + ICPU_MEMPHY_ZCAL) & ICPU_MEMPHY_ZCAL_ZCAL_ENA)
 		;
-#ifdef CONFIG_SOC_OCELOT
+#if defined(CONFIG_SOC_OCELOT) || defined(CONFIG_SOC_JR2)
 	/* Check no ZCAL_ERR */
 	if (readl(BASE_CFG + ICPU_MEMPHY_ZCAL_STAT)
 	    & ICPU_MEMPHY_ZCAL_STAT_ZCAL_ERR)
@@ -752,7 +773,7 @@
 	writel(MSCC_MEMPARM_MEMCFG, BASE_CFG + ICPU_MEMCTRL_CFG);
 	writel(MSCC_MEMPARM_PERIOD, BASE_CFG + ICPU_MEMCTRL_REF_PERIOD);
 
-#ifdef CONFIG_SOC_OCELOT
+#if defined(CONFIG_SOC_OCELOT) || defined(CONFIG_SOC_JR2)
 	writel(MSCC_MEMPARM_TIMING0, BASE_CFG + ICPU_MEMCTRL_TIMING0);
 #else /* Luton */
 	clrbits_le32(BASE_CFG + ICPU_MEMCTRL_TIMING0, ((1 << 20) - 1));
@@ -767,7 +788,7 @@
 	writel(MSCC_MEMPARM_MR2, BASE_CFG + ICPU_MEMCTRL_MR2_VAL);
 	writel(MSCC_MEMPARM_MR3, BASE_CFG + ICPU_MEMCTRL_MR3_VAL);
 
-#ifdef CONFIG_SOC_OCELOT
+#if defined(CONFIG_SOC_OCELOT)
 	/* Termination setup - enable ODT */
 	writel(ICPU_MEMCTRL_TERMRES_CTRL_LOCAL_ODT_RD_ENA |
 	       /* Assert ODT0 for any write */
@@ -778,6 +799,9 @@
 	hal_vcoreiii_ddr_reset_release();
 
 	writel(readl(BASE_CFG + ICPU_GPR(7)) + 1, BASE_CFG + ICPU_GPR(7));
+#elif defined(CONFIG_SOC_JR2)
+	writel(ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_ENA(3),
+	       BASE_CFG + ICPU_MEMCTRL_TERMRES_CTRL);
 #else				/* Luton */
 	/* Termination setup - disable ODT */
 	writel(0, BASE_CFG + ICPU_MEMCTRL_TERMRES_CTRL);
@@ -796,7 +820,7 @@
 
 	/* Settle...? */
 	sleep_100ns(10000);
-#ifdef CONFIG_SOC_OCELOT
+#if defined(CONFIG_SOC_OCELOT) || defined(CONFIG_SOC_JR2)
 	/* Establish data contents in DDR RAM for training */
 
 	__raw_writel(0xcacafefe, ((void __iomem *)MSCC_DDR_TO));
diff --git a/arch/mips/mach-mscc/include/mach/jr2/jr2.h b/arch/mips/mach-mscc/include/mach/jr2/jr2.h
new file mode 100644
index 0000000..67244f6
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/jr2/jr2.h
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Microsemi Jaguar2 Switch driver
+ *
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _MSCC_JR2_H_
+#define _MSCC_JR2_H_
+
+#include <linux/bitops.h>
+#include <dm.h>
+
+/*
+ * Target offset base(s)
+ */
+#define MSCC_IO_ORIGIN1_OFFSET 0x70000000
+#define MSCC_IO_ORIGIN1_SIZE   0x00200000
+#define MSCC_IO_ORIGIN2_OFFSET 0x71000000
+#define MSCC_IO_ORIGIN2_SIZE   0x01000000
+#define BASE_CFG        ((void __iomem *)0x70000000)
+#define BASE_DEVCPU_GCB ((void __iomem *)0x71010000)
+
+#endif
diff --git a/arch/mips/mach-mscc/include/mach/jr2/jr2_devcpu_gcb.h b/arch/mips/mach-mscc/include/mach/jr2/jr2_devcpu_gcb.h
new file mode 100644
index 0000000..4a1228d
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/jr2/jr2_devcpu_gcb.h
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _MSCC_JR2_DEVCPU_GCB_H_
+#define _MSCC_JR2_DEVCPU_GCB_H_
+
+#define PERF_GPR                                          0x4
+
+#define PERF_SOFT_RST                                     0x8
+
+#define PERF_SOFT_RST_SOFT_NON_CFG_RST                    BIT(2)
+#define PERF_SOFT_RST_SOFT_SWC_RST                        BIT(1)
+#define PERF_SOFT_RST_SOFT_CHIP_RST                       BIT(0)
+
+#define GPIO_GPIO_ALT(x)                                  (0x78 + 4 * (x))
+#define GPIO_GPIO_ALT1(x)                                 (0x80 + 4 * (x))
+
+#endif
diff --git a/arch/mips/mach-mscc/include/mach/jr2/jr2_devcpu_gcb_miim_regs.h b/arch/mips/mach-mscc/include/mach/jr2/jr2_devcpu_gcb_miim_regs.h
new file mode 100644
index 0000000..3c84edc
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/jr2/jr2_devcpu_gcb_miim_regs.h
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _MSCC_JR2_DEVCPU_GCB_MIIM_REGS_H_
+#define _MSCC_JR2_DEVCPU_GCB_MIIM_REGS_H_
+
+#define MIIM_MII_STATUS(gi)  (0xc8 + (gi * 36))
+#define MIIM_MII_CMD(gi)     (0xd0 + (gi * 36))
+#define MIIM_MII_DATA(gi)    (0xd4 + (gi * 36))
+
+#define  MSCC_F_MII_STATUS_MIIM_STAT_BUSY(x)  ((x) ? BIT(3) : 0)
+
+#define MSCC_F_MII_CMD_MIIM_CMD_VLD(x)        ((x) ? BIT(31) : 0)
+#define MSCC_F_MII_CMD_MIIM_CMD_PHYAD(x)      (GENMASK(29, 25) & ((x) << 25))
+#define MSCC_F_MII_CMD_MIIM_CMD_REGAD(x)      (GENMASK(24, 20) & ((x) << 20))
+#define MSCC_F_MII_CMD_MIIM_CMD_WRDATA(x)     (GENMASK(19, 4) & ((x) << 4))
+#define MSCC_F_MII_CMD_MIIM_CMD_OPR_FIELD(x)  (GENMASK(2, 1) & ((x) << 1))
+#define MSCC_F_MII_CMD_MIIM_CMD_SCAN(x)       ((x) ? BIT(0) : 0)
+
+#define MSCC_M_MII_DATA_MIIM_DATA_SUCCESS     GENMASK(17, 16)
+#define MSCC_X_MII_DATA_MIIM_DATA_RDDATA(x)   (((x) >> 0) & GENMASK(15, 0))
+
+#endif
diff --git a/arch/mips/mach-mscc/include/mach/jr2/jr2_icpu_cfg.h b/arch/mips/mach-mscc/include/mach/jr2/jr2_icpu_cfg.h
new file mode 100644
index 0000000..6e0bbe2
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/jr2/jr2_icpu_cfg.h
@@ -0,0 +1,321 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _MSCC_JR2_ICPU_CFG_H_
+#define _MSCC_JR2_ICPU_CFG_H_
+
+#define ICPU_GPR(x)                                       (0x4 * (x))
+#define ICPU_GPR_RSZ                                      0x4
+
+#define ICPU_RESET                                        0x20
+
+#define ICPU_RESET_CORE_RST_CPU_ONLY                      BIT(3)
+#define ICPU_RESET_CORE_RST_PROTECT                       BIT(2)
+#define ICPU_RESET_CORE_RST_FORCE                         BIT(1)
+#define ICPU_RESET_MEM_RST_FORCE                          BIT(0)
+
+#define ICPU_GENERAL_CTRL                                 0x24
+
+#define ICPU_GENERAL_CTRL_CPU_BUSIF_SLEEP_DIS             BIT(15)
+#define ICPU_GENERAL_CTRL_CPU_BUSIF_WERR_ENA              BIT(14)
+#define ICPU_GENERAL_CTRL_CPU_8051_IROM_ENA               BIT(13)
+#define ICPU_GENERAL_CTRL_CPU_MIPS_DIS                    BIT(12)
+#define ICPU_GENERAL_CTRL_IF_MIIM_SLV_ENA                 BIT(11)
+#define ICPU_GENERAL_CTRL_IF_PI_SLV_DONEPOL               BIT(10)
+#define ICPU_GENERAL_CTRL_IF_PI_MST_ENA                   BIT(9)
+#define ICPU_GENERAL_CTRL_IF_PI_SLV_ENA                   BIT(8)
+#define ICPU_GENERAL_CTRL_IF_SI_OWNER(x)                  (((x) << 6) & GENMASK(7, 6))
+#define ICPU_GENERAL_CTRL_IF_SI_OWNER_M                   GENMASK(7, 6)
+#define ICPU_GENERAL_CTRL_IF_SI_OWNER_X(x)                (((x) & GENMASK(7, 6)) >> 4)
+#define ICPU_GENERAL_CTRL_IF_SI1_OWNER(x)                 (((x) << 4) & GENMASK(5, 4))
+#define ICPU_GENERAL_CTRL_IF_SI1_OWNER_M                  GENMASK(5, 4)
+#define ICPU_GENERAL_CTRL_IF_SI1_OWNER_X(x)               (((x) & GENMASK(5, 4)) >> 4)
+#define ICPU_GENERAL_CTRL_SSI_MST_CONTENTION              BIT(3)
+#define ICPU_GENERAL_CTRL_CPU_BE_ENA                      BIT(2)
+#define ICPU_GENERAL_CTRL_CPU_DIS                         BIT(1)
+#define ICPU_GENERAL_CTRL_BOOT_MODE_ENA                   BIT(0)
+
+#define ICPU_SPI_MST_CFG                                  0x3c
+
+#define ICPU_SPI_MST_CFG_A32B_ENA                         BIT(11)
+#define ICPU_SPI_MST_CFG_FAST_READ_ENA                    BIT(10)
+#define ICPU_SPI_MST_CFG_CS_DESELECT_TIME(x)              (((x) << 5) & GENMASK(9, 5))
+#define ICPU_SPI_MST_CFG_CS_DESELECT_TIME_M               GENMASK(9, 5)
+#define ICPU_SPI_MST_CFG_CS_DESELECT_TIME_X(x)            (((x) & GENMASK(9, 5)) >> 5)
+#define ICPU_SPI_MST_CFG_CLK_DIV(x)                       ((x) & GENMASK(4, 0))
+#define ICPU_SPI_MST_CFG_CLK_DIV_M                        GENMASK(4, 0)
+
+#define ICPU_SW_MODE                                      0x50
+
+#define ICPU_SW_MODE_SW_PIN_CTRL_MODE                     BIT(13)
+#define ICPU_SW_MODE_SW_SPI_SCK                           BIT(12)
+#define ICPU_SW_MODE_SW_SPI_SCK_OE                        BIT(11)
+#define ICPU_SW_MODE_SW_SPI_SDO                           BIT(10)
+#define ICPU_SW_MODE_SW_SPI_SDO_OE                        BIT(9)
+#define ICPU_SW_MODE_SW_SPI_CS(x)                         (((x) << 5) & GENMASK(8, 5))
+#define ICPU_SW_MODE_SW_SPI_CS_M                          GENMASK(8, 5)
+#define ICPU_SW_MODE_SW_SPI_CS_X(x)                       (((x) & GENMASK(8, 5)) >> 5)
+#define ICPU_SW_MODE_SW_SPI_CS_OE(x)                      (((x) << 1) & GENMASK(4, 1))
+#define ICPU_SW_MODE_SW_SPI_CS_OE_M                       GENMASK(4, 1)
+#define ICPU_SW_MODE_SW_SPI_CS_OE_X(x)                    (((x) & GENMASK(4, 1)) >> 1)
+#define ICPU_SW_MODE_SW_SPI_SDI                           BIT(0)
+
+#define ICPU_INTR_ENA                                     0x88
+
+#define ICPU_DST_INTR_MAP(x)                              (0x98 + 0x4 * (x))
+#define ICPU_DST_INTR_MAP_RSZ                             0x4
+
+#define ICPU_TIMER_TICK_DIV                               0x108
+
+#define ICPU_TIMER_VALUE(x)                               (0x10c + 0x4 * (x))
+#define ICPU_TIMER_VALUE_RSZ                              0x4
+
+#define ICPU_TIMER_CTRL(x)                                (0x124 + 0x4 * (x))
+#define ICPU_TIMER_CTRL_RSZ                               0x4
+
+#define ICPU_TIMER_CTRL_MAX_FREQ_ENA                      BIT(3)
+#define ICPU_TIMER_CTRL_ONE_SHOT_ENA                      BIT(2)
+#define ICPU_TIMER_CTRL_TIMER_ENA                         BIT(1)
+#define ICPU_TIMER_CTRL_FORCE_RELOAD                      BIT(0)
+
+#define ICPU_MEMCTRL_CTRL                                 0x130
+
+#define ICPU_MEMCTRL_CTRL_PWR_DOWN                        BIT(3)
+#define ICPU_MEMCTRL_CTRL_MDSET                           BIT(2)
+#define ICPU_MEMCTRL_CTRL_STALL_REF_ENA                   BIT(1)
+#define ICPU_MEMCTRL_CTRL_INITIALIZE                      BIT(0)
+
+#define ICPU_MEMCTRL_CFG                                  0x134
+
+#define ICPU_MEMCTRL_CFG_DDR_512MBYTE_PLUS                BIT(16)
+#define ICPU_MEMCTRL_CFG_DDR_ECC_ERR_ENA                  BIT(15)
+#define ICPU_MEMCTRL_CFG_DDR_ECC_COR_ENA                  BIT(14)
+#define ICPU_MEMCTRL_CFG_DDR_ECC_ENA                      BIT(13)
+#define ICPU_MEMCTRL_CFG_DDR_WIDTH                        BIT(12)
+#define ICPU_MEMCTRL_CFG_DDR_MODE                         BIT(11)
+#define ICPU_MEMCTRL_CFG_BURST_SIZE                       BIT(10)
+#define ICPU_MEMCTRL_CFG_BURST_LEN                        BIT(9)
+#define ICPU_MEMCTRL_CFG_BANK_CNT                         BIT(8)
+#define ICPU_MEMCTRL_CFG_MSB_ROW_ADDR(x)                  (((x) << 4) & GENMASK(7, 4))
+#define ICPU_MEMCTRL_CFG_MSB_ROW_ADDR_M                   GENMASK(7, 4)
+#define ICPU_MEMCTRL_CFG_MSB_ROW_ADDR_X(x)                (((x) & GENMASK(7, 4)) >> 4)
+#define ICPU_MEMCTRL_CFG_MSB_COL_ADDR(x)                  ((x) & GENMASK(3, 0))
+#define ICPU_MEMCTRL_CFG_MSB_COL_ADDR_M                   GENMASK(3, 0)
+
+#define ICPU_MEMCTRL_STAT                                 0x138
+
+#define ICPU_MEMCTRL_STAT_RDATA_MASKED                    BIT(5)
+#define ICPU_MEMCTRL_STAT_RDATA_DUMMY                     BIT(4)
+#define ICPU_MEMCTRL_STAT_RDATA_ECC_ERR                   BIT(3)
+#define ICPU_MEMCTRL_STAT_RDATA_ECC_COR                   BIT(2)
+#define ICPU_MEMCTRL_STAT_PWR_DOWN_ACK                    BIT(1)
+#define ICPU_MEMCTRL_STAT_INIT_DONE                       BIT(0)
+
+#define ICPU_MEMCTRL_REF_PERIOD                           0x13c
+
+#define ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF(x)           (((x) << 16) & GENMASK(19, 16))
+#define ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF_M            GENMASK(19, 16)
+#define ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF_X(x)         (((x) & GENMASK(19, 16)) >> 16)
+#define ICPU_MEMCTRL_REF_PERIOD_REF_PERIOD(x)             ((x) & GENMASK(15, 0))
+#define ICPU_MEMCTRL_REF_PERIOD_REF_PERIOD_M              GENMASK(15, 0)
+
+#define ICPU_MEMCTRL_ZQCAL                                0x140
+
+#define ICPU_MEMCTRL_ZQCAL_ZQCAL_LONG                     BIT(1)
+#define ICPU_MEMCTRL_ZQCAL_ZQCAL_SHORT                    BIT(0)
+
+#define ICPU_MEMCTRL_TIMING0                              0x144
+
+#define ICPU_MEMCTRL_TIMING0_RD_TO_WR_DLY(x)              (((x) << 28) & GENMASK(31, 28))
+#define ICPU_MEMCTRL_TIMING0_RD_TO_WR_DLY_M               GENMASK(31, 28)
+#define ICPU_MEMCTRL_TIMING0_RD_TO_WR_DLY_X(x)            (((x) & GENMASK(31, 28)) >> 28)
+#define ICPU_MEMCTRL_TIMING0_WR_CS_CHANGE_DLY(x)          (((x) << 24) & GENMASK(27, 24))
+#define ICPU_MEMCTRL_TIMING0_WR_CS_CHANGE_DLY_M           GENMASK(27, 24)
+#define ICPU_MEMCTRL_TIMING0_WR_CS_CHANGE_DLY_X(x)        (((x) & GENMASK(27, 24)) >> 24)
+#define ICPU_MEMCTRL_TIMING0_RD_CS_CHANGE_DLY(x)          (((x) << 20) & GENMASK(23, 20))
+#define ICPU_MEMCTRL_TIMING0_RD_CS_CHANGE_DLY_M           GENMASK(23, 20)
+#define ICPU_MEMCTRL_TIMING0_RD_CS_CHANGE_DLY_X(x)        (((x) & GENMASK(23, 20)) >> 20)
+#define ICPU_MEMCTRL_TIMING0_RAS_TO_PRECH_DLY(x)          (((x) << 16) & GENMASK(19, 16))
+#define ICPU_MEMCTRL_TIMING0_RAS_TO_PRECH_DLY_M           GENMASK(19, 16)
+#define ICPU_MEMCTRL_TIMING0_RAS_TO_PRECH_DLY_X(x)        (((x) & GENMASK(19, 16)) >> 16)
+#define ICPU_MEMCTRL_TIMING0_WR_TO_PRECH_DLY(x)           (((x) << 12) & GENMASK(15, 12))
+#define ICPU_MEMCTRL_TIMING0_WR_TO_PRECH_DLY_M            GENMASK(15, 12)
+#define ICPU_MEMCTRL_TIMING0_WR_TO_PRECH_DLY_X(x)         (((x) & GENMASK(15, 12)) >> 12)
+#define ICPU_MEMCTRL_TIMING0_RD_TO_PRECH_DLY(x)           (((x) << 8) & GENMASK(11, 8))
+#define ICPU_MEMCTRL_TIMING0_RD_TO_PRECH_DLY_M            GENMASK(11, 8)
+#define ICPU_MEMCTRL_TIMING0_RD_TO_PRECH_DLY_X(x)         (((x) & GENMASK(11, 8)) >> 8)
+#define ICPU_MEMCTRL_TIMING0_WR_DATA_XFR_DLY(x)           (((x) << 4) & GENMASK(7, 4))
+#define ICPU_MEMCTRL_TIMING0_WR_DATA_XFR_DLY_M            GENMASK(7, 4)
+#define ICPU_MEMCTRL_TIMING0_WR_DATA_XFR_DLY_X(x)         (((x) & GENMASK(7, 4)) >> 4)
+#define ICPU_MEMCTRL_TIMING0_RD_DATA_XFR_DLY(x)           ((x) & GENMASK(3, 0))
+#define ICPU_MEMCTRL_TIMING0_RD_DATA_XFR_DLY_M            GENMASK(3, 0)
+
+#define ICPU_MEMCTRL_TIMING1                              0x148
+
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_SAME_BANK_DLY(x)  (((x) << 24) & GENMASK(31, 24))
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_SAME_BANK_DLY_M   GENMASK(31, 24)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_SAME_BANK_DLY_X(x) (((x) & GENMASK(31, 24)) >> 24)
+#define ICPU_MEMCTRL_TIMING1_BANK8_FAW_DLY(x)             (((x) << 16) & GENMASK(23, 16))
+#define ICPU_MEMCTRL_TIMING1_BANK8_FAW_DLY_M              GENMASK(23, 16)
+#define ICPU_MEMCTRL_TIMING1_BANK8_FAW_DLY_X(x)           (((x) & GENMASK(23, 16)) >> 16)
+#define ICPU_MEMCTRL_TIMING1_PRECH_TO_RAS_DLY(x)          (((x) << 12) & GENMASK(15, 12))
+#define ICPU_MEMCTRL_TIMING1_PRECH_TO_RAS_DLY_M           GENMASK(15, 12)
+#define ICPU_MEMCTRL_TIMING1_PRECH_TO_RAS_DLY_X(x)        (((x) & GENMASK(15, 12)) >> 12)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_DLY(x)            (((x) << 8) & GENMASK(11, 8))
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_DLY_M             GENMASK(11, 8)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_DLY_X(x)          (((x) & GENMASK(11, 8)) >> 8)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_CAS_DLY(x)            (((x) << 4) & GENMASK(7, 4))
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_CAS_DLY_M             GENMASK(7, 4)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_CAS_DLY_X(x)          (((x) & GENMASK(7, 4)) >> 4)
+#define ICPU_MEMCTRL_TIMING1_WR_TO_RD_DLY(x)              ((x) & GENMASK(3, 0))
+#define ICPU_MEMCTRL_TIMING1_WR_TO_RD_DLY_M               GENMASK(3, 0)
+
+#define ICPU_MEMCTRL_TIMING2                              0x14c
+
+#define ICPU_MEMCTRL_TIMING2_PRECH_ALL_DLY(x)             (((x) << 28) & GENMASK(31, 28))
+#define ICPU_MEMCTRL_TIMING2_PRECH_ALL_DLY_M              GENMASK(31, 28)
+#define ICPU_MEMCTRL_TIMING2_PRECH_ALL_DLY_X(x)           (((x) & GENMASK(31, 28)) >> 28)
+#define ICPU_MEMCTRL_TIMING2_MDSET_DLY(x)                 (((x) << 24) & GENMASK(27, 24))
+#define ICPU_MEMCTRL_TIMING2_MDSET_DLY_M                  GENMASK(27, 24)
+#define ICPU_MEMCTRL_TIMING2_MDSET_DLY_X(x)               (((x) & GENMASK(27, 24)) >> 24)
+#define ICPU_MEMCTRL_TIMING2_REF_DLY(x)                   (((x) << 16) & GENMASK(23, 16))
+#define ICPU_MEMCTRL_TIMING2_REF_DLY_M                    GENMASK(23, 16)
+#define ICPU_MEMCTRL_TIMING2_REF_DLY_X(x)                 (((x) & GENMASK(23, 16)) >> 16)
+#define ICPU_MEMCTRL_TIMING2_INIT_DLY(x)                  ((x) & GENMASK(15, 0))
+#define ICPU_MEMCTRL_TIMING2_INIT_DLY_M                   GENMASK(15, 0)
+
+#define ICPU_MEMCTRL_TIMING3                              0x150
+
+#define ICPU_MEMCTRL_TIMING3_RMW_DLY(x)                   (((x) << 16) & GENMASK(19, 16))
+#define ICPU_MEMCTRL_TIMING3_RMW_DLY_M                    GENMASK(19, 16)
+#define ICPU_MEMCTRL_TIMING3_RMW_DLY_X(x)                 (((x) & GENMASK(19, 16)) >> 16)
+#define ICPU_MEMCTRL_TIMING3_ODT_RD_DLY(x)                (((x) << 12) & GENMASK(15, 12))
+#define ICPU_MEMCTRL_TIMING3_ODT_RD_DLY_M                 GENMASK(15, 12)
+#define ICPU_MEMCTRL_TIMING3_ODT_RD_DLY_X(x)              (((x) & GENMASK(15, 12)) >> 12)
+#define ICPU_MEMCTRL_TIMING3_ODT_WR_DLY(x)                (((x) << 8) & GENMASK(11, 8))
+#define ICPU_MEMCTRL_TIMING3_ODT_WR_DLY_M                 GENMASK(11, 8)
+#define ICPU_MEMCTRL_TIMING3_ODT_WR_DLY_X(x)              (((x) & GENMASK(11, 8)) >> 8)
+#define ICPU_MEMCTRL_TIMING3_LOCAL_ODT_RD_DLY(x)          (((x) << 4) & GENMASK(7, 4))
+#define ICPU_MEMCTRL_TIMING3_LOCAL_ODT_RD_DLY_M           GENMASK(7, 4)
+#define ICPU_MEMCTRL_TIMING3_LOCAL_ODT_RD_DLY_X(x)        (((x) & GENMASK(7, 4)) >> 4)
+#define ICPU_MEMCTRL_TIMING3_WR_TO_RD_CS_CHANGE_DLY(x)    ((x) & GENMASK(3, 0))
+#define ICPU_MEMCTRL_TIMING3_WR_TO_RD_CS_CHANGE_DLY_M     GENMASK(3, 0)
+
+#define ICPU_MEMCTRL_TIMING4                              0x154
+
+#define ICPU_MEMCTRL_TIMING4_ZQCAL_INIT_DLY(x)            (((x) << 20) & GENMASK(31, 20))
+#define ICPU_MEMCTRL_TIMING4_ZQCAL_INIT_DLY_M             GENMASK(31, 20)
+#define ICPU_MEMCTRL_TIMING4_ZQCAL_INIT_DLY_X(x)          (((x) & GENMASK(31, 20)) >> 20)
+#define ICPU_MEMCTRL_TIMING4_ZQCAL_LONG_DLY(x)            (((x) << 8) & GENMASK(19, 8))
+#define ICPU_MEMCTRL_TIMING4_ZQCAL_LONG_DLY_M             GENMASK(19, 8)
+#define ICPU_MEMCTRL_TIMING4_ZQCAL_LONG_DLY_X(x)          (((x) & GENMASK(19, 8)) >> 8)
+#define ICPU_MEMCTRL_TIMING4_ZQCAL_SHORT_DLY(x)           ((x) & GENMASK(7, 0))
+#define ICPU_MEMCTRL_TIMING4_ZQCAL_SHORT_DLY_M            GENMASK(7, 0)
+
+#define ICPU_MEMCTRL_MR0_VAL                              0x158
+
+#define ICPU_MEMCTRL_MR1_VAL                              0x15c
+
+#define ICPU_MEMCTRL_MR2_VAL                              0x160
+
+#define ICPU_MEMCTRL_MR3_VAL                              0x164
+
+#define ICPU_MEMCTRL_TERMRES_CTRL                         0x168
+
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_EXT              BIT(11)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_ENA(x)           (((x) << 7) & GENMASK(10, 7))
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_ENA_M            GENMASK(10, 7)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_ENA_X(x)         (((x) & GENMASK(10, 7)) >> 7)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_EXT              BIT(6)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_ENA(x)           (((x) << 2) & GENMASK(5, 2))
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_ENA_M            GENMASK(5, 2)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_ENA_X(x)         (((x) & GENMASK(5, 2)) >> 2)
+#define ICPU_MEMCTRL_TERMRES_CTRL_LOCAL_ODT_RD_EXT        BIT(1)
+#define ICPU_MEMCTRL_TERMRES_CTRL_LOCAL_ODT_RD_ENA        BIT(0)
+
+#define ICPU_MEMCTRL_DFT                                  0x16c
+
+#define ICPU_MEMCTRL_DFT_DDRDFT_LBW                       BIT(7)
+#define ICPU_MEMCTRL_DFT_DDRDFT_GATE_ENA                  BIT(6)
+#define ICPU_MEMCTRL_DFT_DDRDFT_TERM_ENA                  BIT(5)
+#define ICPU_MEMCTRL_DFT_DDRDFT_A10                       BIT(4)
+#define ICPU_MEMCTRL_DFT_DDRDFT_STAT                      BIT(3)
+#define ICPU_MEMCTRL_DFT_DDRDFT_MODE(x)                   (((x) << 1) & GENMASK(2, 1))
+#define ICPU_MEMCTRL_DFT_DDRDFT_MODE_M                    GENMASK(2, 1)
+#define ICPU_MEMCTRL_DFT_DDRDFT_MODE_X(x)                 (((x) & GENMASK(2, 1)) >> 1)
+#define ICPU_MEMCTRL_DFT_DDRDFT_ENA                       BIT(0)
+
+#define ICPU_MEMCTRL_DQS_DLY(x)                           (0x170 + 0x4 * (x))
+#define ICPU_MEMCTRL_DQS_DLY_RSZ                          0x4
+
+#define ICPU_MEMCTRL_DQS_DLY_TRAIN_DQ_ENA                 BIT(11)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM1(x)              (((x) << 8) & GENMASK(10, 8))
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM1_M               GENMASK(10, 8)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM1_X(x)            (((x) & GENMASK(10, 8)) >> 8)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM0(x)              (((x) << 5) & GENMASK(7, 5))
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM0_M               GENMASK(7, 5)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM0_X(x)            (((x) & GENMASK(7, 5)) >> 5)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY(x)                   ((x) & GENMASK(4, 0))
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_M                    GENMASK(4, 0)
+
+#define ICPU_MEMCTRL_DQS_AUTO                             (0x178 + 0x4 * (x))
+#define ICPU_MEMCTRL_DQS_AUTO_RSZ                         0x4
+
+#define ICPU_MEMCTRL_DQS_AUTO_DQS_DRIFT(x)                (((x) << 6) & GENMASK(7, 6))
+#define ICPU_MEMCTRL_DQS_AUTO_DQS_DRIFT_M                 GENMASK(7, 6)
+#define ICPU_MEMCTRL_DQS_AUTO_DQS_DRIFT_X(x)              (((x) & GENMASK(7, 6)) >> 6)
+#define ICPU_MEMCTRL_DQS_AUTO_DQS_OVERFLOW                BIT(5)
+#define ICPU_MEMCTRL_DQS_AUTO_DQS_UNDERFLOW               BIT(4)
+#define ICPU_MEMCTRL_DQS_AUTO_DQS_AUTO_SRC                BIT(3)
+#define ICPU_MEMCTRL_DQS_AUTO_DQS_AUTO_UP                 BIT(2)
+#define ICPU_MEMCTRL_DQS_AUTO_DQS_AUTO_DOWN               BIT(1)
+#define ICPU_MEMCTRL_DQS_AUTO_DQS_AUTO_ENA                BIT(0)
+
+#define ICPU_MEMPHY_CFG                                   0x180
+
+#define ICPU_MEMPHY_CFG_PHY_FLUSH_DIS                     BIT(10)
+#define ICPU_MEMPHY_CFG_PHY_RD_ADJ_DIS                    BIT(9)
+#define ICPU_MEMPHY_CFG_PHY_DQS_EXT                       BIT(8)
+#define ICPU_MEMPHY_CFG_PHY_FIFO_RST                      BIT(7)
+#define ICPU_MEMPHY_CFG_PHY_DLL_BL_RST                    BIT(6)
+#define ICPU_MEMPHY_CFG_PHY_DLL_CL_RST                    BIT(5)
+#define ICPU_MEMPHY_CFG_PHY_ODT_OE                        BIT(4)
+#define ICPU_MEMPHY_CFG_PHY_CK_OE                         BIT(3)
+#define ICPU_MEMPHY_CFG_PHY_CL_OE                         BIT(2)
+#define ICPU_MEMPHY_CFG_PHY_SSTL_ENA                      BIT(1)
+#define ICPU_MEMPHY_CFG_PHY_RST                           BIT(0)
+
+#define ICPU_MEMPHY_ZCAL                                  0x1a8
+
+#define ICPU_MEMPHY_ZCAL_ZCAL_CLK_SEL                     BIT(9)
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_ODT(x)                 (((x) << 5) & GENMASK(8, 5))
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_ODT_M                  GENMASK(8, 5)
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_ODT_X(x)               (((x) & GENMASK(8, 5)) >> 5)
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG(x)                     (((x) << 1) & GENMASK(4, 1))
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_M                      GENMASK(4, 1)
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_X(x)                   (((x) & GENMASK(4, 1)) >> 1)
+#define ICPU_MEMPHY_ZCAL_ZCAL_ENA                         BIT(0)
+//
+#define ICPU_MEMPHY_ZCAL_STAT                             0x1ac
+
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_ZCTRL(x)               (((x) << 12) & GENMASK(31, 12))
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_ZCTRL_M                GENMASK(31, 12)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_ZCTRL_X(x)             (((x) & GENMASK(31, 12)) >> 12)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_ODTPU(x)          (((x) << 8) & GENMASK(9, 8))
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_ODTPU_M           GENMASK(9, 8)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_ODTPU_X(x)        (((x) & GENMASK(9, 8)) >> 8)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_ODTPD(x)          (((x) << 6) & GENMASK(7, 6))
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_ODTPD_M           GENMASK(7, 6)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_ODTPD_X(x)        (((x) & GENMASK(7, 6)) >> 6)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_PU(x)             (((x) << 4) & GENMASK(5, 4))
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_PU_M              GENMASK(5, 4)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_PU_X(x)           (((x) & GENMASK(5, 4)) >> 4)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_PD(x)             (((x) << 2) & GENMASK(3, 2))
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_PD_M              GENMASK(3, 2)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_PD_X(x)           (((x) & GENMASK(3, 2)) >> 2)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_ERR                    BIT(1)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_DONE                   BIT(0)
+
+#endif
diff --git a/arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb.h b/arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb.h
index 8c0b612..a74a685 100644
--- a/arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb.h
+++ b/arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb.h
@@ -11,4 +11,8 @@
 #define PERF_SOFT_RST_SOFT_SWC_RST                        BIT(1)
 #define PERF_SOFT_RST_SOFT_CHIP_RST                       BIT(0)
 
+#define GPIO_ALT(x)				(0x88 + 4 * (x))
+
+#define CHIP_ID					(0x08)
+
 #endif
diff --git a/arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb_miim_regs.h b/arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb_miim_regs.h
new file mode 100644
index 0000000..2303734
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb_miim_regs.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Microsemi Ocelot Switch driver
+ *
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _MSCC_LUTON_MIIM_REGS_H_
+#define _MSCC_LUTON_MIIM_REGS_H_
+
+#define MIIM_MII_STATUS(gi) (0xa0 + (gi * 36))
+#define MIIM_MII_CMD(gi)    (0xa8 + (gi * 36))
+#define MIIM_MII_DATA(gi)   (0xac + (gi * 36))
+
+#define MSCC_F_MII_STATUS_MIIM_STAT_BUSY(x)   (x ? BIT(3) : 0)
+
+#define MSCC_F_MII_CMD_MIIM_CMD_VLD(x)        (x ? BIT(31) : 0)
+#define MSCC_F_MII_CMD_MIIM_CMD_PHYAD(x)      (GENMASK(29, 25) & (x << 25))
+#define MSCC_F_MII_CMD_MIIM_CMD_REGAD(x)      (GENMASK(24, 20) & (x << 20))
+#define MSCC_F_MII_CMD_MIIM_CMD_WRDATA(x)     (GENMASK(19, 4) & (x << 4))
+#define MSCC_F_MII_CMD_MIIM_CMD_OPR_FIELD(x)  (GENMASK(2, 1) & (x << 1))
+
+#define MSCC_M_MII_DATA_MIIM_DATA_SUCCESS     GENMASK(17, 16)
+#define MSCC_X_MII_DATA_MIIM_DATA_RDDATA(x)   ((x >> 0) & GENMASK(15, 0))
+
+#endif
diff --git a/arch/mips/mach-mscc/include/mach/ocelot/ocelot_devcpu_gcb.h b/arch/mips/mach-mscc/include/mach/ocelot/ocelot_devcpu_gcb.h
index f8aa97b..d3a7641 100644
--- a/arch/mips/mach-mscc/include/mach/ocelot/ocelot_devcpu_gcb.h
+++ b/arch/mips/mach-mscc/include/mach/ocelot/ocelot_devcpu_gcb.h
@@ -18,4 +18,6 @@
 
 #define PERF_GPIO_OE                                      0x44
 
+#define GPIO_ALT(x)				(0x54 + 4 * (x))
+
 #endif
diff --git a/arch/mips/mach-mscc/include/mach/ocelot/ocelot_devcpu_gcb_miim_regs.h b/arch/mips/mach-mscc/include/mach/ocelot/ocelot_devcpu_gcb_miim_regs.h
new file mode 100644
index 0000000..4ad9221
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/ocelot/ocelot_devcpu_gcb_miim_regs.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _MSCC_OCELOT_DEVCPU_GCB_MIIM_REGS_H_
+#define _MSCC_OCELOT_DEVCPU_GCB_MIIM_REGS_H_
+
+#define MIIM_MII_STATUS(gi) (0x9c + (gi * 36))
+#define MIIM_MII_CMD(gi)    (0xa4 + (gi * 36))
+#define MIIM_MII_DATA(gi)   (0xa8 + (gi * 36))
+
+#define MSCC_F_MII_STATUS_MIIM_STAT_BUSY(x)   ((x) ? BIT(3) : 0)
+
+#define MSCC_F_MII_CMD_MIIM_CMD_VLD(x)        ((x) ? BIT(31) : 0)
+#define MSCC_F_MII_CMD_MIIM_CMD_PHYAD(x)      (GENMASK(29, 25) & ((x) << 25))
+#define MSCC_F_MII_CMD_MIIM_CMD_REGAD(x)      (GENMASK(24, 20) & ((x) << 20))
+#define MSCC_F_MII_CMD_MIIM_CMD_WRDATA(x)     (GENMASK(19, 4) & ((x) << 4))
+#define MSCC_F_MII_CMD_MIIM_CMD_OPR_FIELD(x)  (GENMASK(2, 1) & ((x) << 1))
+#define MSCC_F_MII_CMD_MIIM_CMD_SCAN(x)       ((x) ? BIT(0) : 0)
+
+#define MSCC_M_MII_DATA_MIIM_DATA_SUCCESS     GENMASK(17, 16)
+#define MSCC_X_MII_DATA_MIIM_DATA_RDDATA(x)   (((x) >> 0) & GENMASK(15, 0))
+
+#endif
diff --git a/arch/mips/mach-mscc/phy.c b/arch/mips/mach-mscc/phy.c
new file mode 100644
index 0000000..add6280
--- /dev/null
+++ b/arch/mips/mach-mscc/phy.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+int mscc_phy_rd_wr(u8 read,
+		   u32 miimdev,
+		   u8 miim_addr,
+		   u8 addr,
+		   u16 *value)
+{
+	u32 data;
+	int i;
+
+	/* Command part */
+	data = (read ? MSCC_F_MII_CMD_MIIM_CMD_OPR_FIELD(2) : /* Read */
+		MSCC_F_MII_CMD_MIIM_CMD_OPR_FIELD(1) | /* Write */
+		MSCC_F_MII_CMD_MIIM_CMD_WRDATA(*value)); /* value */
+
+	/* Addressing part */
+	data |=
+		MSCC_F_MII_CMD_MIIM_CMD_VLD(1) | /* Valid command */
+		MSCC_F_MII_CMD_MIIM_CMD_REGAD(addr) | /* Reg addr */
+		MSCC_F_MII_CMD_MIIM_CMD_PHYAD(miim_addr); /* Miim addr */
+
+	/* Enqueue MIIM operation to be executed */
+	writel(data, BASE_DEVCPU_GCB + MIIM_MII_CMD(miimdev));
+
+	/* Wait for MIIM operation to finish */
+	i = 0;
+	do {
+		if (i++ > 100) {
+			debug("Miim timeout");
+			return -1;
+		}
+		data = readl(BASE_DEVCPU_GCB + MIIM_MII_STATUS(miimdev));
+		debug("Read status miim(%d): 0x%08x\n", miimdev, data);
+	} while (data & MSCC_F_MII_STATUS_MIIM_STAT_BUSY(1));
+
+	if (read) {
+		data = readl(BASE_DEVCPU_GCB + MIIM_MII_DATA(miimdev));
+		if (data & MSCC_M_MII_DATA_MIIM_DATA_SUCCESS) {
+			debug("Read(%d, %d) returned 0x%08x\n",
+			      miim_addr, addr, data);
+			return -1;
+		}
+		*value = MSCC_X_MII_DATA_MIIM_DATA_RDDATA(data);
+	}
+
+	return 0;
+}
+
+int mscc_phy_rd(u32 miimdev,
+		u8 miim_addr,
+		u8 addr,
+		u16 *value)
+{
+	if (mscc_phy_rd_wr(1, miimdev, miim_addr, addr, value) == 0)
+		return 0;
+	debug("Read(%d, %d) returned error\n", miim_addr, addr);
+	return -1;
+}
+
+int mscc_phy_wr(u32 miimdev,
+		u8 miim_addr,
+		u8 addr,
+		u16 value)
+{
+	return mscc_phy_rd_wr(0, miimdev, miim_addr, addr, &value);
+}
diff --git a/arch/mips/mach-mscc/reset.c b/arch/mips/mach-mscc/reset.c
index 390bbd0..e0e610a 100644
--- a/arch/mips/mach-mscc/reset.c
+++ b/arch/mips/mach-mscc/reset.c
@@ -12,6 +12,22 @@
 
 void _machine_restart(void)
 {
+#if defined(CONFIG_SOC_JR2)
+	register u32 reg = readl(BASE_CFG + ICPU_GENERAL_CTRL);
+	/* Set owner */
+	reg &= ~ICPU_GENERAL_CTRL_IF_SI_OWNER_M;
+	reg |= ICPU_GENERAL_CTRL_IF_SI_OWNER(1);
+	/* Set boot mode */
+	reg |= ICPU_GENERAL_CTRL_BOOT_MODE_ENA;
+	writel(reg, BASE_CFG + ICPU_GENERAL_CTRL);
+	/* Read back in order to make BOOT mode setting active */
+	reg = readl(BASE_CFG + ICPU_GENERAL_CTRL);
+	/* Reset CPU only - still executing _here_. but from cache */
+	writel(readl(BASE_CFG + ICPU_RESET) |
+	       ICPU_RESET_CORE_RST_CPU_ONLY |
+	       ICPU_RESET_CORE_RST_FORCE,
+	       BASE_CFG + ICPU_RESET);
+#else
 	register u32 resetbits = PERF_SOFT_RST_SOFT_CHIP_RST;
 	(void)readl(BASE_DEVCPU_GCB + PERF_SOFT_RST);
 
@@ -24,6 +40,7 @@
 
 	/* Do the global reset */
 	writel(resetbits, BASE_DEVCPU_GCB + PERF_SOFT_RST);
+#endif
 
 	while (1)
 		; /* NOP */
diff --git a/arch/riscv/config.mk b/arch/riscv/config.mk
index ff4fe64..84654eb 100644
--- a/arch/riscv/config.mk
+++ b/arch/riscv/config.mk
@@ -23,8 +23,7 @@
 EFI_LDS			:= elf_riscv64_efi.lds
 endif
 
-CONFIG_STANDALONE_LOAD_ADDR = 0x00000000
-LDFLAGS_STANDALONE += -T $(srctree)/examples/standalone/riscv.lds
+CONFIG_STANDALONE_LOAD_ADDR ?= 0x00000000
 
 PLATFORM_CPPFLAGS	+= -ffixed-gp -fpic
 PLATFORM_RELFLAGS	+= -fno-common -gdwarf-2 -ffunction-sections \
diff --git a/arch/riscv/cpu/ax25/cache.c b/arch/riscv/cpu/ax25/cache.c
index 8d6ae17..228fc55 100644
--- a/arch/riscv/cpu/ax25/cache.c
+++ b/arch/riscv/cpu/ax25/cache.c
@@ -6,6 +6,28 @@
 
 #include <common.h>
 
+void flush_dcache_all(void)
+{
+	/*
+	 * Andes' AX25 does not have a coherence agent. U-Boot must use data
+	 * cache flush and invalidate functions to keep data in the system
+	 * coherent.
+	 * The implementation of the fence instruction in the AX25 flushes the
+	 * data cache and is used for this purpose.
+	 */
+	asm volatile ("fence" ::: "memory");
+}
+
+void flush_dcache_range(unsigned long start, unsigned long end)
+{
+	flush_dcache_all();
+}
+
+void invalidate_dcache_range(unsigned long start, unsigned long end)
+{
+	flush_dcache_all();
+}
+
 void icache_enable(void)
 {
 #ifndef CONFIG_SYS_ICACHE_OFF
diff --git a/arch/riscv/lib/cache.c b/arch/riscv/lib/cache.c
index ae5c607..5437a12 100644
--- a/arch/riscv/lib/cache.c
+++ b/arch/riscv/lib/cache.c
@@ -11,13 +11,12 @@
 	asm volatile ("fence.i" ::: "memory");
 }
 
-void flush_dcache_all(void)
+__weak void flush_dcache_all(void)
 {
-	asm volatile ("fence" :::"memory");
 }
-void flush_dcache_range(unsigned long start, unsigned long end)
+
+__weak void flush_dcache_range(unsigned long start, unsigned long end)
 {
-	flush_dcache_all();
 }
 
 void invalidate_icache_range(unsigned long start, unsigned long end)
@@ -29,9 +28,8 @@
 	invalidate_icache_all();
 }
 
-void invalidate_dcache_range(unsigned long start, unsigned long end)
+__weak void invalidate_dcache_range(unsigned long start, unsigned long end)
 {
-	flush_dcache_all();
 }
 
 void cache_flush(void)
@@ -42,8 +40,8 @@
 
 void flush_cache(unsigned long addr, unsigned long size)
 {
-	invalidate_icache_all();
-	flush_dcache_all();
+	invalidate_icache_range(addr, addr + size);
+	flush_dcache_range(addr, addr + size);
 }
 
 __weak void icache_enable(void)
diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c
index e185933..74c1e56 100644
--- a/arch/riscv/lib/interrupts.c
+++ b/arch/riscv/lib/interrupts.c
@@ -37,7 +37,8 @@
 		printf("exception code: %ld , %s , epc %lx , ra %lx\n",
 		       code, exception_code[code], epc, regs->ra);
 	} else {
-		printf("Reserved\n");
+		printf("reserved exception code: %ld , epc %lx , ra %lx\n",
+		       code, epc, regs->ra);
 	}
 
 	hang();
diff --git a/arch/sandbox/config.mk b/arch/sandbox/config.mk
index 7226b7b..31a12db 100644
--- a/arch/sandbox/config.mk
+++ b/arch/sandbox/config.mk
@@ -11,11 +11,9 @@
 ifneq ($(NO_SDL),)
 PLATFORM_CPPFLAGS += -DSANDBOX_NO_SDL
 else
-ifdef CONFIG_SANDBOX_SDL
 PLATFORM_LIBS += $(shell sdl-config --libs)
 PLATFORM_CPPFLAGS += $(shell sdl-config --cflags)
 endif
-endif
 
 cmd_u-boot__ = $(CC) -o $@ -Wl,-T u-boot.lds $(u-boot-init) \
 	-Wl,--start-group $(u-boot-main) -Wl,--end-group \
diff --git a/arch/sandbox/cpu/sdl.c b/arch/sandbox/cpu/sdl.c
index f668f53..080c7c8 100644
--- a/arch/sandbox/cpu/sdl.c
+++ b/arch/sandbox/cpu/sdl.c
@@ -6,7 +6,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include <linux/input.h>
-#include <SDL/SDL.h>
+#include <SDL.h>
 #include <asm/state.h>
 
 /**
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index ae3189e..a41b5f0 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -100,11 +100,13 @@
 		eeprom@2c {
 			reg = <0x2c>;
 			compatible = "i2c-eeprom";
+			sandbox,emul = <&emul_eeprom>;
 		};
 
 		rtc_0: rtc@43 {
 			reg = <0x43>;
 			compatible = "sandbox-rtc";
+			sandbox,emul = <&emul0>;
 		};
 		sandbox_pmic: sandbox_pmic {
 			reg = <0x40>;
@@ -115,18 +117,14 @@
 		};
 
 		i2c_emul: emul {
-			#address-cells = <1>;
-			#size-cells = <0>;
 			reg = <0xff>;
 			compatible = "sandbox,i2c-emul-parent";
-			emul-eeprom {
-				reg = <0x2c>;
+			emul_eeprom: emul-eeprom {
 				compatible = "sandbox,i2c-eeprom";
 				sandbox,filename = "i2c.bin";
 				sandbox,size = <256>;
 			};
-			emul0 {
-				reg = <0x43>;
+			emul0: emul0 {
 				compatible = "sandbox,i2c-rtc";
 			};
 		};
diff --git a/arch/sandbox/dts/sandbox64.dts b/arch/sandbox/dts/sandbox64.dts
index d30fd62..a3c95f2 100644
--- a/arch/sandbox/dts/sandbox64.dts
+++ b/arch/sandbox/dts/sandbox64.dts
@@ -90,11 +90,13 @@
 		eeprom@2c {
 			reg = <0x2c>;
 			compatible = "i2c-eeprom";
+			sandbox,emul = <&emul_eeprom>;
 		};
 
 		rtc_0: rtc@43 {
 			reg = <0x43>;
 			compatible = "sandbox-rtc";
+			sandbox,emul = <&emul0>;
 		};
 		sandbox_pmic: sandbox_pmic {
 			reg = <0x40>;
@@ -107,12 +109,12 @@
 		i2c_emul: emul {
 			reg = <0xff>;
 			compatible = "sandbox,i2c-emul-parent";
-			emul-eeprom {
+			emul_eeprom: emul-eeprom {
 				compatible = "sandbox,i2c-eeprom";
 				sandbox,filename = "i2c.bin";
 				sandbox,size = <256>;
 			};
-			emul0 {
+			emul0: emul0 {
 				compatible = "sandbox,i2c-rtc";
 			};
 		};
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 3790b4c..1d011de 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -315,6 +315,12 @@
 		};
 	};
 
+	bootcount@0 {
+		compatible = "u-boot,bootcount-rtc";
+		rtc = <&rtc_1>;
+		offset = <0x13>;
+	};
+
 	adc@0 {
 		compatible = "sandbox,adc";
 		vdd-supply = <&buck2>;
diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h
index 81b7750..2a350a8 100644
--- a/arch/sandbox/include/asm/io.h
+++ b/arch/sandbox/include/asm/io.h
@@ -173,6 +173,18 @@
 {
 }
 
+static inline void memset_io(volatile void *addr, unsigned char val, int count)
+{
+}
+
+static inline void memcpy_fromio(void *dst, const volatile void *src, int count)
+{
+}
+
+static inline void memcpy_toio(volatile void *dst, const void *src, int count)
+{
+}
+
 #define insw(port, buf, ns)		_insw((u16 *)port, buf, ns)
 #define outsw(port, buf, ns)		_outsw((u16 *)port, buf, ns)
 
diff --git a/arch/x86/cpu/qemu/Kconfig b/arch/x86/cpu/qemu/Kconfig
index fdf558d..f8f2f64 100644
--- a/arch/x86/cpu/qemu/Kconfig
+++ b/arch/x86/cpu/qemu/Kconfig
@@ -28,7 +28,7 @@
 	hex
 	default 0xe400
 	help
-	  ACPI Power Managment 1 (PM1) i/o-mapped base address.
+	  ACPI Power Management 1 (PM1) i/o-mapped base address.
 	  This device is defined in ACPI specification, with 16 bytes in size.
 
 endif
diff --git a/arch/x86/cpu/quark/Kconfig b/arch/x86/cpu/quark/Kconfig
index 3a18cb0..430cce1 100644
--- a/arch/x86/cpu/quark/Kconfig
+++ b/arch/x86/cpu/quark/Kconfig
@@ -84,7 +84,7 @@
 	hex
 	default 0x1000
 	help
-	  ACPI Power Managment 1 (PM1) i/o-mapped base address.
+	  ACPI Power Management 1 (PM1) i/o-mapped base address.
 	  This device is defined in ACPI specification, with 16 bytes in size.
 
 config ACPI_PBLK_BASE
diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c
index 79bc200..04058a6 100644
--- a/arch/x86/lib/acpi_table.c
+++ b/arch/x86/lib/acpi_table.c
@@ -342,6 +342,7 @@
 	struct acpi_table_header *header = &(spcr->header);
 	struct serial_device_info serial_info = {0};
 	ulong serial_address, serial_offset;
+	struct udevice *dev;
 	uint serial_config;
 	uint serial_width;
 	int access_size;
@@ -353,7 +354,10 @@
 	header->length = sizeof(struct acpi_spcr);
 	header->revision = 2;
 
-	ret = serial_getinfo(&serial_info);
+	/* Read the device once, here. It is reused below */
+	ret = uclass_first_device_err(UCLASS_SERIAL, &dev);
+	if (!ret)
+		ret = serial_getinfo(dev, &serial_info);
 	if (ret)
 		serial_info.type = SERIAL_CHIP_UNKNOWN;
 
@@ -431,9 +435,9 @@
 		break;
 	}
 
-	ret = serial_getconfig(&serial_config);
-	if (ret)
-		serial_config = SERIAL_DEFAULT_CONFIG;
+	serial_config = SERIAL_DEFAULT_CONFIG;
+	if (dev)
+		ret = serial_getconfig(dev, &serial_config);
 
 	spcr->parity = SERIAL_GET_PARITY(serial_config);
 	spcr->stop_bits = SERIAL_GET_STOP(serial_config);
diff --git a/board/hisilicon/poplar/poplar.c b/board/hisilicon/poplar/poplar.c
index 8adc750..155dfbb 100644
--- a/board/hisilicon/poplar/poplar.c
+++ b/board/hisilicon/poplar/poplar.c
@@ -166,6 +166,34 @@
 	return ret;
 }
 
+#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
+#include <usb.h>
+#include <usb/dwc2_udc.h>
+#include <g_dnl.h>
+
+static struct dwc2_plat_otg_data poplar_otg_data = {
+	.regs_otg = HIOTG_BASE_ADDR
+};
+
+static void set_usb_to_device(void)
+{
+	setbits_le32(PERI_CTRL_USB3, USB2_2P_CHIPID);
+}
+
+int board_usb_init(int index, enum usb_init_type init)
+{
+	set_usb_to_device();
+	return dwc2_udc_probe(&poplar_otg_data);
+}
+
+int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
+{
+	if (!env_get("serial#"))
+		g_dnl_set_serialnumber("0123456789POPLAR");
+	return 0;
+}
+#endif
+
 int board_init(void)
 {
 	usb2_phy_init();
diff --git a/board/isee/igep00x0/Kconfig b/board/isee/igep00x0/Kconfig
index aa46882..597d6d9 100644
--- a/board/isee/igep00x0/Kconfig
+++ b/board/isee/igep00x0/Kconfig
@@ -9,4 +9,6 @@
 config SYS_CONFIG_NAME
 	default "omap3_igep00x0"
 
+source "board/ti/common/Kconfig"
+
 endif
diff --git a/board/isee/igep00x0/MAINTAINERS b/board/isee/igep00x0/MAINTAINERS
index d75d400..a07c9f4 100644
--- a/board/isee/igep00x0/MAINTAINERS
+++ b/board/isee/igep00x0/MAINTAINERS
@@ -4,4 +4,3 @@
 F:	board/isee/igep00x0/
 F:	include/configs/omap3_igep00x0.h
 F:	configs/igep00x0_defconfig
-F:	configs/igep0032_defconfig
diff --git a/board/mediatek/mt7623/mt7623_rfb.c b/board/mediatek/mt7623/mt7623_rfb.c
index 08468b5..4ec2764 100644
--- a/board/mediatek/mt7623/mt7623_rfb.c
+++ b/board/mediatek/mt7623/mt7623_rfb.c
@@ -14,3 +14,22 @@
 
 	return 0;
 }
+
+int mmc_get_boot_dev(void)
+{
+	int g_mmc_devid = -1;
+	char *uflag = (char *)0x81DFFFF0;
+	if (strncmp(uflag,"eMMC",4)==0) {
+		g_mmc_devid = 0;
+		printf("Boot From Emmc(id:%d)\n\n", g_mmc_devid);
+	} else {
+		g_mmc_devid = 1;
+		printf("Boot From SD(id:%d)\n\n", g_mmc_devid);
+	}
+	return g_mmc_devid;
+}
+
+int mmc_get_env_dev(void)
+{
+	return mmc_get_boot_dev();
+}
diff --git a/board/mscc/common/Makefile b/board/mscc/common/Makefile
new file mode 100644
index 0000000..4f0eded
--- /dev/null
+++ b/board/mscc/common/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+obj-$(CONFIG_SOC_JR2)	:= spi.o
+obj-$(CONFIG_SOC_OCELOT)	:= spi.o
diff --git a/board/mscc/common/spi.c b/board/mscc/common/spi.c
new file mode 100644
index 0000000..0566fcb
--- /dev/null
+++ b/board/mscc/common/spi.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Coprporation
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <spi.h>
+
+void external_cs_manage(struct udevice *dev, bool enable)
+{
+	u32 cs = spi_chip_select(dev);
+	/* IF_SI0_OWNER, select the owner of the SI interface
+	 * Encoding: 0: SI Slave
+	 *	     1: SI Boot Master
+	 *	     2: SI Master Controller
+	 */
+	if (!enable) {
+		writel(ICPU_SW_MODE_SW_PIN_CTRL_MODE |
+		       ICPU_SW_MODE_SW_SPI_CS(BIT(cs)),
+		       BASE_CFG + ICPU_SW_MODE);
+		clrsetbits_le32(BASE_CFG + ICPU_GENERAL_CTRL,
+				ICPU_GENERAL_CTRL_IF_SI_OWNER_M,
+				ICPU_GENERAL_CTRL_IF_SI_OWNER(2));
+	} else {
+		writel(0, BASE_CFG + ICPU_SW_MODE);
+		clrsetbits_le32(BASE_CFG + ICPU_GENERAL_CTRL,
+				ICPU_GENERAL_CTRL_IF_SI_OWNER_M,
+				ICPU_GENERAL_CTRL_IF_SI_OWNER(1));
+	}
+}
diff --git a/board/mscc/jr2/Kconfig b/board/mscc/jr2/Kconfig
new file mode 100644
index 0000000..68a2de8
--- /dev/null
+++ b/board/mscc/jr2/Kconfig
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+config SYS_VENDOR
+	default "mscc"
+
+if SOC_JR2
+
+config SYS_BOARD
+	default "jr2"
+
+config SYS_CONFIG_NAME
+	default "jr2"
+
+endif
+
diff --git a/board/mscc/jr2/Makefile b/board/mscc/jr2/Makefile
new file mode 100644
index 0000000..c1db2a9
--- /dev/null
+++ b/board/mscc/jr2/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+obj-$(CONFIG_SOC_JR2)	:= jr2.o
+
diff --git a/board/mscc/jr2/jr2.c b/board/mscc/jr2/jr2.c
new file mode 100644
index 0000000..eac4dca
--- /dev/null
+++ b/board/mscc/jr2/jr2.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <led.h>
+
+enum {
+	BOARD_TYPE_PCB110 = 0xAABBCE00,
+	BOARD_TYPE_PCB111,
+	BOARD_TYPE_PCB112,
+};
+
+int board_early_init_r(void)
+{
+	/* Prepare SPI controller to be used in master mode */
+	writel(0, BASE_CFG + ICPU_SW_MODE);
+	clrsetbits_le32(BASE_CFG + ICPU_GENERAL_CTRL,
+			ICPU_GENERAL_CTRL_IF_SI_OWNER_M,
+			ICPU_GENERAL_CTRL_IF_SI_OWNER(2));
+
+	/* Address of boot parameters */
+	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE;
+
+	/* LED setup */
+	if (IS_ENABLED(CONFIG_LED))
+		led_default_state();
+
+	return 0;
+}
+
+static void vcoreiii_gpio_set_alternate(int gpio, int mode)
+{
+	u32 mask;
+	u32 val0, val1;
+	void __iomem *reg0, *reg1;
+
+	if (gpio < 32) {
+		mask = BIT(gpio);
+		reg0 = BASE_DEVCPU_GCB + GPIO_GPIO_ALT(0);
+		reg1 = BASE_DEVCPU_GCB + GPIO_GPIO_ALT(1);
+	} else {
+		gpio -= 32;
+		mask = BIT(gpio);
+		reg0 = BASE_DEVCPU_GCB + GPIO_GPIO_ALT1(0);
+		reg1 = BASE_DEVCPU_GCB + GPIO_GPIO_ALT1(1);
+	}
+	val0 = readl(reg0);
+	val1 = readl(reg1);
+	if (mode == 1) {
+		writel(val0 | mask, reg0);
+		writel(val1 & ~mask, reg1);
+	} else if (mode == 2) {
+		writel(val0 & ~mask, reg0);
+		writel(val1 | mask, reg1);
+	} else if (mode == 3) {
+		writel(val0 | mask, reg0);
+		writel(val1 | mask, reg1);
+	} else {
+		writel(val0 & ~mask, reg0);
+		writel(val1 & ~mask, reg1);
+	}
+}
+
+static void do_board_detect(void)
+{
+	int i;
+	u16 pval;
+
+	/* MIIM 1 + 2  MDC/MDIO */
+	for (i = 56; i < 60; i++)
+		vcoreiii_gpio_set_alternate(i, 1);
+
+	if (mscc_phy_rd(0, 0x10, 0x3, &pval) == 0 &&
+	    ((pval >> 4) & 0x3F) == 0x3c) {
+		gd->board_type = BOARD_TYPE_PCB112; /* Serval2-NID */
+	} else if (mscc_phy_rd(1, 0x0, 0x3, &pval) == 0 &&
+		   ((pval >> 4) & 0x3F) == 0x3c) {
+		gd->board_type = BOARD_TYPE_PCB110; /* Jr2-24 */
+	} else {
+		/* Fall-back */
+		gd->board_type = BOARD_TYPE_PCB111; /* Jr2-48 */
+	}
+}
+
+#if defined(CONFIG_MULTI_DTB_FIT)
+int board_fit_config_name_match(const char *name)
+{
+	if (gd->board_type == BOARD_TYPE_PCB110 &&
+	    strcmp(name, "jr2_pcb110") == 0)
+		return 0;
+
+	if (gd->board_type == BOARD_TYPE_PCB111 &&
+	    strcmp(name, "jr2_pcb111") == 0)
+		return 0;
+
+	if (gd->board_type == BOARD_TYPE_PCB112 &&
+	    strcmp(name, "serval2_pcb112") == 0)
+		return 0;
+
+	return -1;
+}
+#endif
+
+#if defined(CONFIG_DTB_RESELECT)
+int embedded_dtb_select(void)
+{
+	do_board_detect();
+	fdtdec_setup();
+
+	return 0;
+}
+#endif
diff --git a/board/mscc/luton/luton.c b/board/mscc/luton/luton.c
index 41fc6d5..807c717 100644
--- a/board/mscc/luton/luton.c
+++ b/board/mscc/luton/luton.c
@@ -5,16 +5,20 @@
 
 #include <common.h>
 #include <asm/io.h>
-
-#define MSCC_GPIO_ALT0		0x88
-#define MSCC_GPIO_ALT1		0x8C
+#include <led.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+enum {
+	BOARD_TYPE_PCB090 = 0xAABBCD00,
+	BOARD_TYPE_PCB091,
+};
+
 void board_debug_uart_init(void)
 {
 	/* too early for the pinctrl driver, so configure the UART pins here */
-	setbits_le32(BASE_DEVCPU_GCB + MSCC_GPIO_ALT0, BIT(30) | BIT(31));
+	mscc_gpio_set_alternate(30, 1);
+	mscc_gpio_set_alternate(31, 1);
 }
 
 int board_early_init_r(void)
@@ -24,5 +28,45 @@
 
 	/* Address of boot parameters */
 	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE;
+
+	/* LED setup */
+	if (IS_ENABLED(CONFIG_LED))
+		led_default_state();
+
+	return 0;
+}
+
+static void do_board_detect(void)
+{
+	u32 chipid = (readl(BASE_DEVCPU_GCB + CHIP_ID) >> 12) & 0xFFFF;
+
+	if (chipid == 0x7428 || chipid == 0x7424)
+		gd->board_type = BOARD_TYPE_PCB091;    // Lu10
+	else
+		gd->board_type = BOARD_TYPE_PCB090;    // Lu26
+}
+
+#if defined(CONFIG_MULTI_DTB_FIT)
+int board_fit_config_name_match(const char *name)
+{
+	if (gd->board_type == BOARD_TYPE_PCB090 &&
+	    strcmp(name, "luton_pcb090") == 0)
+		return 0;
+
+	if (gd->board_type == BOARD_TYPE_PCB091 &&
+	    strcmp(name, "luton_pcb091") == 0)
+		return 0;
+
+	return -1;
+}
+#endif
+
+#if defined(CONFIG_DTB_RESELECT)
+int embedded_dtb_select(void)
+{
+	do_board_detect();
+	fdtdec_setup();
+
 	return 0;
 }
+#endif
diff --git a/board/mscc/ocelot/ocelot.c b/board/mscc/ocelot/ocelot.c
index d521a61..0f7a532 100644
--- a/board/mscc/ocelot/ocelot.c
+++ b/board/mscc/ocelot/ocelot.c
@@ -9,39 +9,20 @@
 #include <asm/types.h>
 #include <environment.h>
 #include <spi.h>
+#include <led.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#define MSCC_GPIO_ALT0		0x54
-#define MSCC_GPIO_ALT1		0x58
-
-void external_cs_manage(struct udevice *dev, bool enable)
-{
-	u32 cs = spi_chip_select(dev);
-	/* IF_SI0_OWNER, select the owner of the SI interface
-	 * Encoding: 0: SI Slave
-	 *           1: SI Boot Master
-	 *           2: SI Master Controller
-	 */
-	if (!enable) {
-		writel(ICPU_SW_MODE_SW_PIN_CTRL_MODE |
-		       ICPU_SW_MODE_SW_SPI_CS(BIT(cs)), BASE_CFG + ICPU_SW_MODE);
-		clrsetbits_le32(BASE_CFG + ICPU_GENERAL_CTRL,
-				ICPU_GENERAL_CTRL_IF_SI_OWNER_M,
-				ICPU_GENERAL_CTRL_IF_SI_OWNER(2));
-	} else {
-		writel(0, BASE_CFG + ICPU_SW_MODE);
-		clrsetbits_le32(BASE_CFG + ICPU_GENERAL_CTRL,
-				ICPU_GENERAL_CTRL_IF_SI_OWNER_M,
-				ICPU_GENERAL_CTRL_IF_SI_OWNER(1));
-	}
-}
+enum {
+	BOARD_TYPE_PCB120 = 0xAABBCC00,
+	BOARD_TYPE_PCB123,
+};
 
 void board_debug_uart_init(void)
 {
 	/* too early for the pinctrl driver, so configure the UART pins here */
-	setbits_le32(BASE_DEVCPU_GCB + MSCC_GPIO_ALT0, BIT(6) | BIT(7));
-	clrbits_le32(BASE_DEVCPU_GCB + MSCC_GPIO_ALT1, BIT(6) | BIT(7));
+	mscc_gpio_set_alternate(6, 1);
+	mscc_gpio_set_alternate(7, 1);
 }
 
 int board_early_init_r(void)
@@ -54,5 +35,48 @@
 
 	/* Address of boot parameters */
 	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE;
+
+	/* LED setup */
+	if (IS_ENABLED(CONFIG_LED))
+		led_default_state();
+
+	return 0;
+}
+
+static void do_board_detect(void)
+{
+	u16 dummy = 0;
+
+	/* Enable MIIM */
+	mscc_gpio_set_alternate(14, 1);
+	mscc_gpio_set_alternate(15, 1);
+	if (mscc_phy_rd(1, 0, 0, &dummy) == 0)
+		gd->board_type = BOARD_TYPE_PCB120;
+	else
+		gd->board_type = BOARD_TYPE_PCB123;
+}
+
+#if defined(CONFIG_MULTI_DTB_FIT)
+int board_fit_config_name_match(const char *name)
+{
+	if (gd->board_type == BOARD_TYPE_PCB120 &&
+	    strcmp(name, "ocelot_pcb120") == 0)
+		return 0;
+
+	if (gd->board_type == BOARD_TYPE_PCB123 &&
+	    strcmp(name, "ocelot_pcb123") == 0)
+		return 0;
+
+	return -1;
+}
+#endif
+
+#if defined(CONFIG_DTB_RESELECT)
+int embedded_dtb_select(void)
+{
+	do_board_detect();
+	fdtdec_setup();
+
 	return 0;
 }
+#endif
diff --git a/board/ti/am335x/MAINTAINERS b/board/ti/am335x/MAINTAINERS
index c99e06d..565f705 100644
--- a/board/ti/am335x/MAINTAINERS
+++ b/board/ti/am335x/MAINTAINERS
@@ -6,7 +6,4 @@
 F:	configs/am335x_boneblack_defconfig
 F:	configs/am335x_boneblack_vboot_defconfig
 F:	configs/am335x_evm_defconfig
-F:	configs/am335x_evm_nor_defconfig
-F:	configs/am335x_evm_norboot_defconfig
-F:	configs/am335x_evm_spiboot_defconfig
 F:	configs/am335x_evm_usbspl_defconfig
diff --git a/board/ti/am43xx/MAINTAINERS b/board/ti/am43xx/MAINTAINERS
index bf09806..ab9da22 100644
--- a/board/ti/am43xx/MAINTAINERS
+++ b/board/ti/am43xx/MAINTAINERS
@@ -4,7 +4,6 @@
 F:	board/ti/am43xx/
 F:	include/configs/am43xx_evm.h
 F:	configs/am43xx_evm_defconfig
-F:	configs/am43xx_evm_ethboot_defconfig
 F:	configs/am43xx_evm_qspiboot_defconfig
 F:	configs/am43xx_evm_usbhost_boot_defconfig
 F:	configs/am43xx_evm_rtconly_defconfig
diff --git a/board/work-microwave/work_92105/Kconfig b/board/work-microwave/work_92105/Kconfig
index 32632f5..380e2df 100644
--- a/board/work-microwave/work_92105/Kconfig
+++ b/board/work-microwave/work_92105/Kconfig
@@ -10,7 +10,7 @@
 	default "work_92105"
 
 config CMD_HD44760
-	bool "Enable 'hd44780' LCD-control comand"
+	bool "Enable 'hd44780' LCD-control command"
 	help
 	  This controls the LCD driver.
 
diff --git a/cmd/adc.c b/cmd/adc.c
index 2d635ac..381961c 100644
--- a/cmd/adc.c
+++ b/cmd/adc.c
@@ -146,37 +146,14 @@
 	return CMD_RET_SUCCESS;
 }
 
-static cmd_tbl_t cmd_adc_sub[] = {
-	U_BOOT_CMD_MKENT(list, 1, 1, do_adc_list, "", ""),
-	U_BOOT_CMD_MKENT(info, 2, 1, do_adc_info, "", ""),
-	U_BOOT_CMD_MKENT(single, 3, 1, do_adc_single, "", ""),
-	U_BOOT_CMD_MKENT(scan, 3, 1, do_adc_scan, "", ""),
-};
-
-static int do_adc(cmd_tbl_t *cmdtp, int flag, int argc,
-		  char *const argv[])
-{
-	cmd_tbl_t *c;
-
-	if (argc < 2)
-		return CMD_RET_USAGE;
-
-	/* Strip off leading 'adc' command argument */
-	argc--;
-	argv++;
-
-	c = find_cmd_tbl(argv[0], &cmd_adc_sub[0], ARRAY_SIZE(cmd_adc_sub));
-
-	if (c)
-		return c->cmd(cmdtp, flag, argc, argv);
-	else
-		return CMD_RET_USAGE;
-}
-
 static char adc_help_text[] =
 	"list - list ADC devices\n"
 	"adc info <name> - Get ADC device info\n"
 	"adc single <name> <channel> - Get Single data of ADC device channel\n"
 	"adc scan <name> [channel mask] - Scan all [or masked] ADC channels";
 
-U_BOOT_CMD(adc, 4, 1, do_adc, "ADC sub-system", adc_help_text);
+U_BOOT_CMD_WITH_SUBCMDS(adc, "ADC sub-system", adc_help_text,
+	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_adc_list),
+	U_BOOT_SUBCMD_MKENT(info, 2, 1, do_adc_info),
+	U_BOOT_SUBCMD_MKENT(single, 3, 1, do_adc_single),
+	U_BOOT_SUBCMD_MKENT(scan, 3, 1, do_adc_scan));
diff --git a/cmd/dtimg.c b/cmd/dtimg.c
index 65c8d10..ae7d82f 100644
--- a/cmd/dtimg.c
+++ b/cmd/dtimg.c
@@ -116,7 +116,7 @@
 
 	if (!cp || argc > cp->maxargs)
 		return CMD_RET_USAGE;
-	if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
+	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
 		return CMD_RET_SUCCESS;
 
 	return cp->cmd(cmdtp, flag, argc, argv);
diff --git a/cmd/gpio.c b/cmd/gpio.c
index ecdc453..c60946b 100644
--- a/cmd/gpio.c
+++ b/cmd/gpio.c
@@ -213,7 +213,7 @@
 		}
 		gpio_direction_output(gpio, value);
 	}
-	printf("gpio: pin %s (gpio %i) value is ", str_gpio, gpio);
+	printf("gpio: pin %s (gpio %u) value is ", str_gpio, gpio);
 	if (IS_ERR_VALUE(value))
 		printf("unknown (ret=%d)\n", value);
 	else
diff --git a/cmd/help.c b/cmd/help.c
index 503fa63..fa2010c 100644
--- a/cmd/help.c
+++ b/cmd/help.c
@@ -29,7 +29,7 @@
 
 /* This does not use the U_BOOT_CMD macro as ? can't be used in symbol names */
 ll_entry_declare(cmd_tbl_t, question_mark, cmd) = {
-	"?",	CONFIG_SYS_MAXARGS,	1,	do_help,
+	"?",	CONFIG_SYS_MAXARGS, cmd_always_repeatable,	do_help,
 	"alias for 'help'",
 #ifdef  CONFIG_SYS_LONGHELP
 	""
diff --git a/cmd/mmc.c b/cmd/mmc.c
index 3920a18..8bc3648 100644
--- a/cmd/mmc.c
+++ b/cmd/mmc.c
@@ -101,10 +101,19 @@
 		return NULL;
 	}
 
+	if (!mmc_getcd(mmc))
+		force_init = true;
+
 	if (force_init)
 		mmc->has_init = 0;
 	if (mmc_init(mmc))
 		return NULL;
+
+#ifdef CONFIG_BLOCK_CACHE
+	struct blk_desc *bd = mmc_get_blk_desc(mmc);
+	blkcache_invalidate(bd->if_type, bd->devnum);
+#endif
+
 	return mmc;
 }
 static int do_mmcinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
@@ -247,7 +256,7 @@
 
 	if (cp == NULL || argc > cp->maxargs)
 		return CMD_RET_USAGE;
-	if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
+	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
 		return CMD_RET_SUCCESS;
 
 	mmc = init_mmc_device(curr_device, false);
@@ -907,7 +916,7 @@
 
 	if (cp == NULL || argc > cp->maxargs)
 		return CMD_RET_USAGE;
-	if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
+	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
 		return CMD_RET_SUCCESS;
 
 	if (curr_device < 0) {
diff --git a/cmd/mtd.c b/cmd/mtd.c
index 6142223..1b6b8dd 100644
--- a/cmd/mtd.c
+++ b/cmd/mtd.c
@@ -15,6 +15,22 @@
 #include <mapmem.h>
 #include <mtd.h>
 
+#include <linux/ctype.h>
+
+static struct mtd_info *get_mtd_by_name(const char *name)
+{
+	struct mtd_info *mtd;
+
+	mtd_probe_devices();
+
+	mtd = get_mtd_device_nm(name);
+	if (IS_ERR_OR_NULL(mtd))
+		printf("MTD device %s not found, ret %ld\n", name,
+		       PTR_ERR(mtd));
+
+	return mtd;
+}
+
 static uint mtd_len_to_pages(struct mtd_info *mtd, u64 len)
 {
 	do_div(len, mtd->writesize);
@@ -177,7 +193,8 @@
 	return true;
 }
 
-static int do_mtd_list(void)
+static int do_mtd_list(cmd_tbl_t *cmdtp, int flag, int argc,
+		       char * const argv[])
 {
 	struct mtd_info *mtd;
 	int dev_nb = 0;
@@ -221,231 +238,289 @@
 	return ret;
 }
 
-static int do_mtd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int do_mtd_io(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
+	bool dump, read, raw, woob, write_empty_pages, has_pages = false;
+	u64 start_off, off, len, remaining, default_len;
+	struct mtd_oob_ops io_op = {};
+	uint user_addr = 0, npages;
+	const char *cmd = argv[0];
 	struct mtd_info *mtd;
-	const char *cmd;
-	char *mtd_name;
+	u32 oob_len;
+	u8 *buf;
+	int ret;
 
-	/* All MTD commands need at least two arguments */
 	if (argc < 2)
 		return CMD_RET_USAGE;
 
-	/* Parse the command name and its optional suffixes */
-	cmd = argv[1];
+	mtd = get_mtd_by_name(argv[1]);
+	if (IS_ERR_OR_NULL(mtd))
+		return CMD_RET_FAILURE;
 
-	/* List the MTD devices if that is what the user wants */
-	if (strcmp(cmd, "list") == 0)
-		return do_mtd_list();
+	if (mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH)
+		has_pages = true;
 
-	/*
-	 * The remaining commands require also at least a device ID.
-	 * Check the selected device is valid. Ensure it is probed.
-	 */
-	if (argc < 3)
-		return CMD_RET_USAGE;
+	dump = !strncmp(cmd, "dump", 4);
+	read = dump || !strncmp(cmd, "read", 4);
+	raw = strstr(cmd, ".raw");
+	woob = strstr(cmd, ".oob");
+	write_empty_pages = !has_pages || strstr(cmd, ".dontskipff");
 
-	mtd_name = argv[2];
-	mtd_probe_devices();
-	mtd = get_mtd_device_nm(mtd_name);
-	if (IS_ERR_OR_NULL(mtd)) {
-		printf("MTD device %s not found, ret %ld\n",
-		       mtd_name, PTR_ERR(mtd));
-		return CMD_RET_FAILURE;
+	argc -= 2;
+	argv += 2;
+
+	if (!dump) {
+		if (!argc) {
+			ret = CMD_RET_USAGE;
+			goto out_put_mtd;
+		}
+
+		user_addr = simple_strtoul(argv[0], NULL, 16);
+		argc--;
+		argv++;
 	}
-	put_mtd_device(mtd);
 
-	argc -= 3;
-	argv += 3;
+	start_off = argc > 0 ? simple_strtoul(argv[0], NULL, 16) : 0;
+	if (!mtd_is_aligned_with_min_io_size(mtd, start_off)) {
+		printf("Offset not aligned with a page (0x%x)\n",
+		       mtd->writesize);
+		ret = CMD_RET_FAILURE;
+		goto out_put_mtd;
+	}
 
-	/* Do the parsing */
-	if (!strncmp(cmd, "read", 4) || !strncmp(cmd, "dump", 4) ||
-	    !strncmp(cmd, "write", 5)) {
-		bool has_pages = mtd->type == MTD_NANDFLASH ||
-				 mtd->type == MTD_MLCNANDFLASH;
-		bool dump, read, raw, woob, write_empty_pages;
-		struct mtd_oob_ops io_op = {};
-		uint user_addr = 0, npages;
-		u64 start_off, off, len, remaining, default_len;
-		u32 oob_len;
-		u8 *buf;
-		int ret;
+	default_len = dump ? mtd->writesize : mtd->size;
+	len = argc > 1 ? simple_strtoul(argv[1], NULL, 16) : default_len;
+	if (!mtd_is_aligned_with_min_io_size(mtd, len)) {
+		len = round_up(len, mtd->writesize);
+		printf("Size not on a page boundary (0x%x), rounding to 0x%llx\n",
+		       mtd->writesize, len);
+	}
 
-		dump = !strncmp(cmd, "dump", 4);
-		read = dump || !strncmp(cmd, "read", 4);
-		raw = strstr(cmd, ".raw");
-		woob = strstr(cmd, ".oob");
-		write_empty_pages = !has_pages || strstr(cmd, ".dontskipff");
+	remaining = len;
+	npages = mtd_len_to_pages(mtd, len);
+	oob_len = woob ? npages * mtd->oobsize : 0;
 
-		if (!dump) {
-			if (!argc)
-				return CMD_RET_USAGE;
+	if (dump)
+		buf = kmalloc(len + oob_len, GFP_KERNEL);
+	else
+		buf = map_sysmem(user_addr, 0);
 
-			user_addr = simple_strtoul(argv[0], NULL, 16);
-			argc--;
-			argv++;
-		}
+	if (!buf) {
+		printf("Could not map/allocate the user buffer\n");
+		ret = CMD_RET_FAILURE;
+		goto out_put_mtd;
+	}
 
-		start_off = argc > 0 ? simple_strtoul(argv[0], NULL, 16) : 0;
-		if (!mtd_is_aligned_with_min_io_size(mtd, start_off)) {
-			printf("Offset not aligned with a page (0x%x)\n",
-			       mtd->writesize);
-			return CMD_RET_FAILURE;
-		}
+	if (has_pages)
+		printf("%s %lld byte(s) (%d page(s)) at offset 0x%08llx%s%s%s\n",
+		       read ? "Reading" : "Writing", len, npages, start_off,
+		       raw ? " [raw]" : "", woob ? " [oob]" : "",
+		       !read && write_empty_pages ? " [dontskipff]" : "");
+	else
+		printf("%s %lld byte(s) at offset 0x%08llx\n",
+		       read ? "Reading" : "Writing", len, start_off);
 
-		default_len = dump ? mtd->writesize : mtd->size;
-		len = argc > 1 ? simple_strtoul(argv[1], NULL, 16) :
-				 default_len;
-		if (!mtd_is_aligned_with_min_io_size(mtd, len)) {
-			len = round_up(len, mtd->writesize);
-			printf("Size not on a page boundary (0x%x), rounding to 0x%llx\n",
-			       mtd->writesize, len);
-		}
+	io_op.mode = raw ? MTD_OPS_RAW : MTD_OPS_AUTO_OOB;
+	io_op.len = has_pages ? mtd->writesize : len;
+	io_op.ooblen = woob ? mtd->oobsize : 0;
+	io_op.datbuf = buf;
+	io_op.oobbuf = woob ? &buf[len] : NULL;
 
-		remaining = len;
-		npages = mtd_len_to_pages(mtd, len);
-		oob_len = woob ? npages * mtd->oobsize : 0;
+	/* Search for the first good block after the given offset */
+	off = start_off;
+	while (mtd_block_isbad(mtd, off))
+		off += mtd->erasesize;
 
-		if (dump)
-			buf = kmalloc(len + oob_len, GFP_KERNEL);
+	/* Loop over the pages to do the actual read/write */
+	while (remaining) {
+		/* Skip the block if it is bad */
+		if (mtd_is_aligned_with_block_size(mtd, off) &&
+		    mtd_block_isbad(mtd, off)) {
+			off += mtd->erasesize;
+			continue;
+		}
+
+		if (read)
+			ret = mtd_read_oob(mtd, off, &io_op);
 		else
-			buf = map_sysmem(user_addr, 0);
+			ret = mtd_special_write_oob(mtd, off, &io_op,
+						    write_empty_pages, woob);
 
-		if (!buf) {
-			printf("Could not map/allocate the user buffer\n");
-			return CMD_RET_FAILURE;
+		if (ret) {
+			printf("Failure while %s at offset 0x%llx\n",
+			       read ? "reading" : "writing", off);
+			break;
 		}
 
-		if (has_pages)
-			printf("%s %lld byte(s) (%d page(s)) at offset 0x%08llx%s%s%s\n",
-			       read ? "Reading" : "Writing", len, npages, start_off,
-			       raw ? " [raw]" : "", woob ? " [oob]" : "",
-			       !read && write_empty_pages ? " [dontskipff]" : "");
-		else
-			printf("%s %lld byte(s) at offset 0x%08llx\n",
-			       read ? "Reading" : "Writing", len, start_off);
+		off += io_op.retlen;
+		remaining -= io_op.retlen;
+		io_op.datbuf += io_op.retlen;
+		io_op.oobbuf += io_op.oobretlen;
+	}
 
-		io_op.mode = raw ? MTD_OPS_RAW : MTD_OPS_AUTO_OOB;
-		io_op.len = has_pages ? mtd->writesize : len;
-		io_op.ooblen = woob ? mtd->oobsize : 0;
-		io_op.datbuf = buf;
-		io_op.oobbuf = woob ? &buf[len] : NULL;
+	if (!ret && dump)
+		mtd_dump_device_buf(mtd, start_off, buf, len, woob);
 
-		/* Search for the first good block after the given offset */
-		off = start_off;
-		while (mtd_block_isbad(mtd, off))
-			off += mtd->erasesize;
+	if (dump)
+		kfree(buf);
+	else
+		unmap_sysmem(buf);
 
-		/* Loop over the pages to do the actual read/write */
-		while (remaining) {
-			/* Skip the block if it is bad */
-			if (mtd_is_aligned_with_block_size(mtd, off) &&
-			    mtd_block_isbad(mtd, off)) {
-				off += mtd->erasesize;
-				continue;
-			}
+	if (ret) {
+		printf("%s on %s failed with error %d\n",
+		       read ? "Read" : "Write", mtd->name, ret);
+		ret = CMD_RET_FAILURE;
+	} else {
+		ret = CMD_RET_SUCCESS;
+	}
 
-			if (read)
-				ret = mtd_read_oob(mtd, off, &io_op);
-			else
-				ret = mtd_special_write_oob(mtd, off, &io_op,
-							    write_empty_pages,
-							    woob);
+out_put_mtd:
+	put_mtd_device(mtd);
 
-			if (ret) {
-				printf("Failure while %s at offset 0x%llx\n",
-				       read ? "reading" : "writing", off);
-				return CMD_RET_FAILURE;
-			}
+	return ret;
+}
 
-			off += io_op.retlen;
-			remaining -= io_op.retlen;
-			io_op.datbuf += io_op.retlen;
-			io_op.oobbuf += io_op.oobretlen;
-		}
+static int do_mtd_erase(cmd_tbl_t *cmdtp, int flag, int argc,
+			char * const argv[])
+{
+	struct erase_info erase_op = {};
+	struct mtd_info *mtd;
+	u64 off, len;
+	bool scrub;
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
 
-		if (!ret && dump)
-			mtd_dump_device_buf(mtd, start_off, buf, len, woob);
+	mtd = get_mtd_by_name(argv[1]);
+	if (IS_ERR_OR_NULL(mtd))
+		return CMD_RET_FAILURE;
 
-		if (dump)
-			kfree(buf);
-		else
-			unmap_sysmem(buf);
+	scrub = strstr(argv[0], ".dontskipbad");
 
-		if (ret) {
-			printf("%s on %s failed with error %d\n",
-			       read ? "Read" : "Write", mtd->name, ret);
-			return CMD_RET_FAILURE;
-		}
+	argc -= 2;
+	argv += 2;
 
-	} else if (!strcmp(cmd, "erase")) {
-		bool scrub = strstr(cmd, ".dontskipbad");
-		struct erase_info erase_op = {};
-		u64 off, len;
-		int ret;
+	off = argc > 0 ? simple_strtoul(argv[0], NULL, 16) : 0;
+	len = argc > 1 ? simple_strtoul(argv[1], NULL, 16) : mtd->size;
 
-		off = argc > 0 ? simple_strtoul(argv[0], NULL, 16) : 0;
-		len = argc > 1 ? simple_strtoul(argv[1], NULL, 16) : mtd->size;
+	if (!mtd_is_aligned_with_block_size(mtd, off)) {
+		printf("Offset not aligned with a block (0x%x)\n",
+		       mtd->erasesize);
+		ret = CMD_RET_FAILURE;
+		goto out_put_mtd;
+	}
 
-		if (!mtd_is_aligned_with_block_size(mtd, off)) {
-			printf("Offset not aligned with a block (0x%x)\n",
-			       mtd->erasesize);
-			return CMD_RET_FAILURE;
-		}
+	if (!mtd_is_aligned_with_block_size(mtd, len)) {
+		printf("Size not a multiple of a block (0x%x)\n",
+		       mtd->erasesize);
+		ret = CMD_RET_FAILURE;
+		goto out_put_mtd;
+	}
 
-		if (!mtd_is_aligned_with_block_size(mtd, len)) {
-			printf("Size not a multiple of a block (0x%x)\n",
-			       mtd->erasesize);
-			return CMD_RET_FAILURE;
-		}
+	printf("Erasing 0x%08llx ... 0x%08llx (%d eraseblock(s))\n",
+	       off, off + len - 1, mtd_div_by_eb(len, mtd));
 
-		printf("Erasing 0x%08llx ... 0x%08llx (%d eraseblock(s))\n",
-		       off, off + len - 1, mtd_div_by_eb(len, mtd));
+	erase_op.mtd = mtd;
+	erase_op.addr = off;
+	erase_op.len = len;
+	erase_op.scrub = scrub;
 
-		erase_op.mtd = mtd;
-		erase_op.addr = off;
-		erase_op.len = len;
-		erase_op.scrub = scrub;
+	while (erase_op.len) {
+		ret = mtd_erase(mtd, &erase_op);
 
-		while (erase_op.len) {
-			ret = mtd_erase(mtd, &erase_op);
+		/* Abort if its not a bad block error */
+		if (ret != -EIO)
+			break;
 
-			/* Abort if its not a bad block error */
-			if (ret != -EIO)
-				break;
+		printf("Skipping bad block at 0x%08llx\n", erase_op.fail_addr);
 
-			printf("Skipping bad block at 0x%08llx\n",
-			       erase_op.fail_addr);
+		/* Skip bad block and continue behind it */
+		erase_op.len -= erase_op.fail_addr - erase_op.addr;
+		erase_op.len -= mtd->erasesize;
+		erase_op.addr = erase_op.fail_addr + mtd->erasesize;
+	}
 
-			/* Skip bad block and continue behind it */
-			erase_op.len -= erase_op.fail_addr - erase_op.addr;
-			erase_op.len -= mtd->erasesize;
-			erase_op.addr = erase_op.fail_addr + mtd->erasesize;
-		}
+	if (ret && ret != -EIO)
+		ret = CMD_RET_FAILURE;
+	else
+		ret = CMD_RET_SUCCESS;
 
-		if (ret && ret != -EIO)
-			return CMD_RET_FAILURE;
-	} else if (!strcmp(cmd, "bad")) {
-		loff_t off;
+out_put_mtd:
+	put_mtd_device(mtd);
 
-		if (!mtd_can_have_bb(mtd)) {
-			printf("Only NAND-based devices can have bad blocks\n");
-			return CMD_RET_SUCCESS;
-		}
+	return ret;
+}
 
-		printf("MTD device %s bad blocks list:\n", mtd->name);
-		for (off = 0; off < mtd->size; off += mtd->erasesize)
-			if (mtd_block_isbad(mtd, off))
-				printf("\t0x%08llx\n", off);
-	} else {
+static int do_mtd_bad(cmd_tbl_t *cmdtp, int flag, int argc,
+		      char * const argv[])
+{
+	struct mtd_info *mtd;
+	loff_t off;
+
+	if (argc < 2)
 		return CMD_RET_USAGE;
+
+	mtd = get_mtd_by_name(argv[1]);
+	if (IS_ERR_OR_NULL(mtd))
+		return CMD_RET_FAILURE;
+
+	if (!mtd_can_have_bb(mtd)) {
+		printf("Only NAND-based devices can have bad blocks\n");
+		goto out_put_mtd;
+	}
+
+	printf("MTD device %s bad blocks list:\n", mtd->name);
+	for (off = 0; off < mtd->size; off += mtd->erasesize) {
+		if (mtd_block_isbad(mtd, off))
+			printf("\t0x%08llx\n", off);
 	}
 
+out_put_mtd:
+	put_mtd_device(mtd);
+
 	return CMD_RET_SUCCESS;
 }
 
-static char mtd_help_text[] =
+#ifdef CONFIG_AUTO_COMPLETE
+static int mtd_name_complete(int argc, char * const argv[], char last_char,
+			     int maxv, char *cmdv[])
+{
+	int len = 0, n_found = 0;
+	struct mtd_info *mtd;
+
+	argc--;
+	argv++;
+
+	if (argc > 1 ||
+	    (argc == 1 && (last_char == '\0' || isblank(last_char))))
+		return 0;
+
+	if (argc)
+		len = strlen(argv[0]);
+
+	mtd_for_each_device(mtd) {
+		if (argc &&
+		    (len > strlen(mtd->name) ||
+		     strncmp(argv[0], mtd->name, len)))
+			continue;
+
+		if (n_found >= maxv - 2) {
+			cmdv[n_found++] = "...";
+			break;
+		}
+
+		cmdv[n_found++] = mtd->name;
+	}
+
+	cmdv[n_found] = NULL;
+
+	return n_found;
+}
+#endif /* CONFIG_AUTO_COMPLETE */
+
 #ifdef CONFIG_SYS_LONGHELP
+static char mtd_help_text[] =
 	"- generic operations on memory technology devices\n\n"
 	"mtd list\n"
 	"mtd read[.raw][.oob]                  <name> <addr> [<off> [<size>]]\n"
@@ -466,8 +541,18 @@
 	"\t\t* must be a multiple of a block for erase\n"
 	"\t\t* must be a multiple of a page otherwise (special case: default is a page with dump)\n"
 	"\n"
-	"The .dontskipff option forces writing empty pages, don't use it if unsure.\n"
+	"The .dontskipff option forces writing empty pages, don't use it if unsure.\n";
 #endif
-	"";
 
-U_BOOT_CMD(mtd, 10, 1, do_mtd, "MTD utils", mtd_help_text);
+U_BOOT_CMD_WITH_SUBCMDS(mtd, "MTD utils", mtd_help_text,
+		U_BOOT_SUBCMD_MKENT(list, 1, 1, do_mtd_list),
+		U_BOOT_SUBCMD_MKENT_COMPLETE(read, 5, 0, do_mtd_io,
+					     mtd_name_complete),
+		U_BOOT_SUBCMD_MKENT_COMPLETE(write, 5, 0, do_mtd_io,
+					     mtd_name_complete),
+		U_BOOT_SUBCMD_MKENT_COMPLETE(dump, 4, 0, do_mtd_io,
+					     mtd_name_complete),
+		U_BOOT_SUBCMD_MKENT_COMPLETE(erase, 4, 0, do_mtd_erase,
+					     mtd_name_complete),
+		U_BOOT_SUBCMD_MKENT_COMPLETE(bad, 2, 1, do_mtd_bad,
+					     mtd_name_complete));
diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index de16c72..ebaa16b 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -708,8 +708,8 @@
 		if (n)
 			*--buf = '\0';
 
-		printf("env_buf [%d bytes] too small for value of \"%s\"\n",
-			len, name);
+		printf("env_buf [%u bytes] too small for value of \"%s\"\n",
+		       len, name);
 
 		return n;
 	}
diff --git a/cmd/sf.c b/cmd/sf.c
index 84bb057..738ef0e 100644
--- a/cmd/sf.c
+++ b/cmd/sf.c
@@ -413,7 +413,7 @@
 		do_div(speed, test->time_ms[stage] * 1024);
 	bps = speed * 8;
 
-	printf("%d %s: %d ticks, %d KiB/s %d.%03d Mbps\n", stage,
+	printf("%d %s: %u ticks, %d KiB/s %d.%03d Mbps\n", stage,
 	       stage_name[stage], test->time_ms[stage],
 	       (int)speed, bps / 1000, bps % 1000);
 }
diff --git a/cmd/tpm-v2.c b/cmd/tpm-v2.c
index bb51834..459a955 100644
--- a/cmd/tpm-v2.c
+++ b/cmd/tpm-v2.c
@@ -151,7 +151,7 @@
 
 	rc = tpm2_pcr_read(dev, index, priv->pcr_select_min, data, &updates);
 	if (!rc) {
-		printf("PCR #%u content (%d known updates):\n", index, updates);
+		printf("PCR #%u content (%u known updates):\n", index, updates);
 		print_byte_string(data, TPM2_DIGEST_LEN);
 	}
 
diff --git a/cmd/ubi.c b/cmd/ubi.c
index a12ac70..c511a2f 100644
--- a/cmd/ubi.c
+++ b/cmd/ubi.c
@@ -472,12 +472,8 @@
 	if (argc < 2)
 		return CMD_RET_USAGE;
 
-	if (strcmp(argv[1], "detach") == 0) {
-		if (argc < 2)
-			return CMD_RET_USAGE;
-
+	if (strcmp(argv[1], "detach") == 0)
 		return ubi_detach();
-	}
 
 	if (strcmp(argv[1], "part") == 0) {
 		const char *vid_header_offset = NULL;
diff --git a/cmd/unzip.c b/cmd/unzip.c
index f7aabf7..6c0f97c 100644
--- a/cmd/unzip.c
+++ b/cmd/unzip.c
@@ -27,7 +27,7 @@
 	if (gunzip((void *) dst, dst_len, (void *) src, &src_len) != 0)
 		return 1;
 
-	printf("Uncompressed size: %ld = 0x%lX\n", src_len, src_len);
+	printf("Uncompressed size: %lu = 0x%lX\n", src_len, src_len);
 	env_set_hex("filesize", src_len);
 
 	return 0;
diff --git a/cmd/zip.c b/cmd/zip.c
index d105d84..9cd400a 100644
--- a/cmd/zip.c
+++ b/cmd/zip.c
@@ -28,7 +28,7 @@
 	if (gzip((void *) dst, &dst_len, (void *) src, src_len) != 0)
 		return 1;
 
-	printf("Compressed size: %ld = 0x%lX\n", dst_len, dst_len);
+	printf("Compressed size: %lu = 0x%lX\n", dst_len, dst_len);
 	env_set_hex("filesize", dst_len);
 
 	return 0;
diff --git a/common/Kconfig b/common/Kconfig
index 57bd16d..2c017df 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -308,7 +308,7 @@
 	help
 	  This option allows the console to be silenced, meaning that no
 	  output will appear on the console devices. This is controlled by
-	  setting the environment vaariable 'silent' to a non-empty value.
+	  setting the environment variable 'silent' to a non-empty value.
 	  Note this also silences the console when booting Linux.
 
 	  When the console is set up, the variable is checked, and the
@@ -430,7 +430,7 @@
 	help
 	  Normally U-Boot displays the current settings for stdout, stdin
 	  and stderr on boot when the post-relocation console is set up.
-	  Enable this option to supress this output. It can be obtained by
+	  Enable this option to suppress this output. It can be obtained by
 	  calling stdio_print_current_devices() from board code.
 
 config SYS_STDIO_DEREGISTER
@@ -565,14 +565,14 @@
 	  This enables a 'log test' command to test logging. It is normally
 	  executed from a pytest and simply outputs logging information
 	  in various different ways to test that the logging system works
-	  correctly with varoius settings.
+	  correctly with various settings.
 
 config LOG_ERROR_RETURN
 	bool "Log all functions which return an error"
 	depends on LOG
 	help
 	  When an error is returned in U-Boot it is sometimes difficult to
-	  figure out the root cause. For eaxmple, reading from SPI flash may
+	  figure out the root cause. For example, reading from SPI flash may
 	  fail due to a problem in the SPI controller or due to the flash part
 	  not returning the expected information. This option changes
 	  log_ret() to log any errors it sees. With this option disabled,
@@ -661,7 +661,7 @@
 	  With this option U-Boot will call arch_misc_init() after
 	  relocation to allow miscellaneous arch-dependent initialisation
 	  to be performed. This function should be defined by the board
-	  and will be called after the console is set up, after relocaiton.
+	  and will be called after the console is set up, after relocation.
 
 config BOARD_EARLY_INIT_F
 	bool "Call board-specific init before relocation"
diff --git a/common/bootm.c b/common/bootm.c
index 8bf84eb..a4618b6 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -56,15 +56,11 @@
 	ulong		mem_start;
 	phys_size_t	mem_size;
 
-	lmb_init(&images->lmb);
-
 	mem_start = env_get_bootm_low();
 	mem_size = env_get_bootm_size();
 
-	lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
-
-	arch_lmb_reserve(&images->lmb);
-	board_lmb_reserve(&images->lmb);
+	lmb_init_and_reserve(&images->lmb, (phys_addr_t)mem_start, mem_size,
+			     NULL);
 }
 #else
 #define lmb_reserve(lmb, base, size)
@@ -262,7 +258,8 @@
 		puts("Could not find a valid device tree\n");
 		return 1;
 	}
-	set_working_fdt_addr(map_to_sysmem(images.ft_addr));
+	if (CONFIG_IS_ENABLED(CMD_FDT))
+		set_working_fdt_addr(map_to_sysmem(images.ft_addr));
 #endif
 
 #if IMAGE_ENABLE_FIT
diff --git a/common/command.c b/common/command.c
index 2433a89..e14d1fa 100644
--- a/common/command.c
+++ b/common/command.c
@@ -142,30 +142,45 @@
 }
 
 #ifdef CONFIG_AUTO_COMPLETE
+static char env_complete_buf[512];
 
 int var_complete(int argc, char * const argv[], char last_char, int maxv, char *cmdv[])
 {
-	static char tmp_buf[512];
 	int space;
 
 	space = last_char == '\0' || isblank(last_char);
 
 	if (space && argc == 1)
-		return env_complete("", maxv, cmdv, sizeof(tmp_buf), tmp_buf);
+		return env_complete("", maxv, cmdv, sizeof(env_complete_buf),
+				    env_complete_buf, false);
 
 	if (!space && argc == 2)
-		return env_complete(argv[1], maxv, cmdv, sizeof(tmp_buf), tmp_buf);
+		return env_complete(argv[1], maxv, cmdv,
+				    sizeof(env_complete_buf),
+				    env_complete_buf, false);
 
 	return 0;
 }
 
+static int dollar_complete(int argc, char * const argv[], char last_char,
+			   int maxv, char *cmdv[])
+{
+	/* Make sure the last argument starts with a $. */
+	if (argc < 1 || argv[argc - 1][0] != '$' ||
+	    last_char == '\0' || isblank(last_char))
+		return 0;
+
+	return env_complete(argv[argc - 1], maxv, cmdv, sizeof(env_complete_buf),
+			    env_complete_buf, true);
+}
+
 /*************************************************************************************/
 
-static int complete_cmdv(int argc, char * const argv[], char last_char, int maxv, char *cmdv[])
+int complete_subcmdv(cmd_tbl_t *cmdtp, int count, int argc,
+		     char * const argv[], char last_char,
+		     int maxv, char *cmdv[])
 {
 #ifdef CONFIG_CMDLINE
-	cmd_tbl_t *cmdtp = ll_entry_start(cmd_tbl_t, cmd);
-	const int count = ll_entry_count(cmd_tbl_t, cmd);
 	const cmd_tbl_t *cmdend = cmdtp + count;
 	const char *p;
 	int len, clen;
@@ -193,7 +208,7 @@
 
 	/* more than one arg or one but the start of the next */
 	if (argc > 1 || last_char == '\0' || isblank(last_char)) {
-		cmdtp = find_cmd(argv[0]);
+		cmdtp = find_cmd_tbl(argv[0], cmdtp, count);
 		if (cmdtp == NULL || cmdtp->complete == NULL) {
 			cmdv[0] = NULL;
 			return 0;
@@ -238,6 +253,18 @@
 #endif
 }
 
+static int complete_cmdv(int argc, char * const argv[], char last_char,
+			 int maxv, char *cmdv[])
+{
+#ifdef CONFIG_CMDLINE
+	return complete_subcmdv(ll_entry_start(cmd_tbl_t, cmd),
+				ll_entry_count(cmd_tbl_t, cmd), argc, argv,
+				last_char, maxv, cmdv);
+#else
+	return 0;
+#endif
+}
+
 static int make_argv(char *s, int argvsz, char *argv[])
 {
 	int argc = 0;
@@ -345,9 +372,14 @@
 	/* separate into argv */
 	argc = make_argv(tmp_buf, sizeof(argv)/sizeof(argv[0]), argv);
 
-	/* do the completion and return the possible completions */
-	i = complete_cmdv(argc, argv, last_char,
-			  sizeof(cmdv) / sizeof(cmdv[0]), cmdv);
+	/* first try a $ completion */
+	i = dollar_complete(argc, argv, last_char,
+			    sizeof(cmdv) / sizeof(cmdv[0]), cmdv);
+	if (!i) {
+		/* do the completion and return the possible completions */
+		i = complete_cmdv(argc, argv, last_char,
+				  sizeof(cmdv) / sizeof(cmdv[0]), cmdv);
+	}
 
 	/* no match; bell and out */
 	if (i == 0) {
@@ -362,13 +394,21 @@
 	sep = NULL;
 	seplen = 0;
 	if (i == 1) { /* one match; perfect */
-		k = strlen(argv[argc - 1]);
+		if (last_char != '\0' && !isblank(last_char))
+			k = strlen(argv[argc - 1]);
+		else
+			k = 0;
+
 		s = cmdv[0] + k;
 		len = strlen(s);
 		sep = " ";
 		seplen = 1;
 	} else if (i > 1 && (j = find_common_prefix(cmdv)) != 0) { /* more */
-		k = strlen(argv[argc - 1]);
+		if (last_char != '\0' && !isblank(last_char))
+			k = strlen(argv[argc - 1]);
+		else
+			k = 0;
+
 		j -= k;
 		if (j > 0) {
 			s = cmdv[0] + k;
@@ -481,6 +521,30 @@
 }
 #endif
 
+int cmd_always_repeatable(cmd_tbl_t *cmdtp, int flag, int argc,
+			  char * const argv[], int *repeatable)
+{
+	*repeatable = 1;
+
+	return cmdtp->cmd(cmdtp, flag, argc, argv);
+}
+
+int cmd_never_repeatable(cmd_tbl_t *cmdtp, int flag, int argc,
+			 char * const argv[], int *repeatable)
+{
+	*repeatable = 0;
+
+	return cmdtp->cmd(cmdtp, flag, argc, argv);
+}
+
+int cmd_discard_repeatable(cmd_tbl_t *cmdtp, int flag, int argc,
+			   char * const argv[])
+{
+	int repeatable;
+
+	return cmdtp->cmd_rep(cmdtp, flag, argc, argv, &repeatable);
+}
+
 /**
  * Call a command function. This should be the only route in U-Boot to call
  * a command, so that we can track whether we are waiting for input or
@@ -490,13 +554,15 @@
  * @param flag		Some flags normally 0 (see CMD_FLAG_.. above)
  * @param argc		Number of arguments (arg 0 must be the command text)
  * @param argv		Arguments
+ * @param repeatable	Can the command be repeated
  * @return 0 if command succeeded, else non-zero (CMD_RET_...)
  */
-static int cmd_call(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int cmd_call(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
+		    int *repeatable)
 {
 	int result;
 
-	result = (cmdtp->cmd)(cmdtp, flag, argc, argv);
+	result = cmdtp->cmd_rep(cmdtp, flag, argc, argv, repeatable);
 	if (result)
 		debug("Command failed, result=%d\n", result);
 	return result;
@@ -533,12 +599,14 @@
 
 	/* If OK so far, then do the command */
 	if (!rc) {
+		int newrep;
+
 		if (ticks)
 			*ticks = get_timer(0);
-		rc = cmd_call(cmdtp, flag, argc, argv);
+		rc = cmd_call(cmdtp, flag, argc, argv, &newrep);
 		if (ticks)
 			*ticks = get_timer(*ticks);
-		*repeatable &= cmdtp->repeatable;
+		*repeatable &= newrep;
 	}
 	if (rc == CMD_RET_USAGE)
 		rc = cmd_usage(cmdtp);
diff --git a/common/fdt_support.c b/common/fdt_support.c
index 3440e42..42583e3 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -1025,7 +1025,7 @@
 	s  = fdt_read_number(range + na + pna, ns);
 	da = fdt_read_number(addr, na);
 
-	debug("OF: default map, cp=%llu, s=%llu, da=%llu\n", cp, s, da);
+	debug("OF: default map, cp=%llx, s=%llx, da=%llx\n", cp, s, da);
 
 	if (da < cp || da >= (cp + s))
 		return OF_BAD_ADDR;
@@ -1080,7 +1080,7 @@
 	s  = fdt_read_number(range + na + pna, ns);
 	da = fdt_read_number(addr + 1, na - 1);
 
-	debug("OF: ISA map, cp=%llu, s=%llu, da=%llu\n", cp, s, da);
+	debug("OF: ISA map, cp=%llx, s=%llx, da=%llx\n", cp, s, da);
 
 	if (da < cp || da >= (cp + s))
 		return OF_BAD_ADDR;
diff --git a/common/image-fdt.c b/common/image-fdt.c
index 95748f0..5988808 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -10,6 +10,7 @@
 
 #include <common.h>
 #include <fdt_support.h>
+#include <fdtdec.h>
 #include <errno.h>
 #include <image.h>
 #include <linux/libfdt.h>
@@ -67,30 +68,66 @@
 }
 #endif
 
+static void boot_fdt_reserve_region(struct lmb *lmb, uint64_t addr,
+				    uint64_t size)
+{
+	int ret;
+
+	ret = lmb_reserve(lmb, addr, size);
+	if (!ret) {
+		debug("   reserving fdt memory region: addr=%llx size=%llx\n",
+		      (unsigned long long)addr, (unsigned long long)size);
+	} else {
+		puts("ERROR: reserving fdt memory region failed ");
+		printf("(addr=%llx size=%llx)\n",
+		       (unsigned long long)addr, (unsigned long long)size);
+	}
+}
+
 /**
- * boot_fdt_add_mem_rsv_regions - Mark the memreserve sections as unusable
+ * boot_fdt_add_mem_rsv_regions - Mark the memreserve and reserved-memory
+ * sections as unusable
  * @lmb: pointer to lmb handle, will be used for memory mgmt
  * @fdt_blob: pointer to fdt blob base address
  *
- * Adds the memreserve regions in the dtb to the lmb block.  Adding the
- * memreserve regions prevents u-boot from using them to store the initrd
- * or the fdt blob.
+ * Adds the and reserved-memorymemreserve regions in the dtb to the lmb block.
+ * Adding the memreserve regions prevents u-boot from using them to store the
+ * initrd or the fdt blob.
  */
 void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob)
 {
 	uint64_t addr, size;
-	int i, total;
+	int i, total, ret;
+	int nodeoffset, subnode;
+	struct fdt_resource res;
 
 	if (fdt_check_header(fdt_blob) != 0)
 		return;
 
+	/* process memreserve sections */
 	total = fdt_num_mem_rsv(fdt_blob);
 	for (i = 0; i < total; i++) {
 		if (fdt_get_mem_rsv(fdt_blob, i, &addr, &size) != 0)
 			continue;
-		printf("   reserving fdt memory region: addr=%llx size=%llx\n",
-		       (unsigned long long)addr, (unsigned long long)size);
-		lmb_reserve(lmb, addr, size);
+		boot_fdt_reserve_region(lmb, addr, size);
+	}
+
+	/* process reserved-memory */
+	nodeoffset = fdt_subnode_offset(fdt_blob, 0, "reserved-memory");
+	if (nodeoffset >= 0) {
+		subnode = fdt_first_subnode(fdt_blob, nodeoffset);
+		while (subnode >= 0) {
+			/* check if this subnode has a reg property */
+			ret = fdt_get_resource(fdt_blob, subnode, "reg", 0,
+					       &res);
+			if (!ret) {
+				addr = res.start;
+				size = res.end - res.start + 1;
+				boot_fdt_reserve_region(lmb, addr, size);
+			}
+
+			subnode = fdt_next_subnode(fdt_blob, subnode);
+		}
 	}
 }
 
@@ -193,7 +230,8 @@
 	*of_flat_tree = of_start;
 	*of_size = of_len;
 
-	set_working_fdt_addr(map_to_sysmem(*of_flat_tree));
+	if (CONFIG_IS_ENABLED(CMD_FDT))
+		set_working_fdt_addr(map_to_sysmem(*of_flat_tree));
 	return 0;
 
 error:
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 37ecbc6..d175bb6 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -608,7 +608,7 @@
 	default "tpl/u-boot-with-tpl.bin" if TPL
 	default "u-boot.bin"
 	help
-	  Payload for SPL boot. For backward compability, default to
+	  Payload for SPL boot. For backward compatibility, default to
 	  u-boot.bin, i.e. RAW image without any header. In case of
 	  TPL, tpl/u-boot-with-tpl.bin. For new boards, suggest to
 	  use u-boot.img.
diff --git a/common/spl/spl_ymodem.c b/common/spl/spl_ymodem.c
index 3b1bd71..577fdc6 100644
--- a/common/spl/spl_ymodem.c
+++ b/common/spl/spl_ymodem.c
@@ -69,12 +69,13 @@
 static int spl_ymodem_load_image(struct spl_image_info *spl_image,
 				 struct spl_boot_device *bootdev)
 {
-	int size = 0;
+	ulong size = 0;
 	int err;
 	int res;
 	int ret;
 	connection_info_t info;
 	char buf[BUF_SIZE];
+	struct image_header *ih;
 	ulong addr = 0;
 
 	info.mode = xyzModem_ymodem;
@@ -107,12 +108,18 @@
 		while ((res = xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0)
 			size += res;
 	} else {
-		ret = spl_parse_image_header(spl_image,
-					     (struct image_header *)buf);
+		ih = (struct image_header *)buf;
+		ret = spl_parse_image_header(spl_image, ih);
 		if (ret)
 			return ret;
-		addr = spl_image->load_addr;
+#ifdef CONFIG_SPL_GZIP
+		if (ih->ih_comp == IH_COMP_GZIP)
+			addr = CONFIG_SYS_LOAD_ADDR;
+		else
+#endif
+			addr = spl_image->load_addr;
 		memcpy((void *)addr, buf, res);
+		ih = (struct image_header *)addr;
 		size += res;
 		addr += res;
 
@@ -121,13 +128,25 @@
 			size += res;
 			addr += res;
 		}
+
+#ifdef CONFIG_SPL_GZIP
+		if (ih->ih_comp == IH_COMP_GZIP) {
+			if (gunzip((void *)(spl_image->load_addr + sizeof(*ih)),
+				   CONFIG_SYS_BOOTM_LEN,
+				   (void *)(CONFIG_SYS_LOAD_ADDR + sizeof(*ih)),
+				   &size)) {
+				puts("Uncompressing error\n");
+				return -EIO;
+			}
+		}
+#endif
 	}
 
 end_stream:
 	xyzModem_stream_close(&err);
 	xyzModem_stream_terminate(false, &getcymodem);
 
-	printf("Loaded %d bytes\n", size);
+	printf("Loaded %lu bytes\n", size);
 	return 0;
 }
 SPL_LOAD_IMAGE_METHOD("UART", 0, BOOT_DEVICE_UART, spl_ymodem_load_image);
diff --git a/common/xyzModem.c b/common/xyzModem.c
index e5c65b4..e85da74 100644
--- a/common/xyzModem.c
+++ b/common/xyzModem.c
@@ -25,6 +25,7 @@
 #include <xyzModem.h>
 #include <stdarg.h>
 #include <u-boot/crc.h>
+#include <watchdog.h>
 
 /* Assumption - run xyzModem protocol over the console port */
 
@@ -63,6 +64,7 @@
 {
 
   ulong now = get_timer(0);
+  WATCHDOG_RESET();
   while (!tstc ())
     {
       if (get_timer(now) > xyzModem_CHAR_TIMEOUT)
diff --git a/configs/am335x_boneblack_defconfig b/configs/am335x_boneblack_defconfig
deleted file mode 100644
index 439d0cb..0000000
--- a/configs/am335x_boneblack_defconfig
+++ /dev/null
@@ -1,50 +0,0 @@
-CONFIG_ARM=y
-CONFIG_ARCH_OMAP2PLUS=y
-CONFIG_TI_COMMON_CMD_OPTIONS=y
-CONFIG_AM33XX=y
-CONFIG_SPL=y
-CONFIG_DISTRO_DEFAULTS=y
-CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT"
-CONFIG_BOOTCOMMAND="if test ${boot_fit} -eq 1; then run update_to_fit; fi; run findfdt; run init_console; run envboot; run distro_bootcmd"
-CONFIG_SYS_CONSOLE_INFO_QUIET=y
-CONFIG_VERSION_VARIABLE=y
-CONFIG_ARCH_MISC_INIT=y
-CONFIG_SPL_MUSB_NEW_SUPPORT=y
-# CONFIG_SPL_NAND_SUPPORT is not set
-CONFIG_SPL_OS_BOOT=y
-CONFIG_AUTOBOOT_KEYED=y
-CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n"
-CONFIG_AUTOBOOT_DELAY_STR="d"
-CONFIG_AUTOBOOT_STOP_STR=" "
-CONFIG_CMD_SPL=y
-# CONFIG_CMD_FLASH is not set
-# CONFIG_CMD_SETEXPR is not set
-CONFIG_ENV_IS_IN_MMC=y
-CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
-CONFIG_BOOTCOUNT_LIMIT=y
-CONFIG_DFU_TFTP=y
-CONFIG_DFU_MMC=y
-CONFIG_DFU_RAM=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_FASTBOOT_FLASH=y
-CONFIG_FASTBOOT_FLASH_MMC_DEV=1
-CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
-CONFIG_MMC_OMAP_HS=y
-CONFIG_SPI_FLASH=y
-CONFIG_SPI_FLASH_WINBOND=y
-CONFIG_MII=y
-CONFIG_DRIVER_TI_CPSW=y
-CONFIG_SPI=y
-CONFIG_OMAP3_SPI=y
-CONFIG_USB=y
-CONFIG_USB_MUSB_HOST=y
-CONFIG_USB_MUSB_GADGET=y
-CONFIG_USB_MUSB_DSPS=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
-CONFIG_USB_GADGET_VENDOR_NUM=0x0451
-CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
-CONFIG_USB_ETHER=y
-CONFIG_USBNET_HOST_ADDR="de:ad:be:af:00:00"
-CONFIG_LZO=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig
index 0931c1e..21c5bdb 100644
--- a/configs/am335x_evm_defconfig
+++ b/configs/am335x_evm_defconfig
@@ -37,6 +37,7 @@
 CONFIG_DM_MMC=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_NAND=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_DM_ETH=y
@@ -44,6 +45,7 @@
 CONFIG_MII=y
 CONFIG_DRIVER_TI_CPSW=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_OMAP3_SPI=y
 CONFIG_TIMER=y
 CONFIG_OMAP_TIMER=y
diff --git a/configs/am335x_evm_nor_defconfig b/configs/am335x_evm_nor_defconfig
deleted file mode 100644
index e08234e..0000000
--- a/configs/am335x_evm_nor_defconfig
+++ /dev/null
@@ -1,52 +0,0 @@
-CONFIG_ARM=y
-CONFIG_ARCH_OMAP2PLUS=y
-CONFIG_TI_COMMON_CMD_OPTIONS=y
-CONFIG_AM33XX=y
-CONFIG_NOR=y
-CONFIG_SPL=y
-CONFIG_DISTRO_DEFAULTS=y
-CONFIG_BOOTCOMMAND="if test ${boot_fit} -eq 1; then run update_to_fit; fi; run findfdt; run init_console; run envboot; run distro_bootcmd"
-CONFIG_SYS_CONSOLE_INFO_QUIET=y
-CONFIG_VERSION_VARIABLE=y
-CONFIG_ARCH_MISC_INIT=y
-CONFIG_SPL_MTD_SUPPORT=y
-CONFIG_SPL_MUSB_NEW_SUPPORT=y
-CONFIG_SPL_OS_BOOT=y
-CONFIG_CMD_SPL=y
-CONFIG_CMD_SPL_NAND_OFS=0x00080000
-CONFIG_CMD_NAND=y
-# CONFIG_CMD_SETEXPR is not set
-CONFIG_CMD_MTDPARTS=y
-CONFIG_MTDIDS_DEFAULT="nand0=nand.0"
-CONFIG_MTDPARTS_DEFAULT="mtdparts=nand.0:128k(NAND.SPL),128k(NAND.SPL.backup1),128k(NAND.SPL.backup2),128k(NAND.SPL.backup3),256k(NAND.u-boot-spl-os),1m(NAND.u-boot),128k(NAND.u-boot-env),128k(NAND.u-boot-env.backup1),8m(NAND.kernel),-(NAND.file-system)"
-CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
-CONFIG_BOOTCOUNT_LIMIT=y
-CONFIG_DFU_MMC=y
-CONFIG_DFU_NAND=y
-CONFIG_DFU_RAM=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_MMC_OMAP_HS=y
-CONFIG_MTD_NOR_FLASH=y
-CONFIG_FLASH_CFI_DRIVER=y
-CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
-CONFIG_FLASH_CFI_MTD=y
-CONFIG_SYS_FLASH_PROTECTION=y
-CONFIG_SYS_FLASH_CFI=y
-CONFIG_NAND=y
-CONFIG_SPI_FLASH=y
-CONFIG_SPI_FLASH_WINBOND=y
-CONFIG_MII=y
-CONFIG_DRIVER_TI_CPSW=y
-CONFIG_SPI=y
-CONFIG_OMAP3_SPI=y
-CONFIG_USB=y
-CONFIG_USB_MUSB_HOST=y
-CONFIG_USB_MUSB_GADGET=y
-CONFIG_USB_MUSB_DSPS=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
-CONFIG_USB_GADGET_VENDOR_NUM=0x0451
-CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
-CONFIG_USB_ETHER=y
-CONFIG_LZO=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/am335x_evm_norboot_defconfig b/configs/am335x_evm_norboot_defconfig
deleted file mode 100644
index 040384f..0000000
--- a/configs/am335x_evm_norboot_defconfig
+++ /dev/null
@@ -1,49 +0,0 @@
-CONFIG_ARM=y
-# CONFIG_SYS_THUMB_BUILD is not set
-CONFIG_ARCH_OMAP2PLUS=y
-CONFIG_SYS_TEXT_BASE=0x08000000
-CONFIG_TI_COMMON_CMD_OPTIONS=y
-CONFIG_AM33XX=y
-CONFIG_NOR=y
-CONFIG_DISTRO_DEFAULTS=y
-CONFIG_NOR_BOOT=y
-CONFIG_BOOTCOMMAND="if test ${boot_fit} -eq 1; then run update_to_fit; fi; run findfdt; run init_console; run envboot; run distro_bootcmd"
-CONFIG_SYS_CONSOLE_INFO_QUIET=y
-CONFIG_VERSION_VARIABLE=y
-CONFIG_ARCH_MISC_INIT=y
-CONFIG_BOARD_EARLY_INIT_F=y
-# CONFIG_CMD_SETEXPR is not set
-CONFIG_CMD_MTDPARTS=y
-CONFIG_MTDIDS_DEFAULT="nor0=physmap-flash.0"
-CONFIG_MTDPARTS_DEFAULT="mtdparts=physmap-flash.0:512k(u-boot),128k(u-boot-env1),128k(u-boot-env2),4m(kernel),-(rootfs)"
-CONFIG_ENV_IS_IN_FLASH=y
-CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
-CONFIG_DFU_MMC=y
-CONFIG_DFU_RAM=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_MMC_OMAP_HS=y
-CONFIG_MTD_NOR_FLASH=y
-CONFIG_MTD_DEVICE=y
-CONFIG_FLASH_CFI_DRIVER=y
-CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
-CONFIG_FLASH_CFI_MTD=y
-CONFIG_SYS_FLASH_PROTECTION=y
-CONFIG_SYS_FLASH_CFI=y
-CONFIG_SPI_FLASH=y
-CONFIG_SPI_FLASH_WINBOND=y
-CONFIG_MII=y
-CONFIG_DRIVER_TI_CPSW=y
-CONFIG_SPI=y
-CONFIG_OMAP3_SPI=y
-CONFIG_USB=y
-CONFIG_USB_MUSB_HOST=y
-CONFIG_USB_MUSB_GADGET=y
-CONFIG_USB_MUSB_DSPS=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
-CONFIG_USB_GADGET_VENDOR_NUM=0x0451
-CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
-CONFIG_USB_ETHER=y
-CONFIG_USBNET_HOST_ADDR="de:ad:be:af:00:00"
-CONFIG_LZO=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/am335x_evm_spiboot_defconfig b/configs/am335x_evm_spiboot_defconfig
deleted file mode 100644
index 1f430ad..0000000
--- a/configs/am335x_evm_spiboot_defconfig
+++ /dev/null
@@ -1,47 +0,0 @@
-CONFIG_ARM=y
-CONFIG_ARCH_OMAP2PLUS=y
-CONFIG_TI_COMMON_CMD_OPTIONS=y
-CONFIG_AM33XX=y
-CONFIG_SPL=y
-CONFIG_SPL_SPI_FLASH_SUPPORT=y
-CONFIG_SPL_SPI_SUPPORT=y
-CONFIG_DISTRO_DEFAULTS=y
-CONFIG_SYS_EXTRA_OPTIONS="SPI_BOOT"
-CONFIG_SPI_BOOT=y
-CONFIG_BOOTCOMMAND="if test ${boot_fit} -eq 1; then run update_to_fit; fi; run findfdt; run init_console; run envboot; run distro_bootcmd"
-CONFIG_SYS_CONSOLE_INFO_QUIET=y
-CONFIG_VERSION_VARIABLE=y
-CONFIG_ARCH_MISC_INIT=y
-CONFIG_SPL_MUSB_NEW_SUPPORT=y
-# CONFIG_SPL_NAND_SUPPORT is not set
-CONFIG_SPL_SPI_LOAD=y
-# CONFIG_CMD_FLASH is not set
-# CONFIG_CMD_SETEXPR is not set
-CONFIG_CMD_MTDPARTS=y
-CONFIG_MTDIDS_DEFAULT="nor0=m25p80-flash.0"
-CONFIG_MTDPARTS_DEFAULT="mtdparts=m25p80-flash.0:128k(SPL),512k(u-boot),128k(u-boot-env1),128k(u-boot-env2),3464k(kernel),-(rootfs)"
-CONFIG_ENV_IS_IN_SPI_FLASH=y
-CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
-CONFIG_BOOTCOUNT_LIMIT=y
-CONFIG_DFU_MMC=y
-CONFIG_DFU_RAM=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_MMC_OMAP_HS=y
-CONFIG_MTD_DEVICE=y
-CONFIG_SPI_FLASH=y
-CONFIG_SPI_FLASH_WINBOND=y
-CONFIG_MII=y
-CONFIG_DRIVER_TI_CPSW=y
-CONFIG_SPI=y
-CONFIG_OMAP3_SPI=y
-CONFIG_USB=y
-CONFIG_USB_MUSB_HOST=y
-CONFIG_USB_MUSB_GADGET=y
-CONFIG_USB_MUSB_DSPS=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
-CONFIG_USB_GADGET_VENDOR_NUM=0x0451
-CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
-CONFIG_USB_ETHER=y
-CONFIG_LZO=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/am335x_hs_evm_defconfig b/configs/am335x_hs_evm_defconfig
index 1a7c5cf..b158fd1 100644
--- a/configs/am335x_hs_evm_defconfig
+++ b/configs/am335x_hs_evm_defconfig
@@ -43,6 +43,7 @@
 # CONFIG_MMC_HW_PARTITIONING is not set
 CONFIG_MMC_OMAP_HS=y
 CONFIG_NAND=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_DM_ETH=y
@@ -50,6 +51,7 @@
 CONFIG_MII=y
 CONFIG_DRIVER_TI_CPSW=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_OMAP3_SPI=y
 CONFIG_TIMER=y
 CONFIG_OMAP_TIMER=y
diff --git a/configs/am335x_hs_evm_uart_defconfig b/configs/am335x_hs_evm_uart_defconfig
index 147da80..e5f54a0 100644
--- a/configs/am335x_hs_evm_uart_defconfig
+++ b/configs/am335x_hs_evm_uart_defconfig
@@ -45,6 +45,7 @@
 # CONFIG_MMC_HW_PARTITIONING is not set
 CONFIG_MMC_OMAP_HS=y
 CONFIG_NAND=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_DM_ETH=y
@@ -52,6 +53,7 @@
 CONFIG_MII=y
 CONFIG_DRIVER_TI_CPSW=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_OMAP3_SPI=y
 CONFIG_TIMER=y
 CONFIG_OMAP_TIMER=y
diff --git a/configs/am335x_igep003x_defconfig b/configs/am335x_igep003x_defconfig
index 186c65f..0a8fead 100644
--- a/configs/am335x_igep003x_defconfig
+++ b/configs/am335x_igep003x_defconfig
@@ -41,6 +41,9 @@
 # CONFIG_CMD_UBIFS is not set
 CONFIG_ENV_IS_IN_UBI=y
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DEFAULT_DEVICE_TREE="am335x-base0033"
+CONFIG_OF_CONTROL=y
+CONFIG_DM_MMC=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_NAND=y
 CONFIG_MTD_UBI_FASTMAP=y
diff --git a/configs/am335x_pdu001_defconfig b/configs/am335x_pdu001_defconfig
index e93c411..2a8d318 100644
--- a/configs/am335x_pdu001_defconfig
+++ b/configs/am335x_pdu001_defconfig
@@ -50,6 +50,5 @@
 CONFIG_DM_REGULATOR_FIXED=y
 CONFIG_DM_REGULATOR_TPS65910=y
 CONFIG_CONS_INDEX=4
-CONFIG_SPI=y
 # CONFIG_USE_TINY_PRINTF is not set
 # CONFIG_EFI_LOADER is not set
diff --git a/configs/am335x_sl50_defconfig b/configs/am335x_sl50_defconfig
index 822f73d..8c62247 100644
--- a/configs/am335x_sl50_defconfig
+++ b/configs/am335x_sl50_defconfig
@@ -40,6 +40,9 @@
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
 CONFIG_BOOTCOUNT_LIMIT=y
+CONFIG_DEFAULT_DEVICE_TREE="am335x-sl50"
+CONFIG_OF_CONTROL=y
+CONFIG_DM_MMC=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_MII=y
 CONFIG_DRIVER_TI_CPSW=y
diff --git a/configs/am43xx_evm_ethboot_defconfig b/configs/am43xx_evm_ethboot_defconfig
deleted file mode 100644
index c1b32be..0000000
--- a/configs/am43xx_evm_ethboot_defconfig
+++ /dev/null
@@ -1,64 +0,0 @@
-CONFIG_ARM=y
-CONFIG_ARCH_OMAP2PLUS=y
-CONFIG_AM43XX=y
-CONFIG_SPL=y
-CONFIG_DISTRO_DEFAULTS=y
-CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=1"
-# CONFIG_USE_BOOTCOMMAND is not set
-CONFIG_SYS_CONSOLE_INFO_QUIET=y
-# CONFIG_MISC_INIT_R is not set
-CONFIG_VERSION_VARIABLE=y
-# CONFIG_SPL_SYS_MALLOC_SIMPLE is not set
-CONFIG_SPL_ETH_SUPPORT=y
-CONFIG_SPL_MTD_SUPPORT=y
-CONFIG_SPL_NET_SUPPORT=y
-CONFIG_SPL_NET_VCI_STRING="AM43xx U-Boot SPL"
-CONFIG_SPL_OS_BOOT=y
-CONFIG_CMD_SPL=y
-CONFIG_CMD_SPL_NAND_OFS=0x00100000
-CONFIG_CMD_SPL_WRITE_SIZE=0x40000
-CONFIG_CMD_ASKENV=y
-CONFIG_CMD_EEPROM=y
-CONFIG_CMD_DFU=y
-# CONFIG_CMD_FLASH is not set
-CONFIG_CMD_GPIO=y
-CONFIG_CMD_GPT=y
-CONFIG_CMD_I2C=y
-CONFIG_CMD_MMC=y
-CONFIG_CMD_NAND=y
-CONFIG_CMD_SF=y
-CONFIG_CMD_SPI=y
-CONFIG_CMD_USB=y
-# CONFIG_CMD_SETEXPR is not set
-CONFIG_CMD_EXT4_WRITE=y
-CONFIG_CMD_MTDPARTS=y
-CONFIG_MTDIDS_DEFAULT="nand0=nand.0"
-CONFIG_MTDPARTS_DEFAULT="mtdparts=nand.0:256k(NAND.SPL),256k(NAND.SPL.backup1),256k(NAND.SPL.backup2),256k(NAND.SPL.backup3),512k(NAND.u-boot-spl-os),1m(NAND.u-boot),256k(NAND.u-boot-env),256k(NAND.u-boot-env.backup1),7m(NAND.kernel),-(NAND.file-system)"
-CONFIG_ENV_IS_IN_FAT=y
-CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
-CONFIG_DFU_MMC=y
-CONFIG_DFU_RAM=y
-CONFIG_DFU_SF=y
-CONFIG_MMC_OMAP_HS=y
-CONFIG_NAND=y
-CONFIG_SPI_FLASH=y
-CONFIG_SPI_FLASH_MACRONIX=y
-CONFIG_MII=y
-CONFIG_DRIVER_TI_CPSW=y
-CONFIG_SYS_NS16550=y
-CONFIG_SPI=y
-CONFIG_TI_QSPI=y
-CONFIG_USB=y
-CONFIG_USB_XHCI_HCD=y
-CONFIG_USB_XHCI_DWC3=y
-CONFIG_USB_DWC3=y
-CONFIG_USB_DWC3_GADGET=y
-CONFIG_USB_DWC3_OMAP=y
-CONFIG_USB_DWC3_PHY_OMAP=y
-CONFIG_OMAP_USB_PHY=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
-CONFIG_USB_GADGET_VENDOR_NUM=0x0403
-CONFIG_USB_GADGET_PRODUCT_NUM=0xbd00
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/am57xx_evm_defconfig b/configs/am57xx_evm_defconfig
index 91293da..51dedc6 100644
--- a/configs/am57xx_evm_defconfig
+++ b/configs/am57xx_evm_defconfig
@@ -25,6 +25,7 @@
 # CONFIG_SPL_NAND_SUPPORT is not set
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_SPI_LOAD=y
+CONFIG_SPL_YMODEM_SUPPORT=y
 CONFIG_CMD_SPL=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
diff --git a/configs/bcm968380gerg_ram_defconfig b/configs/bcm968380gerg_ram_defconfig
index 8b2b318..fdecc0f 100644
--- a/configs/bcm968380gerg_ram_defconfig
+++ b/configs/bcm968380gerg_ram_defconfig
@@ -26,7 +26,6 @@
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_LOADS is not set
 # CONFIG_CMD_MISC is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="brcm,bcm968380gerg"
 # CONFIG_NET is not set
 # CONFIG_DM_DEVICE_REMOVE is not set
diff --git a/configs/boston32r2_defconfig b/configs/boston32r2_defconfig
index 2d52f52..3d8d972 100644
--- a/configs/boston32r2_defconfig
+++ b/configs/boston32r2_defconfig
@@ -23,7 +23,6 @@
 CONFIG_CMD_EXT4_WRITE=y
 # CONFIG_DOS_PARTITION is not set
 # CONFIG_ISO_PARTITION is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="img,boston"
 CONFIG_ENV_IS_IN_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/boston32r2el_defconfig b/configs/boston32r2el_defconfig
index 2e2beed..6650211 100644
--- a/configs/boston32r2el_defconfig
+++ b/configs/boston32r2el_defconfig
@@ -24,7 +24,6 @@
 CONFIG_CMD_EXT4_WRITE=y
 # CONFIG_DOS_PARTITION is not set
 # CONFIG_ISO_PARTITION is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="img,boston"
 CONFIG_ENV_IS_IN_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/boston32r6_defconfig b/configs/boston32r6_defconfig
index 07613bf..b916460 100644
--- a/configs/boston32r6_defconfig
+++ b/configs/boston32r6_defconfig
@@ -24,7 +24,6 @@
 CONFIG_CMD_EXT4_WRITE=y
 # CONFIG_DOS_PARTITION is not set
 # CONFIG_ISO_PARTITION is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="img,boston"
 CONFIG_ENV_IS_IN_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/boston32r6el_defconfig b/configs/boston32r6el_defconfig
index 14d9aa1..6bf0027 100644
--- a/configs/boston32r6el_defconfig
+++ b/configs/boston32r6el_defconfig
@@ -25,7 +25,6 @@
 CONFIG_CMD_EXT4_WRITE=y
 # CONFIG_DOS_PARTITION is not set
 # CONFIG_ISO_PARTITION is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="img,boston"
 CONFIG_ENV_IS_IN_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/boston64r2_defconfig b/configs/boston64r2_defconfig
index 310c4a9..250a70d 100644
--- a/configs/boston64r2_defconfig
+++ b/configs/boston64r2_defconfig
@@ -24,7 +24,6 @@
 CONFIG_CMD_EXT4_WRITE=y
 # CONFIG_DOS_PARTITION is not set
 # CONFIG_ISO_PARTITION is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="img,boston"
 CONFIG_ENV_IS_IN_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/boston64r2el_defconfig b/configs/boston64r2el_defconfig
index 3b39df1..84c4e53 100644
--- a/configs/boston64r2el_defconfig
+++ b/configs/boston64r2el_defconfig
@@ -25,7 +25,6 @@
 CONFIG_CMD_EXT4_WRITE=y
 # CONFIG_DOS_PARTITION is not set
 # CONFIG_ISO_PARTITION is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="img,boston"
 CONFIG_ENV_IS_IN_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/boston64r6_defconfig b/configs/boston64r6_defconfig
index a0779b8..133a0a9 100644
--- a/configs/boston64r6_defconfig
+++ b/configs/boston64r6_defconfig
@@ -24,7 +24,6 @@
 CONFIG_CMD_EXT4_WRITE=y
 # CONFIG_DOS_PARTITION is not set
 # CONFIG_ISO_PARTITION is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="img,boston"
 CONFIG_ENV_IS_IN_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/boston64r6el_defconfig b/configs/boston64r6el_defconfig
index 3cdd1de..8c97dca 100644
--- a/configs/boston64r6el_defconfig
+++ b/configs/boston64r6el_defconfig
@@ -25,7 +25,6 @@
 CONFIG_CMD_EXT4_WRITE=y
 # CONFIG_DOS_PARTITION is not set
 # CONFIG_ISO_PARTITION is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="img,boston"
 CONFIG_ENV_IS_IN_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/ci20_mmc_defconfig b/configs/ci20_mmc_defconfig
index c1b1c3f..9602c8c 100644
--- a/configs/ci20_mmc_defconfig
+++ b/configs/ci20_mmc_defconfig
@@ -1,5 +1,4 @@
 CONFIG_MIPS=y
-CONFIG_SPL_LDSCRIPT="arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds"
 CONFIG_SYS_TEXT_BASE=0x80010000
 CONFIG_SPL_GPIO_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
diff --git a/configs/comtrend_ar5315u_ram_defconfig b/configs/comtrend_ar5315u_ram_defconfig
index 1b8e4e4..f6f0977 100644
--- a/configs/comtrend_ar5315u_ram_defconfig
+++ b/configs/comtrend_ar5315u_ram_defconfig
@@ -31,7 +31,6 @@
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,ar-5315u"
 CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
diff --git a/configs/comtrend_ar5387un_ram_defconfig b/configs/comtrend_ar5387un_ram_defconfig
index 5ba401a..8304552 100644
--- a/configs/comtrend_ar5387un_ram_defconfig
+++ b/configs/comtrend_ar5387un_ram_defconfig
@@ -31,7 +31,6 @@
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,ar-5387un"
 CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
diff --git a/configs/comtrend_ct5361_ram_defconfig b/configs/comtrend_ct5361_ram_defconfig
index 6297e78..b87a161 100644
--- a/configs/comtrend_ct5361_ram_defconfig
+++ b/configs/comtrend_ct5361_ram_defconfig
@@ -28,7 +28,6 @@
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,ct-5361"
 CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
diff --git a/configs/comtrend_vr3032u_ram_defconfig b/configs/comtrend_vr3032u_ram_defconfig
index 47f5399..0c27bfc 100644
--- a/configs/comtrend_vr3032u_ram_defconfig
+++ b/configs/comtrend_vr3032u_ram_defconfig
@@ -29,7 +29,6 @@
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,vr-3032u"
 CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
diff --git a/configs/comtrend_wap5813n_ram_defconfig b/configs/comtrend_wap5813n_ram_defconfig
index fd5107b..9e5f9ed 100644
--- a/configs/comtrend_wap5813n_ram_defconfig
+++ b/configs/comtrend_wap5813n_ram_defconfig
@@ -28,7 +28,6 @@
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,wap-5813n"
 CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
diff --git a/configs/gardena-smart-gateway-mt7688-ram_defconfig b/configs/gardena-smart-gateway-mt7688-ram_defconfig
index ae8bf29..bfd9bad 100644
--- a/configs/gardena-smart-gateway-mt7688-ram_defconfig
+++ b/configs/gardena-smart-gateway-mt7688-ram_defconfig
@@ -33,8 +33,8 @@
 CONFIG_CMD_TIME=y
 CONFIG_CMD_UUID=y
 CONFIG_CMD_MTDPARTS=y
-CONFIG_MTDIDS_DEFAULT="spi-nand0=gd5f,nor0=spi0.0"
-CONFIG_MTDPARTS_DEFAULT="spi0.0:640k(uboot),64k(uboot_env0),64k(uboot_env1),64k(factory),-(unused);gd5f:-(nand)"
+CONFIG_MTDIDS_DEFAULT="spi-nand0=spi0.1,nor0=spi0.0"
+CONFIG_MTDPARTS_DEFAULT="spi0.0:640k(uboot),64k(uboot_env0),64k(uboot_env1),64k(factory),-(unused);spi0.1:-(nand)"
 CONFIG_CMD_UBI=y
 CONFIG_DEFAULT_DEVICE_TREE="gardena-smart-gateway-mt7688"
 CONFIG_ENV_IS_IN_SPI_FLASH=y
diff --git a/configs/gardena-smart-gateway-mt7688_defconfig b/configs/gardena-smart-gateway-mt7688_defconfig
index b7024e3..d844932 100644
--- a/configs/gardena-smart-gateway-mt7688_defconfig
+++ b/configs/gardena-smart-gateway-mt7688_defconfig
@@ -36,8 +36,8 @@
 CONFIG_CMD_TIME=y
 CONFIG_CMD_UUID=y
 CONFIG_CMD_MTDPARTS=y
-CONFIG_MTDIDS_DEFAULT="spi-nand0=gd5f,nor0=spi0.0"
-CONFIG_MTDPARTS_DEFAULT="spi0.0:640k(uboot),64k(uboot_env0),64k(uboot_env1),64k(factory),-(unused);gd5f:-(nand)"
+CONFIG_MTDIDS_DEFAULT="spi-nand0=spi0.1,nor0=spi0.0"
+CONFIG_MTDPARTS_DEFAULT="spi0.0:640k(uboot),64k(uboot_env0),64k(uboot_env1),64k(factory),-(unused);spi0.1:-(nand)"
 CONFIG_CMD_UBI=y
 CONFIG_DEFAULT_DEVICE_TREE="gardena-smart-gateway-mt7688"
 CONFIG_ENV_IS_IN_SPI_FLASH=y
diff --git a/configs/hikey_defconfig b/configs/hikey_defconfig
index 3bc5ceb..e9a9857 100644
--- a/configs/hikey_defconfig
+++ b/configs/hikey_defconfig
@@ -18,6 +18,7 @@
 CONFIG_ENV_IS_IN_FAT=y
 CONFIG_ENV_FAT_INTERFACE="mmc"
 CONFIG_ENV_FAT_DEVICE_AND_PART="1:1"
+CONFIG_DM_MMC=y
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_K3=y
 CONFIG_CONS_INDEX=4
diff --git a/configs/huawei_hg556a_ram_defconfig b/configs/huawei_hg556a_ram_defconfig
index d4e6144..1d4b833 100644
--- a/configs/huawei_hg556a_ram_defconfig
+++ b/configs/huawei_hg556a_ram_defconfig
@@ -28,7 +28,6 @@
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="huawei,hg556a"
 CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
diff --git a/configs/igep0032_defconfig b/configs/igep0032_defconfig
deleted file mode 100644
index 20d2cf5..0000000
--- a/configs/igep0032_defconfig
+++ /dev/null
@@ -1,53 +0,0 @@
-CONFIG_ARM=y
-CONFIG_ARCH_OMAP2PLUS=y
-CONFIG_TARGET_OMAP3_IGEP00X0=y
-CONFIG_SPL=y
-CONFIG_DISTRO_DEFAULTS=y
-CONFIG_NR_DRAM_BANKS=2
-CONFIG_OF_BOARD_SETUP=y
-CONFIG_BOOTDELAY=3
-CONFIG_BOOTCOMMAND="run findfdt; run distro_bootcmd"
-CONFIG_SYS_CONSOLE_IS_IN_ENV=y
-CONFIG_SYS_CONSOLE_INFO_QUIET=y
-CONFIG_VERSION_VARIABLE=y
-# CONFIG_DISPLAY_BOARDINFO is not set
-# CONFIG_SPL_EXT_SUPPORT is not set
-CONFIG_SPL_MTD_SUPPORT=y
-CONFIG_SPL_ONENAND_SUPPORT=y
-CONFIG_SPL_OS_BOOT=y
-CONFIG_CMD_SPL=y
-CONFIG_CMD_ASKENV=y
-# CONFIG_CMD_FLASH is not set
-CONFIG_CMD_GPIO=y
-CONFIG_CMD_I2C=y
-CONFIG_CMD_MMC=y
-CONFIG_CMD_NAND=y
-CONFIG_CMD_ONENAND=y
-CONFIG_CMD_SPI=y
-# CONFIG_CMD_SETEXPR is not set
-CONFIG_CMD_CACHE=y
-CONFIG_CMD_EXT4_WRITE=y
-CONFIG_CMD_MTDPARTS=y
-CONFIG_CMD_UBI=y
-# CONFIG_CMD_UBIFS is not set
-CONFIG_NET_RANDOM_ETHADDR=y
-CONFIG_MMC_OMAP_HS=y
-CONFIG_NAND=y
-CONFIG_SYS_NAND_BUSWIDTH_16BIT=y
-CONFIG_SPL_NAND_SIMPLE=y
-CONFIG_SMC911X=y
-CONFIG_SMC911X_BASE=0x2C000000
-CONFIG_SMC911X_32_BIT=y
-CONFIG_CONS_INDEX=3
-CONFIG_SPI=y
-CONFIG_OMAP3_SPI=y
-CONFIG_USB=y
-CONFIG_USB_MUSB_UDC=y
-CONFIG_USB_OMAP3=y
-CONFIG_TWL4030_USB=y
-CONFIG_USB_GADGET=y
-CONFIG_FAT_WRITE=y
-CONFIG_UBIFS_SILENCE_MSG=y
-CONFIG_BCH=y
-CONFIG_OF_LIBFDT=y
-CONFIG_FDT_FIXUP_PARTITIONS=y
diff --git a/configs/igep00x0_defconfig b/configs/igep00x0_defconfig
index 330350c..efd8519 100644
--- a/configs/igep00x0_defconfig
+++ b/configs/igep00x0_defconfig
@@ -1,7 +1,9 @@
 CONFIG_ARM=y
 CONFIG_ARCH_OMAP2PLUS=y
+CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_TARGET_OMAP3_IGEP00X0=y
 CONFIG_SPL=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_OF_BOARD_SETUP=y
@@ -16,21 +18,18 @@
 CONFIG_SPL_ONENAND_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_CMD_SPL=y
-CONFIG_CMD_ASKENV=y
 # CONFIG_CMD_FLASH is not set
-CONFIG_CMD_GPIO=y
-CONFIG_CMD_I2C=y
-CONFIG_CMD_MMC=y
 CONFIG_CMD_NAND=y
 CONFIG_CMD_ONENAND=y
-CONFIG_CMD_SPI=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_CACHE=y
-CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_MTDPARTS=y
 CONFIG_CMD_UBI=y
 # CONFIG_CMD_UBIFS is not set
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_DEFAULT_DEVICE_TREE="omap3-igep0020"
+CONFIG_OF_CONTROL=y
+CONFIG_DM_MMC=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_NAND=y
 CONFIG_SYS_NAND_BUSWIDTH_16BIT=y
@@ -42,11 +41,6 @@
 CONFIG_CONS_INDEX=3
 CONFIG_SPI=y
 CONFIG_OMAP3_SPI=y
-CONFIG_USB=y
-CONFIG_USB_MUSB_UDC=y
-CONFIG_USB_OMAP3=y
-CONFIG_TWL4030_USB=y
-CONFIG_USB_GADGET=y
 CONFIG_FAT_WRITE=y
 CONFIG_UBIFS_SILENCE_MSG=y
 CONFIG_BCH=y
diff --git a/configs/imgtec_xilfpga_defconfig b/configs/imgtec_xilfpga_defconfig
index 4fe7531..cea6424 100644
--- a/configs/imgtec_xilfpga_defconfig
+++ b/configs/imgtec_xilfpga_defconfig
@@ -17,7 +17,6 @@
 CONFIG_CMD_PING=y
 CONFIG_CMD_TIME=y
 # CONFIG_ISO_PARTITION is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="nexys4ddr"
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_NETCONSOLE=y
diff --git a/configs/malta64_defconfig b/configs/malta64_defconfig
index 15c4e62..10d2e55 100644
--- a/configs/malta64_defconfig
+++ b/configs/malta64_defconfig
@@ -18,7 +18,6 @@
 CONFIG_CMD_PING=y
 CONFIG_CMD_DATE=y
 # CONFIG_ISO_PARTITION is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="mti,malta"
 CONFIG_ENV_IS_IN_FLASH=y
 CONFIG_MTD_NOR_FLASH=y
diff --git a/configs/malta64el_defconfig b/configs/malta64el_defconfig
index 592fef5..6759d18 100644
--- a/configs/malta64el_defconfig
+++ b/configs/malta64el_defconfig
@@ -19,7 +19,6 @@
 CONFIG_CMD_PING=y
 CONFIG_CMD_DATE=y
 # CONFIG_ISO_PARTITION is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="mti,malta"
 CONFIG_ENV_IS_IN_FLASH=y
 CONFIG_MTD_NOR_FLASH=y
diff --git a/configs/malta_defconfig b/configs/malta_defconfig
index 9d6064e..6b6869d 100644
--- a/configs/malta_defconfig
+++ b/configs/malta_defconfig
@@ -17,7 +17,6 @@
 CONFIG_CMD_PING=y
 CONFIG_CMD_DATE=y
 # CONFIG_ISO_PARTITION is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="mti,malta"
 CONFIG_ENV_IS_IN_FLASH=y
 CONFIG_MTD_NOR_FLASH=y
diff --git a/configs/maltael_defconfig b/configs/maltael_defconfig
index f30f451..8dca7ff 100644
--- a/configs/maltael_defconfig
+++ b/configs/maltael_defconfig
@@ -18,7 +18,6 @@
 CONFIG_CMD_PING=y
 CONFIG_CMD_DATE=y
 # CONFIG_ISO_PARTITION is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="mti,malta"
 CONFIG_ENV_IS_IN_FLASH=y
 CONFIG_MTD_NOR_FLASH=y
diff --git a/configs/mscc_ocelot_pcb120_defconfig b/configs/mscc_jr2_defconfig
similarity index 73%
rename from configs/mscc_ocelot_pcb120_defconfig
rename to configs/mscc_jr2_defconfig
index c5a9f96..b215754 100644
--- a/configs/mscc_ocelot_pcb120_defconfig
+++ b/configs/mscc_jr2_defconfig
@@ -2,6 +2,7 @@
 CONFIG_SYS_TEXT_BASE=0x40000000
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ARCH_MSCC=y
+CONFIG_SOC_JR2=y
 CONFIG_SYS_LITTLE_ENDIAN=y
 CONFIG_FIT=y
 CONFIG_BOOTDELAY=3
@@ -9,7 +10,7 @@
 CONFIG_BOOTARGS="console=ttyS0,115200"
 CONFIG_LOGLEVEL=7
 CONFIG_DISPLAY_CPUINFO=y
-CONFIG_SYS_PROMPT="pcb120 # "
+CONFIG_SYS_PROMPT="jr2 # "
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_CONSOLE is not set
 # CONFIG_CMD_ELF is not set
@@ -21,26 +22,24 @@
 CONFIG_CMD_MEMTEST=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_GPIO=y
-CONFIG_CMD_MTD=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
-CONFIG_CMD_DHCP=y
-# CONFIG_NET_TFTP_VARS is not set
-# CONFIG_CMD_NFS is not set
-CONFIG_CMD_PING=y
+# CONFIG_CMD_NET is not set
 CONFIG_CMD_MTDPARTS=y
 CONFIG_MTDIDS_DEFAULT="nor0=spi_flash"
-CONFIG_MTDPARTS_DEFAULT="mtdparts=spi_flash:512k(UBoot),256k(Env),256k(conf),15m(linux),15m(linux.bk)"
-CONFIG_CMD_UBI=y
-# CONFIG_CMD_UBIFS is not set
+CONFIG_MTDPARTS_DEFAULT="mtdparts=spi_flash:1m(UBoot),256k(Env),256k(Env.bk)"
 # CONFIG_ISO_PARTITION is not set
-CONFIG_DEFAULT_DEVICE_TREE="ocelot_pcb120"
+CONFIG_DEFAULT_DEVICE_TREE="jr2_pcb110"
+CONFIG_OF_LIST="jr2_pcb110 jr2_pcb111 serval2_pcb112"
+CONFIG_DTB_RESELECT=y
+CONFIG_MULTI_DTB_FIT=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_CLK=y
 CONFIG_DM_GPIO=y
-CONFIG_MTD=y
-CONFIG_MTD_SPI_NAND=y
+CONFIG_MSCC_SGPIO=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
@@ -56,5 +55,5 @@
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
 CONFIG_DM_SPI=y
-CONFIG_DESIGNWARE_SPI=y
 CONFIG_LZMA=y
+CONFIG_XZ=y
diff --git a/configs/mscc_luton_defconfig b/configs/mscc_luton_defconfig
index d7476c4..7154e97 100644
--- a/configs/mscc_luton_defconfig
+++ b/configs/mscc_luton_defconfig
@@ -5,7 +5,7 @@
 CONFIG_DEBUG_UART_BASE=0x70100000
 CONFIG_DEBUG_UART_CLOCK=208333333
 CONFIG_ARCH_MSCC=y
-CONFIG_TARGET_LUTON_PCB091=y
+CONFIG_SOC_LUTON=y
 CONFIG_DDRTYPE_MT47H128M8HQ=y
 CONFIG_SYS_LITTLE_ENDIAN=y
 CONFIG_MIPS_BOOT_FDT=y
@@ -16,7 +16,7 @@
 CONFIG_BOOTARGS="console=ttyS0,115200"
 CONFIG_LOGLEVEL=7
 CONFIG_DISPLAY_CPUINFO=y
-CONFIG_SYS_PROMPT="pcb091 # "
+CONFIG_SYS_PROMPT="luton # "
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_CONSOLE is not set
 # CONFIG_CMD_ELF is not set
@@ -34,15 +34,22 @@
 # CONFIG_NET_TFTP_VARS is not set
 # CONFIG_CMD_NFS is not set
 CONFIG_CMD_PING=y
+CONFIG_CMD_TIME=y
 CONFIG_CMD_MTDPARTS=y
 CONFIG_MTDIDS_DEFAULT="nor0=spi_flash"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=spi_flash:512k(UBoot),256k(Env),256k(conf),6m@1m(linux)"
 # CONFIG_ISO_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="luton_pcb091"
+CONFIG_OF_LIST="luton_pcb090 luton_pcb091"
+CONFIG_DTB_RESELECT=y
+CONFIG_MULTI_DTB_FIT=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_CLK=y
 CONFIG_DM_GPIO=y
+CONFIG_MSCC_SGPIO=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
@@ -60,5 +67,5 @@
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
 CONFIG_DM_SPI=y
-CONFIG_SOFT_SPI=y
+CONFIG_MSCC_BB_SPI=y
 CONFIG_LZMA=y
diff --git a/configs/mscc_ocelot_defconfig b/configs/mscc_ocelot_defconfig
index 5fa74db..fb6a5bd 100644
--- a/configs/mscc_ocelot_defconfig
+++ b/configs/mscc_ocelot_defconfig
@@ -5,7 +5,6 @@
 CONFIG_DEBUG_UART_BASE=0x70100000
 CONFIG_DEBUG_UART_CLOCK=250000000
 CONFIG_ARCH_MSCC=y
-CONFIG_TARGET_OCELOT_PCB123=y
 CONFIG_SYS_LITTLE_ENDIAN=y
 CONFIG_DEBUG_UART=y
 CONFIG_FIT=y
@@ -14,7 +13,7 @@
 CONFIG_BOOTARGS="console=ttyS0,115200"
 CONFIG_LOGLEVEL=7
 CONFIG_DISPLAY_CPUINFO=y
-CONFIG_SYS_PROMPT="pcb123 # "
+CONFIG_SYS_PROMPT="ocelot # "
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_CONSOLE is not set
 # CONFIG_CMD_ELF is not set
@@ -40,12 +39,18 @@
 # CONFIG_CMD_UBIFS is not set
 # CONFIG_ISO_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="ocelot_pcb123"
+CONFIG_OF_LIST="ocelot_pcb120 ocelot_pcb123"
+CONFIG_DTB_RESELECT=y
+CONFIG_MULTI_DTB_FIT=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_CLK=y
 CONFIG_DM_GPIO=y
 CONFIG_MTD=y
 CONFIG_MTD_SPI_NAND=y
+CONFIG_MSCC_SGPIO=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
@@ -63,5 +68,4 @@
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
 CONFIG_DM_SPI=y
-CONFIG_DESIGNWARE_SPI=y
 CONFIG_LZMA=y
diff --git a/configs/mt7623n_bpir2_defconfig b/configs/mt7623n_bpir2_defconfig
index ae4fb28..70fb5a1 100644
--- a/configs/mt7623n_bpir2_defconfig
+++ b/configs/mt7623n_bpir2_defconfig
@@ -26,8 +26,10 @@
 CONFIG_CMD_PING=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
-CONFIG_OF_EMBED=y
+CONFIG_OF_SEPARATE=y
 CONFIG_DEFAULT_DEVICE_TREE="mt7623n-bananapi-bpi-r2"
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_ENV_IS_IN_MMC=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 # CONFIG_BLOCK_CACHE is not set
@@ -37,6 +39,11 @@
 # CONFIG_MMC_QUIRKS is not set
 CONFIG_MMC_HS400_SUPPORT=y
 CONFIG_MMC_MTK=y
+CONFIG_DM_RESET=y
+CONFIG_RESET_MEDIATEK=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_MEDIATEK_ETH=y
 CONFIG_PINCTRL=y
 CONFIG_PINCONF=y
 CONFIG_PINCTRL_MT7623=y
diff --git a/configs/mt7629_rfb_defconfig b/configs/mt7629_rfb_defconfig
index 1729d13..1da9932 100644
--- a/configs/mt7629_rfb_defconfig
+++ b/configs/mt7629_rfb_defconfig
@@ -29,9 +29,10 @@
 # CONFIG_CMD_NFS is not set
 CONFIG_CMD_PING=y
 # CONFIG_PARTITIONS is not set
-CONFIG_OF_EMBED=y
+CONFIG_OF_SEPARATE=y
 CONFIG_DEFAULT_DEVICE_TREE="mt7629-rfb"
 CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-parents"
+CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_REGMAP=y
 CONFIG_SPL_REGMAP=y
@@ -51,6 +52,10 @@
 CONFIG_SPI_FLASH_SPANSION=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_RESET=y
+CONFIG_RESET_MEDIATEK=y
+CONFIG_DM_ETH=y
+CONFIG_MEDIATEK_ETH=y
 CONFIG_PINCTRL=y
 CONFIG_PINCONF=y
 CONFIG_PINCTRL_MT7629=y
diff --git a/configs/netgear_cg3100d_ram_defconfig b/configs/netgear_cg3100d_ram_defconfig
index 83e8224..5fada57 100644
--- a/configs/netgear_cg3100d_ram_defconfig
+++ b/configs/netgear_cg3100d_ram_defconfig
@@ -27,7 +27,6 @@
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 # CONFIG_CMD_MISC is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="netgear,cg3100d"
 # CONFIG_NET is not set
 # CONFIG_DM_DEVICE_REMOVE is not set
diff --git a/configs/netgear_dgnd3700v2_ram_defconfig b/configs/netgear_dgnd3700v2_ram_defconfig
index 0f3914f..8968517 100644
--- a/configs/netgear_dgnd3700v2_ram_defconfig
+++ b/configs/netgear_dgnd3700v2_ram_defconfig
@@ -30,7 +30,6 @@
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="netgear,dgnd3700v2"
 CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
diff --git a/configs/pic32mzdask_defconfig b/configs/pic32mzdask_defconfig
index de699fc..d411031 100644
--- a/configs/pic32mzdask_defconfig
+++ b/configs/pic32mzdask_defconfig
@@ -21,7 +21,6 @@
 CONFIG_CMD_EXT4_WRITE=y
 # CONFIG_ISO_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="pic32mzda_sk"
 CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_BLK is not set
diff --git a/configs/poplar_defconfig b/configs/poplar_defconfig
index 239783a..81bd370 100644
--- a/configs/poplar_defconfig
+++ b/configs/poplar_defconfig
@@ -11,11 +11,23 @@
 # CONFIG_ISO_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="hi3798cv200-poplar"
 CONFIG_ENV_IS_IN_MMC=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x20000000
+CONFIG_FASTBOOT_BUF_SIZE=0x10000000
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=0
+CONFIG_DM_MMC=y
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_K3=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="HiSilicon"
+CONFIG_USB_GADGET_VENDOR_NUM=0x18d1
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd00d
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_GADGET_DWC2_OTG_PHY_BUS_WIDTH_8=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_FAT_WRITE=y
diff --git a/configs/sagem_f@st1704_ram_defconfig b/configs/sagem_f@st1704_ram_defconfig
index 8c36f5d..da19b61 100644
--- a/configs/sagem_f@st1704_ram_defconfig
+++ b/configs/sagem_f@st1704_ram_defconfig
@@ -30,7 +30,6 @@
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="sagem,f@st1704"
 CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 90146f6..78a684b 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -57,6 +57,7 @@
 CONFIG_CMD_LINK_LOCAL=y
 CONFIG_CMD_ETHSW=y
 CONFIG_CMD_BMP=y
+CONFIG_CMD_BOOTCOUNT=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_TIMER=y
 CONFIG_CMD_SOUND=y
@@ -86,6 +87,9 @@
 CONFIG_ADC_SANDBOX=y
 CONFIG_AXI=y
 CONFIG_AXI_SANDBOX=y
+CONFIG_BOOTCOUNT_LIMIT=y
+CONFIG_DM_BOOTCOUNT=y
+CONFIG_DM_BOOTCOUNT_RTC=y
 CONFIG_CLK=y
 CONFIG_CPU=y
 CONFIG_DM_DEMO=y
@@ -217,3 +221,4 @@
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
 CONFIG_UT_ENV=y
+CONFIG_UT_OVERLAY=y
diff --git a/configs/sfr_nb4-ser_ram_defconfig b/configs/sfr_nb4-ser_ram_defconfig
index 3962287..600e656 100644
--- a/configs/sfr_nb4-ser_ram_defconfig
+++ b/configs/sfr_nb4-ser_ram_defconfig
@@ -29,7 +29,6 @@
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="sfr,nb4-ser"
 CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
diff --git a/configs/stm32f429-discovery_defconfig b/configs/stm32f429-discovery_defconfig
index ef0f6f7..265b1ec 100644
--- a/configs/stm32f429-discovery_defconfig
+++ b/configs/stm32f429-discovery_defconfig
@@ -20,7 +20,6 @@
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_TIMER=y
 CONFIG_OF_CONTROL=y
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="stm32f429-disco"
 CONFIG_ENV_IS_IN_FLASH=y
 # CONFIG_MMC is not set
diff --git a/configs/stm32f429-evaluation_defconfig b/configs/stm32f429-evaluation_defconfig
index 6a2ed2a..9f1a768 100644
--- a/configs/stm32f429-evaluation_defconfig
+++ b/configs/stm32f429-evaluation_defconfig
@@ -23,7 +23,6 @@
 CONFIG_CMD_TIMER=y
 # CONFIG_ISO_PARTITION is not set
 CONFIG_OF_CONTROL=y
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="stm32429i-eval"
 CONFIG_DM_MMC=y
 CONFIG_ARM_PL180_MMCI=y
diff --git a/configs/stm32f469-discovery_defconfig b/configs/stm32f469-discovery_defconfig
index 0b36c0f..801af6b 100644
--- a/configs/stm32f469-discovery_defconfig
+++ b/configs/stm32f469-discovery_defconfig
@@ -23,7 +23,6 @@
 CONFIG_CMD_TIMER=y
 # CONFIG_ISO_PARTITION is not set
 CONFIG_OF_CONTROL=y
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="stm32f469-disco"
 CONFIG_DM_MMC=y
 CONFIG_ARM_PL180_MMCI=y
diff --git a/configs/stm32h743-disco_defconfig b/configs/stm32h743-disco_defconfig
index 92d21d1..5460ad0 100644
--- a/configs/stm32h743-disco_defconfig
+++ b/configs/stm32h743-disco_defconfig
@@ -23,7 +23,6 @@
 CONFIG_CMD_EXT4_WRITE=y
 # CONFIG_ISO_PARTITION is not set
 CONFIG_OF_CONTROL=y
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="stm32h743i-disco"
 CONFIG_DM_MMC=y
 CONFIG_STM32_SDMMC2=y
diff --git a/configs/stm32h743-eval_defconfig b/configs/stm32h743-eval_defconfig
index c08363d..2884c96 100644
--- a/configs/stm32h743-eval_defconfig
+++ b/configs/stm32h743-eval_defconfig
@@ -23,7 +23,6 @@
 CONFIG_CMD_EXT4_WRITE=y
 # CONFIG_ISO_PARTITION is not set
 CONFIG_OF_CONTROL=y
-CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="stm32h743i-eval"
 CONFIG_DM_MMC=y
 CONFIG_STM32_SDMMC2=y
diff --git a/disk/part_efi.c b/disk/part_efi.c
index d6bb53e..239455b 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -66,7 +66,7 @@
 	return name;
 }
 
-static efi_guid_t system_guid = PARTITION_SYSTEM_GUID;
+static const efi_guid_t system_guid = PARTITION_SYSTEM_GUID;
 
 static inline int is_bootable(gpt_entry *p)
 {
diff --git a/doc/device-tree-bindings/gpio/mscc_sgpio.txt b/doc/device-tree-bindings/gpio/mscc_sgpio.txt
new file mode 100644
index 0000000..3d344d6
--- /dev/null
+++ b/doc/device-tree-bindings/gpio/mscc_sgpio.txt
@@ -0,0 +1,45 @@
+Microsemi Corporation (MSCC) Serial GPIO driver
+
+The MSCC serial GPIO extends the number or GPIO's on the system by
+means of 4 dedicated pins: one input, one output, one clock and one
+strobe pin. By attaching a number of (external) shift registers, the
+effective GPIO count can be extended by up to 128 GPIO's per
+controller.
+
+Required properties:
+- compatible : "mscc,luton-sgpio" or "mscc,ocelot-sgpio"
+- clock: Reference clock used to generate clock divider setting. See
+  mscc,sgpio-frequency property.
+- reg : Physical base address and length of the controller's registers.
+- #gpio-cells : Should be two. The first cell is the pin number and the
+  second cell is used to specify optional parameters:
+  - bit 0 specifies polarity (0 for normal, 1 for inverted)
+- gpio-controller : Marks the device node as a GPIO controller.
+- gpio-ranges: Standard gpio range(s): phandle, gpio base, pinctrl base
+  and count.
+
+Optional properties:
+- ngpios: See gpio.txt
+- mscc,sgpio-frequency: The frequency at which the serial bitstream is
+  generated and sampled. Default: 12500000 (Hz).
+- mscc,sgpio-ports: A bitmask (32 bits) of which ports are enabled in
+  the serialized gpio stream. One 'port' will transport from 1 to 4
+  gpio bits. Default: 0xFFFFFFFF.
+
+Typically the pinctrl-0 and pinctrl-names properties will also be
+present to enable the use of the SIO CLK, LD, DI and DO for some
+regular GPIO pins.
+
+Example:
+
+sgpio: gpio@10700f8 {
+       compatible = "mscc,ocelot-sgpio";
+       pinctrl-0 = <&sgpio_pins>;
+       pinctrl-names = "default";
+       reg = <0x10700f8 0x100>;
+       gpio-controller;
+       #gpio-cells = <2>;
+       gpio-ranges = <&sgpio 0 0 64>;
+       mscc,sgpio-frequency = <12500>;
+       mscc,sgpio-ports = <0x000FFFFF>;
+};
diff --git a/doc/driver-model/fs_firmware_loader.txt b/doc/driver-model/fs_firmware_loader.txt
index 290915a..b9aee84 100644
--- a/doc/driver-model/fs_firmware_loader.txt
+++ b/doc/driver-model/fs_firmware_loader.txt
@@ -74,17 +74,16 @@
 File system firmware Loader API
 -------------------------------
 
-int request_firmware_into_buf(struct device_platdata *plat,
+int request_firmware_into_buf(struct udevice *dev,
 				 const char *name,
-				 void *buf, size_t size, u32 offset,
-				 struct firmware **firmwarep)
+				 void *buf, size_t size, u32 offset)
 --------------------------------------------------------------------
 Load firmware into a previously allocated buffer
 
 Parameters:
 
-1. struct device_platdata *plat
-	Platform data such as storage and partition firmware loading from
+1. struct udevice *dev
+	An instance of a driver
 
 2. const char *name
 	name of firmware file
@@ -98,36 +97,16 @@
 5. u32 offset
 	offset of a file for start reading into buffer
 
-6. struct firmware **firmwarep
-	pointer to firmware image
-
 return:
 	size of total read
 	-ve when error
 
 Description:
-	The firmware is loaded directly into the buffer pointed to by buf and
-	the @firmwarep data member is pointed at buf
-
-Note: Memory would be allocated for firmware image, hence user should
-	  free() *firmwarep and *firmwarep->priv structs after usage of
-	  request_firmware_into_buf(), otherwise it will always leak memory
-	  while subsequent calls of request_firmware_into_buf() with the same
-	  *firmwarep argument. Those arguments can be free through calling API
-	  below release_firmware();
+	The firmware is loaded directly into the buffer pointed to by buf
 
 Example of creating firmware loader instance and calling
 request_firmware_into_buf API:
 	if (uclass_get_device(UCLASS_FS_FIRMWARE_LOADER, 0, &dev)) {
-		request_firmware_into_buf(dev->plat, filename, buffer_location,
-					 buffer_size, offset_ofreading, &fw);
+		request_firmware_into_buf(dev, filename, buffer_location,
+					 buffer_size, offset_ofreading);
 	}
-
-void release_firmware(struct firmware *firmware)
-------------------------------------------------
-Release the resource associated with a firmware image
-
-Parameters:
-
-1. struct firmware *firmware
-	Firmware resource to release
diff --git a/drivers/block/blkcache.c b/drivers/block/blkcache.c
index 294511f..1fa6498 100644
--- a/drivers/block/blkcache.c
+++ b/drivers/block/blkcache.c
@@ -24,7 +24,7 @@
 static LIST_HEAD(block_cache);
 
 static struct block_cache_stats _stats = {
-	.max_blocks_per_entry = 2,
+	.max_blocks_per_entry = 8,
 	.max_entries = 32
 };
 
diff --git a/drivers/clk/mediatek/clk-mt7623.c b/drivers/clk/mediatek/clk-mt7623.c
index c6b09d8..87ad4f7 100644
--- a/drivers/clk/mediatek/clk-mt7623.c
+++ b/drivers/clk/mediatek/clk-mt7623.c
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <asm/arch-mediatek/reset.h>
 #include <asm/io.h>
 #include <dt-bindings/clock/mt7623-clk.h>
 
@@ -782,6 +783,19 @@
 	return mtk_common_clk_gate_init(dev, &mt7623_clk_tree, eth_cgs);
 }
 
+static int mt7623_ethsys_bind(struct udevice *dev)
+{
+	int ret = 0;
+
+#if CONFIG_IS_ENABLED(RESET_MEDIATEK)
+	ret = mediatek_reset_bind(dev, ETHSYS_RST_CTRL_OFS, 1);
+	if (ret)
+		debug("Warning: failed to bind ethsys reset controller\n");
+#endif
+
+	return ret;
+}
+
 static const struct udevice_id mt7623_apmixed_compat[] = {
 	{ .compatible = "mediatek,mt7623-apmixedsys" },
 	{ }
@@ -865,6 +879,7 @@
 	.id = UCLASS_CLK,
 	.of_match = mt7623_ethsys_compat,
 	.probe = mt7623_ethsys_probe,
+	.bind = mt7623_ethsys_bind,
 	.priv_auto_alloc_size = sizeof(struct mtk_cg_priv),
 	.ops = &mtk_clk_gate_ops,
 };
diff --git a/drivers/clk/mediatek/clk-mt7629.c b/drivers/clk/mediatek/clk-mt7629.c
index 2601b6c..6a9f601 100644
--- a/drivers/clk/mediatek/clk-mt7629.c
+++ b/drivers/clk/mediatek/clk-mt7629.c
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <asm/arch-mediatek/reset.h>
 #include <asm/io.h>
 #include <dt-bindings/clock/mt7629-clk.h>
 
@@ -602,6 +603,19 @@
 	return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, eth_cgs);
 }
 
+static int mt7629_ethsys_bind(struct udevice *dev)
+{
+	int ret = 0;
+
+#if CONFIG_IS_ENABLED(RESET_MEDIATEK)
+	ret = mediatek_reset_bind(dev, ETHSYS_RST_CTRL_OFS, 1);
+	if (ret)
+		debug("Warning: failed to bind ethsys reset controller\n");
+#endif
+
+	return ret;
+}
+
 static int mt7629_sgmiisys_probe(struct udevice *dev)
 {
 	return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, sgmii_cgs);
@@ -695,6 +709,7 @@
 	.id = UCLASS_CLK,
 	.of_match = mt7629_ethsys_compat,
 	.probe = mt7629_ethsys_probe,
+	.bind = mt7629_ethsys_bind,
 	.priv_auto_alloc_size = sizeof(struct mtk_cg_priv),
 	.ops = &mtk_clk_gate_ops,
 };
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index 74152ed..7847388 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -23,6 +23,8 @@
 #define CLK_PARENT_TOPCKGEN		BIT(5)
 #define CLK_PARENT_MASK			GENMASK(5, 4)
 
+#define ETHSYS_RST_CTRL_OFS		0x34
+
 /* struct mtk_pll_data - hardware-specific PLLs data */
 struct mtk_pll_data {
 	const int id;
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 046b87a..ddf2fb3 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -232,7 +232,7 @@
 	  Is this option is enabled then support for the ISA bus will
 	  be included for addresses read from DT. This is something that
 	  should be known to be required or not based upon the board
-	  being targetted, and whether or not it makes use of an ISA bus.
+	  being targeted, and whether or not it makes use of an ISA bus.
 
 	  The bus is matched based upon its node name equalling "isa". The
 	  busses #address-cells should equal 2, with the first cell being
diff --git a/drivers/core/dump.c b/drivers/core/dump.c
index 04217cb..8fbfd93 100644
--- a/drivers/core/dump.c
+++ b/drivers/core/dump.c
@@ -16,7 +16,7 @@
 	struct udevice *child;
 
 	/* print the first 20 characters to not break the tree-format. */
-	printf(" %-10.10s  %d  [ %c ]   %-20.20s  ", dev->uclass->uc_drv->name,
+	printf(" %-10.10s  %2d  [ %c ]   %-20.20s  ", dev->uclass->uc_drv->name,
 	       dev_get_uclass_index(dev, NULL),
 	       dev->flags & DM_FLAG_ACTIVATED ? '+' : ' ', dev->driver->name);
 
@@ -49,7 +49,7 @@
 
 	root = dm_root();
 	if (root) {
-		printf(" Class    index  Probed  Driver                Name\n");
+		printf(" Class     Index  Probed  Driver                Name\n");
 		printf("-----------------------------------------------------------\n");
 		show_devices(root, -1, 0);
 	}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index c8c6c60..14a14be 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -99,12 +99,16 @@
 	help
 	  Support for the LPC32XX GPIO driver.
 
-config MSCC_BITBANG_SPI_GPIO
-	bool "Microsemi bitbang spi GPIO driver"
+config MSCC_SGPIO
+	bool "Microsemi Serial GPIO driver"
 	depends on DM_GPIO && SOC_VCOREIII
 	help
-	  Support controlling the GPIO used for SPI bitbang by software. Can
-	  be used by the VCoreIII SoCs, but it was mainly useful for Luton.
+	  Support for the VCoreIII SoC serial GPIO device. By using a
+          serial interface, the SIO controller significantly extends
+          the number of available GPIOs with a minimum number of
+          additional pins on the device. The primary purpose of the
+          SIO controller is to connect control signals from SFP
+          modules and to act as an LED controller.
 
 config MSM_GPIO
 	bool "Qualcomm GPIO driver"
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 61feda1..7c479ef 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -59,4 +59,4 @@
 obj-$(CONFIG_$(SPL_)PCF8575_GPIO)	+= pcf8575_gpio.o
 obj-$(CONFIG_PM8916_GPIO)	+= pm8916_gpio.o
 obj-$(CONFIG_MT7621_GPIO)	+= mt7621_gpio.o
-obj-$(CONFIG_MSCC_BITBANG_SPI_GPIO)	+= gpio-mscc-bitbang-spi.o
+obj-$(CONFIG_MSCC_SGPIO)	+= mscc_sgpio.o
diff --git a/drivers/gpio/gpio-mscc-bitbang-spi.c b/drivers/gpio/gpio-mscc-bitbang-spi.c
deleted file mode 100644
index b675f90..0000000
--- a/drivers/gpio/gpio-mscc-bitbang-spi.c
+++ /dev/null
@@ -1,122 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0 OR MIT)
-/*
- * Microsemi SoCs pinctrl driver
- *
- * Author: <gregory.clement@bootlin.com>
- * License: Dual MIT/GPL
- * Copyright (c) 2018 Microsemi Corporation
- */
-
-#include <common.h>
-#include <asm-generic/gpio.h>
-#include <asm/io.h>
-#include <dm.h>
-#include <errno.h>
-
-enum {
-	SDI,
-	CS0,
-	CS1,
-	CS2,
-	CS3,
-	SDO,
-	SCK
-};
-
-static const int pinmap[] = { 0, 5, 6, 7, 8, 10, 12 };
-
-#define SW_SPI_CSn_OE	 0x1E	/* bits 1 to 4 */
-#define SW_SPI_CS0_OE	 BIT(1)
-#define SW_SPI_SDO_OE	 BIT(9)
-#define SW_SPI_SCK_OE	 BIT(11)
-#define SW_PIN_CTRL_MODE BIT(13)
-
-struct mscc_bb_spi_gpio {
-	void __iomem *regs;
-	u32 cache_val;
-};
-
-static int mscc_bb_spi_gpio_set(struct udevice *dev, unsigned oft, int val)
-{
-	struct mscc_bb_spi_gpio *gpio = dev_get_priv(dev);
-
-	if (val)
-		gpio->cache_val |= BIT(pinmap[oft]);
-	else
-		gpio->cache_val &= ~BIT(pinmap[oft]);
-
-	writel(gpio->cache_val, gpio->regs);
-
-	return 0;
-}
-
-static int mscc_bb_spi_gpio_direction_output(struct udevice *dev, unsigned oft,
-					     int val)
-{
-	if (oft == 0) {
-		pr_err("SW_SPI_DSI can't be used as output\n");
-		return -ENOTSUPP;
-	}
-
-	mscc_bb_spi_gpio_set(dev, oft, val);
-
-	return 0;
-}
-
-static int mscc_bb_spi_gpio_direction_input(struct udevice *dev, unsigned oft)
-{
-	return 0;
-}
-
-static int mscc_bb_spi_gpio_get(struct udevice *dev, unsigned int oft)
-{
-	struct mscc_bb_spi_gpio *gpio = dev_get_priv(dev);
-	u32 val = readl(gpio->regs);
-
-	return !!(val & BIT(pinmap[oft]));
-}
-
-static const struct dm_gpio_ops mscc_bb_spi_gpio_ops = {
-	.direction_output	= mscc_bb_spi_gpio_direction_output,
-	.direction_input	= mscc_bb_spi_gpio_direction_input,
-	.set_value		= mscc_bb_spi_gpio_set,
-	.get_value		= mscc_bb_spi_gpio_get,
-};
-
-static int mscc_bb_spi_gpio_probe(struct udevice *dev)
-{
-	struct mscc_bb_spi_gpio *gpio = dev_get_priv(dev);
-	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
-
-	gpio->regs = dev_remap_addr(dev);
-	if (!gpio->regs)
-		return -EINVAL;
-
-	uc_priv->bank_name = dev->name;
-	uc_priv->gpio_count = ARRAY_SIZE(pinmap);
-	/*
-	 * Enable software mode to control the SPI pin, enables the
-	 * output mode for most of the pin and initialize the cache
-	 * value in the same time
-	 */
-
-	gpio->cache_val = SW_PIN_CTRL_MODE | SW_SPI_SCK_OE | SW_SPI_SDO_OE |
-	    SW_SPI_CS0_OE;
-	writel(gpio->cache_val, gpio->regs);
-
-	return 0;
-}
-
-static const struct udevice_id mscc_bb_spi_gpio_ids[] = {
-	{.compatible = "mscc,spi-bitbang-gpio"},
-	{}
-};
-
-U_BOOT_DRIVER(gpio_mscc_bb_spi) = {
-	.name	= "gpio-mscc-spi-bitbang",
-	.id	= UCLASS_GPIO,
-	.ops	= &mscc_bb_spi_gpio_ops,
-	.probe	= mscc_bb_spi_gpio_probe,
-	.of_match = of_match_ptr(mscc_bb_spi_gpio_ids),
-	.priv_auto_alloc_size = sizeof(struct mscc_bb_spi_gpio),
-};
diff --git a/drivers/gpio/mscc_sgpio.c b/drivers/gpio/mscc_sgpio.c
new file mode 100644
index 0000000..c899454
--- /dev/null
+++ b/drivers/gpio/mscc_sgpio.c
@@ -0,0 +1,275 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Microsemi SoCs serial gpio driver
+ *
+ * Author: <lars.povlsen@microchip.com>
+ *
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <errno.h>
+#include <clk.h>
+
+#define MSCC_SGPIOS_PER_BANK	32
+#define MSCC_SGPIO_BANK_DEPTH	4
+
+enum {
+	REG_INPUT_DATA,
+	REG_PORT_CONFIG,
+	REG_PORT_ENABLE,
+	REG_SIO_CONFIG,
+	REG_SIO_CLOCK,
+	MAXREG
+};
+
+struct mscc_sgpio_bf {
+	u8 beg;
+	u8 end;
+};
+
+struct mscc_sgpio_props {
+	u8 regoff[MAXREG];
+	struct mscc_sgpio_bf auto_repeat;
+	struct mscc_sgpio_bf port_width;
+	struct mscc_sgpio_bf clk_freq;
+	struct mscc_sgpio_bf bit_source;
+};
+
+#define __M(bf)		GENMASK((bf).end, (bf).beg)
+#define __F(bf, x)	(__M(bf) & ((x) << (bf).beg))
+#define __X(bf, x)	(((x) >> (bf).beg) & GENMASK(((bf).end - (bf).beg), 0))
+
+#define MSCC_M_CFG_SIO_AUTO_REPEAT(p)		BIT(p->props->auto_repeat.beg)
+#define MSCC_F_CFG_SIO_PORT_WIDTH(p, x)		__F(p->props->port_width, x)
+#define MSCC_M_CFG_SIO_PORT_WIDTH(p)		__M(p->props->port_width)
+#define MSCC_F_CLOCK_SIO_CLK_FREQ(p, x)		__F(p->props->clk_freq, x)
+#define MSCC_M_CLOCK_SIO_CLK_FREQ(p)		__M(p->props->clk_freq)
+#define MSCC_F_PORT_CFG_BIT_SOURCE(p, x)	__F(p->props->bit_source, x)
+#define MSCC_X_PORT_CFG_BIT_SOURCE(p, x)	__X(p->props->bit_source, x)
+
+const struct mscc_sgpio_props props_luton = {
+	.regoff = { 0x00, 0x09, 0x29, 0x2a, 0x2b },
+	.auto_repeat = { 5, 5 },
+	.port_width  = { 2, 3 },
+	.clk_freq    = { 0, 11 },
+	.bit_source  = { 0, 11 },
+};
+
+const struct mscc_sgpio_props props_ocelot = {
+	.regoff = { 0x00, 0x06, 0x26, 0x04, 0x05 },
+	.auto_repeat = { 10, 10 },
+	.port_width  = {  7, 8  },
+	.clk_freq    = {  8, 19 },
+	.bit_source  = { 12, 23 },
+};
+
+struct mscc_sgpio_priv {
+	u32 bitcount;
+	u32 ports;
+	u32 clock;
+	u32 mode[MSCC_SGPIOS_PER_BANK];
+	u32 __iomem *regs;
+	const struct mscc_sgpio_props *props;
+};
+
+static inline u32 sgpio_readl(struct mscc_sgpio_priv *priv, u32 rno, u32 off)
+{
+	u32 __iomem *reg = &priv->regs[priv->props->regoff[rno] + off];
+
+	return readl(reg);
+}
+
+static inline void sgpio_writel(struct mscc_sgpio_priv *priv,
+				u32 val, u32 rno, u32 off)
+{
+	u32 __iomem *reg = &priv->regs[priv->props->regoff[rno] + off];
+
+	writel(val, reg);
+}
+
+static void sgpio_clrsetbits(struct mscc_sgpio_priv *priv,
+			     u32 rno, u32 off, u32 clear, u32 set)
+{
+	u32 __iomem *reg = &priv->regs[priv->props->regoff[rno] + off];
+
+	clrsetbits_le32(reg, clear, set);
+}
+
+static int mscc_sgpio_direction_input(struct udevice *dev, unsigned int gpio)
+{
+	struct mscc_sgpio_priv *priv = dev_get_priv(dev);
+
+	u32 port = gpio % MSCC_SGPIOS_PER_BANK;
+	u32 bit = gpio / MSCC_SGPIOS_PER_BANK;
+
+	priv->mode[port] |= BIT(bit);
+
+	return 0;
+}
+
+static int mscc_sgpio_direction_output(struct udevice *dev,
+				       unsigned int gpio, int value)
+{
+	struct mscc_sgpio_priv *priv = dev_get_priv(dev);
+	u32 port = gpio % MSCC_SGPIOS_PER_BANK;
+	u32 bit = gpio / MSCC_SGPIOS_PER_BANK;
+	u32 mask = 3 << (3 * bit);
+
+	debug("set: port %d, bit %d, mask 0x%08x, value %d\n",
+	      port, bit, mask, value);
+
+	value = (value & 3) << (3 * bit);
+	sgpio_clrsetbits(priv, REG_PORT_CONFIG, port,
+			 MSCC_F_PORT_CFG_BIT_SOURCE(priv, mask),
+			 MSCC_F_PORT_CFG_BIT_SOURCE(priv, value));
+	clrbits_le32(&priv->mode[port], BIT(bit));
+
+	return 0;
+}
+
+static int mscc_sgpio_get_function(struct udevice *dev, unsigned int gpio)
+{
+	struct mscc_sgpio_priv *priv = dev_get_priv(dev);
+	u32 port = gpio % MSCC_SGPIOS_PER_BANK;
+	u32 bit = gpio / MSCC_SGPIOS_PER_BANK;
+	u32 val = priv->mode[port] & BIT(bit);
+
+	if (val)
+		return GPIOF_INPUT;
+	else
+		return GPIOF_OUTPUT;
+}
+
+static int mscc_sgpio_set_value(struct udevice *dev,
+				unsigned int gpio, int value)
+{
+	return mscc_sgpio_direction_output(dev, gpio, value);
+}
+
+static int mscc_sgpio_get_value(struct udevice *dev, unsigned int gpio)
+{
+	struct mscc_sgpio_priv *priv = dev_get_priv(dev);
+	u32 port = gpio % MSCC_SGPIOS_PER_BANK;
+	u32 bit = gpio / MSCC_SGPIOS_PER_BANK;
+	int ret;
+
+	if (mscc_sgpio_get_function(dev, gpio) == GPIOF_INPUT) {
+		ret = !!(sgpio_readl(priv, REG_INPUT_DATA, bit) & BIT(port));
+	} else {
+		u32 portval = sgpio_readl(priv, REG_PORT_CONFIG, port);
+
+		ret = MSCC_X_PORT_CFG_BIT_SOURCE(priv, portval);
+		ret = !!(ret & (3 << (3 * bit)));
+	}
+
+	debug("get: gpio %d, port %d, bit %d, value %d\n",
+	      gpio, port, bit, ret);
+	return ret;
+}
+
+static int mscc_sgpio_get_count(struct udevice *dev)
+{
+	struct ofnode_phandle_args args;
+	int count = 0, i = 0, ret;
+
+	ret = dev_read_phandle_with_args(dev, "gpio-ranges", NULL, 3, i, &args);
+	while (ret != -ENOENT) {
+		count += args.args[2];
+		ret = dev_read_phandle_with_args(dev, "gpio-ranges", NULL, 3,
+						 ++i, &args);
+	}
+	return count;
+}
+
+static int mscc_sgpio_probe(struct udevice *dev)
+{
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct mscc_sgpio_priv *priv = dev_get_priv(dev);
+	int err, div_clock = 0, port;
+	u32 val;
+	struct clk clk;
+
+	err = clk_get_by_index(dev, 0, &clk);
+	if (!err) {
+		err = clk_get_rate(&clk);
+		if (IS_ERR_VALUE(err)) {
+			dev_err(dev, "Invalid clk rate\n");
+			return -EINVAL;
+		}
+		div_clock = err;
+	} else {
+		dev_err(dev, "Failed to get clock\n");
+		return err;
+	}
+
+	priv->props = (const struct mscc_sgpio_props *)dev_get_driver_data(dev);
+	priv->ports = dev_read_u32_default(dev, "mscc,sgpio-ports", 0xFFFFFFFF);
+	priv->clock = dev_read_u32_default(dev, "mscc,sgpio-frequency",
+					   12500000);
+	if (priv->clock <= 0 || priv->clock > div_clock) {
+		dev_err(dev, "Invalid frequency %d\n", priv->clock);
+		return -EINVAL;
+	}
+
+	uc_priv->gpio_count = mscc_sgpio_get_count(dev);
+	uc_priv->gpio_count = dev_read_u32_default(dev, "ngpios",
+						   uc_priv->gpio_count);
+	if (uc_priv->gpio_count < 1 || uc_priv->gpio_count >
+	    (4 * MSCC_SGPIOS_PER_BANK)) {
+		dev_err(dev, "Invalid gpio count %d\n", uc_priv->gpio_count);
+		return -EINVAL;
+	}
+	priv->bitcount = DIV_ROUND_UP(uc_priv->gpio_count,
+				      MSCC_SGPIOS_PER_BANK);
+	debug("probe: gpios = %d, bit-count = %d\n",
+	      uc_priv->gpio_count, priv->bitcount);
+
+	priv->regs = (u32 __iomem *)dev_read_addr(dev);
+	uc_priv->bank_name = "sgpio";
+
+	sgpio_clrsetbits(priv, REG_SIO_CONFIG, 0,
+			 MSCC_M_CFG_SIO_PORT_WIDTH(priv),
+			 MSCC_F_CFG_SIO_PORT_WIDTH(priv, priv->bitcount - 1) |
+			 MSCC_M_CFG_SIO_AUTO_REPEAT(priv));
+	val = div_clock / priv->clock;
+	debug("probe: div-clock = %d KHz, freq = %d KHz, div = %d\n",
+	      div_clock / 1000, priv->clock / 1000, val);
+	sgpio_clrsetbits(priv, REG_SIO_CLOCK, 0,
+			 MSCC_M_CLOCK_SIO_CLK_FREQ(priv),
+			 MSCC_F_CLOCK_SIO_CLK_FREQ(priv, val));
+
+	for (port = 0; port < 32; port++)
+		sgpio_writel(priv, 0, REG_PORT_CONFIG, port);
+	sgpio_writel(priv, priv->ports, REG_PORT_ENABLE, 0);
+
+	debug("probe: sgpio regs = %p\n", priv->regs);
+
+	return 0;
+}
+
+static const struct dm_gpio_ops mscc_sgpio_ops = {
+	.direction_input	= mscc_sgpio_direction_input,
+	.direction_output	= mscc_sgpio_direction_output,
+	.get_function		= mscc_sgpio_get_function,
+	.get_value		= mscc_sgpio_get_value,
+	.set_value		= mscc_sgpio_set_value,
+};
+
+static const struct udevice_id mscc_sgpio_ids[] = {
+	{ .compatible = "mscc,luton-sgpio", .data = (ulong)&props_luton },
+	{ .compatible = "mscc,ocelot-sgpio", .data = (ulong)&props_ocelot },
+	{ }
+};
+
+U_BOOT_DRIVER(gpio_mscc_sgpio) = {
+	.name			= "mscc-sgpio",
+	.id			= UCLASS_GPIO,
+	.of_match		= mscc_sgpio_ids,
+	.ops			= &mscc_sgpio_ops,
+	.probe			= mscc_sgpio_probe,
+	.priv_auto_alloc_size	= sizeof(struct mscc_sgpio_priv),
+};
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 1ef22e6..d83afe4 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -157,9 +157,9 @@
 config SYS_I2C_MXC
 	bool "NXP MXC I2C driver"
 	help
-	  Add support for the NXP I2C driver. This supports upto for bus
-	  channels and operating on standard mode upto 100 kbits/s and fast
-	  mode upto 400 kbits/s.
+	  Add support for the NXP I2C driver. This supports up to four bus
+	  channels and operating on standard mode up to 100 kbits/s and fast
+	  mode up to 400 kbits/s.
 
 if SYS_I2C_MXC
 config SYS_I2C_MXC_I2C1
@@ -363,7 +363,7 @@
 	help
 	  Add support for the Rockchip I2C driver. This is used with various
 	  Rockchip parts such as RK3126, RK3128, RK3036 and RK3288. All chips
-	  have several I2C ports and all are provided, controled by the
+	  have several I2C ports and all are provided, controlled by the
 	  device tree.
 
 config SYS_I2C_SANDBOX
@@ -450,9 +450,16 @@
 	help
 	  Define the maximum number of available I2C buses.
 
+config SYS_I2C_XILINX_XIIC
+	bool "Xilinx AXI I2C driver"
+	depends on DM_I2C
+	help
+	  Support for Xilinx AXI I2C controller.
+
 config SYS_I2C_ZYNQ
 	bool "Xilinx I2C driver"
 	depends on ARCH_ZYNQMP || ARCH_ZYNQ
+	depends on !DM_I2C
 	help
 	  Support for Xilinx I2C controller.
 
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index d3637bc..ec2d196 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -37,6 +37,7 @@
 obj-$(CONFIG_SYS_I2C_UNIPHIER) += i2c-uniphier.o
 obj-$(CONFIG_SYS_I2C_UNIPHIER_F) += i2c-uniphier-f.o
 obj-$(CONFIG_SYS_I2C_VERSATILE) += i2c-versatile.o
+obj-$(CONFIG_SYS_I2C_XILINX_XIIC) += xilinx_xiic.o
 obj-$(CONFIG_SYS_I2C_ZYNQ) += zynq_i2c.o
 obj-$(CONFIG_TEGRA186_BPMP_I2C) += tegra186_bpmp_i2c.o
 
diff --git a/drivers/i2c/i2c-cdns.c b/drivers/i2c/i2c-cdns.c
index 30be173..f2c4b20 100644
--- a/drivers/i2c/i2c-cdns.c
+++ b/drivers/i2c/i2c-cdns.c
@@ -17,6 +17,7 @@
 #include <fdtdec.h>
 #include <mapmem.h>
 #include <wait_bit.h>
+#include <clk.h>
 
 /* i2c register set */
 struct cdns_i2c_regs {
@@ -415,6 +416,8 @@
 	struct i2c_cdns_bus *i2c_bus = dev_get_priv(dev);
 	struct cdns_i2c_platform_data *pdata =
 		(struct cdns_i2c_platform_data *)dev_get_driver_data(dev);
+	struct clk clk;
+	int ret;
 
 	i2c_bus->regs = (struct cdns_i2c_regs *)devfdt_get_addr(dev);
 	if (!i2c_bus->regs)
@@ -423,7 +426,11 @@
 	if (pdata)
 		i2c_bus->quirks = pdata->quirks;
 
-	i2c_bus->input_freq = 100000000; /* TODO hardcode input freq for now */
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret)
+		return ret;
+
+	i2c_bus->input_freq = clk_get_rate(&clk);
 
 	return 0;
 }
diff --git a/drivers/i2c/muxes/i2c-mux-uclass.c b/drivers/i2c/muxes/i2c-mux-uclass.c
index 1033691..a680ee1 100644
--- a/drivers/i2c/muxes/i2c-mux-uclass.c
+++ b/drivers/i2c/muxes/i2c-mux-uclass.c
@@ -11,8 +11,6 @@
 #include <dm/lists.h>
 #include <dm/root.h>
 
-DECLARE_GLOBAL_DATA_PTR;
-
 /**
  * struct i2c_mux: Information the uclass stores about an I2C mux
  *
@@ -39,7 +37,7 @@
 	struct i2c_mux_bus *plat = dev_get_parent_platdata(dev);
 	int channel;
 
-	channel = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "reg", -1);
+	channel = dev_read_u32_default(dev, "reg", -1);
 	if (channel < 0)
 		return -EINVAL;
 	plat->channel = channel;
diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c
index ab8b400..bd4e9ab 100644
--- a/drivers/i2c/muxes/pca954x.c
+++ b/drivers/i2c/muxes/pca954x.c
@@ -101,7 +101,7 @@
 	struct pca954x_priv *priv = dev_get_priv(dev);
 	const struct chip_desc *chip = &chips[dev_get_driver_data(dev)];
 
-	priv->addr = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "reg", 0);
+	priv->addr = dev_read_u32_default(dev, "reg", 0);
 	if (!priv->addr) {
 		debug("MUX not found\n");
 		return -ENODEV;
diff --git a/drivers/i2c/xilinx_xiic.c b/drivers/i2c/xilinx_xiic.c
new file mode 100644
index 0000000..83114ed
--- /dev/null
+++ b/drivers/i2c/xilinx_xiic.c
@@ -0,0 +1,340 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Xilinx AXI I2C driver
+ *
+ * Copyright (C) 2018 Marek Vasut <marex@denx.de>
+ *
+ * Based on Linux 4.14.y i2c-xiic.c
+ * Copyright (c) 2002-2007 Xilinx Inc.
+ * Copyright (c) 2009-2010 Intel Corporation
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <i2c.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+struct xilinx_xiic_priv {
+	void __iomem		*base;
+	struct clk		clk;
+};
+
+#define XIIC_MSB_OFFSET 0
+#define XIIC_REG_OFFSET (0x100+XIIC_MSB_OFFSET)
+
+/*
+ * Register offsets in bytes from RegisterBase. Three is added to the
+ * base offset to access LSB (IBM style) of the word
+ */
+#define XIIC_CR_REG_OFFSET   (0x00+XIIC_REG_OFFSET)	/* Control Register   */
+#define XIIC_SR_REG_OFFSET   (0x04+XIIC_REG_OFFSET)	/* Status Register    */
+#define XIIC_DTR_REG_OFFSET  (0x08+XIIC_REG_OFFSET)	/* Data Tx Register   */
+#define XIIC_DRR_REG_OFFSET  (0x0C+XIIC_REG_OFFSET)	/* Data Rx Register   */
+#define XIIC_ADR_REG_OFFSET  (0x10+XIIC_REG_OFFSET)	/* Address Register   */
+#define XIIC_TFO_REG_OFFSET  (0x14+XIIC_REG_OFFSET)	/* Tx FIFO Occupancy  */
+#define XIIC_RFO_REG_OFFSET  (0x18+XIIC_REG_OFFSET)	/* Rx FIFO Occupancy  */
+#define XIIC_TBA_REG_OFFSET  (0x1C+XIIC_REG_OFFSET)	/* 10 Bit Address reg */
+#define XIIC_RFD_REG_OFFSET  (0x20+XIIC_REG_OFFSET)	/* Rx FIFO Depth reg  */
+#define XIIC_GPO_REG_OFFSET  (0x24+XIIC_REG_OFFSET)	/* Output Register    */
+
+/* Control Register masks */
+#define XIIC_CR_ENABLE_DEVICE_MASK        0x01	/* Device enable = 1      */
+#define XIIC_CR_TX_FIFO_RESET_MASK        0x02	/* Transmit FIFO reset=1  */
+#define XIIC_CR_MSMS_MASK                 0x04	/* Master starts Txing=1  */
+#define XIIC_CR_DIR_IS_TX_MASK            0x08	/* Dir of tx. Txing=1     */
+#define XIIC_CR_NO_ACK_MASK               0x10	/* Tx Ack. NO ack = 1     */
+#define XIIC_CR_REPEATED_START_MASK       0x20	/* Repeated start = 1     */
+#define XIIC_CR_GENERAL_CALL_MASK         0x40	/* Gen Call enabled = 1   */
+
+/* Status Register masks */
+#define XIIC_SR_GEN_CALL_MASK             0x01	/* 1=a mstr issued a GC   */
+#define XIIC_SR_ADDR_AS_SLAVE_MASK        0x02	/* 1=when addr as slave   */
+#define XIIC_SR_BUS_BUSY_MASK             0x04	/* 1 = bus is busy        */
+#define XIIC_SR_MSTR_RDING_SLAVE_MASK     0x08	/* 1=Dir: mstr <-- slave  */
+#define XIIC_SR_TX_FIFO_FULL_MASK         0x10	/* 1 = Tx FIFO full       */
+#define XIIC_SR_RX_FIFO_FULL_MASK         0x20	/* 1 = Rx FIFO full       */
+#define XIIC_SR_RX_FIFO_EMPTY_MASK        0x40	/* 1 = Rx FIFO empty      */
+#define XIIC_SR_TX_FIFO_EMPTY_MASK        0x80	/* 1 = Tx FIFO empty      */
+
+/* Interrupt Status Register masks    Interrupt occurs when...       */
+#define XIIC_INTR_ARB_LOST_MASK           0x01	/* 1 = arbitration lost   */
+#define XIIC_INTR_TX_ERROR_MASK           0x02	/* 1=Tx error/msg complete */
+#define XIIC_INTR_TX_EMPTY_MASK           0x04	/* 1 = Tx FIFO/reg empty  */
+#define XIIC_INTR_RX_FULL_MASK            0x08	/* 1=Rx FIFO/reg=OCY level */
+#define XIIC_INTR_BNB_MASK                0x10	/* 1 = Bus not busy       */
+#define XIIC_INTR_AAS_MASK                0x20	/* 1 = when addr as slave */
+#define XIIC_INTR_NAAS_MASK               0x40	/* 1 = not addr as slave  */
+#define XIIC_INTR_TX_HALF_MASK            0x80	/* 1 = TX FIFO half empty */
+
+/* The following constants specify the depth of the FIFOs */
+#define IIC_RX_FIFO_DEPTH         16	/* Rx fifo capacity               */
+#define IIC_TX_FIFO_DEPTH         16	/* Tx fifo capacity               */
+
+/*
+ * Tx Fifo upper bit masks.
+ */
+#define XIIC_TX_DYN_START_MASK            0x0100 /* 1 = Set dynamic start */
+#define XIIC_TX_DYN_STOP_MASK             0x0200 /* 1 = Set dynamic stop */
+
+/*
+ * The following constants define the register offsets for the Interrupt
+ * registers. There are some holes in the memory map for reserved addresses
+ * to allow other registers to be added and still match the memory map of the
+ * interrupt controller registers
+ */
+#define XIIC_DGIER_OFFSET    0x1C /* Device Global Interrupt Enable Register */
+#define XIIC_IISR_OFFSET     0x20 /* Interrupt Status Register */
+#define XIIC_IIER_OFFSET     0x28 /* Interrupt Enable Register */
+#define XIIC_RESETR_OFFSET   0x40 /* Reset Register */
+
+#define XIIC_RESET_MASK             0xAUL
+
+static u8 i2c_8bit_addr_from_flags(uint addr, u16 flags)
+{
+	return (addr << 1) | (flags & I2C_M_RD ? 1 : 0);
+}
+
+static void xiic_irq_clr(struct xilinx_xiic_priv *priv, u32 mask)
+{
+	u32 isr = readl(priv->base + XIIC_IISR_OFFSET);
+
+	writel(isr & mask, priv->base + XIIC_IISR_OFFSET);
+}
+
+static int xiic_read_rx(struct xilinx_xiic_priv *priv,
+			struct i2c_msg *msg, int nmsgs)
+{
+	u8 bytes_in_fifo;
+	u32 pos = 0;
+	int i, ret;
+
+	while (pos < msg->len) {
+		ret = wait_for_bit_8(priv->base + XIIC_SR_REG_OFFSET,
+				     XIIC_SR_RX_FIFO_EMPTY_MASK, false,
+				     1000, true);
+		if (ret)
+			return ret;
+
+		bytes_in_fifo = readb(priv->base + XIIC_RFO_REG_OFFSET) + 1;
+
+		if (bytes_in_fifo > msg->len)
+			bytes_in_fifo = msg->len;
+
+		for (i = 0; i < bytes_in_fifo; i++) {
+			msg->buf[pos++] = readb(priv->base +
+						XIIC_DRR_REG_OFFSET);
+		}
+	}
+
+	return 0;
+}
+
+static int xiic_tx_fifo_space(struct xilinx_xiic_priv *priv)
+{
+	/* return the actual space left in the FIFO */
+	return IIC_TX_FIFO_DEPTH - readb(priv->base + XIIC_TFO_REG_OFFSET) - 1;
+}
+
+static void xiic_fill_tx_fifo(struct xilinx_xiic_priv *priv,
+			      struct i2c_msg *msg, int nmsgs)
+{
+	u8 fifo_space = xiic_tx_fifo_space(priv);
+	int len = msg->len;
+	u32 pos = 0;
+
+	len = (len > fifo_space) ? fifo_space : len;
+
+	while (len--) {
+		u16 data = msg->buf[pos++];
+
+		if (pos == len && nmsgs == 1) {
+			/* last message in transfer -> STOP */
+			data |= XIIC_TX_DYN_STOP_MASK;
+		}
+		writew(data, priv->base + XIIC_DTR_REG_OFFSET);
+	}
+}
+
+static void xilinx_xiic_set_addr(struct udevice *dev, u8 addr,
+				 u16 flags, u32 len, u32 nmsgs)
+{
+	struct xilinx_xiic_priv *priv = dev_get_priv(dev);
+
+	xiic_irq_clr(priv, XIIC_INTR_TX_ERROR_MASK);
+
+	if (!(flags & I2C_M_NOSTART)) {
+		/* write the address */
+		u16 data = i2c_8bit_addr_from_flags(addr, flags) |
+			XIIC_TX_DYN_START_MASK;
+		if (nmsgs == 1 && len == 0)
+			/* no data and last message -> add STOP */
+			data |= XIIC_TX_DYN_STOP_MASK;
+
+		writew(data, priv->base + XIIC_DTR_REG_OFFSET);
+	}
+}
+
+static int xilinx_xiic_read_common(struct udevice *dev, struct i2c_msg *msg,
+				   u32 nmsgs)
+{
+	struct xilinx_xiic_priv *priv = dev_get_priv(dev);
+	u8 rx_watermark;
+
+	/* Clear and enable Rx full interrupt. */
+	xiic_irq_clr(priv, XIIC_INTR_RX_FULL_MASK | XIIC_INTR_TX_ERROR_MASK);
+
+	/* we want to get all but last byte, because the TX_ERROR IRQ is used
+	 * to inidicate error ACK on the address, and negative ack on the last
+	 * received byte, so to not mix them receive all but last.
+	 * In the case where there is only one byte to receive
+	 * we can check if ERROR and RX full is set at the same time
+	 */
+	rx_watermark = msg->len;
+	if (rx_watermark > IIC_RX_FIFO_DEPTH)
+		rx_watermark = IIC_RX_FIFO_DEPTH;
+
+	writeb(rx_watermark - 1, priv->base + XIIC_RFD_REG_OFFSET);
+
+	xilinx_xiic_set_addr(dev, msg->addr, msg->flags, msg->len, nmsgs);
+
+	xiic_irq_clr(priv, XIIC_INTR_BNB_MASK);
+
+	writew((msg->len & 0xff) | ((nmsgs == 1) ? XIIC_TX_DYN_STOP_MASK : 0),
+	       priv->base + XIIC_DTR_REG_OFFSET);
+
+	if (nmsgs == 1)
+		/* very last, enable bus not busy as well */
+		xiic_irq_clr(priv, XIIC_INTR_BNB_MASK);
+
+	return xiic_read_rx(priv, msg, nmsgs);
+}
+
+static int xilinx_xiic_write_common(struct udevice *dev, struct i2c_msg *msg,
+				    int nmsgs)
+{
+	struct xilinx_xiic_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	xilinx_xiic_set_addr(dev, msg->addr, msg->flags, msg->len, nmsgs);
+	xiic_fill_tx_fifo(priv, msg, nmsgs);
+
+	ret = wait_for_bit_8(priv->base + XIIC_SR_REG_OFFSET,
+			     XIIC_SR_TX_FIFO_EMPTY_MASK, false, 1000, true);
+	if (ret)
+		return ret;
+
+	/* Clear any pending Tx empty, Tx Error and then enable them. */
+	xiic_irq_clr(priv, XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_ERROR_MASK |
+			   XIIC_INTR_BNB_MASK);
+
+	return 0;
+}
+
+static void xiic_clear_rx_fifo(struct xilinx_xiic_priv *priv)
+{
+	u8 sr;
+
+	for (sr = readb(priv->base + XIIC_SR_REG_OFFSET);
+		!(sr & XIIC_SR_RX_FIFO_EMPTY_MASK);
+		sr = readb(priv->base + XIIC_SR_REG_OFFSET))
+		readb(priv->base + XIIC_DRR_REG_OFFSET);
+}
+
+static void xiic_reinit(struct xilinx_xiic_priv *priv)
+{
+	writel(XIIC_RESET_MASK, priv->base + XIIC_RESETR_OFFSET);
+
+	/* Set receive Fifo depth to maximum (zero based). */
+	writeb(IIC_RX_FIFO_DEPTH - 1, priv->base + XIIC_RFD_REG_OFFSET);
+
+	/* Reset Tx Fifo. */
+	writeb(XIIC_CR_TX_FIFO_RESET_MASK, priv->base + XIIC_CR_REG_OFFSET);
+
+	/* Enable IIC Device, remove Tx Fifo reset & disable general call. */
+	writeb(XIIC_CR_ENABLE_DEVICE_MASK, priv->base + XIIC_CR_REG_OFFSET);
+
+	/* make sure RX fifo is empty */
+	xiic_clear_rx_fifo(priv);
+
+	/* Disable interrupts */
+	writel(0, priv->base + XIIC_DGIER_OFFSET);
+
+	xiic_irq_clr(priv, XIIC_INTR_ARB_LOST_MASK);
+}
+
+static int xilinx_xiic_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
+{
+	int ret = 0;
+
+	for (; nmsgs > 0; nmsgs--, msg++) {
+		if (msg->flags & I2C_M_RD)
+			ret = xilinx_xiic_read_common(dev, msg, nmsgs);
+		else
+			ret = xilinx_xiic_write_common(dev, msg, nmsgs);
+
+		if (ret)
+			return -EREMOTEIO;
+	}
+
+	return ret;
+}
+
+static int xilinx_xiic_probe_chip(struct udevice *dev, uint addr, uint flags)
+{
+	struct xilinx_xiic_priv *priv = dev_get_priv(dev);
+	u32 reg;
+	int ret;
+
+	xiic_reinit(priv);
+
+	xilinx_xiic_set_addr(dev, addr, 0, 0, 1);
+	ret = wait_for_bit_8(priv->base + XIIC_SR_REG_OFFSET,
+			     XIIC_SR_BUS_BUSY_MASK, false, 1000, true);
+	if (ret)
+		return ret;
+
+	reg = readl(priv->base + XIIC_IISR_OFFSET);
+	if (reg & XIIC_INTR_TX_ERROR_MASK)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int xilinx_xiic_set_speed(struct udevice *dev, uint speed)
+{
+	return 0;
+}
+
+static int xilinx_xiic_probe(struct udevice *dev)
+{
+	struct xilinx_xiic_priv *priv = dev_get_priv(dev);
+
+	priv->base = dev_read_addr_ptr(dev);
+
+	writel(XIIC_CR_TX_FIFO_RESET_MASK, priv->base + XIIC_CR_REG_OFFSET);
+	xiic_reinit(priv);
+
+	return 0;
+}
+
+static const struct dm_i2c_ops xilinx_xiic_ops = {
+	.xfer		= xilinx_xiic_xfer,
+	.probe_chip	= xilinx_xiic_probe_chip,
+	.set_bus_speed	= xilinx_xiic_set_speed,
+};
+
+static const struct udevice_id xilinx_xiic_ids[] = {
+	{ .compatible = "xlnx,xps-iic-2.00.a" },
+	{ }
+};
+
+U_BOOT_DRIVER(xilinx_xiic) = {
+	.name		= "xilinx_axi_i2c",
+	.id		= UCLASS_I2C,
+	.of_match	= xilinx_xiic_ids,
+	.probe		= xilinx_xiic_probe,
+	.priv_auto_alloc_size = sizeof(struct xilinx_xiic_priv),
+	.ops		= &xilinx_xiic_ops,
+};
diff --git a/drivers/misc/fs_loader.c b/drivers/misc/fs_loader.c
index baa5f83..57a14a3 100644
--- a/drivers/misc/fs_loader.c
+++ b/drivers/misc/fs_loader.c
@@ -16,9 +16,22 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-struct firmware_priv {
-	const char *name;	/* Filename */
-	u32 offset;		/* Offset of reading a file */
+/**
+ * struct firmware - A place for storing firmware and its attribute data.
+ *
+ * This holds information about a firmware and its content.
+ *
+ * @size: Size of a file
+ * @data: Buffer for file
+ * @priv: Firmware loader private fields
+ * @name: Filename
+ * @offset: Offset of reading a file
+ */
+struct firmware {
+	size_t size;
+	const u8 *data;
+	const char *name;
+	u32 offset;
 };
 
 #ifdef CONFIG_CMD_UBIFS
@@ -88,74 +101,42 @@
 /**
  * _request_firmware_prepare - Prepare firmware struct.
  *
+ * @dev: An instance of a driver.
  * @name: Name of firmware file.
  * @dbuf: Address of buffer to load firmware into.
  * @size: Size of buffer.
  * @offset: Offset of a file for start reading into buffer.
- * @firmwarep: Pointer to pointer to firmware image.
  *
  * Return: Negative value if fail, 0 for successful.
  */
-static int _request_firmware_prepare(const char *name, void *dbuf,
-				    size_t size, u32 offset,
-				    struct firmware **firmwarep)
+static int _request_firmware_prepare(struct udevice *dev,
+				    const char *name, void *dbuf,
+				    size_t size, u32 offset)
 {
 	if (!name || name[0] == '\0')
 		return -EINVAL;
 
-	/* No memory allocation is required if *firmwarep is allocated */
-	if (!(*firmwarep)) {
-		(*firmwarep) = calloc(1, sizeof(struct firmware));
-		if (!(*firmwarep))
-			return -ENOMEM;
+	struct firmware *firmwarep = dev_get_priv(dev);
 
-		(*firmwarep)->priv = calloc(1, sizeof(struct firmware_priv));
-		if (!(*firmwarep)->priv) {
-			free(*firmwarep);
-			return -ENOMEM;
-		}
-	} else if (!(*firmwarep)->priv) {
-		(*firmwarep)->priv = calloc(1, sizeof(struct firmware_priv));
-		if (!(*firmwarep)->priv) {
-			free(*firmwarep);
-			return -ENOMEM;
-		}
-	}
+	if (!firmwarep)
+		return -ENOMEM;
 
-	((struct firmware_priv *)((*firmwarep)->priv))->name = name;
-	((struct firmware_priv *)((*firmwarep)->priv))->offset = offset;
-	(*firmwarep)->data = dbuf;
-	(*firmwarep)->size = size;
+	firmwarep->name = name;
+	firmwarep->offset = offset;
+	firmwarep->data = dbuf;
+	firmwarep->size = size;
 
 	return 0;
 }
 
 /**
- * release_firmware - Release the resource associated with a firmware image
- * @firmware: Firmware resource to release
- */
-void release_firmware(struct firmware *firmware)
-{
-	if (firmware) {
-		if (firmware->priv) {
-			free(firmware->priv);
-			firmware->priv = NULL;
-		}
-		free(firmware);
-	}
-}
-
-/**
  * fw_get_filesystem_firmware - load firmware into an allocated buffer.
- * @plat: Platform data such as storage and partition firmware loading from.
- * @firmware: pointer to firmware image.
+ * @dev: An instance of a driver.
  *
  * Return: Size of total read, negative value when error.
  */
-static int fw_get_filesystem_firmware(struct device_platdata *plat,
-				     struct firmware *firmware)
+static int fw_get_filesystem_firmware(struct udevice *dev)
 {
-	struct firmware_priv *fw_priv = NULL;
 	loff_t actread;
 	char *storage_interface, *dev_part, *ubi_mtdpart, *ubi_volume;
 	int ret;
@@ -178,20 +159,23 @@
 		else
 			ret = -ENODEV;
 	} else {
-		ret = select_fs_dev(plat);
+		ret = select_fs_dev(dev->platdata);
 	}
 
 	if (ret)
 		goto out;
 
-	fw_priv = firmware->priv;
+	struct firmware *firmwarep = dev_get_priv(dev);
 
-	ret = fs_read(fw_priv->name, (ulong)map_to_sysmem(firmware->data),
-			fw_priv->offset, firmware->size, &actread);
+	if (!firmwarep)
+		return -ENOMEM;
+
+	ret = fs_read(firmwarep->name, (ulong)map_to_sysmem(firmwarep->data),
+			firmwarep->offset, firmwarep->size, &actread);
 
 	if (ret) {
 		debug("Error: %d Failed to read %s from flash %lld != %zu.\n",
-		      ret, fw_priv->name, actread, firmware->size);
+		      ret, firmwarep->name, actread, firmwarep->size);
 	} else {
 		ret = actread;
 	}
@@ -205,33 +189,30 @@
 
 /**
  * request_firmware_into_buf - Load firmware into a previously allocated buffer.
- * @plat: Platform data such as storage and partition firmware loading from.
+ * @dev: An instance of a driver.
  * @name: Name of firmware file.
  * @buf: Address of buffer to load firmware into.
  * @size: Size of buffer.
  * @offset: Offset of a file for start reading into buffer.
- * @firmwarep: Pointer to firmware image.
  *
- * The firmware is loaded directly into the buffer pointed to by @buf and
- * the @firmwarep data member is pointed at @buf.
+ * The firmware is loaded directly into the buffer pointed to by @buf.
  *
  * Return: Size of total read, negative value when error.
  */
-int request_firmware_into_buf(struct device_platdata *plat,
+int request_firmware_into_buf(struct udevice *dev,
 			      const char *name,
-			      void *buf, size_t size, u32 offset,
-			      struct firmware **firmwarep)
+			      void *buf, size_t size, u32 offset)
 {
 	int ret;
 
-	if (!plat)
+	if (!dev)
 		return -EINVAL;
 
-	ret = _request_firmware_prepare(name, buf, size, offset, firmwarep);
+	ret = _request_firmware_prepare(dev, name, buf, size, offset);
 	if (ret < 0) /* error */
 		return ret;
 
-	ret = fw_get_filesystem_firmware(plat, *firmwarep);
+	ret = fw_get_filesystem_firmware(dev);
 
 	return ret;
 }
@@ -286,6 +267,7 @@
 	.probe			= fs_loader_probe,
 	.ofdata_to_platdata	= fs_loader_ofdata_to_platdata,
 	.platdata_auto_alloc_size	= sizeof(struct device_platdata),
+	.priv_auto_alloc_size	= sizeof(struct firmware),
 };
 
 UCLASS_DRIVER(fs_loader) = {
diff --git a/drivers/mmc/hi6220_dw_mmc.c b/drivers/mmc/hi6220_dw_mmc.c
index ce395d5..cc58aff 100644
--- a/drivers/mmc/hi6220_dw_mmc.c
+++ b/drivers/mmc/hi6220_dw_mmc.c
@@ -5,51 +5,89 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <dwmmc.h>
+#include <errno.h>
+#include <fdtdec.h>
 #include <malloc.h>
-#include <linux/errno.h>
 
-#define	DWMMC_MAX_CH_NUM		4
+DECLARE_GLOBAL_DATA_PTR;
 
-#define	DWMMC_MAX_FREQ			50000000
-#define	DWMMC_MIN_FREQ			400000
+struct hi6220_dwmmc_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
 
-/* Source clock is configured to 100MHz by ATF bl1*/
-#define MMC0_DEFAULT_FREQ		100000000
+struct hi6220_dwmmc_priv_data {
+	struct dwmci_host host;
+};
 
-static int hi6220_dwmci_core_init(struct dwmci_host *host, int index)
+static int hi6220_dwmmc_ofdata_to_platdata(struct udevice *dev)
 {
-	host->name = "Hisilicon DWMMC";
+	struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev);
+	struct dwmci_host *host = &priv->host;
 
-	host->dev_index = index;
+	host->name = dev->name;
+	host->ioaddr = (void *)devfdt_get_addr(dev);
+	host->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+					"bus-width", 4);
 
-	/* 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);
-		return -1;
-	}
+	/* use non-removable property for differentiating SD card and eMMC */
+	if (dev_read_bool(dev, "non-removable"))
+		host->dev_index = 0;
+	else
+		host->dev_index = 1;
+
+	host->priv = priv;
+
 	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'.
- */
-int hi6220_dwmci_add_port(int index, u32 regbase, int bus_width)
+static int hi6220_dwmmc_probe(struct udevice *dev)
 {
-	struct dwmci_host *host = NULL;
+	struct hi6220_dwmmc_plat *plat = dev_get_platdata(dev);
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev);
+	struct dwmci_host *host = &priv->host;
+
+	/* Use default bus speed due to absence of clk driver */
+	host->bus_hz = 50000000;
 
-	host = calloc(1, sizeof(struct dwmci_host));
-	if (!host) {
-		pr_err("dwmci_host calloc failed!\n");
-		return -ENOMEM;
-	}
+	dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, 400000);
+	host->mmc = &plat->mmc;
 
-	host->ioaddr = (void *)(ulong)regbase;
-	host->buswidth = bus_width;
-	host->bus_hz = MMC0_DEFAULT_FREQ;
+	host->mmc->priv = &priv->host;
+	upriv->mmc = host->mmc;
+	host->mmc->dev = dev;
 
-	return hi6220_dwmci_core_init(host, index);
+	return dwmci_probe(dev);
 }
+
+static int hi6220_dwmmc_bind(struct udevice *dev)
+{
+	struct hi6220_dwmmc_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 hi6220_dwmmc_ids[] = {
+	{ .compatible = "hisilicon,hi6220-dw-mshc" },
+	{ }
+};
+
+U_BOOT_DRIVER(hi6220_dwmmc_drv) = {
+	.name = "hi6220_dwmmc",
+	.id = UCLASS_MMC,
+	.of_match = hi6220_dwmmc_ids,
+	.ofdata_to_platdata = hi6220_dwmmc_ofdata_to_platdata,
+	.ops = &dm_dwmci_ops,
+	.bind = hi6220_dwmmc_bind,
+	.probe = hi6220_dwmmc_probe,
+	.priv_auto_alloc_size = sizeof(struct hi6220_dwmmc_priv_data),
+	.platdata_auto_alloc_size = sizeof(struct hi6220_dwmmc_plat),
+};
diff --git a/drivers/mmc/jz_mmc.c b/drivers/mmc/jz_mmc.c
index 3132c3e..cb2a7c3 100644
--- a/drivers/mmc/jz_mmc.c
+++ b/drivers/mmc/jz_mmc.c
@@ -134,6 +134,60 @@
 	return 24000000;
 }
 
+#if CONFIG_IS_ENABLED(MMC_WRITE)
+static inline void jz_mmc_write_data(struct jz_mmc_priv *priv, struct mmc_data *data)
+{
+	int sz = DIV_ROUND_UP(data->blocks * data->blocksize, 4);
+	const void *buf = data->src;
+
+	while (sz--) {
+		u32 val = get_unaligned_le32(buf);
+
+		wait_for_bit_le32(priv->regs + MSC_IREG,
+				  MSC_IREG_TXFIFO_WR_REQ,
+				  true, 10000, false);
+		writel(val, priv->regs + MSC_TXFIFO);
+		buf += 4;
+	}
+}
+#else
+static void jz_mmc_write_data(struct jz_mmc_priv *priv, struct mmc_data *data)
+{}
+#endif
+
+static inline int jz_mmc_read_data(struct jz_mmc_priv *priv, struct mmc_data *data)
+{
+	int sz = data->blocks * data->blocksize;
+	void *buf = data->dest;
+	u32 stat, val;
+
+	do {
+		stat = readl(priv->regs + MSC_STAT);
+
+		if (stat & MSC_STAT_TIME_OUT_READ)
+			return -ETIMEDOUT;
+		if (stat & MSC_STAT_CRC_READ_ERROR)
+			return -EINVAL;
+		if (stat & MSC_STAT_DATA_FIFO_EMPTY) {
+			udelay(10);
+			continue;
+		}
+		do {
+			val = readl(priv->regs + MSC_RXFIFO);
+			if (sz == 1)
+				*(u8 *)buf = (u8)val;
+			else if (sz == 2)
+				put_unaligned_le16(val, buf);
+			else if (sz >= 4)
+				put_unaligned_le32(val, buf);
+			buf += 4;
+			sz -= 4;
+			stat = readl(priv->regs + MSC_STAT);
+		} while (!(stat & MSC_STAT_DATA_FIFO_EMPTY));
+	} while (!(stat & MSC_STAT_DATA_TRAN_DONE));
+	return 0;
+}
+
 static int jz_mmc_send_cmd(struct mmc *mmc, struct jz_mmc_priv *priv,
 			   struct mmc_cmd *cmd, struct mmc_data *data)
 {
@@ -249,51 +303,14 @@
 			cmd->response[0] |= readw(priv->regs + MSC_RES) & 0xff;
 		}
 	}
-
-	if (data && (data->flags & MMC_DATA_WRITE)) {
-		/* write the data */
-		int sz = DIV_ROUND_UP(data->blocks * data->blocksize, 4);
-		const void *buf = data->src;
-
-		while (sz--) {
-			u32 val = get_unaligned_le32(buf);
-
-			wait_for_bit_le32(priv->regs + MSC_IREG,
-					  MSC_IREG_TXFIFO_WR_REQ,
-					  true, 10000, false);
-			writel(val, priv->regs + MSC_TXFIFO);
-			buf += 4;
+	if (data) {
+		if (data->flags & MMC_DATA_WRITE)
+			jz_mmc_write_data(priv, data);
+		else if (data->flags & MMC_DATA_READ) {
+			ret = jz_mmc_read_data(priv, data);
+			if (ret)
+				return ret;
 		}
-	} else if (data && (data->flags & MMC_DATA_READ)) {
-		/* read the data */
-		int sz = data->blocks * data->blocksize;
-		void *buf = data->dest;
-
-		do {
-			stat = readl(priv->regs + MSC_STAT);
-
-			if (stat & MSC_STAT_TIME_OUT_READ)
-				return -ETIMEDOUT;
-			if (stat & MSC_STAT_CRC_READ_ERROR)
-				return -EINVAL;
-			if (stat & MSC_STAT_DATA_FIFO_EMPTY) {
-				udelay(10);
-				continue;
-			}
-			do {
-				u32 val = readl(priv->regs + MSC_RXFIFO);
-
-				if (sz == 1)
-					*(u8 *)buf = (u8)val;
-				else if (sz == 2)
-					put_unaligned_le16(val, buf);
-				else if (sz >= 4)
-					put_unaligned_le32(val, buf);
-				buf += 4;
-				sz -= 4;
-				stat = readl(priv->regs + MSC_STAT);
-			} while (!(stat & MSC_STAT_DATA_FIFO_EMPTY));
-		} while (!(stat & MSC_STAT_DATA_TRAN_DONE));
 	}
 
 	return 0;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index d858127..84d157ff 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -754,7 +754,8 @@
 }
 
 #if !CONFIG_IS_ENABLED(MMC_TINY)
-static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode)
+static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode,
+			      bool hsdowngrade)
 {
 	int err;
 	int speed_bits;
@@ -788,6 +789,20 @@
 	if (err)
 		return err;
 
+#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+    CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
+	/*
+	 * In case the eMMC is in HS200/HS400 mode and we are downgrading
+	 * to HS mode, the card clock are still running much faster than
+	 * the supported HS mode clock, so we can not reliably read out
+	 * Extended CSD. Reconfigure the controller to run at HS mode.
+	 */
+	if (hsdowngrade) {
+		mmc_select_mode(mmc, MMC_HS);
+		mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS), false);
+	}
+#endif
+
 	if ((mode == MMC_HS) || (mode == MMC_HS_52)) {
 		/* Now check to see that it worked */
 		err = mmc_send_ext_csd(mmc, test_csd);
@@ -1849,7 +1864,7 @@
 	int err;
 
 	/* Set timing to HS200 for tuning */
-	err = mmc_set_card_speed(mmc, MMC_HS_200);
+	err = mmc_set_card_speed(mmc, MMC_HS_200, false);
 	if (err)
 		return err;
 
@@ -1865,7 +1880,7 @@
 	}
 
 	/* Set back to HS */
-	mmc_set_card_speed(mmc, MMC_HS);
+	mmc_set_card_speed(mmc, MMC_HS, false);
 	mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS), false);
 
 	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
@@ -1873,7 +1888,7 @@
 	if (err)
 		return err;
 
-	err = mmc_set_card_speed(mmc, MMC_HS_400);
+	err = mmc_set_card_speed(mmc, MMC_HS_400, false);
 	if (err)
 		return err;
 
@@ -1920,7 +1935,19 @@
 		return -ENOTSUPP;
 	}
 
-	mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE);
+#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+    CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
+	/*
+	 * In case the eMMC is in HS200/HS400 mode, downgrade to HS mode
+	 * before doing anything else, since a transition from either of
+	 * the HS200/HS400 mode directly to legacy mode is not supported.
+	 */
+	if (mmc->selected_mode == MMC_HS_200 ||
+	    mmc->selected_mode == MMC_HS_400)
+		mmc_set_card_speed(mmc, MMC_HS, true);
+	else
+#endif
+		mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE);
 
 	for_each_mmc_mode_by_pref(card_caps, mwt) {
 		for_each_supported_width(card_caps & mwt->widths,
@@ -1952,7 +1979,7 @@
 				}
 			} else {
 				/* configure the bus speed (card) */
-				err = mmc_set_card_speed(mmc, mwt->mode);
+				err = mmc_set_card_speed(mmc, mwt->mode, false);
 				if (err)
 					goto error;
 
diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c
index b8acc33..c8c83c9 100644
--- a/drivers/mmc/mmc_write.c
+++ b/drivers/mmc/mmc_write.c
@@ -65,13 +65,13 @@
 	return err;
 }
 
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
 ulong mmc_berase(struct udevice *dev, lbaint_t start, lbaint_t blkcnt)
 #else
 ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt)
 #endif
 {
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
 	struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
 #endif
 	int dev_num = block_dev->devnum;
@@ -183,7 +183,7 @@
 	return blkcnt;
 }
 
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
 ulong mmc_bwrite(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
 		 const void *src)
 #else
@@ -191,7 +191,7 @@
 		 const void *src)
 #endif
 {
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
 	struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
 #endif
 	int dev_num = block_dev->devnum;
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index fd1723f..ffc6cc9 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -9,6 +9,12 @@
 	  This option, if enabled, provides more flexible and linux-like
 	  NAND initialization process.
 
+config SYS_NAND_DRIVER_ECC_LAYOUT
+	bool
+	help
+	  Omit standard ECC layouts to safe space. Select this if your driver
+	  is known to provide its own ECC layout.
+
 config NAND_ATMEL
 	bool "Support Atmel NAND controller"
 	imply SYS_NAND_USE_FLASH_BBT
@@ -81,6 +87,7 @@
 config NAND_VF610_NFC
 	bool "Support for Freescale NFC for VF610"
 	select SYS_NAND_SELF_INIT
+	select SYS_NAND_DRIVER_ECC_LAYOUT
 	imply CMD_NAND
 	help
 	  Enables support for NAND Flash Controller on some Freescale
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 92daebe..6d2ff58 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -47,6 +47,7 @@
 #include <linux/errno.h>
 
 /* Define default oob placement schemes for large and small page devices */
+#ifdef CONFIG_SYS_NAND_DRIVER_ECC_LAYOUT
 static struct nand_ecclayout nand_oob_8 = {
 	.eccbytes = 3,
 	.eccpos = {0, 1, 2},
@@ -89,6 +90,7 @@
 		{.offset = 2,
 		 .length = 78} }
 };
+#endif
 
 static int nand_get_device(struct mtd_info *mtd, int new_state);
 
@@ -4339,6 +4341,7 @@
 	 */
 	if (!ecc->layout && (ecc->mode != NAND_ECC_SOFT_BCH)) {
 		switch (mtd->oobsize) {
+#ifdef CONFIG_SYS_NAND_DRIVER_ECC_LAYOUT
 		case 8:
 			ecc->layout = &nand_oob_8;
 			break;
@@ -4351,6 +4354,7 @@
 		case 128:
 			ecc->layout = &nand_oob_128;
 			break;
+#endif
 		default:
 			pr_warn("No oob scheme defined for oobsize %d\n",
 				   mtd->oobsize);
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 7044c6a..ff55e03 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -513,4 +513,14 @@
 	  This driver implements support for the (Enhanced) Three-Speed
 	  Ethernet Controller found on Freescale SoCs.
 
+config MEDIATEK_ETH
+	bool "MediaTek Ethernet GMAC Driver"
+	depends on DM_ETH
+	select PHYLIB
+	select DM_GPIO
+	select DM_RESET
+	help
+	  This Driver support MediaTek Ethernet GMAC
+	  Say Y to enable support for the MediaTek Ethernet GMAC.
+
 endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 0dbfa03..ee7f3e7 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -74,3 +74,4 @@
 obj-$(CONFIG_FSL_PFE) += pfe_eth/
 obj-$(CONFIG_SNI_AVE) += sni_ave.o
 obj-y += ti/
+obj-$(CONFIG_MEDIATEK_ETH) += mtk_eth.o
diff --git a/drivers/net/bcm6368-eth.c b/drivers/net/bcm6368-eth.c
index a31efba..110985e 100644
--- a/drivers/net/bcm6368-eth.c
+++ b/drivers/net/bcm6368-eth.c
@@ -309,6 +309,43 @@
 	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
 	uint8_t i;
 
+	/* disable all ports */
+	for (i = 0; i < priv->num_ports; i++) {
+		setbits_8(priv->base + ETH_PORTOV_REG(i),
+			  ETH_PORTOV_ENABLE_MASK);
+		setbits_8(priv->base + ETH_PTCTRL_REG(i),
+			  ETH_PTCTRL_RXDIS_MASK | ETH_PTCTRL_TXDIS_MASK);
+		priv->sw_port_link[i] = 0;
+	}
+
+	/* enable external ports */
+	for (i = ETH_RGMII_PORT0; i < priv->num_ports; i++) {
+		u8 rgmii_ctrl = ETH_RGMII_CTRL_GMII_CLK_EN;
+
+		if (!priv->used_ports[i].used)
+			continue;
+
+		if (priv->rgmii_override)
+			rgmii_ctrl |= ETH_RGMII_CTRL_MII_OVERRIDE_EN;
+		if (priv->rgmii_timing)
+			rgmii_ctrl |= ETH_RGMII_CTRL_TIMING_SEL_EN;
+
+		setbits_8(priv->base + ETH_RGMII_CTRL_REG(i), rgmii_ctrl);
+	}
+
+	/* reset mib */
+	setbits_8(priv->base + ETH_GMCR_REG, ETH_GMCR_RST_MIB_MASK);
+	mdelay(1);
+	clrbits_8(priv->base + ETH_GMCR_REG, ETH_GMCR_RST_MIB_MASK);
+	mdelay(1);
+
+	/* force CPU port state */
+	setbits_8(priv->base + ETH_IMPOV_REG,
+		  ETH_IMPOV_FORCE_MASK | ETH_IMPOV_LINKUP_MASK);
+
+	/* enable switch forward engine */
+	setbits_8(priv->base + ETH_SWMODE_REG, ETH_SWMODE_FWD_EN_MASK);
+
 	/* prepare rx dma buffers */
 	for (i = 0; i < ETH_RX_DESC; i++) {
 		int ret = dma_prepare_rcv_buf(&priv->rx_dma, net_rx_packets[i],
@@ -368,6 +405,31 @@
 static void bcm6368_eth_stop(struct udevice *dev)
 {
 	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+	uint8_t i;
+
+	/* disable all ports */
+	for (i = 0; i < priv->num_ports; i++) {
+		setbits_8(priv->base + ETH_PORTOV_REG(i),
+			  ETH_PORTOV_ENABLE_MASK);
+		setbits_8(priv->base + ETH_PTCTRL_REG(i),
+			  ETH_PTCTRL_RXDIS_MASK | ETH_PTCTRL_TXDIS_MASK);
+	}
+
+	/* disable external ports */
+	for (i = ETH_RGMII_PORT0; i < priv->num_ports; i++) {
+		if (!priv->used_ports[i].used)
+			continue;
+
+		clrbits_8(priv->base + ETH_RGMII_CTRL_REG(i),
+			  ETH_RGMII_CTRL_GMII_CLK_EN);
+	}
+
+	/* disable CPU port */
+	clrbits_8(priv->base + ETH_IMPOV_REG,
+		  ETH_IMPOV_FORCE_MASK | ETH_IMPOV_LINKUP_MASK);
+
+	/* disable switch forward engine */
+	clrbits_8(priv->base + ETH_SWMODE_REG, ETH_SWMODE_FWD_EN_MASK);
 
 	/* disable dma rx channel */
 	dma_disable(&priv->rx_dma);
@@ -444,7 +506,6 @@
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
 	int num_ports, ret, i;
-	uint32_t val;
 	ofnode node;
 
 	/* get base address */
@@ -561,52 +622,6 @@
 	if (ret)
 		return ret;
 
-	/* disable all ports */
-	for (i = 0; i < priv->num_ports; i++) {
-		writeb_be(ETH_PORTOV_ENABLE_MASK,
-			      priv->base + ETH_PORTOV_REG(i));
-		writeb_be(ETH_PTCTRL_RXDIS_MASK |
-			      ETH_PTCTRL_TXDIS_MASK,
-			      priv->base + ETH_PTCTRL_REG(i));
-
-		priv->sw_port_link[i] = 0;
-	}
-
-	/* enable external ports */
-	for (i = ETH_RGMII_PORT0; i < priv->num_ports; i++) {
-		u8 rgmii_ctrl;
-
-		if (!priv->used_ports[i].used)
-			continue;
-
-		rgmii_ctrl = readb_be(priv->base + ETH_RGMII_CTRL_REG(i));
-		rgmii_ctrl |= ETH_RGMII_CTRL_GMII_CLK_EN;
-		if (priv->rgmii_override)
-			rgmii_ctrl |= ETH_RGMII_CTRL_MII_OVERRIDE_EN;
-		if (priv->rgmii_timing)
-			rgmii_ctrl |= ETH_RGMII_CTRL_TIMING_SEL_EN;
-		writeb_be(rgmii_ctrl, priv->base + ETH_RGMII_CTRL_REG(i));
-	}
-
-	/* reset mib */
-	val = readb_be(priv->base + ETH_GMCR_REG);
-	val |= ETH_GMCR_RST_MIB_MASK;
-	writeb_be(val, priv->base + ETH_GMCR_REG);
-	mdelay(1);
-	val &= ~ETH_GMCR_RST_MIB_MASK;
-	writeb_be(val, priv->base + ETH_GMCR_REG);
-	mdelay(1);
-
-	/* force CPU port state */
-	val = readb_be(priv->base + ETH_IMPOV_REG);
-	val |= ETH_IMPOV_FORCE_MASK | ETH_IMPOV_LINKUP_MASK;
-	writeb_be(val, priv->base + ETH_IMPOV_REG);
-
-	/* enable switch forward engine */
-	val = readb_be(priv->base + ETH_SWMODE_REG);
-	val |= ETH_SWMODE_FWD_EN_MASK;
-	writeb_be(val, priv->base + ETH_SWMODE_REG);
-
 	/* enable jumbo on all ports */
 	writel_be(0x1ff, priv->base + ETH_JMBCTL_PORT_REG);
 	writew_be(9728, priv->base + ETH_JMBCTL_MAXSIZE_REG);
diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c
new file mode 100644
index 0000000..cc09404
--- /dev/null
+++ b/drivers/net/mtk_eth.c
@@ -0,0 +1,1175 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ * Author: Mark Lee <mark-mc.lee@mediatek.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <miiphy.h>
+#include <regmap.h>
+#include <reset.h>
+#include <syscon.h>
+#include <wait_bit.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <linux/err.h>
+#include <linux/ioport.h>
+#include <linux/mdio.h>
+#include <linux/mii.h>
+
+#include "mtk_eth.h"
+
+#define NUM_TX_DESC		24
+#define NUM_RX_DESC		24
+#define TX_TOTAL_BUF_SIZE	(NUM_TX_DESC * PKTSIZE_ALIGN)
+#define RX_TOTAL_BUF_SIZE	(NUM_RX_DESC * PKTSIZE_ALIGN)
+#define TOTAL_PKT_BUF_SIZE	(TX_TOTAL_BUF_SIZE + RX_TOTAL_BUF_SIZE)
+
+#define MT7530_NUM_PHYS		5
+#define MT7530_DFL_SMI_ADDR	31
+
+#define MT7530_PHY_ADDR(base, addr) \
+	(((base) + (addr)) & 0x1f)
+
+#define GDMA_FWD_TO_CPU \
+	(0x20000000 | \
+	GDM_ICS_EN | \
+	GDM_TCS_EN | \
+	GDM_UCS_EN | \
+	STRP_CRC | \
+	(DP_PDMA << MYMAC_DP_S) | \
+	(DP_PDMA << BC_DP_S) | \
+	(DP_PDMA << MC_DP_S) | \
+	(DP_PDMA << UN_DP_S))
+
+#define GDMA_FWD_DISCARD \
+	(0x20000000 | \
+	GDM_ICS_EN | \
+	GDM_TCS_EN | \
+	GDM_UCS_EN | \
+	STRP_CRC | \
+	(DP_DISCARD << MYMAC_DP_S) | \
+	(DP_DISCARD << BC_DP_S) | \
+	(DP_DISCARD << MC_DP_S) | \
+	(DP_DISCARD << UN_DP_S))
+
+struct pdma_rxd_info1 {
+	u32 PDP0;
+};
+
+struct pdma_rxd_info2 {
+	u32 PLEN1 : 14;
+	u32 LS1 : 1;
+	u32 UN_USED : 1;
+	u32 PLEN0 : 14;
+	u32 LS0 : 1;
+	u32 DDONE : 1;
+};
+
+struct pdma_rxd_info3 {
+	u32 PDP1;
+};
+
+struct pdma_rxd_info4 {
+	u32 FOE_ENTRY : 14;
+	u32 CRSN : 5;
+	u32 SP : 3;
+	u32 L4F : 1;
+	u32 L4VLD : 1;
+	u32 TACK : 1;
+	u32 IP4F : 1;
+	u32 IP4 : 1;
+	u32 IP6 : 1;
+	u32 UN_USED : 4;
+};
+
+struct pdma_rxdesc {
+	struct pdma_rxd_info1 rxd_info1;
+	struct pdma_rxd_info2 rxd_info2;
+	struct pdma_rxd_info3 rxd_info3;
+	struct pdma_rxd_info4 rxd_info4;
+};
+
+struct pdma_txd_info1 {
+	u32 SDP0;
+};
+
+struct pdma_txd_info2 {
+	u32 SDL1 : 14;
+	u32 LS1 : 1;
+	u32 BURST : 1;
+	u32 SDL0 : 14;
+	u32 LS0 : 1;
+	u32 DDONE : 1;
+};
+
+struct pdma_txd_info3 {
+	u32 SDP1;
+};
+
+struct pdma_txd_info4 {
+	u32 VLAN_TAG : 16;
+	u32 INS : 1;
+	u32 RESV : 2;
+	u32 UDF : 6;
+	u32 FPORT : 3;
+	u32 TSO : 1;
+	u32 TUI_CO : 3;
+};
+
+struct pdma_txdesc {
+	struct pdma_txd_info1 txd_info1;
+	struct pdma_txd_info2 txd_info2;
+	struct pdma_txd_info3 txd_info3;
+	struct pdma_txd_info4 txd_info4;
+};
+
+enum mtk_switch {
+	SW_NONE,
+	SW_MT7530
+};
+
+enum mtk_soc {
+	SOC_MT7623,
+	SOC_MT7629
+};
+
+struct mtk_eth_priv {
+	char pkt_pool[TOTAL_PKT_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN);
+
+	struct pdma_txdesc *tx_ring_noc;
+	struct pdma_rxdesc *rx_ring_noc;
+
+	int rx_dma_owner_idx0;
+	int tx_cpu_owner_idx0;
+
+	void __iomem *fe_base;
+	void __iomem *gmac_base;
+	void __iomem *ethsys_base;
+
+	struct mii_dev *mdio_bus;
+	int (*mii_read)(struct mtk_eth_priv *priv, u8 phy, u8 reg);
+	int (*mii_write)(struct mtk_eth_priv *priv, u8 phy, u8 reg, u16 val);
+	int (*mmd_read)(struct mtk_eth_priv *priv, u8 addr, u8 devad, u16 reg);
+	int (*mmd_write)(struct mtk_eth_priv *priv, u8 addr, u8 devad, u16 reg,
+			 u16 val);
+
+	enum mtk_soc soc;
+	int gmac_id;
+	int force_mode;
+	int speed;
+	int duplex;
+
+	struct phy_device *phydev;
+	int phy_interface;
+	int phy_addr;
+
+	enum mtk_switch sw;
+	int (*switch_init)(struct mtk_eth_priv *priv);
+	u32 mt7530_smi_addr;
+	u32 mt7530_phy_base;
+
+	struct gpio_desc rst_gpio;
+	int mcm;
+
+	struct reset_ctl rst_fe;
+	struct reset_ctl rst_mcm;
+};
+
+static void mtk_pdma_write(struct mtk_eth_priv *priv, u32 reg, u32 val)
+{
+	writel(val, priv->fe_base + PDMA_BASE + reg);
+}
+
+static void mtk_pdma_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr,
+			 u32 set)
+{
+	clrsetbits_le32(priv->fe_base + PDMA_BASE + reg, clr, set);
+}
+
+static void mtk_gdma_write(struct mtk_eth_priv *priv, int no, u32 reg,
+			   u32 val)
+{
+	u32 gdma_base;
+
+	if (no == 1)
+		gdma_base = GDMA2_BASE;
+	else
+		gdma_base = GDMA1_BASE;
+
+	writel(val, priv->fe_base + gdma_base + reg);
+}
+
+static u32 mtk_gmac_read(struct mtk_eth_priv *priv, u32 reg)
+{
+	return readl(priv->gmac_base + reg);
+}
+
+static void mtk_gmac_write(struct mtk_eth_priv *priv, u32 reg, u32 val)
+{
+	writel(val, priv->gmac_base + reg);
+}
+
+static void mtk_gmac_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr, u32 set)
+{
+	clrsetbits_le32(priv->gmac_base + reg, clr, set);
+}
+
+static void mtk_ethsys_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr,
+			   u32 set)
+{
+	clrsetbits_le32(priv->ethsys_base + reg, clr, set);
+}
+
+/* Direct MDIO clause 22/45 access via SoC */
+static int mtk_mii_rw(struct mtk_eth_priv *priv, u8 phy, u8 reg, u16 data,
+		      u32 cmd, u32 st)
+{
+	int ret;
+	u32 val;
+
+	val = (st << MDIO_ST_S) |
+	      ((cmd << MDIO_CMD_S) & MDIO_CMD_M) |
+	      (((u32)phy << MDIO_PHY_ADDR_S) & MDIO_PHY_ADDR_M) |
+	      (((u32)reg << MDIO_REG_ADDR_S) & MDIO_REG_ADDR_M);
+
+	if (cmd == MDIO_CMD_WRITE)
+		val |= data & MDIO_RW_DATA_M;
+
+	mtk_gmac_write(priv, GMAC_PIAC_REG, val | PHY_ACS_ST);
+
+	ret = wait_for_bit_le32(priv->gmac_base + GMAC_PIAC_REG,
+				PHY_ACS_ST, 0, 5000, 0);
+	if (ret) {
+		pr_warn("MDIO access timeout\n");
+		return ret;
+	}
+
+	if (cmd == MDIO_CMD_READ) {
+		val = mtk_gmac_read(priv, GMAC_PIAC_REG);
+		return val & MDIO_RW_DATA_M;
+	}
+
+	return 0;
+}
+
+/* Direct MDIO clause 22 read via SoC */
+static int mtk_mii_read(struct mtk_eth_priv *priv, u8 phy, u8 reg)
+{
+	return mtk_mii_rw(priv, phy, reg, 0, MDIO_CMD_READ, MDIO_ST_C22);
+}
+
+/* Direct MDIO clause 22 write via SoC */
+static int mtk_mii_write(struct mtk_eth_priv *priv, u8 phy, u8 reg, u16 data)
+{
+	return mtk_mii_rw(priv, phy, reg, data, MDIO_CMD_WRITE, MDIO_ST_C22);
+}
+
+/* Direct MDIO clause 45 read via SoC */
+static int mtk_mmd_read(struct mtk_eth_priv *priv, u8 addr, u8 devad, u16 reg)
+{
+	int ret;
+
+	ret = mtk_mii_rw(priv, addr, devad, reg, MDIO_CMD_ADDR, MDIO_ST_C45);
+	if (ret)
+		return ret;
+
+	return mtk_mii_rw(priv, addr, devad, 0, MDIO_CMD_READ_C45,
+			  MDIO_ST_C45);
+}
+
+/* Direct MDIO clause 45 write via SoC */
+static int mtk_mmd_write(struct mtk_eth_priv *priv, u8 addr, u8 devad,
+			 u16 reg, u16 val)
+{
+	int ret;
+
+	ret = mtk_mii_rw(priv, addr, devad, reg, MDIO_CMD_ADDR, MDIO_ST_C45);
+	if (ret)
+		return ret;
+
+	return mtk_mii_rw(priv, addr, devad, val, MDIO_CMD_WRITE,
+			  MDIO_ST_C45);
+}
+
+/* Indirect MDIO clause 45 read via MII registers */
+static int mtk_mmd_ind_read(struct mtk_eth_priv *priv, u8 addr, u8 devad,
+			    u16 reg)
+{
+	int ret;
+
+	ret = priv->mii_write(priv, addr, MII_MMD_ACC_CTL_REG,
+			      (MMD_ADDR << MMD_CMD_S) |
+			      ((devad << MMD_DEVAD_S) & MMD_DEVAD_M));
+	if (ret)
+		return ret;
+
+	ret = priv->mii_write(priv, addr, MII_MMD_ADDR_DATA_REG, reg);
+	if (ret)
+		return ret;
+
+	ret = priv->mii_write(priv, addr, MII_MMD_ACC_CTL_REG,
+			      (MMD_DATA << MMD_CMD_S) |
+			      ((devad << MMD_DEVAD_S) & MMD_DEVAD_M));
+	if (ret)
+		return ret;
+
+	return priv->mii_read(priv, addr, MII_MMD_ADDR_DATA_REG);
+}
+
+/* Indirect MDIO clause 45 write via MII registers */
+static int mtk_mmd_ind_write(struct mtk_eth_priv *priv, u8 addr, u8 devad,
+			     u16 reg, u16 val)
+{
+	int ret;
+
+	ret = priv->mii_write(priv, addr, MII_MMD_ACC_CTL_REG,
+			      (MMD_ADDR << MMD_CMD_S) |
+			      ((devad << MMD_DEVAD_S) & MMD_DEVAD_M));
+	if (ret)
+		return ret;
+
+	ret = priv->mii_write(priv, addr, MII_MMD_ADDR_DATA_REG, reg);
+	if (ret)
+		return ret;
+
+	ret = priv->mii_write(priv, addr, MII_MMD_ACC_CTL_REG,
+			      (MMD_DATA << MMD_CMD_S) |
+			      ((devad << MMD_DEVAD_S) & MMD_DEVAD_M));
+	if (ret)
+		return ret;
+
+	return priv->mii_write(priv, addr, MII_MMD_ADDR_DATA_REG, val);
+}
+
+static int mtk_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
+{
+	struct mtk_eth_priv *priv = bus->priv;
+
+	if (devad < 0)
+		return priv->mii_read(priv, addr, reg);
+	else
+		return priv->mmd_read(priv, addr, devad, reg);
+}
+
+static int mtk_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
+			  u16 val)
+{
+	struct mtk_eth_priv *priv = bus->priv;
+
+	if (devad < 0)
+		return priv->mii_write(priv, addr, reg, val);
+	else
+		return priv->mmd_write(priv, addr, devad, reg, val);
+}
+
+static int mtk_mdio_register(struct udevice *dev)
+{
+	struct mtk_eth_priv *priv = dev_get_priv(dev);
+	struct mii_dev *mdio_bus = mdio_alloc();
+	int ret;
+
+	if (!mdio_bus)
+		return -ENOMEM;
+
+	/* Assign MDIO access APIs according to the switch/phy */
+	switch (priv->sw) {
+	case SW_MT7530:
+		priv->mii_read = mtk_mii_read;
+		priv->mii_write = mtk_mii_write;
+		priv->mmd_read = mtk_mmd_ind_read;
+		priv->mmd_write = mtk_mmd_ind_write;
+		break;
+	default:
+		priv->mii_read = mtk_mii_read;
+		priv->mii_write = mtk_mii_write;
+		priv->mmd_read = mtk_mmd_read;
+		priv->mmd_write = mtk_mmd_write;
+	}
+
+	mdio_bus->read = mtk_mdio_read;
+	mdio_bus->write = mtk_mdio_write;
+	snprintf(mdio_bus->name, sizeof(mdio_bus->name), dev->name);
+
+	mdio_bus->priv = (void *)priv;
+
+	ret = mdio_register(mdio_bus);
+
+	if (ret)
+		return ret;
+
+	priv->mdio_bus = mdio_bus;
+
+	return 0;
+}
+
+/*
+ * MT7530 Internal Register Address Bits
+ * -------------------------------------------------------------------
+ * | 15  14  13  12  11  10   9   8   7   6 | 5   4   3   2 | 1   0  |
+ * |----------------------------------------|---------------|--------|
+ * |              Page Address              |  Reg Address  | Unused |
+ * -------------------------------------------------------------------
+ */
+
+static int mt7530_reg_read(struct mtk_eth_priv *priv, u32 reg, u32 *data)
+{
+	int ret, low_word, high_word;
+
+	/* Write page address */
+	ret = mtk_mii_write(priv, priv->mt7530_smi_addr, 0x1f, reg >> 6);
+	if (ret)
+		return ret;
+
+	/* Read low word */
+	low_word = mtk_mii_read(priv, priv->mt7530_smi_addr, (reg >> 2) & 0xf);
+	if (low_word < 0)
+		return low_word;
+
+	/* Read high word */
+	high_word = mtk_mii_read(priv, priv->mt7530_smi_addr, 0x10);
+	if (high_word < 0)
+		return high_word;
+
+	if (data)
+		*data = ((u32)high_word << 16) | (low_word & 0xffff);
+
+	return 0;
+}
+
+static int mt7530_reg_write(struct mtk_eth_priv *priv, u32 reg, u32 data)
+{
+	int ret;
+
+	/* Write page address */
+	ret = mtk_mii_write(priv, priv->mt7530_smi_addr, 0x1f, reg >> 6);
+	if (ret)
+		return ret;
+
+	/* Write low word */
+	ret = mtk_mii_write(priv, priv->mt7530_smi_addr, (reg >> 2) & 0xf,
+			    data & 0xffff);
+	if (ret)
+		return ret;
+
+	/* Write high word */
+	return mtk_mii_write(priv, priv->mt7530_smi_addr, 0x10, data >> 16);
+}
+
+static void mt7530_reg_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr,
+			   u32 set)
+{
+	u32 val;
+
+	mt7530_reg_read(priv, reg, &val);
+	val &= ~clr;
+	val |= set;
+	mt7530_reg_write(priv, reg, val);
+}
+
+static void mt7530_core_reg_write(struct mtk_eth_priv *priv, u32 reg, u32 val)
+{
+	u8 phy_addr = MT7530_PHY_ADDR(priv->mt7530_phy_base, 0);
+
+	mtk_mmd_ind_write(priv, phy_addr, 0x1f, reg, val);
+}
+
+static int mt7530_pad_clk_setup(struct mtk_eth_priv *priv, int mode)
+{
+	u32 ncpo1, ssc_delta;
+
+	switch (mode) {
+	case PHY_INTERFACE_MODE_RGMII:
+		ncpo1 = 0x0c80;
+		ssc_delta = 0x87;
+		break;
+	default:
+		printf("error: xMII mode %d not supported\n", mode);
+		return -EINVAL;
+	}
+
+	/* Disable MT7530 core clock */
+	mt7530_core_reg_write(priv, CORE_TRGMII_GSW_CLK_CG, 0);
+
+	/* Disable MT7530 PLL */
+	mt7530_core_reg_write(priv, CORE_GSWPLL_GRP1,
+			      (2 << RG_GSWPLL_POSDIV_200M_S) |
+			      (32 << RG_GSWPLL_FBKDIV_200M_S));
+
+	/* For MT7530 core clock = 500Mhz */
+	mt7530_core_reg_write(priv, CORE_GSWPLL_GRP2,
+			      (1 << RG_GSWPLL_POSDIV_500M_S) |
+			      (25 << RG_GSWPLL_FBKDIV_500M_S));
+
+	/* Enable MT7530 PLL */
+	mt7530_core_reg_write(priv, CORE_GSWPLL_GRP1,
+			      (2 << RG_GSWPLL_POSDIV_200M_S) |
+			      (32 << RG_GSWPLL_FBKDIV_200M_S) |
+			      RG_GSWPLL_EN_PRE);
+
+	udelay(20);
+
+	mt7530_core_reg_write(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN);
+
+	/* Setup the MT7530 TRGMII Tx Clock */
+	mt7530_core_reg_write(priv, CORE_PLL_GROUP5, ncpo1);
+	mt7530_core_reg_write(priv, CORE_PLL_GROUP6, 0);
+	mt7530_core_reg_write(priv, CORE_PLL_GROUP10, ssc_delta);
+	mt7530_core_reg_write(priv, CORE_PLL_GROUP11, ssc_delta);
+	mt7530_core_reg_write(priv, CORE_PLL_GROUP4, RG_SYSPLL_DDSFBK_EN |
+			      RG_SYSPLL_BIAS_EN | RG_SYSPLL_BIAS_LPF_EN);
+
+	mt7530_core_reg_write(priv, CORE_PLL_GROUP2,
+			      RG_SYSPLL_EN_NORMAL | RG_SYSPLL_VODEN |
+			      (1 << RG_SYSPLL_POSDIV_S));
+
+	mt7530_core_reg_write(priv, CORE_PLL_GROUP7,
+			      RG_LCDDS_PCW_NCPO_CHG | (3 << RG_LCCDS_C_S) |
+			      RG_LCDDS_PWDB | RG_LCDDS_ISO_EN);
+
+	/* Enable MT7530 core clock */
+	mt7530_core_reg_write(priv, CORE_TRGMII_GSW_CLK_CG,
+			      REG_GSWCK_EN | REG_TRGMIICK_EN);
+
+	return 0;
+}
+
+static int mt7530_setup(struct mtk_eth_priv *priv)
+{
+	u16 phy_addr, phy_val;
+	u32 val;
+	int i;
+
+	/* Select 250MHz clk for RGMII mode */
+	mtk_ethsys_rmw(priv, ETHSYS_CLKCFG0_REG,
+		       ETHSYS_TRGMII_CLK_SEL362_5, 0);
+
+	/* Global reset switch */
+	if (priv->mcm) {
+		reset_assert(&priv->rst_mcm);
+		udelay(1000);
+		reset_deassert(&priv->rst_mcm);
+		mdelay(1000);
+	} else if (dm_gpio_is_valid(&priv->rst_gpio)) {
+		dm_gpio_set_value(&priv->rst_gpio, 0);
+		udelay(1000);
+		dm_gpio_set_value(&priv->rst_gpio, 1);
+		mdelay(1000);
+	}
+
+	/* Modify HWTRAP first to allow direct access to internal PHYs */
+	mt7530_reg_read(priv, HWTRAP_REG, &val);
+	val |= CHG_TRAP;
+	val &= ~C_MDIO_BPS;
+	mt7530_reg_write(priv, MHWTRAP_REG, val);
+
+	/* Calculate the phy base address */
+	val = ((val & SMI_ADDR_M) >> SMI_ADDR_S) << 3;
+	priv->mt7530_phy_base = (val | 0x7) + 1;
+
+	/* Turn off PHYs */
+	for (i = 0; i < MT7530_NUM_PHYS; i++) {
+		phy_addr = MT7530_PHY_ADDR(priv->mt7530_phy_base, i);
+		phy_val = priv->mii_read(priv, phy_addr, MII_BMCR);
+		phy_val |= BMCR_PDOWN;
+		priv->mii_write(priv, phy_addr, MII_BMCR, phy_val);
+	}
+
+	/* Force MAC link down before reset */
+	mt7530_reg_write(priv, PCMR_REG(5), FORCE_MODE);
+	mt7530_reg_write(priv, PCMR_REG(6), FORCE_MODE);
+
+	/* MT7530 reset */
+	mt7530_reg_write(priv, SYS_CTRL_REG, SW_SYS_RST | SW_REG_RST);
+	udelay(100);
+
+	val = (1 << IPG_CFG_S) |
+	      MAC_MODE | FORCE_MODE |
+	      MAC_TX_EN | MAC_RX_EN |
+	      BKOFF_EN | BACKPR_EN |
+	      (SPEED_1000M << FORCE_SPD_S) |
+	      FORCE_DPX | FORCE_LINK;
+
+	/* MT7530 Port6: Forced 1000M/FD, FC disabled */
+	mt7530_reg_write(priv, PCMR_REG(6), val);
+
+	/* MT7530 Port5: Forced link down */
+	mt7530_reg_write(priv, PCMR_REG(5), FORCE_MODE);
+
+	/* MT7530 Port6: Set to RGMII */
+	mt7530_reg_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_M, P6_INTF_MODE_RGMII);
+
+	/* Hardware Trap: Enable Port6, Disable Port5 */
+	mt7530_reg_read(priv, HWTRAP_REG, &val);
+	val |= CHG_TRAP | LOOPDET_DIS | P5_INTF_DIS |
+	       (P5_INTF_SEL_GMAC5 << P5_INTF_SEL_S) |
+	       (P5_INTF_MODE_RGMII << P5_INTF_MODE_S);
+	val &= ~(C_MDIO_BPS | P6_INTF_DIS);
+	mt7530_reg_write(priv, MHWTRAP_REG, val);
+
+	/* Setup switch core pll */
+	mt7530_pad_clk_setup(priv, priv->phy_interface);
+
+	/* Lower Tx Driving for TRGMII path */
+	for (i = 0 ; i < NUM_TRGMII_CTRL ; i++)
+		mt7530_reg_write(priv, MT7530_TRGMII_TD_ODT(i),
+				 (8 << TD_DM_DRVP_S) | (8 << TD_DM_DRVN_S));
+
+	for (i = 0 ; i < NUM_TRGMII_CTRL; i++)
+		mt7530_reg_rmw(priv, MT7530_TRGMII_RD(i), RD_TAP_M, 16);
+
+	/* Turn on PHYs */
+	for (i = 0; i < MT7530_NUM_PHYS; i++) {
+		phy_addr = MT7530_PHY_ADDR(priv->mt7530_phy_base, i);
+		phy_val = priv->mii_read(priv, phy_addr, MII_BMCR);
+		phy_val &= ~BMCR_PDOWN;
+		priv->mii_write(priv, phy_addr, MII_BMCR, phy_val);
+	}
+
+	/* Set port isolation */
+	for (i = 0; i < 8; i++) {
+		/* Set port matrix mode */
+		if (i != 6)
+			mt7530_reg_write(priv, PCR_REG(i),
+					 (0x40 << PORT_MATRIX_S));
+		else
+			mt7530_reg_write(priv, PCR_REG(i),
+					 (0x3f << PORT_MATRIX_S));
+
+		/* Set port mode to user port */
+		mt7530_reg_write(priv, PVC_REG(i),
+				 (0x8100 << STAG_VPID_S) |
+				 (VLAN_ATTR_USER << VLAN_ATTR_S));
+	}
+
+	return 0;
+}
+
+static void mtk_phy_link_adjust(struct mtk_eth_priv *priv)
+{
+	u16 lcl_adv = 0, rmt_adv = 0;
+	u8 flowctrl;
+	u32 mcr;
+
+	mcr = (1 << IPG_CFG_S) |
+	      (MAC_RX_PKT_LEN_1536 << MAC_RX_PKT_LEN_S) |
+	      MAC_MODE | FORCE_MODE |
+	      MAC_TX_EN | MAC_RX_EN |
+	      BKOFF_EN | BACKPR_EN;
+
+	switch (priv->phydev->speed) {
+	case SPEED_10:
+		mcr |= (SPEED_10M << FORCE_SPD_S);
+		break;
+	case SPEED_100:
+		mcr |= (SPEED_100M << FORCE_SPD_S);
+		break;
+	case SPEED_1000:
+		mcr |= (SPEED_1000M << FORCE_SPD_S);
+		break;
+	};
+
+	if (priv->phydev->link)
+		mcr |= FORCE_LINK;
+
+	if (priv->phydev->duplex) {
+		mcr |= FORCE_DPX;
+
+		if (priv->phydev->pause)
+			rmt_adv = LPA_PAUSE_CAP;
+		if (priv->phydev->asym_pause)
+			rmt_adv |= LPA_PAUSE_ASYM;
+
+		if (priv->phydev->advertising & ADVERTISED_Pause)
+			lcl_adv |= ADVERTISE_PAUSE_CAP;
+		if (priv->phydev->advertising & ADVERTISED_Asym_Pause)
+			lcl_adv |= ADVERTISE_PAUSE_ASYM;
+
+		flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
+
+		if (flowctrl & FLOW_CTRL_TX)
+			mcr |= FORCE_TX_FC;
+		if (flowctrl & FLOW_CTRL_RX)
+			mcr |= FORCE_RX_FC;
+
+		debug("rx pause %s, tx pause %s\n",
+		      flowctrl & FLOW_CTRL_RX ? "enabled" : "disabled",
+		      flowctrl & FLOW_CTRL_TX ? "enabled" : "disabled");
+	}
+
+	mtk_gmac_write(priv, GMAC_PORT_MCR(priv->gmac_id), mcr);
+}
+
+static int mtk_phy_start(struct mtk_eth_priv *priv)
+{
+	struct phy_device *phydev = priv->phydev;
+	int ret;
+
+	ret = phy_startup(phydev);
+
+	if (ret) {
+		debug("Could not initialize PHY %s\n", phydev->dev->name);
+		return ret;
+	}
+
+	if (!phydev->link) {
+		debug("%s: link down.\n", phydev->dev->name);
+		return 0;
+	}
+
+	mtk_phy_link_adjust(priv);
+
+	debug("Speed: %d, %s duplex%s\n", phydev->speed,
+	      (phydev->duplex) ? "full" : "half",
+	      (phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
+
+	return 0;
+}
+
+static int mtk_phy_probe(struct udevice *dev)
+{
+	struct mtk_eth_priv *priv = dev_get_priv(dev);
+	struct phy_device *phydev;
+
+	phydev = phy_connect(priv->mdio_bus, priv->phy_addr, dev,
+			     priv->phy_interface);
+	if (!phydev)
+		return -ENODEV;
+
+	phydev->supported &= PHY_GBIT_FEATURES;
+	phydev->advertising = phydev->supported;
+
+	priv->phydev = phydev;
+	phy_config(phydev);
+
+	return 0;
+}
+
+static void mtk_mac_init(struct mtk_eth_priv *priv)
+{
+	int i, ge_mode = 0;
+	u32 mcr;
+
+	switch (priv->phy_interface) {
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_SGMII:
+		ge_mode = GE_MODE_RGMII;
+		break;
+	case PHY_INTERFACE_MODE_MII:
+	case PHY_INTERFACE_MODE_GMII:
+		ge_mode = GE_MODE_MII;
+		break;
+	case PHY_INTERFACE_MODE_RMII:
+		ge_mode = GE_MODE_RMII;
+		break;
+	default:
+		break;
+	}
+
+	/* set the gmac to the right mode */
+	mtk_ethsys_rmw(priv, ETHSYS_SYSCFG0_REG,
+		       SYSCFG0_GE_MODE_M << SYSCFG0_GE_MODE_S(priv->gmac_id),
+		       ge_mode << SYSCFG0_GE_MODE_S(priv->gmac_id));
+
+	if (priv->force_mode) {
+		mcr = (1 << IPG_CFG_S) |
+		      (MAC_RX_PKT_LEN_1536 << MAC_RX_PKT_LEN_S) |
+		      MAC_MODE | FORCE_MODE |
+		      MAC_TX_EN | MAC_RX_EN |
+		      BKOFF_EN | BACKPR_EN |
+		      FORCE_LINK;
+
+		switch (priv->speed) {
+		case SPEED_10:
+			mcr |= SPEED_10M << FORCE_SPD_S;
+			break;
+		case SPEED_100:
+			mcr |= SPEED_100M << FORCE_SPD_S;
+			break;
+		case SPEED_1000:
+			mcr |= SPEED_1000M << FORCE_SPD_S;
+			break;
+		}
+
+		if (priv->duplex)
+			mcr |= FORCE_DPX;
+
+		mtk_gmac_write(priv, GMAC_PORT_MCR(priv->gmac_id), mcr);
+	}
+
+	if (priv->soc == SOC_MT7623) {
+		/* Lower Tx Driving for TRGMII path */
+		for (i = 0 ; i < NUM_TRGMII_CTRL; i++)
+			mtk_gmac_write(priv, GMAC_TRGMII_TD_ODT(i),
+				       (8 << TD_DM_DRVP_S) |
+				       (8 << TD_DM_DRVN_S));
+
+		mtk_gmac_rmw(priv, GMAC_TRGMII_RCK_CTRL, 0,
+			     RX_RST | RXC_DQSISEL);
+		mtk_gmac_rmw(priv, GMAC_TRGMII_RCK_CTRL, RX_RST, 0);
+	}
+}
+
+static void mtk_eth_fifo_init(struct mtk_eth_priv *priv)
+{
+	char *pkt_base = priv->pkt_pool;
+	int i;
+
+	mtk_pdma_rmw(priv, PDMA_GLO_CFG_REG, 0xffff0000, 0);
+	udelay(500);
+
+	memset(priv->tx_ring_noc, 0, NUM_TX_DESC * sizeof(struct pdma_txdesc));
+	memset(priv->rx_ring_noc, 0, NUM_RX_DESC * sizeof(struct pdma_rxdesc));
+	memset(priv->pkt_pool, 0, TOTAL_PKT_BUF_SIZE);
+
+	flush_dcache_range((u32)pkt_base, (u32)(pkt_base + TOTAL_PKT_BUF_SIZE));
+
+	priv->rx_dma_owner_idx0 = 0;
+	priv->tx_cpu_owner_idx0 = 0;
+
+	for (i = 0; i < NUM_TX_DESC; i++) {
+		priv->tx_ring_noc[i].txd_info2.LS0 = 1;
+		priv->tx_ring_noc[i].txd_info2.DDONE = 1;
+		priv->tx_ring_noc[i].txd_info4.FPORT = priv->gmac_id + 1;
+
+		priv->tx_ring_noc[i].txd_info1.SDP0 = virt_to_phys(pkt_base);
+		pkt_base += PKTSIZE_ALIGN;
+	}
+
+	for (i = 0; i < NUM_RX_DESC; i++) {
+		priv->rx_ring_noc[i].rxd_info2.PLEN0 = PKTSIZE_ALIGN;
+		priv->rx_ring_noc[i].rxd_info1.PDP0 = virt_to_phys(pkt_base);
+		pkt_base += PKTSIZE_ALIGN;
+	}
+
+	mtk_pdma_write(priv, TX_BASE_PTR_REG(0),
+		       virt_to_phys(priv->tx_ring_noc));
+	mtk_pdma_write(priv, TX_MAX_CNT_REG(0), NUM_TX_DESC);
+	mtk_pdma_write(priv, TX_CTX_IDX_REG(0), priv->tx_cpu_owner_idx0);
+
+	mtk_pdma_write(priv, RX_BASE_PTR_REG(0),
+		       virt_to_phys(priv->rx_ring_noc));
+	mtk_pdma_write(priv, RX_MAX_CNT_REG(0), NUM_RX_DESC);
+	mtk_pdma_write(priv, RX_CRX_IDX_REG(0), NUM_RX_DESC - 1);
+
+	mtk_pdma_write(priv, PDMA_RST_IDX_REG, RST_DTX_IDX0 | RST_DRX_IDX0);
+}
+
+static int mtk_eth_start(struct udevice *dev)
+{
+	struct mtk_eth_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	/* Reset FE */
+	reset_assert(&priv->rst_fe);
+	udelay(1000);
+	reset_deassert(&priv->rst_fe);
+	mdelay(10);
+
+	/* Packets forward to PDMA */
+	mtk_gdma_write(priv, priv->gmac_id, GDMA_IG_CTRL_REG, GDMA_FWD_TO_CPU);
+
+	if (priv->gmac_id == 0)
+		mtk_gdma_write(priv, 1, GDMA_IG_CTRL_REG, GDMA_FWD_DISCARD);
+	else
+		mtk_gdma_write(priv, 0, GDMA_IG_CTRL_REG, GDMA_FWD_DISCARD);
+
+	udelay(500);
+
+	mtk_eth_fifo_init(priv);
+
+	/* Start PHY */
+	if (priv->sw == SW_NONE) {
+		ret = mtk_phy_start(priv);
+		if (ret)
+			return ret;
+	}
+
+	mtk_pdma_rmw(priv, PDMA_GLO_CFG_REG, 0,
+		     TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN);
+	udelay(500);
+
+	return 0;
+}
+
+static void mtk_eth_stop(struct udevice *dev)
+{
+	struct mtk_eth_priv *priv = dev_get_priv(dev);
+
+	mtk_pdma_rmw(priv, PDMA_GLO_CFG_REG,
+		     TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN, 0);
+	udelay(500);
+
+	wait_for_bit_le32(priv->fe_base + PDMA_BASE + PDMA_GLO_CFG_REG,
+			  RX_DMA_BUSY | TX_DMA_BUSY, 0, 5000, 0);
+}
+
+static int mtk_eth_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct mtk_eth_priv *priv = dev_get_priv(dev);
+	unsigned char *mac = pdata->enetaddr;
+	u32 macaddr_lsb, macaddr_msb;
+
+	macaddr_msb = ((u32)mac[0] << 8) | (u32)mac[1];
+	macaddr_lsb = ((u32)mac[2] << 24) | ((u32)mac[3] << 16) |
+		      ((u32)mac[4] << 8) | (u32)mac[5];
+
+	mtk_gdma_write(priv, priv->gmac_id, GDMA_MAC_MSB_REG, macaddr_msb);
+	mtk_gdma_write(priv, priv->gmac_id, GDMA_MAC_LSB_REG, macaddr_lsb);
+
+	return 0;
+}
+
+static int mtk_eth_send(struct udevice *dev, void *packet, int length)
+{
+	struct mtk_eth_priv *priv = dev_get_priv(dev);
+	u32 idx = priv->tx_cpu_owner_idx0;
+	void *pkt_base;
+
+	if (!priv->tx_ring_noc[idx].txd_info2.DDONE) {
+		debug("mtk-eth: TX DMA descriptor ring is full\n");
+		return -EPERM;
+	}
+
+	pkt_base = (void *)phys_to_virt(priv->tx_ring_noc[idx].txd_info1.SDP0);
+	memcpy(pkt_base, packet, length);
+	flush_dcache_range((u32)pkt_base, (u32)pkt_base +
+			   roundup(length, ARCH_DMA_MINALIGN));
+
+	priv->tx_ring_noc[idx].txd_info2.SDL0 = length;
+	priv->tx_ring_noc[idx].txd_info2.DDONE = 0;
+
+	priv->tx_cpu_owner_idx0 = (priv->tx_cpu_owner_idx0 + 1) % NUM_TX_DESC;
+	mtk_pdma_write(priv, TX_CTX_IDX_REG(0), priv->tx_cpu_owner_idx0);
+
+	return 0;
+}
+
+static int mtk_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct mtk_eth_priv *priv = dev_get_priv(dev);
+	u32 idx = priv->rx_dma_owner_idx0;
+	uchar *pkt_base;
+	u32 length;
+
+	if (!priv->rx_ring_noc[idx].rxd_info2.DDONE) {
+		debug("mtk-eth: RX DMA descriptor ring is empty\n");
+		return -EAGAIN;
+	}
+
+	length = priv->rx_ring_noc[idx].rxd_info2.PLEN0;
+	pkt_base = (void *)phys_to_virt(priv->rx_ring_noc[idx].rxd_info1.PDP0);
+	invalidate_dcache_range((u32)pkt_base, (u32)pkt_base +
+				roundup(length, ARCH_DMA_MINALIGN));
+
+	if (packetp)
+		*packetp = pkt_base;
+
+	return length;
+}
+
+static int mtk_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+	struct mtk_eth_priv *priv = dev_get_priv(dev);
+	u32 idx = priv->rx_dma_owner_idx0;
+
+	priv->rx_ring_noc[idx].rxd_info2.DDONE = 0;
+	priv->rx_ring_noc[idx].rxd_info2.LS0 = 0;
+	priv->rx_ring_noc[idx].rxd_info2.PLEN0 = PKTSIZE_ALIGN;
+
+	mtk_pdma_write(priv, RX_CRX_IDX_REG(0), idx);
+	priv->rx_dma_owner_idx0 = (priv->rx_dma_owner_idx0 + 1) % NUM_RX_DESC;
+
+	return 0;
+}
+
+static int mtk_eth_probe(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct mtk_eth_priv *priv = dev_get_priv(dev);
+	u32 iobase = pdata->iobase;
+	int ret;
+
+	/* Frame Engine Register Base */
+	priv->fe_base = (void *)iobase;
+
+	/* GMAC Register Base */
+	priv->gmac_base = (void *)(iobase + GMAC_BASE);
+
+	/* MDIO register */
+	ret = mtk_mdio_register(dev);
+	if (ret)
+		return ret;
+
+	/* Prepare for tx/rx rings */
+	priv->tx_ring_noc = (struct pdma_txdesc *)
+		noncached_alloc(sizeof(struct pdma_txdesc) * NUM_TX_DESC,
+				ARCH_DMA_MINALIGN);
+	priv->rx_ring_noc = (struct pdma_rxdesc *)
+		noncached_alloc(sizeof(struct pdma_rxdesc) * NUM_RX_DESC,
+				ARCH_DMA_MINALIGN);
+
+	/* Set MAC mode */
+	mtk_mac_init(priv);
+
+	/* Probe phy if switch is not specified */
+	if (priv->sw == SW_NONE)
+		return mtk_phy_probe(dev);
+
+	/* Initialize switch */
+	return priv->switch_init(priv);
+}
+
+static int mtk_eth_remove(struct udevice *dev)
+{
+	struct mtk_eth_priv *priv = dev_get_priv(dev);
+
+	/* MDIO unregister */
+	mdio_unregister(priv->mdio_bus);
+	mdio_free(priv->mdio_bus);
+
+	/* Stop possibly started DMA */
+	mtk_eth_stop(dev);
+
+	return 0;
+}
+
+static int mtk_eth_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct mtk_eth_priv *priv = dev_get_priv(dev);
+	struct ofnode_phandle_args args;
+	struct regmap *regmap;
+	const char *str;
+	ofnode subnode;
+	int ret;
+
+	priv->soc = dev_get_driver_data(dev);
+
+	pdata->iobase = devfdt_get_addr(dev);
+
+	/* get corresponding ethsys phandle */
+	ret = dev_read_phandle_with_args(dev, "mediatek,ethsys", NULL, 0, 0,
+					 &args);
+	if (ret)
+		return ret;
+
+	regmap = syscon_node_to_regmap(args.node);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	priv->ethsys_base = regmap_get_range(regmap, 0);
+	if (!priv->ethsys_base) {
+		dev_err(dev, "Unable to find ethsys\n");
+		return -ENODEV;
+	}
+
+	/* Reset controllers */
+	ret = reset_get_by_name(dev, "fe", &priv->rst_fe);
+	if (ret) {
+		printf("error: Unable to get reset ctrl for frame engine\n");
+		return ret;
+	}
+
+	priv->gmac_id = dev_read_u32_default(dev, "mediatek,gmac-id", 0);
+
+	/* Interface mode is required */
+	str = dev_read_string(dev, "phy-mode");
+	if (str) {
+		pdata->phy_interface = phy_get_interface_by_name(str);
+		priv->phy_interface = pdata->phy_interface;
+	} else {
+		printf("error: phy-mode is not set\n");
+		return -EINVAL;
+	}
+
+	/* Force mode or autoneg */
+	subnode = ofnode_find_subnode(dev_ofnode(dev), "fixed-link");
+	if (ofnode_valid(subnode)) {
+		priv->force_mode = 1;
+		priv->speed = ofnode_read_u32_default(subnode, "speed", 0);
+		priv->duplex = ofnode_read_bool(subnode, "full-duplex");
+
+		if (priv->speed != SPEED_10 && priv->speed != SPEED_100 &&
+		    priv->speed != SPEED_1000) {
+			printf("error: no valid speed set in fixed-link\n");
+			return -EINVAL;
+		}
+	}
+
+	/* check for switch first, otherwise phy will be used */
+	priv->sw = SW_NONE;
+	priv->switch_init = NULL;
+	str = dev_read_string(dev, "mediatek,switch");
+
+	if (str) {
+		if (!strcmp(str, "mt7530")) {
+			priv->sw = SW_MT7530;
+			priv->switch_init = mt7530_setup;
+			priv->mt7530_smi_addr = MT7530_DFL_SMI_ADDR;
+		} else {
+			printf("error: unsupported switch\n");
+			return -EINVAL;
+		}
+
+		priv->mcm = dev_read_bool(dev, "mediatek,mcm");
+		if (priv->mcm) {
+			ret = reset_get_by_name(dev, "mcm", &priv->rst_mcm);
+			if (ret) {
+				printf("error: no reset ctrl for mcm\n");
+				return ret;
+			}
+		} else {
+			gpio_request_by_name(dev, "reset-gpios", 0,
+					     &priv->rst_gpio, GPIOD_IS_OUT);
+		}
+	} else {
+		subnode = ofnode_find_subnode(dev_ofnode(dev), "phy-handle");
+		if (!ofnode_valid(subnode)) {
+			printf("error: phy-handle is not specified\n");
+			return ret;
+		}
+
+		priv->phy_addr = ofnode_read_s32_default(subnode, "reg", -1);
+		if (priv->phy_addr < 0) {
+			printf("error: phy address is not specified\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static const struct udevice_id mtk_eth_ids[] = {
+	{ .compatible = "mediatek,mt7629-eth", .data = SOC_MT7629 },
+	{ .compatible = "mediatek,mt7623-eth", .data = SOC_MT7623 },
+	{}
+};
+
+static const struct eth_ops mtk_eth_ops = {
+	.start = mtk_eth_start,
+	.stop = mtk_eth_stop,
+	.send = mtk_eth_send,
+	.recv = mtk_eth_recv,
+	.free_pkt = mtk_eth_free_pkt,
+	.write_hwaddr = mtk_eth_write_hwaddr,
+};
+
+U_BOOT_DRIVER(mtk_eth) = {
+	.name = "mtk-eth",
+	.id = UCLASS_ETH,
+	.of_match = mtk_eth_ids,
+	.ofdata_to_platdata = mtk_eth_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+	.probe = mtk_eth_probe,
+	.remove = mtk_eth_remove,
+	.ops = &mtk_eth_ops,
+	.priv_auto_alloc_size = sizeof(struct mtk_eth_priv),
+	.flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
diff --git a/drivers/net/mtk_eth.h b/drivers/net/mtk_eth.h
new file mode 100644
index 0000000..fe89a03
--- /dev/null
+++ b/drivers/net/mtk_eth.h
@@ -0,0 +1,286 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ * Author: Mark Lee <mark-mc.lee@mediatek.com>
+ */
+
+#ifndef _MTK_ETH_H_
+#define _MTK_ETH_H_
+
+/* Frame Engine Register Bases */
+#define PDMA_BASE			0x0800
+#define GDMA1_BASE			0x0500
+#define GDMA2_BASE			0x1500
+#define GMAC_BASE			0x10000
+
+/* Ethernet subsystem registers */
+
+#define ETHSYS_SYSCFG0_REG		0x14
+#define SYSCFG0_GE_MODE_S(n)		(12 + ((n) * 2))
+#define SYSCFG0_GE_MODE_M		0x3
+
+#define ETHSYS_CLKCFG0_REG		0x2c
+#define ETHSYS_TRGMII_CLK_SEL362_5	BIT(11)
+
+/* SYSCFG0_GE_MODE: GE Modes */
+#define GE_MODE_RGMII			0
+#define GE_MODE_MII			1
+#define GE_MODE_MII_PHY			2
+#define GE_MODE_RMII			3
+
+/* Frame Engine Registers */
+
+/* PDMA */
+#define TX_BASE_PTR_REG(n)		(0x000 + (n) * 0x10)
+#define TX_MAX_CNT_REG(n)		(0x004 + (n) * 0x10)
+#define TX_CTX_IDX_REG(n)		(0x008 + (n) * 0x10)
+#define TX_DTX_IDX_REG(n)		(0x00c + (n) * 0x10)
+
+#define RX_BASE_PTR_REG(n)		(0x100 + (n) * 0x10)
+#define RX_MAX_CNT_REG(n)		(0x104 + (n) * 0x10)
+#define RX_CRX_IDX_REG(n)		(0x108 + (n) * 0x10)
+#define RX_DRX_IDX_REG(n)		(0x10c + (n) * 0x10)
+
+#define PDMA_GLO_CFG_REG		0x204
+#define TX_WB_DDONE			BIT(6)
+#define RX_DMA_BUSY			BIT(3)
+#define RX_DMA_EN			BIT(2)
+#define TX_DMA_BUSY			BIT(1)
+#define TX_DMA_EN			BIT(0)
+
+#define PDMA_RST_IDX_REG		0x208
+#define RST_DRX_IDX0			BIT(16)
+#define RST_DTX_IDX0			BIT(0)
+
+/* GDMA */
+#define GDMA_IG_CTRL_REG		0x000
+#define GDM_ICS_EN			BIT(22)
+#define GDM_TCS_EN			BIT(21)
+#define GDM_UCS_EN			BIT(20)
+#define STRP_CRC			BIT(16)
+#define MYMAC_DP_S			12
+#define MYMAC_DP_M			0xf000
+#define BC_DP_S				8
+#define BC_DP_M				0xf00
+#define MC_DP_S				4
+#define MC_DP_M				0xf0
+#define UN_DP_S				0
+#define UN_DP_M				0x0f
+
+#define GDMA_MAC_LSB_REG		0x008
+
+#define GDMA_MAC_MSB_REG		0x00c
+
+/* MYMAC_DP/BC_DP/MC_DP/UN_DP: Destination ports */
+#define DP_PDMA				0
+#define DP_GDMA1			1
+#define DP_GDMA2			2
+#define DP_PPE				4
+#define DP_QDMA				5
+#define DP_DISCARD			7
+
+/* GMAC Registers */
+
+#define GMAC_PIAC_REG			0x0004
+#define PHY_ACS_ST			BIT(31)
+#define MDIO_REG_ADDR_S			25
+#define MDIO_REG_ADDR_M			0x3e000000
+#define MDIO_PHY_ADDR_S			20
+#define MDIO_PHY_ADDR_M			0x1f00000
+#define MDIO_CMD_S			18
+#define MDIO_CMD_M			0xc0000
+#define MDIO_ST_S			16
+#define MDIO_ST_M			0x30000
+#define MDIO_RW_DATA_S			0
+#define MDIO_RW_DATA_M			0xffff
+
+/* MDIO_CMD: MDIO commands */
+#define MDIO_CMD_ADDR			0
+#define MDIO_CMD_WRITE			1
+#define MDIO_CMD_READ			2
+#define MDIO_CMD_READ_C45		3
+
+/* MDIO_ST: MDIO start field */
+#define MDIO_ST_C45			0
+#define MDIO_ST_C22			1
+
+#define GMAC_PORT_MCR(p)		(0x0100 + (p) * 0x100)
+#define MAC_RX_PKT_LEN_S		24
+#define MAC_RX_PKT_LEN_M		0x3000000
+#define IPG_CFG_S			18
+#define IPG_CFG_M			0xc0000
+#define MAC_MODE			BIT(16)
+#define FORCE_MODE			BIT(15)
+#define MAC_TX_EN			BIT(14)
+#define MAC_RX_EN			BIT(13)
+#define BKOFF_EN			BIT(9)
+#define BACKPR_EN			BIT(8)
+#define FORCE_RX_FC			BIT(5)
+#define FORCE_TX_FC			BIT(4)
+#define FORCE_SPD_S			2
+#define FORCE_SPD_M			0x0c
+#define FORCE_DPX			BIT(1)
+#define FORCE_LINK			BIT(0)
+
+/* MAC_RX_PKT_LEN: Max RX packet length */
+#define MAC_RX_PKT_LEN_1518		0
+#define MAC_RX_PKT_LEN_1536		1
+#define MAC_RX_PKT_LEN_1552		2
+#define MAC_RX_PKT_LEN_JUMBO		3
+
+/* FORCE_SPD: Forced link speed */
+#define SPEED_10M			0
+#define SPEED_100M			1
+#define SPEED_1000M			2
+
+#define GMAC_TRGMII_RCK_CTRL		0x300
+#define RX_RST				BIT(31)
+#define RXC_DQSISEL			BIT(30)
+
+#define GMAC_TRGMII_TD_ODT(n)		(0x354 + (n) * 8)
+#define TD_DM_DRVN_S			4
+#define TD_DM_DRVN_M			0xf0
+#define TD_DM_DRVP_S			0
+#define TD_DM_DRVP_M			0x0f
+
+/* MT7530 Registers */
+
+#define PCR_REG(p)			(0x2004 + (p) * 0x100)
+#define PORT_MATRIX_S			16
+#define PORT_MATRIX_M			0xff0000
+
+#define PVC_REG(p)			(0x2010 + (p) * 0x100)
+#define STAG_VPID_S			16
+#define STAG_VPID_M			0xffff0000
+#define VLAN_ATTR_S			6
+#define VLAN_ATTR_M			0xc0
+
+/* VLAN_ATTR: VLAN attributes */
+#define VLAN_ATTR_USER			0
+#define VLAN_ATTR_STACK			1
+#define VLAN_ATTR_TRANSLATION		2
+#define VLAN_ATTR_TRANSPARENT		3
+
+#define PCMR_REG(p)			(0x3000 + (p) * 0x100)
+/* XXX: all fields are defined under GMAC_PORT_MCR */
+
+#define SYS_CTRL_REG			0x7000
+#define SW_PHY_RST			BIT(2)
+#define SW_SYS_RST			BIT(1)
+#define SW_REG_RST			BIT(0)
+
+#define NUM_TRGMII_CTRL			5
+
+#define HWTRAP_REG			0x7800
+#define MHWTRAP_REG			0x7804
+#define CHG_TRAP			BIT(16)
+#define LOOPDET_DIS			BIT(14)
+#define P5_INTF_SEL_S			13
+#define P5_INTF_SEL_M			0x2000
+#define SMI_ADDR_S			11
+#define SMI_ADDR_M			0x1800
+#define XTAL_FSEL_S			9
+#define XTAL_FSEL_M			0x600
+#define P6_INTF_DIS			BIT(8)
+#define P5_INTF_MODE_S			7
+#define P5_INTF_MODE_M			0x80
+#define P5_INTF_DIS			BIT(6)
+#define C_MDIO_BPS			BIT(5)
+#define CHIP_MODE_S			0
+#define CHIP_MODE_M			0x0f
+
+/* P5_INTF_SEL: Interface type of Port5 */
+#define P5_INTF_SEL_GPHY		0
+#define P5_INTF_SEL_GMAC5		1
+
+/* P5_INTF_MODE: Interface mode of Port5 */
+#define P5_INTF_MODE_GMII_MII		0
+#define P5_INTF_MODE_RGMII		1
+
+#define MT7530_P6ECR			0x7830
+#define P6_INTF_MODE_M			0x3
+#define P6_INTF_MODE_S			0
+
+/* P6_INTF_MODE: Interface mode of Port6 */
+#define P6_INTF_MODE_RGMII		0
+#define P6_INTF_MODE_TRGMII		1
+
+#define MT7530_TRGMII_RD(n)		(0x7a10 + (n) * 8)
+#define RD_TAP_S			0
+#define RD_TAP_M			0x7f
+
+#define MT7530_TRGMII_TD_ODT(n)		(0x7a54 + (n) * 8)
+/* XXX: all fields are defined under GMAC_TRGMII_TD_ODT */
+
+/* MT7530 GPHY MDIO Indirect Access Registers */
+
+#define MII_MMD_ACC_CTL_REG		0x0d
+#define MMD_CMD_S			14
+#define MMD_CMD_M			0xc000
+#define MMD_DEVAD_S			0
+#define MMD_DEVAD_M			0x1f
+
+/* MMD_CMD: MMD commands */
+#define MMD_ADDR			0
+#define MMD_DATA			1
+#define MMD_DATA_RW_POST_INC		2
+#define MMD_DATA_W_POST_INC		3
+
+#define MII_MMD_ADDR_DATA_REG		0x0e
+
+/* MT7530 GPHY MDIO MMD Registers */
+
+#define CORE_PLL_GROUP2			0x401
+#define RG_SYSPLL_EN_NORMAL		BIT(15)
+#define RG_SYSPLL_VODEN			BIT(14)
+#define RG_SYSPLL_POSDIV_S		5
+#define RG_SYSPLL_POSDIV_M		0x60
+
+#define CORE_PLL_GROUP4			0x403
+#define RG_SYSPLL_DDSFBK_EN		BIT(12)
+#define RG_SYSPLL_BIAS_EN		BIT(11)
+#define RG_SYSPLL_BIAS_LPF_EN		BIT(10)
+
+#define CORE_PLL_GROUP5			0x404
+#define RG_LCDDS_PCW_NCPO1_S		0
+#define RG_LCDDS_PCW_NCPO1_M		0xffff
+
+#define CORE_PLL_GROUP6			0x405
+#define RG_LCDDS_PCW_NCPO0_S		0
+#define RG_LCDDS_PCW_NCPO0_M		0xffff
+
+#define CORE_PLL_GROUP7			0x406
+#define RG_LCDDS_PWDB			BIT(15)
+#define RG_LCDDS_ISO_EN			BIT(13)
+#define RG_LCCDS_C_S			4
+#define RG_LCCDS_C_M			0x70
+#define RG_LCDDS_PCW_NCPO_CHG		BIT(3)
+
+#define CORE_PLL_GROUP10		0x409
+#define RG_LCDDS_SSC_DELTA_S		0
+#define RG_LCDDS_SSC_DELTA_M		0xfff
+
+#define CORE_PLL_GROUP11		0x40a
+#define RG_LCDDS_SSC_DELTA1_S		0
+#define RG_LCDDS_SSC_DELTA1_M		0xfff
+
+#define CORE_GSWPLL_GRP1		0x40d
+#define RG_GSWPLL_POSDIV_200M_S		12
+#define RG_GSWPLL_POSDIV_200M_M		0x3000
+#define RG_GSWPLL_EN_PRE		BIT(11)
+#define RG_GSWPLL_FBKDIV_200M_S		0
+#define RG_GSWPLL_FBKDIV_200M_M		0xff
+
+#define CORE_GSWPLL_GRP2		0x40e
+#define RG_GSWPLL_POSDIV_500M_S		8
+#define RG_GSWPLL_POSDIV_500M_M		0x300
+#define RG_GSWPLL_FBKDIV_500M_S		0
+#define RG_GSWPLL_FBKDIV_500M_M		0xff
+
+#define CORE_TRGMII_GSW_CLK_CG		0x410
+#define REG_GSWCK_EN			BIT(0)
+#define REG_TRGMIICK_EN			BIT(1)
+
+#endif /* _MTK_ETH_H_ */
diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
index 09cc678..7e6625d 100644
--- a/drivers/net/sandbox-raw.c
+++ b/drivers/net/sandbox-raw.c
@@ -152,7 +152,6 @@
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
 	const char *ifname;
-	u32 local;
 	int ret;
 
 	pdata->iobase = dev_read_addr(dev);
@@ -173,10 +172,10 @@
 		       priv->host_ifindex, priv->host_ifname);
 	}
 
-	local = sandbox_eth_raw_os_is_local(priv->host_ifname);
-	if (local < 0)
-		return local;
-	priv->local = local;
+	ret = sandbox_eth_raw_os_is_local(priv->host_ifname);
+	if (ret < 0)
+		return ret;
+	priv->local = ret;
 
 	return 0;
 }
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 30a6aa6..fb441b3 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -146,7 +146,7 @@
 	  Supports individual pin selection and configuration for each
 	  remappable peripheral available on Microchip PIC32
 	  SoCs. This driver is controlled by a device tree node which
-	  contains both GPIO defintion and pin control functions.
+	  contains both GPIO definition and pin control functions.
 
 config PINCTRL_QCA953X
 	bool "QCA/Athores qca953x pin control driver"
diff --git a/drivers/pinctrl/mscc/Kconfig b/drivers/pinctrl/mscc/Kconfig
index cfc6c06..d07ea1b 100644
--- a/drivers/pinctrl/mscc/Kconfig
+++ b/drivers/pinctrl/mscc/Kconfig
@@ -20,3 +20,12 @@
 	help
 	   Support pin multiplexing and pin configuration control on
 	   Microsemi luton SoCs.
+
+config PINCTRL_MSCC_JR2
+	depends on SOC_JR2 && PINCTRL_FULL && OF_CONTROL
+	select PINCTRL_MSCC
+	default y
+	bool "Microsemi jr2 family pin control driver"
+	help
+	    Support pin multiplexing and pin configuration control on
+	    Microsemi jr2 SoCs.
diff --git a/drivers/pinctrl/mscc/Makefile b/drivers/pinctrl/mscc/Makefile
index 6910671..8038d54 100644
--- a/drivers/pinctrl/mscc/Makefile
+++ b/drivers/pinctrl/mscc/Makefile
@@ -3,3 +3,4 @@
 obj-y += mscc-common.o
 obj-$(CONFIG_PINCTRL_MSCC_OCELOT) += pinctrl-ocelot.o
 obj-$(CONFIG_PINCTRL_MSCC_LUTON) += pinctrl-luton.o
+obj-$(CONFIG_PINCTRL_MSCC_JR2) += pinctrl-jr2.o
diff --git a/drivers/pinctrl/mscc/mscc-common.c b/drivers/pinctrl/mscc/mscc-common.c
index d74b8a6..bd3e6ea 100644
--- a/drivers/pinctrl/mscc/mscc-common.c
+++ b/drivers/pinctrl/mscc/mscc-common.c
@@ -22,16 +22,37 @@
 #include <linux/io.h>
 #include "mscc-common.h"
 
-#define MSCC_GPIO_OUT_SET	0x0
-#define MSCC_GPIO_OUT_CLR	0x4
-#define MSCC_GPIO_OUT		0x8
-#define MSCC_GPIO_IN		0xc
-#define MSCC_GPIO_OE		0x10
-#define MSCC_GPIO_INTR		0x14
-#define MSCC_GPIO_INTR_ENA	0x18
-#define MSCC_GPIO_INTR_IDENT	0x1c
-#define MSCC_GPIO_ALT0		0x20
-#define MSCC_GPIO_ALT1		0x24
+static void mscc_writel(unsigned int offset, void *addr)
+{
+	if (offset < 32)
+		writel(BIT(offset), addr);
+	else
+		writel(BIT(offset % 32), addr + 4);
+}
+
+static unsigned int mscc_readl(unsigned int offset, void *addr)
+{
+	if (offset < 32)
+		return readl(addr);
+	else
+		return readl(addr + 4);
+}
+
+static void mscc_setbits(unsigned int offset, void *addr)
+{
+	if (offset < 32)
+		writel(readl(addr) | BIT(offset), addr);
+	else
+		writel(readl(addr + 4) | BIT(offset % 32), addr + 4);
+}
+
+static void mscc_clrbits(unsigned int offset, void *addr)
+{
+	if (offset < 32)
+		writel(readl(addr) & ~BIT(offset), addr);
+	else
+		writel(readl(addr + 4) & ~BIT(offset % 32), addr + 4);
+}
 
 static int mscc_get_functions_count(struct udevice *dev)
 {
@@ -67,7 +88,7 @@
 {
 	struct mscc_pinctrl *info = dev_get_priv(dev);
 	struct mscc_pin_caps *pin = info->mscc_pins[pin_selector].drv_data;
-	int f;
+	int f, offset, regoff;
 
 	f = mscc_pin_function_idx(pin_selector, selector, info->mscc_pins);
 	if (f < 0)
@@ -79,15 +100,22 @@
 	 * This is racy because both registers can't be updated at the same time
 	 * but it doesn't matter much for now.
 	 */
+	offset = pin->pin;
+	regoff = info->mscc_gpios[MSCC_GPIO_ALT0];
+	if (offset >= 32) {
+		offset = offset % 32;
+		regoff = info->mscc_gpios[MSCC_GPIO_ALT1];
+	}
+
 	if (f & BIT(0))
-		setbits_le32(info->regs + MSCC_GPIO_ALT0, BIT(pin->pin));
+		mscc_setbits(offset, info->regs + regoff);
 	else
-		clrbits_le32(info->regs + MSCC_GPIO_ALT0, BIT(pin->pin));
+		mscc_clrbits(offset, info->regs + regoff);
 
 	if (f & BIT(1))
-		setbits_le32(info->regs + MSCC_GPIO_ALT1, BIT(pin->pin - 1));
+		mscc_setbits(offset, info->regs + regoff + 4);
 	else
-		clrbits_le32(info->regs + MSCC_GPIO_ALT1, BIT(pin->pin - 1));
+		mscc_clrbits(offset, info->regs + regoff + 4);
 
 	return 0;
 }
@@ -120,8 +148,8 @@
 		}
 
 		info->func[f].ngroups = npins;
-		info->func[f].groups = devm_kzalloc(dev, npins *
-						    sizeof(char *), GFP_KERNEL);
+		info->func[f].groups = devm_kzalloc(dev, npins * sizeof(char *),
+						    GFP_KERNEL);
 		if (!info->func[f].groups)
 			return -ENOMEM;
 
@@ -150,9 +178,15 @@
 	struct mscc_pinctrl *info = dev_get_priv(dev->parent);
 	unsigned int val;
 
-	val = readl(info->regs + MSCC_GPIO_IN);
+	if (mscc_readl(offset, info->regs + info->mscc_gpios[MSCC_GPIO_OE]) &
+	    BIT(offset % 32))
+		val = mscc_readl(offset,
+				 info->regs + info->mscc_gpios[MSCC_GPIO_OUT]);
+	else
+		val = mscc_readl(offset,
+				 info->regs + info->mscc_gpios[MSCC_GPIO_IN]);
 
-	return !!(val & BIT(offset));
+	return !!(val & BIT(offset % 32));
 }
 
 static int mscc_gpio_set(struct udevice *dev, unsigned int offset, int value)
@@ -160,9 +194,11 @@
 	struct mscc_pinctrl *info = dev_get_priv(dev->parent);
 
 	if (value)
-		writel(BIT(offset), info->regs + MSCC_GPIO_OUT_SET);
+		mscc_writel(offset,
+			    info->regs + info->mscc_gpios[MSCC_GPIO_OUT_SET]);
 	else
-		writel(BIT(offset), info->regs + MSCC_GPIO_OUT_CLR);
+		mscc_writel(offset,
+			    info->regs + info->mscc_gpios[MSCC_GPIO_OUT_CLR]);
 
 	return 0;
 }
@@ -172,16 +208,16 @@
 	struct mscc_pinctrl *info = dev_get_priv(dev->parent);
 	unsigned int val;
 
-	val = readl(info->regs + MSCC_GPIO_OE);
+	val = mscc_readl(offset, info->regs + info->mscc_gpios[MSCC_GPIO_OE]);
 
-	return (val & BIT(offset)) ? GPIOF_OUTPUT : GPIOF_INPUT;
+	return (val & BIT(offset % 32)) ? GPIOF_OUTPUT : GPIOF_INPUT;
 }
 
 static int mscc_gpio_direction_input(struct udevice *dev, unsigned int offset)
 {
 	struct mscc_pinctrl *info = dev_get_priv(dev->parent);
 
-	clrbits_le32(info->regs + MSCC_GPIO_OE, BIT(offset));
+	mscc_clrbits(offset, info->regs + info->mscc_gpios[MSCC_GPIO_OE]);
 
 	return 0;
 }
@@ -191,7 +227,7 @@
 {
 	struct mscc_pinctrl *info = dev_get_priv(dev->parent);
 
-	setbits_le32(info->regs + MSCC_GPIO_OE, BIT(offset));
+	mscc_setbits(offset, info->regs + info->mscc_gpios[MSCC_GPIO_OE]);
 
 	return mscc_gpio_set(dev, offset, value);
 }
@@ -215,7 +251,8 @@
 
 int mscc_pinctrl_probe(struct udevice *dev, int num_func,
 		       const struct mscc_pin_data *mscc_pins, int num_pins,
-		       char *const *function_names)
+		       char * const *function_names,
+		       const unsigned long *mscc_gpios)
 {
 	struct mscc_pinctrl *priv = dev_get_priv(dev);
 	int ret;
@@ -230,6 +267,7 @@
 	priv->mscc_pins = mscc_pins;
 	priv->num_pins = num_pins;
 	priv->function_names = function_names;
+	priv->mscc_gpios = mscc_gpios;
 	ret = mscc_pinctrl_register(dev, priv);
 
 	return ret;
diff --git a/drivers/pinctrl/mscc/mscc-common.h b/drivers/pinctrl/mscc/mscc-common.h
index b0001db..3c5c1fa 100644
--- a/drivers/pinctrl/mscc/mscc-common.h
+++ b/drivers/pinctrl/mscc/mscc-common.h
@@ -9,6 +9,19 @@
 
 #define MSCC_FUNC_PER_PIN	4
 
+enum mscc_regs_gpio {
+	MSCC_GPIO_OUT_SET,
+	MSCC_GPIO_OUT_CLR,
+	MSCC_GPIO_OUT,
+	MSCC_GPIO_IN,
+	MSCC_GPIO_OE,
+	MSCC_GPIO_INTR,
+	MSCC_GPIO_INTR_ENA,
+	MSCC_GPIO_INTR_IDENT,
+	MSCC_GPIO_ALT0,
+	MSCC_GPIO_ALT1,
+};
+
 struct mscc_pin_caps {
 	unsigned int pin;
 	unsigned char functions[MSCC_FUNC_PER_PIN];
@@ -41,11 +54,13 @@
 	const struct mscc_pin_data *mscc_pins;
 	int num_pins;
 	char * const *function_names;
+	const unsigned long *mscc_gpios;
 };
 
 int mscc_pinctrl_probe(struct udevice *dev, int num_func,
 		       const struct mscc_pin_data *mscc_pins, int num_pins,
-		       char * const *function_names);
+		       char * const *function_names,
+		       const unsigned long *mscc_gpios);
 const struct pinctrl_ops mscc_pinctrl_ops;
 
 const struct dm_gpio_ops mscc_gpio_ops;
diff --git a/drivers/pinctrl/mscc/pinctrl-jr2.c b/drivers/pinctrl/mscc/pinctrl-jr2.c
new file mode 100644
index 0000000..72a9470
--- /dev/null
+++ b/drivers/pinctrl/mscc/pinctrl-jr2.c
@@ -0,0 +1,323 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Microsemi SoCs pinctrl driver
+ *
+ * Author: <horatiu.vultur@microchip.com>
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <common.h>
+#include <config.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/pinctrl.h>
+#include <dm/root.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <linux/io.h>
+#include <asm/gpio.h>
+#include <asm/system.h>
+#include "mscc-common.h"
+
+enum {
+	FUNC_NONE,
+	FUNC_GPIO,
+	FUNC_IRQ0_IN,
+	FUNC_IRQ0_OUT,
+	FUNC_IRQ1_IN,
+	FUNC_IRQ1_OUT,
+	FUNC_MIIM1,
+	FUNC_MIIM2,
+	FUNC_PCI_WAKE,
+	FUNC_PTP0,
+	FUNC_PTP1,
+	FUNC_PTP2,
+	FUNC_PTP3,
+	FUNC_PWM,
+	FUNC_RECO_CLK0,
+	FUNC_RECO_CLK1,
+	FUNC_SFP0,
+	FUNC_SFP1,
+	FUNC_SFP2,
+	FUNC_SFP3,
+	FUNC_SFP4,
+	FUNC_SFP5,
+	FUNC_SFP6,
+	FUNC_SFP7,
+	FUNC_SFP8,
+	FUNC_SFP9,
+	FUNC_SFP10,
+	FUNC_SFP11,
+	FUNC_SFP12,
+	FUNC_SFP13,
+	FUNC_SFP14,
+	FUNC_SFP15,
+	FUNC_SG0,
+	FUNC_SG1,
+	FUNC_SG2,
+	FUNC_SI,
+	FUNC_TACHO,
+	FUNC_TWI,
+	FUNC_TWI2,
+	FUNC_TWI_SCL_M,
+	FUNC_UART,
+	FUNC_UART2,
+	FUNC_MAX
+};
+
+static char * const jr2_function_names[] = {
+	[FUNC_NONE]		= "none",
+	[FUNC_GPIO]		= "gpio",
+	[FUNC_IRQ0_IN]		= "irq0_in",
+	[FUNC_IRQ0_OUT]		= "irq0_out",
+	[FUNC_IRQ1_IN]		= "irq1_in",
+	[FUNC_IRQ1_OUT]		= "irq1_out",
+	[FUNC_MIIM1]		= "miim1",
+	[FUNC_MIIM2]		= "miim2",
+	[FUNC_PCI_WAKE]		= "pci_wake",
+	[FUNC_PTP0]		= "ptp0",
+	[FUNC_PTP1]		= "ptp1",
+	[FUNC_PTP2]		= "ptp2",
+	[FUNC_PTP3]		= "ptp3",
+	[FUNC_PWM]		= "pwm",
+	[FUNC_RECO_CLK0]	= "reco_clk0",
+	[FUNC_RECO_CLK1]	= "reco_clk1",
+	[FUNC_SFP0]		= "sfp0",
+	[FUNC_SFP1]		= "sfp1",
+	[FUNC_SFP2]		= "sfp2",
+	[FUNC_SFP3]		= "sfp3",
+	[FUNC_SFP4]		= "sfp4",
+	[FUNC_SFP5]		= "sfp5",
+	[FUNC_SFP6]		= "sfp6",
+	[FUNC_SFP7]		= "sfp7",
+	[FUNC_SFP8]		= "sfp8",
+	[FUNC_SFP9]		= "sfp9",
+	[FUNC_SFP10]		= "sfp10",
+	[FUNC_SFP11]		= "sfp11",
+	[FUNC_SFP12]		= "sfp12",
+	[FUNC_SFP13]		= "sfp13",
+	[FUNC_SFP14]		= "sfp14",
+	[FUNC_SFP15]		= "sfp15",
+	[FUNC_SG0]		= "sg0",
+	[FUNC_SG1]		= "sg1",
+	[FUNC_SG2]		= "sg2",
+	[FUNC_SI]		= "si",
+	[FUNC_TACHO]		= "tacho",
+	[FUNC_TWI]		= "twi",
+	[FUNC_TWI2]		= "twi2",
+	[FUNC_TWI_SCL_M]	= "twi_scl_m",
+	[FUNC_UART]		= "uart",
+	[FUNC_UART2]		= "uart2",
+};
+
+#define JR2_P(p, f0, f1)						\
+static struct mscc_pin_caps jr2_pin_##p = {				\
+	.pin = p,							\
+	.functions = {							\
+			FUNC_GPIO, FUNC_##f0, FUNC_##f1, FUNC_NONE	\
+	},								\
+}
+
+JR2_P(0,  SG0,       NONE);
+JR2_P(1,  SG0,       NONE);
+JR2_P(2,  SG0,       NONE);
+JR2_P(3,  SG0,       NONE);
+JR2_P(4,  SG1,       NONE);
+JR2_P(5,  SG1,       NONE);
+JR2_P(6,  IRQ0_IN,   IRQ0_OUT);
+JR2_P(7,  IRQ1_IN,   IRQ1_OUT);
+JR2_P(8,  PTP0,      NONE);
+JR2_P(9,  PTP1,      NONE);
+JR2_P(10, UART,      NONE);
+JR2_P(11, UART,      NONE);
+JR2_P(12, SG1,       NONE);
+JR2_P(13, SG1,       NONE);
+JR2_P(14, TWI,       TWI_SCL_M);
+JR2_P(15, TWI,       NONE);
+JR2_P(16, SI,        TWI_SCL_M);
+JR2_P(17, SI,        TWI_SCL_M);
+JR2_P(18, SI,        TWI_SCL_M);
+JR2_P(19, PCI_WAKE,  NONE);
+JR2_P(20, IRQ0_OUT,  TWI_SCL_M);
+JR2_P(21, IRQ1_OUT,  TWI_SCL_M);
+JR2_P(22, TACHO,     NONE);
+JR2_P(23, PWM,       NONE);
+JR2_P(24, UART2,     NONE);
+JR2_P(25, UART2,     SI);
+JR2_P(26, PTP2,      SI);
+JR2_P(27, PTP3,      SI);
+JR2_P(28, TWI2,      SI);
+JR2_P(29, TWI,       SI);
+JR2_P(30, SG2,       SI);
+JR2_P(31, SG2,       SI);
+JR2_P(32, SG2,       SI);
+JR2_P(33, SG2,       SI);
+JR2_P(34, NONE,      TWI_SCL_M);
+JR2_P(35, NONE,      TWI_SCL_M);
+JR2_P(36, NONE,      TWI_SCL_M);
+JR2_P(37, NONE,      TWI_SCL_M);
+JR2_P(38, NONE,      TWI_SCL_M);
+JR2_P(39, NONE,      TWI_SCL_M);
+JR2_P(40, NONE,      TWI_SCL_M);
+JR2_P(41, NONE,      TWI_SCL_M);
+JR2_P(42, NONE,      TWI_SCL_M);
+JR2_P(43, NONE,      TWI_SCL_M);
+JR2_P(44, NONE,      SFP8);
+JR2_P(45, NONE,      SFP9);
+JR2_P(46, NONE,      SFP10);
+JR2_P(47, NONE,      SFP11);
+JR2_P(48, SFP0,      NONE);
+JR2_P(49, SFP1,      SI);
+JR2_P(50, SFP2,      SI);
+JR2_P(51, SFP3,      SI);
+JR2_P(52, SFP4,      NONE);
+JR2_P(53, SFP5,      NONE);
+JR2_P(54, SFP6,      NONE);
+JR2_P(55, SFP7,      NONE);
+JR2_P(56, MIIM1,     SFP12);
+JR2_P(57, MIIM1,     SFP13);
+JR2_P(58, MIIM2,     SFP14);
+JR2_P(59, MIIM2,     SFP15);
+JR2_P(60, NONE,      NONE);
+JR2_P(61, NONE,      NONE);
+JR2_P(62, NONE,      NONE);
+JR2_P(63, NONE,      NONE);
+
+#define JR2_PIN(n) {						\
+	.name = "GPIO_"#n,					\
+	.drv_data = &jr2_pin_##n				\
+}
+
+static const struct mscc_pin_data jr2_pins[] = {
+	JR2_PIN(0),
+	JR2_PIN(1),
+	JR2_PIN(2),
+	JR2_PIN(3),
+	JR2_PIN(4),
+	JR2_PIN(5),
+	JR2_PIN(6),
+	JR2_PIN(7),
+	JR2_PIN(8),
+	JR2_PIN(9),
+	JR2_PIN(10),
+	JR2_PIN(11),
+	JR2_PIN(12),
+	JR2_PIN(13),
+	JR2_PIN(14),
+	JR2_PIN(15),
+	JR2_PIN(16),
+	JR2_PIN(17),
+	JR2_PIN(18),
+	JR2_PIN(19),
+	JR2_PIN(20),
+	JR2_PIN(21),
+	JR2_PIN(22),
+	JR2_PIN(23),
+	JR2_PIN(24),
+	JR2_PIN(25),
+	JR2_PIN(26),
+	JR2_PIN(27),
+	JR2_PIN(28),
+	JR2_PIN(29),
+	JR2_PIN(30),
+	JR2_PIN(31),
+	JR2_PIN(32),
+	JR2_PIN(33),
+	JR2_PIN(34),
+	JR2_PIN(35),
+	JR2_PIN(36),
+	JR2_PIN(37),
+	JR2_PIN(38),
+	JR2_PIN(39),
+	JR2_PIN(40),
+	JR2_PIN(41),
+	JR2_PIN(42),
+	JR2_PIN(43),
+	JR2_PIN(44),
+	JR2_PIN(45),
+	JR2_PIN(46),
+	JR2_PIN(47),
+	JR2_PIN(48),
+	JR2_PIN(49),
+	JR2_PIN(50),
+	JR2_PIN(51),
+	JR2_PIN(52),
+	JR2_PIN(53),
+	JR2_PIN(54),
+	JR2_PIN(55),
+	JR2_PIN(56),
+	JR2_PIN(57),
+	JR2_PIN(58),
+	JR2_PIN(59),
+	JR2_PIN(60),
+	JR2_PIN(61),
+	JR2_PIN(62),
+	JR2_PIN(63),
+};
+
+static const unsigned long jr2_gpios[] = {
+	[MSCC_GPIO_OUT_SET] = 0x00,
+	[MSCC_GPIO_OUT_CLR] = 0x08,
+	[MSCC_GPIO_OUT] = 0x10,
+	[MSCC_GPIO_IN] = 0x18,
+	[MSCC_GPIO_OE] = 0x20,
+	[MSCC_GPIO_INTR] = 0x28,
+	[MSCC_GPIO_INTR_ENA] = 0x30,
+	[MSCC_GPIO_INTR_IDENT] = 0x38,
+	[MSCC_GPIO_ALT0] = 0x40,
+	[MSCC_GPIO_ALT1] = 0x48,
+};
+
+static int jr2_gpio_probe(struct udevice *dev)
+{
+	struct gpio_dev_priv *uc_priv;
+
+	uc_priv = dev_get_uclass_priv(dev);
+	uc_priv->bank_name = "jr2-gpio";
+	uc_priv->gpio_count = ARRAY_SIZE(jr2_pins);
+
+	return 0;
+}
+
+static struct driver jr2_gpio_driver = {
+	.name	= "jr2-gpio",
+	.id	= UCLASS_GPIO,
+	.probe	= jr2_gpio_probe,
+	.ops	= &mscc_gpio_ops,
+};
+
+static int jr2_pinctrl_probe(struct udevice *dev)
+{
+	int ret;
+
+	ret = mscc_pinctrl_probe(dev, FUNC_MAX, jr2_pins,
+				 ARRAY_SIZE(jr2_pins),
+				 jr2_function_names,
+				 jr2_gpios);
+
+	if (ret)
+		return ret;
+
+	ret = device_bind(dev, &jr2_gpio_driver, "jr2-gpio", NULL,
+			  dev_of_offset(dev), NULL);
+
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct udevice_id jr2_pinctrl_of_match[] = {
+	{ .compatible = "mscc,jaguar2-pinctrl" },
+	{},
+};
+
+U_BOOT_DRIVER(jr2_pinctrl) = {
+	.name = "jr2-pinctrl",
+	.id = UCLASS_PINCTRL,
+	.of_match = of_match_ptr(jr2_pinctrl_of_match),
+	.probe = jr2_pinctrl_probe,
+	.priv_auto_alloc_size = sizeof(struct mscc_pinctrl),
+	.ops = &mscc_pinctrl_ops,
+};
diff --git a/drivers/pinctrl/mscc/pinctrl-luton.c b/drivers/pinctrl/mscc/pinctrl-luton.c
index 7166588..17fbc53 100644
--- a/drivers/pinctrl/mscc/pinctrl-luton.c
+++ b/drivers/pinctrl/mscc/pinctrl-luton.c
@@ -123,6 +123,19 @@
 	LUTON_PIN(31),
 };
 
+static const unsigned long luton_gpios[] = {
+	[MSCC_GPIO_OUT_SET] = 0x00,
+	[MSCC_GPIO_OUT_CLR] = 0x04,
+	[MSCC_GPIO_OUT] = 0x08,
+	[MSCC_GPIO_IN] = 0x0c,
+	[MSCC_GPIO_OE] = 0x10,
+	[MSCC_GPIO_INTR] = 0x14,
+	[MSCC_GPIO_INTR_ENA] = 0x18,
+	[MSCC_GPIO_INTR_IDENT] = 0x1c,
+	[MSCC_GPIO_ALT0] = 0x20,
+	[MSCC_GPIO_ALT1] = 0x24,
+};
+
 static int luton_gpio_probe(struct udevice *dev)
 {
 	struct gpio_dev_priv *uc_priv;
@@ -146,7 +159,8 @@
 	int ret;
 
 	ret = mscc_pinctrl_probe(dev, FUNC_MAX, luton_pins,
-				 ARRAY_SIZE(luton_pins), luton_function_names);
+				 ARRAY_SIZE(luton_pins), luton_function_names,
+				 luton_gpios);
 
 	if (ret)
 		return ret;
diff --git a/drivers/pinctrl/mscc/pinctrl-ocelot.c b/drivers/pinctrl/mscc/pinctrl-ocelot.c
index 10f9b90..49e026b 100644
--- a/drivers/pinctrl/mscc/pinctrl-ocelot.c
+++ b/drivers/pinctrl/mscc/pinctrl-ocelot.c
@@ -138,6 +138,19 @@
 	OCELOT_PIN(21),
 };
 
+static const unsigned long ocelot_gpios[] = {
+	[MSCC_GPIO_OUT_SET] = 0x00,
+	[MSCC_GPIO_OUT_CLR] = 0x04,
+	[MSCC_GPIO_OUT] = 0x08,
+	[MSCC_GPIO_IN] = 0x0c,
+	[MSCC_GPIO_OE] = 0x10,
+	[MSCC_GPIO_INTR] = 0x14,
+	[MSCC_GPIO_INTR_ENA] = 0x18,
+	[MSCC_GPIO_INTR_IDENT] = 0x1c,
+	[MSCC_GPIO_ALT0] = 0x20,
+	[MSCC_GPIO_ALT1] = 0x24,
+};
+
 static int ocelot_gpio_probe(struct udevice *dev)
 {
 	struct gpio_dev_priv *uc_priv;
@@ -162,7 +175,8 @@
 
 	ret = mscc_pinctrl_probe(dev, FUNC_MAX, ocelot_pins,
 				 ARRAY_SIZE(ocelot_pins),
-				 ocelot_function_names);
+				 ocelot_function_names,
+				 ocelot_gpios);
 
 	if (ret)
 		return ret;
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 9c5208b..3a6d61f 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -106,4 +106,11 @@
 	help
 	  Support for reset controller on SoCFPGA platform.
 
+config RESET_MEDIATEK
+	bool "Reset controller driver for MediaTek SoCs"
+	depends on DM_RESET && ARCH_MEDIATEK && CLK
+	default y
+	help
+	  Support for reset controller on MediaTek SoCs.
+
 endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index f452087..8a4dcab 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -17,3 +17,4 @@
 obj-$(CONFIG_RESET_ROCKCHIP) += reset-rockchip.o
 obj-$(CONFIG_RESET_MESON) += reset-meson.o
 obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
+obj-$(CONFIG_RESET_MEDIATEK) += reset-mediatek.o
diff --git a/drivers/reset/reset-mediatek.c b/drivers/reset/reset-mediatek.c
new file mode 100644
index 0000000..e3614e6
--- /dev/null
+++ b/drivers/reset/reset-mediatek.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ *	   Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/lists.h>
+#include <regmap.h>
+#include <reset-uclass.h>
+#include <syscon.h>
+
+struct mediatek_reset_priv {
+	struct regmap *regmap;
+	u32 regofs;
+	u32 nr_resets;
+};
+
+static int mediatek_reset_request(struct reset_ctl *reset_ctl)
+{
+	return 0;
+}
+
+static int mediatek_reset_free(struct reset_ctl *reset_ctl)
+{
+	return 0;
+}
+
+static int mediatek_reset_assert(struct reset_ctl *reset_ctl)
+{
+	struct mediatek_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+	int id = reset_ctl->id;
+
+	if (id >= priv->nr_resets)
+		return -EINVAL;
+
+	return regmap_update_bits(priv->regmap,
+		priv->regofs + ((id / 32) << 2), BIT(id % 32), BIT(id % 32));
+}
+
+static int mediatek_reset_deassert(struct reset_ctl *reset_ctl)
+{
+	struct mediatek_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+	int id = reset_ctl->id;
+
+	if (id >= priv->nr_resets)
+		return -EINVAL;
+
+	return regmap_update_bits(priv->regmap,
+		priv->regofs + ((id / 32) << 2), BIT(id % 32), 0);
+}
+
+struct reset_ops mediatek_reset_ops = {
+	.request = mediatek_reset_request,
+	.free = mediatek_reset_free,
+	.rst_assert = mediatek_reset_assert,
+	.rst_deassert = mediatek_reset_deassert,
+};
+
+static int mediatek_reset_probe(struct udevice *dev)
+{
+	struct mediatek_reset_priv *priv = dev_get_priv(dev);
+
+	if (!priv->regofs && !priv->nr_resets)
+		return -EINVAL;
+
+	priv->regmap = syscon_node_to_regmap(dev_ofnode(dev));
+	if (IS_ERR(priv->regmap))
+		return PTR_ERR(priv->regmap);
+
+	return 0;
+}
+
+int mediatek_reset_bind(struct udevice *pdev, u32 regofs, u32 num_regs)
+{
+	struct udevice *rst_dev;
+	struct mediatek_reset_priv *priv;
+	int ret;
+
+	ret = device_bind_driver_to_node(pdev, "mediatek_reset", "reset",
+					 dev_ofnode(pdev), &rst_dev);
+	if (ret)
+		return ret;
+
+	priv = malloc(sizeof(struct mediatek_reset_priv));
+	priv->regofs = regofs;
+	priv->nr_resets = num_regs * 32;
+	rst_dev->priv = priv;
+
+	return 0;
+}
+
+U_BOOT_DRIVER(mediatek_reset) = {
+	.name = "mediatek_reset",
+	.id = UCLASS_RESET,
+	.probe = mediatek_reset_probe,
+	.ops = &mediatek_reset_ops,
+	.priv_auto_alloc_size = sizeof(struct mediatek_reset_priv),
+};
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index b7ff296..887cd68 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -442,10 +442,23 @@
 
 config DEBUG_UART_SKIP_INIT
 	bool "Skip UART initialization"
+	depends on DEBUG_UART
 	help
 	  Select this if the UART you want to use for debug output is already
 	  initialized by the time U-Boot starts its execution.
 
+config DEBUG_UART_NS16550_CHECK_ENABLED
+	bool "Check if UART is enabled on output"
+	depends on DEBUG_UART
+	depends on DEBUG_UART_NS16550
+	help
+	  Select this if puts()/putc() might be called before the debug UART
+	  has been initialized. If this is disabled, putc() might sit in a
+	  tight loop if it is called before debug_uart_init() has been called.
+
+	  Note that this does not work for every ns16550-compatible UART and
+	  so has to be enabled carefully or you might notice lost characters.
+
 config ALTERA_JTAG_UART
 	bool "Altera JTAG UART support"
 	depends on DM_SERIAL
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 560ca2a..6cf2be8 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -272,12 +272,28 @@
 	serial_dout(&com_port->lcr, UART_LCRVAL);
 }
 
+static inline int NS16550_read_baud_divisor(struct NS16550 *com_port)
+{
+	int ret;
+
+	serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL);
+	ret = serial_din(&com_port->dll) & 0xff;
+	ret |= (serial_din(&com_port->dlm) & 0xff) << 8;
+	serial_dout(&com_port->lcr, UART_LCRVAL);
+
+	return ret;
+}
+
 static inline void _debug_uart_putc(int ch)
 {
 	struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
 
-	while (!(serial_din(&com_port->lsr) & UART_LSR_THRE))
-		;
+	while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) {
+#ifdef CONFIG_DEBUG_UART_NS16550_CHECK_ENABLED
+		if (!NS16550_read_baud_divisor(com_port))
+			return;
+#endif
+	}
 	serial_dout(&com_port->thr, ch);
 }
 
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index ffcd6d1..d4488a2 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -294,49 +294,40 @@
 		ops->setbrg(gd->cur_serial_dev, gd->baudrate);
 }
 
-int serial_getconfig(uint *config)
+int serial_getconfig(struct udevice *dev, uint *config)
 {
 	struct dm_serial_ops *ops;
 
-	if (!gd->cur_serial_dev)
-		return 0;
-
-	ops = serial_get_ops(gd->cur_serial_dev);
+	ops = serial_get_ops(dev);
 	if (ops->getconfig)
-		return ops->getconfig(gd->cur_serial_dev, config);
+		return ops->getconfig(dev, config);
 
 	return 0;
 }
 
-int serial_setconfig(uint config)
+int serial_setconfig(struct udevice *dev, uint config)
 {
 	struct dm_serial_ops *ops;
 
-	if (!gd->cur_serial_dev)
-		return 0;
-
-	ops = serial_get_ops(gd->cur_serial_dev);
+	ops = serial_get_ops(dev);
 	if (ops->setconfig)
-		return ops->setconfig(gd->cur_serial_dev, config);
+		return ops->setconfig(dev, config);
 
 	return 0;
 }
 
-int serial_getinfo(struct serial_device_info *info)
+int serial_getinfo(struct udevice *dev, struct serial_device_info *info)
 {
 	struct dm_serial_ops *ops;
 
-	if (!gd->cur_serial_dev)
-		return -ENODEV;
-
 	if (!info)
 		return -EINVAL;
 
 	info->baudrate = gd->baudrate;
 
-	ops = serial_get_ops(gd->cur_serial_dev);
+	ops = serial_get_ops(dev);
 	if (ops->getinfo)
-		return ops->getinfo(gd->cur_serial_dev, info);
+		return ops->getinfo(dev, info);
 
 	return -EINVAL;
 }
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index a7bb5b3..de4d62d 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -294,6 +294,13 @@
 	 Enable Soft SPI driver. This driver is to use GPIO simulate
 	 the SPI protocol.
 
+config MSCC_BB_SPI
+	bool "MSCC bitbang SPI driver"
+	depends on SOC_VCOREIII
+	help
+	  Enable MSCC bitbang SPI driver. This driver can be used on
+	  MSCC SOCs.
+
 config CF_SPI
 	bool "ColdFire SPI driver"
 	help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 392a925..4acec3e 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -36,6 +36,7 @@
 obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
 obj-$(CONFIG_MTK_QSPI) += mtk_qspi.o
 obj-$(CONFIG_MT7621_SPI) += mt7621_spi.o
+obj-$(CONFIG_MSCC_BB_SPI) += mscc_bb_spi.o
 obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
 obj-$(CONFIG_MXC_SPI) += mxc_spi.o
 obj-$(CONFIG_MXS_SPI) += mxs_spi.o
diff --git a/drivers/spi/mscc_bb_spi.c b/drivers/spi/mscc_bb_spi.c
new file mode 100644
index 0000000..c3c7b80
--- /dev/null
+++ b/drivers/spi/mscc_bb_spi.c
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Microsemi SoCs spi driver
+ *
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <malloc.h>
+#include <spi.h>
+#include <dm.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+
+struct mscc_bb_priv {
+	void __iomem *regs;
+	u32 deactivate_delay_us;
+	bool cs_active;   /* State flag as to whether CS is asserted */
+	int cs_num;
+	u32 svalue;			/* Value to start transfer with */
+	u32 clk1;			/* Clock value start */
+	u32 clk2;			/* Clock value 2nd phase */
+};
+
+/* Delay 24 instructions for this particular application */
+#define hold_time_delay() mscc_vcoreiii_nop_delay(3)
+
+static int mscc_bb_spi_cs_activate(struct mscc_bb_priv *priv, int mode, int cs)
+{
+	if (!priv->cs_active) {
+		int cpha = mode & SPI_CPHA;
+		u32 cs_value;
+
+		priv->cs_num = cs;
+
+		if (cpha) {
+			/* Initial clock starts SCK=1 */
+			priv->clk1 = ICPU_SW_MODE_SW_SPI_SCK;
+			priv->clk2 = 0;
+		} else {
+			/* Initial clock starts SCK=0 */
+			priv->clk1 = 0;
+			priv->clk2 = ICPU_SW_MODE_SW_SPI_SCK;
+		}
+
+		/* Enable bitbang, SCK_OE, SDO_OE */
+		priv->svalue = (ICPU_SW_MODE_SW_PIN_CTRL_MODE | /* Bitbang */
+				ICPU_SW_MODE_SW_SPI_SCK_OE    | /* SCK_OE */
+				ICPU_SW_MODE_SW_SPI_SDO_OE);   /* SDO OE */
+
+		/* Add CS */
+		if (cs >= 0) {
+			cs_value =
+				ICPU_SW_MODE_SW_SPI_CS_OE(BIT(cs)) |
+				ICPU_SW_MODE_SW_SPI_CS(BIT(cs));
+		} else {
+			cs_value = 0;
+		}
+
+		priv->svalue |= cs_value;
+
+		/* Enable the CS in HW, Initial clock value */
+		writel(priv->svalue | priv->clk2, priv->regs);
+
+		priv->cs_active = true;
+		debug("Activated CS%d\n", priv->cs_num);
+	}
+
+	return 0;
+}
+
+static int mscc_bb_spi_cs_deactivate(struct mscc_bb_priv *priv, int deact_delay)
+{
+	if (priv->cs_active) {
+		/* Keep driving the CLK to its current value while
+		 * actively deselecting CS.
+		 */
+		u32 value = readl(priv->regs);
+
+		value &= ~ICPU_SW_MODE_SW_SPI_CS_M;
+		writel(value, priv->regs);
+		hold_time_delay();
+
+		/* Stop driving the clock, but keep CS with nCS == 1 */
+		value &= ~ICPU_SW_MODE_SW_SPI_SCK_OE;
+		writel(value, priv->regs);
+
+		/* Deselect hold time delay */
+		if (deact_delay)
+			udelay(deact_delay);
+
+		/* Drop everything */
+		writel(0, priv->regs);
+
+		priv->cs_active = false;
+		debug("Deactivated CS%d\n", priv->cs_num);
+	}
+
+	return 0;
+}
+
+int mscc_bb_spi_claim_bus(struct udevice *dev)
+{
+	return 0;
+}
+
+int mscc_bb_spi_release_bus(struct udevice *dev)
+{
+	return 0;
+}
+
+int mscc_bb_spi_xfer(struct udevice *dev, unsigned int bitlen,
+		     const void *dout, void *din, unsigned long flags)
+{
+	struct udevice *bus = dev_get_parent(dev);
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
+	struct mscc_bb_priv *priv = dev_get_priv(bus);
+	u32             i, count;
+	const u8	*txd = dout;
+	u8		*rxd = din;
+
+	debug("spi_xfer: slave %s:%s cs%d mode %d, dout %p din %p bitlen %u\n",
+	      dev->parent->name, dev->name, plat->cs,  plat->mode, dout,
+	      din, bitlen);
+
+	if (flags & SPI_XFER_BEGIN)
+		mscc_bb_spi_cs_activate(priv, plat->mode, plat->cs);
+
+	count = bitlen / 8;
+	for (i = 0; i < count; i++) {
+		u32 rx = 0, mask = 0x80, value;
+
+		while (mask) {
+			/* Initial condition: CLK is low. */
+			value = priv->svalue;
+			if (txd && txd[i] & mask)
+				value |= ICPU_SW_MODE_SW_SPI_SDO;
+
+			/* Drive data while taking CLK low. The device
+			 * we're accessing will sample on the
+			 * following rising edge and will output data
+			 * on this edge for us to be sampled at the
+			 * end of this loop.
+			 */
+			writel(value | priv->clk1, priv->regs);
+
+			/* Wait for t_setup. All devices do have a
+			 * setup-time, so we always insert some delay
+			 * here. Some devices have a very long
+			 * setup-time, which can be adjusted by the
+			 * user through vcoreiii_device->delay.
+			 */
+			hold_time_delay();
+
+			/* Drive the clock high. */
+			writel(value | priv->clk2, priv->regs);
+
+			/* Wait for t_hold. See comment about t_setup
+			 * above.
+			 */
+			hold_time_delay();
+
+			/* We sample as close to the next falling edge
+			 * as possible.
+			 */
+			value = readl(priv->regs);
+			if (value & ICPU_SW_MODE_SW_SPI_SDI)
+				rx |= mask;
+			mask >>= 1;
+		}
+		if (rxd) {
+			debug("Read 0x%02x\n", rx);
+			rxd[i] = (u8)rx;
+		}
+		debug("spi_xfer: byte %d/%d\n", i + 1, count);
+	}
+
+	debug("spi_xfer: done\n");
+
+	if (flags & SPI_XFER_END)
+		mscc_bb_spi_cs_deactivate(priv, priv->deactivate_delay_us);
+
+	return 0;
+}
+
+int mscc_bb_spi_set_speed(struct udevice *dev, unsigned int speed)
+{
+	/* Accept any speed */
+	return 0;
+}
+
+int mscc_bb_spi_set_mode(struct udevice *dev, unsigned int mode)
+{
+	return 0;
+}
+
+static const struct dm_spi_ops mscc_bb_ops = {
+	.claim_bus	= mscc_bb_spi_claim_bus,
+	.release_bus	= mscc_bb_spi_release_bus,
+	.xfer		= mscc_bb_spi_xfer,
+	.set_speed	= mscc_bb_spi_set_speed,
+	.set_mode	= mscc_bb_spi_set_mode,
+};
+
+static const struct udevice_id mscc_bb_ids[] = {
+	{ .compatible = "mscc,luton-bb-spi" },
+	{ }
+};
+
+static int mscc_bb_spi_probe(struct udevice *bus)
+{
+	struct mscc_bb_priv *priv = dev_get_priv(bus);
+
+	debug("%s: loaded, priv %p\n", __func__, priv);
+
+	priv->regs = (void __iomem *)dev_read_addr(bus);
+
+	priv->deactivate_delay_us =
+		dev_read_u32_default(bus, "spi-deactivate-delay", 0);
+
+	priv->cs_active = false;
+
+	return 0;
+}
+
+U_BOOT_DRIVER(mscc_bb) = {
+	.name	= "mscc_bb",
+	.id	= UCLASS_SPI,
+	.of_match = mscc_bb_ids,
+	.ops	= &mscc_bb_ops,
+	.priv_auto_alloc_size = sizeof(struct mscc_bb_priv),
+	.probe	= mscc_bb_spi_probe,
+};
diff --git a/drivers/video/rockchip/Kconfig b/drivers/video/rockchip/Kconfig
index b1d7c62..10182d0 100644
--- a/drivers/video/rockchip/Kconfig
+++ b/drivers/video/rockchip/Kconfig
@@ -65,6 +65,6 @@
 	help
 	  This enables Mobile Industry Processor Interface(MIPI) display
 	  support. The mipi controller and dphy on rk3288& rk3399 support
-	  16,18, 24 bits per pixel with upto 2k resolution ratio.
+	  16,18, 24 bits per pixel with up to 2k resolution ratio.
 
 endif
diff --git a/dts/Makefile b/dts/Makefile
index cd6e9a9..a7a6043 100644
--- a/dts/Makefile
+++ b/dts/Makefile
@@ -43,9 +43,6 @@
 arch-dtbs:
 	$(Q)$(MAKE) $(build)=$(ARCH_PATH) dtbs
 
-.SECONDARY: $(obj)/dt.dtb.S $(obj)/dt-spl.dtb.S
-
-
 ifeq ($(CONFIG_SPL_BUILD),y)
 obj-$(CONFIG_OF_EMBED) := dt-spl.dtb.o
 # support "out-of-tree" build for dtb-spl
diff --git a/env/common.c b/env/common.c
index 3317cef..d1a6a52 100644
--- a/env/common.c
+++ b/env/common.c
@@ -240,32 +240,76 @@
 	}
 }
 
-#if defined(CONFIG_AUTO_COMPLETE) && !defined(CONFIG_SPL_BUILD)
-int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf)
+#ifdef CONFIG_AUTO_COMPLETE
+int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf,
+		 bool dollar_comp)
 {
 	ENTRY *match;
 	int found, idx;
 
+	if (dollar_comp) {
+		/*
+		 * When doing $ completion, the first character should
+		 * obviously be a '$'.
+		 */
+		if (var[0] != '$')
+			return 0;
+
+		var++;
+
+		/*
+		 * The second one, if present, should be a '{', as some
+		 * configuration of the u-boot shell expand ${var} but not
+		 * $var.
+		 */
+		if (var[0] == '{')
+			var++;
+		else if (var[0] != '\0')
+			return 0;
+	}
+
 	idx = 0;
 	found = 0;
 	cmdv[0] = NULL;
 
+
 	while ((idx = hmatch_r(var, idx, &match, &env_htab))) {
 		int vallen = strlen(match->key) + 1;
 
-		if (found >= maxv - 2 || bufsz < vallen)
+		if (found >= maxv - 2 ||
+		    bufsz < vallen + (dollar_comp ? 3 : 0))
 			break;
 
 		cmdv[found++] = buf;
+
+		/* Add the '${' prefix to each var when doing $ completion. */
+		if (dollar_comp) {
+			strcpy(buf, "${");
+			buf += 2;
+			bufsz -= 3;
+		}
+
 		memcpy(buf, match->key, vallen);
 		buf += vallen;
 		bufsz -= vallen;
+
+		if (dollar_comp) {
+			/*
+			 * This one is a bit odd: vallen already contains the
+			 * '\0' character but we need to add the '}' suffix,
+			 * hence the buf - 1 here. strcpy() will add the '\0'
+			 * character just after '}'. buf is then incremented
+			 * to account for the extra '}' we just added.
+			 */
+			strcpy(buf - 1, "}");
+			buf++;
+		}
 	}
 
 	qsort(cmdv, found, sizeof(cmdv[0]), strcmp_compar);
 
 	if (idx)
-		cmdv[found++] = "...";
+		cmdv[found++] = dollar_comp ? "${...}" : "...";
 
 	cmdv[found] = NULL;
 	return found;
diff --git a/env/sf.c b/env/sf.c
index 23cbad5..31dd003 100644
--- a/env/sf.c
+++ b/env/sf.c
@@ -81,6 +81,40 @@
 	return 0;
 }
 
+static int is_end(const char *addr, size_t size)
+{
+	/* The end of env variables is marked by '\0\0' */
+	int i = 0;
+
+	for (i = 0; i < size - 1; ++i)
+		if (addr[i] == 0x0 && addr[i + 1] == 0x0)
+			return 1;
+	return 0;
+}
+
+static int spi_flash_read_env(struct spi_flash *flash, u32 offset, size_t len,
+			      void *buf)
+{
+	u32 addr = 0;
+	u32 page_size = flash->page_size;
+
+	memset(buf, 0xff, len);
+	for (int i = 0; i < len / page_size; ++i) {
+		int ret = spi_flash_read(flash, offset, page_size,
+					 &((char *)buf)[addr]);
+
+		if (ret < 0)
+			return ret;
+
+		if (is_end(&((char *)buf)[addr], page_size))
+			return 0;
+
+		addr += page_size;
+		offset += page_size;
+	}
+	return 0;
+}
+
 #if defined(CONFIG_ENV_OFFSET_REDUND)
 #ifdef CMD_SAVEENV
 static int env_sf_save(void)
@@ -116,8 +150,8 @@
 			ret = -ENOMEM;
 			goto done;
 		}
-		ret = spi_flash_read(env_flash, saved_offset,
-					saved_size, saved_buffer);
+		ret = spi_flash_read_env(env_flash, saved_offset,
+					 saved_size, saved_buffer);
 		if (ret)
 			goto done;
 	}
@@ -183,10 +217,10 @@
 	if (ret)
 		goto out;
 
-	read1_fail = spi_flash_read(env_flash, CONFIG_ENV_OFFSET,
-				    CONFIG_ENV_SIZE, tmp_env1);
-	read2_fail = spi_flash_read(env_flash, CONFIG_ENV_OFFSET_REDUND,
-				    CONFIG_ENV_SIZE, tmp_env2);
+	read1_fail = spi_flash_read_env(env_flash, CONFIG_ENV_OFFSET,
+					CONFIG_ENV_SIZE, tmp_env1);
+	read2_fail = spi_flash_read_env(env_flash, CONFIG_ENV_OFFSET_REDUND,
+					CONFIG_ENV_SIZE, tmp_env2);
 
 	ret = env_import_redund((char *)tmp_env1, read1_fail, (char *)tmp_env2,
 				read2_fail);
@@ -220,8 +254,8 @@
 		if (!saved_buffer)
 			goto done;
 
-		ret = spi_flash_read(env_flash, saved_offset,
-			saved_size, saved_buffer);
+		ret = spi_flash_read_env(env_flash, saved_offset,
+					 saved_size, saved_buffer);
 		if (ret)
 			goto done;
 	}
@@ -277,10 +311,10 @@
 	if (ret)
 		goto out;
 
-	ret = spi_flash_read(env_flash,
-		CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, buf);
+	ret = spi_flash_read_env(env_flash, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
+				 buf);
 	if (ret) {
-		set_default_env("spi_flash_read() failed", 0);
+		set_default_env("spi_flash_read_env() failed", 0);
 		goto err_read;
 	}
 
diff --git a/examples/standalone/Makefile b/examples/standalone/Makefile
index f01816f..0b17a91 100644
--- a/examples/standalone/Makefile
+++ b/examples/standalone/Makefile
@@ -26,7 +26,6 @@
 LIBOBJS-$(CONFIG_PPC) += ppc_longjmp.o ppc_setjmp.o
 LIBOBJS-y += stubs.o
 
-.SECONDARY: $(call objectify,$(COBJS))
 targets += $(patsubst $(obj)/%,%,$(LIB)) $(COBJS) $(LIBOBJS-y)
 
 LIBOBJS	:= $(addprefix $(obj)/,$(LIBOBJS-y))
diff --git a/examples/standalone/riscv.lds b/examples/standalone/riscv.lds
deleted file mode 100644
index 9a25861..0000000
--- a/examples/standalone/riscv.lds
+++ /dev/null
@@ -1,40 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2017 Andes Technology Corporation
- * Rick Chen, Andes Technology Corporation <rick@andestech.com>
- */
-
-OUTPUT_ARCH(riscv)
-ENTRY(_start)
-SECTIONS
-{
-    . = ALIGN(4);
-    .text :
-    {
-        *(.text)
-    }
-
-    . = ALIGN(4);
-    .data : {
-			__global_pointer$ = . + 0x800;
-			*(.data)
-		}
-
-    . = ALIGN(4);
-
-    .got : {
-        __got_start = .;
-        *(.got)
-        __got_end = .;
-    }
-
-     . = ALIGN(4);
-    __bss_start = .;
-    .bss : { *(.bss) }
-    __bss_end = .;
-
-    . = ALIGN(4);
-    .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
-
-    _end = .;
-}
diff --git a/examples/standalone/stubs.c b/examples/standalone/stubs.c
index fadde66..0827bde 100644
--- a/examples/standalone/stubs.c
+++ b/examples/standalone/stubs.c
@@ -174,16 +174,27 @@
 	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "$r16");
 #elif defined(CONFIG_RISCV)
 /*
- * t7 holds the pointer to the global_data. gp is call clobbered.
+ * gp holds the pointer to the global_data. t0 is call clobbered.
  */
+#ifdef CONFIG_ARCH_RV64I
 #define EXPORT_FUNC(f, a, x, ...)	\
 	asm volatile (			\
 "	.globl " #x "\n"		\
 #x ":\n"				\
-"	lw	x19, %0(gp)\n"		\
-"	lw	x19, %1(x19)\n"		\
-"	jr	x19\n"			\
-	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "x19");
+"	ld	t0, %0(gp)\n"		\
+"	ld	t0, %1(t0)\n"		\
+"	jr	t0\n"			\
+	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "t0");
+#else
+#define EXPORT_FUNC(f, a, x, ...)	\
+	asm volatile (			\
+"	.globl " #x "\n"		\
+#x ":\n"				\
+"	lw	t0, %0(gp)\n"		\
+"	lw	t0, %1(t0)\n"		\
+"	jr	t0\n"			\
+	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "t0");
+#endif
 #elif defined(CONFIG_ARC)
 /*
  * r25 holds the pointer to the global_data. r10 is call clobbered.
diff --git a/fs/fs.c b/fs/fs.c
index cb26517..7fd2210 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -429,13 +429,57 @@
 	return ret;
 }
 
-int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
-	    loff_t *actread)
+#ifdef CONFIG_LMB
+/* Check if a file may be read to the given address */
+static int fs_read_lmb_check(const char *filename, ulong addr, loff_t offset,
+			     loff_t len, struct fstype_info *info)
+{
+	struct lmb lmb;
+	int ret;
+	loff_t size;
+	loff_t read_len;
+
+	/* get the actual size of the file */
+	ret = info->size(filename, &size);
+	if (ret)
+		return ret;
+	if (offset >= size) {
+		/* offset >= EOF, no bytes will be written */
+		return 0;
+	}
+	read_len = size - offset;
+
+	/* limit to 'len' if it is smaller */
+	if (len && len < read_len)
+		read_len = len;
+
+	lmb_init_and_reserve(&lmb, gd->bd->bi_dram[0].start,
+			     gd->bd->bi_dram[0].size, (void *)gd->fdt_blob);
+	lmb_dump_all(&lmb);
+
+	if (lmb_alloc_addr(&lmb, addr, read_len) == addr)
+		return 0;
+
+	printf("** Reading file would overwrite reserved memory **\n");
+	return -ENOSPC;
+}
+#endif
+
+static int _fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
+		    int do_lmb_check, loff_t *actread)
 {
 	struct fstype_info *info = fs_get_info(fs_type);
 	void *buf;
 	int ret;
 
+#ifdef CONFIG_LMB
+	if (do_lmb_check) {
+		ret = fs_read_lmb_check(filename, addr, offset, len, info);
+		if (ret)
+			return ret;
+	}
+#endif
+
 	/*
 	 * We don't actually know how many bytes are being read, since len==0
 	 * means read the whole file.
@@ -452,6 +496,12 @@
 	return ret;
 }
 
+int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
+	    loff_t *actread)
+{
+	return _fs_read(filename, addr, offset, len, 0, actread);
+}
+
 int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,
 	     loff_t *actwrite)
 {
@@ -622,7 +672,7 @@
 		pos = 0;
 
 	time = get_timer(0);
-	ret = fs_read(filename, addr, pos, bytes, &len_read);
+	ret = _fs_read(filename, addr, pos, bytes, 1, &len_read);
 	time = get_timer(time);
 	if (ret < 0)
 		return 1;
diff --git a/include/command.h b/include/command.h
index 200c7a5..461b174 100644
--- a/include/command.h
+++ b/include/command.h
@@ -29,7 +29,16 @@
 struct cmd_tbl_s {
 	char		*name;		/* Command Name			*/
 	int		maxargs;	/* maximum number of arguments	*/
-	int		repeatable;	/* autorepeat allowed?		*/
+					/*
+					 * Same as ->cmd() except the command
+					 * tells us if it can be repeated.
+					 * Replaces the old ->repeatable field
+					 * which was not able to make
+					 * repeatable property different for
+					 * the main command and sub-commands.
+					 */
+	int		(*cmd_rep)(struct cmd_tbl_s *cmd, int flags, int argc,
+				   char * const argv[], int *repeatable);
 					/* Implementation function	*/
 	int		(*cmd)(struct cmd_tbl_s *, int, int, char * const []);
 	char		*usage;		/* Usage message	(short)	*/
@@ -54,9 +63,25 @@
 	      flag, int argc, char * const argv[]);
 cmd_tbl_t *find_cmd(const char *cmd);
 cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len);
+int complete_subcmdv(cmd_tbl_t *cmdtp, int count, int argc,
+		     char * const argv[], char last_char, int maxv,
+		     char *cmdv[]);
 
 extern int cmd_usage(const cmd_tbl_t *cmdtp);
 
+/* Dummy ->cmd and ->cmd_rep wrappers. */
+int cmd_always_repeatable(cmd_tbl_t *cmdtp, int flag, int argc,
+			  char * const argv[], int *repeatable);
+int cmd_never_repeatable(cmd_tbl_t *cmdtp, int flag, int argc,
+			 char * const argv[], int *repeatable);
+int cmd_discard_repeatable(cmd_tbl_t *cmdtp, int flag, int argc,
+			   char * const argv[]);
+
+static inline bool cmd_is_repeatable(cmd_tbl_t *cmdtp)
+{
+	return cmdtp->cmd_rep == cmd_always_repeatable;
+}
+
 #ifdef CONFIG_AUTO_COMPLETE
 extern int var_complete(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]);
 extern int cmd_auto_complete(const char *const prompt, char *buf, int *np, int *colp);
@@ -184,17 +209,93 @@
 # define _CMD_HELP(x)
 #endif
 
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+#define U_BOOT_SUBCMDS_RELOC(_cmdname)					\
+	static void _cmdname##_subcmds_reloc(void)			\
+	{								\
+		static int relocated;					\
+									\
+		if (relocated)						\
+			return;						\
+									\
+		fixup_cmdtable(_cmdname##_subcmds,			\
+			       ARRAY_SIZE(_cmdname##_subcmds));		\
+		relocated = 1;						\
+	}
+#else
+#define U_BOOT_SUBCMDS_RELOC(_cmdname)					\
+	static void _cmdname##_subcmds_reloc(void) { }
+#endif
+
+#define U_BOOT_SUBCMDS_DO_CMD(_cmdname)					\
+	static int do_##_cmdname(cmd_tbl_t *cmdtp, int flag, int argc,	\
+				 char * const argv[], int *repeatable)	\
+	{								\
+		cmd_tbl_t *subcmd;					\
+									\
+		_cmdname##_subcmds_reloc();				\
+									\
+		/* We need at least the cmd and subcmd names. */	\
+		if (argc < 2 || argc > CONFIG_SYS_MAXARGS)		\
+			return CMD_RET_USAGE;				\
+									\
+		subcmd = find_cmd_tbl(argv[1], _cmdname##_subcmds,	\
+				      ARRAY_SIZE(_cmdname##_subcmds));	\
+		if (!subcmd || argc - 1 > subcmd->maxargs)		\
+			return CMD_RET_USAGE;				\
+									\
+		if (flag == CMD_FLAG_REPEAT &&				\
+		    !cmd_is_repeatable(subcmd))				\
+			return CMD_RET_SUCCESS;				\
+									\
+		return subcmd->cmd_rep(subcmd, flag, argc - 1,		\
+				       argv + 1, repeatable);		\
+	}
+
+#ifdef CONFIG_AUTO_COMPLETE
+#define U_BOOT_SUBCMDS_COMPLETE(_cmdname)				\
+	static int complete_##_cmdname(int argc, char * const argv[],	\
+				       char last_char, int maxv,	\
+				       char *cmdv[])			\
+	{								\
+		return complete_subcmdv(_cmdname##_subcmds,		\
+					ARRAY_SIZE(_cmdname##_subcmds),	\
+					argc - 1, argv + 1, last_char,	\
+					maxv, cmdv);			\
+	}
+#else
+#define U_BOOT_SUBCMDS_COMPLETE(_cmdname)
+#endif
+
+#define U_BOOT_SUBCMDS(_cmdname, ...)					\
+	static cmd_tbl_t _cmdname##_subcmds[] = { __VA_ARGS__ };	\
+	U_BOOT_SUBCMDS_RELOC(_cmdname)					\
+	U_BOOT_SUBCMDS_DO_CMD(_cmdname)					\
+	U_BOOT_SUBCMDS_COMPLETE(_cmdname)
+
 #ifdef CONFIG_CMDLINE
+#define U_BOOT_CMDREP_MKENT_COMPLETE(_name, _maxargs, _cmd_rep,		\
+				     _usage, _help, _comp)		\
+		{ #_name, _maxargs, _cmd_rep, cmd_discard_repeatable,	\
+		  _usage, _CMD_HELP(_help) _CMD_COMPLETE(_comp) }
+
 #define U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd,		\
 				_usage, _help, _comp)			\
-		{ #_name, _maxargs, _rep, _cmd, _usage,			\
-			_CMD_HELP(_help) _CMD_COMPLETE(_comp) }
+		{ #_name, _maxargs,					\
+		 _rep ? cmd_always_repeatable : cmd_never_repeatable,	\
+		 _cmd, _usage, _CMD_HELP(_help) _CMD_COMPLETE(_comp) }
 
 #define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, _comp) \
 	ll_entry_declare(cmd_tbl_t, _name, cmd) =			\
 		U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd,	\
 						_usage, _help, _comp);
 
+#define U_BOOT_CMDREP_COMPLETE(_name, _maxargs, _cmd_rep, _usage,	\
+			       _help, _comp)				\
+	ll_entry_declare(cmd_tbl_t, _name, cmd) =			\
+		U_BOOT_CMDREP_MKENT_COMPLETE(_name, _maxargs, _cmd_rep,	\
+					     _usage, _help, _comp)
+
 #else
 #define U_BOOT_SUBCMD_START(name)	static cmd_tbl_t name[] = {};
 #define U_BOOT_SUBCMD_END
@@ -206,15 +307,25 @@
 			_cmd(NULL, 0, 0, NULL);				\
 		return 0;						\
 	}
+
+#define U_BOOT_CMDREP_MKENT_COMPLETE(_name, _maxargs, _cmd_rep,		\
+				     _usage, _help, _comp)		\
+		{ #_name, _maxargs, 0 ? _cmd_rep : NULL, NULL, _usage,	\
+			_CMD_HELP(_help) _CMD_COMPLETE(_comp) }
+
 #define U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, _usage,	\
 				  _help, _comp)				\
-		{ #_name, _maxargs, _rep, 0 ? _cmd : NULL, _usage,	\
+		{ #_name, _maxargs, NULL, 0 ? _cmd : NULL, _usage,	\
 			_CMD_HELP(_help) _CMD_COMPLETE(_comp) }
 
 #define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help,	\
 			    _comp)				\
 	_CMD_REMOVE(sub_ ## _name, _cmd)
 
+#define U_BOOT_CMDREP_COMPLETE(_name, _maxargs, _cmd_rep, _usage,	\
+			       _help, _comp)				\
+	_CMD_REMOVE(sub_ ## _name, _cmd_rep)
+
 #endif /* CONFIG_CMDLINE */
 
 #define U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help)		\
@@ -224,4 +335,18 @@
 	U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd,		\
 					_usage, _help, NULL)
 
+#define U_BOOT_SUBCMD_MKENT_COMPLETE(_name, _maxargs, _rep, _do_cmd,	\
+				     _comp)				\
+	U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _do_cmd,	\
+				  "", "", _comp)
+
+#define U_BOOT_SUBCMD_MKENT(_name, _maxargs, _rep, _do_cmd)		\
+	U_BOOT_SUBCMD_MKENT_COMPLETE(_name, _maxargs, _rep, _do_cmd,	\
+				     NULL)
+
+#define U_BOOT_CMD_WITH_SUBCMDS(_name, _usage, _help, ...)		\
+	U_BOOT_SUBCMDS(_name, __VA_ARGS__)				\
+	U_BOOT_CMDREP_COMPLETE(_name, CONFIG_SYS_MAXARGS, do_##_name,	\
+			       _usage, _help, complete_##_name)
+
 #endif	/* __COMMAND_H */
diff --git a/include/common.h b/include/common.h
index 657cc40..2c21dee 100644
--- a/include/common.h
+++ b/include/common.h
@@ -248,7 +248,8 @@
 }
 
 #ifdef CONFIG_AUTO_COMPLETE
-int env_complete(char *var, int maxv, char *cmdv[], int maxsz, char *buf);
+int env_complete(char *var, int maxv, char *cmdv[], int maxsz, char *buf,
+		 bool dollar_comp);
 #endif
 int get_env_id (void);
 
@@ -350,8 +351,6 @@
 void smp_kick_all_cpus(void);
 
 /* $(CPU)/serial.c */
-struct serial_device_info;
-
 int	serial_init   (void);
 void	serial_setbrg (void);
 void	serial_putc   (const char);
@@ -359,9 +358,6 @@
 void	serial_puts   (const char *);
 int	serial_getc   (void);
 int	serial_tstc   (void);
-int	serial_getconfig(uint *config);
-int	serial_setconfig(uint config);
-int	serial_getinfo(struct serial_device_info *info);
 
 /* $(CPU)/speed.c */
 int	get_clocks (void);
diff --git a/include/configs/hikey.h b/include/configs/hikey.h
index 1376d61..572a52f 100644
--- a/include/configs/hikey.h
+++ b/include/configs/hikey.h
@@ -18,6 +18,8 @@
 
 #define CONFIG_REMAKE_ELF
 
+#define CONFIG_SYS_BOOTM_LEN		SZ_64M
+
 /* Physical Memory Map */
 
 /* CONFIG_SYS_TEXT_BASE needs to align with where ATF loads bl33.bin */
diff --git a/include/configs/mt7623.h b/include/configs/mt7623.h
index ba76350..e449364 100644
--- a/include/configs/mt7623.h
+++ b/include/configs/mt7623.h
@@ -24,6 +24,7 @@
 
 /* Size of malloc() pool */
 #define CONFIG_SYS_MALLOC_LEN		SZ_4M
+#define CONFIG_SYS_NONCACHED_MEMORY	SZ_1M
 
 /* Environment */
 #define CONFIG_ENV_SIZE			SZ_4K
@@ -53,4 +54,11 @@
 #define CONFIG_EXTRA_ENV_SETTINGS	\
 	FDT_HIGH
 
+/* Ethernet */
+#define CONFIG_IPADDR			192.168.1.1
+#define CONFIG_SERVERIP			192.168.1.2
+
+#define CONFIG_SYS_MMC_ENV_DEV		0
+#define CONFIG_ENV_OFFSET		0x100000
+
 #endif
diff --git a/include/configs/mt7629.h b/include/configs/mt7629.h
index a665a5e..9910d8c 100644
--- a/include/configs/mt7629.h
+++ b/include/configs/mt7629.h
@@ -24,6 +24,7 @@
 
 /* Size of malloc() pool */
 #define CONFIG_SYS_MALLOC_LEN		SZ_4M
+#define CONFIG_SYS_NONCACHED_MEMORY	SZ_1M
 
 /* Environment */
 #define CONFIG_ENV_SIZE			SZ_4K
@@ -54,4 +55,8 @@
 /* DRAM */
 #define CONFIG_SYS_SDRAM_BASE		0x40000000
 
+/* Ethernet */
+#define CONFIG_IPADDR			192.168.1.1
+#define CONFIG_SERVERIP			192.168.1.2
+
 #endif
diff --git a/include/configs/omap3_igep00x0.h b/include/configs/omap3_igep00x0.h
index 775374c..521e167 100644
--- a/include/configs/omap3_igep00x0.h
+++ b/include/configs/omap3_igep00x0.h
@@ -32,16 +32,6 @@
 #define GPIO_IGEP00X0_BOARD_DETECTION		28
 #define GPIO_IGEP00X0_REVISION_DETECTION	129
 
-/* USB device configuration */
-#define CONFIG_USB_DEVICE		1
-#define CONFIG_USB_TTY			1
-
-/* 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	"IGEP"
-
 #ifndef CONFIG_SPL_BUILD
 
 /* Environment */
diff --git a/include/configs/qemu-riscv.h b/include/configs/qemu-riscv.h
index b29d155..2588c5a 100644
--- a/include/configs/qemu-riscv.h
+++ b/include/configs/qemu-riscv.h
@@ -17,6 +17,8 @@
 
 #define CONFIG_SYS_BOOTM_LEN		SZ_16M
 
+#define CONFIG_STANDALONE_LOAD_ADDR	0x80200000
+
 /* Environment options */
 #define CONFIG_ENV_SIZE			SZ_4K
 
diff --git a/include/configs/vcoreiii.h b/include/configs/vcoreiii.h
index df89cda..4ea5f40 100644
--- a/include/configs/vcoreiii.h
+++ b/include/configs/vcoreiii.h
@@ -22,6 +22,8 @@
 #endif
 #define CONFIG_SYS_NS16550_CLK		CONFIG_SYS_MIPS_TIMER_FREQ
 
+#define CONFIG_BOARD_TYPES
+
 #if defined(CONFIG_ENV_IS_IN_SPI_FLASH) && !defined(CONFIG_ENV_OFFSET)
 #define CONFIG_ENV_OFFSET		(1024 * 1024)
 #define CONFIG_ENV_SIZE			(256 * 1024)
diff --git a/include/dt-bindings/reset/mtk-reset.h b/include/dt-bindings/reset/mtk-reset.h
new file mode 100644
index 0000000..5f0a74f
--- /dev/null
+++ b/include/dt-bindings/reset/mtk-reset.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#ifndef _DT_BINDINGS_MTK_RESET_H_
+#define _DT_BINDINGS_MTK_RESET_H_
+
+/* ETHSYS */
+#define ETHSYS_PPE_RST			31
+#define ETHSYS_EPHY_RST			24
+#define ETHSYS_GMAC_RST			23
+#define ETHSYS_ESW_RST			16
+#define ETHSYS_FE_RST			6
+#define ETHSYS_MCM_RST			2
+#define ETHSYS_SYS_RST			0
+
+#endif /* _DT_BINDINGS_MTK_RESET_H_ */
diff --git a/include/fs_loader.h b/include/fs_loader.h
index 0be4f17..b728c06 100644
--- a/include/fs_loader.h
+++ b/include/fs_loader.h
@@ -9,21 +9,6 @@
 #include <dm.h>
 
 /**
- * struct firmware - A place for storing firmware and its attribute data.
- *
- * This holds information about a firmware and its content.
- *
- * @size: Size of a file
- * @data: Buffer for file
- * @priv: Firmware loader private fields
- */
-struct firmware {
-	size_t size;
-	const u8 *data;
-	void *priv;
-};
-
-/**
  * struct phandle_part - A place for storing phandle of node and its partition
  *
  * This holds information about a phandle of the block device, and its
@@ -53,27 +38,18 @@
 };
 
 /**
- * release_firmware - Release the resource associated with a firmware image
- * @firmware: Firmware resource to release
- */
-void release_firmware(struct firmware *firmware);
-
-/**
  * request_firmware_into_buf - Load firmware into a previously allocated buffer.
- * @plat: Platform data such as storage and partition firmware loading from.
+ * @dev: An instance of a driver.
  * @name: Name of firmware file.
  * @buf: Address of buffer to load firmware into.
  * @size: Size of buffer.
  * @offset: Offset of a file for start reading into buffer.
- * @firmwarep: Pointer to firmware image.
  *
- * The firmware is loaded directly into the buffer pointed to by @buf and
- * the @firmwarep data member is pointed at @buf.
+ * The firmware is loaded directly into the buffer pointed to by @buf.
  *
  * Return: Size of total read, negative value when error.
  */
-int request_firmware_into_buf(struct device_platdata *plat,
+int request_firmware_into_buf(struct udevice *dev,
 			      const char *name,
-			      void *buf, size_t size, u32 offset,
-			      struct firmware **firmwarep);
+			      void *buf, size_t size, u32 offset);
 #endif
diff --git a/include/lmb.h b/include/lmb.h
index f04d058..1bb003e 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -28,9 +28,9 @@
 	struct lmb_region reserved;
 };
 
-extern struct lmb lmb;
-
 extern void lmb_init(struct lmb *lmb);
+extern void lmb_init_and_reserve(struct lmb *lmb, phys_addr_t base,
+				 phys_size_t size, void *fdt_blob);
 extern long lmb_add(struct lmb *lmb, phys_addr_t base, phys_size_t size);
 extern long lmb_reserve(struct lmb *lmb, phys_addr_t base, phys_size_t size);
 extern phys_addr_t lmb_alloc(struct lmb *lmb, phys_size_t size, ulong align);
@@ -38,6 +38,9 @@
 			    phys_addr_t max_addr);
 extern phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align,
 			      phys_addr_t max_addr);
+extern phys_addr_t lmb_alloc_addr(struct lmb *lmb, phys_addr_t base,
+				  phys_size_t size);
+extern phys_size_t lmb_get_unreserved_size(struct lmb *lmb, phys_addr_t addr);
 extern int lmb_is_reserved(struct lmb *lmb, phys_addr_t addr);
 extern long lmb_free(struct lmb *lmb, phys_addr_t base, phys_size_t size);
 
diff --git a/include/log.h b/include/log.h
index 0f2bc19..d7f6471 100644
--- a/include/log.h
+++ b/include/log.h
@@ -73,7 +73,8 @@
  * @return 0 if log record was emitted, -ve on error
  */
 int _log(enum log_category_t cat, enum log_level_t level, const char *file,
-	 int line, const char *func, const char *fmt, ...);
+	 int line, const char *func, const char *fmt, ...)
+		__attribute__ ((format (__printf__, 6, 7)));
 
 /* Define this at the top of a file to add a prefix to debug messages */
 #ifndef pr_fmt
diff --git a/include/regmap.h b/include/regmap.h
index a3afb72..8359c51 100644
--- a/include/regmap.h
+++ b/include/regmap.h
@@ -248,6 +248,8 @@
  * @cond:	Break condition (usually involving @val)
  * @sleep_us:	Maximum time to sleep between reads in us (0 tight-loops).
  * @timeout_ms:	Timeout in ms, 0 means never timeout
+ * @test_add_time: Used for sandbox testing - amount of time to add after
+ *		starting the loop (0 if not testing)
  *
  * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_read
  * error return value in case of a error read. In the two former cases,
@@ -256,8 +258,12 @@
  *
  * This is modelled after the regmap_read_poll_timeout macros in linux but
  * with millisecond timeout.
+ *
+ * The _test version is for sandbox testing only. Do not use this in normal
+ * code as it advances the timer.
  */
-#define regmap_read_poll_timeout(map, addr, val, cond, sleep_us, timeout_ms) \
+#define regmap_read_poll_timeout_test(map, addr, val, cond, sleep_us, \
+				      timeout_ms, test_add_time) \
 ({ \
 	unsigned long __start = get_timer(0); \
 	int __ret; \
@@ -267,6 +273,8 @@
 			break; \
 		if (cond) \
 			break; \
+		if (IS_ENABLED(CONFIG_SANDBOX) && test_add_time) \
+			sandbox_timer_add_offset(test_add_time); \
 		if ((timeout_ms) && get_timer(__start) > (timeout_ms)) { \
 			__ret = regmap_read((map), (addr), &(val)); \
 			break; \
@@ -277,6 +285,10 @@
 	__ret ?: ((cond) ? 0 : -ETIMEDOUT); \
 })
 
+#define regmap_read_poll_timeout(map, addr, val, cond, sleep_us, timeout_ms) \
+	regmap_read_poll_timeout_test(map, addr, val, cond, sleep_us, \
+				      timeout_ms, 0) \
+
 /**
  * regmap_update_bits() - Perform a read/modify/write using a mask
  *
diff --git a/include/serial.h b/include/serial.h
index c1a9fee..c1368c6 100644
--- a/include/serial.h
+++ b/include/serial.h
@@ -235,9 +235,7 @@
 	 * Get a current config for this device.
 	 *
 	 * @dev: Device pointer
-	 * @parity: parity to use
-	 * @bits: bits number to use
-	 * @stop: stop bits number to use
+	 * @serial_config: Returns config information (see SERIAL_... above)
 	 * @return 0 if OK, -ve on error
 	 */
 	int (*getconfig)(struct udevice *dev, uint *serial_config);
@@ -257,6 +255,7 @@
 	 *
 	 * @dev: Device pointer
 	 * @info: struct serial_device_info to fill
+	 * @return 0 if OK, -ve on error
 	 */
 	int (*getinfo)(struct udevice *dev, struct serial_device_info *info);
 };
@@ -281,6 +280,39 @@
 /* Access the serial operations for a device */
 #define serial_get_ops(dev)	((struct dm_serial_ops *)(dev)->driver->ops)
 
+/**
+ * serial_getconfig() - Get the uart configuration
+ * (parity, 5/6/7/8 bits word length, stop bits)
+ *
+ * Get a current config for this device.
+ *
+ * @dev: Device pointer
+ * @serial_config: Returns config information (see SERIAL_... above)
+ * @return 0 if OK, -ve on error
+ */
+int serial_getconfig(struct udevice *dev, uint *config);
+
+/**
+ * serial_setconfig() - Set up the uart configuration
+ * (parity, 5/6/7/8 bits word length, stop bits)
+ *
+ * Set up a new config for this device.
+ *
+ * @dev: Device pointer
+ * @serial_config: number of bits, parity and number of stopbits to use
+ * @return 0 if OK, -ve on error
+ */
+int serial_setconfig(struct udevice *dev, uint config);
+
+/**
+ * serial_getinfo() - Get serial device information
+ *
+ * @dev: Device pointer
+ * @info: struct serial_device_info to fill
+ * @return 0 if OK, -ve on error
+ */
+int serial_getinfo(struct udevice *dev, struct serial_device_info *info);
+
 void atmel_serial_initialize(void);
 void mcf_serial_initialize(void);
 void mpc85xx_serial_initialize(void);
diff --git a/lib/Kconfig b/lib/Kconfig
index 0333ab1..366d164 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -147,7 +147,7 @@
 	  The faster memset() is the arch-specific one (if available) enabled
 	  by CONFIG_USE_ARCH_MEMSET. If that is not enabled, we can still get
 	  better performance by writing a word at a time. But in very
-	  size-constrained envrionments even this may be too big. Enable this
+	  size-constrained environments even this may be too big. Enable this
 	  option to reduce code size slightly at the cost of some speed.
 
 config TPL_TINY_MEMSET
@@ -156,7 +156,7 @@
 	  The faster memset() is the arch-specific one (if available) enabled
 	  by CONFIG_USE_ARCH_MEMSET. If that is not enabled, we can still get
 	  better performance by writing a word at a time. But in very
-	  size-constrained envrionments even this may be too big. Enable this
+	  size-constrained environments even this may be too big. Enable this
 	  option to reduce code size slightly at the cost of some speed.
 
 config RBTREE
diff --git a/lib/Makefile b/lib/Makefile
index a6dd928..61d7ff0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -36,12 +36,10 @@
 obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o
 obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o
 obj-y += initcall.o
-obj-$(CONFIG_LMB) += lmb.o
 obj-y += ldiv.o
 obj-$(CONFIG_MD5) += md5.o
 obj-y += net_utils.o
 obj-$(CONFIG_PHYSMEM) += physmem.o
-obj-y += qsort.o
 obj-y += rc4.o
 obj-$(CONFIG_SUPPORT_EMMC_RPMB) += sha256.o
 obj-$(CONFIG_RBTREE)	+= rbtree.o
@@ -67,7 +65,6 @@
 
 obj-$(CONFIG_LIBAVB) += libavb/
 
-obj-$(CONFIG_$(SPL_TPL_)SAVEENV) += qsort.o
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/
 ifneq ($(CONFIG_$(SPL_TPL_)BUILD)$(CONFIG_$(SPL_TPL_)OF_PLATDATA),yy)
 obj-$(CONFIG_$(SPL_TPL_)OF_CONTROL) += fdtdec_common.o
@@ -80,6 +77,7 @@
 obj-$(CONFIG_SPL_NET_SUPPORT) += net_utils.o
 endif
 obj-$(CONFIG_ADDR_MAP) += addr_map.o
+obj-y += qsort.o
 obj-y += hashtable.o
 obj-y += errno.o
 obj-y += display_options.o
@@ -89,9 +87,11 @@
 obj-$(CONFIG_CRC32C) += crc32c.o
 obj-y += ctype.o
 obj-y += div64.o
+obj-$(CONFIG_OF_LIBFDT) += fdtdec.o
 obj-y += hang.o
 obj-y += linux_compat.o
 obj-y += linux_string.o
+obj-$(CONFIG_LMB) += lmb.o
 obj-y += membuff.o
 obj-$(CONFIG_REGEX) += slre.o
 obj-y += string.o
diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
index 128cb0a..8a4f3a9 100644
--- a/lib/efi_loader/efi_file.c
+++ b/lib/efi_loader/efi_file.c
@@ -221,8 +221,8 @@
 	struct file_handle *fh = to_fh(file);
 	efi_status_t ret;
 
-	EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", file, new_handle, file_name,
-		  open_mode, attributes);
+	EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", file, new_handle,
+		  (wchar_t *)file_name, open_mode, attributes);
 
 	/* Check parameters */
 	if (!file || !new_handle || !file_name) {
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 6f8ec0d..18663ce 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -95,16 +95,6 @@
 
 	debug("%s: %s: ", __func__, prop_name);
 
-	if (na > (sizeof(fdt_addr_t) / sizeof(fdt32_t))) {
-		debug("(na too large for fdt_addr_t type)\n");
-		return FDT_ADDR_T_NONE;
-	}
-
-	if (ns > (sizeof(fdt_size_t) / sizeof(fdt32_t))) {
-		debug("(ns too large for fdt_size_t type)\n");
-		return FDT_ADDR_T_NONE;
-	}
-
 	prop = fdt_getprop(blob, node, prop_name, &len);
 	if (!prop) {
 		debug("(not found)\n");
diff --git a/lib/lmb.c b/lib/lmb.c
index 1705417..3407705 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -43,7 +43,10 @@
 static long lmb_addrs_overlap(phys_addr_t base1,
 		phys_size_t size1, phys_addr_t base2, phys_size_t size2)
 {
-	return ((base1 < (base2+size2)) && (base2 < (base1+size1)));
+	const phys_addr_t base1_end = base1 + size1 - 1;
+	const phys_addr_t base2_end = base2 + size2 - 1;
+
+	return ((base1 <= base2_end) && (base2 <= base1_end));
 }
 
 static long lmb_addrs_adjacent(phys_addr_t base1, phys_size_t size1,
@@ -89,30 +92,35 @@
 
 void lmb_init(struct lmb *lmb)
 {
-	/* Create a dummy zero size LMB which will get coalesced away later.
-	 * This simplifies the lmb_add() code below...
-	 */
-	lmb->memory.region[0].base = 0;
-	lmb->memory.region[0].size = 0;
-	lmb->memory.cnt = 1;
+	lmb->memory.cnt = 0;
 	lmb->memory.size = 0;
-
-	/* Ditto. */
-	lmb->reserved.region[0].base = 0;
-	lmb->reserved.region[0].size = 0;
-	lmb->reserved.cnt = 1;
+	lmb->reserved.cnt = 0;
 	lmb->reserved.size = 0;
 }
 
+/* Initialize the struct, add memory and call arch/board reserve functions */
+void lmb_init_and_reserve(struct lmb *lmb, phys_addr_t base, phys_size_t size,
+			  void *fdt_blob)
+{
+	lmb_init(lmb);
+	lmb_add(lmb, base, size);
+	arch_lmb_reserve(lmb);
+	board_lmb_reserve(lmb);
+
+	if (IMAGE_ENABLE_OF_LIBFDT && fdt_blob)
+		boot_fdt_add_mem_rsv_regions(lmb, fdt_blob);
+}
+
 /* This routine called with relocation disabled. */
 static long lmb_add_region(struct lmb_region *rgn, phys_addr_t base, phys_size_t size)
 {
 	unsigned long coalesced = 0;
 	long adjacent, i;
 
-	if ((rgn->cnt == 1) && (rgn->region[0].size == 0)) {
+	if (rgn->cnt == 0) {
 		rgn->region[0].base = base;
 		rgn->region[0].size = size;
+		rgn->cnt = 1;
 		return 0;
 	}
 
@@ -136,6 +144,9 @@
 			rgn->region[i].size += size;
 			coalesced++;
 			break;
+		} else if (lmb_addrs_overlap(base, size, rgnbase, rgnsize)) {
+			/* regions overlap */
+			return -1;
 		}
 	}
 
@@ -183,7 +194,7 @@
 {
 	struct lmb_region *rgn = &(lmb->reserved);
 	phys_addr_t rgnbegin, rgnend;
-	phys_addr_t end = base + size;
+	phys_addr_t end = base + size - 1;
 	int i;
 
 	rgnbegin = rgnend = 0; /* supress gcc warnings */
@@ -191,7 +202,7 @@
 	/* Find the region where (base, size) belongs to */
 	for (i=0; i < rgn->cnt; i++) {
 		rgnbegin = rgn->region[i].base;
-		rgnend = rgnbegin + rgn->region[i].size;
+		rgnend = rgnbegin + rgn->region[i].size - 1;
 
 		if ((rgnbegin <= base) && (end <= rgnend))
 			break;
@@ -209,7 +220,7 @@
 
 	/* Check to see if region is matching at the front */
 	if (rgnbegin == base) {
-		rgn->region[i].base = end;
+		rgn->region[i].base = end + 1;
 		rgn->region[i].size -= size;
 		return 0;
 	}
@@ -225,7 +236,7 @@
 	 * beginging of the hole and add the region after hole.
 	 */
 	rgn->region[i].size = base - rgn->region[i].base;
-	return lmb_add_region(rgn, end, rgnend - end);
+	return lmb_add_region(rgn, end + 1, rgnend - end);
 }
 
 long lmb_reserve(struct lmb *lmb, phys_addr_t base, phys_size_t size)
@@ -274,11 +285,6 @@
 	return addr & ~(size - 1);
 }
 
-static phys_addr_t lmb_align_up(phys_addr_t addr, ulong size)
-{
-	return (addr + (size - 1)) & ~(size - 1);
-}
-
 phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phys_addr_t max_addr)
 {
 	long i, j;
@@ -307,8 +313,7 @@
 			if (j < 0) {
 				/* This area isn't reserved, take it */
 				if (lmb_add_region(&lmb->reserved, base,
-							lmb_align_up(size,
-								align)) < 0)
+						   size) < 0)
 					return 0;
 				return base;
 			}
@@ -317,6 +322,59 @@
 				break;
 			base = lmb_align_down(res_base - size, align);
 		}
+	}
+	return 0;
+}
+
+/*
+ * Try to allocate a specific address range: must be in defined memory but not
+ * reserved
+ */
+phys_addr_t lmb_alloc_addr(struct lmb *lmb, phys_addr_t base, phys_size_t size)
+{
+	long j;
+
+	/* Check if the requested address is in one of the memory regions */
+	j = lmb_overlaps_region(&lmb->memory, base, size);
+	if (j >= 0) {
+		/*
+		 * Check if the requested end address is in the same memory
+		 * region we found.
+		 */
+		if (lmb_addrs_overlap(lmb->memory.region[j].base,
+				      lmb->memory.region[j].size, base + size -
+				      1, 1)) {
+			/* ok, reserve the memory */
+			if (lmb_reserve(lmb, base, size) >= 0)
+				return base;
+		}
+	}
+	return 0;
+}
+
+/* Return number of bytes from a given address that are free */
+phys_size_t lmb_get_unreserved_size(struct lmb *lmb, phys_addr_t addr)
+{
+	int i;
+	long j;
+
+	/* check if the requested address is in the memory regions */
+	j = lmb_overlaps_region(&lmb->memory, addr, 1);
+	if (j >= 0) {
+		for (i = 0; i < lmb->reserved.cnt; i++) {
+			if (addr < lmb->reserved.region[i].base) {
+				/* first reserved range > requested address */
+				return lmb->reserved.region[i].base - addr;
+			}
+			if (lmb->reserved.region[i].base +
+			    lmb->reserved.region[i].size > addr) {
+				/* requested addr is in this reserved range */
+				return 0;
+			}
+		}
+		/* if we come here: no reserved ranges above requested addr */
+		return lmb->memory.region[lmb->memory.cnt - 1].base +
+		       lmb->memory.region[lmb->memory.cnt - 1].size - addr;
 	}
 	return 0;
 }
diff --git a/lib/uuid.c b/lib/uuid.c
index 5d5adf6..fa20ee3 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -271,7 +271,7 @@
 	uuid_bin_to_str(uuid_bin, uuid_str, str_format);
 }
 
-#ifdef CONFIG_CMD_UUID
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CMD_UUID)
 int do_uuid(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	char uuid[UUID_STR_LEN + 1];
diff --git a/net/tftp.c b/net/tftp.c
index 68ffd81..a9335b1b7 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -17,6 +17,8 @@
 #include <flash.h>
 #endif
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /* Well known TFTP port # */
 #define WELL_KNOWN_PORT	69
 /* Millisecs to timeout for lost pkt */
@@ -81,6 +83,10 @@
 /* memory offset due to wrapping */
 static ulong	tftp_block_wrap_offset;
 static int	tftp_state;
+static ulong	tftp_load_addr;
+#ifdef CONFIG_LMB
+static ulong	tftp_load_size;
+#endif
 #ifdef CONFIG_TFTP_TSIZE
 /* The file size reported by the server */
 static int	tftp_tsize;
@@ -164,10 +170,11 @@
 
 #endif	/* CONFIG_MCAST_TFTP */
 
-static inline void store_block(int block, uchar *src, unsigned len)
+static inline int store_block(int block, uchar *src, unsigned int len)
 {
 	ulong offset = block * tftp_block_size + tftp_block_wrap_offset;
 	ulong newsize = offset + len;
+	ulong store_addr = tftp_load_addr + offset;
 #ifdef CONFIG_SYS_DIRECT_FLASH_TFTP
 	int i, rc = 0;
 
@@ -175,24 +182,32 @@
 		/* start address in flash? */
 		if (flash_info[i].flash_id == FLASH_UNKNOWN)
 			continue;
-		if (load_addr + offset >= flash_info[i].start[0]) {
+		if (store_addr >= flash_info[i].start[0]) {
 			rc = 1;
 			break;
 		}
 	}
 
 	if (rc) { /* Flash is destination for this packet */
-		rc = flash_write((char *)src, (ulong)(load_addr+offset), len);
+		rc = flash_write((char *)src, store_addr, len);
 		if (rc) {
 			flash_perror(rc);
-			net_set_state(NETLOOP_FAIL);
-			return;
+			return rc;
 		}
 	} else
 #endif /* CONFIG_SYS_DIRECT_FLASH_TFTP */
 	{
-		void *ptr = map_sysmem(load_addr + offset, len);
+		void *ptr;
 
+#ifdef CONFIG_LMB
+		if (store_addr < tftp_load_addr ||
+		    store_addr + len > tftp_load_addr + tftp_load_size) {
+			puts("\nTFTP error: ");
+			puts("trying to overwrite reserved memory...\n");
+			return -1;
+		}
+#endif
+		ptr = map_sysmem(store_addr, len);
 		memcpy(ptr, src, len);
 		unmap_sysmem(ptr);
 	}
@@ -203,6 +218,8 @@
 
 	if (net_boot_file_size < newsize)
 		net_boot_file_size = newsize;
+
+	return 0;
 }
 
 /* Clear our state ready for a new transfer */
@@ -606,7 +623,11 @@
 		timeout_count_max = tftp_timeout_count_max;
 		net_set_timeout_handler(timeout_ms, tftp_timeout_handler);
 
-		store_block(tftp_cur_block - 1, pkt + 2, len);
+		if (store_block(tftp_cur_block - 1, pkt + 2, len)) {
+			eth_halt();
+			net_set_state(NETLOOP_FAIL);
+			break;
+		}
 
 		/*
 		 *	Acknowledge the block just received, which will prompt
@@ -695,6 +716,25 @@
 	}
 }
 
+/* Initialize tftp_load_addr and tftp_load_size from load_addr and lmb */
+static int tftp_init_load_addr(void)
+{
+#ifdef CONFIG_LMB
+	struct lmb lmb;
+	phys_size_t max_size;
+
+	lmb_init_and_reserve(&lmb, gd->bd->bi_dram[0].start,
+			     gd->bd->bi_dram[0].size, (void *)gd->fdt_blob);
+
+	max_size = lmb_get_unreserved_size(&lmb, load_addr);
+	if (!max_size)
+		return -1;
+
+	tftp_load_size = max_size;
+#endif
+	tftp_load_addr = load_addr;
+	return 0;
+}
 
 void tftp_start(enum proto_t protocol)
 {
@@ -791,7 +831,14 @@
 	} else
 #endif
 	{
-		printf("Load address: 0x%lx\n", load_addr);
+		if (tftp_init_load_addr()) {
+			eth_halt();
+			net_set_state(NETLOOP_FAIL);
+			puts("\nTFTP error: ");
+			puts("trying to overwrite reserved memory...\n");
+			return;
+		}
+		printf("Load address: 0x%lx\n", tftp_load_addr);
 		puts("Loading: *\b");
 		tftp_state = STATE_SEND_RRQ;
 #ifdef CONFIG_CMD_BOOTEFI
@@ -842,9 +889,15 @@
 {
 	tftp_filename[0] = 0;
 
+	if (tftp_init_load_addr()) {
+		eth_halt();
+		net_set_state(NETLOOP_FAIL);
+		puts("\nTFTP error: trying to overwrite reserved memory...\n");
+		return;
+	}
 	printf("Using %s device\n", eth_get_name());
 	printf("Listening for TFTP transfer on %pI4\n", &net_ip);
-	printf("Load address: 0x%lx\n", load_addr);
+	printf("Load address: 0x%lx\n", tftp_load_addr);
 
 	puts("Loading: *\b");
 
diff --git a/post/lib_powerpc/fpu/Makefile b/post/lib_powerpc/fpu/Makefile
index 404eefc..9b2c1fa 100644
--- a/post/lib_powerpc/fpu/Makefile
+++ b/post/lib_powerpc/fpu/Makefile
@@ -11,9 +11,6 @@
 $(foreach m, $(objs-before-objcopy), $(eval CFLAGS_REMOVE_$m := -msoft-float))
 ccflags-y := -mhard-float -fkeep-inline-functions
 
-# Do not delete intermidiate files (*.o)
-.SECONDARY: $(call objectify, $(objs-before-objcopy))
-
 obj-y := $(objs-before-objcopy:.o=_.o)
 
 OBJCOPYFLAGS := -R .gnu.attributes
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 13ebddd..b8969e2 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -315,6 +315,12 @@
 echo-why = $(call escsq, $(strip $(why)))
 endif
 
+# delete partially updated (i.e. corrupted) files on error
+.DELETE_ON_ERROR:
+
+# do not delete intermediate files automatically
+.SECONDARY:
+
 ifdef CONFIG_SPL_BUILD
 SPL_ := SPL_
 ifeq ($(CONFIG_TPL_BUILD),y)
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 482ed0c..f7a0412 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -331,8 +331,6 @@
       cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \
 				$(subst .h,.c,$@) $(subst .c,.h,$@)
 
-.PRECIOUS: $(objtree)/$(obj)/%-asn1.c $(objtree)/$(obj)/%-asn1.h
-
 $(obj)/%-asn1.c $(obj)/%-asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
 	$(call cmd,asn1_compiler)
 
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index a4f16bb..a5b57fc 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -214,7 +214,6 @@
 quiet_cmd_flex = LEX     $@
       cmd_flex = $(LEX) -o$@ -L $<
 
-.PRECIOUS: $(obj)/%.lex.c
 $(obj)/%.lex.c: $(src)/%.l FORCE
 	$(call if_changed,flex)
 
@@ -223,14 +222,12 @@
 quiet_cmd_bison = YACC    $@
       cmd_bison = $(YACC) -o$@ -t -l $<
 
-.PRECIOUS: $(obj)/%.tab.c
 $(obj)/%.tab.c: $(src)/%.y FORCE
 	$(call if_changed,bison)
 
 quiet_cmd_bison_h = YACC    $@
       cmd_bison_h = $(YACC) -o/dev/null --defines=$@ -t -l $<
 
-.PRECIOUS: $(obj)/%.tab.h
 $(obj)/%.tab.h: $(src)/%.y FORCE
 	$(call if_changed,bison_h)
 
diff --git a/scripts/dtc/pylibfdt/Makefile b/scripts/dtc/pylibfdt/Makefile
index c769d7d..15e66ad 100644
--- a/scripts/dtc/pylibfdt/Makefile
+++ b/scripts/dtc/pylibfdt/Makefile
@@ -21,7 +21,7 @@
 		CPPFLAGS="$(HOSTCFLAGS) -I$(LIBFDT_srcdir)" OBJDIR=$(obj) \
 		SOURCES="$(PYLIBFDT_srcs)" \
 		SWIG_OPTS="-I$(LIBFDT_srcdir) -I$(LIBFDT_srcdir)/.." \
-		$(PYTHON) $< --quiet build_ext --inplace
+		$(PYTHON2) $< --quiet build_ext --inplace
 
 $(obj)/_libfdt.so: $(src)/setup.py $(PYLIBFDT_srcs) FORCE
 	$(call if_changed,pymod)
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 7dc80be..1b08996 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -15,6 +15,7 @@
 obj-$(CONFIG_SOUND) += audio.o
 obj-$(CONFIG_BLK) += blk.o
 obj-$(CONFIG_BOARD) += board.o
+obj-$(CONFIG_DM_BOOTCOUNT) += bootcount.o
 obj-$(CONFIG_CLK) += clk.o
 obj-$(CONFIG_DM_ETH) += eth.o
 obj-$(CONFIG_FIRMWARE) += firmware.o
diff --git a/test/dm/bootcount.c b/test/dm/bootcount.c
new file mode 100644
index 0000000..0817b7d
--- /dev/null
+++ b/test/dm/bootcount.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) 2018 Theobroma Systems Design und Consulting GmbH
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <bootcount.h>
+#include <asm/test.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+static int dm_test_bootcount(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	u32 val;
+
+	ut_assertok(uclass_get_device(UCLASS_BOOTCOUNT, 0, &dev));
+	ut_assertok(dm_bootcount_set(dev, 0));
+	ut_assertok(dm_bootcount_get(dev, &val));
+	ut_assert(val == 0);
+	ut_assertok(dm_bootcount_set(dev, 0xab));
+	ut_assertok(dm_bootcount_get(dev, &val));
+	ut_assert(val == 0xab);
+
+	return 0;
+}
+
+DM_TEST(dm_test_bootcount, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
diff --git a/test/dm/regmap.c b/test/dm/regmap.c
index 9a70c15..82de295 100644
--- a/test/dm/regmap.c
+++ b/test/dm/regmap.c
@@ -160,9 +160,10 @@
 	start = get_timer(0);
 
 	ut_asserteq(-ETIMEDOUT,
-		    regmap_read_poll_timeout(map, 0, reg,
-					     (reg == 0xcacafafa),
-					     1, 5 * CONFIG_SYS_HZ));
+		    regmap_read_poll_timeout_test(map, 0, reg,
+						  (reg == 0xcacafafa),
+						  1, 5 * CONFIG_SYS_HZ,
+						  5 * CONFIG_SYS_HZ));
 
 	ut_assert(get_timer(start) > (5 * CONFIG_SYS_HZ));
 
diff --git a/test/dm/serial.c b/test/dm/serial.c
index 19a15d5..3d741a8 100644
--- a/test/dm/serial.c
+++ b/test/dm/serial.c
@@ -23,23 +23,24 @@
 	 * test with default config which is the only one supported by
 	 * sandbox_serial driver
 	 */
-	ut_assertok(serial_setconfig(SERIAL_DEFAULT_CONFIG));
-	ut_assertok(serial_getconfig(&value_serial));
+	ut_assertok(serial_setconfig(dev_serial, SERIAL_DEFAULT_CONFIG));
+	ut_assertok(serial_getconfig(dev_serial, &value_serial));
 	ut_assert(value_serial == SERIAL_DEFAULT_CONFIG);
-	ut_assertok(serial_getinfo(&info_serial));
+	ut_assertok(serial_getinfo(dev_serial, &info_serial));
 	ut_assert(info_serial.type == SERIAL_CHIP_UNKNOWN);
 	ut_assert(info_serial.addr == SERIAL_DEFAULT_ADDRESS);
 	/*
 	 * test with a parameter which is NULL pointer
 	 */
-	ut_asserteq(-EINVAL, serial_getconfig(NULL));
-	ut_asserteq(-EINVAL, serial_getinfo(NULL));
+	ut_asserteq(-EINVAL, serial_getconfig(dev_serial, NULL));
+	ut_asserteq(-EINVAL, serial_getinfo(dev_serial, NULL));
 	/*
 	 * test with a serial config which is not supported by
 	 * sandbox_serial driver: test with wrong parity
 	 */
 	ut_asserteq(-ENOTSUPP,
-		    serial_setconfig(SERIAL_CONFIG(SERIAL_PAR_ODD,
+		    serial_setconfig(dev_serial,
+				     SERIAL_CONFIG(SERIAL_PAR_ODD,
 						   SERIAL_8_BITS,
 						   SERIAL_ONE_STOP)));
 	/*
@@ -47,7 +48,8 @@
 	 * sandbox_serial driver: test with wrong bits number
 	 */
 	ut_asserteq(-ENOTSUPP,
-		    serial_setconfig(SERIAL_CONFIG(SERIAL_PAR_NONE,
+		    serial_setconfig(dev_serial,
+				     SERIAL_CONFIG(SERIAL_PAR_NONE,
 						   SERIAL_6_BITS,
 						   SERIAL_ONE_STOP)));
 
@@ -56,7 +58,8 @@
 	 * sandbox_serial driver: test with wrong stop bits number
 	 */
 	ut_asserteq(-ENOTSUPP,
-		    serial_setconfig(SERIAL_CONFIG(SERIAL_PAR_NONE,
+		    serial_setconfig(dev_serial,
+				     SERIAL_CONFIG(SERIAL_PAR_NONE,
 						   SERIAL_8_BITS,
 						   SERIAL_TWO_STOP)));
 
diff --git a/test/lib/Makefile b/test/lib/Makefile
index ea68fae..5a636aa 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -3,3 +3,4 @@
 # (C) Copyright 2018
 # Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
 obj-y += hexdump.o
+obj-y += lmb.o
diff --git a/test/lib/lmb.c b/test/lib/lmb.c
new file mode 100644
index 0000000..058d3c3
--- /dev/null
+++ b/test/lib/lmb.c
@@ -0,0 +1,601 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018 Simon Goldschmidt
+ */
+
+#include <common.h>
+#include <lmb.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+static int check_lmb(struct unit_test_state *uts, struct lmb *lmb,
+		     phys_addr_t ram_base, phys_size_t ram_size,
+		     unsigned long num_reserved,
+		     phys_addr_t base1, phys_size_t size1,
+		     phys_addr_t base2, phys_size_t size2,
+		     phys_addr_t base3, phys_size_t size3)
+{
+	ut_asserteq(lmb->memory.cnt, 1);
+	ut_asserteq(lmb->memory.region[0].base, ram_base);
+	ut_asserteq(lmb->memory.region[0].size, ram_size);
+
+	ut_asserteq(lmb->reserved.cnt, num_reserved);
+	if (num_reserved > 0) {
+		ut_asserteq(lmb->reserved.region[0].base, base1);
+		ut_asserteq(lmb->reserved.region[0].size, size1);
+	}
+	if (num_reserved > 1) {
+		ut_asserteq(lmb->reserved.region[1].base, base2);
+		ut_asserteq(lmb->reserved.region[1].size, size2);
+	}
+	if (num_reserved > 2) {
+		ut_asserteq(lmb->reserved.region[2].base, base3);
+		ut_asserteq(lmb->reserved.region[2].size, size3);
+	}
+	return 0;
+}
+
+#define ASSERT_LMB(lmb, ram_base, ram_size, num_reserved, base1, size1, \
+		   base2, size2, base3, size3) \
+		   ut_assert(!check_lmb(uts, lmb, ram_base, ram_size, \
+			     num_reserved, base1, size1, base2, size2, base3, \
+			     size3))
+
+/*
+ * Test helper function that reserves 64 KiB somewhere in the simulated RAM and
+ * then does some alloc + free tests.
+ */
+static int test_multi_alloc(struct unit_test_state *uts,
+			    const phys_addr_t ram, const phys_size_t ram_size,
+			    const phys_addr_t alloc_64k_addr)
+{
+	const phys_addr_t ram_end = ram + ram_size;
+	const phys_addr_t alloc_64k_end = alloc_64k_addr + 0x10000;
+
+	struct lmb lmb;
+	long ret;
+	phys_addr_t a, a2, b, b2, c, d;
+
+	/* check for overflow */
+	ut_assert(ram_end == 0 || ram_end > ram);
+	ut_assert(alloc_64k_end > alloc_64k_addr);
+	/* check input addresses + size */
+	ut_assert(alloc_64k_addr >= ram + 8);
+	ut_assert(alloc_64k_end <= ram_end - 8);
+
+	lmb_init(&lmb);
+
+	ret = lmb_add(&lmb, ram, ram_size);
+	ut_asserteq(ret, 0);
+
+	/* reserve 64KiB somewhere */
+	ret = lmb_reserve(&lmb, alloc_64k_addr, 0x10000);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
+		   0, 0, 0, 0);
+
+	/* allocate somewhere, should be at the end of RAM */
+	a = lmb_alloc(&lmb, 4, 1);
+	ut_asserteq(a, ram_end - 4);
+	ASSERT_LMB(&lmb, ram, ram_size, 2, alloc_64k_addr, 0x10000,
+		   ram_end - 4, 4, 0, 0);
+	/* alloc below end of reserved region -> below reserved region */
+	b = lmb_alloc_base(&lmb, 4, 1, alloc_64k_end);
+	ut_asserteq(b, alloc_64k_addr - 4);
+	ASSERT_LMB(&lmb, ram, ram_size, 2,
+		   alloc_64k_addr - 4, 0x10000 + 4, ram_end - 4, 4, 0, 0);
+
+	/* 2nd time */
+	c = lmb_alloc(&lmb, 4, 1);
+	ut_asserteq(c, ram_end - 8);
+	ASSERT_LMB(&lmb, ram, ram_size, 2,
+		   alloc_64k_addr - 4, 0x10000 + 4, ram_end - 8, 8, 0, 0);
+	d = lmb_alloc_base(&lmb, 4, 1, alloc_64k_end);
+	ut_asserteq(d, alloc_64k_addr - 8);
+	ASSERT_LMB(&lmb, ram, ram_size, 2,
+		   alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 8, 0, 0);
+
+	ret = lmb_free(&lmb, a, 4);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 2,
+		   alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 4, 0, 0);
+	/* allocate again to ensure we get the same address */
+	a2 = lmb_alloc(&lmb, 4, 1);
+	ut_asserteq(a, a2);
+	ASSERT_LMB(&lmb, ram, ram_size, 2,
+		   alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 8, 0, 0);
+	ret = lmb_free(&lmb, a2, 4);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 2,
+		   alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 4, 0, 0);
+
+	ret = lmb_free(&lmb, b, 4);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 3,
+		   alloc_64k_addr - 8, 4, alloc_64k_addr, 0x10000,
+		   ram_end - 8, 4);
+	/* allocate again to ensure we get the same address */
+	b2 = lmb_alloc_base(&lmb, 4, 1, alloc_64k_end);
+	ut_asserteq(b, b2);
+	ASSERT_LMB(&lmb, ram, ram_size, 2,
+		   alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 4, 0, 0);
+	ret = lmb_free(&lmb, b2, 4);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 3,
+		   alloc_64k_addr - 8, 4, alloc_64k_addr, 0x10000,
+		   ram_end - 8, 4);
+
+	ret = lmb_free(&lmb, c, 4);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 2,
+		   alloc_64k_addr - 8, 4, alloc_64k_addr, 0x10000, 0, 0);
+	ret = lmb_free(&lmb, d, 4);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
+		   0, 0, 0, 0);
+
+	return 0;
+}
+
+static int test_multi_alloc_512mb(struct unit_test_state *uts,
+				  const phys_addr_t ram)
+{
+	return test_multi_alloc(uts, ram, 0x20000000, ram + 0x10000000);
+}
+
+/* Create a memory region with one reserved region and allocate */
+static int lib_test_lmb_simple(struct unit_test_state *uts)
+{
+	int ret;
+
+	/* simulate 512 MiB RAM beginning at 1GiB */
+	ret = test_multi_alloc_512mb(uts, 0x40000000);
+	if (ret)
+		return ret;
+
+	/* simulate 512 MiB RAM beginning at 1.5GiB */
+	return test_multi_alloc_512mb(uts, 0xE0000000);
+}
+
+DM_TEST(lib_test_lmb_simple, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Simulate 512 MiB RAM, allocate some blocks that fit/don't fit */
+static int test_bigblock(struct unit_test_state *uts, const phys_addr_t ram)
+{
+	const phys_size_t ram_size = 0x20000000;
+	const phys_size_t big_block_size = 0x10000000;
+	const phys_addr_t ram_end = ram + ram_size;
+	const phys_addr_t alloc_64k_addr = ram + 0x10000000;
+	struct lmb lmb;
+	long ret;
+	phys_addr_t a, b;
+
+	/* check for overflow */
+	ut_assert(ram_end == 0 || ram_end > ram);
+
+	lmb_init(&lmb);
+
+	ret = lmb_add(&lmb, ram, ram_size);
+	ut_asserteq(ret, 0);
+
+	/* reserve 64KiB in the middle of RAM */
+	ret = lmb_reserve(&lmb, alloc_64k_addr, 0x10000);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
+		   0, 0, 0, 0);
+
+	/* allocate a big block, should be below reserved */
+	a = lmb_alloc(&lmb, big_block_size, 1);
+	ut_asserteq(a, ram);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, a,
+		   big_block_size + 0x10000, 0, 0, 0, 0);
+	/* allocate 2nd big block */
+	/* This should fail, printing an error */
+	b = lmb_alloc(&lmb, big_block_size, 1);
+	ut_asserteq(b, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, a,
+		   big_block_size + 0x10000, 0, 0, 0, 0);
+
+	ret = lmb_free(&lmb, a, big_block_size);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
+		   0, 0, 0, 0);
+
+	/* allocate too big block */
+	/* This should fail, printing an error */
+	a = lmb_alloc(&lmb, ram_size, 1);
+	ut_asserteq(a, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
+		   0, 0, 0, 0);
+
+	return 0;
+}
+
+static int lib_test_lmb_big(struct unit_test_state *uts)
+{
+	int ret;
+
+	/* simulate 512 MiB RAM beginning at 1GiB */
+	ret = test_bigblock(uts, 0x40000000);
+	if (ret)
+		return ret;
+
+	/* simulate 512 MiB RAM beginning at 1.5GiB */
+	return test_bigblock(uts, 0xE0000000);
+}
+
+DM_TEST(lib_test_lmb_big, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Simulate 512 MiB RAM, allocate a block without previous reservation */
+static int test_noreserved(struct unit_test_state *uts, const phys_addr_t ram,
+			   const phys_addr_t alloc_size, const ulong align)
+{
+	const phys_size_t ram_size = 0x20000000;
+	const phys_addr_t ram_end = ram + ram_size;
+	struct lmb lmb;
+	long ret;
+	phys_addr_t a, b;
+	const phys_addr_t alloc_size_aligned = (alloc_size + align - 1) &
+		~(align - 1);
+
+	/* check for overflow */
+	ut_assert(ram_end == 0 || ram_end > ram);
+
+	lmb_init(&lmb);
+
+	ret = lmb_add(&lmb, ram, ram_size);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0);
+
+	/* allocate a block */
+	a = lmb_alloc(&lmb, alloc_size, align);
+	ut_assert(a != 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, ram + ram_size - alloc_size_aligned,
+		   alloc_size, 0, 0, 0, 0);
+	/* allocate another block */
+	b = lmb_alloc(&lmb, alloc_size, align);
+	ut_assert(b != 0);
+	if (alloc_size == alloc_size_aligned) {
+		ASSERT_LMB(&lmb, ram, ram_size, 1, ram + ram_size -
+			   (alloc_size_aligned * 2), alloc_size * 2, 0, 0, 0,
+			   0);
+	} else {
+		ASSERT_LMB(&lmb, ram, ram_size, 2, ram + ram_size -
+			   (alloc_size_aligned * 2), alloc_size, ram + ram_size
+			   - alloc_size_aligned, alloc_size, 0, 0);
+	}
+	/* and free them */
+	ret = lmb_free(&lmb, b, alloc_size);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, ram + ram_size - alloc_size_aligned,
+		   alloc_size, 0, 0, 0, 0);
+	ret = lmb_free(&lmb, a, alloc_size);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0);
+
+	/* allocate a block with base*/
+	b = lmb_alloc_base(&lmb, alloc_size, align, ram_end);
+	ut_assert(a == b);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, ram + ram_size - alloc_size_aligned,
+		   alloc_size, 0, 0, 0, 0);
+	/* and free it */
+	ret = lmb_free(&lmb, b, alloc_size);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0);
+
+	return 0;
+}
+
+static int lib_test_lmb_noreserved(struct unit_test_state *uts)
+{
+	int ret;
+
+	/* simulate 512 MiB RAM beginning at 1GiB */
+	ret = test_noreserved(uts, 0x40000000, 4, 1);
+	if (ret)
+		return ret;
+
+	/* simulate 512 MiB RAM beginning at 1.5GiB */
+	return test_noreserved(uts, 0xE0000000, 4, 1);
+}
+
+DM_TEST(lib_test_lmb_noreserved, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+static int lib_test_lmb_unaligned_size(struct unit_test_state *uts)
+{
+	int ret;
+
+	/* simulate 512 MiB RAM beginning at 1GiB */
+	ret = test_noreserved(uts, 0x40000000, 5, 8);
+	if (ret)
+		return ret;
+
+	/* simulate 512 MiB RAM beginning at 1.5GiB */
+	return test_noreserved(uts, 0xE0000000, 5, 8);
+}
+
+DM_TEST(lib_test_lmb_unaligned_size, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+/*
+ * Simulate a RAM that starts at 0 and allocate down to address 0, which must
+ * fail as '0' means failure for the lmb_alloc functions.
+ */
+static int lib_test_lmb_at_0(struct unit_test_state *uts)
+{
+	const phys_addr_t ram = 0;
+	const phys_size_t ram_size = 0x20000000;
+	struct lmb lmb;
+	long ret;
+	phys_addr_t a, b;
+
+	lmb_init(&lmb);
+
+	ret = lmb_add(&lmb, ram, ram_size);
+	ut_asserteq(ret, 0);
+
+	/* allocate nearly everything */
+	a = lmb_alloc(&lmb, ram_size - 4, 1);
+	ut_asserteq(a, ram + 4);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, a, ram_size - 4,
+		   0, 0, 0, 0);
+	/* allocate the rest */
+	/* This should fail as the allocated address would be 0 */
+	b = lmb_alloc(&lmb, 4, 1);
+	ut_asserteq(b, 0);
+	/* check that this was an error by checking lmb */
+	ASSERT_LMB(&lmb, ram, ram_size, 1, a, ram_size - 4,
+		   0, 0, 0, 0);
+	/* check that this was an error by freeing b */
+	ret = lmb_free(&lmb, b, 4);
+	ut_asserteq(ret, -1);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, a, ram_size - 4,
+		   0, 0, 0, 0);
+
+	ret = lmb_free(&lmb, a, ram_size - 4);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0);
+
+	return 0;
+}
+
+DM_TEST(lib_test_lmb_at_0, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Check that calling lmb_reserve with overlapping regions fails. */
+static int lib_test_lmb_overlapping_reserve(struct unit_test_state *uts)
+{
+	const phys_addr_t ram = 0x40000000;
+	const phys_size_t ram_size = 0x20000000;
+	struct lmb lmb;
+	long ret;
+
+	lmb_init(&lmb);
+
+	ret = lmb_add(&lmb, ram, ram_size);
+	ut_asserteq(ret, 0);
+
+	ret = lmb_reserve(&lmb, 0x40010000, 0x10000);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, 0x40010000, 0x10000,
+		   0, 0, 0, 0);
+	/* allocate overlapping region should fail */
+	ret = lmb_reserve(&lmb, 0x40011000, 0x10000);
+	ut_asserteq(ret, -1);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, 0x40010000, 0x10000,
+		   0, 0, 0, 0);
+	/* allocate 3nd region */
+	ret = lmb_reserve(&lmb, 0x40030000, 0x10000);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 2, 0x40010000, 0x10000,
+		   0x40030000, 0x10000, 0, 0);
+	/* allocate 2nd region */
+	ret = lmb_reserve(&lmb, 0x40020000, 0x10000);
+	ut_assert(ret >= 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, 0x40010000, 0x30000,
+		   0, 0, 0, 0);
+
+	return 0;
+}
+
+DM_TEST(lib_test_lmb_overlapping_reserve,
+	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/*
+ * Simulate 512 MiB RAM, reserve 3 blocks, allocate addresses in between.
+ * Expect addresses outside the memory range to fail.
+ */
+static int test_alloc_addr(struct unit_test_state *uts, const phys_addr_t ram)
+{
+	const phys_size_t ram_size = 0x20000000;
+	const phys_addr_t ram_end = ram + ram_size;
+	const phys_size_t alloc_addr_a = ram + 0x8000000;
+	const phys_size_t alloc_addr_b = ram + 0x8000000 * 2;
+	const phys_size_t alloc_addr_c = ram + 0x8000000 * 3;
+	struct lmb lmb;
+	long ret;
+	phys_addr_t a, b, c, d, e;
+
+	/* check for overflow */
+	ut_assert(ram_end == 0 || ram_end > ram);
+
+	lmb_init(&lmb);
+
+	ret = lmb_add(&lmb, ram, ram_size);
+	ut_asserteq(ret, 0);
+
+	/*  reserve 3 blocks */
+	ret = lmb_reserve(&lmb, alloc_addr_a, 0x10000);
+	ut_asserteq(ret, 0);
+	ret = lmb_reserve(&lmb, alloc_addr_b, 0x10000);
+	ut_asserteq(ret, 0);
+	ret = lmb_reserve(&lmb, alloc_addr_c, 0x10000);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 3, alloc_addr_a, 0x10000,
+		   alloc_addr_b, 0x10000, alloc_addr_c, 0x10000);
+
+	/* allocate blocks */
+	a = lmb_alloc_addr(&lmb, ram, alloc_addr_a - ram);
+	ut_asserteq(a, ram);
+	ASSERT_LMB(&lmb, ram, ram_size, 3, ram, 0x8010000,
+		   alloc_addr_b, 0x10000, alloc_addr_c, 0x10000);
+	b = lmb_alloc_addr(&lmb, alloc_addr_a + 0x10000,
+			   alloc_addr_b - alloc_addr_a - 0x10000);
+	ut_asserteq(b, alloc_addr_a + 0x10000);
+	ASSERT_LMB(&lmb, ram, ram_size, 2, ram, 0x10010000,
+		   alloc_addr_c, 0x10000, 0, 0);
+	c = lmb_alloc_addr(&lmb, alloc_addr_b + 0x10000,
+			   alloc_addr_c - alloc_addr_b - 0x10000);
+	ut_asserteq(c, alloc_addr_b + 0x10000);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000,
+		   0, 0, 0, 0);
+	d = lmb_alloc_addr(&lmb, alloc_addr_c + 0x10000,
+			   ram_end - alloc_addr_c - 0x10000);
+	ut_asserteq(d, alloc_addr_c + 0x10000);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, ram, ram_size,
+		   0, 0, 0, 0);
+
+	/* allocating anything else should fail */
+	e = lmb_alloc(&lmb, 1, 1);
+	ut_asserteq(e, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, ram, ram_size,
+		   0, 0, 0, 0);
+
+	ret = lmb_free(&lmb, d, ram_end - alloc_addr_c - 0x10000);
+	ut_asserteq(ret, 0);
+
+	/* allocate at 3 points in free range */
+
+	d = lmb_alloc_addr(&lmb, ram_end - 4, 4);
+	ut_asserteq(d, ram_end - 4);
+	ASSERT_LMB(&lmb, ram, ram_size, 2, ram, 0x18010000,
+		   d, 4, 0, 0);
+	ret = lmb_free(&lmb, d, 4);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000,
+		   0, 0, 0, 0);
+
+	d = lmb_alloc_addr(&lmb, ram_end - 128, 4);
+	ut_asserteq(d, ram_end - 128);
+	ASSERT_LMB(&lmb, ram, ram_size, 2, ram, 0x18010000,
+		   d, 4, 0, 0);
+	ret = lmb_free(&lmb, d, 4);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000,
+		   0, 0, 0, 0);
+
+	d = lmb_alloc_addr(&lmb, alloc_addr_c + 0x10000, 4);
+	ut_asserteq(d, alloc_addr_c + 0x10000);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010004,
+		   0, 0, 0, 0);
+	ret = lmb_free(&lmb, d, 4);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000,
+		   0, 0, 0, 0);
+
+	/* allocate at the bottom */
+	ret = lmb_free(&lmb, a, alloc_addr_a - ram);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 1, ram + 0x8000000, 0x10010000,
+		   0, 0, 0, 0);
+	d = lmb_alloc_addr(&lmb, ram, 4);
+	ut_asserteq(d, ram);
+	ASSERT_LMB(&lmb, ram, ram_size, 2, d, 4,
+		   ram + 0x8000000, 0x10010000, 0, 0);
+
+	/* check that allocating outside memory fails */
+	if (ram_end != 0) {
+		ret = lmb_alloc_addr(&lmb, ram_end, 1);
+		ut_asserteq(ret, 0);
+	}
+	if (ram != 0) {
+		ret = lmb_alloc_addr(&lmb, ram - 1, 1);
+		ut_asserteq(ret, 0);
+	}
+
+	return 0;
+}
+
+static int lib_test_lmb_alloc_addr(struct unit_test_state *uts)
+{
+	int ret;
+
+	/* simulate 512 MiB RAM beginning at 1GiB */
+	ret = test_alloc_addr(uts, 0x40000000);
+	if (ret)
+		return ret;
+
+	/* simulate 512 MiB RAM beginning at 1.5GiB */
+	return test_alloc_addr(uts, 0xE0000000);
+}
+
+DM_TEST(lib_test_lmb_alloc_addr, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Simulate 512 MiB RAM, reserve 3 blocks, check addresses in between */
+static int test_get_unreserved_size(struct unit_test_state *uts,
+				    const phys_addr_t ram)
+{
+	const phys_size_t ram_size = 0x20000000;
+	const phys_addr_t ram_end = ram + ram_size;
+	const phys_size_t alloc_addr_a = ram + 0x8000000;
+	const phys_size_t alloc_addr_b = ram + 0x8000000 * 2;
+	const phys_size_t alloc_addr_c = ram + 0x8000000 * 3;
+	struct lmb lmb;
+	long ret;
+	phys_size_t s;
+
+	/* check for overflow */
+	ut_assert(ram_end == 0 || ram_end > ram);
+
+	lmb_init(&lmb);
+
+	ret = lmb_add(&lmb, ram, ram_size);
+	ut_asserteq(ret, 0);
+
+	/*  reserve 3 blocks */
+	ret = lmb_reserve(&lmb, alloc_addr_a, 0x10000);
+	ut_asserteq(ret, 0);
+	ret = lmb_reserve(&lmb, alloc_addr_b, 0x10000);
+	ut_asserteq(ret, 0);
+	ret = lmb_reserve(&lmb, alloc_addr_c, 0x10000);
+	ut_asserteq(ret, 0);
+	ASSERT_LMB(&lmb, ram, ram_size, 3, alloc_addr_a, 0x10000,
+		   alloc_addr_b, 0x10000, alloc_addr_c, 0x10000);
+
+	/* check addresses in between blocks */
+	s = lmb_get_unreserved_size(&lmb, ram);
+	ut_asserteq(s, alloc_addr_a - ram);
+	s = lmb_get_unreserved_size(&lmb, ram + 0x10000);
+	ut_asserteq(s, alloc_addr_a - ram - 0x10000);
+	s = lmb_get_unreserved_size(&lmb, alloc_addr_a - 4);
+	ut_asserteq(s, 4);
+
+	s = lmb_get_unreserved_size(&lmb, alloc_addr_a + 0x10000);
+	ut_asserteq(s, alloc_addr_b - alloc_addr_a - 0x10000);
+	s = lmb_get_unreserved_size(&lmb, alloc_addr_a + 0x20000);
+	ut_asserteq(s, alloc_addr_b - alloc_addr_a - 0x20000);
+	s = lmb_get_unreserved_size(&lmb, alloc_addr_b - 4);
+	ut_asserteq(s, 4);
+
+	s = lmb_get_unreserved_size(&lmb, alloc_addr_c + 0x10000);
+	ut_asserteq(s, ram_end - alloc_addr_c - 0x10000);
+	s = lmb_get_unreserved_size(&lmb, alloc_addr_c + 0x20000);
+	ut_asserteq(s, ram_end - alloc_addr_c - 0x20000);
+	s = lmb_get_unreserved_size(&lmb, ram_end - 4);
+	ut_asserteq(s, 4);
+
+	return 0;
+}
+
+static int lib_test_lmb_get_unreserved_size(struct unit_test_state *uts)
+{
+	int ret;
+
+	/* simulate 512 MiB RAM beginning at 1GiB */
+	ret = test_get_unreserved_size(uts, 0x40000000);
+	if (ret)
+		return ret;
+
+	/* simulate 512 MiB RAM beginning at 1.5GiB */
+	return test_get_unreserved_size(uts, 0xE0000000);
+}
+
+DM_TEST(lib_test_lmb_get_unreserved_size,
+	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
diff --git a/test/py/tests/test_avb.py b/test/py/tests/test_avb.py
index 9683fd8..e70a010 100644
--- a/test/py/tests/test_avb.py
+++ b/test/py/tests/test_avb.py
@@ -51,22 +51,22 @@
 
     part_lines = u_boot_console.run_command('mmc part').splitlines()
     part_list = {}
-    cur_partname = ""
+    cur_partname = ''
 
     for line in part_lines:
-        if "\"" in line:
-            start_pt = line.find("\"")
-            end_pt = line.find("\"", start_pt + 1)
+        if '"' in line:
+            start_pt = line.find('"')
+            end_pt = line.find('"', start_pt + 1)
             cur_partname = line[start_pt + 1: end_pt]
 
-        if "guid:" in line:
-            guid_to_check = line.split("guid:\t")
+        if 'guid:' in line:
+            guid_to_check = line.split('guid:\t')
             part_list[cur_partname] = guid_to_check[1]
 
     # lets check all guids with avb get_guid
     for part, guid in part_list.iteritems():
         avb_guid_resp = u_boot_console.run_command('avb get_uuid %s' % part)
-        assert guid == avb_guid_resp.split("UUID: ")[1]
+        assert guid == avb_guid_resp.split('UUID: ')[1]
 
 
 @pytest.mark.buildconfigspec('cmd_avb')
diff --git a/test/py/tests/test_bind.py b/test/py/tests/test_bind.py
index dee3fee..ccf6d62 100644
--- a/test/py/tests/test_bind.py
+++ b/test/py/tests/test_bind.py
@@ -13,7 +13,8 @@
 	else:
 		leaf = leaf + '`'
 	leaf = leaf + '-- ' + name
-	line = ' *{:10.10}  [0-9]*  \[ [ +] \]   {:20.20}  {}$'.format(uclass, drv, leaf)
+	line = (' *{:10.10}   [0-9]*  \[ [ +] \]   {:20.20}  {}$'
+	        .format(uclass, drv, leaf))
 	prog = re.compile(line)
 	for l in lines:
 		if prog.match(l):
@@ -25,82 +26,82 @@
 def test_bind_unbind_with_node(u_boot_console):
 
 	#bind /bind-test. Device should come up as well as its children
-	response = u_boot_console.run_command("bind  /bind-test generic_simple_bus")
+	response = u_boot_console.run_command('bind  /bind-test generic_simple_bus')
 	assert response == ''
-	tree = u_boot_console.run_command("dm tree")
-	assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True)
-	assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, False)
-	assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True)
+	tree = u_boot_console.run_command('dm tree')
+	assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True)
+	assert in_tree(tree, 'bind-test-child1', 'phy', 'phy_sandbox', 1, False)
+	assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True)
 
 	#Unbind child #1. No error expected and all devices should be there except for bind-test-child1
-	response = u_boot_console.run_command("unbind  /bind-test/bind-test-child1")
+	response = u_boot_console.run_command('unbind  /bind-test/bind-test-child1')
 	assert response == ''
-	tree = u_boot_console.run_command("dm tree")
-	assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True)
-	assert "bind-test-child1" not in tree
-	assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True)
+	tree = u_boot_console.run_command('dm tree')
+	assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True)
+	assert 'bind-test-child1' not in tree
+	assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True)
 
 	#bind child #1. No error expected and all devices should be there
-	response = u_boot_console.run_command("bind  /bind-test/bind-test-child1 phy_sandbox")
+	response = u_boot_console.run_command('bind  /bind-test/bind-test-child1 phy_sandbox')
 	assert response == ''
-	tree = u_boot_console.run_command("dm tree")
-	assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True)
-	assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, True)
-	assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, False)
+	tree = u_boot_console.run_command('dm tree')
+	assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True)
+	assert in_tree(tree, 'bind-test-child1', 'phy', 'phy_sandbox', 1, True)
+	assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, False)
 
 	#Unbind child #2. No error expected and all devices should be there except for bind-test-child2
-	response = u_boot_console.run_command("unbind  /bind-test/bind-test-child2")
+	response = u_boot_console.run_command('unbind  /bind-test/bind-test-child2')
 	assert response == ''
-	tree = u_boot_console.run_command("dm tree")
-	assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True)
-	assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, True)
-	assert "bind-test-child2" not in tree
+	tree = u_boot_console.run_command('dm tree')
+	assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True)
+	assert in_tree(tree, 'bind-test-child1', 'phy', 'phy_sandbox', 1, True)
+	assert 'bind-test-child2' not in tree
 
 
 	#Bind child #2. No error expected and all devices should be there
-	response = u_boot_console.run_command("bind /bind-test/bind-test-child2 generic_simple_bus")
+	response = u_boot_console.run_command('bind /bind-test/bind-test-child2 generic_simple_bus')
 	assert response == ''
-	tree = u_boot_console.run_command("dm tree")
-	assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True)
-	assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, False)
-	assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True)
+	tree = u_boot_console.run_command('dm tree')
+	assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True)
+	assert in_tree(tree, 'bind-test-child1', 'phy', 'phy_sandbox', 1, False)
+	assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True)
 
 	#Unbind parent. No error expected. All devices should be removed and unbound
-	response = u_boot_console.run_command("unbind  /bind-test")
+	response = u_boot_console.run_command('unbind  /bind-test')
 	assert response == ''
-	tree = u_boot_console.run_command("dm tree")
-	assert "bind-test" not in tree
-	assert "bind-test-child1" not in tree
-	assert "bind-test-child2" not in tree
+	tree = u_boot_console.run_command('dm tree')
+	assert 'bind-test' not in tree
+	assert 'bind-test-child1' not in tree
+	assert 'bind-test-child2' not in tree
 
 	#try binding invalid node with valid driver
-	response = u_boot_console.run_command("bind  /not-a-valid-node generic_simple_bus")
+	response = u_boot_console.run_command('bind  /not-a-valid-node generic_simple_bus')
 	assert response != ''
-	tree = u_boot_console.run_command("dm tree")
-	assert "not-a-valid-node" not in tree
+	tree = u_boot_console.run_command('dm tree')
+	assert 'not-a-valid-node' not in tree
 
 	#try binding valid node with invalid driver
-	response = u_boot_console.run_command("bind  /bind-test not_a_driver")
+	response = u_boot_console.run_command('bind  /bind-test not_a_driver')
 	assert response != ''
-	tree = u_boot_console.run_command("dm tree")
-	assert "bind-test" not in tree
+	tree = u_boot_console.run_command('dm tree')
+	assert 'bind-test' not in tree
 
 	#bind /bind-test. Device should come up as well as its children
-	response = u_boot_console.run_command("bind  /bind-test generic_simple_bus")
+	response = u_boot_console.run_command('bind  /bind-test generic_simple_bus')
 	assert response == ''
-	tree = u_boot_console.run_command("dm tree")
-	assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True)
-	assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, False)
-	assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True)
+	tree = u_boot_console.run_command('dm tree')
+	assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True)
+	assert in_tree(tree, 'bind-test-child1', 'phy', 'phy_sandbox', 1, False)
+	assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True)
 
-	response = u_boot_console.run_command("unbind  /bind-test")
+	response = u_boot_console.run_command('unbind  /bind-test')
 	assert response == ''
 
 def get_next_line(tree, name):
 	treelines = [x.strip() for x in tree.splitlines() if x.strip()]
-	child_line = ""
+	child_line = ''
 	for idx, line in enumerate(treelines):
-		if ("-- " + name) in line:
+		if ('-- ' + name) in line:
 			try:
 				child_line = treelines[idx+1]
 			except:
@@ -111,68 +112,68 @@
 @pytest.mark.buildconfigspec('cmd_bind')
 def test_bind_unbind_with_uclass(u_boot_console):
 	#bind /bind-test
-	response = u_boot_console.run_command("bind  /bind-test generic_simple_bus")
+	response = u_boot_console.run_command('bind  /bind-test generic_simple_bus')
 	assert response == ''
 
 	#make sure bind-test-child2 is there and get its uclass/index pair
-	tree = u_boot_console.run_command("dm tree")
-	child2_line = [x.strip() for x in tree.splitlines() if "-- bind-test-child2" in x]
+	tree = u_boot_console.run_command('dm tree')
+	child2_line = [x.strip() for x in tree.splitlines() if '-- bind-test-child2' in x]
 	assert len(child2_line) == 1
 
 	child2_uclass = child2_line[0].split()[0]
 	child2_index = int(child2_line[0].split()[1])
 
 	#bind generic_simple_bus as a child of bind-test-child2
-	response = u_boot_console.run_command("bind  {} {} generic_simple_bus".format(child2_uclass, child2_index, "generic_simple_bus"))
+	response = u_boot_console.run_command('bind  {} {} generic_simple_bus'.format(child2_uclass, child2_index, 'generic_simple_bus'))
 
 	#check that the child is there and its uclass/index pair is right
-	tree = u_boot_console.run_command("dm tree")
+	tree = u_boot_console.run_command('dm tree')
 
-	child_of_child2_line = get_next_line(tree, "bind-test-child2")
+	child_of_child2_line = get_next_line(tree, 'bind-test-child2')
 	assert child_of_child2_line
 	child_of_child2_index = int(child_of_child2_line.split()[1])
-	assert in_tree(tree, "generic_simple_bus", "simple_bus", "generic_simple_bus", 2, True)
+	assert in_tree(tree, 'generic_simple_bus', 'simple_bus', 'generic_simple_bus', 2, True)
 	assert child_of_child2_index == child2_index + 1
 
 	#unbind the child and check it has been removed
-	response = u_boot_console.run_command("unbind  simple_bus {}".format(child_of_child2_index))
+	response = u_boot_console.run_command('unbind  simple_bus {}'.format(child_of_child2_index))
 	assert response == ''
-	tree = u_boot_console.run_command("dm tree")
-	assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True)
-	assert not in_tree(tree, "generic_simple_bus", "simple_bus", "generic_simple_bus", 2, True)
-	child_of_child2_line = get_next_line(tree, "bind-test-child2")
-	assert child_of_child2_line == ""
+	tree = u_boot_console.run_command('dm tree')
+	assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True)
+	assert not in_tree(tree, 'generic_simple_bus', 'simple_bus', 'generic_simple_bus', 2, True)
+	child_of_child2_line = get_next_line(tree, 'bind-test-child2')
+	assert child_of_child2_line == ''
 
 	#bind generic_simple_bus as a child of bind-test-child2
-	response = u_boot_console.run_command("bind  {} {} generic_simple_bus".format(child2_uclass, child2_index, "generic_simple_bus"))
+	response = u_boot_console.run_command('bind  {} {} generic_simple_bus'.format(child2_uclass, child2_index, 'generic_simple_bus'))
 
 	#check that the child is there and its uclass/index pair is right
-	tree = u_boot_console.run_command("dm tree")
+	tree = u_boot_console.run_command('dm tree')
 	treelines = [x.strip() for x in tree.splitlines() if x.strip()]
 
-	child_of_child2_line = get_next_line(tree, "bind-test-child2")
+	child_of_child2_line = get_next_line(tree, 'bind-test-child2')
 	assert child_of_child2_line
 	child_of_child2_index = int(child_of_child2_line.split()[1])
-	assert in_tree(tree, "generic_simple_bus", "simple_bus", "generic_simple_bus", 2, True)
+	assert in_tree(tree, 'generic_simple_bus', 'simple_bus', 'generic_simple_bus', 2, True)
 	assert child_of_child2_index == child2_index + 1
 
 	#unbind the child and check it has been removed
-	response = u_boot_console.run_command("unbind  {} {} generic_simple_bus".format(child2_uclass, child2_index, "generic_simple_bus"))
+	response = u_boot_console.run_command('unbind  {} {} generic_simple_bus'.format(child2_uclass, child2_index, 'generic_simple_bus'))
 	assert response == ''
 
-	tree = u_boot_console.run_command("dm tree")
-	assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True)
+	tree = u_boot_console.run_command('dm tree')
+	assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True)
 
-	child_of_child2_line = get_next_line(tree, "bind-test-child2")
-	assert child_of_child2_line == ""
+	child_of_child2_line = get_next_line(tree, 'bind-test-child2')
+	assert child_of_child2_line == ''
 
 	#unbind the child again and check it doesn't change the tree
-	tree_old = u_boot_console.run_command("dm tree")
-	response = u_boot_console.run_command("unbind  {} {} generic_simple_bus".format(child2_uclass, child2_index, "generic_simple_bus"))
-	tree_new = u_boot_console.run_command("dm tree")
+	tree_old = u_boot_console.run_command('dm tree')
+	response = u_boot_console.run_command('unbind  {} {} generic_simple_bus'.format(child2_uclass, child2_index, 'generic_simple_bus'))
+	tree_new = u_boot_console.run_command('dm tree')
 
 	assert response == ''
 	assert tree_old == tree_new
 
-	response = u_boot_console.run_command("unbind  /bind-test")
+	response = u_boot_console.run_command('unbind  /bind-test')
 	assert response == ''
diff --git a/test/py/tests/test_dfu.py b/test/py/tests/test_dfu.py
index a246003..5d87eb3 100644
--- a/test/py/tests/test_dfu.py
+++ b/test/py/tests/test_dfu.py
@@ -20,28 +20,28 @@
 
 env__usb_dev_ports = (
     {
-        "fixture_id": "micro_b",
-        "tgt_usb_ctlr": "0",
-        "host_usb_dev_node": "/dev/usbdev-p2371-2180",
+        'fixture_id': 'micro_b',
+        'tgt_usb_ctlr': '0',
+        'host_usb_dev_node': '/dev/usbdev-p2371-2180',
         # This parameter is optional /if/ you only have a single board
         # attached to your host at a time.
-        "host_usb_port_path": "3-13",
+        'host_usb_port_path': '3-13',
     },
 )
 
-# Optional entries (required only when "alt_id_test_file" and
-# "alt_id_dummy_file" are specified).
-test_file_name = "/dfu_test.bin"
-dummy_file_name = "/dfu_dummy.bin"
-# Above files are used to generate proper "alt_info" entry
-"alt_info": "/%s ext4 0 2;/%s ext4 0 2" % (test_file_name, dummy_file_name),
+# Optional entries (required only when 'alt_id_test_file' and
+# 'alt_id_dummy_file' are specified).
+test_file_name = '/dfu_test.bin'
+dummy_file_name = '/dfu_dummy.bin'
+# Above files are used to generate proper 'alt_info' entry
+'alt_info': '/%s ext4 0 2;/%s ext4 0 2' % (test_file_name, dummy_file_name),
 
 env__dfu_configs = (
     # eMMC, partition 1
     {
-        "fixture_id": "emmc",
-        "alt_info": "/dfu_test.bin ext4 0 1;/dfu_dummy.bin ext4 0 1",
-        "cmd_params": "mmc 0",
+        'fixture_id': 'emmc',
+        'alt_info': '/dfu_test.bin ext4 0 1;/dfu_dummy.bin ext4 0 1',
+        'cmd_params': 'mmc 0',
         # This value is optional.
         # If present, it specified the set of transfer sizes tested.
         # If missing, a default list of sizes will be used, which covers
@@ -49,7 +49,7 @@
         # Manually specifying test sizes is useful if you wish to test 4 DFU
         # configurations, but don't want to test every single transfer size
         # on each, to avoid bloating the overall time taken by testing.
-        "test_sizes": (63, 64, 65),
+        'test_sizes': (63, 64, 65),
         # This value is optional.
         # The name of the environment variable that the the dfu command reads
         # alt info from. If unspecified, this defaults to dfu_alt_info, which is
@@ -57,17 +57,17 @@
         # One example is the Odroid XU3,  which automatically generates
         # $dfu_alt_info, each time the dfu command is run, by concatenating
         # $dfu_alt_boot and $dfu_alt_system.
-        "alt_info_env_name": "dfu_alt_system",
+        'alt_info_env_name': 'dfu_alt_system',
         # This value is optional.
-        # For boards which require the "test file" alt setting number other than
+        # For boards which require the 'test file' alt setting number other than
         # default (0) it is possible to specify exact file name to be used as
         # this parameter.
-        "alt_id_test_file": test_file_name,
+        'alt_id_test_file': test_file_name,
         # This value is optional.
-        # For boards which require the "dummy file" alt setting number other
+        # For boards which require the 'dummy file' alt setting number other
         # than default (1) it is possible to specify exact file name to be used
         # as this parameter.
-        "alt_id_dummy_file": dummy_file_name,
+        'alt_id_dummy_file': dummy_file_name,
     },
 )
 
diff --git a/test/py/tests/test_efi_loader.py b/test/py/tests/test_efi_loader.py
index a66c6e6..d6b214f 100644
--- a/test/py/tests/test_efi_loader.py
+++ b/test/py/tests/test_efi_loader.py
@@ -35,17 +35,17 @@
 # static IP. If solely relying on DHCP, this variable may be omitted or set to
 # an empty list.
 env__net_static_env_vars = [
-    ("ipaddr", "10.0.0.100"),
-    ("netmask", "255.255.255.0"),
-    ("serverip", "10.0.0.1"),
+    ('ipaddr', '10.0.0.100'),
+    ('netmask', '255.255.255.0'),
+    ('serverip', '10.0.0.1'),
 ]
 
 # Details regarding a file that may be read from a TFTP server. This variable
 # may be omitted or set to None if TFTP testing is not possible or desired.
 env__efi_loader_helloworld_file = {
-    "fn": "lib/efi_loader/helloworld.efi",
-    "size": 5058624,
-    "crc32": "c2244b26",
+    'fn': 'lib/efi_loader/helloworld.efi',
+    'size': 5058624,
+    'crc32': 'c2244b26',
 }
 """
 
diff --git a/test/py/tests/test_fpga.py b/test/py/tests/test_fpga.py
index 7459ce5..798f6ee 100644
--- a/test/py/tests/test_fpga.py
+++ b/test/py/tests/test_fpga.py
@@ -24,40 +24,40 @@
 # static IP. In this test case we atleast need serverip for performing tftpb
 # to get required files.
 env__net_static_env_vars = [
-    ("ipaddr", "10.0.0.100"),
-    ("netmask", "255.255.255.0"),
-    ("serverip", "10.0.0.1"),
+    ('ipaddr', '10.0.0.100'),
+    ('netmask', '255.255.255.0'),
+    ('serverip', '10.0.0.1'),
 ]
 
 # Details regarding the files that may be read from a TFTP server. .
 env__fpga_secure_readable_file = {
-    "fn": "auth_bhdr_ppk1_bit.bin",
-    "enckupfn": "auth_bhdr_enc_kup_load_bit.bin",
-    "addr": 0x1000000,
-    "keyaddr": 0x100000,
-    "keyfn": "key.txt",
+    'fn': 'auth_bhdr_ppk1_bit.bin',
+    'enckupfn': 'auth_bhdr_enc_kup_load_bit.bin',
+    'addr': 0x1000000,
+    'keyaddr': 0x100000,
+    'keyfn': 'key.txt',
 }
 
 env__fpga_under_test = {
-    "dev": 0,
-    "addr" : 0x1000000,
-    "bitstream_load": "compress.bin",
-    "bitstream_load_size": 1831960,
-    "bitstream_loadp": "compress_pr.bin",
-    "bitstream_loadp_size": 423352,
-    "bitstream_loadb": "compress.bit",
-    "bitstream_loadb_size": 1832086,
-    "bitstream_loadbp": "compress_pr.bit",
-    "bitstream_loadbp_size": 423491,
-    "mkimage_legacy": "download.ub",
-    "mkimage_legacy_size": 13321468,
-    "mkimage_legacy_gz": "download.gz.ub",
-    "mkimage_legacy_gz_size": 53632,
-    "mkimage_fit": "download-fit.ub",
-    "mkimage_fit_size": 13322784,
-    "loadfs": "mmc 0 compress.bin",
-    "loadfs_size": 1831960,
-    "loadfs_block_size": 0x10000,
+    'dev': 0,
+    'addr' : 0x1000000,
+    'bitstream_load': 'compress.bin',
+    'bitstream_load_size': 1831960,
+    'bitstream_loadp': 'compress_pr.bin',
+    'bitstream_loadp_size': 423352,
+    'bitstream_loadb': 'compress.bit',
+    'bitstream_loadb_size': 1832086,
+    'bitstream_loadbp': 'compress_pr.bit',
+    'bitstream_loadbp_size': 423491,
+    'mkimage_legacy': 'download.ub',
+    'mkimage_legacy_size': 13321468,
+    'mkimage_legacy_gz': 'download.gz.ub',
+    'mkimage_legacy_gz_size': 53632,
+    'mkimage_fit': 'download-fit.ub',
+    'mkimage_fit_size': 13322784,
+    'loadfs': 'mmc 0 compress.bin',
+    'loadfs_size': 1831960,
+    'loadfs_block_size': 0x10000,
 }
 """
 
diff --git a/test/py/tests/test_fs/conftest.py b/test/py/tests/test_fs/conftest.py
index 60b4a2d..43eeb4b 100644
--- a/test/py/tests/test_fs/conftest.py
+++ b/test/py/tests/test_fs/conftest.py
@@ -54,7 +54,7 @@
 
     supported_fs = config.getoption('fs_type')
     if supported_fs:
-        print("*** FS TYPE modified: %s" % supported_fs)
+        print('*** FS TYPE modified: %s' % supported_fs)
         supported_fs_basic =  intersect(supported_fs, supported_fs_basic)
         supported_fs_ext =  intersect(supported_fs, supported_fs_ext)
         supported_fs_mkdir =  intersect(supported_fs, supported_fs_mkdir)
@@ -174,7 +174,7 @@
     Return:
         True if available, False if not.
     """
-    for path in os.environ["PATH"].split(os.pathsep):
+    for path in os.environ['PATH'].split(os.pathsep):
         fn = os.path.join(path, tool)
         if os.path.isfile(fn) and os.access(fn, os.X_OK):
             return True
@@ -202,9 +202,9 @@
             check_call('guestmount -a %s -m /dev/sda %s'
                 % (device, mount_point), shell=True)
         else:
-            mount_opt = "loop,rw"
+            mount_opt = 'loop,rw'
             if re.match('fat', fs_type):
-                mount_opt += ",umask=0000"
+                mount_opt += ',umask=0000'
 
             check_call('sudo mount -o %s %s %s'
                 % (mount_opt, device, mount_point), shell=True)
diff --git a/test/py/tests/test_mmc_rd.py b/test/py/tests/test_mmc_rd.py
index c5858cb..a13bc0a 100644
--- a/test/py/tests/test_mmc_rd.py
+++ b/test/py/tests/test_mmc_rd.py
@@ -14,45 +14,45 @@
 
 env__mmc_rd_configs = (
     {
-        "fixture_id": "emmc-boot0",
-        "is_emmc": True,
-        "devid": 0,
-        "partid": 1,
-        "sector": 0x10,
-        "count": 1,
+        'fixture_id': 'emmc-boot0',
+        'is_emmc': True,
+        'devid': 0,
+        'partid': 1,
+        'sector': 0x10,
+        'count': 1,
     },
     {
-        "fixture_id": "emmc-boot1",
-        "is_emmc": True,
-        "devid": 0,
-        "partid": 2,
-        "sector": 0x10,
-        "count": 1,
+        'fixture_id': 'emmc-boot1',
+        'is_emmc': True,
+        'devid': 0,
+        'partid': 2,
+        'sector': 0x10,
+        'count': 1,
     },
     {
-        "fixture_id": "emmc-data",
-        "is_emmc": True,
-        "devid": 0,
-        "partid": 0,
-        "sector": 0x10,
-        "count": 0x1000,
+        'fixture_id': 'emmc-data',
+        'is_emmc': True,
+        'devid': 0,
+        'partid': 0,
+        'sector': 0x10,
+        'count': 0x1000,
     },
     {
-        "fixture_id": "sd-mbr",
-        "is_emmc": False,
-        "devid": 1,
-        "partid": None,
-        "sector": 0,
-        "count": 1,
-        "crc32": "8f6ecf0d",
+        'fixture_id': 'sd-mbr',
+        'is_emmc': False,
+        'devid': 1,
+        'partid': None,
+        'sector': 0,
+        'count': 1,
+        'crc32': '8f6ecf0d',
     },
     {
-        "fixture_id": "sd-large",
-        "is_emmc": False,
-        "devid": 1,
-        "partid": None,
-        "sector": 0x10,
-        "count": 0x1000,
+        'fixture_id': 'sd-large',
+        'is_emmc': False,
+        'devid': 1,
+        'partid': None,
+        'sector': 0x10,
+        'count': 0x1000,
     },
 )
 """
@@ -92,9 +92,9 @@
     response = u_boot_console.run_command(cmd)
     assert 'no card present' not in response
     if is_emmc:
-        partid_response = "(part %d)" % partid
+        partid_response = '(part %d)' % partid
     else:
-        partid_response = ""
+        partid_response = ''
     good_response = 'mmc%d%s is current device' % (devid, partid_response)
     assert good_response in response
 
diff --git a/test/py/tests/test_net.py b/test/py/tests/test_net.py
index 2821ce6..9c395e6 100644
--- a/test/py/tests/test_net.py
+++ b/test/py/tests/test_net.py
@@ -33,27 +33,27 @@
 # static IP. If solely relying on DHCP, this variable may be omitted or set to
 # an empty list.
 env__net_static_env_vars = [
-    ("ipaddr", "10.0.0.100"),
-    ("netmask", "255.255.255.0"),
-    ("serverip", "10.0.0.1"),
+    ('ipaddr', '10.0.0.100'),
+    ('netmask', '255.255.255.0'),
+    ('serverip', '10.0.0.1'),
 ]
 
 # Details regarding a file that may be read from a TFTP server. This variable
 # may be omitted or set to None if TFTP testing is not possible or desired.
 env__net_tftp_readable_file = {
-    "fn": "ubtest-readable.bin",
-    "addr": 0x10000000,
-    "size": 5058624,
-    "crc32": "c2244b26",
+    'fn': 'ubtest-readable.bin',
+    'addr': 0x10000000,
+    'size': 5058624,
+    'crc32': 'c2244b26',
 }
 
 # Details regarding a file that may be read from a NFS server. This variable
 # may be omitted or set to None if NFS testing is not possible or desired.
 env__net_nfs_readable_file = {
-    "fn": "ubtest-readable.bin",
-    "addr": 0x10000000,
-    "size": 5058624,
-    "crc32": "c2244b26",
+    'fn': 'ubtest-readable.bin',
+    'addr': 0x10000000,
+    'size': 5058624,
+    'crc32': 'c2244b26',
 }
 """
 
diff --git a/test/py/tests/test_ums.py b/test/py/tests/test_ums.py
index e8eb43c..749b160 100644
--- a/test/py/tests/test_ums.py
+++ b/test/py/tests/test_ums.py
@@ -23,35 +23,35 @@
 # Leave this list empty if you have no block_devs below with writable
 # partitions defined.
 env__mount_points = (
-    "/mnt/ubtest-mnt-p2371-2180-na",
+    '/mnt/ubtest-mnt-p2371-2180-na',
 )
 
 env__usb_dev_ports = (
     {
-        "fixture_id": "micro_b",
-        "tgt_usb_ctlr": "0",
-        "host_ums_dev_node": "/dev/disk/by-path/pci-0000:00:14.0-usb-0:13:1.0-scsi-0:0:0:0",
+        'fixture_id': 'micro_b',
+        'tgt_usb_ctlr': '0',
+        'host_ums_dev_node': '/dev/disk/by-path/pci-0000:00:14.0-usb-0:13:1.0-scsi-0:0:0:0',
     },
 )
 
 env__block_devs = (
     # eMMC; always present
     {
-        "fixture_id": "emmc",
-        "type": "mmc",
-        "id": "0",
+        'fixture_id': 'emmc',
+        'type': 'mmc',
+        'id': '0',
         # The following two properties are optional.
         # If present, the partition will be mounted and a file written-to and
         # read-from it. If missing, only a simple block read test will be
         # performed.
-        "writable_fs_partition": 1,
-        "writable_fs_subdir": "tmp/",
+        'writable_fs_partition': 1,
+        'writable_fs_subdir': 'tmp/',
     },
     # SD card; present since I plugged one in
     {
-        "fixture_id": "sd",
-        "type": "mmc",
-        "id": "1"
+        'fixture_id': 'sd',
+        'type': 'mmc',
+        'id': '1'
     },
 )
 
diff --git a/tools/buildman/README b/tools/buildman/README
index 5a709c6..56a99c7 100644
--- a/tools/buildman/README
+++ b/tools/buildman/README
@@ -1046,6 +1046,16 @@
 
 The -U option uses the u-boot.env files which are produced by a build.
 
+
+Building with clang
+===================
+
+To build with clang (sandbox only), use the -O option to override the
+toolchain. For example:
+
+   buildman -O clang-7 --board sandbox
+
+
 Other options
 =============
 
@@ -1169,8 +1179,6 @@
 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/builderthread.py b/tools/buildman/builderthread.py
index c84ba6a..6b156f1 100644
--- a/tools/buildman/builderthread.py
+++ b/tools/buildman/builderthread.py
@@ -156,7 +156,12 @@
         if result.already_done:
             # Get the return code from that build and use it
             with open(done_file, 'r') as fd:
-                result.return_code = int(fd.readline())
+                try:
+                    result.return_code = int(fd.readline())
+                except ValueError:
+                    # The file may be empty due to running out of disk space.
+                    # Try a rebuild
+                    result.return_code = RETURN_CODE_RETRY
 
             # Check the signal that the build needs to be retried
             if result.return_code == RETURN_CODE_RETRY:
@@ -224,6 +229,7 @@
                 config_args = ['%s_defconfig' % brd.target]
                 config_out = ''
                 args.extend(self.builder.toolchains.GetMakeArguments(brd))
+                args.extend(self.toolchain.MakeArgs())
 
                 # If we need to reconfigure, do that now
                 if do_config:
diff --git a/tools/buildman/cmdline.py b/tools/buildman/cmdline.py
index 93d09ca..832a514 100644
--- a/tools/buildman/cmdline.py
+++ b/tools/buildman/cmdline.py
@@ -74,6 +74,8 @@
     parser.add_option('-o', '--output-dir', type='string',
           dest='output_dir', default='..',
           help='Directory where all builds happen and buildman has its workspace (default is ../)')
+    parser.add_option('-O', '--override-toolchain', type='string',
+          help="Override host toochain to use for sandbox (e.g. 'clang-7')")
     parser.add_option('-Q', '--quick', action='store_true',
           default=False, help='Do a rough build, with limited warning resolution')
     parser.add_option('-p', '--full-path', action='store_true',
diff --git a/tools/buildman/control.py b/tools/buildman/control.py
index c900211..27916d3 100644
--- a/tools/buildman/control.py
+++ b/tools/buildman/control.py
@@ -141,7 +141,7 @@
 
     no_toolchains = toolchains is None
     if no_toolchains:
-        toolchains = toolchain.Toolchains()
+        toolchains = toolchain.Toolchains(options.override_toolchain)
 
     if options.fetch_arch:
         if options.fetch_arch == 'list':
diff --git a/tools/buildman/toolchain.py b/tools/buildman/toolchain.py
index c62ce13..a65737f 100644
--- a/tools/buildman/toolchain.py
+++ b/tools/buildman/toolchain.py
@@ -54,9 +54,11 @@
         arch: Architecture of toolchain as determined from the first
                 component of the filename. E.g. arm-linux-gcc becomes arm
         priority: Toolchain priority (0=highest, 20=lowest)
+        override_toolchain: Toolchain to use for sandbox, overriding the normal
+                one
     """
     def __init__(self, fname, test, verbose=False, priority=PRIORITY_CALC,
-                 arch=None):
+                 arch=None, override_toolchain=None):
         """Create a new toolchain object.
 
         Args:
@@ -68,6 +70,7 @@
         """
         self.gcc = fname
         self.path = os.path.dirname(fname)
+        self.override_toolchain = override_toolchain
 
         # Find the CROSS_COMPILE prefix to use for U-Boot. For example,
         # 'arm-linux-gnueabihf-gcc' turns into 'arm-linux-gnueabihf-'.
@@ -81,6 +84,8 @@
             self.arch = arch
         else:
             self.arch = self.cross[:pos] if pos != -1 else 'sandbox'
+        if self.arch == 'sandbox' and override_toolchain:
+            self.gcc = override_toolchain
 
         env = self.MakeEnvironment(False)
 
@@ -130,8 +135,8 @@
     def GetWrapper(self, show_warning=True):
         """Get toolchain wrapper from the setting file.
         """
-	value = ''
-	for name, value in bsettings.GetItems('toolchain-wrapper'):
+        value = ''
+        for name, value in bsettings.GetItems('toolchain-wrapper'):
             if not value:
                 print "Warning: Wrapper not found"
         if value:
@@ -150,11 +155,18 @@
         Args:
             full_path: Return the full path in CROSS_COMPILE and don't set
                 PATH
+        Returns:
+            Dict containing the environemnt to use. This is based on the current
+            environment, with changes as needed to CROSS_COMPILE, PATH and
+            LC_ALL.
         """
         env = dict(os.environ)
         wrapper = self.GetWrapper()
 
-        if full_path:
+        if self.override_toolchain:
+            # We'll use MakeArgs() to provide this
+            pass
+        elif full_path:
             env['CROSS_COMPILE'] = wrapper + os.path.join(self.path, self.cross)
         else:
             env['CROSS_COMPILE'] = wrapper + self.cross
@@ -164,6 +176,22 @@
 
         return env
 
+    def MakeArgs(self):
+        """Create the 'make' arguments for a toolchain
+
+        This is only used when the toolchain is being overridden. Since the
+        U-Boot Makefile sets CC and HOSTCC explicitly we cannot rely on the
+        environment (and MakeEnvironment()) to override these values. This
+        function returns the arguments to accomplish this.
+
+        Returns:
+            List of arguments to pass to 'make'
+        """
+        if self.override_toolchain:
+            return ['HOSTCC=%s' % self.override_toolchain,
+                    'CC=%s' % self.override_toolchain]
+        return []
+
 
 class Toolchains:
     """Manage a list of toolchains for building U-Boot
@@ -180,10 +208,11 @@
         paths: List of paths to check for toolchains (may contain wildcards)
     """
 
-    def __init__(self):
+    def __init__(self, override_toolchain=None):
         self.toolchains = {}
         self.prefixes = {}
         self.paths = []
+        self.override_toolchain = override_toolchain
         self._make_flags = dict(bsettings.GetItems('make-flags'))
 
     def GetPathList(self, show_warning=True):
@@ -234,7 +263,8 @@
             priority: Priority to use for this toolchain
             arch: Toolchain architecture, or None if not known
         """
-        toolchain = Toolchain(fname, test, verbose, priority, arch)
+        toolchain = Toolchain(fname, test, verbose, priority, arch,
+                              self.override_toolchain)
         add_it = toolchain.ok
         if toolchain.arch in self.toolchains:
             add_it = (toolchain.priority <
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py
index 6cb1259..ca580b4 100644
--- a/tools/dtoc/dtb_platdata.py
+++ b/tools/dtoc/dtb_platdata.py
@@ -461,7 +461,7 @@
         """
         struct_name, _ = get_compat_name(node)
         var_name = conv_name_to_c(node.name)
-        self.buf('static struct %s%s %s%s = {\n' %
+        self.buf('static const struct %s%s %s%s = {\n' %
                  (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
         for pname, prop in node.props.items():
             if pname in PROP_IGNORE_LIST or pname[0] == '#':
diff --git a/tools/imx8image.c b/tools/imx8image.c
index 0d856b9..435f308 100644
--- a/tools/imx8image.c
+++ b/tools/imx8image.c
@@ -674,7 +674,7 @@
 			fclose(fd);
 
 			if (header.tag != IVT_HEADER_TAG_B0) {
-				fprintf(stderr, "header tag missmatched \n");
+				fprintf(stderr, "header tag mismatched \n");
 				exit(EXIT_FAILURE);
 			} else {
 				file_off +=