Merge tag 'mips-pull-2019-11-16' of git://git.denx.de/u-boot-mips

- MIPS: mscc: various enhancements for Luton and Ocelot platforms
- MIPS: mscc: added support for Jaguar2 platform
- MIPS: optimised SPL linker script
- MIPS: bcm6368: fix restart flow issues
- MIPS: fixed CONFIG_OF_EMBED warnings for all MIPS boards
- MIPS: mt7688: small fixes and enhancements
- mmc: compile-out write support if disabled
diff --git a/.travis.yml b/.travis.yml
index 321fd79..fc4d5a1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -109,16 +109,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;
@@ -351,7 +344,7 @@
       env:
         - TEST_PY_BD="sandbox"
           BUILDMAN="^sandbox$"
-          TOOLCHAIN="clang"
+          OVERRIDE="clang-7"
     - name: "test/py sandbox_spl"
       env:
         - TEST_PY_BD="sandbox_spl"
diff --git a/MAINTAINERS b/MAINTAINERS
index 3fa5d3e..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
diff --git a/Makefile b/Makefile
index 6aa0896..3be9fc5 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
@@ -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-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/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/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/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/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..cda702d 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,228 +238,286 @@
 	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));
+
+	erase_op.mtd = mtd;
+	erase_op.addr = off;
+	erase_op.len = len;
+	erase_op.scrub = scrub;
 
-		printf("Erasing 0x%08llx ... 0x%08llx (%d eraseblock(s))\n",
-		       off, off + len - 1, mtd_div_by_eb(len, mtd));
+	while (erase_op.len) {
+		ret = mtd_erase(mtd, &erase_op);
 
-		erase_op.mtd = mtd;
-		erase_op.addr = off;
-		erase_op.len = len;
-		erase_op.scrub = scrub;
+		/* Abort if its not a bad block error */
+		if (ret != -EIO)
+			break;
 
-		while (erase_op.len) {
-			ret = mtd_erase(mtd, &erase_op);
+		printf("Skipping bad block at 0x%08llx\n", erase_op.fail_addr);
 
-			/* Abort if its not a bad block error */
-			if (ret != -EIO)
-				break;
+		/* 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;
+	}
 
-			printf("Skipping bad block at 0x%08llx\n",
-			       erase_op.fail_addr);
+	if (ret && ret != -EIO)
+		ret = CMD_RET_FAILURE;
+	else
+		ret = CMD_RET_SUCCESS;
 
-			/* 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;
-		}
+out_put_mtd:
+	put_mtd_device(mtd);
 
-		if (ret && ret != -EIO)
-			return CMD_RET_FAILURE;
-	} else if (!strcmp(cmd, "bad")) {
-		loff_t off;
+	return ret;
+}
 
-		if (!mtd_can_have_bb(mtd)) {
-			printf("Only NAND-based devices can have bad blocks\n");
-			return CMD_RET_SUCCESS;
-		}
+static int do_mtd_bad(cmd_tbl_t *cmdtp, int flag, int argc,
+		      char * const argv[])
+{
+	struct mtd_info *mtd;
+	loff_t off;
 
-		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 {
+	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;
 }
+
+#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 */
 
 static char mtd_help_text[] =
 #ifdef CONFIG_SYS_LONGHELP
@@ -470,4 +545,15 @@
 #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/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_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_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/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/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/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/mt7623n_bpir2_defconfig b/configs/mt7623n_bpir2_defconfig
index ae4fb28..8cb4907 100644
--- a/configs/mt7623n_bpir2_defconfig
+++ b/configs/mt7623n_bpir2_defconfig
@@ -26,8 +26,9 @@
 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_REGMAP=y
 CONFIG_SYSCON=y
 # CONFIG_BLOCK_CACHE is not set
@@ -37,6 +38,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/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/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/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/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/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/i2c/Kconfig b/drivers/i2c/Kconfig
index 1ef22e6..7579eb8 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -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/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/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/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/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/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..b3dec82 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, 0x0, 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..5129c83 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,8 @@
 #define CONFIG_EXTRA_ENV_SETTINGS	\
 	FDT_HIGH
 
+/* Ethernet */
+#define CONFIG_IPADDR			192.168.1.1
+#define CONFIG_SERVERIP			192.168.1.2
+
 #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/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/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 +=