Merge https://gitlab.denx.de/u-boot/custodians/u-boot-fsl-qoriq

- Bug fixes and updates on ls2088a,ls1028a, ls1046a, ls1043a, ls1012a
- lx2-watchdog support
- layerscape: pci-endpoint support, spin table relocation fixes and
  cleanups
- fsl-crypto: RNG support and bug fixes
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 303857c..9ba9f1d 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -158,7 +158,7 @@
           ./tools/binman/binman --toolpath ${UBOOT_TRAVIS_BUILD_DIR}/tools test
           ./tools/buildman/buildman -t
           ./tools/dtoc/dtoc -t
-          ./tools/patman/patman --test
+          ./tools/patman/patman test
           make O=${UBOOT_TRAVIS_BUILD_DIR} testconfig
           EOF
           cat build.sh
diff --git a/.gitignore b/.gitignore
index 2e1c8bf..e66aa86 100644
--- a/.gitignore
+++ b/.gitignore
@@ -92,3 +92,6 @@
 *.orig
 *~
 \#*#
+
+# Python cache
+__pycache__
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e8ad3f4..43f9d3b 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -169,7 +169,7 @@
       ./tools/binman/binman --toolpath ${UBOOT_TRAVIS_BUILD_DIR}/tools test;
       ./tools/buildman/buildman -t;
       ./tools/dtoc/dtoc -t;
-      ./tools/patman/patman --test;
+      ./tools/patman/patman test;
       make testconfig
 
 Run tests for Nokia RX-51 (aka N900):
diff --git a/.travis.yml b/.travis.yml
index 96fd55f..66ccf5b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -23,7 +23,6 @@
     - build-essential
     - libsdl2-dev
     - python
-    - python-pyelftools
     - python3-sphinx
     - python3-virtualenv
     - python3-pip
@@ -256,8 +255,9 @@
      if [[ -n "${TEST_PY_TOOLS}" ]]; then
        export PYTHONPATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc/pylibfdt";
        export PATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc:${PATH}";
+       pip install pyelftools &&
        ./tools/binman/binman --toolpath ${UBOOT_TRAVIS_BUILD_DIR}/tools test &&
-       ./tools/patman/patman --test &&
+       ./tools/patman/patman test &&
        ./tools/buildman/buildman -t &&
        ./tools/dtoc/dtoc -t &&
        make testconfig;
diff --git a/README b/README
index 2384966..7ab7e37 100644
--- a/README
+++ b/README
@@ -871,9 +871,6 @@
 		Allow generic access to the SPI bus on the Intel 8257x, for
 		example with the "sspi" command.
 
-		CONFIG_TULIP
-		Support for Digital 2114x chips.
-
 		CONFIG_NATSEMI
 		Support for National dp83815 chips.
 
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 5726156..f01eb7b 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -774,6 +774,7 @@
 	r8a7794-silk-u-boot.dtb
 
 dtb-$(CONFIG_RCAR_GEN3) += \
+	r8a774a1-beacon-rzg2m-kit.dtb \
 	r8a77950-ulcb-u-boot.dtb \
 	r8a77950-salvator-x-u-boot.dtb \
 	r8a77960-ulcb-u-boot.dtb \
diff --git a/arch/arm/dts/beacon-renesom-baseboard.dtsi b/arch/arm/dts/beacon-renesom-baseboard.dtsi
new file mode 100644
index 0000000..8a472c0
--- /dev/null
+++ b/arch/arm/dts/beacon-renesom-baseboard.dtsi
@@ -0,0 +1,597 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2020, Compass Electronics Group, LLC
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	aliases {
+		serial0 = &scif2;
+		serial1 = &hscif0;
+		serial2 = &hscif1;
+		serial3 = &scif0;
+		serial4 = &hscif2;
+		serial5 = &scif5;
+		spi0 = &msiof0;
+		spi1 = &msiof1;
+		spi2 = &msiof2;
+		spi3 = &msiof3;
+		ethernet0 = &avb;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		power-supply = <&reg_lcd>;
+		enable-gpios = <&gpio_exp1 3 GPIO_ACTIVE_HIGH>;
+		pwms = <&pwm0 0 50000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+	};
+
+	hdmi0-out {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi0_con: endpoint {
+				remote-endpoint = <&rcar_dw_hdmi0_out>;
+			};
+		};
+	};
+
+	keys {
+		compatible = "gpio-keys";
+
+		key-1 {
+			gpios = <&gpio4 6 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_1>;
+			label = "Switch-1";
+			wakeup-source;
+			debounce-interval = <20>;
+		};
+		key-2 {
+			gpios = <&gpio3 13 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_2>;
+			label = "Switch-2";
+			wakeup-source;
+			debounce-interval = <20>;
+		};
+		key-3 {
+			gpios = <&gpio5 17 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_3>;
+			label = "Switch-3";
+			wakeup-source;
+			debounce-interval = <20>;
+		};
+		key-4 {
+			gpios = <&gpio5 20 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_4>;
+			label = "Switch-4";
+			wakeup-source;
+			debounce-interval = <20>;
+		};
+		key-5 {
+			gpios = <&gpio5 22 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_5>;
+			label = "Switch-4";
+			wakeup-source;
+			debounce-interval = <20>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-0 = <&led_pins>;
+		pinctrl-names = "default";
+
+		led0 {
+			gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
+			label = "LED0";
+			linux,default-trigger = "heartbeat";
+		};
+		led1 {
+			gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>;
+			label = "LED1";
+			linux,default-trigger = "heartbeat";
+		};
+		led2 {
+			gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
+			label = "LED2";
+			linux,default-trigger = "heartbeat";
+		};
+		led3 {
+			gpios = <&gpio7 3 GPIO_ACTIVE_HIGH>;
+			label = "LED3";
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	reg_audio: regulator_audio {
+		compatible = "regulator-fixed";
+		regulator-name = "audio-1.8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		gpio = <&gpio_exp2 7 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_lcd: regulator-lcd {
+		compatible = "regulator-fixed";
+		regulator-name = "lcd_panel_pwr";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio_exp1 1 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_lcd_reset: regulator-lcd-reset {
+		compatible = "regulator-fixed";
+		regulator-name = "nLCD_RESET";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio5 3 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		vin-supply = <&reg_lcd>;
+	};
+
+	reg_cam0: regulator_camera {
+		compatible = "regulator-fixed";
+		regulator-name = "reg_cam0";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		gpio = <&gpio_exp2 2 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_cam1: regulator_camera {
+		compatible = "regulator-fixed";
+		regulator-name = "reg_cam1";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		gpio = <&gpio_exp2 5 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		startup-delay-us = <100000>;
+	};
+
+	sound_card {
+		compatible = "audio-graph-card";
+		label = "rcar-sound";
+		dais = <&rsnd_port0>, <&rsnd_port1>;
+	};
+
+	vccq_sdhi0: regulator-vccq-sdhi0 {
+		compatible = "regulator-gpio";
+
+		regulator-name = "SDHI0 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio6 30 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <3300000 1>, <1800000 0>;
+		regulator-always-on;
+	};
+
+	/* External DU dot clocks */
+	x302_clk: x302-clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <33000000>;
+	};
+
+	x304_clk: x304-clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+};
+
+&audio_clk_a {
+	clock-frequency = <22579200>;
+};
+
+&audio_clk_b {
+	clock-frequency = <22579200>;
+};
+
+&can0 {
+	pinctrl-0 = <&can0_pins>;
+	pinctrl-names = "default";
+	renesas,can-clock-select = <0x0>;
+	status = "okay";
+};
+
+&can1 {
+	pinctrl-0 = <&can1_pins>;
+	pinctrl-names = "default";
+	renesas,can-clock-select = <0x0>;
+	status = "okay";
+};
+
+&du {
+	pinctrl-0 = <&du_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	clocks = <&cpg CPG_MOD 724>,
+		<&cpg CPG_MOD 723>,
+		<&cpg CPG_MOD 722>,
+		<&versaclock5 1>,
+		<&x302_clk>,
+		<&versaclock5 2>;
+	clock-names = "du.0", "du.1", "du.2",
+		"dclkin.0", "dclkin.1", "dclkin.2";
+};
+
+&ehci0 {
+	dr_mode = "otg";
+	status = "okay";
+	clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>, <&versaclock5 3>, <&versaclock6_bb 4>;
+};
+
+&ehci1 {
+	status = "okay";
+	clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>, <&versaclock5 4>;
+};
+
+&hdmi0 {
+	status = "okay";
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		port@0 {
+			reg = <0>;
+			dw_hdmi0_in: endpoint {
+				remote-endpoint = <&du_out_hdmi0>;
+			};
+		};
+		port@1 {
+			reg = <1>;
+			rcar_dw_hdmi0_out: endpoint {
+				remote-endpoint = <&hdmi0_con>;
+			};
+		};
+		port@2 {
+			/* HDMI sound */
+			reg = <2>;
+			dw_hdmi0_snd_in: endpoint {
+				remote-endpoint = <&rsnd_endpoint1>;
+			};
+		};
+	};
+};
+
+&hscif1 {
+	pinctrl-0 = <&hscif1_pins>;
+	pinctrl-names = "default";
+	uart-has-rtscts;
+	status = "okay";
+};
+
+&hsusb {
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&i2c2 {
+	status = "okay";
+	clock-frequency = <100000>;
+	pinctrl-0 = <&i2c2_pins>;
+	pinctrl-names = "default";
+
+	gpio_exp2: gpio@21 {
+		compatible = "onnn,pca9654";
+		reg = <0x21>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	gpio_exp3: gpio@22 {
+		compatible = "onnn,pca9654";
+		reg = <0x22>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	versaclock6_bb: versaclock6_bb@6a {
+		compatible = "idt,5p49v6965";
+		reg = <0x6a>;
+		#clock-cells = <1>;
+		clocks = <&x304_clk>;
+		clock-names = "xin";
+		/* CSI0_MCLK, CSI1_MCLK, AUDIO_CLKIN, USB_HUB_MCLK_BB */
+		assigned-clocks = <&versaclock6_bb 1>,
+				   <&versaclock6_bb 2>,
+				   <&versaclock6_bb 3>,
+				   <&versaclock6_bb 4>;
+		assigned-clock-rates =	<24000000>, <24000000>, <24000000>, <24000000>;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	pinctrl-0 = <&i2c0_pins>;
+	pinctrl-names = "default";
+};
+
+&i2c5 {
+	status = "okay";
+	clock-frequency = <100000>;
+	pinctrl-0 = <&i2c5_pins>;
+	pinctrl-names = "default";
+
+	codec: wm8962@1a {
+		compatible = "wlf,wm8962";
+		reg = <0x1a>;
+		DCVDD-supply = <&reg_audio>;
+		DBVDD-supply = <&reg_audio>;
+		AVDD-supply = <&reg_audio>;
+		CPVDD-supply = <&reg_audio>;
+		MICVDD-supply = <&reg_audio>;
+		PLLVDD-supply = <&reg_audio>;
+		SPKVDD1-supply = <&reg_audio>;
+		SPKVDD2-supply = <&reg_audio>;
+		gpio-cfg = <
+			0x0000 /* 0:Default */
+			0x0000 /* 1:Default */
+			0x0000 /* 2:Default */
+			0x0000 /* 3:Default */
+			0x0000 /* 4:Default */
+			0x0000 /* 5:Default */
+		>;
+		port {
+			wm8962_endpoint: endpoint {
+				remote-endpoint = <&rsnd_endpoint0>;
+			};
+		};
+	};
+
+	/* 0 - lcd_reset */
+	/* 1 - lcd_pwr */
+	/* 2 - lcd_select */
+	/* 3 - backlight-enable */
+	/* 4 - Touch_shdwn */
+	/* 5 - LCD_H_pol */
+	/* 6 - lcd_V_pol */
+	gpio_exp1: gpio@20 {
+		compatible = "onnn,pca9654";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	touchscreen@26 {
+		compatible = "ilitek,ili2117";
+		reg = <0x26>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+		wakeup-source;
+	};
+};
+
+&ohci0 {
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&pciec0 {
+	status = "okay";
+};
+
+&pciec1 {
+	status = "okay";
+};
+
+&pcie_bus_clk {
+	clock-frequency = <100000000>;
+};
+
+&pfc {
+	can0_pins: can0 {
+		groups = "can0_data_a";
+		function = "can0";
+	};
+
+	can1_pins: can1 {
+		groups = "can1_data";
+		function = "can1";
+	};
+
+	du_pins: du {
+		groups = "du_rgb888", "du_sync", "du_clk_out_1", "du_disp";
+		function = "du";
+	};
+
+	i2c2_pins: i2c2 {
+		groups = "i2c2_a";
+		function = "i2c2";
+	};
+
+	i2c5_pins: i2c5 {
+		groups = "i2c5";
+		function = "i2c5";
+	};
+
+	led_pins: leds {
+		/* GP_0_4 , AVS1, AVS2, GP_7_3 */
+		pins = "GP_0_4", "GP_7_0", "GP_7_1", "GP_7_3";
+		bias-pull-down;
+	};
+
+	msiof1_pins: msiof1 {
+		groups = "msiof1_clk_g", "msiof1_rxd_g", "msiof1_txd_g";
+		function = "msiof1";
+	};
+
+	pwm0_pins: pwm0 {
+		groups = "pwm0";
+		function = "pwm0";
+	};
+
+	sdhi0_pins: sd0 {
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
+		power-source = <3300>;
+	};
+
+	sdhi0_pins_uhs: sd0_uhs {
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
+		power-source = <1800>;
+	};
+
+	sound_pins: sound {
+		groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a";
+		function = "ssi";
+	};
+
+	sound_clk_pins: sound_clk {
+		groups = "audio_clk_a_a";
+		function = "audio_clk";
+	};
+
+	usb0_pins: usb0 {
+		mux {
+			groups = "usb0";
+			function = "usb0";
+		};
+	};
+
+	usb1_pins: usb1 {
+		mux {
+			groups = "usb1";
+			function = "usb1";
+		};
+	};
+
+	usb30_pins: usb30 {
+		mux {
+			groups = "usb30";
+			function = "usb30";
+		};
+	};
+};
+
+&pwm0 {
+	pinctrl-0 = <&pwm0_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&rcar_sound {
+	pinctrl-0 = <&sound_pins &sound_clk_pins>;
+	pinctrl-names = "default";
+
+	/* Single DAI */
+	#sound-dai-cells = <0>;
+
+	/* audio_clkout0/1/2/3 */
+	#clock-cells = <1>;
+	clock-frequency = <11289600>;
+
+	status = "okay";
+
+	clocks = <&cpg CPG_MOD 1005>,
+		 <&cpg CPG_MOD 1006>, <&cpg CPG_MOD 1007>,
+		 <&cpg CPG_MOD 1008>, <&cpg CPG_MOD 1009>,
+		 <&cpg CPG_MOD 1010>, <&cpg CPG_MOD 1011>,
+		 <&cpg CPG_MOD 1012>, <&cpg CPG_MOD 1013>,
+		 <&cpg CPG_MOD 1014>, <&cpg CPG_MOD 1015>,
+		 <&cpg CPG_MOD 1022>, <&cpg CPG_MOD 1023>,
+		 <&cpg CPG_MOD 1024>, <&cpg CPG_MOD 1025>,
+		 <&cpg CPG_MOD 1026>, <&cpg CPG_MOD 1027>,
+		 <&cpg CPG_MOD 1028>, <&cpg CPG_MOD 1029>,
+		 <&cpg CPG_MOD 1030>, <&cpg CPG_MOD 1031>,
+		 <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>,
+		 <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>,
+		 <&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
+		 <&audio_clk_a>, <&audio_clk_b>, <&audio_clk_c>,
+		 <&cpg CPG_CORE R8A774A1_CLK_S0D4>;
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		rsnd_port0: port@0 {
+			reg = <0>;
+			rsnd_endpoint0: endpoint {
+				remote-endpoint = <&wm8962_endpoint>;
+
+				dai-format = "i2s";
+				bitclock-master = <&rsnd_endpoint0>;
+				frame-master = <&rsnd_endpoint0>;
+
+				playback = <&ssi1 &dvc1 &src1>;
+				capture = <&ssi0>;
+			};
+		};
+		rsnd_port1: port@1 {
+		    reg = <0x01>;
+			rsnd_endpoint1: endpoint {
+				remote-endpoint = <&dw_hdmi0_snd_in>;
+
+				dai-format = "i2s";
+				bitclock-master = <&rsnd_endpoint1>;
+				frame-master = <&rsnd_endpoint1>;
+
+				playback = <&ssi2>;
+			};
+		};
+	};
+};
+
+&scif0 {
+	pinctrl-0 = <&scif0_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&scif5 {
+	pinctrl-0 = <&scif5_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&scif_clk {
+	clock-frequency = <14745600>;
+};
+
+&sdhi0 {
+	pinctrl-0 = <&sdhi0_pins>;
+	pinctrl-1 = <&sdhi0_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&vccq_sdhi0>;
+	cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
+	bus-width = <4>;
+	sd-uhs-sdr50;
+	sd-uhs-sdr104;
+	status = "okay";
+};
+
+&ssi1 {
+	shared-pin;
+};
+
+&usb2_phy0 {
+	pinctrl-0 = <&usb0_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&usb2_phy1 {
+	pinctrl-0 = <&usb1_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
diff --git a/arch/arm/dts/beacon-renesom-som.dtsi b/arch/arm/dts/beacon-renesom-som.dtsi
new file mode 100644
index 0000000..6c16a27
--- /dev/null
+++ b/arch/arm/dts/beacon-renesom-som.dtsi
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2020, Compass Electronics Group, LLC
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	memory@48000000 {
+		device_type = "memory";
+		/* first 128MB is reserved for secure area. */
+		reg = <0x0 0x48000000 0x0 0x78000000>;
+	};
+
+	memory@600000000 {
+		device_type = "memory";
+		reg = <0x6 0x00000000 0x0 0x80000000>;
+	};
+
+	osc_32k: osc_32k {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		clock-output-names = "osc_32k";
+	};
+
+	reg_1p8v: regulator0 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-1.8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator1 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	wlan_pwrseq: wlan_pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&pca9654 1 GPIO_ACTIVE_LOW>;
+		clocks = <&osc_32k>;
+		clock-names = "ext_clock";
+		post-power-on-delay-ms = <80>;
+	};
+};
+
+&avb {
+	pinctrl-0 = <&avb_pins>;
+	pinctrl-names = "default";
+	phy-handle = <&phy0>;
+	phy-mode = "rgmii-id";
+	status = "okay";
+
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+		interrupt-parent = <&gpio2>;
+		interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+		reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&extal_clk {
+	clock-frequency = <16666666>;
+};
+
+&extalr_clk {
+	clock-frequency = <32768>;
+};
+
+&gpio6 {
+	usb_hub_reset {
+		gpio-hog;
+		gpios = <10 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "usb-hub-reset";
+	};
+};
+
+&hscif0 {
+	pinctrl-0 = <&hscif0_pins>;
+	pinctrl-names = "default";
+	uart-has-rtscts;
+	status = "okay";
+	max-speed = <4000000>;
+
+	bluetooth {
+		compatible = "brcm,bcm43438-bt";
+		shutdown-gpios = <&pca9654 2 GPIO_ACTIVE_HIGH>;
+		host-wakeup-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+		device-wakeup-gpios = <&pca9654 5 GPIO_ACTIVE_HIGH>;
+		clocks = <&osc_32k>;
+		clock-names = "extclk";
+	};
+};
+
+&hscif2 {
+	status = "okay";
+	pinctrl-0 = <&hscif2_pins>;
+	pinctrl-names = "default";
+};
+
+&i2c4 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	pca9654: gpio@20 {
+		compatible = "onnn,pca9654";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names =
+			"i2c4_20_0",
+			"wl_reg_on",
+			"bt_reg_on",
+			"i2c4_20_3",
+			"i2c4_20_4",
+			"bt_dev_wake",
+			"i2c4_20_6",
+			"i2c4_20_7";
+	};
+
+	pca9654_lte: gpio@21 {
+		compatible = "onnn,pca9654";
+		reg = <0x21>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names =
+			"i2c4_21_0",
+			"zoe_pwr_on",
+			"zoe_extint",
+			"zoe_reset_n",
+			"sara_reset",
+			"i2c4_21_5",
+			"sara_pwr_off",
+			"sara_networking_status";
+	};
+
+	eeprom@50 {
+		compatible = "microchip, at24c64", "atmel,24c64";
+		pagesize = <32>;
+		read-only;	/* Manufacturing EEPROM programmed at factory */
+		reg = <0x50>;
+	};
+
+	rtc@51 {
+		compatible = "nxp,pcf85263";
+		reg = <0x51>;
+	};
+
+	versaclock5: versaclock_som@6a {
+		compatible = "idt,5p49v6965";
+		reg = <0x6a>;
+		#clock-cells = <1>;
+		clocks = <&x304_clk>;
+		clock-names = "xin";
+		/* du_dotclkin0, du_dotclkin2, usb_extal, avb_txcrefclk */
+		assigned-clocks = <&versaclock5 1>,
+				   <&versaclock5 2>,
+				   <&versaclock5 3>,
+				   <&versaclock5 4>;
+		assigned-clock-rates = <33333333>, <33333333>, <50000000>, <125000000>;
+	};
+};
+
+&pfc {
+	pinctrl-0 = <&scif_clk_pins>;
+	pinctrl-names = "default";
+
+	avb_pins: avb {
+		mux {
+			groups = "avb_link", "avb_mdio", "avb_mii";
+			function = "avb";
+		};
+
+		pins_mdio {
+			groups = "avb_mdio";
+			drive-strength = <24>;
+		};
+
+		pins_mii_tx {
+			pins = "PIN_AVB_TX_CTL", "PIN_AVB_TXC", "PIN_AVB_TD0",
+			       "PIN_AVB_TD1", "PIN_AVB_TD2", "PIN_AVB_TD3";
+			drive-strength = <12>;
+		};
+	};
+
+	scif2_pins: scif2 {
+		groups = "scif2_data_a";
+		function = "scif2";
+	};
+
+	hscif0_pins: hscif0 {
+		groups = "hscif0_data", "hscif0_ctrl";
+		function = "hscif0";
+	};
+
+	hscif1_pins: hscif1 {
+		groups = "hscif1_data_a", "hscif1_ctrl_a";
+		function = "hscif1";
+	};
+
+	hscif2_pins: hscif2 {
+		groups = "hscif2_data_a";
+		function = "hscif2";
+	};
+
+	scif0_pins: scif0 {
+		groups = "scif0_data";
+		function = "scif0";
+	};
+
+	scif5_pins: scif5 {
+		groups = "scif5_data_a";
+		function = "scif5";
+	};
+
+	scif_clk_pins: scif_clk {
+		groups = "scif_clk_a";
+		function = "scif_clk";
+	};
+
+	i2c0_pins: i2c0 {
+		groups = "i2c0";
+		function = "i2c0";
+	};
+
+	sdhi2_pins: sd2 {
+		groups = "sdhi2_data4", "sdhi2_ctrl";
+		function = "sdhi2";
+		power-source = <1800>;
+	};
+
+	sdhi3_pins: sd3 {
+		groups = "sdhi3_data8", "sdhi3_ctrl", "sdhi3_ds";
+		function = "sdhi3";
+		power-source = <1800>;
+	};
+};
+
+&scif_clk {
+	clock-frequency = <14745600>;
+};
+
+&scif2 {
+	pinctrl-0 = <&scif2_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&sdhi2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdhi2_pins>;
+	bus-width = <4>;
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&reg_1p8v>;
+	non-removable;
+	cap-power-off-card;
+	pm-ignore-notify;
+	keep-power-in-suspend;
+	mmc-pwrseq = <&wlan_pwrseq>;
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	brcmf: bcrmf@1 {
+		reg = <1>;
+		compatible = "brcm,bcm4329-fmac";
+		interrupt-parent = <&gpio1>;
+		interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-names = "host-wake";
+	};
+};
+
+&sdhi3 {
+	pinctrl-0 = <&sdhi3_pins>;
+	pinctrl-1 = <&sdhi3_pins>;
+	pinctrl-names = "default", "state_uhs";
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&reg_1p8v>;
+	bus-width = <8>;
+	mmc-hs200-1_8v;
+	non-removable;
+	fixed-emmc-driver-type = <1>;
+	status = "okay";
+};
+
+&usb_extal_clk {
+	clock-frequency = <50000000>;
+};
+
+&usb3s0_clk {
+	clock-frequency = <100000000>;
+};
+
+&vspb {
+	status = "okay";
+};
+
+&vspi0 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/k3-am65-wakeup.dtsi b/arch/arm/dts/k3-am65-wakeup.dtsi
index 2676d60..666c30d 100644
--- a/arch/arm/dts/k3-am65-wakeup.dtsi
+++ b/arch/arm/dts/k3-am65-wakeup.dtsi
@@ -62,4 +62,9 @@
 		clocks = <&k3_clks 115 1>;
 		power-domains = <&k3_pds 115 TI_SCI_PD_EXCLUSIVE>;
 	};
+
+	chipid: chipid@43000014 {
+		compatible = "ti,am654-chipid";
+		reg = <0x43000014 0x4>;
+	};
 };
diff --git a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi
index d9ff3ed4..a30680d 100644
--- a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi
+++ b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi
@@ -246,3 +246,7 @@
 		u-boot,dm-spl;
 	};
 };
+
+&chipid {
+	u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/k3-j721e-common-proc-board-u-boot.dtsi b/arch/arm/dts/k3-j721e-common-proc-board-u-boot.dtsi
index 6e748bf..cfb3932 100644
--- a/arch/arm/dts/k3-j721e-common-proc-board-u-boot.dtsi
+++ b/arch/arm/dts/k3-j721e-common-proc-board-u-boot.dtsi
@@ -211,3 +211,7 @@
 &mcu_fss0_ospi1_pins_default {
 	u-boot,dm-spl;
 };
+
+&chipid {
+	u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/k3-j721e-mcu-wakeup.dtsi b/arch/arm/dts/k3-j721e-mcu-wakeup.dtsi
index e6c99ab..60695f5 100644
--- a/arch/arm/dts/k3-j721e-mcu-wakeup.dtsi
+++ b/arch/arm/dts/k3-j721e-mcu-wakeup.dtsi
@@ -316,4 +316,9 @@
 			ti,cpts-periodic-outputs = <2>;
 		};
 	};
+
+	chipid: chipid@43000014 {
+		compatible = "ti,am654-chipid";
+		reg = <0x0 0x43000014 0x0 0x4>;
+	};
 };
diff --git a/arch/arm/dts/r8a774a1-beacon-rzg2m-kit-u-boot.dtsi b/arch/arm/dts/r8a774a1-beacon-rzg2m-kit-u-boot.dtsi
new file mode 100644
index 0000000..a0c0a7f
--- /dev/null
+++ b/arch/arm/dts/r8a774a1-beacon-rzg2m-kit-u-boot.dtsi
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2020 Compass Electronics Group, LLC
+ */
+
+/ {
+	soc {
+		u-boot,dm-pre-reloc;
+	};
+};
+
+&cpg {
+	u-boot,dm-pre-reloc;
+};
+
+&extal_clk {
+	u-boot,dm-pre-reloc;
+};
+
+&prr {
+	u-boot,dm-pre-reloc;
+};
+
+&extalr_clk {
+	u-boot,dm-pre-reloc;
+};
+
+&sdhi0 {
+	/delete-property/ cd-gpios;
+};
+
+&sdhi2 {
+	status = "disabled";
+};
diff --git a/arch/arm/dts/r8a774a1-beacon-rzg2m-kit.dts b/arch/arm/dts/r8a774a1-beacon-rzg2m-kit.dts
new file mode 100644
index 0000000..e7ed5d4
--- /dev/null
+++ b/arch/arm/dts/r8a774a1-beacon-rzg2m-kit.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2020, Compass Electronics Group, LLC
+ */
+
+/dts-v1/;
+
+#include "r8a774a1.dtsi"
+#include "beacon-renesom-som.dtsi"
+#include "beacon-renesom-baseboard.dtsi"
+
+/ {
+	model = "Beacon Embedded Works RZ/G2M Development Kit";
+	compatible =	"beacon,beacon-rzg2m", "renesas,r8a774a1";
+};
diff --git a/arch/arm/dts/r8a774a1.dtsi b/arch/arm/dts/r8a774a1.dtsi
new file mode 100644
index 0000000..a603d94
--- /dev/null
+++ b/arch/arm/dts/r8a774a1.dtsi
@@ -0,0 +1,2787 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the r8a774a1 SoC
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/r8a774a1-cpg-mssr.h>
+#include <dt-bindings/power/r8a774a1-sysc.h>
+
+/ {
+	compatible = "renesas,r8a774a1";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		i2c4 = &i2c4;
+		i2c5 = &i2c5;
+		i2c6 = &i2c6;
+		i2c7 = &i2c_dvfs;
+	};
+
+	/*
+	 * The external audio clocks are configured as 0 Hz fixed frequency
+	 * clocks by default.
+	 * Boards that provide audio clocks should override them.
+	 */
+	audio_clk_a: audio_clk_a {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <0>;
+	};
+
+	audio_clk_b: audio_clk_b {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <0>;
+	};
+
+	audio_clk_c: audio_clk_c {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <0>;
+	};
+
+	/* External CAN clock - to be overridden by boards that provide it */
+	can_clk: can {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <0>;
+	};
+
+	cluster0_opp: opp_table0 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp-500000000 {
+			opp-hz = /bits/ 64 <500000000>;
+			opp-microvolt = <820000>;
+			clock-latency-ns = <300000>;
+		};
+		opp-1000000000 {
+			opp-hz = /bits/ 64 <1000000000>;
+			opp-microvolt = <820000>;
+			clock-latency-ns = <300000>;
+		};
+		opp-1500000000 {
+			opp-hz = /bits/ 64 <1500000000>;
+			opp-microvolt = <820000>;
+			clock-latency-ns = <300000>;
+		};
+	};
+
+	cluster1_opp: opp_table1 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp-800000000 {
+			opp-hz = /bits/ 64 <800000000>;
+			opp-microvolt = <820000>;
+			clock-latency-ns = <300000>;
+		};
+		opp-1000000000 {
+			opp-hz = /bits/ 64 <1000000000>;
+			opp-microvolt = <820000>;
+			clock-latency-ns = <300000>;
+		};
+		opp-1200000000 {
+			opp-hz = /bits/ 64 <1200000000>;
+			opp-microvolt = <820000>;
+			clock-latency-ns = <300000>;
+		};
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&a57_0>;
+				};
+				core1 {
+					cpu = <&a57_1>;
+				};
+			};
+
+			cluster1 {
+				core0 {
+					cpu = <&a53_0>;
+				};
+				core1 {
+					cpu = <&a53_1>;
+				};
+				core2 {
+					cpu = <&a53_2>;
+				};
+				core3 {
+					cpu = <&a53_3>;
+				};
+			};
+		};
+
+		a57_0: cpu@0 {
+			compatible = "arm,cortex-a57";
+			reg = <0x0>;
+			device_type = "cpu";
+			power-domains = <&sysc R8A774A1_PD_CA57_CPU0>;
+			next-level-cache = <&L2_CA57>;
+			enable-method = "psci";
+			dynamic-power-coefficient = <854>;
+			clocks = <&cpg CPG_CORE R8A774A1_CLK_Z>;
+			operating-points-v2 = <&cluster0_opp>;
+			capacity-dmips-mhz = <1024>;
+			#cooling-cells = <2>;
+		};
+
+		a57_1: cpu@1 {
+			compatible = "arm,cortex-a57";
+			reg = <0x1>;
+			device_type = "cpu";
+			power-domains = <&sysc R8A774A1_PD_CA57_CPU1>;
+			next-level-cache = <&L2_CA57>;
+			enable-method = "psci";
+			clocks = <&cpg CPG_CORE R8A774A1_CLK_Z>;
+			operating-points-v2 = <&cluster0_opp>;
+			capacity-dmips-mhz = <1024>;
+			#cooling-cells = <2>;
+		};
+
+		a53_0: cpu@100 {
+			compatible = "arm,cortex-a53";
+			reg = <0x100>;
+			device_type = "cpu";
+			power-domains = <&sysc R8A774A1_PD_CA53_CPU0>;
+			next-level-cache = <&L2_CA53>;
+			enable-method = "psci";
+			#cooling-cells = <2>;
+			dynamic-power-coefficient = <277>;
+			clocks = <&cpg CPG_CORE R8A774A1_CLK_Z2>;
+			operating-points-v2 = <&cluster1_opp>;
+			capacity-dmips-mhz = <560>;
+		};
+
+		a53_1: cpu@101 {
+			compatible = "arm,cortex-a53";
+			reg = <0x101>;
+			device_type = "cpu";
+			power-domains = <&sysc R8A774A1_PD_CA53_CPU1>;
+			next-level-cache = <&L2_CA53>;
+			enable-method = "psci";
+			clocks = <&cpg CPG_CORE R8A774A1_CLK_Z2>;
+			operating-points-v2 = <&cluster1_opp>;
+			capacity-dmips-mhz = <560>;
+		};
+
+		a53_2: cpu@102 {
+			compatible = "arm,cortex-a53";
+			reg = <0x102>;
+			device_type = "cpu";
+			power-domains = <&sysc R8A774A1_PD_CA53_CPU2>;
+			next-level-cache = <&L2_CA53>;
+			enable-method = "psci";
+			clocks = <&cpg CPG_CORE R8A774A1_CLK_Z2>;
+			operating-points-v2 = <&cluster1_opp>;
+			capacity-dmips-mhz = <560>;
+		};
+
+		a53_3: cpu@103 {
+			compatible = "arm,cortex-a53";
+			reg = <0x103>;
+			device_type = "cpu";
+			power-domains = <&sysc R8A774A1_PD_CA53_CPU3>;
+			next-level-cache = <&L2_CA53>;
+			enable-method = "psci";
+			clocks = <&cpg CPG_CORE R8A774A1_CLK_Z2>;
+			operating-points-v2 = <&cluster1_opp>;
+			capacity-dmips-mhz = <560>;
+		};
+
+		L2_CA57: cache-controller-0 {
+			compatible = "cache";
+			power-domains = <&sysc R8A774A1_PD_CA57_SCU>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		L2_CA53: cache-controller-1 {
+			compatible = "cache";
+			power-domains = <&sysc R8A774A1_PD_CA53_SCU>;
+			cache-unified;
+			cache-level = <2>;
+		};
+	};
+
+	extal_clk: extal {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board */
+		clock-frequency = <0>;
+	};
+
+	extalr_clk: extalr {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board */
+		clock-frequency = <0>;
+	};
+
+	/* External PCIe clock - can be overridden by the board */
+	pcie_bus_clk: pcie_bus {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <0>;
+	};
+
+	pmu_a53 {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts-extended = <&gic GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
+				      <&gic GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
+				      <&gic GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>,
+				      <&gic GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&a53_0>, <&a53_1>, <&a53_2>, <&a53_3>;
+	};
+
+	pmu_a57 {
+		compatible = "arm,cortex-a57-pmu";
+		interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+				      <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&a57_0>, <&a57_1>;
+	};
+
+	psci {
+		compatible = "arm,psci-1.0", "arm,psci-0.2";
+		method = "smc";
+	};
+
+	/* External SCIF clock - to be overridden by boards that provide it */
+	scif_clk: scif {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <0>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		interrupt-parent = <&gic>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		rwdt: watchdog@e6020000 {
+			compatible = "renesas,r8a774a1-wdt",
+				     "renesas,rcar-gen3-wdt";
+			reg = <0 0xe6020000 0 0x0c>;
+			clocks = <&cpg CPG_MOD 402>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 402>;
+			status = "disabled";
+		};
+
+		gpio0: gpio@e6050000 {
+			compatible = "renesas,gpio-r8a774a1",
+				     "renesas,rcar-gen3-gpio";
+			reg = <0 0xe6050000 0 0x50>;
+			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+			#gpio-cells = <2>;
+			gpio-controller;
+			gpio-ranges = <&pfc 0 0 16>;
+			#interrupt-cells = <2>;
+			interrupt-controller;
+			clocks = <&cpg CPG_MOD 912>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 912>;
+		};
+
+		gpio1: gpio@e6051000 {
+			compatible = "renesas,gpio-r8a774a1",
+				     "renesas,rcar-gen3-gpio";
+			reg = <0 0xe6051000 0 0x50>;
+			interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+			#gpio-cells = <2>;
+			gpio-controller;
+			gpio-ranges = <&pfc 0 32 29>;
+			#interrupt-cells = <2>;
+			interrupt-controller;
+			clocks = <&cpg CPG_MOD 911>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 911>;
+		};
+
+		gpio2: gpio@e6052000 {
+			compatible = "renesas,gpio-r8a774a1",
+				     "renesas,rcar-gen3-gpio";
+			reg = <0 0xe6052000 0 0x50>;
+			interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+			#gpio-cells = <2>;
+			gpio-controller;
+			gpio-ranges = <&pfc 0 64 15>;
+			#interrupt-cells = <2>;
+			interrupt-controller;
+			clocks = <&cpg CPG_MOD 910>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 910>;
+		};
+
+		gpio3: gpio@e6053000 {
+			compatible = "renesas,gpio-r8a774a1",
+				     "renesas,rcar-gen3-gpio";
+			reg = <0 0xe6053000 0 0x50>;
+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+			#gpio-cells = <2>;
+			gpio-controller;
+			gpio-ranges = <&pfc 0 96 16>;
+			#interrupt-cells = <2>;
+			interrupt-controller;
+			clocks = <&cpg CPG_MOD 909>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 909>;
+		};
+
+		gpio4: gpio@e6054000 {
+			compatible = "renesas,gpio-r8a774a1",
+				     "renesas,rcar-gen3-gpio";
+			reg = <0 0xe6054000 0 0x50>;
+			interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+			#gpio-cells = <2>;
+			gpio-controller;
+			gpio-ranges = <&pfc 0 128 18>;
+			#interrupt-cells = <2>;
+			interrupt-controller;
+			clocks = <&cpg CPG_MOD 908>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 908>;
+		};
+
+		gpio5: gpio@e6055000 {
+			compatible = "renesas,gpio-r8a774a1",
+				     "renesas,rcar-gen3-gpio";
+			reg = <0 0xe6055000 0 0x50>;
+			interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+			#gpio-cells = <2>;
+			gpio-controller;
+			gpio-ranges = <&pfc 0 160 26>;
+			#interrupt-cells = <2>;
+			interrupt-controller;
+			clocks = <&cpg CPG_MOD 907>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 907>;
+		};
+
+		gpio6: gpio@e6055400 {
+			compatible = "renesas,gpio-r8a774a1",
+				     "renesas,rcar-gen3-gpio";
+			reg = <0 0xe6055400 0 0x50>;
+			interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+			#gpio-cells = <2>;
+			gpio-controller;
+			gpio-ranges = <&pfc 0 192 32>;
+			#interrupt-cells = <2>;
+			interrupt-controller;
+			clocks = <&cpg CPG_MOD 906>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 906>;
+		};
+
+		gpio7: gpio@e6055800 {
+			compatible = "renesas,gpio-r8a774a1",
+				     "renesas,rcar-gen3-gpio";
+			reg = <0 0xe6055800 0 0x50>;
+			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+			#gpio-cells = <2>;
+			gpio-controller;
+			gpio-ranges = <&pfc 0 224 4>;
+			#interrupt-cells = <2>;
+			interrupt-controller;
+			clocks = <&cpg CPG_MOD 905>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 905>;
+		};
+
+		pfc: pin-controller@e6060000 {
+			compatible = "renesas,pfc-r8a774a1";
+			reg = <0 0xe6060000 0 0x50c>;
+		};
+
+		cmt0: timer@e60f0000 {
+			compatible = "renesas,r8a774a1-cmt0",
+				     "renesas,rcar-gen3-cmt0";
+			reg = <0 0xe60f0000 0 0x1004>;
+			interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 303>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 303>;
+			status = "disabled";
+		};
+
+		cmt1: timer@e6130000 {
+			compatible = "renesas,r8a774a1-cmt1",
+				     "renesas,rcar-gen3-cmt1";
+			reg = <0 0xe6130000 0 0x1004>;
+			interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 302>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 302>;
+			status = "disabled";
+		};
+
+		cmt2: timer@e6140000 {
+			compatible = "renesas,r8a774a1-cmt1",
+				     "renesas,rcar-gen3-cmt1";
+			reg = <0 0xe6140000 0 0x1004>;
+			interrupts = <GIC_SPI 398 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 399 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 401 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 402 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 403 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 405 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 301>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 301>;
+			status = "disabled";
+		};
+
+		cmt3: timer@e6148000 {
+			compatible = "renesas,r8a774a1-cmt1",
+				     "renesas,rcar-gen3-cmt1";
+			reg = <0 0xe6148000 0 0x1004>;
+			interrupts = <GIC_SPI 470 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 471 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 475 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 476 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 477 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 300>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 300>;
+			status = "disabled";
+		};
+
+		cpg: clock-controller@e6150000 {
+			compatible = "renesas,r8a774a1-cpg-mssr";
+			reg = <0 0xe6150000 0 0x0bb0>;
+			clocks = <&extal_clk>, <&extalr_clk>;
+			clock-names = "extal", "extalr";
+			#clock-cells = <2>;
+			#power-domain-cells = <0>;
+			#reset-cells = <1>;
+		};
+
+		rst: reset-controller@e6160000 {
+			compatible = "renesas,r8a774a1-rst";
+			reg = <0 0xe6160000 0 0x018c>;
+		};
+
+		sysc: system-controller@e6180000 {
+			compatible = "renesas,r8a774a1-sysc";
+			reg = <0 0xe6180000 0 0x0400>;
+			#power-domain-cells = <1>;
+		};
+
+		tsc: thermal@e6198000 {
+			compatible = "renesas,r8a774a1-thermal";
+			reg = <0 0xe6198000 0 0x100>,
+			      <0 0xe61a0000 0 0x100>,
+			      <0 0xe61a8000 0 0x100>;
+			interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 522>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 522>;
+			#thermal-sensor-cells = <1>;
+		};
+
+		intc_ex: interrupt-controller@e61c0000 {
+			compatible = "renesas,intc-ex-r8a774a1", "renesas,irqc";
+			#interrupt-cells = <2>;
+			interrupt-controller;
+			reg = <0 0xe61c0000 0 0x200>;
+			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 407>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 407>;
+		};
+
+		tmu0: timer@e61e0000 {
+			compatible = "renesas,tmu-r8a774a1", "renesas,tmu";
+			reg = <0 0xe61e0000 0 0x30>;
+			interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 125>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 125>;
+			status = "disabled";
+		};
+
+		tmu1: timer@e6fc0000 {
+			compatible = "renesas,tmu-r8a774a1", "renesas,tmu";
+			reg = <0 0xe6fc0000 0 0x30>;
+			interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 124>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 124>;
+			status = "disabled";
+		};
+
+		tmu2: timer@e6fd0000 {
+			compatible = "renesas,tmu-r8a774a1", "renesas,tmu";
+			reg = <0 0xe6fd0000 0 0x30>;
+			interrupts = <GIC_SPI 303 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 304 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 305 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 123>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 123>;
+			status = "disabled";
+		};
+
+		tmu3: timer@e6fe0000 {
+			compatible = "renesas,tmu-r8a774a1", "renesas,tmu";
+			reg = <0 0xe6fe0000 0 0x30>;
+			interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 122>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 122>;
+			status = "disabled";
+		};
+
+		tmu4: timer@ffc00000 {
+			compatible = "renesas,tmu-r8a774a1", "renesas,tmu";
+			reg = <0 0xffc00000 0 0x30>;
+			interrupts = <GIC_SPI 406 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 407 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 408 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 121>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 121>;
+			status = "disabled";
+		};
+
+		i2c0: i2c@e6500000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a774a1",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe6500000 0 0x40>;
+			interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 931>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 931>;
+			dmas = <&dmac1 0x91>, <&dmac1 0x90>,
+			       <&dmac2 0x91>, <&dmac2 0x90>;
+			dma-names = "tx", "rx", "tx", "rx";
+			i2c-scl-internal-delay-ns = <110>;
+			status = "disabled";
+		};
+
+		i2c1: i2c@e6508000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a774a1",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe6508000 0 0x40>;
+			interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 930>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 930>;
+			dmas = <&dmac1 0x93>, <&dmac1 0x92>,
+			       <&dmac2 0x93>, <&dmac2 0x92>;
+			dma-names = "tx", "rx", "tx", "rx";
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
+		i2c2: i2c@e6510000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a774a1",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe6510000 0 0x40>;
+			interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 929>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 929>;
+			dmas = <&dmac1 0x95>, <&dmac1 0x94>,
+			       <&dmac2 0x95>, <&dmac2 0x94>;
+			dma-names = "tx", "rx", "tx", "rx";
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
+		i2c3: i2c@e66d0000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a774a1",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe66d0000 0 0x40>;
+			interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 928>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 928>;
+			dmas = <&dmac0 0x97>, <&dmac0 0x96>;
+			dma-names = "tx", "rx";
+			i2c-scl-internal-delay-ns = <110>;
+			status = "disabled";
+		};
+
+		i2c4: i2c@e66d8000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a774a1",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe66d8000 0 0x40>;
+			interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 927>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 927>;
+			dmas = <&dmac0 0x99>, <&dmac0 0x98>;
+			dma-names = "tx", "rx";
+			i2c-scl-internal-delay-ns = <110>;
+			status = "disabled";
+		};
+
+		i2c5: i2c@e66e0000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a774a1",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe66e0000 0 0x40>;
+			interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 919>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 919>;
+			dmas = <&dmac0 0x9b>, <&dmac0 0x9a>;
+			dma-names = "tx", "rx";
+			i2c-scl-internal-delay-ns = <110>;
+			status = "disabled";
+		};
+
+		i2c6: i2c@e66e8000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a774a1",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe66e8000 0 0x40>;
+			interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 918>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 918>;
+			dmas = <&dmac0 0x9d>, <&dmac0 0x9c>;
+			dma-names = "tx", "rx";
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
+		i2c_dvfs: i2c@e60b0000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,iic-r8a774a1",
+				     "renesas,rcar-gen3-iic",
+				     "renesas,rmobile-iic";
+			reg = <0 0xe60b0000 0 0x425>;
+			interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 926>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 926>;
+			dmas = <&dmac0 0x11>, <&dmac0 0x10>;
+			dma-names = "tx", "rx";
+			status = "disabled";
+		};
+
+		hscif0: serial@e6540000 {
+			compatible = "renesas,hscif-r8a774a1",
+				     "renesas,rcar-gen3-hscif",
+				     "renesas,hscif";
+			reg = <0 0xe6540000 0 0x60>;
+			interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 520>,
+				 <&cpg CPG_CORE R8A774A1_CLK_S3D1>,
+				 <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac1 0x31>, <&dmac1 0x30>,
+			       <&dmac2 0x31>, <&dmac2 0x30>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 520>;
+			status = "disabled";
+		};
+
+		hscif1: serial@e6550000 {
+			compatible = "renesas,hscif-r8a774a1",
+				     "renesas,rcar-gen3-hscif",
+				     "renesas,hscif";
+			reg = <0 0xe6550000 0 0x60>;
+			interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 519>,
+				 <&cpg CPG_CORE R8A774A1_CLK_S3D1>,
+				 <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac1 0x33>, <&dmac1 0x32>,
+			       <&dmac2 0x33>, <&dmac2 0x32>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 519>;
+			status = "disabled";
+		};
+
+		hscif2: serial@e6560000 {
+			compatible = "renesas,hscif-r8a774a1",
+				     "renesas,rcar-gen3-hscif",
+				     "renesas,hscif";
+			reg = <0 0xe6560000 0 0x60>;
+			interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 518>,
+				 <&cpg CPG_CORE R8A774A1_CLK_S3D1>,
+				 <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac1 0x35>, <&dmac1 0x34>,
+			       <&dmac2 0x35>, <&dmac2 0x34>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 518>;
+			status = "disabled";
+		};
+
+		hscif3: serial@e66a0000 {
+			compatible = "renesas,hscif-r8a774a1",
+				     "renesas,rcar-gen3-hscif",
+				     "renesas,hscif";
+			reg = <0 0xe66a0000 0 0x60>;
+			interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 517>,
+				 <&cpg CPG_CORE R8A774A1_CLK_S3D1>,
+				 <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x37>, <&dmac0 0x36>;
+			dma-names = "tx", "rx";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 517>;
+			status = "disabled";
+		};
+
+		hscif4: serial@e66b0000 {
+			compatible = "renesas,hscif-r8a774a1",
+				     "renesas,rcar-gen3-hscif",
+				     "renesas,hscif";
+			reg = <0 0xe66b0000 0 0x60>;
+			interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 516>,
+				 <&cpg CPG_CORE R8A774A1_CLK_S3D1>,
+				 <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x39>, <&dmac0 0x38>;
+			dma-names = "tx", "rx";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 516>;
+			status = "disabled";
+		};
+
+		hsusb: usb@e6590000 {
+			compatible = "renesas,usbhs-r8a774a1",
+				     "renesas,rcar-gen3-usbhs";
+			reg = <0 0xe6590000 0 0x200>;
+			interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 704>, <&cpg CPG_MOD 703>;
+			dmas = <&usb_dmac0 0>, <&usb_dmac0 1>,
+			       <&usb_dmac1 0>, <&usb_dmac1 1>;
+			dma-names = "ch0", "ch1", "ch2", "ch3";
+			renesas,buswait = <11>;
+			phys = <&usb2_phy0 3>;
+			phy-names = "usb";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 704>, <&cpg 703>;
+			status = "disabled";
+		};
+
+		usb_dmac0: dma-controller@e65a0000 {
+			compatible = "renesas,r8a774a1-usb-dmac",
+				     "renesas,usb-dmac";
+			reg = <0 0xe65a0000 0 0x100>;
+			interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "ch0", "ch1";
+			clocks = <&cpg CPG_MOD 330>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 330>;
+			#dma-cells = <1>;
+			dma-channels = <2>;
+		};
+
+		usb_dmac1: dma-controller@e65b0000 {
+			compatible = "renesas,r8a774a1-usb-dmac",
+				     "renesas,usb-dmac";
+			reg = <0 0xe65b0000 0 0x100>;
+			interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "ch0", "ch1";
+			clocks = <&cpg CPG_MOD 331>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 331>;
+			#dma-cells = <1>;
+			dma-channels = <2>;
+		};
+
+		usb3_phy0: usb-phy@e65ee000 {
+			compatible = "renesas,r8a774a1-usb3-phy",
+				     "renesas,rcar-gen3-usb3-phy";
+			reg = <0 0xe65ee000 0 0x90>;
+			clocks = <&cpg CPG_MOD 328>, <&usb3s0_clk>,
+				 <&usb_extal_clk>;
+			clock-names = "usb3-if", "usb3s_clk", "usb_extal";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 328>;
+			#phy-cells = <0>;
+			status = "disabled";
+		};
+
+		dmac0: dma-controller@e6700000 {
+			compatible = "renesas,dmac-r8a774a1",
+				     "renesas,rcar-dmac";
+			reg = <0 0xe6700000 0 0x10000>;
+			interrupts = <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "error",
+					"ch0", "ch1", "ch2", "ch3",
+					"ch4", "ch5", "ch6", "ch7",
+					"ch8", "ch9", "ch10", "ch11",
+					"ch12", "ch13", "ch14", "ch15";
+			clocks = <&cpg CPG_MOD 219>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 219>;
+			#dma-cells = <1>;
+			dma-channels = <16>;
+			iommus = <&ipmmu_ds0 0>, <&ipmmu_ds0 1>,
+			       <&ipmmu_ds0 2>, <&ipmmu_ds0 3>,
+			       <&ipmmu_ds0 4>, <&ipmmu_ds0 5>,
+			       <&ipmmu_ds0 6>, <&ipmmu_ds0 7>,
+			       <&ipmmu_ds0 8>, <&ipmmu_ds0 9>,
+			       <&ipmmu_ds0 10>, <&ipmmu_ds0 11>,
+			       <&ipmmu_ds0 12>, <&ipmmu_ds0 13>,
+			       <&ipmmu_ds0 14>, <&ipmmu_ds0 15>;
+		};
+
+		dmac1: dma-controller@e7300000 {
+			compatible = "renesas,dmac-r8a774a1",
+				     "renesas,rcar-dmac";
+			reg = <0 0xe7300000 0 0x10000>;
+			interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "error",
+					"ch0", "ch1", "ch2", "ch3",
+					"ch4", "ch5", "ch6", "ch7",
+					"ch8", "ch9", "ch10", "ch11",
+					"ch12", "ch13", "ch14", "ch15";
+			clocks = <&cpg CPG_MOD 218>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 218>;
+			#dma-cells = <1>;
+			dma-channels = <16>;
+			iommus = <&ipmmu_ds1 0>, <&ipmmu_ds1 1>,
+			       <&ipmmu_ds1 2>, <&ipmmu_ds1 3>,
+			       <&ipmmu_ds1 4>, <&ipmmu_ds1 5>,
+			       <&ipmmu_ds1 6>, <&ipmmu_ds1 7>,
+			       <&ipmmu_ds1 8>, <&ipmmu_ds1 9>,
+			       <&ipmmu_ds1 10>, <&ipmmu_ds1 11>,
+			       <&ipmmu_ds1 12>, <&ipmmu_ds1 13>,
+			       <&ipmmu_ds1 14>, <&ipmmu_ds1 15>;
+		};
+
+		dmac2: dma-controller@e7310000 {
+			compatible = "renesas,dmac-r8a774a1",
+				     "renesas,rcar-dmac";
+			reg = <0 0xe7310000 0 0x10000>;
+			interrupts = <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 427 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 428 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 430 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 431 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 397 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "error",
+					"ch0", "ch1", "ch2", "ch3",
+					"ch4", "ch5", "ch6", "ch7",
+					"ch8", "ch9", "ch10", "ch11",
+					"ch12", "ch13", "ch14", "ch15";
+			clocks = <&cpg CPG_MOD 217>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 217>;
+			#dma-cells = <1>;
+			dma-channels = <16>;
+			iommus = <&ipmmu_ds1 16>, <&ipmmu_ds1 17>,
+			       <&ipmmu_ds1 18>, <&ipmmu_ds1 19>,
+			       <&ipmmu_ds1 20>, <&ipmmu_ds1 21>,
+			       <&ipmmu_ds1 22>, <&ipmmu_ds1 23>,
+			       <&ipmmu_ds1 24>, <&ipmmu_ds1 25>,
+			       <&ipmmu_ds1 26>, <&ipmmu_ds1 27>,
+			       <&ipmmu_ds1 28>, <&ipmmu_ds1 29>,
+			       <&ipmmu_ds1 30>, <&ipmmu_ds1 31>;
+		};
+
+		ipmmu_ds0: iommu@e6740000 {
+			compatible = "renesas,ipmmu-r8a774a1";
+			reg = <0 0xe6740000 0 0x1000>;
+			renesas,ipmmu-main = <&ipmmu_mm 0>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			#iommu-cells = <1>;
+		};
+
+		ipmmu_ds1: iommu@e7740000 {
+			compatible = "renesas,ipmmu-r8a774a1";
+			reg = <0 0xe7740000 0 0x1000>;
+			renesas,ipmmu-main = <&ipmmu_mm 1>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			#iommu-cells = <1>;
+		};
+
+		ipmmu_hc: iommu@e6570000 {
+			compatible = "renesas,ipmmu-r8a774a1";
+			reg = <0 0xe6570000 0 0x1000>;
+			renesas,ipmmu-main = <&ipmmu_mm 2>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			#iommu-cells = <1>;
+		};
+
+		ipmmu_mm: iommu@e67b0000 {
+			compatible = "renesas,ipmmu-r8a774a1";
+			reg = <0 0xe67b0000 0 0x1000>;
+			interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			#iommu-cells = <1>;
+		};
+
+		ipmmu_mp: iommu@ec670000 {
+			compatible = "renesas,ipmmu-r8a774a1";
+			reg = <0 0xec670000 0 0x1000>;
+			renesas,ipmmu-main = <&ipmmu_mm 4>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			#iommu-cells = <1>;
+		};
+
+		ipmmu_pv0: iommu@fd800000 {
+			compatible = "renesas,ipmmu-r8a774a1";
+			reg = <0 0xfd800000 0 0x1000>;
+			renesas,ipmmu-main = <&ipmmu_mm 5>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			#iommu-cells = <1>;
+		};
+
+		ipmmu_pv1: iommu@fd950000 {
+			compatible = "renesas,ipmmu-r8a774a1";
+			reg = <0 0xfd950000 0 0x1000>;
+			renesas,ipmmu-main = <&ipmmu_mm 6>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			#iommu-cells = <1>;
+		};
+
+		ipmmu_vc0: iommu@fe6b0000 {
+			compatible = "renesas,ipmmu-r8a774a1";
+			reg = <0 0xfe6b0000 0 0x1000>;
+			renesas,ipmmu-main = <&ipmmu_mm 8>;
+			power-domains = <&sysc R8A774A1_PD_A3VC>;
+			#iommu-cells = <1>;
+		};
+
+		ipmmu_vi0: iommu@febd0000 {
+			compatible = "renesas,ipmmu-r8a774a1";
+			reg = <0 0xfebd0000 0 0x1000>;
+			renesas,ipmmu-main = <&ipmmu_mm 9>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			#iommu-cells = <1>;
+		};
+
+		avb: ethernet@e6800000 {
+			compatible = "renesas,etheravb-r8a774a1",
+				     "renesas,etheravb-rcar-gen3";
+			reg = <0 0xe6800000 0 0x800>;
+			interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "ch0", "ch1", "ch2", "ch3",
+					  "ch4", "ch5", "ch6", "ch7",
+					  "ch8", "ch9", "ch10", "ch11",
+					  "ch12", "ch13", "ch14", "ch15",
+					  "ch16", "ch17", "ch18", "ch19",
+					  "ch20", "ch21", "ch22", "ch23",
+					  "ch24";
+			clocks = <&cpg CPG_MOD 812>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 812>;
+			phy-mode = "rgmii";
+			iommus = <&ipmmu_ds0 16>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		can0: can@e6c30000 {
+			compatible = "renesas,can-r8a774a1",
+				     "renesas,rcar-gen3-can";
+			reg = <0 0xe6c30000 0 0x1000>;
+			interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 916>,
+				 <&cpg CPG_CORE R8A774A1_CLK_CANFD>,
+				 <&can_clk>;
+			clock-names = "clkp1", "clkp2", "can_clk";
+			assigned-clocks = <&cpg CPG_CORE R8A774A1_CLK_CANFD>;
+			assigned-clock-rates = <40000000>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 916>;
+			status = "disabled";
+		};
+
+		can1: can@e6c38000 {
+			compatible = "renesas,can-r8a774a1",
+				     "renesas,rcar-gen3-can";
+			reg = <0 0xe6c38000 0 0x1000>;
+			interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 915>,
+				 <&cpg CPG_CORE R8A774A1_CLK_CANFD>,
+				 <&can_clk>;
+			clock-names = "clkp1", "clkp2", "can_clk";
+			assigned-clocks = <&cpg CPG_CORE R8A774A1_CLK_CANFD>;
+			assigned-clock-rates = <40000000>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 915>;
+			status = "disabled";
+		};
+
+		canfd: can@e66c0000 {
+			compatible = "renesas,r8a774a1-canfd",
+				     "renesas,rcar-gen3-canfd";
+			reg = <0 0xe66c0000 0 0x8000>;
+			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 914>,
+				 <&cpg CPG_CORE R8A774A1_CLK_CANFD>,
+				 <&can_clk>;
+			clock-names = "fck", "canfd", "can_clk";
+			assigned-clocks = <&cpg CPG_CORE R8A774A1_CLK_CANFD>;
+			assigned-clock-rates = <40000000>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 914>;
+			status = "disabled";
+
+			channel0 {
+				status = "disabled";
+			};
+
+			channel1 {
+				status = "disabled";
+			};
+		};
+
+		pwm0: pwm@e6e30000 {
+			compatible = "renesas,pwm-r8a774a1", "renesas,pwm-rcar";
+			reg = <0 0xe6e30000 0 0x8>;
+			#pwm-cells = <2>;
+			clocks = <&cpg CPG_MOD 523>;
+			resets = <&cpg 523>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		pwm1: pwm@e6e31000 {
+			compatible = "renesas,pwm-r8a774a1", "renesas,pwm-rcar";
+			reg = <0 0xe6e31000 0 0x8>;
+			#pwm-cells = <2>;
+			clocks = <&cpg CPG_MOD 523>;
+			resets = <&cpg 523>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		pwm2: pwm@e6e32000 {
+			compatible = "renesas,pwm-r8a774a1", "renesas,pwm-rcar";
+			reg = <0 0xe6e32000 0 0x8>;
+			#pwm-cells = <2>;
+			clocks = <&cpg CPG_MOD 523>;
+			resets = <&cpg 523>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		pwm3: pwm@e6e33000 {
+			compatible = "renesas,pwm-r8a774a1", "renesas,pwm-rcar";
+			reg = <0 0xe6e33000 0 0x8>;
+			#pwm-cells = <2>;
+			clocks = <&cpg CPG_MOD 523>;
+			resets = <&cpg 523>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		pwm4: pwm@e6e34000 {
+			compatible = "renesas,pwm-r8a774a1", "renesas,pwm-rcar";
+			reg = <0 0xe6e34000 0 0x8>;
+			#pwm-cells = <2>;
+			clocks = <&cpg CPG_MOD 523>;
+			resets = <&cpg 523>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		pwm5: pwm@e6e35000 {
+			compatible = "renesas,pwm-r8a774a1", "renesas,pwm-rcar";
+			reg = <0 0xe6e35000 0 0x8>;
+			#pwm-cells = <2>;
+			clocks = <&cpg CPG_MOD 523>;
+			resets = <&cpg 523>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		pwm6: pwm@e6e36000 {
+			compatible = "renesas,pwm-r8a774a1", "renesas,pwm-rcar";
+			reg = <0 0xe6e36000 0 0x8>;
+			#pwm-cells = <2>;
+			clocks = <&cpg CPG_MOD 523>;
+			resets = <&cpg 523>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scif0: serial@e6e60000 {
+			compatible = "renesas,scif-r8a774a1",
+				     "renesas,rcar-gen3-scif", "renesas,scif";
+			reg = <0 0xe6e60000 0 0x40>;
+			interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 207>,
+				 <&cpg CPG_CORE R8A774A1_CLK_S3D1>,
+				 <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac1 0x51>, <&dmac1 0x50>,
+			       <&dmac2 0x51>, <&dmac2 0x50>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 207>;
+			status = "disabled";
+		};
+
+		scif1: serial@e6e68000 {
+			compatible = "renesas,scif-r8a774a1",
+				     "renesas,rcar-gen3-scif", "renesas,scif";
+			reg = <0 0xe6e68000 0 0x40>;
+			interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 206>,
+				 <&cpg CPG_CORE R8A774A1_CLK_S3D1>,
+				 <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac1 0x53>, <&dmac1 0x52>,
+			       <&dmac2 0x53>, <&dmac2 0x52>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 206>;
+			status = "disabled";
+		};
+
+		scif2: serial@e6e88000 {
+			compatible = "renesas,scif-r8a774a1",
+				     "renesas,rcar-gen3-scif", "renesas,scif";
+			reg = <0 0xe6e88000 0 0x40>;
+			interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 310>,
+				 <&cpg CPG_CORE R8A774A1_CLK_S3D1>,
+				 <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac1 0x13>, <&dmac1 0x12>,
+			       <&dmac2 0x13>, <&dmac2 0x12>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 310>;
+			status = "disabled";
+		};
+
+		scif3: serial@e6c50000 {
+			compatible = "renesas,scif-r8a774a1",
+				     "renesas,rcar-gen3-scif", "renesas,scif";
+			reg = <0 0xe6c50000 0 0x40>;
+			interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 204>,
+				 <&cpg CPG_CORE R8A774A1_CLK_S3D1>,
+				 <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x57>, <&dmac0 0x56>;
+			dma-names = "tx", "rx";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 204>;
+			status = "disabled";
+		};
+
+		scif4: serial@e6c40000 {
+			compatible = "renesas,scif-r8a774a1",
+				     "renesas,rcar-gen3-scif", "renesas,scif";
+			reg = <0 0xe6c40000 0 0x40>;
+			interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 203>,
+				 <&cpg CPG_CORE R8A774A1_CLK_S3D1>,
+				 <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x59>, <&dmac0 0x58>;
+			dma-names = "tx", "rx";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 203>;
+			status = "disabled";
+		};
+
+		scif5: serial@e6f30000 {
+			compatible = "renesas,scif-r8a774a1",
+				     "renesas,rcar-gen3-scif", "renesas,scif";
+			reg = <0 0xe6f30000 0 0x40>;
+			interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 202>,
+				 <&cpg CPG_CORE R8A774A1_CLK_S3D1>,
+				 <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac1 0x5b>, <&dmac1 0x5a>,
+			       <&dmac2 0x5b>, <&dmac2 0x5a>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 202>;
+			status = "disabled";
+		};
+
+		msiof0: spi@e6e90000 {
+			compatible = "renesas,msiof-r8a774a1",
+				     "renesas,rcar-gen3-msiof";
+			reg = <0 0xe6e90000 0 0x0064>;
+			interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 211>;
+			dmas = <&dmac1 0x41>, <&dmac1 0x40>,
+			       <&dmac2 0x41>, <&dmac2 0x40>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 211>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		msiof1: spi@e6ea0000 {
+			compatible = "renesas,msiof-r8a774a1",
+				     "renesas,rcar-gen3-msiof";
+			reg = <0 0xe6ea0000 0 0x0064>;
+			interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 210>;
+			dmas = <&dmac1 0x43>, <&dmac1 0x42>,
+			       <&dmac2 0x43>, <&dmac2 0x42>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 210>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		msiof2: spi@e6c00000 {
+			compatible = "renesas,msiof-r8a774a1",
+				     "renesas,rcar-gen3-msiof";
+			reg = <0 0xe6c00000 0 0x0064>;
+			interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 209>;
+			dmas = <&dmac0 0x45>, <&dmac0 0x44>;
+			dma-names = "tx", "rx";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 209>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		msiof3: spi@e6c10000 {
+			compatible = "renesas,msiof-r8a774a1",
+				     "renesas,rcar-gen3-msiof";
+			reg = <0 0xe6c10000 0 0x0064>;
+			interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 208>;
+			dmas = <&dmac0 0x47>, <&dmac0 0x46>;
+			dma-names = "tx", "rx";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 208>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		vin0: video@e6ef0000 {
+			compatible = "renesas,vin-r8a774a1";
+			reg = <0 0xe6ef0000 0 0x1000>;
+			interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 811>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 811>;
+			renesas,id = <0>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					reg = <1>;
+
+					vin0csi20: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&csi20vin0>;
+					};
+					vin0csi40: endpoint@2 {
+						reg = <2>;
+						remote-endpoint = <&csi40vin0>;
+					};
+				};
+			};
+		};
+
+		vin1: video@e6ef1000 {
+			compatible = "renesas,vin-r8a774a1";
+			reg = <0 0xe6ef1000 0 0x1000>;
+			interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 810>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 810>;
+			renesas,id = <1>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					reg = <1>;
+
+					vin1csi20: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&csi20vin1>;
+					};
+					vin1csi40: endpoint@2 {
+						reg = <2>;
+						remote-endpoint = <&csi40vin1>;
+					};
+				};
+			};
+		};
+
+		vin2: video@e6ef2000 {
+			compatible = "renesas,vin-r8a774a1";
+			reg = <0 0xe6ef2000 0 0x1000>;
+			interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 809>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 809>;
+			renesas,id = <2>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					reg = <1>;
+
+					vin2csi20: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&csi20vin2>;
+					};
+					vin2csi40: endpoint@2 {
+						reg = <2>;
+						remote-endpoint = <&csi40vin2>;
+					};
+				};
+			};
+		};
+
+		vin3: video@e6ef3000 {
+			compatible = "renesas,vin-r8a774a1";
+			reg = <0 0xe6ef3000 0 0x1000>;
+			interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 808>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 808>;
+			renesas,id = <3>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					reg = <1>;
+
+					vin3csi20: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&csi20vin3>;
+					};
+					vin3csi40: endpoint@2 {
+						reg = <2>;
+						remote-endpoint = <&csi40vin3>;
+					};
+				};
+			};
+		};
+
+		vin4: video@e6ef4000 {
+			compatible = "renesas,vin-r8a774a1";
+			reg = <0 0xe6ef4000 0 0x1000>;
+			interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 807>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 807>;
+			renesas,id = <4>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					reg = <1>;
+
+					vin4csi20: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&csi20vin4>;
+					};
+					vin4csi40: endpoint@2 {
+						reg = <2>;
+						remote-endpoint = <&csi40vin4>;
+					};
+				};
+			};
+		};
+
+		vin5: video@e6ef5000 {
+			compatible = "renesas,vin-r8a774a1";
+			reg = <0 0xe6ef5000 0 0x1000>;
+			interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 806>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 806>;
+			renesas,id = <5>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					reg = <1>;
+
+					vin5csi20: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&csi20vin5>;
+					};
+					vin5csi40: endpoint@2 {
+						reg = <2>;
+						remote-endpoint = <&csi40vin5>;
+					};
+				};
+			};
+		};
+
+		vin6: video@e6ef6000 {
+			compatible = "renesas,vin-r8a774a1";
+			reg = <0 0xe6ef6000 0 0x1000>;
+			interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 805>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 805>;
+			renesas,id = <6>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					reg = <1>;
+
+					vin6csi20: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&csi20vin6>;
+					};
+					vin6csi40: endpoint@2 {
+						reg = <2>;
+						remote-endpoint = <&csi40vin6>;
+					};
+				};
+			};
+		};
+
+		vin7: video@e6ef7000 {
+			compatible = "renesas,vin-r8a774a1";
+			reg = <0 0xe6ef7000 0 0x1000>;
+			interrupts = <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 804>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 804>;
+			renesas,id = <7>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					reg = <1>;
+
+					vin7csi20: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&csi20vin7>;
+					};
+					vin7csi40: endpoint@2 {
+						reg = <2>;
+						remote-endpoint = <&csi40vin7>;
+					};
+				};
+			};
+		};
+
+		rcar_sound: sound@ec500000 {
+			/*
+			 * #sound-dai-cells is required
+			 *
+			 * Single DAI : #sound-dai-cells = <0>;	<&rcar_sound>;
+			 * Multi  DAI : #sound-dai-cells = <1>;	<&rcar_sound N>;
+			 */
+			/*
+			 * #clock-cells is required for audio_clkout0/1/2/3
+			 *
+			 * clkout	: #clock-cells = <0>;	<&rcar_sound>;
+			 * clkout0/1/2/3: #clock-cells = <1>;	<&rcar_sound N>;
+			 */
+			compatible =  "renesas,rcar_sound-r8a774a1", "renesas,rcar_sound-gen3";
+			reg =	<0 0xec500000 0 0x1000>, /* SCU */
+				<0 0xec5a0000 0 0x100>,  /* ADG */
+				<0 0xec540000 0 0x1000>, /* SSIU */
+				<0 0xec541000 0 0x280>,  /* SSI */
+				<0 0xec760000 0 0x200>;  /* Audio DMAC peri peri*/
+			reg-names = "scu", "adg", "ssiu", "ssi", "audmapp";
+
+			clocks = <&cpg CPG_MOD 1005>,
+				 <&cpg CPG_MOD 1006>, <&cpg CPG_MOD 1007>,
+				 <&cpg CPG_MOD 1008>, <&cpg CPG_MOD 1009>,
+				 <&cpg CPG_MOD 1010>, <&cpg CPG_MOD 1011>,
+				 <&cpg CPG_MOD 1012>, <&cpg CPG_MOD 1013>,
+				 <&cpg CPG_MOD 1014>, <&cpg CPG_MOD 1015>,
+				 <&cpg CPG_MOD 1022>, <&cpg CPG_MOD 1023>,
+				 <&cpg CPG_MOD 1024>, <&cpg CPG_MOD 1025>,
+				 <&cpg CPG_MOD 1026>, <&cpg CPG_MOD 1027>,
+				 <&cpg CPG_MOD 1028>, <&cpg CPG_MOD 1029>,
+				 <&cpg CPG_MOD 1030>, <&cpg CPG_MOD 1031>,
+				 <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>,
+				 <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>,
+				 <&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
+				 <&audio_clk_a>, <&audio_clk_b>,
+				 <&audio_clk_c>,
+				 <&cpg CPG_CORE R8A774A1_CLK_S0D4>;
+			clock-names = "ssi-all",
+				      "ssi.9", "ssi.8", "ssi.7", "ssi.6",
+				      "ssi.5", "ssi.4", "ssi.3", "ssi.2",
+				      "ssi.1", "ssi.0",
+				      "src.9", "src.8", "src.7", "src.6",
+				      "src.5", "src.4", "src.3", "src.2",
+				      "src.1", "src.0",
+				      "mix.1", "mix.0",
+				      "ctu.1", "ctu.0",
+				      "dvc.0", "dvc.1",
+				      "clk_a", "clk_b", "clk_c", "clk_i";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 1005>,
+				 <&cpg 1006>, <&cpg 1007>,
+				 <&cpg 1008>, <&cpg 1009>,
+				 <&cpg 1010>, <&cpg 1011>,
+				 <&cpg 1012>, <&cpg 1013>,
+				 <&cpg 1014>, <&cpg 1015>;
+			reset-names = "ssi-all",
+				      "ssi.9", "ssi.8", "ssi.7", "ssi.6",
+				      "ssi.5", "ssi.4", "ssi.3", "ssi.2",
+				      "ssi.1", "ssi.0";
+			status = "disabled";
+
+			rcar_sound,ctu {
+				ctu00: ctu-0 { };
+				ctu01: ctu-1 { };
+				ctu02: ctu-2 { };
+				ctu03: ctu-3 { };
+				ctu10: ctu-4 { };
+				ctu11: ctu-5 { };
+				ctu12: ctu-6 { };
+				ctu13: ctu-7 { };
+			};
+
+			rcar_sound,dvc {
+				dvc0: dvc-0 {
+					dmas = <&audma1 0xbc>;
+					dma-names = "tx";
+				};
+				dvc1: dvc-1 {
+					dmas = <&audma1 0xbe>;
+					dma-names = "tx";
+				};
+			};
+
+			rcar_sound,mix {
+				mix0: mix-0 { };
+				mix1: mix-1 { };
+			};
+
+			rcar_sound,src {
+				src0: src-0 {
+					interrupts = <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x85>, <&audma1 0x9a>;
+					dma-names = "rx", "tx";
+				};
+				src1: src-1 {
+					interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x87>, <&audma1 0x9c>;
+					dma-names = "rx", "tx";
+				};
+				src2: src-2 {
+					interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x89>, <&audma1 0x9e>;
+					dma-names = "rx", "tx";
+				};
+				src3: src-3 {
+					interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x8b>, <&audma1 0xa0>;
+					dma-names = "rx", "tx";
+				};
+				src4: src-4 {
+					interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x8d>, <&audma1 0xb0>;
+					dma-names = "rx", "tx";
+				};
+				src5: src-5 {
+					interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x8f>, <&audma1 0xb2>;
+					dma-names = "rx", "tx";
+				};
+				src6: src-6 {
+					interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x91>, <&audma1 0xb4>;
+					dma-names = "rx", "tx";
+				};
+				src7: src-7 {
+					interrupts = <GIC_SPI 359 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x93>, <&audma1 0xb6>;
+					dma-names = "rx", "tx";
+				};
+				src8: src-8 {
+					interrupts = <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x95>, <&audma1 0xb8>;
+					dma-names = "rx", "tx";
+				};
+				src9: src-9 {
+					interrupts = <GIC_SPI 361 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x97>, <&audma1 0xba>;
+					dma-names = "rx", "tx";
+				};
+			};
+
+			rcar_sound,ssi {
+				ssi0: ssi-0 {
+					interrupts = <GIC_SPI 370 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x01>, <&audma1 0x02>;
+					dma-names = "rx", "tx";
+				};
+				ssi1: ssi-1 {
+					interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x03>, <&audma1 0x04>;
+					dma-names = "rx", "tx";
+				};
+				ssi2: ssi-2 {
+					interrupts = <GIC_SPI 372 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x05>, <&audma1 0x06>;
+					dma-names = "rx", "tx";
+				};
+				ssi3: ssi-3 {
+					interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x07>, <&audma1 0x08>;
+					dma-names = "rx", "tx";
+				};
+				ssi4: ssi-4 {
+					interrupts = <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x09>, <&audma1 0x0a>;
+					dma-names = "rx", "tx";
+				};
+				ssi5: ssi-5 {
+					interrupts = <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x0b>, <&audma1 0x0c>;
+					dma-names = "rx", "tx";
+				};
+				ssi6: ssi-6 {
+					interrupts = <GIC_SPI 376 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x0d>, <&audma1 0x0e>;
+					dma-names = "rx", "tx";
+				};
+				ssi7: ssi-7 {
+					interrupts = <GIC_SPI 377 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x0f>, <&audma1 0x10>;
+					dma-names = "rx", "tx";
+				};
+				ssi8: ssi-8 {
+					interrupts = <GIC_SPI 378 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x11>, <&audma1 0x12>;
+					dma-names = "rx", "tx";
+				};
+				ssi9: ssi-9 {
+					interrupts = <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&audma0 0x13>, <&audma1 0x14>;
+					dma-names = "rx", "tx";
+				};
+			};
+
+			rcar_sound,ssiu {
+				ssiu00: ssiu-0 {
+					dmas = <&audma0 0x15>, <&audma1 0x16>;
+					dma-names = "rx", "tx";
+				};
+				ssiu01: ssiu-1 {
+					dmas = <&audma0 0x35>, <&audma1 0x36>;
+					dma-names = "rx", "tx";
+				};
+				ssiu02: ssiu-2 {
+					dmas = <&audma0 0x37>, <&audma1 0x38>;
+					dma-names = "rx", "tx";
+				};
+				ssiu03: ssiu-3 {
+					dmas = <&audma0 0x47>, <&audma1 0x48>;
+					dma-names = "rx", "tx";
+				};
+				ssiu04: ssiu-4 {
+					dmas = <&audma0 0x3F>, <&audma1 0x40>;
+					dma-names = "rx", "tx";
+				};
+				ssiu05: ssiu-5 {
+					dmas = <&audma0 0x43>, <&audma1 0x44>;
+					dma-names = "rx", "tx";
+				};
+				ssiu06: ssiu-6 {
+					dmas = <&audma0 0x4F>, <&audma1 0x50>;
+					dma-names = "rx", "tx";
+				};
+				ssiu07: ssiu-7 {
+					dmas = <&audma0 0x53>, <&audma1 0x54>;
+					dma-names = "rx", "tx";
+				};
+				ssiu10: ssiu-8 {
+					dmas = <&audma0 0x49>, <&audma1 0x4a>;
+					dma-names = "rx", "tx";
+				};
+				ssiu11: ssiu-9 {
+					dmas = <&audma0 0x4B>, <&audma1 0x4C>;
+					dma-names = "rx", "tx";
+				};
+				ssiu12: ssiu-10 {
+					dmas = <&audma0 0x57>, <&audma1 0x58>;
+					dma-names = "rx", "tx";
+				};
+				ssiu13: ssiu-11 {
+					dmas = <&audma0 0x59>, <&audma1 0x5A>;
+					dma-names = "rx", "tx";
+				};
+				ssiu14: ssiu-12 {
+					dmas = <&audma0 0x5F>, <&audma1 0x60>;
+					dma-names = "rx", "tx";
+				};
+				ssiu15: ssiu-13 {
+					dmas = <&audma0 0xC3>, <&audma1 0xC4>;
+					dma-names = "rx", "tx";
+				};
+				ssiu16: ssiu-14 {
+					dmas = <&audma0 0xC7>, <&audma1 0xC8>;
+					dma-names = "rx", "tx";
+				};
+				ssiu17: ssiu-15 {
+					dmas = <&audma0 0xCB>, <&audma1 0xCC>;
+					dma-names = "rx", "tx";
+				};
+				ssiu20: ssiu-16 {
+					dmas = <&audma0 0x63>, <&audma1 0x64>;
+					dma-names = "rx", "tx";
+				};
+				ssiu21: ssiu-17 {
+					dmas = <&audma0 0x67>, <&audma1 0x68>;
+					dma-names = "rx", "tx";
+				};
+				ssiu22: ssiu-18 {
+					dmas = <&audma0 0x6B>, <&audma1 0x6C>;
+					dma-names = "rx", "tx";
+				};
+				ssiu23: ssiu-19 {
+					dmas = <&audma0 0x6D>, <&audma1 0x6E>;
+					dma-names = "rx", "tx";
+				};
+				ssiu24: ssiu-20 {
+					dmas = <&audma0 0xCF>, <&audma1 0xCE>;
+					dma-names = "rx", "tx";
+				};
+				ssiu25: ssiu-21 {
+					dmas = <&audma0 0xEB>, <&audma1 0xEC>;
+					dma-names = "rx", "tx";
+				};
+				ssiu26: ssiu-22 {
+					dmas = <&audma0 0xED>, <&audma1 0xEE>;
+					dma-names = "rx", "tx";
+				};
+				ssiu27: ssiu-23 {
+					dmas = <&audma0 0xEF>, <&audma1 0xF0>;
+					dma-names = "rx", "tx";
+				};
+				ssiu30: ssiu-24 {
+					dmas = <&audma0 0x6f>, <&audma1 0x70>;
+					dma-names = "rx", "tx";
+				};
+				ssiu31: ssiu-25 {
+					dmas = <&audma0 0x21>, <&audma1 0x22>;
+					dma-names = "rx", "tx";
+				};
+				ssiu32: ssiu-26 {
+					dmas = <&audma0 0x23>, <&audma1 0x24>;
+					dma-names = "rx", "tx";
+				};
+				ssiu33: ssiu-27 {
+					dmas = <&audma0 0x25>, <&audma1 0x26>;
+					dma-names = "rx", "tx";
+				};
+				ssiu34: ssiu-28 {
+					dmas = <&audma0 0x27>, <&audma1 0x28>;
+					dma-names = "rx", "tx";
+				};
+				ssiu35: ssiu-29 {
+					dmas = <&audma0 0x29>, <&audma1 0x2A>;
+					dma-names = "rx", "tx";
+				};
+				ssiu36: ssiu-30 {
+					dmas = <&audma0 0x2B>, <&audma1 0x2C>;
+					dma-names = "rx", "tx";
+				};
+				ssiu37: ssiu-31 {
+					dmas = <&audma0 0x2D>, <&audma1 0x2E>;
+					dma-names = "rx", "tx";
+				};
+				ssiu40: ssiu-32 {
+					dmas =	<&audma0 0x71>, <&audma1 0x72>;
+					dma-names = "rx", "tx";
+				};
+				ssiu41: ssiu-33 {
+					dmas = <&audma0 0x17>, <&audma1 0x18>;
+					dma-names = "rx", "tx";
+				};
+				ssiu42: ssiu-34 {
+					dmas = <&audma0 0x19>, <&audma1 0x1A>;
+					dma-names = "rx", "tx";
+				};
+				ssiu43: ssiu-35 {
+					dmas = <&audma0 0x1B>, <&audma1 0x1C>;
+					dma-names = "rx", "tx";
+				};
+				ssiu44: ssiu-36 {
+					dmas = <&audma0 0x1D>, <&audma1 0x1E>;
+					dma-names = "rx", "tx";
+				};
+				ssiu45: ssiu-37 {
+					dmas = <&audma0 0x1F>, <&audma1 0x20>;
+					dma-names = "rx", "tx";
+				};
+				ssiu46: ssiu-38 {
+					dmas = <&audma0 0x31>, <&audma1 0x32>;
+					dma-names = "rx", "tx";
+				};
+				ssiu47: ssiu-39 {
+					dmas = <&audma0 0x33>, <&audma1 0x34>;
+					dma-names = "rx", "tx";
+				};
+				ssiu50: ssiu-40 {
+					dmas = <&audma0 0x73>, <&audma1 0x74>;
+					dma-names = "rx", "tx";
+				};
+				ssiu60: ssiu-41 {
+					dmas = <&audma0 0x75>, <&audma1 0x76>;
+					dma-names = "rx", "tx";
+				};
+				ssiu70: ssiu-42 {
+					dmas = <&audma0 0x79>, <&audma1 0x7a>;
+					dma-names = "rx", "tx";
+				};
+				ssiu80: ssiu-43 {
+					dmas = <&audma0 0x7b>, <&audma1 0x7c>;
+					dma-names = "rx", "tx";
+				};
+				ssiu90: ssiu-44 {
+					dmas = <&audma0 0x7d>, <&audma1 0x7e>;
+					dma-names = "rx", "tx";
+				};
+				ssiu91: ssiu-45 {
+					dmas = <&audma0 0x7F>, <&audma1 0x80>;
+					dma-names = "rx", "tx";
+				};
+				ssiu92: ssiu-46 {
+					dmas = <&audma0 0x81>, <&audma1 0x82>;
+					dma-names = "rx", "tx";
+				};
+				ssiu93: ssiu-47 {
+					dmas = <&audma0 0x83>, <&audma1 0x84>;
+					dma-names = "rx", "tx";
+				};
+				ssiu94: ssiu-48 {
+					dmas = <&audma0 0xA3>, <&audma1 0xA4>;
+					dma-names = "rx", "tx";
+				};
+				ssiu95: ssiu-49 {
+					dmas = <&audma0 0xA5>, <&audma1 0xA6>;
+					dma-names = "rx", "tx";
+				};
+				ssiu96: ssiu-50 {
+					dmas = <&audma0 0xA7>, <&audma1 0xA8>;
+					dma-names = "rx", "tx";
+				};
+				ssiu97: ssiu-51 {
+					dmas = <&audma0 0xA9>, <&audma1 0xAA>;
+					dma-names = "rx", "tx";
+				};
+			};
+		};
+
+		audma0: dma-controller@ec700000 {
+			compatible = "renesas,dmac-r8a774a1",
+				     "renesas,rcar-dmac";
+			reg = <0 0xec700000 0 0x10000>;
+			interrupts = <GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 322 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 323 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 325 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 333 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "error",
+					"ch0", "ch1", "ch2", "ch3",
+					"ch4", "ch5", "ch6", "ch7",
+					"ch8", "ch9", "ch10", "ch11",
+					"ch12", "ch13", "ch14", "ch15";
+			clocks = <&cpg CPG_MOD 502>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 502>;
+			#dma-cells = <1>;
+			dma-channels = <16>;
+			iommus = <&ipmmu_mp 0>, <&ipmmu_mp 1>,
+			       <&ipmmu_mp 2>, <&ipmmu_mp 3>,
+			       <&ipmmu_mp 4>, <&ipmmu_mp 5>,
+			       <&ipmmu_mp 6>, <&ipmmu_mp 7>,
+			       <&ipmmu_mp 8>, <&ipmmu_mp 9>,
+			       <&ipmmu_mp 10>, <&ipmmu_mp 11>,
+			       <&ipmmu_mp 12>, <&ipmmu_mp 13>,
+			       <&ipmmu_mp 14>, <&ipmmu_mp 15>;
+		};
+
+		audma1: dma-controller@ec720000 {
+			compatible = "renesas,dmac-r8a774a1",
+				     "renesas,rcar-dmac";
+			reg = <0 0xec720000 0 0x10000>;
+			interrupts = <GIC_SPI 351 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 347 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 349 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 382 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "error",
+					"ch0", "ch1", "ch2", "ch3",
+					"ch4", "ch5", "ch6", "ch7",
+					"ch8", "ch9", "ch10", "ch11",
+					"ch12", "ch13", "ch14", "ch15";
+			clocks = <&cpg CPG_MOD 501>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 501>;
+			#dma-cells = <1>;
+			dma-channels = <16>;
+			iommus = <&ipmmu_mp 16>, <&ipmmu_mp 17>,
+			       <&ipmmu_mp 18>, <&ipmmu_mp 19>,
+			       <&ipmmu_mp 20>, <&ipmmu_mp 21>,
+			       <&ipmmu_mp 22>, <&ipmmu_mp 23>,
+			       <&ipmmu_mp 24>, <&ipmmu_mp 25>,
+			       <&ipmmu_mp 26>, <&ipmmu_mp 27>,
+			       <&ipmmu_mp 28>, <&ipmmu_mp 29>,
+			       <&ipmmu_mp 30>, <&ipmmu_mp 31>;
+		};
+
+		xhci0: usb@ee000000 {
+			compatible = "renesas,xhci-r8a774a1",
+				     "renesas,rcar-gen3-xhci";
+			reg = <0 0xee000000 0 0xc00>;
+			interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 328>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 328>;
+			status = "disabled";
+		};
+
+		usb3_peri0: usb@ee020000 {
+			compatible = "renesas,r8a774a1-usb3-peri",
+				     "renesas,rcar-gen3-usb3-peri";
+			reg = <0 0xee020000 0 0x400>;
+			interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 328>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 328>;
+			status = "disabled";
+		};
+
+		ohci0: usb@ee080000 {
+			compatible = "generic-ohci";
+			reg = <0 0xee080000 0 0x100>;
+			interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>;
+			phys = <&usb2_phy0 1>;
+			phy-names = "usb";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 703>, <&cpg 704>;
+			status = "disabled";
+		};
+
+		ohci1: usb@ee0a0000 {
+			compatible = "generic-ohci";
+			reg = <0 0xee0a0000 0 0x100>;
+			interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 702>;
+			phys = <&usb2_phy1 1>;
+			phy-names = "usb";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 702>;
+			status = "disabled";
+		};
+
+		ehci0: usb@ee080100 {
+			compatible = "generic-ehci";
+			reg = <0 0xee080100 0 0x100>;
+			interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>;
+			phys = <&usb2_phy0 2>;
+			phy-names = "usb";
+			companion = <&ohci0>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 703>, <&cpg 704>;
+			status = "disabled";
+		};
+
+		ehci1: usb@ee0a0100 {
+			compatible = "generic-ehci";
+			reg = <0 0xee0a0100 0 0x100>;
+			interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 702>;
+			phys = <&usb2_phy1 2>;
+			phy-names = "usb";
+			companion = <&ohci1>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 702>;
+			status = "disabled";
+		};
+
+		usb2_phy0: usb-phy@ee080200 {
+			compatible = "renesas,usb2-phy-r8a774a1",
+				     "renesas,rcar-gen3-usb2-phy";
+			reg = <0 0xee080200 0 0x700>;
+			interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 703>, <&cpg 704>;
+			#phy-cells = <1>;
+			status = "disabled";
+		};
+
+		usb2_phy1: usb-phy@ee0a0200 {
+			compatible = "renesas,usb2-phy-r8a774a1",
+				     "renesas,rcar-gen3-usb2-phy";
+			reg = <0 0xee0a0200 0 0x700>;
+			clocks = <&cpg CPG_MOD 702>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 702>;
+			#phy-cells = <1>;
+			status = "disabled";
+		};
+
+		sdhi0: sd@ee100000 {
+			compatible = "renesas,sdhi-r8a774a1",
+				     "renesas,rcar-gen3-sdhi";
+			reg = <0 0xee100000 0 0x2000>;
+			interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 314>;
+			max-frequency = <200000000>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 314>;
+			status = "disabled";
+		};
+
+		sdhi1: sd@ee120000 {
+			compatible = "renesas,sdhi-r8a774a1",
+				     "renesas,rcar-gen3-sdhi";
+			reg = <0 0xee120000 0 0x2000>;
+			interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 313>;
+			max-frequency = <200000000>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 313>;
+			status = "disabled";
+		};
+
+		sdhi2: sd@ee140000 {
+			compatible = "renesas,sdhi-r8a774a1",
+				     "renesas,rcar-gen3-sdhi";
+			reg = <0 0xee140000 0 0x2000>;
+			interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 312>;
+			max-frequency = <200000000>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 312>;
+			status = "disabled";
+		};
+
+		sdhi3: sd@ee160000 {
+			compatible = "renesas,sdhi-r8a774a1",
+				     "renesas,rcar-gen3-sdhi";
+			reg = <0 0xee160000 0 0x2000>;
+			interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 311>;
+			max-frequency = <200000000>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 311>;
+			status = "disabled";
+		};
+
+		gic: interrupt-controller@f1010000 {
+			compatible = "arm,gic-400";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			reg = <0x0 0xf1010000 0 0x1000>,
+			      <0x0 0xf1020000 0 0x20000>,
+			      <0x0 0xf1040000 0 0x20000>,
+			      <0x0 0xf1060000 0 0x20000>;
+			interrupts = <GIC_PPI 9
+					(GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_HIGH)>;
+			clocks = <&cpg CPG_MOD 408>;
+			clock-names = "clk";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 408>;
+		};
+
+		pciec0: pcie@fe000000 {
+			compatible = "renesas,pcie-r8a774a1",
+				     "renesas,pcie-rcar-gen3";
+			reg = <0 0xfe000000 0 0x80000>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			bus-range = <0x00 0xff>;
+			device_type = "pci";
+			ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000>,
+				 <0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000>,
+				 <0x02000000 0 0x30000000 0 0x30000000 0 0x08000000>,
+				 <0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
+			/* Map all possible DDR as inbound ranges */
+			dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>;
+			interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+			#interrupt-cells = <1>;
+			interrupt-map-mask = <0 0 0 0>;
+			interrupt-map = <0 0 0 0 &gic GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 319>, <&pcie_bus_clk>;
+			clock-names = "pcie", "pcie_bus";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 319>;
+			status = "disabled";
+		};
+
+		pciec1: pcie@ee800000 {
+			compatible = "renesas,pcie-r8a774a1",
+				     "renesas,pcie-rcar-gen3";
+			reg = <0 0xee800000 0 0x80000>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			bus-range = <0x00 0xff>;
+			device_type = "pci";
+			ranges = <0x01000000 0 0x00000000 0 0xee900000 0 0x00100000>,
+				 <0x02000000 0 0xeea00000 0 0xeea00000 0 0x00200000>,
+				 <0x02000000 0 0xc0000000 0 0xc0000000 0 0x08000000>,
+				 <0x42000000 0 0xc8000000 0 0xc8000000 0 0x08000000>;
+			/* Map all possible DDR as inbound ranges */
+			dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>;
+			interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+			#interrupt-cells = <1>;
+			interrupt-map-mask = <0 0 0 0>;
+			interrupt-map = <0 0 0 0 &gic GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 318>, <&pcie_bus_clk>;
+			clock-names = "pcie", "pcie_bus";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 318>;
+			status = "disabled";
+		};
+
+		fdp1@fe940000 {
+			compatible = "renesas,fdp1";
+			reg = <0 0xfe940000 0 0x2400>;
+			interrupts = <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 119>;
+			power-domains = <&sysc R8A774A1_PD_A3VC>;
+			resets = <&cpg 119>;
+			renesas,fcp = <&fcpf0>;
+		};
+
+		fcpf0: fcp@fe950000 {
+			compatible = "renesas,fcpf";
+			reg = <0 0xfe950000 0 0x200>;
+			clocks = <&cpg CPG_MOD 615>;
+			power-domains = <&sysc R8A774A1_PD_A3VC>;
+			resets = <&cpg 615>;
+		};
+
+		fcpvb0: fcp@fe96f000 {
+			compatible = "renesas,fcpv";
+			reg = <0 0xfe96f000 0 0x200>;
+			clocks = <&cpg CPG_MOD 607>;
+			power-domains = <&sysc R8A774A1_PD_A3VC>;
+			resets = <&cpg 607>;
+		};
+
+		fcpvd0: fcp@fea27000 {
+			compatible = "renesas,fcpv";
+			reg = <0 0xfea27000 0 0x200>;
+			clocks = <&cpg CPG_MOD 603>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 603>;
+			iommus = <&ipmmu_vi0 8>;
+		};
+
+		fcpvd1: fcp@fea2f000 {
+			compatible = "renesas,fcpv";
+			reg = <0 0xfea2f000 0 0x200>;
+			clocks = <&cpg CPG_MOD 602>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 602>;
+			iommus = <&ipmmu_vi0 9>;
+		};
+
+		fcpvd2: fcp@fea37000 {
+			compatible = "renesas,fcpv";
+			reg = <0 0xfea37000 0 0x200>;
+			clocks = <&cpg CPG_MOD 601>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 601>;
+			iommus = <&ipmmu_vi0 10>;
+		};
+
+		fcpvi0: fcp@fe9af000 {
+			compatible = "renesas,fcpv";
+			reg = <0 0xfe9af000 0 0x200>;
+			clocks = <&cpg CPG_MOD 611>;
+			power-domains = <&sysc R8A774A1_PD_A3VC>;
+			resets = <&cpg 611>;
+			iommus = <&ipmmu_vc0 19>;
+		};
+
+		vspb: vsp@fe960000 {
+			compatible = "renesas,vsp2";
+			reg = <0 0xfe960000 0 0x8000>;
+			interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 626>;
+			power-domains = <&sysc R8A774A1_PD_A3VC>;
+			resets = <&cpg 626>;
+
+			renesas,fcp = <&fcpvb0>;
+		};
+
+		vspd0: vsp@fea20000 {
+			compatible = "renesas,vsp2";
+			reg = <0 0xfea20000 0 0x5000>;
+			interrupts = <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 623>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 623>;
+
+			renesas,fcp = <&fcpvd0>;
+		};
+
+		vspd1: vsp@fea28000 {
+			compatible = "renesas,vsp2";
+			reg = <0 0xfea28000 0 0x5000>;
+			interrupts = <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 622>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 622>;
+
+			renesas,fcp = <&fcpvd1>;
+		};
+
+		vspd2: vsp@fea30000 {
+			compatible = "renesas,vsp2";
+			reg = <0 0xfea30000 0 0x5000>;
+			interrupts = <GIC_SPI 468 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 621>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 621>;
+
+			renesas,fcp = <&fcpvd2>;
+		};
+
+		vspi0: vsp@fe9a0000 {
+			compatible = "renesas,vsp2";
+			reg = <0 0xfe9a0000 0 0x8000>;
+			interrupts = <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 631>;
+			power-domains = <&sysc R8A774A1_PD_A3VC>;
+			resets = <&cpg 631>;
+
+			renesas,fcp = <&fcpvi0>;
+		};
+
+		csi20: csi2@fea80000 {
+			compatible = "renesas,r8a774a1-csi2";
+			reg = <0 0xfea80000 0 0x10000>;
+			interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 714>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 714>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					reg = <1>;
+
+					csi20vin0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&vin0csi20>;
+					};
+					csi20vin1: endpoint@1 {
+						reg = <1>;
+						remote-endpoint = <&vin1csi20>;
+					};
+					csi20vin2: endpoint@2 {
+						reg = <2>;
+						remote-endpoint = <&vin2csi20>;
+					};
+					csi20vin3: endpoint@3 {
+						reg = <3>;
+						remote-endpoint = <&vin3csi20>;
+					};
+					csi20vin4: endpoint@4 {
+						reg = <4>;
+						remote-endpoint = <&vin4csi20>;
+					};
+					csi20vin5: endpoint@5 {
+						reg = <5>;
+						remote-endpoint = <&vin5csi20>;
+					};
+					csi20vin6: endpoint@6 {
+						reg = <6>;
+						remote-endpoint = <&vin6csi20>;
+					};
+					csi20vin7: endpoint@7 {
+						reg = <7>;
+						remote-endpoint = <&vin7csi20>;
+					};
+				};
+			};
+		};
+
+		csi40: csi2@feaa0000 {
+			compatible = "renesas,r8a774a1-csi2";
+			reg = <0 0xfeaa0000 0 0x10000>;
+			interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 716>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 716>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					reg = <1>;
+
+					csi40vin0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&vin0csi40>;
+					};
+					csi40vin1: endpoint@1 {
+						reg = <1>;
+						remote-endpoint = <&vin1csi40>;
+					};
+					csi40vin2: endpoint@2 {
+						reg = <2>;
+						remote-endpoint = <&vin2csi40>;
+					};
+					csi40vin3: endpoint@3 {
+						reg = <3>;
+						remote-endpoint = <&vin3csi40>;
+					};
+					csi40vin4: endpoint@4 {
+						reg = <4>;
+						remote-endpoint = <&vin4csi40>;
+					};
+					csi40vin5: endpoint@5 {
+						reg = <5>;
+						remote-endpoint = <&vin5csi40>;
+					};
+					csi40vin6: endpoint@6 {
+						reg = <6>;
+						remote-endpoint = <&vin6csi40>;
+					};
+					csi40vin7: endpoint@7 {
+						reg = <7>;
+						remote-endpoint = <&vin7csi40>;
+					};
+				};
+
+			};
+		};
+
+		hdmi0: hdmi@fead0000 {
+			compatible = "renesas,r8a774a1-hdmi",
+				     "renesas,rcar-gen3-hdmi";
+			reg = <0 0xfead0000 0 0x10000>;
+			interrupts = <GIC_SPI 389 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 729>,
+				 <&cpg CPG_CORE R8A774A1_CLK_HDMI>;
+			clock-names = "iahb", "isfr";
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 729>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				port@0 {
+					reg = <0>;
+					dw_hdmi0_in: endpoint {
+						remote-endpoint = <&du_out_hdmi0>;
+					};
+				};
+				port@1 {
+					reg = <1>;
+				};
+				port@2 {
+					/* HDMI sound */
+					reg = <2>;
+				};
+			};
+		};
+
+		du: display@feb00000 {
+			compatible = "renesas,du-r8a774a1";
+			reg = <0 0xfeb00000 0 0x70000>;
+			interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>,
+				 <&cpg CPG_MOD 722>;
+			clock-names = "du.0", "du.1", "du.2";
+			resets = <&cpg 724>, <&cpg 722>;
+			reset-names = "du.0", "du.2";
+			status = "disabled";
+
+			renesas,vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					du_out_rgb: endpoint {
+					};
+				};
+				port@1 {
+					reg = <1>;
+					du_out_hdmi0: endpoint {
+						remote-endpoint = <&dw_hdmi0_in>;
+					};
+				};
+				port@2 {
+					reg = <2>;
+					du_out_lvds0: endpoint {
+						remote-endpoint = <&lvds0_in>;
+					};
+				};
+			};
+		};
+
+		lvds0: lvds@feb90000 {
+			compatible = "renesas,r8a774a1-lvds";
+			reg = <0 0xfeb90000 0 0x14>;
+			clocks = <&cpg CPG_MOD 727>;
+			power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
+			resets = <&cpg 727>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					lvds0_in: endpoint {
+						remote-endpoint = <&du_out_lvds0>;
+					};
+				};
+				port@1 {
+					reg = <1>;
+					lvds0_out: endpoint {
+					};
+				};
+			};
+		};
+
+		prr: chipid@fff00044 {
+			compatible = "renesas,prr";
+			reg = <0 0xfff00044 0 4>;
+		};
+	};
+
+	thermal-zones {
+		sensor_thermal1: sensor-thermal1 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+			thermal-sensors = <&tsc 0>;
+			sustainable-power = <3874>;
+
+			trips {
+				sensor1_crit: sensor1-crit {
+					temperature = <120000>;
+					hysteresis = <1000>;
+					type = "critical";
+				};
+			};
+		};
+
+		sensor_thermal2: sensor-thermal2 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+			thermal-sensors = <&tsc 1>;
+			sustainable-power = <3874>;
+
+			trips {
+				sensor2_crit: sensor2-crit {
+					temperature = <120000>;
+					hysteresis = <1000>;
+					type = "critical";
+				};
+			};
+		};
+
+		sensor_thermal3: sensor-thermal3 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+			thermal-sensors = <&tsc 2>;
+			sustainable-power = <3874>;
+
+			cooling-maps {
+				map0 {
+					trip = <&target>;
+					cooling-device = <&a57_0 0 2>;
+					contribution = <1024>;
+				};
+				map1 {
+					trip = <&target>;
+					cooling-device = <&a53_0 0 2>;
+					contribution = <1024>;
+				};
+			};
+			trips {
+				target: trip-point1 {
+					temperature = <100000>;
+					hysteresis = <1000>;
+					type = "passive";
+				};
+
+				sensor3_crit: sensor3-crit {
+					temperature = <120000>;
+					hysteresis = <1000>;
+					type = "critical";
+				};
+			};
+		};
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
+				      <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
+				      <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
+				      <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	/* External USB clocks - can be overridden by the board */
+	usb3s0_clk: usb3s0 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <0>;
+	};
+
+	usb_extal_clk: usb_extal {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <0>;
+	};
+};
diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c
index 63bf060..4335f28 100644
--- a/arch/arm/mach-k3/common.c
+++ b/arch/arm/mach-k3/common.c
@@ -25,6 +25,7 @@
 #include <fs.h>
 #include <env.h>
 #include <elf.h>
+#include <soc.h>
 
 struct ti_sci_handle *get_ti_sci_handle(void)
 {
@@ -308,38 +309,27 @@
 #if defined(CONFIG_DISPLAY_CPUINFO)
 int print_cpuinfo(void)
 {
-	u32 soc, rev;
-	char *name;
-
-	soc = (readl(CTRLMMR_WKUP_JTAG_ID) &
-		JTAG_ID_PARTNO_MASK) >> JTAG_ID_PARTNO_SHIFT;
-	rev = (readl(CTRLMMR_WKUP_JTAG_ID) &
-		JTAG_ID_VARIANT_MASK) >> JTAG_ID_VARIANT_SHIFT;
+	struct udevice *soc;
+	char name[64];
+	int ret;
 
 	printf("SoC:   ");
-	switch (soc) {
-	case AM65X:
-		name = "AM65x";
-		break;
-	case J721E:
-		name = "J721E";
-		break;
-	default:
-		name = "Unknown Silicon";
-	};
 
-	printf("%s SR ", name);
-	switch (rev) {
-	case REV_PG1_0:
-		name = "1.0";
-		break;
-	case REV_PG2_0:
-		name = "2.0";
-		break;
-	default:
-		name = "Unknown Revision";
-	};
-	printf("%s\n", name);
+	ret = soc_get(&soc);
+	if (ret) {
+		printf("UNKNOWN\n");
+		return 0;
+	}
+
+	ret = soc_get_family(soc, name, 64);
+	if (!ret) {
+		printf("%s ", name);
+	}
+
+	ret = soc_get_revision(soc, name, 64);
+	if (!ret) {
+		printf("%s\n", name);
+	}
 
 	return 0;
 }
diff --git a/arch/arm/mach-k3/common.h b/arch/arm/mach-k3/common.h
index 94cdcb5..ba344c5 100644
--- a/arch/arm/mach-k3/common.h
+++ b/arch/arm/mach-k3/common.h
@@ -8,12 +8,6 @@
 
 #include <asm/armv7_mpu.h>
 
-#define AM65X	0xbb5a
-#define J721E	0xbb64
-
-#define REV_PG1_0	0
-#define REV_PG2_0	1
-
 struct fwl_data {
 	const char *name;
 	u16 fwl_id;
diff --git a/arch/arm/mach-k3/include/mach/hardware.h b/arch/arm/mach-k3/include/mach/hardware.h
index 0ad7614..f2ca80a 100644
--- a/arch/arm/mach-k3/include/mach/hardware.h
+++ b/arch/arm/mach-k3/include/mach/hardware.h
@@ -15,7 +15,6 @@
 #endif
 
 /* Assuming these addresses and definitions stay common across K3 devices */
-#define CTRLMMR_WKUP_JTAG_ID	0x43000014
 #define JTAG_ID_VARIANT_SHIFT	28
 #define JTAG_ID_VARIANT_MASK	(0xf << 28)
 #define JTAG_ID_PARTNO_SHIFT	12
diff --git a/arch/arm/mach-rmobile/Kconfig.64 b/arch/arm/mach-rmobile/Kconfig.64
index c8f93c6..07f607d 100644
--- a/arch/arm/mach-rmobile/Kconfig.64
+++ b/arch/arm/mach-rmobile/Kconfig.64
@@ -2,6 +2,9 @@
 
 menu "Select Target SoC"
 
+config R8A774A1
+        bool "Renesas SoC R8A774A1"
+
 config R8A7795
 	bool "Renesas SoC R8A7795"
 	imply CLK_R8A7795
@@ -43,6 +46,11 @@
 	prompt "Renesas ARM64 SoCs board select"
 	optional
 
+config TARGET_BEACON_RZG2M
+	bool "Beacon EmbeddedWorks RZ/G2M Dev Kit"
+	select R8A774A1
+	select PINCTRL_PFC_R8A774A1
+
 config TARGET_CONDOR
 	bool "Condor board"
 	imply R8A77980
@@ -100,6 +108,7 @@
 source "board/renesas/ebisu/Kconfig"
 source "board/renesas/salvator-x/Kconfig"
 source "board/renesas/ulcb/Kconfig"
+source "board/beacon/beacon-rzg2m/Kconfig"
 
 config MULTI_DTB_FIT_UNCOMPRESS_SZ
 	default 0x80000 if TARGET_SALVATOR_X
diff --git a/arch/arm/mach-snapdragon/clock-snapdragon.c b/arch/arm/mach-snapdragon/clock-snapdragon.c
index 8552618..69d65c8 100644
--- a/arch/arm/mach-snapdragon/clock-snapdragon.c
+++ b/arch/arm/mach-snapdragon/clock-snapdragon.c
@@ -114,7 +114,7 @@
 {
 	struct msm_clk_priv *priv = dev_get_priv(dev);
 
-	priv->base = devfdt_get_addr(dev);
+	priv->base = dev_read_addr(dev);
 	if (priv->base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/arch/arm/mach-snapdragon/pinctrl-snapdragon.c b/arch/arm/mach-snapdragon/pinctrl-snapdragon.c
index 442d236..4c2af21 100644
--- a/arch/arm/mach-snapdragon/pinctrl-snapdragon.c
+++ b/arch/arm/mach-snapdragon/pinctrl-snapdragon.c
@@ -56,7 +56,7 @@
 {
 	struct msm_pinctrl_priv *priv = dev_get_priv(dev);
 
-	priv->base = devfdt_get_addr(dev);
+	priv->base = dev_read_addr(dev);
 	priv->data = (struct msm_pinctrl_data *)dev->driver_data;
 
 	return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0;
diff --git a/arch/nios2/cpu/cpu.c b/arch/nios2/cpu/cpu.c
index 7f5e731..e7ca988 100644
--- a/arch/nios2/cpu/cpu.c
+++ b/arch/nios2/cpu/cpu.c
@@ -79,7 +79,8 @@
 	return 0;
 }
 
-static int altera_nios2_get_desc(struct udevice *dev, char *buf, int size)
+static int altera_nios2_get_desc(const struct udevice *dev, char *buf,
+				 int size)
 {
 	const char *cpu_name = "Nios-II";
 
@@ -90,7 +91,8 @@
 	return 0;
 }
 
-static int altera_nios2_get_info(struct udevice *dev, struct cpu_info *info)
+static int altera_nios2_get_info(const struct udevice *dev,
+				 struct cpu_info *info)
 {
 	info->cpu_freq = gd->cpu_clk;
 	info->features = (1 << CPU_FEAT_L1_CACHE) |
@@ -99,7 +101,7 @@
 	return 0;
 }
 
-static int altera_nios2_get_count(struct udevice *dev)
+static int altera_nios2_get_count(const struct udevice *dev)
 {
 	return 1;
 }
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 3744a46..2ae4239 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -521,6 +521,10 @@
 		};
 	};
 
+	chipid: chipid {
+		compatible = "sandbox,soc";
+	};
+
 	i2s: i2s {
 		compatible = "sandbox,i2s";
 		#sound-dai-cells = <1>;
diff --git a/arch/x86/cpu/apollolake/cpu.c b/arch/x86/cpu/apollolake/cpu.c
index aa7a3db..0a6d2ad 100644
--- a/arch/x86/cpu/apollolake/cpu.c
+++ b/arch/x86/cpu/apollolake/cpu.c
@@ -9,7 +9,7 @@
 #include <asm/cpu_common.h>
 #include <asm/cpu_x86.h>
 
-static int apl_get_info(struct udevice *dev, struct cpu_info *info)
+static int apl_get_info(const struct udevice *dev, struct cpu_info *info)
 {
 	return cpu_intel_get_info(info, INTEL_BCLK_MHZ);
 }
diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c
index 18e48ff..309a50a 100644
--- a/arch/x86/cpu/baytrail/cpu.c
+++ b/arch/x86/cpu/baytrail/cpu.c
@@ -150,7 +150,7 @@
 	return bclk * ((platform_info.lo >> 8) & 0xff);
 }
 
-static int baytrail_get_info(struct udevice *dev, struct cpu_info *info)
+static int baytrail_get_info(const struct udevice *dev, struct cpu_info *info)
 {
 	info->cpu_freq = tsc_freq();
 	info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU;
@@ -158,7 +158,7 @@
 	return 0;
 }
 
-static int baytrail_get_count(struct udevice *dev)
+static int baytrail_get_count(const struct udevice *dev)
 {
 	int ecx = 0;
 
diff --git a/arch/x86/cpu/broadwell/cpu_full.c b/arch/x86/cpu/broadwell/cpu_full.c
index 64a1cd4..706f68f 100644
--- a/arch/x86/cpu/broadwell/cpu_full.c
+++ b/arch/x86/cpu/broadwell/cpu_full.c
@@ -626,12 +626,12 @@
 	}
 }
 
-static int broadwell_get_info(struct udevice *dev, struct cpu_info *info)
+static int broadwell_get_info(const struct udevice *dev, struct cpu_info *info)
 {
 	return cpu_intel_get_info(info, INTEL_BCLK_MHZ);
 }
 
-static int broadwell_get_count(struct udevice *dev)
+static int broadwell_get_count(const struct udevice *dev)
 {
 	return 4;
 }
diff --git a/arch/x86/cpu/cpu_x86.c b/arch/x86/cpu/cpu_x86.c
index 3f2ba08..7e83051 100644
--- a/arch/x86/cpu/cpu_x86.c
+++ b/arch/x86/cpu/cpu_x86.c
@@ -26,7 +26,7 @@
 	return 0;
 }
 
-int cpu_x86_get_vendor(struct udevice *dev, char *buf, int size)
+int cpu_x86_get_vendor(const struct udevice *dev, char *buf, int size)
 {
 	const char *vendor = cpu_vendor_name(gd->arch.x86_vendor);
 
@@ -38,7 +38,7 @@
 	return 0;
 }
 
-int cpu_x86_get_desc(struct udevice *dev, char *buf, int size)
+int cpu_x86_get_desc(const struct udevice *dev, char *buf, int size)
 {
 	char *ptr;
 
@@ -52,7 +52,7 @@
 	return 0;
 }
 
-int cpu_x86_get_count(struct udevice *dev)
+int cpu_x86_get_count(const struct udevice *dev)
 {
 	int node, cpu;
 	int num = 0;
diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c
index 5954a24..55f7cc2 100644
--- a/arch/x86/cpu/ivybridge/model_206ax.c
+++ b/arch/x86/cpu/ivybridge/model_206ax.c
@@ -410,14 +410,15 @@
 	return 0;
 }
 
-static int model_206ax_get_info(struct udevice *dev, struct cpu_info *info)
+static int model_206ax_get_info(const struct udevice *dev,
+				struct cpu_info *info)
 {
 	return cpu_intel_get_info(info, INTEL_BCLK_MHZ);
 
 	return 0;
 }
 
-static int model_206ax_get_count(struct udevice *dev)
+static int model_206ax_get_count(const struct udevice *dev)
 {
 	return 4;
 }
diff --git a/arch/x86/cpu/qemu/cpu.c b/arch/x86/cpu/qemu/cpu.c
index f40fb4d..9ce86b3 100644
--- a/arch/x86/cpu/qemu/cpu.c
+++ b/arch/x86/cpu/qemu/cpu.c
@@ -10,7 +10,7 @@
 #include <qfw.h>
 #include <asm/cpu.h>
 
-int cpu_qemu_get_desc(struct udevice *dev, char *buf, int size)
+int cpu_qemu_get_desc(const struct udevice *dev, char *buf, int size)
 {
 	if (size < CPU_MAX_NAME_LEN)
 		return -ENOSPC;
@@ -20,7 +20,7 @@
 	return 0;
 }
 
-static int cpu_qemu_get_count(struct udevice *dev)
+static int cpu_qemu_get_count(const struct udevice *dev)
 {
 	return qemu_fwcfg_online_cpus();
 }
diff --git a/arch/x86/include/asm/cpu_x86.h b/arch/x86/include/asm/cpu_x86.h
index ae8f4dc..4fd5f03 100644
--- a/arch/x86/include/asm/cpu_x86.h
+++ b/arch/x86/include/asm/cpu_x86.h
@@ -28,7 +28,7 @@
  * @size:	Size of string space
  * @return:	0 if OK, -ENOSPC if buffer is too small, other -ve on error
  */
-int cpu_x86_get_desc(struct udevice *dev, char *buf, int size);
+int cpu_x86_get_desc(const struct udevice *dev, char *buf, int size);
 
 /**
  * cpu_x86_get_count() - Get the number of cores for an x86 CPU
@@ -40,7 +40,7 @@
  * @return:	Number of cores if successful,
  *		-ENOENT if not "/cpus" entry is found in the device tree
  */
-int cpu_x86_get_count(struct udevice *dev);
+int cpu_x86_get_count(const struct udevice *dev);
 
 /**
  * cpu_x86_get_vendor() - Get a vendor string for an x86 CPU
@@ -53,6 +53,6 @@
  * @size:	Size of string space
  * @return:	0 if OK, -ENOSPC if buffer is too small, other -ve on error
  */
-int cpu_x86_get_vendor(struct udevice *dev, char *buf, int size);
+int cpu_x86_get_vendor(const struct udevice *dev, char *buf, int size);
 
 #endif /* _ASM_CPU_X86_H */
diff --git a/board/beacon/beacon-rzg2m/Kconfig b/board/beacon/beacon-rzg2m/Kconfig
new file mode 100644
index 0000000..c03857c
--- /dev/null
+++ b/board/beacon/beacon-rzg2m/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_BEACON_RZG2M
+
+config SYS_SOC
+	default "rmobile"
+
+config SYS_BOARD
+	default "beacon-rzg2m"
+
+config SYS_VENDOR
+	default "beacon"
+
+config SYS_CONFIG_NAME
+	default "beacon-rzg2m"
+
+endif
diff --git a/board/beacon/beacon-rzg2m/MAINTAINERS b/board/beacon/beacon-rzg2m/MAINTAINERS
new file mode 100644
index 0000000..3383a68
--- /dev/null
+++ b/board/beacon/beacon-rzg2m/MAINTAINERS
@@ -0,0 +1,6 @@
+BEACON_RZG2M BOARD
+M:	Adam Ford <aford173@gmail.com>
+S:	Maintained
+F:	board/beacon/beacon-rzg2m/
+F:	include/configs/beacon-rzg2m.h
+F:	configs/r8a774a1_beacon_defconfig
diff --git a/board/beacon/beacon-rzg2m/Makefile b/board/beacon/beacon-rzg2m/Makefile
new file mode 100644
index 0000000..439f319
--- /dev/null
+++ b/board/beacon/beacon-rzg2m/Makefile
@@ -0,0 +1,9 @@
+#
+# board/renesas/hihope-rzg2m/Makefile
+#
+# Copyright (C) 2019 Renesas Electronics Corporation
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y	:= beacon-rzg2m.o
diff --git a/board/beacon/beacon-rzg2m/beacon-rzg2m.c b/board/beacon/beacon-rzg2m/beacon-rzg2m.c
new file mode 100644
index 0000000..86a24dd
--- /dev/null
+++ b/board/beacon/beacon-rzg2m/beacon-rzg2m.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 Compass Electronics Group, LLC
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/rcar-mstp.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void s_init(void)
+{
+}
+
+/* Kconfig forces this on, so just return 0 */
+int board_early_init_f(void)
+{
+	return 0;
+}
+
+int board_init(void)
+{
+	/* address of boot parameters */
+	gd->bd->bi_boot_params = CONFIG_SYS_TEXT_BASE + 0x50000;
+
+	return 0;
+}
+
+int dram_init(void)
+{
+	if (fdtdec_setup_mem_size_base() != 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+int dram_init_banksize(void)
+{
+	fdtdec_setup_memory_banksize();
+
+	return 0;
+}
+
+#define RST_BASE	0xE6160000
+#define RST_CA57RESCNT	(RST_BASE + 0x40)
+#define RST_CODE	0xA5A5000F
+
+void reset_cpu(ulong addr)
+{
+	writel(RST_CODE, RST_CA57RESCNT);
+}
diff --git a/board/renesas/rcar-common/common.c b/board/renesas/rcar-common/common.c
index 9f50f36..83dd288 100644
--- a/board/renesas/rcar-common/common.c
+++ b/board/renesas/rcar-common/common.c
@@ -33,12 +33,12 @@
 
 int dram_init(void)
 {
-	return fdtdec_setup_mem_size_base_fdt(gd->fdt_blob);
+	return fdtdec_setup_mem_size_base();
 }
 
 int dram_init_banksize(void)
 {
-	fdtdec_setup_memory_banksize_fdt(gd->fdt_blob);
+	fdtdec_setup_memory_banksize();
 
 	return 0;
 }
diff --git a/cmd/Kconfig b/cmd/Kconfig
index bfe6c16..e2b0a4f 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -601,6 +601,7 @@
 	  This command can be optionally used for evaluation in scripts:
 	  [-d] : evaluate whether default environment is used
 	  [-p] : evaluate whether environment can be persisted
+	  [-q] : quiet output
 	  The result of multiple evaluations will be combined with AND.
 
 endmenu
diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index ca0be92..acd9f82 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -1224,12 +1224,18 @@
  * env info - display environment information
  * env info [-d] - evaluate whether default environment is used
  * env info [-p] - evaluate whether environment can be persisted
+ *      Add [-q] - quiet mode, use only for command result, for test by example:
+ *                 test env info -p -d -q
  */
 static int do_env_info(struct cmd_tbl *cmdtp, int flag,
 		       int argc, char *const argv[])
 {
 	int eval_flags = 0;
 	int eval_results = 0;
+	bool quiet = false;
+#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
+	enum env_location loc;
+#endif
 
 	/* display environment information */
 	if (argc <= 1)
@@ -1247,6 +1253,9 @@
 			case 'p':
 				eval_flags |= ENV_INFO_IS_PERSISTED;
 				break;
+			case 'q':
+				quiet = true;
+				break;
 			default:
 				return CMD_RET_USAGE;
 			}
@@ -1256,20 +1265,30 @@
 	/* evaluate whether default environment is used */
 	if (eval_flags & ENV_INFO_IS_DEFAULT) {
 		if (gd->flags & GD_FLG_ENV_DEFAULT) {
-			printf("Default environment is used\n");
+			if (!quiet)
+				printf("Default environment is used\n");
 			eval_results |= ENV_INFO_IS_DEFAULT;
 		} else {
-			printf("Environment was loaded from persistent storage\n");
+			if (!quiet)
+				printf("Environment was loaded from persistent storage\n");
 		}
 	}
 
 	/* evaluate whether environment can be persisted */
 	if (eval_flags & ENV_INFO_IS_PERSISTED) {
 #if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
-		printf("Environment can be persisted\n");
-		eval_results |= ENV_INFO_IS_PERSISTED;
+		loc = env_get_location(ENVOP_SAVE, gd->env_load_prio);
+		if (ENVL_NOWHERE != loc && ENVL_UNKNOWN != loc) {
+			if (!quiet)
+				printf("Environment can be persisted\n");
+			eval_results |= ENV_INFO_IS_PERSISTED;
+		} else {
+			if (!quiet)
+				printf("Environment cannot be persisted\n");
+		}
 #else
-		printf("Environment cannot be persisted\n");
+		if (!quiet)
+			printf("Environment cannot be persisted\n");
 #endif
 	}
 
@@ -1326,7 +1345,7 @@
 	U_BOOT_CMD_MKENT(import, 5, 0, do_env_import, "", ""),
 #endif
 #if defined(CONFIG_CMD_NVEDIT_INFO)
-	U_BOOT_CMD_MKENT(info, 2, 0, do_env_info, "", ""),
+	U_BOOT_CMD_MKENT(info, 3, 0, do_env_info, "", ""),
 #endif
 	U_BOOT_CMD_MKENT(print, CONFIG_SYS_MAXARGS, 1, do_env_print, "", ""),
 #if defined(CONFIG_CMD_RUN)
@@ -1405,8 +1424,10 @@
 #endif
 #if defined(CONFIG_CMD_NVEDIT_INFO)
 	"env info - display environment information\n"
-	"env info [-d] - whether default environment is used\n"
-	"env info [-p] - whether environment can be persisted\n"
+	"env info [-d] [-p] [-q] - evaluate environment information\n"
+	"      \"-d\": default environment is used\n"
+	"      \"-p\": environment can be persisted\n"
+	"      \"-q\": quiet output\n"
 #endif
 	"env print [-a | name ...] - print environment\n"
 #if defined(CONFIG_CMD_NVEDIT_EFI)
diff --git a/common/fdt_region.c b/common/fdt_region.c
index 6676590..ff12c51 100644
--- a/common/fdt_region.c
+++ b/common/fdt_region.c
@@ -65,6 +65,8 @@
 			stop_at = offset;
 			prop = fdt_get_property_by_offset(fdt, offset, NULL);
 			str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+			if (!str)
+				return -FDT_ERR_BADSTRUCTURE;
 			if (str_in_list(str, exc_prop, exc_prop_count))
 				include = 0;
 			break;
diff --git a/common/fdt_support.c b/common/fdt_support.c
index 3778de5..a565b47 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -816,8 +816,8 @@
 	return 0;
 }
 
-int fdt_node_set_part_info(void *blob, int parent_offset,
-			   struct mtd_device *dev)
+static int fdt_node_set_part_info(void *blob, int parent_offset,
+				  struct mtd_device *dev)
 {
 	struct list_head *pentry;
 	struct part_info *part;
@@ -951,27 +951,35 @@
 	struct mtd_device *dev;
 	int i, idx;
 	int noff;
-
-	if (mtdparts_init() != 0)
-		return;
+	bool inited = false;
 
 	for (i = 0; i < node_info_size; i++) {
 		idx = 0;
-		noff = fdt_node_offset_by_compatible(blob, -1,
-						     node_info[i].compat);
-		while (noff != -FDT_ERR_NOTFOUND) {
+		noff = -1;
+
+		while ((noff = fdt_node_offset_by_compatible(blob, noff,
+						node_info[i].compat)) >= 0) {
+			const char *prop;
+
+			prop = fdt_getprop(blob, noff, "status", NULL);
+			if (prop && !strcmp(prop, "disabled"))
+				continue;
+
 			debug("%s: %s, mtd dev type %d\n",
 				fdt_get_name(blob, noff, 0),
 				node_info[i].compat, node_info[i].type);
+
+			if (!inited) {
+				if (mtdparts_init() != 0)
+					return;
+				inited = true;
+			}
+
 			dev = device_find(node_info[i].type, idx++);
 			if (dev) {
 				if (fdt_node_set_part_info(blob, noff, dev))
 					return; /* return on error */
 			}
-
-			/* Jump to next flash node */
-			noff = fdt_node_offset_by_compatible(blob, noff,
-							     node_info[i].compat);
 		}
 	}
 }
diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig
index 918ff4d..e8f0adb 100644
--- a/configs/am65x_evm_a53_defconfig
+++ b/configs/am65x_evm_a53_defconfig
@@ -146,3 +146,5 @@
 CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_SOC_DEVICE=y
+CONFIG_SOC_DEVICE_TI_K3=y
diff --git a/configs/am65x_evm_r5_defconfig b/configs/am65x_evm_r5_defconfig
index 09c8b74..81ef413 100644
--- a/configs/am65x_evm_r5_defconfig
+++ b/configs/am65x_evm_r5_defconfig
@@ -120,3 +120,5 @@
 CONFIG_SPL_TIMER=y
 CONFIG_OMAP_TIMER=y
 CONFIG_FS_FAT_MAX_CLUSTSIZE=16384
+CONFIG_SOC_DEVICE=y
+CONFIG_SOC_DEVICE_TI_K3=y
diff --git a/configs/am65x_hs_evm_a53_defconfig b/configs/am65x_hs_evm_a53_defconfig
index bc3da74..b58381e 100644
--- a/configs/am65x_hs_evm_a53_defconfig
+++ b/configs/am65x_hs_evm_a53_defconfig
@@ -148,3 +148,5 @@
 CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_SOC_DEVICE=y
+CONFIG_SOC_DEVICE_TI_K3=y
diff --git a/configs/am65x_hs_evm_r5_defconfig b/configs/am65x_hs_evm_r5_defconfig
index ead4a59..e24311a 100644
--- a/configs/am65x_hs_evm_r5_defconfig
+++ b/configs/am65x_hs_evm_r5_defconfig
@@ -121,3 +121,5 @@
 CONFIG_SPL_TIMER=y
 CONFIG_OMAP_TIMER=y
 CONFIG_FS_FAT_MAX_CLUSTSIZE=16384
+CONFIG_SOC_DEVICE=y
+CONFIG_SOC_DEVICE_TI_K3=y
diff --git a/configs/integratorap_cm720t_defconfig b/configs/integratorap_cm720t_defconfig
index 1b7d672..0d9746b 100644
--- a/configs/integratorap_cm720t_defconfig
+++ b/configs/integratorap_cm720t_defconfig
@@ -25,6 +25,7 @@
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
 CONFIG_EEPRO100=y
+CONFIG_TULIP=y
 CONFIG_PCI=y
 CONFIG_BAUDRATE=38400
 CONFIG_OF_LIBFDT=y
diff --git a/configs/integratorap_cm920t_defconfig b/configs/integratorap_cm920t_defconfig
index 116ac01..7d71648 100644
--- a/configs/integratorap_cm920t_defconfig
+++ b/configs/integratorap_cm920t_defconfig
@@ -25,6 +25,7 @@
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
 CONFIG_EEPRO100=y
+CONFIG_TULIP=y
 CONFIG_PCI=y
 CONFIG_BAUDRATE=38400
 CONFIG_OF_LIBFDT=y
diff --git a/configs/integratorap_cm926ejs_defconfig b/configs/integratorap_cm926ejs_defconfig
index 9c1a3fa..921a75e 100644
--- a/configs/integratorap_cm926ejs_defconfig
+++ b/configs/integratorap_cm926ejs_defconfig
@@ -25,6 +25,7 @@
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
 CONFIG_EEPRO100=y
+CONFIG_TULIP=y
 CONFIG_PCI=y
 CONFIG_BAUDRATE=38400
 CONFIG_OF_LIBFDT=y
diff --git a/configs/integratorap_cm946es_defconfig b/configs/integratorap_cm946es_defconfig
index ee9c69b..4032da9 100644
--- a/configs/integratorap_cm946es_defconfig
+++ b/configs/integratorap_cm946es_defconfig
@@ -25,6 +25,7 @@
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
 CONFIG_EEPRO100=y
+CONFIG_TULIP=y
 CONFIG_PCI=y
 CONFIG_BAUDRATE=38400
 CONFIG_OF_LIBFDT=y
diff --git a/configs/j721e_evm_a72_defconfig b/configs/j721e_evm_a72_defconfig
index 09a73e5..e85abee 100644
--- a/configs/j721e_evm_a72_defconfig
+++ b/configs/j721e_evm_a72_defconfig
@@ -170,3 +170,5 @@
 CONFIG_TI_J721E_UFS=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_SOC_DEVICE=y
+CONFIG_SOC_DEVICE_TI_K3=y
diff --git a/configs/j721e_evm_r5_defconfig b/configs/j721e_evm_r5_defconfig
index a06fc7c..488dae2 100644
--- a/configs/j721e_evm_r5_defconfig
+++ b/configs/j721e_evm_r5_defconfig
@@ -135,3 +135,5 @@
 CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_FS_EXT4=y
 CONFIG_FS_FAT_MAX_CLUSTSIZE=16384
+CONFIG_SOC_DEVICE=y
+CONFIG_SOC_DEVICE_TI_K3=y
diff --git a/configs/j721e_hs_evm_a72_defconfig b/configs/j721e_hs_evm_a72_defconfig
index 9b5bc6c..fa92887 100644
--- a/configs/j721e_hs_evm_a72_defconfig
+++ b/configs/j721e_hs_evm_a72_defconfig
@@ -158,3 +158,5 @@
 CONFIG_TI_J721E_UFS=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_SOC_DEVICE=y
+CONFIG_SOC_DEVICE_TI_K3=y
diff --git a/configs/j721e_hs_evm_r5_defconfig b/configs/j721e_hs_evm_r5_defconfig
index 1aa899e..c8773aa 100644
--- a/configs/j721e_hs_evm_r5_defconfig
+++ b/configs/j721e_hs_evm_r5_defconfig
@@ -116,3 +116,5 @@
 CONFIG_OMAP_TIMER=y
 CONFIG_FS_EXT4=y
 CONFIG_FS_FAT_MAX_CLUSTSIZE=16384
+CONFIG_SOC_DEVICE=y
+CONFIG_SOC_DEVICE_TI_K3=y
diff --git a/configs/r8a774a1_beacon_defconfig b/configs/r8a774a1_beacon_defconfig
new file mode 100644
index 0000000..b62d670
--- /dev/null
+++ b/configs/r8a774a1_beacon_defconfig
@@ -0,0 +1,64 @@
+CONFIG_ARM=y
+CONFIG_ARCH_RMOBILE=y
+CONFIG_SYS_TEXT_BASE=0x50000000
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ENV_OFFSET=0x0
+CONFIG_DM_GPIO=y
+CONFIG_RCAR_GEN3=y
+CONFIG_TARGET_BEACON_RZG2M=y
+# CONFIG_SPL is not set
+CONFIG_SMBIOS_PRODUCT_NAME=""
+CONFIG_FIT=y
+# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
+CONFIG_SUPPORT_RAW_INITRD=y
+CONFIG_DEFAULT_FDT_FILE="r8a774a1-beacon-rzg2m-kit.dtb"
+CONFIG_VERSION_VARIABLE=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_OF_CONTROL=y
+CONFIG_DEFAULT_DEVICE_TREE="r8a774a1-beacon-rzg2m-kit"
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CLK=y
+CONFIG_CLK_RENESAS=y
+CONFIG_RCAR_GPIO=y
+CONFIG_DM_PCA953X=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_RCAR_I2C=y
+CONFIG_SYS_I2C_RCAR_IIC=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_IO_VOLTAGE=y
+CONFIG_MMC_UHS_SUPPORT=y
+CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_RENESAS_SDHI=y
+CONFIG_BITBANGMII=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DM_ETH=y
+CONFIG_RENESAS_RAVB=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_GPIO=y
+CONFIG_SPECIFY_CONSOLE_INDEX=y
+CONFIG_SCIF_CONSOLE=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_STORAGE=y
+CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_SMBIOS_MANUFACTURER=""
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index dcf2f44..5794d1d 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -30,6 +30,7 @@
 CONFIG_CMD_ENV_CALLBACK=y
 CONFIG_CMD_ENV_FLAGS=y
 CONFIG_CMD_NVEDIT_EFI=y
+CONFIG_CMD_NVEDIT_INFO=y
 CONFIG_LOOPW=y
 CONFIG_CMD_MD5SUM=y
 CONFIG_CMD_MEMINFO=y
@@ -118,6 +119,7 @@
 CONFIG_DM_MAILBOX=y
 CONFIG_SANDBOX_MBOX=y
 CONFIG_MISC=y
+CONFIG_SOC_DEVICE=y
 CONFIG_CROS_EC=y
 CONFIG_CROS_EC_I2C=y
 CONFIG_CROS_EC_LPC=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 6059d66..4110497 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -34,6 +34,7 @@
 CONFIG_CMD_ENV_CALLBACK=y
 CONFIG_CMD_ENV_FLAGS=y
 CONFIG_CMD_NVEDIT_EFI=y
+CONFIG_CMD_NVEDIT_INFO=y
 CONFIG_LOOPW=y
 CONFIG_CMD_MD5SUM=y
 CONFIG_CMD_MEMINFO=y
@@ -139,6 +140,7 @@
 CONFIG_DM_MAILBOX=y
 CONFIG_SANDBOX_MBOX=y
 CONFIG_MISC=y
+CONFIG_SOC_DEVICE=y
 CONFIG_CROS_EC=y
 CONFIG_CROS_EC_I2C=y
 CONFIG_CROS_EC_LPC=y
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index 4158b9b..bea27f6 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -24,6 +24,7 @@
 # CONFIG_CMD_ELF is not set
 CONFIG_CMD_ASKENV=y
 CONFIG_CMD_GREPENV=y
+CONFIG_CMD_NVEDIT_INFO=y
 CONFIG_LOOPW=y
 CONFIG_CMD_MD5SUM=y
 CONFIG_CMD_MEMINFO=y
@@ -103,6 +104,7 @@
 CONFIG_DM_MAILBOX=y
 CONFIG_SANDBOX_MBOX=y
 CONFIG_MISC=y
+CONFIG_SOC_DEVICE=y
 CONFIG_CROS_EC=y
 CONFIG_CROS_EC_I2C=y
 CONFIG_CROS_EC_LPC=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index b3274a9..ffb6a6f 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -34,6 +34,7 @@
 CONFIG_CMD_GREPENV=y
 CONFIG_CMD_ENV_CALLBACK=y
 CONFIG_CMD_ENV_FLAGS=y
+CONFIG_CMD_NVEDIT_INFO=y
 CONFIG_LOOPW=y
 CONFIG_CMD_MD5SUM=y
 CONFIG_CMD_MEMINFO=y
@@ -120,6 +121,7 @@
 CONFIG_DM_MAILBOX=y
 CONFIG_SANDBOX_MBOX=y
 CONFIG_MISC=y
+CONFIG_SOC_DEVICE=y
 CONFIG_CROS_EC=y
 CONFIG_CROS_EC_I2C=y
 CONFIG_CROS_EC_LPC=y
diff --git a/doc/driver-model/index.rst b/doc/driver-model/index.rst
index b9df221..f17c72c 100644
--- a/doc/driver-model/index.rst
+++ b/doc/driver-model/index.rst
@@ -19,5 +19,6 @@
    pmic-framework
    remoteproc-framework
    serial-howto
+   soc-framework
    spi-howto
    usb-info
diff --git a/doc/driver-model/soc-framework.rst b/doc/driver-model/soc-framework.rst
new file mode 100644
index 0000000..2609fda
--- /dev/null
+++ b/doc/driver-model/soc-framework.rst
@@ -0,0 +1,68 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. (C) Copyright 2020
+.. Texas Instruments Incorporated - http://www.ti.com/
+
+SOC ID Framework
+================
+
+Introduction
+------------
+
+The driver-model SOC ID framework is able to provide identification
+information about a specific SoC in use at runtime, and also provide matching
+from a set of identification information from an array. This can be useful for
+enabling small quirks in drivers that exist between SoC variants that are
+impractical to implement using device tree flags. It is based on UCLASS_SOC.
+
+UCLASS_SOC:
+  - drivers/soc/soc-uclass.c
+  - include/soc.h
+
+Configuration:
+  - CONFIG_SOC_DEVICE is selected by drivers as needed.
+
+Implementing a UCLASS_SOC provider
+----------------------------------
+
+The purpose of this framework is to allow UCLASS_SOC provider drivers to supply
+identification information about the SoC in use at runtime. The framework
+allows drivers to define soc_ops that return identification strings.  All
+soc_ops need not be defined and can be left as NULL, in which case the
+framework will return -ENOSYS and not consider the value when doing an
+soc_device_match.
+
+It is left to the driver implementor to decide how the information returned is
+determined, but in general the same SOC should always return the same set of
+identifying information. Information returned must be in the form of a NULL
+terminated string.
+
+See include/soc.h for documentation of the available soc_ops and the intended
+meaning of the values that can be returned. See drivers/soc/soc_sandbox.c for
+an example UCLASS_SOC provider driver.
+
+Using a UCLASS_SOC driver
+-------------------------
+
+The framework provides the ability to retrieve and use the identification
+strings directly. It also has the ability to return a match from a list of
+different sets of SoC data using soc_device_match.
+
+An array of 'struct soc_attr' can be defined, each containing ID information
+for a specific SoC, and when passed to soc_device_match, the identifier values
+for each entry in the list will be compared against the values provided by the
+UCLASS_SOC driver that is in use. The first entry in the list that matches all
+non-null values will be returned by soc_device_match.
+
+An example of various uses of the framework can be found at test/dm/soc.c.
+
+Describing the device using device tree
+---------------------------------------
+
+.. code-block:: none
+
+   chipid: chipid {
+        compatible = "sandbox,soc";
+   };
+
+All that is required in a DT node is a compatible for a corresponding
+UCLASS_SOC driver.
diff --git a/doc/mkimage.1 b/doc/mkimage.1
index 3dcdced..fea5288 100644
--- a/doc/mkimage.1
+++ b/doc/mkimage.1
@@ -167,6 +167,15 @@
 must be verified for the image to boot. Without this option, the verification
 will be optional (useful for testing but not for release).
 
+.TP
+.BI "\-t
+Update the timestamp in the FIT.
+
+Normally the FIT timestamp is created the first time mkimage is run on a FIT,
+when converting the source .its to the binary .fit file. This corresponds to
+using the -f flag. But if the original input to mkimage is a binary file
+(already compiled) then the timestamp is assumed to have been set previously.
+
 .SH EXAMPLES
 
 List image information:
diff --git a/drivers/adc/exynos-adc.c b/drivers/adc/exynos-adc.c
index 12c49fc..b459b57 100644
--- a/drivers/adc/exynos-adc.c
+++ b/drivers/adc/exynos-adc.c
@@ -106,7 +106,7 @@
 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
 	struct exynos_adc_priv *priv = dev_get_priv(dev);
 
-	priv->regs = (struct exynos_adc_v2 *)devfdt_get_addr(dev);
+	priv->regs = dev_read_addr_ptr(dev);
 	if (priv->regs == (struct exynos_adc_v2 *)FDT_ADDR_T_NONE) {
 		pr_err("Dev: %s - can't get address!", dev->name);
 		return -ENODATA;
diff --git a/drivers/ata/dwc_ahci.c b/drivers/ata/dwc_ahci.c
index 017650a..825fe57 100644
--- a/drivers/ata/dwc_ahci.c
+++ b/drivers/ata/dwc_ahci.c
@@ -34,7 +34,7 @@
 	struct dwc_ahci_priv *priv = dev_get_priv(dev);
 	fdt_addr_t addr;
 
-	priv->base = map_physmem(devfdt_get_addr(dev), sizeof(void *),
+	priv->base = map_physmem(dev_read_addr(dev), sizeof(void *),
 				 MAP_NOCACHE);
 
 	addr = devfdt_get_addr_index(dev, 1);
diff --git a/drivers/clk/altera/clk-agilex.c b/drivers/clk/altera/clk-agilex.c
index 0042958..9927ada 100644
--- a/drivers/clk/altera/clk-agilex.c
+++ b/drivers/clk/altera/clk-agilex.c
@@ -553,7 +553,7 @@
 	struct socfpga_clk_platdata *plat = dev_get_platdata(dev);
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 	plat->regs = (void __iomem *)addr;
diff --git a/drivers/clk/altera/clk-arria10.c b/drivers/clk/altera/clk-arria10.c
index ede0be2..732ed4d 100644
--- a/drivers/clk/altera/clk-arria10.c
+++ b/drivers/clk/altera/clk-arria10.c
@@ -285,7 +285,7 @@
 	socfpga_a10_handoff_workaround(dev);
 
 	if (!fdt_node_check_compatible(fdt, offset, "altr,clk-mgr")) {
-		plat->regs = devfdt_get_addr(dev);
+		plat->regs = dev_read_addr(dev);
 	} else {
 		pdev = dev_get_parent(dev);
 		if (!pdev)
diff --git a/drivers/clk/exynos/clk-exynos7420.c b/drivers/clk/exynos/clk-exynos7420.c
index aa86c7c..4a023ea 100644
--- a/drivers/clk/exynos/clk-exynos7420.c
+++ b/drivers/clk/exynos/clk-exynos7420.c
@@ -95,7 +95,7 @@
 	fdt_addr_t base;
 	int ret;
 
-	base = devfdt_get_addr(dev);
+	base = dev_read_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
@@ -149,7 +149,7 @@
 	if (!priv)
 		return -EINVAL;
 
-	base = devfdt_get_addr(dev);
+	base = dev_read_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig
index e788178..284e213 100644
--- a/drivers/clk/renesas/Kconfig
+++ b/drivers/clk/renesas/Kconfig
@@ -48,6 +48,13 @@
 	help
 	  Enable this to support the clocks on Renesas RCar Gen3 SoC.
 
+config CLK_R8A774A1
+        bool "Renesas R8A774A1 clock driver"
+        def_bool y if R8A774A1
+        depends on CLK_RCAR_GEN3
+        help
+          Enable this to support the clocks on Renesas R8A774A1 SoC.
+
 config CLK_R8A7795
 	bool "Renesas R8A7795 clock driver"
 	depends on CLK_RCAR_GEN3
diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile
index 88339e9..dd599b7 100644
--- a/drivers/clk/renesas/Makefile
+++ b/drivers/clk/renesas/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_CLK_RENESAS) += renesas-cpg-mssr.o
 obj-$(CONFIG_CLK_RCAR_GEN2) += clk-rcar-gen2.o
+obj-$(CONFIG_CLK_R8A774A1) += r8a774a1-cpg-mssr.o
 obj-$(CONFIG_CLK_R8A7790) += r8a7790-cpg-mssr.o
 obj-$(CONFIG_CLK_R8A7791) += r8a7791-cpg-mssr.o
 obj-$(CONFIG_CLK_R8A7792) += r8a7792-cpg-mssr.o
diff --git a/drivers/clk/renesas/clk-rcar-gen2.c b/drivers/clk/renesas/clk-rcar-gen2.c
index 3ed0aa9..16da10c 100644
--- a/drivers/clk/renesas/clk-rcar-gen2.c
+++ b/drivers/clk/renesas/clk-rcar-gen2.c
@@ -283,7 +283,7 @@
 	u32 cpg_mode;
 	int ret;
 
-	priv->base = (struct gen2_base *)devfdt_get_addr(dev);
+	priv->base = dev_read_addr_ptr(dev);
 	if (!priv->base)
 		return -EINVAL;
 
diff --git a/drivers/clk/renesas/clk-rcar-gen3.c b/drivers/clk/renesas/clk-rcar-gen3.c
index 15e3833..30a101f 100644
--- a/drivers/clk/renesas/clk-rcar-gen3.c
+++ b/drivers/clk/renesas/clk-rcar-gen3.c
@@ -359,7 +359,7 @@
 	u32 cpg_mode;
 	int ret;
 
-	priv->base = (struct gen3_base *)devfdt_get_addr(dev);
+	priv->base = dev_read_addr_ptr(dev);
 	if (!priv->base)
 		return -EINVAL;
 
diff --git a/drivers/clk/renesas/r8a774a1-cpg-mssr.c b/drivers/clk/renesas/r8a774a1-cpg-mssr.c
new file mode 100644
index 0000000..8935667
--- /dev/null
+++ b/drivers/clk/renesas/r8a774a1-cpg-mssr.c
@@ -0,0 +1,339 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Renesas R8A774A1 CPG MSSR driver
+ *
+ * Copyright (C) 2017-2019 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on the following driver from Linux kernel:
+ * r8a7796 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2016 Glider bvba
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+
+#include <dt-bindings/clock/r8a774a1-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen3-cpg.h"
+
+enum clk_ids {
+	/* Core Clock Outputs exported to DT */
+	LAST_DT_CORE_CLK = R8A774A1_CLK_CANFD,
+
+	/* External Input Clocks */
+	CLK_EXTAL,
+	CLK_EXTALR,
+
+	/* Internal Core Clocks */
+	CLK_MAIN,
+	CLK_PLL0,
+	CLK_PLL1,
+	CLK_PLL2,
+	CLK_PLL3,
+	CLK_PLL4,
+	CLK_PLL1_DIV2,
+	CLK_PLL1_DIV4,
+	CLK_S0,
+	CLK_S1,
+	CLK_S2,
+	CLK_S3,
+	CLK_SDSRC,
+	CLK_RINT,
+
+	/* Module Clocks */
+	MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a774a1_core_clks[] = {
+	/* External Clock Inputs */
+	DEF_INPUT("extal",      CLK_EXTAL),
+	DEF_INPUT("extalr",     CLK_EXTALR),
+
+	/* Internal Core Clocks */
+	DEF_BASE(".main",       CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
+	DEF_BASE(".pll0",       CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN),
+	DEF_BASE(".pll1",       CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
+	DEF_BASE(".pll2",       CLK_PLL2, CLK_TYPE_GEN3_PLL2, CLK_MAIN),
+	DEF_BASE(".pll3",       CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
+	DEF_BASE(".pll4",       CLK_PLL4, CLK_TYPE_GEN3_PLL4, CLK_MAIN),
+
+	DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2,     CLK_PLL1,       2, 1),
+	DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4,     CLK_PLL1_DIV2,  2, 1),
+	DEF_FIXED(".s0",        CLK_S0,            CLK_PLL1_DIV2,  2, 1),
+	DEF_FIXED(".s1",        CLK_S1,            CLK_PLL1_DIV2,  3, 1),
+	DEF_FIXED(".s2",        CLK_S2,            CLK_PLL1_DIV2,  4, 1),
+	DEF_FIXED(".s3",        CLK_S3,            CLK_PLL1_DIV2,  6, 1),
+	DEF_FIXED(".sdsrc",     CLK_SDSRC,         CLK_PLL1_DIV2,  2, 1),
+
+	DEF_GEN3_OSC(".r",      CLK_RINT,          CLK_EXTAL,      32),
+
+	/* Core Clock Outputs */
+	DEF_GEN3_Z("z",         R8A774A1_CLK_Z,     CLK_TYPE_GEN3_Z,  CLK_PLL0, 2, 8),
+	DEF_GEN3_Z("z2",        R8A774A1_CLK_Z2,    CLK_TYPE_GEN3_Z,  CLK_PLL2, 2, 0),
+	DEF_FIXED("ztr",        R8A774A1_CLK_ZTR,   CLK_PLL1_DIV2,  6, 1),
+	DEF_FIXED("ztrd2",      R8A774A1_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
+	DEF_FIXED("zt",         R8A774A1_CLK_ZT,    CLK_PLL1_DIV2,  4, 1),
+	DEF_FIXED("zx",         R8A774A1_CLK_ZX,    CLK_PLL1_DIV2,  2, 1),
+	DEF_FIXED("s0d1",       R8A774A1_CLK_S0D1,  CLK_S0,         1, 1),
+	DEF_FIXED("s0d2",       R8A774A1_CLK_S0D2,  CLK_S0,         2, 1),
+	DEF_FIXED("s0d3",       R8A774A1_CLK_S0D3,  CLK_S0,         3, 1),
+	DEF_FIXED("s0d4",       R8A774A1_CLK_S0D4,  CLK_S0,         4, 1),
+	DEF_FIXED("s0d6",       R8A774A1_CLK_S0D6,  CLK_S0,         6, 1),
+	DEF_FIXED("s0d8",       R8A774A1_CLK_S0D8,  CLK_S0,         8, 1),
+	DEF_FIXED("s0d12",      R8A774A1_CLK_S0D12, CLK_S0,        12, 1),
+	DEF_FIXED("s1d2",       R8A774A1_CLK_S1D2,  CLK_S1,         2, 1),
+	DEF_FIXED("s1d4",       R8A774A1_CLK_S1D4,  CLK_S1,         4, 1),
+	DEF_FIXED("s2d1",       R8A774A1_CLK_S2D1,  CLK_S2,         1, 1),
+	DEF_FIXED("s2d2",       R8A774A1_CLK_S2D2,  CLK_S2,         2, 1),
+	DEF_FIXED("s2d4",       R8A774A1_CLK_S2D4,  CLK_S2,         4, 1),
+	DEF_FIXED("s3d1",       R8A774A1_CLK_S3D1,  CLK_S3,         1, 1),
+	DEF_FIXED("s3d2",       R8A774A1_CLK_S3D2,  CLK_S3,         2, 1),
+	DEF_FIXED("s3d4",       R8A774A1_CLK_S3D4,  CLK_S3,         4, 1),
+
+	DEF_GEN3_SD("sd0",      R8A774A1_CLK_SD0,   CLK_SDSRC,     0x074),
+	DEF_GEN3_SD("sd1",      R8A774A1_CLK_SD1,   CLK_SDSRC,     0x078),
+	DEF_GEN3_SD("sd2",      R8A774A1_CLK_SD2,   CLK_SDSRC,     0x268),
+	DEF_GEN3_SD("sd3",      R8A774A1_CLK_SD3,   CLK_SDSRC,     0x26c),
+
+	DEF_FIXED("cl",         R8A774A1_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
+	DEF_FIXED("cp",         R8A774A1_CLK_CP,    CLK_EXTAL,      2, 1),
+	DEF_FIXED("cpex",       R8A774A1_CLK_CPEX,  CLK_EXTAL,      2, 1),
+
+	DEF_DIV6P1("canfd",     R8A774A1_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
+	DEF_DIV6P1("csi0",      R8A774A1_CLK_CSI0,  CLK_PLL1_DIV4, 0x00c),
+	DEF_DIV6P1("mso",       R8A774A1_CLK_MSO,   CLK_PLL1_DIV4, 0x014),
+	DEF_DIV6P1("hdmi",      R8A774A1_CLK_HDMI,  CLK_PLL1_DIV4, 0x250),
+
+	DEF_GEN3_OSC("osc",     R8A774A1_CLK_OSC,   CLK_EXTAL,     8),
+
+	DEF_BASE("r",           R8A774A1_CLK_R,     CLK_TYPE_GEN3_R, CLK_RINT),
+};
+
+static const struct mssr_mod_clk r8a774a1_mod_clks[] = {
+	DEF_MOD("tmu4",			 121,	R8A774A1_CLK_S0D6),
+	DEF_MOD("tmu3",			 122,	R8A774A1_CLK_S3D2),
+	DEF_MOD("tmu2",			 123,	R8A774A1_CLK_S3D2),
+	DEF_MOD("tmu1",			 124,	R8A774A1_CLK_S3D2),
+	DEF_MOD("tmu0",			 125,	R8A774A1_CLK_CP),
+	DEF_MOD("fdp1-0",		 119,	R8A774A1_CLK_S0D1),
+	DEF_MOD("scif5",		 202,	R8A774A1_CLK_S3D4),
+	DEF_MOD("scif4",		 203,	R8A774A1_CLK_S3D4),
+	DEF_MOD("scif3",		 204,	R8A774A1_CLK_S3D4),
+	DEF_MOD("scif1",		 206,	R8A774A1_CLK_S3D4),
+	DEF_MOD("scif0",		 207,	R8A774A1_CLK_S3D4),
+	DEF_MOD("msiof3",		 208,	R8A774A1_CLK_MSO),
+	DEF_MOD("msiof2",		 209,	R8A774A1_CLK_MSO),
+	DEF_MOD("msiof1",		 210,	R8A774A1_CLK_MSO),
+	DEF_MOD("msiof0",		 211,	R8A774A1_CLK_MSO),
+	DEF_MOD("sys-dmac2",		 217,	R8A774A1_CLK_S3D1),
+	DEF_MOD("sys-dmac1",		 218,	R8A774A1_CLK_S3D1),
+	DEF_MOD("sys-dmac0",		 219,	R8A774A1_CLK_S0D3),
+	DEF_MOD("cmt3",			 300,	R8A774A1_CLK_R),
+	DEF_MOD("cmt2",			 301,	R8A774A1_CLK_R),
+	DEF_MOD("cmt1",			 302,	R8A774A1_CLK_R),
+	DEF_MOD("cmt0",			 303,	R8A774A1_CLK_R),
+	DEF_MOD("scif2",		 310,	R8A774A1_CLK_S3D4),
+	DEF_MOD("sdif3",		 311,	R8A774A1_CLK_SD3),
+	DEF_MOD("sdif2",		 312,	R8A774A1_CLK_SD2),
+	DEF_MOD("sdif1",		 313,	R8A774A1_CLK_SD1),
+	DEF_MOD("sdif0",		 314,	R8A774A1_CLK_SD0),
+	DEF_MOD("pcie1",		 318,	R8A774A1_CLK_S3D1),
+	DEF_MOD("pcie0",		 319,	R8A774A1_CLK_S3D1),
+	DEF_MOD("usb3-if0",		 328,	R8A774A1_CLK_S3D1),
+	DEF_MOD("usb-dmac0",		 330,	R8A774A1_CLK_S3D1),
+	DEF_MOD("usb-dmac1",		 331,	R8A774A1_CLK_S3D1),
+	DEF_MOD("rwdt",			 402,	R8A774A1_CLK_R),
+	DEF_MOD("intc-ex",		 407,	R8A774A1_CLK_CP),
+	DEF_MOD("intc-ap",		 408,	R8A774A1_CLK_S0D3),
+	DEF_MOD("audmac1",		 501,	R8A774A1_CLK_S1D2),
+	DEF_MOD("audmac0",		 502,	R8A774A1_CLK_S1D2),
+	DEF_MOD("hscif4",		 516,	R8A774A1_CLK_S3D1),
+	DEF_MOD("hscif3",		 517,	R8A774A1_CLK_S3D1),
+	DEF_MOD("hscif2",		 518,	R8A774A1_CLK_S3D1),
+	DEF_MOD("hscif1",		 519,	R8A774A1_CLK_S3D1),
+	DEF_MOD("hscif0",		 520,	R8A774A1_CLK_S3D1),
+	DEF_MOD("thermal",		 522,	R8A774A1_CLK_CP),
+	DEF_MOD("pwm",			 523,	R8A774A1_CLK_S0D12),
+	DEF_MOD("fcpvd2",		 601,	R8A774A1_CLK_S0D2),
+	DEF_MOD("fcpvd1",		 602,	R8A774A1_CLK_S0D2),
+	DEF_MOD("fcpvd0",		 603,	R8A774A1_CLK_S0D2),
+	DEF_MOD("fcpvb0",		 607,	R8A774A1_CLK_S0D1),
+	DEF_MOD("fcpvi0",		 611,	R8A774A1_CLK_S0D1),
+	DEF_MOD("fcpf0",		 615,	R8A774A1_CLK_S0D1),
+	DEF_MOD("fcpci0",		 617,	R8A774A1_CLK_S0D2),
+	DEF_MOD("fcpcs",		 619,	R8A774A1_CLK_S0D2),
+	DEF_MOD("vspd2",		 621,	R8A774A1_CLK_S0D2),
+	DEF_MOD("vspd1",		 622,	R8A774A1_CLK_S0D2),
+	DEF_MOD("vspd0",		 623,	R8A774A1_CLK_S0D2),
+	DEF_MOD("vspb",			 626,	R8A774A1_CLK_S0D1),
+	DEF_MOD("vspi0",		 631,	R8A774A1_CLK_S0D1),
+	DEF_MOD("ehci1",		 702,	R8A774A1_CLK_S3D2),
+	DEF_MOD("ehci0",		 703,	R8A774A1_CLK_S3D2),
+	DEF_MOD("hsusb",		 704,	R8A774A1_CLK_S3D2),
+	DEF_MOD("csi20",		 714,	R8A774A1_CLK_CSI0),
+	DEF_MOD("csi40",		 716,	R8A774A1_CLK_CSI0),
+	DEF_MOD("du2",			 722,	R8A774A1_CLK_S2D1),
+	DEF_MOD("du1",			 723,	R8A774A1_CLK_S2D1),
+	DEF_MOD("du0",			 724,	R8A774A1_CLK_S2D1),
+	DEF_MOD("lvds",			 727,	R8A774A1_CLK_S2D1),
+	DEF_MOD("hdmi0",		 729,	R8A774A1_CLK_HDMI),
+	DEF_MOD("vin7",			 804,	R8A774A1_CLK_S0D2),
+	DEF_MOD("vin6",			 805,	R8A774A1_CLK_S0D2),
+	DEF_MOD("vin5",			 806,	R8A774A1_CLK_S0D2),
+	DEF_MOD("vin4",			 807,	R8A774A1_CLK_S0D2),
+	DEF_MOD("vin3",			 808,	R8A774A1_CLK_S0D2),
+	DEF_MOD("vin2",			 809,	R8A774A1_CLK_S0D2),
+	DEF_MOD("vin1",			 810,	R8A774A1_CLK_S0D2),
+	DEF_MOD("vin0",			 811,	R8A774A1_CLK_S0D2),
+	DEF_MOD("etheravb",		 812,	R8A774A1_CLK_S0D6),
+	DEF_MOD("gpio7",		 905,	R8A774A1_CLK_S3D4),
+	DEF_MOD("gpio6",		 906,	R8A774A1_CLK_S3D4),
+	DEF_MOD("gpio5",		 907,	R8A774A1_CLK_S3D4),
+	DEF_MOD("gpio4",		 908,	R8A774A1_CLK_S3D4),
+	DEF_MOD("gpio3",		 909,	R8A774A1_CLK_S3D4),
+	DEF_MOD("gpio2",		 910,	R8A774A1_CLK_S3D4),
+	DEF_MOD("gpio1",		 911,	R8A774A1_CLK_S3D4),
+	DEF_MOD("gpio0",		 912,	R8A774A1_CLK_S3D4),
+	DEF_MOD("can-fd",		 914,	R8A774A1_CLK_S3D2),
+	DEF_MOD("can-if1",		 915,	R8A774A1_CLK_S3D4),
+	DEF_MOD("can-if0",		 916,	R8A774A1_CLK_S3D4),
+	DEF_MOD("i2c6",			 918,	R8A774A1_CLK_S0D6),
+	DEF_MOD("i2c5",			 919,	R8A774A1_CLK_S0D6),
+	DEF_MOD("i2c-dvfs",		 926,	R8A774A1_CLK_CP),
+	DEF_MOD("i2c4",			 927,	R8A774A1_CLK_S0D6),
+	DEF_MOD("i2c3",			 928,	R8A774A1_CLK_S0D6),
+	DEF_MOD("i2c2",			 929,	R8A774A1_CLK_S3D2),
+	DEF_MOD("i2c1",			 930,	R8A774A1_CLK_S3D2),
+	DEF_MOD("i2c0",			 931,	R8A774A1_CLK_S3D2),
+	DEF_MOD("ssi-all",		1005,	R8A774A1_CLK_S3D4),
+	DEF_MOD("ssi9",			1006,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi8",			1007,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi7",			1008,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi6",			1009,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi5",			1010,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi4",			1011,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi3",			1012,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi2",			1013,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi1",			1014,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi0",			1015,	MOD_CLK_ID(1005)),
+	DEF_MOD("scu-all",		1017,	R8A774A1_CLK_S3D4),
+	DEF_MOD("scu-dvc1",		1018,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-dvc0",		1019,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-ctu1-mix1",	1020,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-ctu0-mix0",	1021,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src9",		1022,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src8",		1023,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src7",		1024,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src6",		1025,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src5",		1026,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src4",		1027,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src3",		1028,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src2",		1029,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src1",		1030,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src0",		1031,	MOD_CLK_ID(1017)),
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ *   MD		EXTAL		PLL0	PLL1	PLL2	PLL3	PLL4	OSC
+ * 14 13 19 17	(MHz)
+ *-------------------------------------------------------------------------
+ * 0  0  0  0	16.66 x 1	x180	x192	x144	x192	x144	/16
+ * 0  0  0  1	16.66 x 1	x180	x192	x144	x128	x144	/16
+ * 0  0  1  0	Prohibited setting
+ * 0  0  1  1	16.66 x 1	x180	x192	x144	x192	x144	/16
+ * 0  1  0  0	20    x 1	x150	x160	x120	x160	x120	/19
+ * 0  1  0  1	20    x 1	x150	x160	x120	x106	x120	/19
+ * 0  1  1  0	Prohibited setting
+ * 0  1  1  1	20    x 1	x150	x160	x120	x160	x120	/19
+ * 1  0  0  0	25    x 1	x120	x128	x96	x128	x96	/24
+ * 1  0  0  1	25    x 1	x120	x128	x96	x84	x96	/24
+ * 1  0  1  0	Prohibited setting
+ * 1  0  1  1	25    x 1	x120	x128	x96	x128	x96	/24
+ * 1  1  0  0	33.33 / 2	x180	x192	x144	x192	x144	/32
+ * 1  1  0  1	33.33 / 2	x180	x192	x144	x128	x144	/32
+ * 1  1  1  0	Prohibited setting
+ * 1  1  1  1	33.33 / 2	x180	x192	x144	x192	x144	/32
+ */
+#define CPG_PLL_CONFIG_INDEX(md)	((((md) & BIT(14)) >> 11) | \
+					 (((md) & BIT(13)) >> 11) | \
+					 (((md) & BIT(19)) >> 18) | \
+					 (((md) & BIT(17)) >> 17))
+
+static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] = {
+	/* EXTAL div	PLL1 mult/div	PLL3 mult/div	OSC prediv */
+	{ 1,		192,	1,	192,	1,	16,	},
+	{ 1,		192,	1,	128,	1,	16,	},
+	{ 0, /* Prohibited setting */				},
+	{ 1,		192,	1,	192,	1,	16,	},
+	{ 1,		160,	1,	160,	1,	19,	},
+	{ 1,		160,	1,	106,	1,	19,	},
+	{ 0, /* Prohibited setting */				},
+	{ 1,		160,	1,	160,	1,	19,	},
+	{ 1,		128,	1,	128,	1,	24,	},
+	{ 1,		128,	1,	84,	1,	24,	},
+	{ 0, /* Prohibited setting */				},
+	{ 1,		128,	1,	128,	1,	24,	},
+	{ 2,		192,	1,	192,	1,	32,	},
+	{ 2,		192,	1,	128,	1,	32,	},
+	{ 0, /* Prohibited setting */				},
+	{ 2,		192,	1,	192,	1,	32,	},
+};
+
+static const struct mstp_stop_table r8a774a1_mstp_table[] = {
+	{ 0x00000000, 0, 0x00000000, 0 },
+	{ 0xc3e81000, 0, 0xc3e81000, 0 },
+	{ 0x000E0FDC, 0, 0x000E0FDC, 0 },
+	{ 0xD00C7C1F, 0, 0xD00C7C1F, 0 },
+	{ 0x80000004, 0, 0x80000004, 0 },
+	{ 0x00DF0006, 0, 0x00DF0006, 0 },
+	{ 0XC5EACCCE, 0, 0XC5EACCCE, 0 },
+	{ 0x29E1401C, 0, 0x29E1401C, 0 },
+	{ 0x00009FF1, 0, 0x00009FF1, 0 },
+	{ 0xFC4FDFE0, 0, 0xFC4FDFE0, 0 },
+	{ 0xFFFEFFE8, 0, 0xFFFEFFE8, 0 },
+};
+
+static const void *r8a774a1_get_pll_config(const u32 cpg_mode)
+{
+	return &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+}
+
+static const struct cpg_mssr_info r8a774a1_cpg_mssr_info = {
+	.core_clk		= r8a774a1_core_clks,
+	.core_clk_size		= ARRAY_SIZE(r8a774a1_core_clks),
+	.mod_clk		= r8a774a1_mod_clks,
+	.mod_clk_size		= ARRAY_SIZE(r8a774a1_mod_clks),
+	.mstp_table		= r8a774a1_mstp_table,
+	.mstp_table_size	= ARRAY_SIZE(r8a774a1_mstp_table),
+	.reset_node		= "renesas,r8a774a1-rst",
+	.extalr_node		= "extalr",
+	.mod_clk_base		= MOD_CLK_BASE,
+	.clk_extal_id		= CLK_EXTAL,
+	.clk_extalr_id		= CLK_EXTALR,
+	.get_pll_config		= r8a774a1_get_pll_config,
+};
+
+static const struct udevice_id r8a774a1_clk_ids[] = {
+	{
+		.compatible	= "renesas,r8a774a1-cpg-mssr",
+		.data		= (ulong)&r8a774a1_cpg_mssr_info,
+	},
+	{ }
+};
+
+U_BOOT_DRIVER(clk_r8a774a1) = {
+	.name		= "clk_r8a774a1",
+	.id		= UCLASS_CLK,
+	.of_match	= r8a774a1_clk_ids,
+	.priv_auto_alloc_size = sizeof(struct gen3_clk_priv),
+	.ops		= &gen3_clk_ops,
+	.probe		= gen3_clk_probe,
+	.remove		= gen3_clk_remove,
+};
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h
index 7b1b242..3beae7d 100644
--- a/drivers/clk/renesas/rcar-gen3-cpg.h
+++ b/drivers/clk/renesas/rcar-gen3-cpg.h
@@ -56,6 +56,8 @@
 	DEF_BASE(_name, _id, CLK_TYPE_GEN3_RCKSEL,	\
 		 (_parent0) << 16 | (_parent1),	.div = (_div0) << 16 | (_div1))
 
+#define DEF_GEN3_Z(_name, _id, _type, _parent, _div, _offset)	\
+	DEF_BASE(_name, _id, _type, _parent, .div = _div, .offset = _offset)
 
 struct rcar_gen3_cpg_pll_config {
 	u8 extal_div;
diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c
index c9ec523..4e25db3 100644
--- a/drivers/clk/uniphier/clk-uniphier-core.c
+++ b/drivers/clk/uniphier/clk-uniphier-core.c
@@ -253,7 +253,7 @@
 	struct uniphier_clk_priv *priv = dev_get_priv(dev);
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev->parent);
+	addr = dev_read_addr(dev->parent);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 476133f..355dbd1 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -82,7 +82,8 @@
 		 * This is just a 'requested' sequence, and will be
 		 * resolved (and ->seq updated) when the device is probed.
 		 */
-		if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
+		if (CONFIG_IS_ENABLED(OF_CONTROL) &&
+		    !CONFIG_IS_ENABLED(OF_PLATDATA)) {
 			if (uc->uc_drv->name && ofnode_valid(node))
 				dev_read_alias_seq(dev, &dev->req_seq);
 #if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
diff --git a/drivers/cpu/bmips_cpu.c b/drivers/cpu/bmips_cpu.c
index 2649c5c..421cc7a 100644
--- a/drivers/cpu/bmips_cpu.c
+++ b/drivers/cpu/bmips_cpu.c
@@ -379,7 +379,7 @@
 };
 
 /* Generic CPU Ops */
-static int bmips_cpu_get_desc(struct udevice *dev, char *buf, int size)
+static int bmips_cpu_get_desc(const struct udevice *dev, char *buf, int size)
 {
 	struct bmips_cpu_priv *priv = dev_get_priv(dev);
 	const struct bmips_cpu_hw *hw = priv->hw;
@@ -387,7 +387,7 @@
 	return hw->get_cpu_desc(priv, buf, size);
 }
 
-static int bmips_cpu_get_info(struct udevice *dev, struct cpu_info *info)
+static int bmips_cpu_get_info(const struct udevice *dev, struct cpu_info *info)
 {
 	struct bmips_cpu_priv *priv = dev_get_priv(dev);
 	const struct bmips_cpu_hw *hw = priv->hw;
@@ -400,7 +400,7 @@
 	return 0;
 }
 
-static int bmips_cpu_get_count(struct udevice *dev)
+static int bmips_cpu_get_count(const struct udevice *dev)
 {
 	struct bmips_cpu_priv *priv = dev_get_priv(dev);
 	const struct bmips_cpu_hw *hw = priv->hw;
@@ -408,7 +408,7 @@
 	return hw->get_cpu_count(priv);
 }
 
-static int bmips_cpu_get_vendor(struct udevice *dev, char *buf, int size)
+static int bmips_cpu_get_vendor(const struct udevice *dev, char *buf, int size)
 {
 	snprintf(buf, size, "Broadcom");
 
diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c
index cbb4419..37e3cf2 100644
--- a/drivers/cpu/cpu-uclass.c
+++ b/drivers/cpu/cpu-uclass.c
@@ -69,7 +69,7 @@
 	return cpu;
 }
 
-int cpu_get_desc(struct udevice *dev, char *buf, int size)
+int cpu_get_desc(const struct udevice *dev, char *buf, int size)
 {
 	struct cpu_ops *ops = cpu_get_ops(dev);
 
@@ -79,7 +79,7 @@
 	return ops->get_desc(dev, buf, size);
 }
 
-int cpu_get_info(struct udevice *dev, struct cpu_info *info)
+int cpu_get_info(const struct udevice *dev, struct cpu_info *info)
 {
 	struct cpu_ops *ops = cpu_get_ops(dev);
 
@@ -92,7 +92,7 @@
 	return ops->get_info(dev, info);
 }
 
-int cpu_get_count(struct udevice *dev)
+int cpu_get_count(const struct udevice *dev)
 {
 	struct cpu_ops *ops = cpu_get_ops(dev);
 
@@ -102,7 +102,7 @@
 	return ops->get_count(dev);
 }
 
-int cpu_get_vendor(struct udevice *dev, char *buf, int size)
+int cpu_get_vendor(const struct udevice *dev, char *buf, int size)
 {
 	struct cpu_ops *ops = cpu_get_ops(dev);
 
diff --git a/drivers/cpu/cpu_sandbox.c b/drivers/cpu/cpu_sandbox.c
index 30a12e5..caa26e5 100644
--- a/drivers/cpu/cpu_sandbox.c
+++ b/drivers/cpu/cpu_sandbox.c
@@ -8,14 +8,14 @@
 #include <dm.h>
 #include <cpu.h>
 
-int cpu_sandbox_get_desc(struct udevice *dev, char *buf, int size)
+int cpu_sandbox_get_desc(const struct udevice *dev, char *buf, int size)
 {
 	snprintf(buf, size, "LEG Inc. SuperMegaUltraTurbo CPU No. 1");
 
 	return 0;
 }
 
-int cpu_sandbox_get_info(struct udevice *dev, struct cpu_info *info)
+int cpu_sandbox_get_info(const struct udevice *dev, struct cpu_info *info)
 {
 	info->cpu_freq = 42 * 42 * 42 * 42 * 42;
 	info->features = 0x42424242;
@@ -24,12 +24,12 @@
 	return 0;
 }
 
-int cpu_sandbox_get_count(struct udevice *dev)
+int cpu_sandbox_get_count(const struct udevice *dev)
 {
 	return 42;
 }
 
-int cpu_sandbox_get_vendor(struct udevice *dev, char *buf, int size)
+int cpu_sandbox_get_vendor(const struct udevice *dev, char *buf, int size)
 {
 	snprintf(buf, size, "Languid Example Garbage Inc.");
 
diff --git a/drivers/cpu/imx8_cpu.c b/drivers/cpu/imx8_cpu.c
index 6345cd0..502c8eb 100644
--- a/drivers/cpu/imx8_cpu.c
+++ b/drivers/cpu/imx8_cpu.c
@@ -100,7 +100,7 @@
 }
 #endif
 
-int cpu_imx_get_desc(struct udevice *dev, char *buf, int size)
+int cpu_imx_get_desc(const struct udevice *dev, char *buf, int size)
 {
 	struct cpu_imx_platdata *plat = dev_get_platdata(dev);
 	int ret, temp;
@@ -126,7 +126,7 @@
 	return 0;
 }
 
-static int cpu_imx_get_info(struct udevice *dev, struct cpu_info *info)
+static int cpu_imx_get_info(const struct udevice *dev, struct cpu_info *info)
 {
 	struct cpu_imx_platdata *plat = dev_get_platdata(dev);
 
@@ -135,7 +135,7 @@
 	return 0;
 }
 
-static int cpu_imx_get_count(struct udevice *dev)
+static int cpu_imx_get_count(const struct udevice *dev)
 {
 	ofnode node;
 	int num = 0;
@@ -157,7 +157,7 @@
 	return num;
 }
 
-static int cpu_imx_get_vendor(struct udevice *dev,  char *buf, int size)
+static int cpu_imx_get_vendor(const struct udevice *dev,  char *buf, int size)
 {
 	snprintf(buf, size, "NXP");
 	return 0;
diff --git a/drivers/cpu/mpc83xx_cpu.c b/drivers/cpu/mpc83xx_cpu.c
index f8a84ba..5f1592f 100644
--- a/drivers/cpu/mpc83xx_cpu.c
+++ b/drivers/cpu/mpc83xx_cpu.c
@@ -60,7 +60,7 @@
  * determine_type() - Determine CPU family of MPC83xx device
  * @dev: CPU device from which to read CPU family from
  */
-static inline void determine_family(struct udevice *dev)
+static inline void determine_family(const struct udevice *dev)
 {
 	struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
 	/* Upper 12 bits of PARTID field (bits 0-23 in SPRIDR) */
@@ -95,7 +95,7 @@
  * determine_type() - Determine CPU type of MPC83xx device
  * @dev: CPU device from which to read CPU type from
  */
-static inline void determine_type(struct udevice *dev)
+static inline void determine_type(const struct udevice *dev)
 {
 	struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
 	/* Upper 16 bits of PVR (Processor Version Register) */
@@ -169,7 +169,7 @@
  * determine_e300_type() - Determine e300 core type of MPC83xx device
  * @dev: CPU device from which to read e300 core type from
  */
-static inline void determine_e300_type(struct udevice *dev)
+static inline void determine_e300_type(const struct udevice *dev)
 {
 	struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
 	/* Upper 16 bits of PVR (Processor Version Register) */
@@ -198,7 +198,7 @@
  * determine_revid() - Determine revision ID of CPU device
  * @dev: CPU device from which to read revision ID
  */
-static inline void determine_revid(struct udevice *dev)
+static inline void determine_revid(const struct udevice *dev)
 {
 	struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
 	u32 REVID_MAJOR_MASK;
@@ -221,7 +221,7 @@
  * determine_cpu_data() - Determine CPU information from hardware
  * @dev: CPU device from which to read information
  */
-static void determine_cpu_data(struct udevice *dev)
+static void determine_cpu_data(const struct udevice *dev)
 {
 	struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
 	const u32 E_FLAG_MASK = 0x00010000;
@@ -239,7 +239,7 @@
 	priv->is_e_processor = !bitfield_extract_by_mask(spridr, E_FLAG_MASK);
 }
 
-static int mpc83xx_cpu_get_desc(struct udevice *dev, char *buf, int size)
+static int mpc83xx_cpu_get_desc(const struct udevice *dev, char *buf, int size)
 {
 	struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
 	struct clk core_clk;
@@ -248,14 +248,14 @@
 	char csb_freq[32];
 	int ret;
 
-	ret = clk_get_by_index(dev, 0, &core_clk);
+	ret = clk_get_by_index((struct udevice *)dev, 0, &core_clk);
 	if (ret) {
 		debug("%s: Failed to get core clock (err = %d)\n",
 		      dev->name, ret);
 		return ret;
 	}
 
-	ret = clk_get_by_index(dev, 1, &csb_clk);
+	ret = clk_get_by_index((struct udevice *)dev, 1, &csb_clk);
 	if (ret) {
 		debug("%s: Failed to get CSB clock (err = %d)\n",
 		      dev->name, ret);
@@ -278,13 +278,14 @@
 	return 0;
 }
 
-static int mpc83xx_cpu_get_info(struct udevice *dev, struct cpu_info *info)
+static int mpc83xx_cpu_get_info(const struct udevice *dev,
+				struct cpu_info *info)
 {
 	struct clk clock;
 	int ret;
 	ulong freq;
 
-	ret = clk_get_by_index(dev, 0, &clock);
+	ret = clk_get_by_index((struct udevice *)dev, 0, &clock);
 	if (ret) {
 		debug("%s: Failed to get core clock (err = %d)\n",
 		      dev->name, ret);
@@ -303,13 +304,14 @@
 	return 0;
 }
 
-static int mpc83xx_cpu_get_count(struct udevice *dev)
+static int mpc83xx_cpu_get_count(const struct udevice *dev)
 {
 	/* We have one e300cX core */
 	return 1;
 }
 
-static int mpc83xx_cpu_get_vendor(struct udevice *dev, char *buf, int size)
+static int mpc83xx_cpu_get_vendor(const struct udevice *dev, char *buf,
+				  int size)
 {
 	snprintf(buf, size, "NXP");
 
diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c
index 100fe55..93ce708 100644
--- a/drivers/cpu/riscv_cpu.c
+++ b/drivers/cpu/riscv_cpu.c
@@ -17,7 +17,7 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static int riscv_cpu_get_desc(struct udevice *dev, char *buf, int size)
+static int riscv_cpu_get_desc(const struct udevice *dev, char *buf, int size)
 {
 	const char *isa;
 
@@ -30,7 +30,7 @@
 	return 0;
 }
 
-static int riscv_cpu_get_info(struct udevice *dev, struct cpu_info *info)
+static int riscv_cpu_get_info(const struct udevice *dev, struct cpu_info *info)
 {
 	int ret;
 	struct clk clk;
@@ -39,7 +39,7 @@
 	u32 d_cache_size;
 
 	/* First try getting the frequency from the assigned clock */
-	ret = clk_get_by_index(dev, 0, &clk);
+	ret = clk_get_by_index((struct udevice *)dev, 0, &clk);
 	if (!ret) {
 		ret = clk_get_rate(&clk);
 		if (!IS_ERR_VALUE(ret))
@@ -67,7 +67,7 @@
 	return 0;
 }
 
-static int riscv_cpu_get_count(struct udevice *dev)
+static int riscv_cpu_get_count(const struct udevice *dev)
 {
 	ofnode node;
 	int num = 0;
diff --git a/drivers/dma/ti-edma3.c b/drivers/dma/ti-edma3.c
index 77c4ba9..13ab967 100644
--- a/drivers/dma/ti-edma3.c
+++ b/drivers/dma/ti-edma3.c
@@ -546,7 +546,7 @@
 {
 	struct ti_edma3_priv *priv = dev_get_priv(dev);
 
-	priv->base = devfdt_get_addr(dev);
+	priv->base = dev_read_addr(dev);
 
 	return 0;
 }
diff --git a/drivers/gpio/altera_pio.c b/drivers/gpio/altera_pio.c
index 324f9c2..75800d9 100644
--- a/drivers/gpio/altera_pio.c
+++ b/drivers/gpio/altera_pio.c
@@ -88,7 +88,7 @@
 {
 	struct altera_pio_platdata *plat = dev_get_platdata(dev);
 
-	plat->regs = map_physmem(devfdt_get_addr(dev),
+	plat->regs = map_physmem(dev_read_addr(dev),
 				 sizeof(struct altera_pio_regs),
 				 MAP_NOCACHE);
 	plat->gpio_count = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
diff --git a/drivers/gpio/atmel_pio4.c b/drivers/gpio/atmel_pio4.c
index 455944d..18f365f 100644
--- a/drivers/gpio/atmel_pio4.c
+++ b/drivers/gpio/atmel_pio4.c
@@ -299,7 +299,7 @@
 
 	clk_free(&clk);
 
-	addr_base = devfdt_get_addr(dev);
+	addr_base = dev_read_addr(dev);
 	if (addr_base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/gpio/bcm2835_gpio.c b/drivers/gpio/bcm2835_gpio.c
index f4b67f1..0dff9ac 100644
--- a/drivers/gpio/bcm2835_gpio.c
+++ b/drivers/gpio/bcm2835_gpio.c
@@ -121,7 +121,7 @@
 	struct bcm2835_gpio_platdata *plat = dev_get_platdata(dev);
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/gpio/da8xx_gpio.c b/drivers/gpio/da8xx_gpio.c
index ab0a5cf..f875888 100644
--- a/drivers/gpio/da8xx_gpio.c
+++ b/drivers/gpio/da8xx_gpio.c
@@ -545,7 +545,7 @@
 	struct davinci_gpio_platdata *plat = dev_get_platdata(dev);
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
index c49a041..a993fd4 100644
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -148,7 +148,7 @@
 	int node = dev_of_offset(dev);
 	int ret;
 
-	priv->regs = (void __iomem *)devfdt_get_addr(dev);
+	priv->regs = dev_read_addr_ptr(dev);
 	uc_priv->bank_name = dev->name;
 
 	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, node, "gpio-ranges",
diff --git a/drivers/gpio/gpio-rza1.c b/drivers/gpio/gpio-rza1.c
index 21a87d6..86804ac 100644
--- a/drivers/gpio/gpio-rza1.c
+++ b/drivers/gpio/gpio-rza1.c
@@ -112,7 +112,7 @@
 
 	uc_priv->bank_name = dev->name;
 	dev = dev_get_parent(dev);
-	addr_base = devfdt_get_addr(dev);
+	addr_base = dev_read_addr(dev);
 	if (addr_base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c
index 30392bc..54a38da 100644
--- a/drivers/gpio/gpio-uniphier.c
+++ b/drivers/gpio/gpio-uniphier.c
@@ -142,7 +142,7 @@
 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c
index ac5d20c..fe6b33e 100644
--- a/drivers/gpio/msm_gpio.c
+++ b/drivers/gpio/msm_gpio.c
@@ -96,7 +96,7 @@
 {
 	struct msm_gpio_bank *priv = dev_get_priv(dev);
 
-	priv->base = devfdt_get_addr(dev);
+	priv->base = dev_read_addr(dev);
 
 	return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0;
 }
diff --git a/drivers/gpio/mvebu_gpio.c b/drivers/gpio/mvebu_gpio.c
index 770cbf6..65eaa71 100644
--- a/drivers/gpio/mvebu_gpio.c
+++ b/drivers/gpio/mvebu_gpio.c
@@ -90,7 +90,7 @@
 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 	struct mvebu_gpio_priv *priv = dev_get_priv(dev);
 
-	priv->regs = (struct mvebu_gpio_regs *)devfdt_get_addr(dev);
+	priv->regs = dev_read_addr_ptr(dev);
 	uc_priv->gpio_count = MVEBU_GPIOS_PER_BANK;
 	priv->name[0] = 'A' + dev->req_seq;
 	uc_priv->bank_name = priv->name;
diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c
index 90d36fb..a16f571 100644
--- a/drivers/gpio/mxc_gpio.c
+++ b/drivers/gpio/mxc_gpio.c
@@ -300,7 +300,7 @@
 	fdt_addr_t addr;
 	struct mxc_gpio_plat *plat = dev_get_platdata(dev);
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/gpio/mxs_gpio.c b/drivers/gpio/mxs_gpio.c
index cb79726..2c16517 100644
--- a/drivers/gpio/mxs_gpio.c
+++ b/drivers/gpio/mxs_gpio.c
@@ -275,7 +275,7 @@
 	int node = dev_of_offset(dev);
 	int ret;
 
-	plat->bank = devfdt_get_addr(dev);
+	plat->bank = dev_read_addr(dev);
 	if (plat->bank == FDT_ADDR_T_NONE) {
 		printf("%s: No 'reg' property defined!\n", __func__);
 		return -EINVAL;
diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c
index c986ef0..6eaa0a0 100644
--- a/drivers/gpio/omap_gpio.c
+++ b/drivers/gpio/omap_gpio.c
@@ -308,7 +308,7 @@
 	if (plat)
 		return 0;
 
-	base_addr = devfdt_get_addr(dev);
+	base_addr = dev_read_addr(dev);
 	if (base_addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
@@ -347,7 +347,7 @@
 	struct omap_gpio_platdata *plat = dev_get_platdata(dev);
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/gpio/pm8916_gpio.c b/drivers/gpio/pm8916_gpio.c
index 51df536..58f0446 100644
--- a/drivers/gpio/pm8916_gpio.c
+++ b/drivers/gpio/pm8916_gpio.c
@@ -256,7 +256,7 @@
 	struct pm8916_gpio_bank *priv = dev_get_priv(dev);
 	int reg;
 
-	priv->pid = devfdt_get_addr(dev);
+	priv->pid = dev_read_addr(dev);
 	if (priv->pid == FDT_ADDR_T_NONE)
 		return log_msg_ret("bad address", -EINVAL);
 
diff --git a/drivers/gpio/s5p_gpio.c b/drivers/gpio/s5p_gpio.c
index 258f133..c78227f 100644
--- a/drivers/gpio/s5p_gpio.c
+++ b/drivers/gpio/s5p_gpio.c
@@ -316,7 +316,7 @@
 	if (plat)
 		return 0;
 
-	base = (struct s5p_gpio_bank *)devfdt_get_addr(parent);
+	base = dev_read_addr_ptr(parent);
 	for (node = fdt_first_subnode(blob, dev_of_offset(parent)), bank = base;
 	     node > 0;
 	     node = fdt_next_subnode(blob, node), bank++) {
@@ -339,7 +339,7 @@
 
 		dev_set_of_offset(dev, node);
 
-		reg = devfdt_get_addr(dev);
+		reg = dev_read_addr(dev);
 		if (reg != FDT_ADDR_T_NONE)
 			bank = (struct s5p_gpio_bank *)((ulong)base + reg);
 
diff --git a/drivers/gpio/sifive-gpio.c b/drivers/gpio/sifive-gpio.c
index 24da3b3..bf3537b 100644
--- a/drivers/gpio/sifive-gpio.c
+++ b/drivers/gpio/sifive-gpio.c
@@ -159,7 +159,7 @@
 	struct sifive_gpio_platdata *plat = dev_get_platdata(dev);
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index 9c3a442..3efccf4 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -293,7 +293,7 @@
 	if (plat)
 		return 0;
 
-	ctlr = (struct sunxi_gpio_reg *)devfdt_get_addr(parent);
+	ctlr = dev_read_addr_ptr(parent);
 	for (bank = 0; bank < soc_data->no_banks; bank++) {
 		struct sunxi_gpio_platdata *plat;
 		struct udevice *dev;
diff --git a/drivers/gpio/vybrid_gpio.c b/drivers/gpio/vybrid_gpio.c
index d2c1d7d..4efff5c 100644
--- a/drivers/gpio/vybrid_gpio.c
+++ b/drivers/gpio/vybrid_gpio.c
@@ -109,7 +109,7 @@
 	struct vybrid_gpio_platdata *plat = dev_get_platdata(dev);
 	fdt_addr_t base_addr;
 
-	base_addr = devfdt_get_addr(dev);
+	base_addr = dev_read_addr(dev);
 	if (base_addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/i2c/at91_i2c.c b/drivers/i2c/at91_i2c.c
index c817ed6..9d6c6d8 100644
--- a/drivers/i2c/at91_i2c.c
+++ b/drivers/i2c/at91_i2c.c
@@ -225,7 +225,7 @@
 	struct at91_i2c_bus *bus = dev_get_priv(dev);
 	int node = dev_of_offset(dev);
 
-	bus->regs = (struct at91_i2c_regs *)devfdt_get_addr(dev);
+	bus->regs = dev_read_addr_ptr(dev);
 	bus->pdata = (struct at91_i2c_pdata *)dev_get_driver_data(dev);
 	bus->clock_frequency = fdtdec_get_int(blob, node,
 					      "clock-frequency", 100000);
diff --git a/drivers/i2c/davinci_i2c.c b/drivers/i2c/davinci_i2c.c
index f8e9d00..a54f215 100644
--- a/drivers/i2c/davinci_i2c.c
+++ b/drivers/i2c/davinci_i2c.c
@@ -471,7 +471,7 @@
 	struct i2c_bus *i2c_bus = dev_get_priv(dev);
 
 	i2c_bus->id = dev->seq;
-	i2c_bus->regs = (struct i2c_regs *)devfdt_get_addr(dev);
+	i2c_bus->regs = dev_read_addr_ptr(dev);
 
 	i2c_bus->speed = 100000;
 	 _davinci_i2c_init(i2c_bus->regs, i2c_bus->speed, 0);
diff --git a/drivers/i2c/exynos_hs_i2c.c b/drivers/i2c/exynos_hs_i2c.c
index 4fc9d90..5785ade 100644
--- a/drivers/i2c/exynos_hs_i2c.c
+++ b/drivers/i2c/exynos_hs_i2c.c
@@ -525,7 +525,7 @@
 
 	node = dev_of_offset(dev);
 
-	i2c_bus->hsregs = (struct exynos5_hsi2c *)devfdt_get_addr(dev);
+	i2c_bus->hsregs = dev_read_addr_ptr(dev);
 
 	i2c_bus->id = pinmux_decode_periph_id(blob, node);
 
diff --git a/drivers/i2c/i2c-uniphier-f.c b/drivers/i2c/i2c-uniphier-f.c
index d8b4a68..a110fe9 100644
--- a/drivers/i2c/i2c-uniphier-f.c
+++ b/drivers/i2c/i2c-uniphier-f.c
@@ -94,7 +94,7 @@
 	fdt_addr_t addr;
 	struct uniphier_fi2c_priv *priv = dev_get_priv(dev);
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/i2c/i2c-uniphier.c b/drivers/i2c/i2c-uniphier.c
index f06523a..e7f44e1 100644
--- a/drivers/i2c/i2c-uniphier.c
+++ b/drivers/i2c/i2c-uniphier.c
@@ -50,7 +50,7 @@
 	fdt_addr_t addr;
 	struct uniphier_i2c_priv *priv = dev_get_priv(dev);
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/i2c/imx_lpi2c.c b/drivers/i2c/imx_lpi2c.c
index b7b2aaf..feeed1e 100644
--- a/drivers/i2c/imx_lpi2c.c
+++ b/drivers/i2c/imx_lpi2c.c
@@ -447,7 +447,7 @@
 
 	i2c_bus->driver_data = dev_get_driver_data(bus);
 
-	addr = devfdt_get_addr(bus);
+	addr = dev_read_addr(bus);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/i2c/iproc_i2c.c b/drivers/i2c/iproc_i2c.c
index a846e0a..b7e9ced 100644
--- a/drivers/i2c/iproc_i2c.c
+++ b/drivers/i2c/iproc_i2c.c
@@ -678,7 +678,7 @@
 	int node = dev_of_offset(bus);
 	const void *blob = gd->fdt_blob;
 
-	bus_prvdata->base = map_physmem(devfdt_get_addr(bus),
+	bus_prvdata->base = map_physmem(dev_read_addr(bus),
 					sizeof(void *),
 					MAP_NOCACHE);
 
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
index 9e1bafc..e3d980a 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -901,7 +901,7 @@
 
 	i2c_bus->driver_data = dev_get_driver_data(bus);
 
-	addr = devfdt_get_addr(bus);
+	addr = dev_read_addr(bus);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index 8592a81..0af4e33 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -1067,7 +1067,7 @@
 {
 	struct omap_i2c_platdata *plat = dev_get_platdata(bus);
 
-	plat->base = devfdt_get_addr(bus);
+	plat->base = dev_read_addr(bus);
 	plat->speed = dev_read_u32_default(bus, "clock-frequency",
 					   I2C_SPEED_STANDARD_RATE);
 	plat->ip_rev = dev_get_driver_data(bus);
diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
index 5907217..cb45d3c 100644
--- a/drivers/i2c/s3c24x0_i2c.c
+++ b/drivers/i2c/s3c24x0_i2c.c
@@ -310,7 +310,7 @@
 
 	node = dev_of_offset(dev);
 
-	i2c_bus->regs = (struct s3c24x0_i2c *)devfdt_get_addr(dev);
+	i2c_bus->regs = dev_read_addr_ptr(dev);
 
 	i2c_bus->id = pinmux_decode_periph_id(blob, node);
 
diff --git a/drivers/input/tegra-kbc.c b/drivers/input/tegra-kbc.c
index 3409bb6..f07a51d 100644
--- a/drivers/input/tegra-kbc.c
+++ b/drivers/input/tegra-kbc.c
@@ -291,7 +291,7 @@
 	struct input_config *input = &uc_priv->input;
 	int ret;
 
-	priv->kbc = (struct kbc_tegra *)devfdt_get_addr(dev);
+	priv->kbc = dev_read_addr_ptr(dev);
 	if ((fdt_addr_t)priv->kbc == FDT_ADDR_T_NONE) {
 		debug("%s: No keyboard register found\n", __func__);
 		return -EINVAL;
diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c
index f82e6d3..e91dac2 100644
--- a/drivers/mailbox/tegra-hsp.c
+++ b/drivers/mailbox/tegra-hsp.c
@@ -153,7 +153,7 @@
 
 	debug("%s(dev=%p)\n", __func__, dev);
 
-	thsp->regs = devfdt_get_addr(dev);
+	thsp->regs = dev_read_addr(dev);
 	if (thsp->regs == FDT_ADDR_T_NONE)
 		return -ENODEV;
 
diff --git a/drivers/misc/altera_sysid.c b/drivers/misc/altera_sysid.c
index 387c70b..c650265 100644
--- a/drivers/misc/altera_sysid.c
+++ b/drivers/misc/altera_sysid.c
@@ -73,7 +73,7 @@
 {
 	struct altera_sysid_platdata *plat = dev_get_platdata(dev);
 
-	plat->regs = map_physmem(devfdt_get_addr(dev),
+	plat->regs = map_physmem(dev_read_addr(dev),
 				 sizeof(struct altera_sysid_regs),
 				 MAP_NOCACHE);
 
diff --git a/drivers/misc/imx8/scu.c b/drivers/misc/imx8/scu.c
index ee635eb..223aac8 100644
--- a/drivers/misc/imx8/scu.c
+++ b/drivers/misc/imx8/scu.c
@@ -187,7 +187,7 @@
 
 	debug("%s(dev=%p) (plat=%p)\n", __func__, dev, plat);
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/misc/microchip_flexcom.c b/drivers/misc/microchip_flexcom.c
index 44a8b18..64cc4ae 100644
--- a/drivers/misc/microchip_flexcom.c
+++ b/drivers/misc/microchip_flexcom.c
@@ -26,7 +26,7 @@
 	struct microchip_flexcom_platdata *plat = dev_get_platdata(dev);
 	int ret;
 
-	plat->regs = map_physmem(devfdt_get_addr(dev),
+	plat->regs = map_physmem(dev_read_addr(dev),
 				 sizeof(struct microchip_flexcom_regs),
 				MAP_NOCACHE);
 
diff --git a/drivers/mmc/aspeed_sdhci.c b/drivers/mmc/aspeed_sdhci.c
index 8929e60..543c65a 100644
--- a/drivers/mmc/aspeed_sdhci.c
+++ b/drivers/mmc/aspeed_sdhci.c
@@ -34,7 +34,7 @@
 		goto free;
 
 	host->name = dev->name;
-	host->ioaddr = (void *)devfdt_get_addr(dev);
+	host->ioaddr = dev_read_addr_ptr(dev);
 
 	max_clk = clk_get_rate(&clk);
 	if (IS_ERR_VALUE(max_clk)) {
diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c
index 2b797c9..0c53caf 100644
--- a/drivers/mmc/atmel_sdhci.c
+++ b/drivers/mmc/atmel_sdhci.c
@@ -69,7 +69,7 @@
 		return ret;
 
 	host->name = dev->name;
-	host->ioaddr = (void *)devfdt_get_addr(dev);
+	host->ioaddr = dev_read_addr_ptr(dev);
 
 	host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD;
 	host->bus_width	= fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c
index 5cdf3c5..7a410d1 100644
--- a/drivers/mmc/bcm2835_sdhci.c
+++ b/drivers/mmc/bcm2835_sdhci.c
@@ -182,7 +182,7 @@
 	int ret;
 	int clock_id = (int)dev_get_driver_data(dev);
 
-	base = devfdt_get_addr(dev);
+	base = dev_read_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/mmc/bcm2835_sdhost.c b/drivers/mmc/bcm2835_sdhost.c
index c4876e8..b793028 100644
--- a/drivers/mmc/bcm2835_sdhost.c
+++ b/drivers/mmc/bcm2835_sdhost.c
@@ -766,7 +766,7 @@
 	upriv->mmc = &plat->mmc;
 	plat->cfg.name = dev->name;
 
-	host->phys_addr = devfdt_get_addr(dev);
+	host->phys_addr = dev_read_addr(dev);
 	if (host->phys_addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/mmc/bcmstb_sdhci.c b/drivers/mmc/bcmstb_sdhci.c
index c14f828..5269aa7 100644
--- a/drivers/mmc/bcmstb_sdhci.c
+++ b/drivers/mmc/bcmstb_sdhci.c
@@ -62,7 +62,7 @@
 	fdt_addr_t base;
 	int ret;
 
-	base = devfdt_get_addr(dev);
+	base = dev_read_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c
index fb28f01..bc0d5ff 100644
--- a/drivers/mmc/ftsdc010_mci.c
+++ b/drivers/mmc/ftsdc010_mci.c
@@ -395,7 +395,7 @@
 	struct ftsdc_priv *priv = dev_get_priv(dev);
 	struct ftsdc010_chip *chip = &priv->chip;
 	chip->name = dev->name;
-	chip->ioaddr = (void *)devfdt_get_addr(dev);
+	chip->ioaddr = dev_read_addr_ptr(dev);
 	chip->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 					"bus-width", 4);
 	chip->priv = dev;
diff --git a/drivers/mmc/hi6220_dw_mmc.c b/drivers/mmc/hi6220_dw_mmc.c
index 6de7924..67d6a05 100644
--- a/drivers/mmc/hi6220_dw_mmc.c
+++ b/drivers/mmc/hi6220_dw_mmc.c
@@ -33,7 +33,7 @@
 	struct dwmci_host *host = &priv->host;
 
 	host->name = dev->name;
-	host->ioaddr = (void *)devfdt_get_addr(dev);
+	host->ioaddr = dev_read_addr_ptr(dev);
 	host->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 					"bus-width", 4);
 
diff --git a/drivers/mmc/iproc_sdhci.c b/drivers/mmc/iproc_sdhci.c
index 91e2e3f..9f53063 100644
--- a/drivers/mmc/iproc_sdhci.c
+++ b/drivers/mmc/iproc_sdhci.c
@@ -188,7 +188,7 @@
 	iproc_host->shadow_blk = 0;
 
 	host->name = dev->name;
-	host->ioaddr = (void *)devfdt_get_addr(dev);
+	host->ioaddr = dev_read_addr_ptr(dev);
 	host->voltages = MMC_VDD_165_195 |
 			 MMC_VDD_32_33 | MMC_VDD_33_34;
 	host->quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B;
diff --git a/drivers/mmc/jz_mmc.c b/drivers/mmc/jz_mmc.c
index d3f1edd..b33f085 100644
--- a/drivers/mmc/jz_mmc.c
+++ b/drivers/mmc/jz_mmc.c
@@ -450,7 +450,7 @@
 	struct mmc_config *cfg;
 	int ret;
 
-	priv->regs = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE);
+	priv->regs = map_physmem(dev_read_addr(dev), 0x100, MAP_NOCACHE);
 	cfg = &plat->cfg;
 
 	cfg->name = "MSC";
diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c
index b7f793c..719dd1e 100644
--- a/drivers/mmc/meson_gx_mmc.c
+++ b/drivers/mmc/meson_gx_mmc.c
@@ -228,7 +228,7 @@
 	struct meson_mmc_platdata *pdata = dev_get_platdata(dev);
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c
index da3ae2e..56c3e35 100644
--- a/drivers/mmc/msm_sdhci.c
+++ b/drivers/mmc/msm_sdhci.c
@@ -171,7 +171,7 @@
 	int node = dev_of_offset(dev);
 
 	host->name = strdup(dev->name);
-	host->ioaddr = (void *)devfdt_get_addr(dev);
+	host->ioaddr = dev_read_addr_ptr(dev);
 	host->bus_width = fdtdec_get_int(gd->fdt_blob, node, "bus-width", 4);
 	host->index = fdtdec_get_uint(gd->fdt_blob, node, "index", 0);
 	priv->base = (void *)fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
diff --git a/drivers/mmc/mv_sdhci.c b/drivers/mmc/mv_sdhci.c
index f5f3e43..9b3dfa1 100644
--- a/drivers/mmc/mv_sdhci.c
+++ b/drivers/mmc/mv_sdhci.c
@@ -112,7 +112,7 @@
 	int ret;
 
 	host->name = MVSDH_NAME;
-	host->ioaddr = (void *)devfdt_get_addr(dev);
+	host->ioaddr = dev_read_addr_ptr(dev);
 	host->quirks = SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_WAIT_SEND_CMD;
 	host->mmc = &plat->mmc;
 	host->mmc->dev = dev;
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index db1f851..715eee0 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -1911,7 +1911,7 @@
 	int node = dev_of_offset(dev);
 	int ret;
 
-	plat->base_addr = map_physmem(devfdt_get_addr(dev),
+	plat->base_addr = map_physmem(dev_read_addr(dev),
 				      sizeof(struct hsmmc *),
 				      MAP_NOCACHE);
 
@@ -1933,7 +1933,7 @@
 		plat->controller_flags |= of_data->controller_flags;
 
 #ifdef CONFIG_OMAP54XX
-	fixups = platform_fixups_mmc(devfdt_get_addr(dev));
+	fixups = platform_fixups_mmc(dev_read_addr(dev));
 	if (fixups) {
 		plat->hw_rev = fixups->hw_rev;
 		cfg->host_caps &= ~fixups->unsupported_caps;
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index d6ea99d..d80b3fc 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -20,7 +20,6 @@
 #include <linux/sizes.h>
 #include <power/regulator.h>
 #include <asm/unaligned.h>
-
 #include "tmio-common.h"
 
 #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
@@ -843,6 +842,7 @@
 	{ .compatible = "renesas,sdhi-r8a7794", .data = RENESAS_GEN2_QUIRKS },
 	{ .compatible = "renesas,sdhi-r8a7795", .data = RENESAS_GEN3_QUIRKS },
 	{ .compatible = "renesas,sdhi-r8a7796", .data = RENESAS_GEN3_QUIRKS },
+	{ .compatible = "renesas,rcar-gen3-sdhi", .data = RENESAS_GEN3_QUIRKS },
 	{ .compatible = "renesas,sdhi-r8a77965", .data = RENESAS_GEN3_QUIRKS },
 	{ .compatible = "renesas,sdhi-r8a77970", .data = RENESAS_GEN3_QUIRKS },
 	{ .compatible = "renesas,sdhi-r8a77990", .data = RENESAS_GEN3_QUIRKS },
diff --git a/drivers/mmc/sdhci-cadence.c b/drivers/mmc/sdhci-cadence.c
index 7b5010b..cc99beb 100644
--- a/drivers/mmc/sdhci-cadence.c
+++ b/drivers/mmc/sdhci-cadence.c
@@ -260,7 +260,7 @@
 	fdt_addr_t base;
 	int ret;
 
-	base = devfdt_get_addr(dev);
+	base = dev_read_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c
index 2e994d0..ad38690 100644
--- a/drivers/mmc/sh_mmcif.c
+++ b/drivers/mmc/sh_mmcif.c
@@ -680,7 +680,7 @@
 	fdt_addr_t base;
 	int ret;
 
-	base = devfdt_get_addr(dev);
+	base = dev_read_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c
index 772fe94..315f95c 100644
--- a/drivers/mmc/sh_sdhi.c
+++ b/drivers/mmc/sh_sdhi.c
@@ -834,7 +834,7 @@
 	fdt_addr_t base;
 	int ret;
 
-	base = devfdt_get_addr(dev);
+	base = dev_read_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c
index 892222d..0022f94 100644
--- a/drivers/mmc/socfpga_dw_mmc.c
+++ b/drivers/mmc/socfpga_dw_mmc.c
@@ -109,7 +109,7 @@
 	}
 
 	host->name = dev->name;
-	host->ioaddr = (void *)devfdt_get_addr(dev);
+	host->ioaddr = dev_read_addr_ptr(dev);
 	host->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 					"bus-width", 4);
 	host->clksel = socfpga_dwmci_clksel;
diff --git a/drivers/mmc/sti_sdhci.c b/drivers/mmc/sti_sdhci.c
index 9bcd8ce..5578fee 100644
--- a/drivers/mmc/sti_sdhci.c
+++ b/drivers/mmc/sti_sdhci.c
@@ -116,7 +116,7 @@
 	struct sdhci_host *host = dev_get_priv(dev);
 
 	host->name = strdup(dev->name);
-	host->ioaddr = (void *)devfdt_get_addr(dev);
+	host->ioaddr = dev_read_addr_ptr(dev);
 
 	host->bus_width = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 					 "bus-width", 4);
diff --git a/drivers/mmc/tangier_sdhci.c b/drivers/mmc/tangier_sdhci.c
index 0d6e5d6..879e2c9 100644
--- a/drivers/mmc/tangier_sdhci.c
+++ b/drivers/mmc/tangier_sdhci.c
@@ -35,7 +35,7 @@
 	fdt_addr_t base;
 	int ret;
 
-	base = devfdt_get_addr(dev);
+	base = dev_read_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index 20cd237..c653973 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -722,7 +722,7 @@
 	ulong mclk;
 	int ret;
 
-	base = devfdt_get_addr(dev);
+	base = dev_read_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/mmc/xenon_sdhci.c b/drivers/mmc/xenon_sdhci.c
index e765dd3..356dd98 100644
--- a/drivers/mmc/xenon_sdhci.c
+++ b/drivers/mmc/xenon_sdhci.c
@@ -455,7 +455,7 @@
 	const char *name;
 
 	host->name = dev->name;
-	host->ioaddr = (void *)devfdt_get_addr(dev);
+	host->ioaddr = dev_read_addr_ptr(dev);
 
 	if (device_is_compatible(dev, "marvell,armada-3700-sdhci"))
 		priv->pad_ctrl_reg = (void *)devfdt_get_addr_index(dev, 1);
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index ec3fb49..15030b8 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -491,6 +491,12 @@
 
 source "drivers/net/ti/Kconfig"
 
+config TULIP
+	bool "DEC Tulip DC2114x Ethernet support"
+	depends on (DM_ETH && DM_PCI) || !DM_ETH
+	help
+	  This driver supports DEC DC2114x Fast ethernet chips.
+
 config XILINX_AXIEMAC
 	depends on DM_ETH && (MICROBLAZE || ARCH_ZYNQ || ARCH_ZYNQMP)
 	select PHYLIB
diff --git a/drivers/net/ag7xxx.c b/drivers/net/ag7xxx.c
index 3b5d11f..ccba394 100644
--- a/drivers/net/ag7xxx.c
+++ b/drivers/net/ag7xxx.c
@@ -1256,7 +1256,7 @@
 	const char *phy_mode;
 	int ret;
 
-	pdata->iobase = devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 	pdata->phy_interface = -1;
 
 	/* Decoding of convoluted PHY wiring on Atheros MIPS. */
diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c
index 0cb54e3..9f8c6c5 100644
--- a/drivers/net/dc2114x.c
+++ b/drivers/net/dc2114x.c
@@ -1,7 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0+
 
 #include <common.h>
-#include <env.h>
+#include <asm/io.h>
+#include <dm.h>
 #include <malloc.h>
 #include <net.h>
 #include <netdev.h>
@@ -11,8 +12,6 @@
 
 #define SROM_DLEVEL	0
 
-#undef UPDATE_SROM
-
 /* PCI Registers. */
 #define PCI_CFDA_PSM	0x43
 
@@ -74,10 +73,12 @@
 
 #define POLL_DEMAND	1
 
-#if defined(CONFIG_E500)
-#define phys_to_bus(a) (a)
+#if defined(CONFIG_DM_ETH)
+#define phys_to_bus(dev, a)	dm_pci_phys_to_mem((dev), (a))
+#elif defined(CONFIG_E500)
+#define phys_to_bus(dev, a)	(a)
 #else
-#define phys_to_bus(a)	pci_phys_to_mem((pci_dev_t)dev->priv, a)
+#define phys_to_bus(dev, a)	pci_phys_to_mem((dev), (a))
 #endif
 
 #define NUM_RX_DESC PKTBUFSRX
@@ -95,87 +96,97 @@
 	u32 next;
 };
 
-/* RX and TX descriptor ring */
-static struct de4x5_desc rx_ring[NUM_RX_DESC] __aligned(32);
-static struct de4x5_desc tx_ring[NUM_TX_DESC] __aligned(32);
-static int rx_new;	/* RX descriptor ring pointer */
-static int tx_new;	/* TX descriptor ring pointer */
-
-static char rx_ring_size;
-static char tx_ring_size;
+struct dc2114x_priv {
+	struct de4x5_desc rx_ring[NUM_RX_DESC] __aligned(32);
+	struct de4x5_desc tx_ring[NUM_TX_DESC] __aligned(32);
+	int rx_new;	/* RX descriptor ring pointer */
+	int tx_new;	/* TX descriptor ring pointer */
+	char rx_ring_size;
+	char tx_ring_size;
+#ifdef CONFIG_DM_ETH
+	struct udevice		*devno;
+#else
+	struct eth_device	dev;
+	pci_dev_t		devno;
+#endif
+	char			*name;
+	void __iomem		*iobase;
+	u8			*enetaddr;
+};
 
-static u32 dc2114x_inl(struct eth_device *dev, u32 addr)
+/* RX and TX descriptor ring */
+static u32 dc2114x_inl(struct dc2114x_priv *priv, u32 addr)
 {
-	return le32_to_cpu(*(volatile u32 *)(addr + dev->iobase));
+	return le32_to_cpu(readl(priv->iobase + addr));
 }
 
-static void dc2114x_outl(struct eth_device *dev, u32 command, u32 addr)
+static void dc2114x_outl(struct dc2114x_priv *priv, u32 command, u32 addr)
 {
-	*(volatile u32 *)(addr + dev->iobase) = cpu_to_le32(command);
+	writel(cpu_to_le32(command), priv->iobase + addr);
 }
 
-static void reset_de4x5(struct eth_device *dev)
+static void reset_de4x5(struct dc2114x_priv *priv)
 {
 	u32 i;
 
-	i = dc2114x_inl(dev, DE4X5_BMR);
+	i = dc2114x_inl(priv, DE4X5_BMR);
 	mdelay(1);
-	dc2114x_outl(dev, i | BMR_SWR, DE4X5_BMR);
+	dc2114x_outl(priv, i | BMR_SWR, DE4X5_BMR);
 	mdelay(1);
-	dc2114x_outl(dev, i, DE4X5_BMR);
+	dc2114x_outl(priv, i, DE4X5_BMR);
 	mdelay(1);
 
 	for (i = 0; i < 5; i++) {
-		dc2114x_inl(dev, DE4X5_BMR);
+		dc2114x_inl(priv, DE4X5_BMR);
 		mdelay(10);
 	}
 
 	mdelay(1);
 }
 
-static void start_de4x5(struct eth_device *dev)
+static void start_de4x5(struct dc2114x_priv *priv)
 {
 	u32 omr;
 
-	omr = dc2114x_inl(dev, DE4X5_OMR);
+	omr = dc2114x_inl(priv, DE4X5_OMR);
 	omr |= OMR_ST | OMR_SR;
-	dc2114x_outl(dev, omr, DE4X5_OMR);	/* Enable the TX and/or RX */
+	dc2114x_outl(priv, omr, DE4X5_OMR);	/* Enable the TX and/or RX */
 }
 
-static void stop_de4x5(struct eth_device *dev)
+static void stop_de4x5(struct dc2114x_priv *priv)
 {
 	u32 omr;
 
-	omr = dc2114x_inl(dev, DE4X5_OMR);
+	omr = dc2114x_inl(priv, DE4X5_OMR);
 	omr &= ~(OMR_ST | OMR_SR);
-	dc2114x_outl(dev, omr, DE4X5_OMR);	/* Disable the TX and/or RX */
+	dc2114x_outl(priv, omr, DE4X5_OMR);	/* Disable the TX and/or RX */
 }
 
 /* SROM Read and write routines. */
-static void sendto_srom(struct eth_device *dev, u_int command, u_long addr)
+static void sendto_srom(struct dc2114x_priv *priv, u_int command, u_long addr)
 {
-	dc2114x_outl(dev, command, addr);
+	dc2114x_outl(priv, command, addr);
 	udelay(1);
 }
 
-static int getfrom_srom(struct eth_device *dev, u_long addr)
+static int getfrom_srom(struct dc2114x_priv *priv, u_long addr)
 {
-	u32 tmp = dc2114x_inl(dev, addr);
+	u32 tmp = dc2114x_inl(priv, addr);
 
 	udelay(1);
 	return tmp;
 }
 
 /* Note: this routine returns extra data bits for size detection. */
-static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location,
+static int do_read_eeprom(struct dc2114x_priv *priv, u_long ioaddr, int location,
 			  int addr_len)
 {
 	int read_cmd = location | (SROM_READ_CMD << addr_len);
 	unsigned int retval = 0;
 	int i;
 
-	sendto_srom(dev, SROM_RD | SROM_SR, ioaddr);
-	sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
+	sendto_srom(priv, SROM_RD | SROM_SR, ioaddr);
+	sendto_srom(priv, SROM_RD | SROM_SR | DT_CS, ioaddr);
 
 	debug_cond(SROM_DLEVEL >= 1, " EEPROM read at %d ", location);
 
@@ -183,35 +194,35 @@
 	for (i = 4 + addr_len; i >= 0; i--) {
 		short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
 
-		sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval,
+		sendto_srom(priv, SROM_RD | SROM_SR | DT_CS | dataval,
 			    ioaddr);
 		udelay(10);
-		sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval | DT_CLK,
+		sendto_srom(priv, SROM_RD | SROM_SR | DT_CS | dataval | DT_CLK,
 			    ioaddr);
 		udelay(10);
 		debug_cond(SROM_DLEVEL >= 2, "%X",
-			   getfrom_srom(dev, ioaddr) & 15);
+			   getfrom_srom(priv, ioaddr) & 15);
 		retval = (retval << 1) |
-			 !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ);
+			 !!(getfrom_srom(priv, ioaddr) & EE_DATA_READ);
 	}
 
-	sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
+	sendto_srom(priv, SROM_RD | SROM_SR | DT_CS, ioaddr);
 
-	debug_cond(SROM_DLEVEL >= 2, " :%X:", getfrom_srom(dev, ioaddr) & 15);
+	debug_cond(SROM_DLEVEL >= 2, " :%X:", getfrom_srom(priv, ioaddr) & 15);
 
 	for (i = 16; i > 0; i--) {
-		sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr);
+		sendto_srom(priv, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr);
 		udelay(10);
 		debug_cond(SROM_DLEVEL >= 2, "%X",
-			   getfrom_srom(dev, ioaddr) & 15);
+			   getfrom_srom(priv, ioaddr) & 15);
 		retval = (retval << 1) |
-			 !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ);
-		sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
+			 !!(getfrom_srom(priv, ioaddr) & EE_DATA_READ);
+		sendto_srom(priv, SROM_RD | SROM_SR | DT_CS, ioaddr);
 		udelay(10);
 	}
 
 	/* Terminate the EEPROM access. */
-	sendto_srom(dev, SROM_RD | SROM_SR, ioaddr);
+	sendto_srom(priv, SROM_RD | SROM_SR, ioaddr);
 
 	debug_cond(SROM_DLEVEL >= 2, " EEPROM value at %d is %5.5x.\n",
 		   location, retval);
@@ -224,139 +235,53 @@
  * enable. It returns the data output from the EEPROM, and thus may
  * also be used for reads.
  */
-static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd,
+static int do_eeprom_cmd(struct dc2114x_priv *priv, u_long ioaddr, int cmd,
 			 int cmd_len)
 {
 	unsigned int retval = 0;
 
 	debug_cond(SROM_DLEVEL >= 1, " EEPROM op 0x%x: ", cmd);
 
-	sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr);
+	sendto_srom(priv, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr);
 
 	/* Shift the command bits out. */
 	do {
 		short dataval = (cmd & BIT(cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
 
-		sendto_srom(dev, dataval, ioaddr);
+		sendto_srom(priv, dataval, ioaddr);
 		udelay(10);
 
 		debug_cond(SROM_DLEVEL >= 2, "%X",
-			   getfrom_srom(dev, ioaddr) & 15);
+			   getfrom_srom(priv, ioaddr) & 15);
 
-		sendto_srom(dev, dataval | DT_CLK, ioaddr);
+		sendto_srom(priv, dataval | DT_CLK, ioaddr);
 		udelay(10);
 		retval = (retval << 1) |
-			 !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ);
+			 !!(getfrom_srom(priv, ioaddr) & EE_DATA_READ);
 	} while (--cmd_len >= 0);
 
-	sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
+	sendto_srom(priv, SROM_RD | SROM_SR | DT_CS, ioaddr);
 
 	/* Terminate the EEPROM access. */
-	sendto_srom(dev, SROM_RD | SROM_SR, ioaddr);
+	sendto_srom(priv, SROM_RD | SROM_SR, ioaddr);
 
 	debug_cond(SROM_DLEVEL >= 1, " EEPROM result is 0x%5.5x.\n", retval);
 
 	return retval;
 }
 
-static int read_srom(struct eth_device *dev, u_long ioaddr, int index)
+static int read_srom(struct dc2114x_priv *priv, u_long ioaddr, int index)
 {
 	int ee_addr_size;
 
-	ee_addr_size = (do_read_eeprom(dev, ioaddr, 0xff, 8) & BIT(18)) ? 8 : 6;
+	ee_addr_size = (do_read_eeprom(priv, ioaddr, 0xff, 8) & BIT(18)) ? 8 : 6;
 
-	return do_eeprom_cmd(dev, ioaddr, 0xffff |
+	return do_eeprom_cmd(priv, ioaddr, 0xffff |
 			     (((SROM_READ_CMD << ee_addr_size) | index) << 16),
 			     3 + ee_addr_size + 16);
 }
 
-#ifdef UPDATE_SROM
-static int write_srom(struct eth_device *dev, u_long ioaddr, int index,
-		      int new_value)
-{
-	unsigned short newval;
-	int ee_addr_size;
-	int i;
-
-	ee_addr_size = (do_read_eeprom(dev, ioaddr, 0xff, 8) & BIT(18)) ? 8 : 6;
-
-	udelay(10 * 1000); /* test-only */
-
-	debug_cond(SROM_DLEVEL >= 1, "ee_addr_size=%d.\n", ee_addr_size);
-	debug_cond(SROM_DLEVEL >= 1,
-		   "Writing new entry 0x%4.4x to offset %d.\n",
-		   new_value, index);
-
-	/* Enable programming modes. */
-	do_eeprom_cmd(dev, ioaddr, 0x4f << (ee_addr_size - 4),
-		      3 + ee_addr_size);
-
-	/* Do the actual write. */
-	do_eeprom_cmd(dev, ioaddr, new_value |
-		      (((SROM_WRITE_CMD << ee_addr_size) | index) << 16),
-		      3 + ee_addr_size + 16);
-
-	/* Poll for write finished. */
-	sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
-	for (i = 0; i < 10000; i++) {	/* Typical 2000 ticks */
-		if (getfrom_srom(dev, ioaddr) & EE_DATA_READ)
-			break;
-	}
-
-	debug_cond(SROM_DLEVEL >= 1, " Write finished after %d ticks.\n", i);
-
-	/* Disable programming. */
-	do_eeprom_cmd(dev, ioaddr, (0x40 << (ee_addr_size - 4)),
-		      3 + ee_addr_size);
-
-	/* And read the result. */
-	newval = do_eeprom_cmd(dev, ioaddr,
-			       (((SROM_READ_CMD << ee_addr_size) | index) << 16)
-			       | 0xffff, 3 + ee_addr_size + 16);
-
-	debug_cond(SROM_DLEVEL >= 1, "  New value at offset %d is %4.4x.\n",
-		   index, newval);
-
-	return 1;
-}
-
-static void update_srom(struct eth_device *dev, struct bd_info *bis)
-{
-	static unsigned short eeprom[0x40] = {
-		0x140b, 0x6610, 0x0000, 0x0000,	/* 00 */
-		0x0000, 0x0000, 0x0000, 0x0000,	/* 04 */
-		0x00a3, 0x0103, 0x0000, 0x0000,	/* 08 */
-		0x0000, 0x1f00, 0x0000, 0x0000,	/* 0c */
-		0x0108, 0x038d, 0x0000, 0x0000,	/* 10 */
-		0xe078, 0x0001, 0x0040, 0x0018,	/* 14 */
-		0x0000, 0x0000, 0x0000, 0x0000,	/* 18 */
-		0x0000, 0x0000, 0x0000, 0x0000,	/* 1c */
-		0x0000, 0x0000, 0x0000, 0x0000,	/* 20 */
-		0x0000, 0x0000, 0x0000, 0x0000,	/* 24 */
-		0x0000, 0x0000, 0x0000, 0x0000,	/* 28 */
-		0x0000, 0x0000, 0x0000, 0x0000,	/* 2c */
-		0x0000, 0x0000, 0x0000, 0x0000,	/* 30 */
-		0x0000, 0x0000, 0x0000, 0x0000,	/* 34 */
-		0x0000, 0x0000, 0x0000, 0x0000,	/* 38 */
-		0x0000, 0x0000, 0x0000, 0x4e07,	/* 3c */
-	};
-	uchar enetaddr[6];
-	int i;
-
-	/* Ethernet Addr... */
-	if (!eth_env_get_enetaddr("ethaddr", enetaddr))
-		return;
-
-	eeprom[0x0a] = (enetaddr[1] << 8) | enetaddr[0];
-	eeprom[0x0b] = (enetaddr[3] << 8) | enetaddr[2];
-	eeprom[0x0c] = (enetaddr[5] << 8) | enetaddr[4];
-
-	for (i = 0; i < 0x40; i++)
-		write_srom(dev, DE4X5_APROM, i, eeprom[i]);
-}
-#endif /* UPDATE_SROM */
-
-static void send_setup_frame(struct eth_device *dev, struct bd_info *bis)
+static void send_setup_frame(struct dc2114x_priv *priv)
 {
 	char setup_frame[SETUP_FRAME_LEN];
 	char *pa = &setup_frame[0];
@@ -365,223 +290,267 @@
 	memset(pa, 0xff, SETUP_FRAME_LEN);
 
 	for (i = 0; i < ETH_ALEN; i++) {
-		*(pa + (i & 1)) = dev->enetaddr[i];
+		*(pa + (i & 1)) = priv->enetaddr[i];
 		if (i & 0x01)
 			pa += 4;
 	}
 
-	for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
+	for (i = 0; priv->tx_ring[priv->tx_new].status & cpu_to_le32(T_OWN); i++) {
 		if (i < TOUT_LOOP)
 			continue;
 
-		printf("%s: tx error buffer not ready\n", dev->name);
+		printf("%s: tx error buffer not ready\n", priv->name);
 		return;
 	}
 
-	tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32)&setup_frame[0]));
-	tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_SET | SETUP_FRAME_LEN);
-	tx_ring[tx_new].status = cpu_to_le32(T_OWN);
+	priv->tx_ring[priv->tx_new].buf = cpu_to_le32(phys_to_bus(priv->devno,
+						      (u32)&setup_frame[0]));
+	priv->tx_ring[priv->tx_new].des1 = cpu_to_le32(TD_TER | TD_SET | SETUP_FRAME_LEN);
+	priv->tx_ring[priv->tx_new].status = cpu_to_le32(T_OWN);
 
-	dc2114x_outl(dev, POLL_DEMAND, DE4X5_TPD);
+	dc2114x_outl(priv, POLL_DEMAND, DE4X5_TPD);
 
-	for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
+	for (i = 0; priv->tx_ring[priv->tx_new].status & cpu_to_le32(T_OWN); i++) {
 		if (i < TOUT_LOOP)
 			continue;
 
-		printf("%s: tx buffer not ready\n", dev->name);
+		printf("%s: tx buffer not ready\n", priv->name);
 		return;
 	}
 
-	if (le32_to_cpu(tx_ring[tx_new].status) != 0x7FFFFFFF) {
+	if (le32_to_cpu(priv->tx_ring[priv->tx_new].status) != 0x7FFFFFFF) {
 		printf("TX error status2 = 0x%08X\n",
-		       le32_to_cpu(tx_ring[tx_new].status));
+		       le32_to_cpu(priv->tx_ring[priv->tx_new].status));
 	}
 
-	tx_new = (tx_new + 1) % NUM_TX_DESC;
+	priv->tx_new = (priv->tx_new + 1) % NUM_TX_DESC;
 }
 
-static int dc21x4x_send(struct eth_device *dev, void *packet, int length)
+static int dc21x4x_send_common(struct dc2114x_priv *priv, void *packet, int length)
 {
 	int status = -1;
 	int i;
 
 	if (length <= 0) {
-		printf("%s: bad packet size: %d\n", dev->name, length);
+		printf("%s: bad packet size: %d\n", priv->name, length);
 		goto done;
 	}
 
-	for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
+	for (i = 0; priv->tx_ring[priv->tx_new].status & cpu_to_le32(T_OWN); i++) {
 		if (i < TOUT_LOOP)
 			continue;
 
-		printf("%s: tx error buffer not ready\n", dev->name);
+		printf("%s: tx error buffer not ready\n", priv->name);
 		goto done;
 	}
 
-	tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32)packet));
-	tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_LS | TD_FS | length);
-	tx_ring[tx_new].status = cpu_to_le32(T_OWN);
+	priv->tx_ring[priv->tx_new].buf = cpu_to_le32(phys_to_bus(priv->devno,
+						      (u32)packet));
+	priv->tx_ring[priv->tx_new].des1 = cpu_to_le32(TD_TER | TD_LS | TD_FS | length);
+	priv->tx_ring[priv->tx_new].status = cpu_to_le32(T_OWN);
 
-	dc2114x_outl(dev, POLL_DEMAND, DE4X5_TPD);
+	dc2114x_outl(priv, POLL_DEMAND, DE4X5_TPD);
 
-	for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
+	for (i = 0; priv->tx_ring[priv->tx_new].status & cpu_to_le32(T_OWN); i++) {
 		if (i < TOUT_LOOP)
 			continue;
 
-		printf(".%s: tx buffer not ready\n", dev->name);
+		printf(".%s: tx buffer not ready\n", priv->name);
 		goto done;
 	}
 
-	if (le32_to_cpu(tx_ring[tx_new].status) & TD_ES) {
-		tx_ring[tx_new].status = 0x0;
+	if (le32_to_cpu(priv->tx_ring[priv->tx_new].status) & TD_ES) {
+		priv->tx_ring[priv->tx_new].status = 0x0;
 		goto done;
 	}
 
 	status = length;
 
 done:
-	tx_new = (tx_new + 1) % NUM_TX_DESC;
+	priv->tx_new = (priv->tx_new + 1) % NUM_TX_DESC;
 	return status;
 }
 
-static int dc21x4x_recv(struct eth_device *dev)
+static int dc21x4x_recv_check(struct dc2114x_priv *priv)
 {
 	int length = 0;
 	u32 status;
 
-	while (true) {
-		status = le32_to_cpu(rx_ring[rx_new].status);
-
-		if (status & R_OWN)
-			break;
+	status = le32_to_cpu(priv->rx_ring[priv->rx_new].status);
 
-		if (status & RD_LS) {
-			/* Valid frame status. */
-			if (status & RD_ES) {
-				/* There was an error. */
-				printf("RX error status = 0x%08X\n", status);
-			} else {
-				/* A valid frame received. */
-				length = (le32_to_cpu(rx_ring[rx_new].status)
-					  >> 16);
+	if (status & R_OWN)
+		return 0;
 
-				/* Pass the packet up to the protocol layers */
-				net_process_received_packet
-					(net_rx_packets[rx_new], length - 4);
-			}
+	if (status & RD_LS) {
+		/* Valid frame status. */
+		if (status & RD_ES) {
+			/* There was an error. */
+			printf("RX error status = 0x%08X\n", status);
+			return -EINVAL;
+		} else {
+			/* A valid frame received. */
+			length = (le32_to_cpu(priv->rx_ring[priv->rx_new].status)
+				  >> 16);
 
-			/*
-			 * Change buffer ownership for this frame,
-			 * back to the adapter.
-			 */
-			rx_ring[rx_new].status = cpu_to_le32(R_OWN);
+			return length;
 		}
-
-		/* Update entry information. */
-		rx_new = (rx_new + 1) % rx_ring_size;
 	}
 
-	return length;
+	return -EAGAIN;
 }
 
-static int dc21x4x_init(struct eth_device *dev, struct bd_info *bis)
+static int dc21x4x_init_common(struct dc2114x_priv *priv)
 {
 	int i;
-	int devbusfn = (int)dev->priv;
 
-	/* Ensure we're not sleeping. */
-	pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP);
-
-	reset_de4x5(dev);
+	reset_de4x5(priv);
 
-	if (dc2114x_inl(dev, DE4X5_STS) & (STS_TS | STS_RS)) {
+	if (dc2114x_inl(priv, DE4X5_STS) & (STS_TS | STS_RS)) {
 		printf("Error: Cannot reset ethernet controller.\n");
 		return -1;
 	}
 
-	dc2114x_outl(dev, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR);
+	dc2114x_outl(priv, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR);
 
 	for (i = 0; i < NUM_RX_DESC; i++) {
-		rx_ring[i].status = cpu_to_le32(R_OWN);
-		rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ);
-		rx_ring[i].buf =
-			cpu_to_le32(phys_to_bus((u32)net_rx_packets[i]));
-		rx_ring[i].next = 0;
+		priv->rx_ring[i].status = cpu_to_le32(R_OWN);
+		priv->rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ);
+		priv->rx_ring[i].buf = cpu_to_le32(phys_to_bus(priv->devno,
+					     (u32)net_rx_packets[i]));
+		priv->rx_ring[i].next = 0;
 	}
 
 	for (i = 0; i < NUM_TX_DESC; i++) {
-		tx_ring[i].status = 0;
-		tx_ring[i].des1 = 0;
-		tx_ring[i].buf = 0;
-		tx_ring[i].next = 0;
+		priv->tx_ring[i].status = 0;
+		priv->tx_ring[i].des1 = 0;
+		priv->tx_ring[i].buf = 0;
+		priv->tx_ring[i].next = 0;
 	}
 
-	rx_ring_size = NUM_RX_DESC;
-	tx_ring_size = NUM_TX_DESC;
+	priv->rx_ring_size = NUM_RX_DESC;
+	priv->tx_ring_size = NUM_TX_DESC;
 
 	/* Write the end of list marker to the descriptor lists. */
-	rx_ring[rx_ring_size - 1].des1 |= cpu_to_le32(RD_RER);
-	tx_ring[tx_ring_size - 1].des1 |= cpu_to_le32(TD_TER);
+	priv->rx_ring[priv->rx_ring_size - 1].des1 |= cpu_to_le32(RD_RER);
+	priv->tx_ring[priv->tx_ring_size - 1].des1 |= cpu_to_le32(TD_TER);
 
 	/* Tell the adapter where the TX/RX rings are located. */
-	dc2114x_outl(dev, phys_to_bus((u32)&rx_ring), DE4X5_RRBA);
-	dc2114x_outl(dev, phys_to_bus((u32)&tx_ring), DE4X5_TRBA);
+	dc2114x_outl(priv, phys_to_bus(priv->devno, (u32)&priv->rx_ring),
+		     DE4X5_RRBA);
+	dc2114x_outl(priv, phys_to_bus(priv->devno, (u32)&priv->tx_ring),
+		     DE4X5_TRBA);
 
-	start_de4x5(dev);
+	start_de4x5(priv);
 
-	tx_new = 0;
-	rx_new = 0;
+	priv->tx_new = 0;
+	priv->rx_new = 0;
 
-	send_setup_frame(dev, bis);
+	send_setup_frame(priv);
 
 	return 0;
 }
 
-static void dc21x4x_halt(struct eth_device *dev)
+static void dc21x4x_halt_common(struct dc2114x_priv *priv)
 {
-	int devbusfn = (int)dev->priv;
-
-	stop_de4x5(dev);
-	dc2114x_outl(dev, 0, DE4X5_SICR);
-
-	pci_write_config_byte(devbusfn, PCI_CFDA_PSM, SLEEP);
+	stop_de4x5(priv);
+	dc2114x_outl(priv, 0, DE4X5_SICR);
 }
 
-static void read_hw_addr(struct eth_device *dev, struct bd_info *bis)
+static void read_hw_addr(struct dc2114x_priv *priv)
 {
-	u_short tmp, *p = (u_short *)(&dev->enetaddr[0]);
+	u_short tmp, *p = (u_short *)(&priv->enetaddr[0]);
 	int i, j = 0;
 
 	for (i = 0; i < (ETH_ALEN >> 1); i++) {
-		tmp = read_srom(dev, DE4X5_APROM, (SROM_HWADD >> 1) + i);
+		tmp = read_srom(priv, DE4X5_APROM, (SROM_HWADD >> 1) + i);
 		*p = le16_to_cpu(tmp);
 		j += *p++;
 	}
 
 	if (!j || j == 0x2fffd) {
-		memset(dev->enetaddr, 0, ETH_ALEN);
+		memset(priv->enetaddr, 0, ETH_ALEN);
 		debug("Warning: can't read HW address from SROM.\n");
-#ifdef UPDATE_SROM
-		update_srom(dev, bis);
-#endif
 	}
 }
 
 static struct pci_device_id supported[] = {
-	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST },
-	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142) },
 	{ }
 };
 
+#ifndef CONFIG_DM_ETH
+static int dc21x4x_init(struct eth_device *dev, struct bd_info *bis)
+{
+	struct dc2114x_priv *priv =
+		container_of(dev, struct dc2114x_priv, dev);
+
+	/* Ensure we're not sleeping. */
+	pci_write_config_byte(priv->devno, PCI_CFDA_PSM, WAKEUP);
+
+	return dc21x4x_init_common(priv);
+}
+
+static void dc21x4x_halt(struct eth_device *dev)
+{
+	struct dc2114x_priv *priv =
+		container_of(dev, struct dc2114x_priv, dev);
+
+	dc21x4x_halt_common(priv);
+
+	pci_write_config_byte(priv->devno, PCI_CFDA_PSM, SLEEP);
+}
+
+static int dc21x4x_send(struct eth_device *dev, void *packet, int length)
+{
+	struct dc2114x_priv *priv =
+		container_of(dev, struct dc2114x_priv, dev);
+
+	return dc21x4x_send_common(priv, packet, length);
+}
+
+static int dc21x4x_recv(struct eth_device *dev)
+{
+	struct dc2114x_priv *priv =
+		container_of(dev, struct dc2114x_priv, dev);
+	int length = 0;
+	int ret;
+
+	while (true) {
+		ret = dc21x4x_recv_check(priv);
+		if (!ret)
+			break;
+
+		if (ret > 0) {
+			length = ret;
+			/* Pass the packet up to the protocol layers */
+			net_process_received_packet
+				(net_rx_packets[priv->rx_new], length - 4);
+		}
+
+		/*
+		 * Change buffer ownership for this frame,
+		 * back to the adapter.
+		 */
+		if (ret != -EAGAIN)
+			priv->rx_ring[priv->rx_new].status = cpu_to_le32(R_OWN);
+
+		/* Update entry information. */
+		priv->rx_new = (priv->rx_new + 1) % priv->rx_ring_size;
+	}
+
+	return length;
+}
+
 int dc21x4x_initialize(struct bd_info *bis)
 {
+	struct dc2114x_priv *priv;
 	struct eth_device *dev;
 	unsigned short status;
 	unsigned char timer;
 	unsigned int iobase;
 	int card_number = 0;
 	pci_dev_t devbusfn;
-	unsigned int cfrv;
 	int idx = 0;
 
 	while (1) {
@@ -589,14 +558,6 @@
 		if (devbusfn == -1)
 			break;
 
-		/* Get the chip configuration revision register. */
-		pci_read_config_dword(devbusfn, PCI_REVISION_ID, &cfrv);
-
-		if ((cfrv & CFRV_RN) < DC2114x_BRK) {
-			printf("Error: The chip is not DC21143.\n");
-			continue;
-		}
-
 		pci_read_config_word(devbusfn, PCI_COMMAND, &status);
 		status |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
 		pci_write_config_word(devbusfn, PCI_COMMAND, status);
@@ -625,15 +586,19 @@
 		iobase &= PCI_BASE_ADDRESS_MEM_MASK;
 		debug("dc21x4x: DEC 21142 PCI Device @0x%x\n", iobase);
 
-		dev = (struct eth_device *)malloc(sizeof(*dev));
-		if (!dev) {
+		priv = memalign(32, sizeof(*priv));
+		if (!priv) {
 			printf("Can not allocalte memory of dc21x4x\n");
 			break;
 		}
+		memset(priv, 0, sizeof(*priv));
 
-		memset(dev, 0, sizeof(*dev));
+		dev = &priv->dev;
 
 		sprintf(dev->name, "dc21x4x#%d", card_number);
+		priv->devno = devbusfn;
+		priv->name = dev->name;
+		priv->enetaddr = dev->enetaddr;
 
 		dev->iobase = pci_mem_to_phys(devbusfn, iobase);
 		dev->priv = (void *)devbusfn;
@@ -647,7 +612,7 @@
 
 		udelay(10 * 1000);
 
-		read_hw_addr(dev, bis);
+		read_hw_addr(priv);
 
 		eth_register(dev);
 
@@ -656,3 +621,139 @@
 
 	return card_number;
 }
+
+#else	/* DM_ETH */
+static int dc2114x_start(struct udevice *dev)
+{
+	struct eth_pdata *plat = dev_get_platdata(dev);
+	struct dc2114x_priv *priv = dev_get_priv(dev);
+
+	memcpy(priv->enetaddr, plat->enetaddr, sizeof(plat->enetaddr));
+
+	/* Ensure we're not sleeping. */
+	dm_pci_write_config8(dev, PCI_CFDA_PSM, WAKEUP);
+
+	return dc21x4x_init_common(priv);
+}
+
+static void dc2114x_stop(struct udevice *dev)
+{
+	struct dc2114x_priv *priv = dev_get_priv(dev);
+
+	dc21x4x_halt_common(priv);
+
+	dm_pci_write_config8(dev, PCI_CFDA_PSM, SLEEP);
+}
+
+static int dc2114x_send(struct udevice *dev, void *packet, int length)
+{
+	struct dc2114x_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = dc21x4x_send_common(priv, packet, length);
+
+	return ret ? 0 : -ETIMEDOUT;
+}
+
+static int dc2114x_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct dc2114x_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = dc21x4x_recv_check(priv);
+
+	if (ret < 0) {
+		/* Update entry information. */
+		priv->rx_new = (priv->rx_new + 1) % priv->rx_ring_size;
+		ret = 0;
+	}
+
+	if (!ret)
+		return 0;
+
+	*packetp = net_rx_packets[priv->rx_new];
+
+	return ret - 4;
+}
+
+static int dc2114x_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+	struct dc2114x_priv *priv = dev_get_priv(dev);
+
+	priv->rx_ring[priv->rx_new].status = cpu_to_le32(R_OWN);
+
+	/* Update entry information. */
+	priv->rx_new = (priv->rx_new + 1) % priv->rx_ring_size;
+
+	return 0;
+}
+
+static int dc2114x_read_rom_hwaddr(struct udevice *dev)
+{
+	struct dc2114x_priv *priv = dev_get_priv(dev);
+
+	read_hw_addr(priv);
+
+	return 0;
+}
+
+static int dc2114x_bind(struct udevice *dev)
+{
+	static int card_number;
+	char name[16];
+
+	sprintf(name, "dc2114x#%u", card_number++);
+
+	return device_set_name(dev, name);
+}
+
+static int dc2114x_probe(struct udevice *dev)
+{
+	struct eth_pdata *plat = dev_get_platdata(dev);
+	struct dc2114x_priv *priv = dev_get_priv(dev);
+	u16 command, status;
+	u32 iobase;
+
+	dm_pci_read_config32(dev, PCI_BASE_ADDRESS_1, &iobase);
+	iobase &= ~0xf;
+
+	debug("dc2114x: DEC 2114x PCI Device @0x%x\n", iobase);
+
+	priv->devno = dev;
+	priv->enetaddr = plat->enetaddr;
+	priv->iobase = (void __iomem *)dm_pci_mem_to_phys(dev, iobase);
+
+	command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+	dm_pci_write_config16(dev, PCI_COMMAND, command);
+	dm_pci_read_config16(dev, PCI_COMMAND, &status);
+	if ((status & command) != command) {
+		printf("dc2114x: Couldn't enable IO access or Bus Mastering\n");
+		return -EINVAL;
+	}
+
+	dm_pci_write_config8(dev, PCI_LATENCY_TIMER, 0x60);
+
+	return 0;
+}
+
+static const struct eth_ops dc2114x_ops = {
+	.start		= dc2114x_start,
+	.send		= dc2114x_send,
+	.recv		= dc2114x_recv,
+	.stop		= dc2114x_stop,
+	.free_pkt	= dc2114x_free_pkt,
+	.read_rom_hwaddr = dc2114x_read_rom_hwaddr,
+};
+
+U_BOOT_DRIVER(eth_dc2114x) = {
+	.name	= "eth_dc2114x",
+	.id	= UCLASS_ETH,
+	.bind	= dc2114x_bind,
+	.probe	= dc2114x_probe,
+	.ops	= &dc2114x_ops,
+	.priv_auto_alloc_size = sizeof(struct dc2114x_priv),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
+
+U_BOOT_PCI_DEVICE(eth_dc2114x, supported);
+#endif
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 62941bb..1d9eefb 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -1995,9 +1995,9 @@
 	eqos->dev = dev;
 	eqos->config = (void *)dev_get_driver_data(dev);
 
-	eqos->regs = devfdt_get_addr(dev);
+	eqos->regs = dev_read_addr(dev);
 	if (eqos->regs == FDT_ADDR_T_NONE) {
-		pr_err("devfdt_get_addr() failed");
+		pr_err("dev_read_addr() failed");
 		return -ENODEV;
 	}
 	eqos->mac_regs = (void *)(eqos->regs + EQOS_MAC_REGS_BASE);
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index fd589a0..b9d80a5 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -690,7 +690,7 @@
 	struct ethoc_eth_pdata *pdata = dev_get_platdata(dev);
 	fdt_addr_t addr;
 
-	pdata->eth_pdata.iobase = devfdt_get_addr(dev);
+	pdata->eth_pdata.iobase = dev_read_addr(dev);
 	addr = devfdt_get_addr_index(dev, 1);
 	if (addr != FDT_ADDR_T_NONE)
 		pdata->packet_base = addr;
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index b3d4acb..bb55be9 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -1534,7 +1534,7 @@
 	struct fec_priv *priv = dev_get_priv(dev);
 	const char *phy_mode;
 
-	pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 	priv->eth = (struct ethernet_regs *)pdata->iobase;
 
 	pdata->phy_interface = -1;
diff --git a/drivers/net/fsl_mcdmafec.c b/drivers/net/fsl_mcdmafec.c
index f33529c..e27f7e5 100644
--- a/drivers/net/fsl_mcdmafec.c
+++ b/drivers/net/fsl_mcdmafec.c
@@ -570,7 +570,7 @@
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 	const u32 *val;
 
-	pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 	/* Default to 10Mbit/s */
 	pdata->max_speed = 10;
 
diff --git a/drivers/net/ftgmac100.c b/drivers/net/ftgmac100.c
index e4d08f2..5676a5b 100644
--- a/drivers/net/ftgmac100.c
+++ b/drivers/net/ftgmac100.c
@@ -517,7 +517,7 @@
 	struct ftgmac100_data *priv = dev_get_priv(dev);
 	const char *phy_mode;
 
-	pdata->iobase = devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 	pdata->phy_interface = -1;
 	phy_mode = dev_read_string(dev, "phy-mode");
 	if (phy_mode)
diff --git a/drivers/net/ftmac100.c b/drivers/net/ftmac100.c
index 79c64ec..292690d 100644
--- a/drivers/net/ftmac100.c
+++ b/drivers/net/ftmac100.c
@@ -398,7 +398,7 @@
 	struct ftmac100_data *priv = dev_get_priv(dev);
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 	const char *mac;
-	pdata->iobase = devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 	priv->iobase = pdata->iobase;
 	mac = dtbmacaddr(0);
 	if (mac)
diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c
index 1773c76..d226684 100644
--- a/drivers/net/ks8851_mll.c
+++ b/drivers/net/ks8851_mll.c
@@ -642,7 +642,7 @@
 	struct ks_net *ks = dev_get_priv(dev);
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 
-	pdata->iobase = devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 	ks->iobase = pdata->iobase;
 
 	return 0;
diff --git a/drivers/net/mcffec.c b/drivers/net/mcffec.c
index 1a8351b..f94a2d8 100644
--- a/drivers/net/mcffec.c
+++ b/drivers/net/mcffec.c
@@ -589,7 +589,7 @@
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 	const u32 *val;
 
-	pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 	/* Default to 10Mbit/s */
 	pdata->max_speed = 10;
 
diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c
index 86f1360..a06a157 100644
--- a/drivers/net/mtk_eth.c
+++ b/drivers/net/mtk_eth.c
@@ -1418,7 +1418,7 @@
 
 	priv->soc = dev_get_driver_data(dev);
 
-	pdata->iobase = devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 
 	/* get corresponding ethsys phandle */
 	ret = dev_read_phandle_with_args(dev, "mediatek,ethsys", NULL, 0, 0,
diff --git a/drivers/net/mvgbe.c b/drivers/net/mvgbe.c
index 86b1b8c..2f9464b 100644
--- a/drivers/net/mvgbe.c
+++ b/drivers/net/mvgbe.c
@@ -997,7 +997,7 @@
 	int pnode;
 	unsigned long addr;
 
-	pdata->iobase = devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 	pdata->phy_interface = -1;
 
 	pnode = fdt_node_offset_by_compatible(blob, node,
diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c
index 092f619..4c7d06c 100644
--- a/drivers/net/mvneta.c
+++ b/drivers/net/mvneta.c
@@ -1796,7 +1796,7 @@
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 	const char *phy_mode;
 
-	pdata->iobase = devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 
 	/* Get phy-mode / phy_interface from DT */
 	pdata->phy_interface = -1;
diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c
index 393ee9b..886f53e 100644
--- a/drivers/net/ravb.c
+++ b/drivers/net/ravb.c
@@ -651,7 +651,7 @@
 	const fdt32_t *cell;
 	int ret = 0;
 
-	pdata->iobase = devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 	pdata->phy_interface = -1;
 	phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
 			       NULL);
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 8823769..4cbffb1 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -918,7 +918,7 @@
 	const fdt32_t *cell;
 	int ret = 0;
 
-	pdata->iobase = devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 	pdata->phy_interface = -1;
 	phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
 			       NULL);
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 9c5dc46..09372d7 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -612,7 +612,7 @@
 	struct smc911x_priv *priv = dev_get_priv(dev);
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 
-	pdata->iobase = devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 	priv->iobase = pdata->iobase;
 
 	return 0;
diff --git a/drivers/net/sni_ave.c b/drivers/net/sni_ave.c
index 0784635..0f7ada8 100644
--- a/drivers/net/sni_ave.c
+++ b/drivers/net/sni_ave.c
@@ -746,7 +746,7 @@
 	if (!priv->data)
 		return -EINVAL;
 
-	pdata->iobase = devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 	pdata->phy_interface = -1;
 	phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
 			       NULL);
diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
index e2b05ac..546cc6c 100644
--- a/drivers/net/sun8i_emac.c
+++ b/drivers/net/sun8i_emac.c
@@ -919,7 +919,7 @@
 #endif
 	int ret;
 
-	pdata->iobase = devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 	if (pdata->iobase == FDT_ADDR_T_NONE) {
 		debug("%s: Cannot find MAC base address\n", __func__);
 		return -EINVAL;
diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c
index 6364beb..df18ecc 100644
--- a/drivers/net/sunxi_emac.c
+++ b/drivers/net/sunxi_emac.c
@@ -594,7 +594,7 @@
 {
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 
-	pdata->iobase = devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 
 	return 0;
 }
diff --git a/drivers/net/ti/keystone_net.c b/drivers/net/ti/keystone_net.c
index e3ac40c..50f0d33 100644
--- a/drivers/net/ti/keystone_net.c
+++ b/drivers/net/ti/keystone_net.c
@@ -787,7 +787,7 @@
 
 	ks2_eth_parse_slave_interface(dev_of_offset(dev), gbe_0, priv, pdata);
 
-	pdata->iobase = devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 
 	return 0;
 }
diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c
index 2cd5596..99d4d85 100644
--- a/drivers/net/xilinx_axi_emac.c
+++ b/drivers/net/xilinx_axi_emac.c
@@ -722,7 +722,7 @@
 	int offset = 0;
 	const char *phy_mode;
 
-	pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 	priv->iobase = (struct axi_regs *)pdata->iobase;
 
 	offset = fdtdec_lookup_phandle(gd->fdt_blob, node,
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index 9bdb679..64c18ba 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -599,7 +599,7 @@
 	struct xemaclite *emaclite = dev_get_priv(dev);
 	int offset = 0;
 
-	pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 	emaclite->regs = (struct emaclite_regs *)ioremap_nocache(pdata->iobase,
 								 0x10000);
 
diff --git a/drivers/pci_endpoint/pcie-cadence-ep.c b/drivers/pci_endpoint/pcie-cadence-ep.c
index 59231d3..74dfdde 100644
--- a/drivers/pci_endpoint/pcie-cadence-ep.c
+++ b/drivers/pci_endpoint/pcie-cadence-ep.c
@@ -144,7 +144,7 @@
 {
 	struct cdns_pcie *pdata = dev_get_priv(dev);
 
-	pdata->reg_base = (void __iomem *)devfdt_get_addr(dev);
+	pdata->reg_base = dev_read_addr_ptr(dev);
 	if (!pdata->reg_base)
 		return -ENOMEM;
 
diff --git a/drivers/pinctrl/ath79/pinctrl_ar933x.c b/drivers/pinctrl/ath79/pinctrl_ar933x.c
index a0625d7..61e8081 100644
--- a/drivers/pinctrl/ath79/pinctrl_ar933x.c
+++ b/drivers/pinctrl/ath79/pinctrl_ar933x.c
@@ -111,7 +111,7 @@
 	struct ar933x_pinctrl_priv *priv = dev_get_priv(dev);
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/pinctrl/ath79/pinctrl_qca953x.c b/drivers/pinctrl/ath79/pinctrl_qca953x.c
index c9f9608..2d5a4a3 100644
--- a/drivers/pinctrl/ath79/pinctrl_qca953x.c
+++ b/drivers/pinctrl/ath79/pinctrl_qca953x.c
@@ -131,7 +131,7 @@
 	struct qca953x_pinctrl_priv *priv = dev_get_priv(dev);
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/pinctrl/exynos/pinctrl-exynos.c b/drivers/pinctrl/exynos/pinctrl-exynos.c
index e3ac5a6..4cdc071 100644
--- a/drivers/pinctrl/exynos/pinctrl-exynos.c
+++ b/drivers/pinctrl/exynos/pinctrl-exynos.c
@@ -127,7 +127,7 @@
 	if (!priv)
 		return -EINVAL;
 
-	base = devfdt_get_addr(dev);
+	base = dev_read_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
index 2dee79a..fb49780 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
@@ -592,7 +592,7 @@
 	info->data = (struct armada_37xx_pin_data *)dev_get_driver_data(dev);
 	pin_data = info->data;
 
-	info->base = (void __iomem *)devfdt_get_addr(dev);
+	info->base = dev_read_addr_ptr(dev);
 	if (!info->base) {
 		pr_err("unable to find regmap\n");
 		return -ENODEV;
diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
index 801d142..fdb7920 100644
--- a/drivers/pinctrl/pinctrl-at91-pio4.c
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -158,7 +158,7 @@
 	fdt_addr_t addr_base;
 
 	dev = dev_get_parent(dev);
-	addr_base = devfdt_get_addr(dev);
+	addr_base = dev_read_addr(dev);
 	if (addr_base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/pinctrl/renesas/Kconfig b/drivers/pinctrl/renesas/Kconfig
index 4d3d68d..8327bca 100644
--- a/drivers/pinctrl/renesas/Kconfig
+++ b/drivers/pinctrl/renesas/Kconfig
@@ -77,6 +77,16 @@
 	  the GPIO definitions and pin control functions for each available
 	  multiplex function.
 
+config PINCTRL_PFC_R8A774A1
+        bool "Renesas RCar Gen3 R8A774A1 pin control driver"
+        depends on PINCTRL_PFC
+        help
+          Support pin multiplexing control on Renesas RZG2M R8A774A1 SoCs.
+
+          The driver is controlled by a device tree node which contains both
+          the GPIO definitions and pin control functions for each available
+          multiplex function.
+
 config PINCTRL_PFC_R8A77965
 	bool "Renesas RCar Gen3 R8A77965 pin control driver"
 	depends on PINCTRL_PFC
diff --git a/drivers/pinctrl/renesas/Makefile b/drivers/pinctrl/renesas/Makefile
index a92f787..a4eb912 100644
--- a/drivers/pinctrl/renesas/Makefile
+++ b/drivers/pinctrl/renesas/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_PINCTRL_PFC) += pfc.o
+obj-$(CONFIG_PINCTRL_PFC_R8A774A1) += pfc-r8a7796.o
 obj-$(CONFIG_PINCTRL_PFC_R8A7790) += pfc-r8a7790.o
 obj-$(CONFIG_PINCTRL_PFC_R8A7791) += pfc-r8a7791.o
 obj-$(CONFIG_PINCTRL_PFC_R8A7792) += pfc-r8a7792.o
diff --git a/drivers/pinctrl/renesas/pfc-r7s72100.c b/drivers/pinctrl/renesas/pfc-r7s72100.c
index 5055780..9d7814a 100644
--- a/drivers/pinctrl/renesas/pfc-r7s72100.c
+++ b/drivers/pinctrl/renesas/pfc-r7s72100.c
@@ -112,7 +112,7 @@
 	fdt_addr_t addr_base;
 	ofnode node;
 
-	addr_base = devfdt_get_addr(dev);
+	addr_base = dev_read_addr(dev);
 	if (addr_base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/pinctrl/renesas/pfc.c b/drivers/pinctrl/renesas/pfc.c
index 1179afd..7183b11 100644
--- a/drivers/pinctrl/renesas/pfc.c
+++ b/drivers/pinctrl/renesas/pfc.c
@@ -32,6 +32,7 @@
 	SH_PFC_R8A7794,
 	SH_PFC_R8A7795,
 	SH_PFC_R8A7796,
+	SH_PFC_R8A774A1,
 	SH_PFC_R8A77965,
 	SH_PFC_R8A77970,
 	SH_PFC_R8A77980,
@@ -817,7 +818,7 @@
 	enum sh_pfc_model model = dev_get_driver_data(dev);
 	fdt_addr_t base;
 
-	base = devfdt_get_addr(dev);
+	base = dev_read_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
@@ -853,6 +854,10 @@
 	if (model == SH_PFC_R8A7796)
 		priv->pfc.info = &r8a7796_pinmux_info;
 #endif
+#ifdef CONFIG_PINCTRL_PFC_R8A774A1
+	if (model == SH_PFC_R8A774A1)
+		priv->pfc.info = &r8a774a1_pinmux_info;
+#endif
 #ifdef CONFIG_PINCTRL_PFC_R8A77965
 	if (model == SH_PFC_R8A77965)
 		priv->pfc.info = &r8a77965_pinmux_info;
@@ -924,6 +929,12 @@
 		.data = SH_PFC_R8A7796,
 	},
 #endif
+#ifdef CONFIG_PINCTRL_PFC_R8A774A1
+	{
+		.compatible = "renesas,pfc-r8a774a1",
+		.data = SH_PFC_R8A774A1,
+	},
+#endif
 #ifdef CONFIG_PINCTRL_PFC_R8A77965
 	{
 		.compatible = "renesas,pfc-r8a77965",
diff --git a/drivers/pinctrl/renesas/sh_pfc.h b/drivers/pinctrl/renesas/sh_pfc.h
index db3d513..81c0179 100644
--- a/drivers/pinctrl/renesas/sh_pfc.h
+++ b/drivers/pinctrl/renesas/sh_pfc.h
@@ -293,6 +293,7 @@
 sh_pfc_pin_to_bias_reg(const struct sh_pfc *pfc, unsigned int pin,
 		       unsigned int *bit);
 
+extern const struct sh_pfc_soc_info r8a774a1_pinmux_info;
 extern const struct sh_pfc_soc_info r8a7790_pinmux_info;
 extern const struct sh_pfc_soc_info r8a7791_pinmux_info;
 extern const struct sh_pfc_soc_info r8a7792_pinmux_info;
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index 8545b9d..631bb1f 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -422,7 +422,7 @@
 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev->parent);
+	addr = dev_read_addr(dev->parent);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/pwm/exynos_pwm.c b/drivers/pwm/exynos_pwm.c
index fed1583..e55fcce 100644
--- a/drivers/pwm/exynos_pwm.c
+++ b/drivers/pwm/exynos_pwm.c
@@ -92,7 +92,7 @@
 {
 	struct exynos_pwm_priv *priv = dev_get_priv(dev);
 
-	priv->regs = (struct s5p_timer *)devfdt_get_addr(dev);
+	priv->regs = dev_read_addr_ptr(dev);
 
 	return 0;
 }
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index f5b9544..77a1907 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -130,7 +130,7 @@
 {
 	struct imx_pwm_priv *priv = dev_get_priv(dev);
 
-	priv->regs = (struct pwm_regs *)devfdt_get_addr(dev);
+	priv->regs = dev_read_addr_ptr(dev);
 
 	return 0;
 }
diff --git a/drivers/pwm/pwm-mtk.c b/drivers/pwm/pwm-mtk.c
index 97ed477..7bd8251 100644
--- a/drivers/pwm/pwm-mtk.c
+++ b/drivers/pwm/pwm-mtk.c
@@ -130,7 +130,7 @@
 	int i;
 
 	priv->soc = (struct mtk_pwm_soc *)dev_get_driver_data(dev);
-	priv->base = (void __iomem *)devfdt_get_addr(dev);
+	priv->base = dev_read_addr_ptr(dev);
 	if (!priv->base)
 		return -EINVAL;
 	ret = clk_get_by_name(dev, "top", &priv->top_clk);
diff --git a/drivers/pwm/sunxi_pwm.c b/drivers/pwm/sunxi_pwm.c
index 56215db..e2ae1a8 100644
--- a/drivers/pwm/sunxi_pwm.c
+++ b/drivers/pwm/sunxi_pwm.c
@@ -152,7 +152,7 @@
 {
 	struct sunxi_pwm_priv *priv = dev_get_priv(dev);
 
-	priv->regs = (struct sunxi_pwm *)devfdt_get_addr(dev);
+	priv->regs = dev_read_addr_ptr(dev);
 
 	return 0;
 }
diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c
index 06079d2..fe1bd55 100644
--- a/drivers/reset/reset-uniphier.c
+++ b/drivers/reset/reset-uniphier.c
@@ -247,7 +247,7 @@
 	struct uniphier_reset_priv *priv = dev_get_priv(dev);
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev->parent);
+	addr = dev_read_addr(dev->parent);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/rtc/mvrtc.c b/drivers/rtc/mvrtc.c
index 6f49505..ed057f7 100644
--- a/drivers/rtc/mvrtc.c
+++ b/drivers/rtc/mvrtc.c
@@ -172,7 +172,7 @@
 {
 	struct mvrtc_pdata *pdata = dev_get_platdata(dev);
 
-	pdata->iobase = devfdt_get_addr(dev);
+	pdata->iobase = dev_read_addr(dev);
 	return 0;
 }
 
diff --git a/drivers/serial/altera_jtag_uart.c b/drivers/serial/altera_jtag_uart.c
index 7a86161..35b76f5 100644
--- a/drivers/serial/altera_jtag_uart.c
+++ b/drivers/serial/altera_jtag_uart.c
@@ -95,7 +95,7 @@
 {
 	struct altera_jtaguart_platdata *plat = dev_get_platdata(dev);
 
-	plat->regs = map_physmem(devfdt_get_addr(dev),
+	plat->regs = map_physmem(dev_read_addr(dev),
 				 sizeof(struct altera_jtaguart_regs),
 				 MAP_NOCACHE);
 
diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c
index f88a293..0be5cd7 100644
--- a/drivers/serial/altera_uart.c
+++ b/drivers/serial/altera_uart.c
@@ -87,7 +87,7 @@
 {
 	struct altera_uart_platdata *plat = dev_get_platdata(dev);
 
-	plat->regs = map_physmem(devfdt_get_addr(dev),
+	plat->regs = map_physmem(dev_read_addr(dev),
 				 sizeof(struct altera_uart_regs),
 				 MAP_NOCACHE);
 	plat->uartclk = dev_read_u32_default(dev, "clock-frequency", 0);
diff --git a/drivers/serial/atmel_usart.c b/drivers/serial/atmel_usart.c
index 71cb31f..f759ea8 100644
--- a/drivers/serial/atmel_usart.c
+++ b/drivers/serial/atmel_usart.c
@@ -268,7 +268,7 @@
 #if CONFIG_IS_ENABLED(OF_CONTROL)
 	fdt_addr_t addr_base;
 
-	addr_base = devfdt_get_addr(dev);
+	addr_base = dev_read_addr(dev);
 	if (addr_base == FDT_ADDR_T_NONE)
 		return -ENODEV;
 
diff --git a/drivers/serial/serial_ar933x.c b/drivers/serial/serial_ar933x.c
index 382c3b3..9de94b6 100644
--- a/drivers/serial/serial_ar933x.c
+++ b/drivers/serial/serial_ar933x.c
@@ -150,7 +150,7 @@
 	fdt_addr_t addr;
 	u32 val;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_arc.c b/drivers/serial/serial_arc.c
index 70dbc6d..04063fb 100644
--- a/drivers/serial/serial_arc.c
+++ b/drivers/serial/serial_arc.c
@@ -114,7 +114,7 @@
 	struct arc_serial_platdata *plat = dev_get_platdata(dev);
 	DECLARE_GLOBAL_DATA_PTR;
 
-	plat->reg = (struct arc_serial_regs *)devfdt_get_addr(dev);
+	plat->reg = dev_read_addr_ptr(dev);
 	plat->uartclk = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 				       "clock-frequency", 0);
 
diff --git a/drivers/serial/serial_bcm283x_mu.c b/drivers/serial/serial_bcm283x_mu.c
index 0102b10..8a4af87 100644
--- a/drivers/serial/serial_bcm283x_mu.c
+++ b/drivers/serial/serial_bcm283x_mu.c
@@ -171,7 +171,7 @@
 	 * since we need the soc simple-bus to be probed so that the 'ranges'
 	 * property is used.
 	 */
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c
index 0c63c41..95cbe63 100644
--- a/drivers/serial/serial_lpuart.c
+++ b/drivers/serial/serial_lpuart.c
@@ -518,7 +518,7 @@
 	int node = dev_of_offset(dev);
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_mcf.c b/drivers/serial/serial_mcf.c
index b599064..402fd53 100644
--- a/drivers/serial/serial_mcf.c
+++ b/drivers/serial/serial_mcf.c
@@ -145,7 +145,7 @@
 	struct coldfire_serial_platdata *plat = dev_get_platdata(dev);
 	fdt_addr_t addr_base;
 
-	addr_base = devfdt_get_addr(dev);
+	addr_base = dev_read_addr(dev);
 	if (addr_base == FDT_ADDR_T_NONE)
 		return -ENODEV;
 
diff --git a/drivers/serial/serial_meson.c b/drivers/serial/serial_meson.c
index 439057b..8cf849f 100644
--- a/drivers/serial/serial_meson.c
+++ b/drivers/serial/serial_meson.c
@@ -106,7 +106,7 @@
 	struct meson_serial_platdata *plat = dev->platdata;
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_msm.c b/drivers/serial/serial_msm.c
index 0cc1aad..a1c9abc 100644
--- a/drivers/serial/serial_msm.c
+++ b/drivers/serial/serial_msm.c
@@ -219,7 +219,7 @@
 {
 	struct msm_serial_data *priv = dev_get_priv(dev);
 
-	priv->base = devfdt_get_addr(dev);
+	priv->base = dev_read_addr(dev);
 	if (priv->base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c
index 42abb96..de6cefc 100644
--- a/drivers/serial/serial_mxc.c
+++ b/drivers/serial/serial_mxc.c
@@ -330,7 +330,7 @@
 	struct mxc_serial_platdata *plat = dev->platdata;
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index 6e5d81c..2772c25 100644
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -354,7 +354,7 @@
 	fdt_addr_t addr;
 	int ret;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c
index e3160cf..9bb2be2 100644
--- a/drivers/serial/serial_s5p.c
+++ b/drivers/serial/serial_s5p.c
@@ -181,7 +181,7 @@
 	struct s5p_serial_platdata *plat = dev->platdata;
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c
index 5f45d58..13b179f 100644
--- a/drivers/serial/serial_sh.c
+++ b/drivers/serial/serial_sh.c
@@ -211,7 +211,7 @@
 	fdt_addr_t addr;
 	int ret;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (!addr)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_sti_asc.c b/drivers/serial/serial_sti_asc.c
index 5fbbfac..33ff396 100644
--- a/drivers/serial/serial_sti_asc.c
+++ b/drivers/serial/serial_sti_asc.c
@@ -171,7 +171,7 @@
 	unsigned long val;
 	fdt_addr_t base;
 
-	base = devfdt_get_addr(dev);
+	base = dev_read_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_stm32.c b/drivers/serial/serial_stm32.c
index e77b906..cab0db2 100644
--- a/drivers/serial/serial_stm32.c
+++ b/drivers/serial/serial_stm32.c
@@ -221,7 +221,7 @@
 {
 	struct stm32x7_serial_platdata *plat = dev_get_platdata(dev);
 
-	plat->base = devfdt_get_addr(dev);
+	plat->base = dev_read_addr(dev);
 	if (plat->base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_uniphier.c b/drivers/serial/serial_uniphier.c
index ad691b6..4004cb8 100644
--- a/drivers/serial/serial_uniphier.c
+++ b/drivers/serial/serial_uniphier.c
@@ -115,7 +115,7 @@
 	fdt_addr_t base;
 	u32 tmp;
 
-	base = devfdt_get_addr(dev);
+	base = dev_read_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_xuartlite.c b/drivers/serial/serial_xuartlite.c
index f29a9a0..5116d13 100644
--- a/drivers/serial/serial_xuartlite.c
+++ b/drivers/serial/serial_xuartlite.c
@@ -85,7 +85,7 @@
 {
 	struct uartlite_platdata *plat = dev_get_platdata(dev);
 
-	plat->regs = (struct uartlite *)devfdt_get_addr(dev);
+	plat->regs = dev_read_addr_ptr(dev);
 
 	return 0;
 }
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 7b4e4d6..864d00a 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -1,5 +1,21 @@
 menu "SOC (System On Chip) specific Drivers"
 
+config SOC_DEVICE
+	bool "Enable SoC Device ID drivers using Driver Model"
+	help
+	  This allows drivers to be provided for SoCs to help in identifying
+	  the SoC in use and matching SoC attributes for selecting SoC
+	  specific data. This is useful for other device drivers that may
+	  need different parameters or quirks enabled depending on the
+	  specific device variant in use.
+
+config SOC_DEVICE_TI_K3
+	depends on SOC_DEVICE
+	bool "Enable SoC Device ID driver for TI K3 SoCs"
+	help
+	  This allows Texas Instruments Keystone 3 SoCs to identify
+	  specifics about the SoC in use.
+
 source "drivers/soc/ti/Kconfig"
 
 endmenu
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index ce253b7..9ef20ca 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -3,3 +3,6 @@
 # Makefile for the U-Boot SOC specific device drivers.
 
 obj-$(CONFIG_SOC_TI) += ti/
+obj-$(CONFIG_SOC_DEVICE) += soc-uclass.o
+obj-$(CONFIG_SOC_DEVICE_TI_K3) += soc_ti_k3.o
+obj-$(CONFIG_SANDBOX) += soc_sandbox.o
diff --git a/drivers/soc/soc-uclass.c b/drivers/soc/soc-uclass.c
new file mode 100644
index 0000000..c32d647
--- /dev/null
+++ b/drivers/soc/soc-uclass.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2020 - Texas Instruments Incorporated - http://www.ti.com/
+ *	Dave Gerlach <d-gerlach@ti.com>
+ */
+
+#include <common.h>
+#include <soc.h>
+#include <dm.h>
+#include <errno.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+
+int soc_get(struct udevice **devp)
+{
+	return uclass_first_device_err(UCLASS_SOC, devp);
+}
+
+int soc_get_machine(struct udevice *dev, char *buf, int size)
+{
+	struct soc_ops *ops = soc_get_ops(dev);
+
+	if (!ops->get_machine)
+		return -ENOSYS;
+
+	return ops->get_machine(dev, buf, size);
+}
+
+int soc_get_family(struct udevice *dev, char *buf, int size)
+{
+	struct soc_ops *ops = soc_get_ops(dev);
+
+	if (!ops->get_family)
+		return -ENOSYS;
+
+	return ops->get_family(dev, buf, size);
+}
+
+int soc_get_revision(struct udevice *dev, char *buf, int size)
+{
+	struct soc_ops *ops = soc_get_ops(dev);
+
+	if (!ops->get_revision)
+		return -ENOSYS;
+
+	return ops->get_revision(dev, buf, size);
+}
+
+const struct soc_attr *
+soc_device_match(const struct soc_attr *matches)
+{
+	bool match;
+	struct udevice *soc;
+	char str[SOC_MAX_STR_SIZE];
+
+	if (!matches)
+		return NULL;
+
+	if (soc_get(&soc))
+		return NULL;
+
+	while (1) {
+		if (!(matches->machine || matches->family ||
+		      matches->revision))
+			break;
+
+		match = true;
+
+		if (matches->machine) {
+			if (!soc_get_machine(soc, str, SOC_MAX_STR_SIZE)) {
+				if (strcmp(matches->machine, str))
+					match = false;
+			}
+		}
+
+		if (matches->family) {
+			if (!soc_get_family(soc, str, SOC_MAX_STR_SIZE)) {
+				if (strcmp(matches->family, str))
+					match = false;
+			}
+		}
+
+		if (matches->revision) {
+			if (!soc_get_revision(soc, str, SOC_MAX_STR_SIZE)) {
+				if (strcmp(matches->revision, str))
+					match = false;
+			}
+		}
+
+		if (match)
+			return matches;
+
+		matches++;
+	}
+
+	return NULL;
+}
+
+UCLASS_DRIVER(soc) = {
+	.id		= UCLASS_SOC,
+	.name		= "soc",
+};
diff --git a/drivers/soc/soc_sandbox.c b/drivers/soc/soc_sandbox.c
new file mode 100644
index 0000000..5c82ad8
--- /dev/null
+++ b/drivers/soc/soc_sandbox.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Sandbox driver for the SOC uclass
+ *
+ * (C) Copyright 2020 - Texas Instruments Incorporated - http://www.ti.com/
+ * Dave Gerlach <d-gerlach@ti.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <soc.h>
+
+int soc_sandbox_get_family(struct udevice *dev, char *buf, int size)
+{
+	snprintf(buf, size, "SANDBOX1xx");
+
+	return 0;
+}
+
+int soc_sandbox_get_machine(struct udevice *dev, char *buf, int size)
+{
+	snprintf(buf, size, "SANDBOX123");
+
+	return 0;
+}
+
+int soc_sandbox_get_revision(struct udevice *dev, char *buf, int size)
+{
+	snprintf(buf, size, "1.0");
+
+	return 0;
+}
+
+static const struct soc_ops soc_sandbox_ops = {
+	.get_family = soc_sandbox_get_family,
+	.get_revision = soc_sandbox_get_revision,
+	.get_machine = soc_sandbox_get_machine,
+};
+
+int soc_sandbox_probe(struct udevice *dev)
+{
+	return 0;
+}
+
+static const struct udevice_id soc_sandbox_ids[] = {
+	{ .compatible = "sandbox,soc" },
+	{ }
+};
+
+U_BOOT_DRIVER(soc_sandbox) = {
+	.name           = "soc_sandbox",
+	.id             = UCLASS_SOC,
+	.ops		= &soc_sandbox_ops,
+	.of_match       = soc_sandbox_ids,
+	.probe          = soc_sandbox_probe,
+};
diff --git a/drivers/soc/soc_ti_k3.c b/drivers/soc/soc_ti_k3.c
new file mode 100644
index 0000000..ae23ef7
--- /dev/null
+++ b/drivers/soc/soc_ti_k3.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
+ *	Dave Gerlach <d-gerlach@ti.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <soc.h>
+
+#include <asm/io.h>
+
+#define AM65X			0xbb5a
+#define J721E			0xbb64
+
+#define REV_SR1_0		0
+#define REV_SR2_0		1
+
+#define JTAG_ID_VARIANT_SHIFT	28
+#define JTAG_ID_VARIANT_MASK	(0xf << 28)
+#define JTAG_ID_PARTNO_SHIFT	12
+#define JTAG_ID_PARTNO_MASK	(0xffff << 12)
+
+struct soc_ti_k3_platdata {
+	const char *family;
+	const char *revision;
+};
+
+static const char *get_family_string(u32 idreg)
+{
+	const char *family;
+	u32 soc;
+
+	soc = (idreg & JTAG_ID_PARTNO_MASK) >> JTAG_ID_PARTNO_SHIFT;
+
+	switch (soc) {
+	case AM65X:
+		family = "AM65X";
+		break;
+	case J721E:
+		family = "J721E";
+		break;
+	default:
+		family = "Unknown Silicon";
+	};
+
+	return family;
+}
+
+static const char *get_rev_string(u32 idreg)
+{
+	const char *revision;
+	u32 rev;
+
+	rev = (idreg & JTAG_ID_VARIANT_MASK) >> JTAG_ID_VARIANT_SHIFT;
+
+	switch (rev) {
+	case REV_SR1_0:
+		revision = "1.0";
+		break;
+	case REV_SR2_0:
+		revision = "2.0";
+		break;
+	default:
+		revision = "Unknown Revision";
+	};
+
+	return revision;
+}
+
+static int soc_ti_k3_get_family(struct udevice *dev, char *buf, int size)
+{
+	struct soc_ti_k3_platdata *plat = dev_get_platdata(dev);
+
+	snprintf(buf, size, "%s", plat->family);
+
+	return 0;
+}
+
+static int soc_ti_k3_get_revision(struct udevice *dev, char *buf, int size)
+{
+	struct soc_ti_k3_platdata *plat = dev_get_platdata(dev);
+
+	snprintf(buf, size, "SR%s", plat->revision);
+
+	return 0;
+}
+
+static const struct soc_ops soc_ti_k3_ops = {
+	.get_family = soc_ti_k3_get_family,
+	.get_revision = soc_ti_k3_get_revision,
+};
+
+int soc_ti_k3_probe(struct udevice *dev)
+{
+	struct soc_ti_k3_platdata *plat = dev_get_platdata(dev);
+	u32 idreg;
+	void *idreg_addr;
+
+	idreg_addr = dev_read_addr_ptr(dev);
+	if (!idreg_addr)
+		return -EINVAL;
+
+	idreg = readl(idreg_addr);
+
+	plat->family = get_family_string(idreg);
+	plat->revision = get_rev_string(idreg);
+
+	return 0;
+}
+
+static const struct udevice_id soc_ti_k3_ids[] = {
+	{ .compatible = "ti,am654-chipid" },
+	{ }
+};
+
+U_BOOT_DRIVER(soc_ti_k3) = {
+	.name           = "soc_ti_k3",
+	.id             = UCLASS_SOC,
+	.ops		= &soc_ti_k3_ops,
+	.of_match       = soc_ti_k3_ids,
+	.probe          = soc_ti_k3_probe,
+	.platdata_auto_alloc_size = sizeof(struct soc_ti_k3_platdata),
+};
diff --git a/drivers/spi/altera_spi.c b/drivers/spi/altera_spi.c
index 3aa7a40..61372c5 100644
--- a/drivers/spi/altera_spi.c
+++ b/drivers/spi/altera_spi.c
@@ -173,7 +173,7 @@
 {
 	struct altera_spi_platdata *plat = dev_get_platdata(bus);
 
-	plat->regs = map_physmem(devfdt_get_addr(bus),
+	plat->regs = map_physmem(dev_read_addr(bus),
 				 sizeof(struct altera_spi_regs),
 				 MAP_NOCACHE);
 
diff --git a/drivers/spi/atcspi200_spi.c b/drivers/spi/atcspi200_spi.c
index 328b16c..39c6e22 100644
--- a/drivers/spi/atcspi200_spi.c
+++ b/drivers/spi/atcspi200_spi.c
@@ -378,7 +378,7 @@
 	const void *blob = gd->fdt_blob;
 	int node = dev_of_offset(bus);
 
-	ns->regs = map_physmem(devfdt_get_addr(bus),
+	ns->regs = map_physmem(dev_read_addr(bus),
 				 sizeof(struct atcspi200_spi_regs),
 				 MAP_NOCACHE);
 	if (!ns->regs) {
diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/ath79_spi.c
index f64a28c..70bedc7 100644
--- a/drivers/spi/ath79_spi.c
+++ b/drivers/spi/ath79_spi.c
@@ -178,7 +178,7 @@
 	struct ath79_spi_priv *priv = dev_get_priv(bus);
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(bus);
+	addr = dev_read_addr(bus);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index b120664..c65733c 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -351,7 +351,7 @@
 	if (ret)
 		return ret;
 
-	bus_plat->regs = (struct at91_spi *)devfdt_get_addr(bus);
+	bus_plat->regs = dev_read_addr_ptr(bus);
 
 #if CONFIG_IS_ENABLED(DM_GPIO)
 	struct atmel_spi_priv *priv = dev_get_priv(bus);
diff --git a/drivers/spi/cf_spi.c b/drivers/spi/cf_spi.c
index dec92df..8fa6d35 100644
--- a/drivers/spi/cf_spi.c
+++ b/drivers/spi/cf_spi.c
@@ -392,7 +392,7 @@
 	int node = dev_of_offset(bus);
 	int *ctar, len;
 
-	addr = devfdt_get_addr(bus);
+	addr = dev_read_addr(bus);
 	if (addr == FDT_ADDR_T_NONE)
 		return -ENOMEM;
 
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
index e1e9b45..a11433d 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -396,7 +396,7 @@
 	struct davinci_spi_platdata *plat = bus->platdata;
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(bus);
+	addr = dev_read_addr(bus);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index c9b14f9..2559aac 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -157,7 +157,7 @@
 {
 	struct dw_spi_platdata *plat = bus->platdata;
 
-	plat->regs = (struct dw_spi *)devfdt_get_addr(bus);
+	plat->regs = dev_read_addr_ptr(bus);
 
 	/* Use 500KHz as a suitable default */
 	plat->frequency = dev_read_u32_default(bus, "spi-max-frequency",
diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c
index 746686a..d338ff5 100644
--- a/drivers/spi/exynos_spi.c
+++ b/drivers/spi/exynos_spi.c
@@ -257,7 +257,7 @@
 	const void *blob = gd->fdt_blob;
 	int node = dev_of_offset(bus);
 
-	plat->regs = (struct exynos_spi *)devfdt_get_addr(bus);
+	plat->regs = dev_read_addr_ptr(bus);
 	plat->periph_id = pinmux_decode_periph_id(blob, node);
 
 	if (plat->periph_id == PERIPH_ID_NONE) {
diff --git a/drivers/spi/fsl_dspi.c b/drivers/spi/fsl_dspi.c
index c55ebee..b22c9b3 100644
--- a/drivers/spi/fsl_dspi.c
+++ b/drivers/spi/fsl_dspi.c
@@ -586,7 +586,7 @@
 	plat->num_chipselect =
 		fdtdec_get_int(blob, node, "num-cs", FSL_DSPI_MAX_CHIPSELECT);
 
-	addr = devfdt_get_addr(bus);
+	addr = dev_read_addr(bus);
 	if (addr == FDT_ADDR_T_NONE) {
 		debug("DSPI: Can't get base address or size\n");
 		return -ENOMEM;
diff --git a/drivers/spi/kirkwood_spi.c b/drivers/spi/kirkwood_spi.c
index 92dc2e1..dc7d2bc 100644
--- a/drivers/spi/kirkwood_spi.c
+++ b/drivers/spi/kirkwood_spi.c
@@ -236,7 +236,7 @@
 	const struct mvebu_spi_dev *drvdata =
 		(struct mvebu_spi_dev *)dev_get_driver_data(bus);
 
-	plat->spireg = (struct kwspi_registers *)devfdt_get_addr(bus);
+	plat->spireg = dev_read_addr_ptr(bus);
 	plat->is_errata_50mhz_ac = drvdata->is_errata_50mhz_ac;
 
 	return 0;
diff --git a/drivers/spi/mtk_snfi_spi.c b/drivers/spi/mtk_snfi_spi.c
index 2a89476..c30c8f4 100644
--- a/drivers/spi/mtk_snfi_spi.c
+++ b/drivers/spi/mtk_snfi_spi.c
@@ -253,7 +253,7 @@
 	struct mtk_snfi_priv *priv = dev_get_priv(bus);
 	int ret;
 
-	priv->base = (void __iomem *)devfdt_get_addr(bus);
+	priv->base = dev_read_addr_ptr(bus);
 	if (!priv->base)
 		return -EINVAL;
 
diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c
index 2302e62..e860b9e 100644
--- a/drivers/spi/mvebu_a3700_spi.c
+++ b/drivers/spi/mvebu_a3700_spi.c
@@ -255,7 +255,7 @@
 	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
 	int ret;
 
-	plat->spireg = (struct spi_reg *)devfdt_get_addr(bus);
+	plat->spireg = dev_read_addr_ptr(bus);
 
 	ret = clk_get_by_index(bus, 0, &plat->clk);
 	if (ret) {
diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c
index aad3780..e90a06a 100644
--- a/drivers/spi/mxc_spi.c
+++ b/drivers/spi/mxc_spi.c
@@ -537,7 +537,7 @@
 		}
 	}
 
-	mxcs->base = devfdt_get_addr(bus);
+	mxcs->base = dev_read_addr(bus);
 	if (mxcs->base == FDT_ADDR_T_NONE)
 		return -ENODEV;
 
diff --git a/drivers/spi/omap3_spi.c b/drivers/spi/omap3_spi.c
index 39e6813..fbf9575 100644
--- a/drivers/spi/omap3_spi.c
+++ b/drivers/spi/omap3_spi.c
@@ -488,7 +488,7 @@
 	struct omap2_mcspi_platform_config* data =
 		(struct omap2_mcspi_platform_config*)dev_get_driver_data(dev);
 
-	priv->regs = (struct mcspi *)(devfdt_get_addr(dev) + data->regs_offset);
+	priv->regs = (struct mcspi *)(dev_read_addr(dev) + data->regs_offset);
 	if (fdtdec_get_bool(blob, node, "ti,pindir-d0-out-d1-in"))
 		priv->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN;
 	else
diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c
index d2dccd6..cd2e17b 100644
--- a/drivers/spi/spi-sunxi.c
+++ b/drivers/spi/spi-sunxi.c
@@ -519,7 +519,7 @@
 	struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
 	int node = dev_of_offset(bus);
 
-	plat->base = devfdt_get_addr(bus);
+	plat->base = dev_read_addr(bus);
 	plat->variant = (struct sun4i_spi_variant *)dev_get_driver_data(bus);
 	plat->max_hz = fdtdec_get_int(gd->fdt_blob, node,
 				      "spi-max-frequency",
diff --git a/drivers/spi/tegra20_sflash.c b/drivers/spi/tegra20_sflash.c
index 22a0304..771744d 100644
--- a/drivers/spi/tegra20_sflash.c
+++ b/drivers/spi/tegra20_sflash.c
@@ -93,7 +93,7 @@
 	const void *blob = gd->fdt_blob;
 	int node = dev_of_offset(bus);
 
-	plat->base = devfdt_get_addr(bus);
+	plat->base = dev_read_addr(bus);
 	plat->periph_id = clock_decode_periph_id(bus);
 
 	if (plat->periph_id == PERIPH_ID_NONE) {
diff --git a/drivers/spi/tegra20_slink.c b/drivers/spi/tegra20_slink.c
index 3679cf0..f9846ee 100644
--- a/drivers/spi/tegra20_slink.c
+++ b/drivers/spi/tegra20_slink.c
@@ -99,7 +99,7 @@
 	const void *blob = gd->fdt_blob;
 	int node = dev_of_offset(bus);
 
-	plat->base = devfdt_get_addr(bus);
+	plat->base = dev_read_addr(bus);
 	plat->periph_id = clock_decode_periph_id(bus);
 
 	if (plat->periph_id == PERIPH_ID_NONE) {
diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c
index 0db0de8..5fdbb49 100644
--- a/drivers/spi/ti_qspi.c
+++ b/drivers/spi/ti_qspi.c
@@ -461,7 +461,7 @@
 	fdt_addr_t mmap_size;
 
 	priv->ctrl_mod_mmap = map_syscon_chipselects(bus);
-	priv->base = map_physmem(devfdt_get_addr(bus),
+	priv->base = map_physmem(dev_read_addr(bus),
 				 sizeof(struct ti_qspi_regs), MAP_NOCACHE);
 	mmap_addr = devfdt_get_addr_size_index(bus, 1, &mmap_size);
 	priv->memory_map = map_physmem(mmap_addr, mmap_size, MAP_NOCACHE);
diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c
index 78ffd3e..9923931 100644
--- a/drivers/spi/zynq_spi.c
+++ b/drivers/spi/zynq_spi.c
@@ -77,7 +77,7 @@
 	const void *blob = gd->fdt_blob;
 	int node = dev_of_offset(bus);
 
-	plat->regs = (struct zynq_spi_regs *)devfdt_get_addr(bus);
+	plat->regs = dev_read_addr_ptr(bus);
 
 	/* FIXME: Use 250MHz as a suitable default */
 	plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
diff --git a/drivers/spi/zynqmp_gqspi.c b/drivers/spi/zynqmp_gqspi.c
index c3a5b3e..a72986b 100644
--- a/drivers/spi/zynqmp_gqspi.c
+++ b/drivers/spi/zynqmp_gqspi.c
@@ -181,10 +181,10 @@
 
 	debug("%s\n", __func__);
 
-	plat->regs = (struct zynqmp_qspi_regs *)(devfdt_get_addr(bus) +
+	plat->regs = (struct zynqmp_qspi_regs *)(dev_read_addr(bus) +
 						 GQSPI_REG_OFFSET);
 	plat->dma_regs = (struct zynqmp_qspi_dma_regs *)
-			  (devfdt_get_addr(bus) + GQSPI_DMA_REG_OFFSET);
+			  (dev_read_addr(bus) + GQSPI_DMA_REG_OFFSET);
 
 	return 0;
 }
diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c
index ed93faf..2f430ae 100644
--- a/drivers/spmi/spmi-msm.c
+++ b/drivers/spmi/spmi-msm.c
@@ -156,7 +156,7 @@
 	bool is_v1;
 	int i;
 
-	priv->arb_chnl = devfdt_get_addr(dev);
+	priv->arb_chnl = dev_read_addr(dev);
 	priv->spmi_core = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
 			dev_of_offset(parent), node, "reg", 1, NULL, false);
 	priv->spmi_obs = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
diff --git a/drivers/timer/ag101p_timer.c b/drivers/timer/ag101p_timer.c
index 6e20b4f..c011906 100644
--- a/drivers/timer/ag101p_timer.c
+++ b/drivers/timer/ag101p_timer.c
@@ -92,7 +92,7 @@
 static int atftme_timer_ofdata_to_platdata(struct udevice *dev)
 {
 	struct atftmr_timer_platdata *plat = dev_get_platdata(dev);
-	plat->regs = map_physmem(devfdt_get_addr(dev),
+	plat->regs = map_physmem(dev_read_addr(dev),
 				 sizeof(struct atftmr_timer_regs),
 				 MAP_NOCACHE);
 	return 0;
diff --git a/drivers/timer/altera_timer.c b/drivers/timer/altera_timer.c
index 6ca9501..6cb2923 100644
--- a/drivers/timer/altera_timer.c
+++ b/drivers/timer/altera_timer.c
@@ -69,7 +69,7 @@
 {
 	struct altera_timer_platdata *plat = dev_get_platdata(dev);
 
-	plat->regs = map_physmem(devfdt_get_addr(dev),
+	plat->regs = map_physmem(dev_read_addr(dev),
 				 sizeof(struct altera_timer_regs),
 				 MAP_NOCACHE);
 
diff --git a/drivers/timer/atcpit100_timer.c b/drivers/timer/atcpit100_timer.c
index c5d43b4..5d4ae68 100644
--- a/drivers/timer/atcpit100_timer.c
+++ b/drivers/timer/atcpit100_timer.c
@@ -89,7 +89,7 @@
 static int atcpit_timer_ofdata_to_platdata(struct udevice *dev)
 {
 	struct atcpit_timer_platdata *plat = dev_get_platdata(dev);
-	plat->regs = map_physmem(devfdt_get_addr(dev) , 0x100 , MAP_NOCACHE);
+	plat->regs = map_physmem(dev_read_addr(dev), 0x100 , MAP_NOCACHE);
 	return 0;
 }
 
diff --git a/drivers/timer/omap-timer.c b/drivers/timer/omap-timer.c
index 700c349..cf3d27b 100644
--- a/drivers/timer/omap-timer.c
+++ b/drivers/timer/omap-timer.c
@@ -79,7 +79,7 @@
 {
 	struct omap_timer_priv *priv = dev_get_priv(dev);
 
-	priv->regs = map_physmem(devfdt_get_addr(dev),
+	priv->regs = map_physmem(dev_read_addr(dev),
 				 sizeof(struct omap_gptimer_regs), MAP_NOCACHE);
 
 	return 0;
diff --git a/drivers/usb/dwc3/dwc3-uniphier.c b/drivers/usb/dwc3/dwc3-uniphier.c
index 88317b1..54b52dc 100644
--- a/drivers/usb/dwc3/dwc3-uniphier.c
+++ b/drivers/usb/dwc3/dwc3-uniphier.c
@@ -70,7 +70,7 @@
 	int (*init)(void __iomem *regs);
 	int ret;
 
-	base = devfdt_get_addr(dev);
+	base = dev_read_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index f9083d9..3b208e8 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -95,7 +95,7 @@
 	/*
 	 * Get the base address for EHCI controller from the device node
 	 */
-	hcd_base = devfdt_get_addr(dev);
+	hcd_base = dev_read_addr(dev);
 	if (hcd_base == FDT_ADDR_T_NONE) {
 		debug("Can't get the EHCI register base address\n");
 		return -ENXIO;
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index 0b0b213..6a37c5d 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -53,7 +53,7 @@
 	/*
 	 * Get the base address for XHCI controller from the device node
 	 */
-	plat->hcd_base = devfdt_get_addr(dev);
+	plat->hcd_base = dev_read_addr(dev);
 	if (plat->hcd_base == FDT_ADDR_T_NONE) {
 		debug("Can't get the XHCI register base address\n");
 		return -ENXIO;
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index ac6c5b5..5423d10 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -105,7 +105,7 @@
 	/*
 	 * Get the base address for EHCI controller from the device node
 	 */
-	priv->hcd_base = devfdt_get_addr(dev);
+	priv->hcd_base = dev_read_addr(dev);
 	if (priv->hcd_base == FDT_ADDR_T_NONE) {
 		debug("Can't get the EHCI register base address\n");
 		return -ENXIO;
diff --git a/drivers/usb/host/ehci-marvell.c b/drivers/usb/host/ehci-marvell.c
index 8fe685a..62414bb 100644
--- a/drivers/usb/host/ehci-marvell.c
+++ b/drivers/usb/host/ehci-marvell.c
@@ -109,7 +109,7 @@
 	/*
 	 * Get the base address for EHCI controller from the device node
 	 */
-	priv->hcd_base = devfdt_get_addr(dev);
+	priv->hcd_base = dev_read_addr(dev);
 	if (priv->hcd_base == FDT_ADDR_T_NONE) {
 		debug("Can't get the EHCI register base address\n");
 		return -ENXIO;
diff --git a/drivers/usb/host/ehci-mx5.c b/drivers/usb/host/ehci-mx5.c
index 212b362..caafa68 100644
--- a/drivers/usb/host/ehci-mx5.c
+++ b/drivers/usb/host/ehci-mx5.c
@@ -306,7 +306,7 @@
 static int ehci_usb_probe(struct udevice *dev)
 {
 	struct usb_platdata *plat = dev_get_platdata(dev);
-	struct usb_ehci *ehci = (struct usb_ehci *)devfdt_get_addr(dev);
+	struct usb_ehci *ehci = dev_read_addr_ptr(dev);
 	struct ehci_mx5_priv_data *priv = dev_get_priv(dev);
 	enum usb_init_type type = plat->init_type;
 	struct ehci_hccr *hccr;
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index 5f84c7b..37b5975 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -473,7 +473,7 @@
 static int ehci_usb_phy_mode(struct udevice *dev)
 {
 	struct usb_platdata *plat = dev_get_platdata(dev);
-	void *__iomem addr = (void *__iomem)devfdt_get_addr(dev);
+	void *__iomem addr = dev_read_addr_ptr(dev);
 	void *__iomem phy_ctrl, *__iomem phy_status;
 	const void *blob = gd->fdt_blob;
 	int offset = dev_of_offset(dev), phy_off;
@@ -580,7 +580,7 @@
 static int ehci_usb_probe(struct udevice *dev)
 {
 	struct usb_platdata *plat = dev_get_platdata(dev);
-	struct usb_ehci *ehci = (struct usb_ehci *)devfdt_get_addr(dev);
+	struct usb_ehci *ehci = dev_read_addr_ptr(dev);
 	struct ehci_mx6_priv_data *priv = dev_get_priv(dev);
 	enum usb_init_type type = plat->init_type;
 	struct ehci_hccr *hccr;
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 93ab839..82b99ee 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -382,7 +382,7 @@
 	struct ehci_hccr *hccr;
 	struct ehci_hcor *hcor;
 
-	priv->ehci = (struct omap_ehci *)devfdt_get_addr(dev);
+	priv->ehci = dev_read_addr_ptr(dev);
 	priv->portnr = dev->seq;
 	priv->init_type = plat->init_type;
 
diff --git a/drivers/usb/host/ehci-vf.c b/drivers/usb/host/ehci-vf.c
index 562207d..2768d40 100644
--- a/drivers/usb/host/ehci-vf.c
+++ b/drivers/usb/host/ehci-vf.c
@@ -224,7 +224,7 @@
 
 	priv->portnr = dev->seq;
 
-	priv->ehci = (struct usb_ehci *)devfdt_get_addr(dev);
+	priv->ehci = dev_read_addr_ptr(dev);
 	mode = fdt_getprop(dt_blob, node, "dr_mode", NULL);
 	if (mode) {
 		if (0 == strcmp(mode, "host")) {
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index 6920182..22e7b56 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -89,7 +89,7 @@
 #if CONFIG_IS_ENABLED(DM_USB)
 static int ohci_da8xx_probe(struct udevice *dev)
 {
-	struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
+	struct ohci_regs *regs = dev_read_addr_ptr(dev);
 	struct da8xx_ohci *priv = dev_get_priv(dev);
 	int i, err, ret, clock_nb;
 
diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c
index 631711a..b84bf8a 100644
--- a/drivers/usb/host/ohci-generic.c
+++ b/drivers/usb/host/ohci-generic.c
@@ -79,7 +79,7 @@
 
 static int ohci_usb_probe(struct udevice *dev)
 {
-	struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
+	struct ohci_regs *regs = dev_read_addr_ptr(dev);
 	struct generic_ohci *priv = dev_get_priv(dev);
 	int i, err, ret, clock_nb, reset_nb;
 
diff --git a/drivers/usb/host/xhci-exynos5.c b/drivers/usb/host/xhci-exynos5.c
index 1705acc..6fb7a7f 100644
--- a/drivers/usb/host/xhci-exynos5.c
+++ b/drivers/usb/host/xhci-exynos5.c
@@ -62,7 +62,7 @@
 	/*
 	 * Get the base address for XHCI controller from the device node
 	 */
-	plat->hcd_base = devfdt_get_addr(dev);
+	plat->hcd_base = dev_read_addr(dev);
 	if (plat->hcd_base == FDT_ADDR_T_NONE) {
 		debug("Can't get the XHCI register base address\n");
 		return -ENXIO;
diff --git a/drivers/usb/host/xhci-fsl.c b/drivers/usb/host/xhci-fsl.c
index d8fb2c5..0a2da70 100644
--- a/drivers/usb/host/xhci-fsl.c
+++ b/drivers/usb/host/xhci-fsl.c
@@ -120,7 +120,7 @@
 	/*
 	 * Get the base address for XHCI controller from the device node
 	 */
-	priv->hcd_base = devfdt_get_addr(dev);
+	priv->hcd_base = dev_read_addr(dev);
 	if (priv->hcd_base == FDT_ADDR_T_NONE) {
 		debug("Can't get the XHCI register base address\n");
 		return -ENXIO;
diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c
index 5fb7484..f2e338f 100644
--- a/drivers/usb/host/xhci-mvebu.c
+++ b/drivers/usb/host/xhci-mvebu.c
@@ -72,7 +72,7 @@
 	/*
 	 * Get the base address for XHCI controller from the device node
 	 */
-	plat->hcd_base = devfdt_get_addr(dev);
+	plat->hcd_base = dev_read_addr(dev);
 	if (plat->hcd_base == FDT_ADDR_T_NONE) {
 		debug("Can't get the XHCI register base address\n");
 		return -ENXIO;
diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c
index 4964697..8fc51df 100644
--- a/drivers/usb/host/xhci-rcar.c
+++ b/drivers/usb/host/xhci-rcar.c
@@ -136,7 +136,7 @@
 {
 	struct rcar_xhci_platdata *plat = dev_get_platdata(dev);
 
-	plat->hcd_base = devfdt_get_addr(dev);
+	plat->hcd_base = dev_read_addr(dev);
 	if (plat->hcd_base == FDT_ADDR_T_NONE) {
 		debug("Can't get the XHCI register base address\n");
 		return -ENXIO;
diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c
index 35a56a8..38def28 100644
--- a/drivers/video/atmel_hlcdfb.c
+++ b/drivers/video/atmel_hlcdfb.c
@@ -507,7 +507,7 @@
 	const void *blob = gd->fdt_blob;
 	int node = dev_of_offset(dev);
 
-	priv->regs = (struct atmel_hlcd_regs *)devfdt_get_addr(dev);
+	priv->regs = dev_read_addr_ptr(dev);
 	if (!priv->regs) {
 		debug("%s: No display controller address\n", __func__);
 		return -EINVAL;
diff --git a/drivers/video/exynos/exynos_dp.c b/drivers/video/exynos/exynos_dp.c
index 749bde8..999ee1c 100644
--- a/drivers/video/exynos/exynos_dp.c
+++ b/drivers/video/exynos/exynos_dp.c
@@ -884,7 +884,7 @@
 	unsigned int node = dev_of_offset(dev);
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE) {
 		debug("Can't get the DP base address\n");
 		return -EINVAL;
diff --git a/drivers/video/exynos/exynos_fb.c b/drivers/video/exynos/exynos_fb.c
index d5b13a6..979b909 100644
--- a/drivers/video/exynos/exynos_fb.c
+++ b/drivers/video/exynos/exynos_fb.c
@@ -486,7 +486,7 @@
 	const void *blob = gd->fdt_blob;
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE) {
 		debug("Can't get the FIMD base address\n");
 		return -EINVAL;
diff --git a/drivers/video/tegra.c b/drivers/video/tegra.c
index 1208d91..827ea13 100644
--- a/drivers/video/tegra.c
+++ b/drivers/video/tegra.c
@@ -346,7 +346,7 @@
 	int rgb;
 	int ret;
 
-	priv->disp = (struct disp_ctlr *)devfdt_get_addr(dev);
+	priv->disp = dev_read_addr_ptr(dev);
 	if (!priv->disp) {
 		debug("%s: No display controller address\n", __func__);
 		return -EINVAL;
diff --git a/drivers/w1/mxc_w1.c b/drivers/w1/mxc_w1.c
index 5bf0865..8e6372f 100644
--- a/drivers/w1/mxc_w1.c
+++ b/drivers/w1/mxc_w1.c
@@ -171,7 +171,7 @@
 	struct mxc_w1_pdata *pdata = dev_get_platdata(dev);
 	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index ed8b219..9059a4c 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -237,7 +237,7 @@
 {
 	struct omap3_wdt_priv *priv = dev_get_priv(dev);
 
-	priv->regs = (struct wd_timer *)devfdt_get_addr(dev);
+	priv->regs = dev_read_addr_ptr(dev);
 	if (!priv->regs)
 		return -EINVAL;
 
diff --git a/drivers/watchdog/stm32mp_wdt.c b/drivers/watchdog/stm32mp_wdt.c
index 2d8bfc0..f673fce 100644
--- a/drivers/watchdog/stm32mp_wdt.c
+++ b/drivers/watchdog/stm32mp_wdt.c
@@ -92,7 +92,7 @@
 
 	debug("IWDG init\n");
 
-	priv->base = devfdt_get_addr(dev);
+	priv->base = dev_read_addr(dev);
 	if (priv->base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/env/Kconfig b/env/Kconfig
index 38e7fad..5784136 100644
--- a/env/Kconfig
+++ b/env/Kconfig
@@ -434,6 +434,10 @@
 	                   If none, first valid partition in device D. If no
 	                   partition table then means device D.
 
+	  If ENV_FAT_INTERFACE is set to "mmc" then device 'D' can be omitted,
+	  leaving the string starting with a colon, and the boot device will
+	  be used.
+
 config ENV_FAT_FILE
 	string "Name of the FAT file to use for the environment"
 	depends on ENV_IS_IN_FAT
diff --git a/env/env.c b/env/env.c
index dcc25c0..2e64346 100644
--- a/env/env.c
+++ b/env/env.c
@@ -103,7 +103,7 @@
 	 * using the above enum value as the bit index. We need to
 	 * make sure that we're not overflowing it.
 	 */
-	BUILD_BUG_ON(ARRAY_SIZE(env_locations) > BITS_PER_LONG);
+	BUILD_BUG_ON(ENVL_COUNT > BITS_PER_LONG);
 
 	gd->env_has_init |= BIT(location);
 }
@@ -240,13 +240,17 @@
 	if (drv) {
 		int ret;
 
-		if (!drv->save)
+		printf("Saving Environment to %s... ", drv->name);
+		if (!drv->save) {
+			printf("not possible\n");
 			return -ENODEV;
+		}
 
-		if (!env_has_inited(drv->location))
+		if (!env_has_inited(drv->location)) {
+			printf("not initialized\n");
 			return -ENODEV;
+		}
 
-		printf("Saving Environment to %s... ", drv->name);
 		ret = drv->save();
 		if (ret)
 			printf("Failed (%d)\n", ret);
diff --git a/env/fat.c b/env/fat.c
index 35a1955..63aced9 100644
--- a/env/fat.c
+++ b/env/fat.c
@@ -29,6 +29,34 @@
 # define LOADENV
 #endif
 
+__weak int mmc_get_env_dev(void)
+{
+#ifdef CONFIG_SYS_MMC_ENV_DEV
+	return CONFIG_SYS_MMC_ENV_DEV;
+#else
+	return 0;
+#endif
+}
+
+static char *env_fat_device_and_part(void)
+{
+#ifdef CONFIG_MMC
+	static char *part_str;
+
+	if (!part_str) {
+		part_str = CONFIG_ENV_FAT_DEVICE_AND_PART;
+		if (!strcmp(CONFIG_ENV_FAT_INTERFACE, "mmc") && part_str[0] == ':') {
+			part_str = "0" CONFIG_ENV_FAT_DEVICE_AND_PART;
+			part_str[0] += mmc_get_env_dev();
+		}
+	}
+
+	return part_str;
+#else
+	return CONFIG_ENV_FAT_DEVICE_AND_PART;
+#endif
+}
+
 static int env_fat_save(void)
 {
 	env_t __aligned(ARCH_DMA_MINALIGN) env_new;
@@ -43,7 +71,7 @@
 		return err;
 
 	part = blk_get_device_part_str(CONFIG_ENV_FAT_INTERFACE,
-					CONFIG_ENV_FAT_DEVICE_AND_PART,
+					env_fat_device_and_part(),
 					&dev_desc, &info, 1);
 	if (part < 0)
 		return 1;
@@ -89,7 +117,7 @@
 #endif
 
 	part = blk_get_device_part_str(CONFIG_ENV_FAT_INTERFACE,
-					CONFIG_ENV_FAT_DEVICE_AND_PART,
+					env_fat_device_and_part(),
 					&dev_desc, &info, 1);
 	if (part < 0)
 		goto err_env_relocate;
diff --git a/env/mmc.c b/env/mmc.c
index a8b661d..aca61b7 100644
--- a/env/mmc.c
+++ b/env/mmc.c
@@ -24,14 +24,25 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#if !defined(CONFIG_SYS_MMC_ENV_DEV)
+#define CONFIG_SYS_MMC_ENV_DEV 0
+#endif
+
+__weak int mmc_get_env_dev(void)
+{
+	return CONFIG_SYS_MMC_ENV_DEV;
+}
+
 #if CONFIG_IS_ENABLED(OF_CONTROL)
-static inline int mmc_offset_try_partition(const char *str, s64 *val)
+static inline int mmc_offset_try_partition(const char *str, int copy, s64 *val)
 {
 	struct disk_partition info;
 	struct blk_desc *desc;
 	int len, i, ret;
+	char dev_str[4];
 
-	ret = blk_get_device_by_str("mmc", STR(CONFIG_SYS_MMC_ENV_DEV), &desc);
+	snprintf(dev_str, sizeof(dev_str), "%d", mmc_get_env_dev());
+	ret = blk_get_device_by_str("mmc", dev_str, &desc);
 	if (ret < 0)
 		return (ret);
 
@@ -45,10 +56,10 @@
 	}
 
 	/* round up to info.blksz */
-	len = (CONFIG_ENV_SIZE + info.blksz - 1) & ~(info.blksz - 1);
+	len = DIV_ROUND_UP(CONFIG_ENV_SIZE, info.blksz);
 
 	/* use the top of the partion for the environment */
-	*val = (info.start + info.size - 1) - len / info.blksz;
+	*val = (info.start + info.size - (1 + copy) * len) * info.blksz;
 
 	return 0;
 }
@@ -73,7 +84,7 @@
 	str = fdtdec_get_config_string(gd->fdt_blob, dt_prop.partition);
 	if (str) {
 		/* try to place the environment at end of the partition */
-		err = mmc_offset_try_partition(str, &val);
+		err = mmc_offset_try_partition(str, copy, &val);
 		if (!err)
 			return val;
 	}
@@ -114,11 +125,6 @@
 	return 0;
 }
 
-__weak int mmc_get_env_dev(void)
-{
-	return CONFIG_SYS_MMC_ENV_DEV;
-}
-
 #ifdef CONFIG_SYS_MMC_ENV_PART
 __weak uint mmc_get_env_part(struct mmc *mmc)
 {
diff --git a/include/configs/MPC8349EMDS.h b/include/configs/MPC8349EMDS.h
index 41ef3d8..c2f4441 100644
--- a/include/configs/MPC8349EMDS.h
+++ b/include/configs/MPC8349EMDS.h
@@ -220,7 +220,6 @@
 
 #define CONFIG_83XX_PCI_STREAMING
 
-#undef CONFIG_TULIP
 
 #if !defined(CONFIG_PCI_PNP)
 	#define PCI_ENET0_IOADDR	0xFIXME
diff --git a/include/configs/MPC8349EMDS_SDRAM.h b/include/configs/MPC8349EMDS_SDRAM.h
index 4b43ee1..618e210 100644
--- a/include/configs/MPC8349EMDS_SDRAM.h
+++ b/include/configs/MPC8349EMDS_SDRAM.h
@@ -275,7 +275,6 @@
 
 #define CONFIG_83XX_PCI_STREAMING
 
-#undef CONFIG_TULIP
 
 #if !defined(CONFIG_PCI_PNP)
 	#define PCI_ENET0_IOADDR	0xFIXME
diff --git a/include/configs/MPC8540ADS.h b/include/configs/MPC8540ADS.h
index d2a9261..8b7e0da 100644
--- a/include/configs/MPC8540ADS.h
+++ b/include/configs/MPC8540ADS.h
@@ -234,7 +234,6 @@
 #define CONFIG_SYS_PCI1_IO_SIZE	0x100000	/* 1M */
 
 #if defined(CONFIG_PCI)
-#undef CONFIG_TULIP
 
 #if !defined(CONFIG_PCI_PNP)
     #define PCI_ENET0_IOADDR	0xe0000000
diff --git a/include/configs/MPC8541CDS.h b/include/configs/MPC8541CDS.h
index 834bf7a..d174b27 100644
--- a/include/configs/MPC8541CDS.h
+++ b/include/configs/MPC8541CDS.h
@@ -280,7 +280,6 @@
 
 #define CONFIG_MPC85XX_PCI2
 
-#undef CONFIG_TULIP
 
 #undef CONFIG_PCI_SCAN_SHOW		/* show pci devices on startup */
 #define CONFIG_SYS_PCI_SUBSYS_VENDORID 0x1057  /* Motorola */
diff --git a/include/configs/MPC8544DS.h b/include/configs/MPC8544DS.h
index b9c57e1..e473c0f 100644
--- a/include/configs/MPC8544DS.h
+++ b/include/configs/MPC8544DS.h
@@ -256,7 +256,6 @@
 #define CONFIG_SYS_ISA_IO_BASE_ADDRESS VIDEO_IO_OFFSET
 #endif
 
-#undef CONFIG_TULIP
 
 #ifndef CONFIG_PCI_PNP
 	#define PCI_ENET0_IOADDR	CONFIG_SYS_PCI1_IO_BUS
diff --git a/include/configs/MPC8548CDS.h b/include/configs/MPC8548CDS.h
index 4b40129..f760518 100644
--- a/include/configs/MPC8548CDS.h
+++ b/include/configs/MPC8548CDS.h
@@ -374,7 +374,6 @@
 #endif
 
 #if defined(CONFIG_PCI)
-#undef CONFIG_TULIP
 
 #if !defined(CONFIG_DM_PCI)
 #define CONFIG_FSL_PCI_INIT		1	/* Use common FSL init code */
diff --git a/include/configs/MPC8555CDS.h b/include/configs/MPC8555CDS.h
index c25b04e..dcb09b0 100644
--- a/include/configs/MPC8555CDS.h
+++ b/include/configs/MPC8555CDS.h
@@ -278,7 +278,6 @@
 
 #define CONFIG_MPC85XX_PCI2
 
-#undef CONFIG_TULIP
 
 #define CONFIG_PCI_SCAN_SHOW		/* show pci devices on startup */
 #define CONFIG_SYS_PCI_SUBSYS_VENDORID 0x1057  /* Motorola */
diff --git a/include/configs/MPC8560ADS.h b/include/configs/MPC8560ADS.h
index 4d1a417..a9f3029 100644
--- a/include/configs/MPC8560ADS.h
+++ b/include/configs/MPC8560ADS.h
@@ -231,7 +231,6 @@
 #define CONFIG_SYS_PCI1_IO_SIZE	0x100000	/* 1M */
 
 #if defined(CONFIG_PCI)
-#undef CONFIG_TULIP
 
 #if !defined(CONFIG_PCI_PNP)
     #define PCI_ENET0_IOADDR	0xe0000000
diff --git a/include/configs/MPC8568MDS.h b/include/configs/MPC8568MDS.h
index 1466364..c49f786 100644
--- a/include/configs/MPC8568MDS.h
+++ b/include/configs/MPC8568MDS.h
@@ -288,7 +288,6 @@
 #endif /* CONFIG_QE */
 
 #if defined(CONFIG_PCI)
-#undef CONFIG_TULIP
 
 #undef CONFIG_PCI_SCAN_SHOW		/* show pci devices on startup */
 #define CONFIG_SYS_PCI_SUBSYS_VENDORID 0x1057  /* Motorola */
diff --git a/include/configs/MPC8569MDS.h b/include/configs/MPC8569MDS.h
index dd291ac..acb8dec 100644
--- a/include/configs/MPC8569MDS.h
+++ b/include/configs/MPC8569MDS.h
@@ -394,7 +394,6 @@
 #endif /* CONFIG_QE */
 
 #if defined(CONFIG_PCI)
-#undef CONFIG_TULIP
 
 #undef CONFIG_PCI_SCAN_SHOW		/* show pci devices on startup */
 
diff --git a/include/configs/MPC8572DS.h b/include/configs/MPC8572DS.h
index 429dae1..57aebfd 100644
--- a/include/configs/MPC8572DS.h
+++ b/include/configs/MPC8572DS.h
@@ -436,7 +436,6 @@
 #define CONFIG_SYS_ISA_IO_BASE_ADDRESS VIDEO_IO_OFFSET
 #endif
 
-#undef CONFIG_TULIP
 
 #ifndef CONFIG_PCI_PNP
 	#define PCI_ENET0_IOADDR	CONFIG_SYS_PCIE3_IO_BUS
diff --git a/include/configs/MPC8641HPCN.h b/include/configs/MPC8641HPCN.h
index 1560b61..42fdcdd 100644
--- a/include/configs/MPC8641HPCN.h
+++ b/include/configs/MPC8641HPCN.h
@@ -330,7 +330,6 @@
 
 #define CONFIG_PCI_SCAN_SHOW		/* show pci devices on startup */
 
-#undef CONFIG_TULIP
 
 /************************************************************
  * USB support
diff --git a/include/configs/TQM834x.h b/include/configs/TQM834x.h
index d43d217..aa70f01 100644
--- a/include/configs/TQM834x.h
+++ b/include/configs/TQM834x.h
@@ -167,7 +167,6 @@
 #define CONFIG_SYS_PCI1_IO_PHYS		CONFIG_SYS_PCI1_IO_BASE
 #define CONFIG_SYS_PCI1_IO_SIZE		0x1000000	/* 16M */
 
-#undef CONFIG_TULIP
 
 #if !defined(CONFIG_PCI_PNP)
 	#define PCI_ENET0_IOADDR	CONFIG_SYS_PCI1_IO_BASE
diff --git a/include/configs/beacon-rzg2m.h b/include/configs/beacon-rzg2m.h
new file mode 100644
index 0000000..0e48fbd
--- /dev/null
+++ b/include/configs/beacon-rzg2m.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Compass Electronics Group, LLC
+ */
+
+#ifndef __BEACON_RZG2M_H
+#define __BEACON_RZG2M_H
+
+#include "rcar-gen3-common.h"
+
+/* Ethernet RAVB */
+#define CONFIG_BITBANGMII_MULTI
+
+/* Environment in eMMC, at the end of 2nd "boot sector" */
+/* #define CONFIG_ENV_OFFSET		(-CONFIG_ENV_SIZE) */
+#define CONFIG_SYS_MMC_ENV_DEV		1
+#define CONFIG_SYS_MMC_ENV_PART		2
+
+#undef CONFIG_EXTRA_ENV_SETTINGS
+
+#define CONFIG_EXTRA_ENV_SETTINGS		\
+	"usb_pgood_delay=2000\0"	\
+	"script=boot.scr\0" \
+	"image=Image\0" \
+	"console=ttySC0,115200\0" \
+	"fdt_addr=0x48000000\0" \
+	"loadaddr=0x48080000\0" \
+	"boot_fdt=try\0" \
+	"fdt_file=" CONFIG_DEFAULT_FDT_FILE "\0" \
+	"initrd_addr=0x43800000\0"		\
+	"mmcdev=0\0" \
+	"mmcpart=1\0" \
+	"mmcrootpart=2\0" \
+	"finduuid=part uuid mmc ${mmcdev}:${mmcrootpart} uuid\0" \
+	"mmcautodetect=yes\0" \
+	"mmcargs=setenv bootargs console=${console} " \
+	" root=PARTUUID=${uuid} rootwait rw ${optargs}\0" \
+	"loadbootscript=load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \
+	"bootscript=echo Running bootscript from mmc ...; " \
+		"source\0" \
+	"loadimage=load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}\0" \
+	"loadfdt=load mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}\0" \
+	"mmcboot=echo Booting from mmc ...; " \
+		"run finduuid; run mmcargs; " \
+		"if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
+			"if run loadfdt; then " \
+				"booti ${loadaddr} - ${fdt_addr}; " \
+			"else " \
+				"echo WARN: Cannot load the DT; " \
+			"fi; " \
+		"else " \
+			"echo wait for boot; " \
+		"fi;\0" \
+	"netargs=setenv bootargs ${jh_clk} console=${console} " \
+		"root=/dev/nfs " \
+		"ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0" \
+	"netboot=echo Booting from net ...; " \
+		"run netargs;  " \
+		"if test ${ip_dyn} = yes; then " \
+			"setenv get_cmd dhcp; " \
+		"else " \
+			"setenv get_cmd tftp; " \
+		"fi; " \
+		"${get_cmd} ${loadaddr} ${image}; " \
+		"if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
+			"if ${get_cmd} ${fdt_addr} ${fdt_file}; then " \
+				"booti ${loadaddr} - ${fdt_addr}; " \
+			"else " \
+				"echo WARN: Cannot load the DT; " \
+			"fi; " \
+		"else " \
+			"booti; " \
+		"fi;\0"
+
+#undef CONFIG_BOOTCOMMAND
+
+#define CONFIG_BOOTCOMMAND \
+	"mmc dev ${mmcdev}; if mmc rescan; then " \
+	   "if run loadbootscript; then " \
+		   "run bootscript; " \
+	   "else " \
+		   "if run loadimage; then " \
+			   "run mmcboot; " \
+		   "else run netboot; " \
+		   "fi; " \
+	   "fi; " \
+	"else booti ${loadaddr} - ${fdt_addr}; fi"
+
+#endif /* __BEACON_RZG2M_H */
diff --git a/include/configs/caddy2.h b/include/configs/caddy2.h
index a7c6677..e51398d 100644
--- a/include/configs/caddy2.h
+++ b/include/configs/caddy2.h
@@ -155,7 +155,6 @@
 
 #if defined(CONFIG_PCI)
 
-#undef CONFIG_TULIP
 
 #if !defined(CONFIG_PCI_PNP)
 	#define PCI_ENET0_IOADDR	0xFIXME
diff --git a/include/configs/integratorap.h b/include/configs/integratorap.h
index 96c1d53..2f8ac20 100644
--- a/include/configs/integratorap.h
+++ b/include/configs/integratorap.h
@@ -34,7 +34,6 @@
  * PCI definitions
  */
 
-#define CONFIG_TULIP
 #define CONFIG_SYS_RX_ETH_BUFFER	8	/* use 8 rx buffer on eepro100	*/
 
 /*-----------------------------------------------------------------------
diff --git a/include/configs/sbc8349.h b/include/configs/sbc8349.h
index cca596d..0561ec2 100644
--- a/include/configs/sbc8349.h
+++ b/include/configs/sbc8349.h
@@ -180,7 +180,6 @@
 
 #if defined(CONFIG_PCI)
 
-#undef CONFIG_TULIP
 
 #if !defined(CONFIG_PCI_PNP)
 	#define PCI_ENET0_IOADDR	0xFIXME
diff --git a/include/configs/sbc8548.h b/include/configs/sbc8548.h
index f946833..6ac5d7b 100644
--- a/include/configs/sbc8548.h
+++ b/include/configs/sbc8548.h
@@ -432,7 +432,6 @@
 #endif
 
 #if defined(CONFIG_PCI)
-#undef CONFIG_TULIP
 
 #define CONFIG_PCI_SCAN_SHOW		/* show pci devices on startup */
 
diff --git a/include/configs/sbc8641d.h b/include/configs/sbc8641d.h
index 5b93ccb..27a15ed 100644
--- a/include/configs/sbc8641d.h
+++ b/include/configs/sbc8641d.h
@@ -274,7 +274,6 @@
 
 #define CONFIG_PCI_SCAN_SHOW            /* show pci devices on startup */
 
-#undef CONFIG_TULIP
 
 #if !defined(CONFIG_PCI_PNP)
     #define PCI_ENET0_IOADDR	0xe0000000
diff --git a/include/configs/vme8349.h b/include/configs/vme8349.h
index 52d632b..bd94352 100644
--- a/include/configs/vme8349.h
+++ b/include/configs/vme8349.h
@@ -155,7 +155,6 @@
 
 #if defined(CONFIG_PCI)
 
-#undef CONFIG_TULIP
 
 #if !defined(CONFIG_PCI_PNP)
 	#define PCI_ENET0_IOADDR	0xFIXME
diff --git a/include/cpu.h b/include/cpu.h
index 2f283fe..78e88b9 100644
--- a/include/cpu.h
+++ b/include/cpu.h
@@ -61,7 +61,7 @@
 	 * @size:	Size of string space
 	 * @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
 	 */
-	int (*get_desc)(struct udevice *dev, char *buf, int size);
+	int (*get_desc)(const struct udevice *dev, char *buf, int size);
 
 	/**
 	 * get_info() - Get information about a CPU
@@ -70,7 +70,7 @@
 	 * @info:	Returns CPU info
 	 * @return 0 if OK, -ve on error
 	 */
-	int (*get_info)(struct udevice *dev, struct cpu_info *info);
+	int (*get_info)(const struct udevice *dev, struct cpu_info *info);
 
 	/**
 	 * get_count() - Get number of CPUs
@@ -78,7 +78,7 @@
 	 * @dev:	Device to check (UCLASS_CPU)
 	 * @return CPU count if OK, -ve on error
 	 */
-	int (*get_count)(struct udevice *dev);
+	int (*get_count)(const struct udevice *dev);
 
 	/**
 	 * get_vendor() - Get vendor name of a CPU
@@ -88,7 +88,7 @@
 	 * @size:	Size of string space
 	 * @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
 	 */
-	int (*get_vendor)(struct udevice *dev, char *buf, int size);
+	int (*get_vendor)(const struct udevice *dev, char *buf, int size);
 
 	/**
 	 * is_current() - Check if the CPU that U-Boot is currently running from
@@ -110,7 +110,7 @@
  *
  * Return: 0 if OK, -ENOSPC if buffer is too small, other -ve on error
  */
-int cpu_get_desc(struct udevice *dev, char *buf, int size);
+int cpu_get_desc(const struct udevice *dev, char *buf, int size);
 
 /**
  * cpu_get_info() - Get information about a CPU
@@ -119,7 +119,7 @@
  *
  * Return: 0 if OK, -ve on error
  */
-int cpu_get_info(struct udevice *dev, struct cpu_info *info);
+int cpu_get_info(const struct udevice *dev, struct cpu_info *info);
 
 /**
  * cpu_get_count() - Get number of CPUs
@@ -127,7 +127,7 @@
  *
  * Return: CPU count if OK, -ve on error
  */
-int cpu_get_count(struct udevice *dev);
+int cpu_get_count(const struct udevice *dev);
 
 /**
  * cpu_get_vendor() - Get vendor name of a CPU
@@ -137,7 +137,7 @@
  *
  * Return: 0 if OK, -ENOSPC if buffer is too small, other -ve on error
  */
-int cpu_get_vendor(struct udevice *dev, char *buf, int size);
+int cpu_get_vendor(const struct udevice *dev, char *buf, int size);
 
 /**
  * cpu_probe_all() - Probe all available CPUs
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 7837d45..690a8ed 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -97,6 +97,7 @@
 	UCLASS_SERIAL,		/* Serial UART */
 	UCLASS_SIMPLE_BUS,	/* Bus with child devices */
 	UCLASS_SMEM,		/* Shared memory interface */
+	UCLASS_SOC,		/* SOC Device */
 	UCLASS_SOUND,		/* Playing simple sounds */
 	UCLASS_SPI,		/* SPI bus */
 	UCLASS_SPI_FLASH,	/* SPI flash */
diff --git a/include/dt-bindings/clock/r8a774a1-cpg-mssr.h b/include/dt-bindings/clock/r8a774a1-cpg-mssr.h
new file mode 100644
index 0000000..ac3fde1
--- /dev/null
+++ b/include/dt-bindings/clock/r8a774a1-cpg-mssr.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 Renesas Electronics Corp.
+ */
+#ifndef __DT_BINDINGS_CLOCK_R8A774A1_CPG_MSSR_H__
+#define __DT_BINDINGS_CLOCK_R8A774A1_CPG_MSSR_H__
+
+#include <dt-bindings/clock/renesas-cpg-mssr.h>
+
+/* r8a774a1 CPG Core Clocks */
+#define R8A774A1_CLK_Z			0
+#define R8A774A1_CLK_Z2			1
+#define R8A774A1_CLK_ZR			2
+#define R8A774A1_CLK_ZG			3
+#define R8A774A1_CLK_ZTR		4
+#define R8A774A1_CLK_ZTRD2		5
+#define R8A774A1_CLK_ZT			6
+#define R8A774A1_CLK_ZX			7
+#define R8A774A1_CLK_S0D1		8
+#define R8A774A1_CLK_S0D2		9
+#define R8A774A1_CLK_S0D3		10
+#define R8A774A1_CLK_S0D4		11
+#define R8A774A1_CLK_S0D6		12
+#define R8A774A1_CLK_S0D8		13
+#define R8A774A1_CLK_S0D12		14
+#define R8A774A1_CLK_S1D1		15
+#define R8A774A1_CLK_S1D2		16
+#define R8A774A1_CLK_S1D4		17
+#define R8A774A1_CLK_S2D1		18
+#define R8A774A1_CLK_S2D2		19
+#define R8A774A1_CLK_S2D4		20
+#define R8A774A1_CLK_S3D1		21
+#define R8A774A1_CLK_S3D2		22
+#define R8A774A1_CLK_S3D4		23
+#define R8A774A1_CLK_LB			24
+#define R8A774A1_CLK_CL			25
+#define R8A774A1_CLK_ZB3		26
+#define R8A774A1_CLK_ZB3D2		27
+#define R8A774A1_CLK_ZB3D4		28
+#define R8A774A1_CLK_CR			29
+#define R8A774A1_CLK_CRD2		30
+#define R8A774A1_CLK_SD0H		31
+#define R8A774A1_CLK_SD0		32
+#define R8A774A1_CLK_SD1H		33
+#define R8A774A1_CLK_SD1		34
+#define R8A774A1_CLK_SD2H		35
+#define R8A774A1_CLK_SD2		36
+#define R8A774A1_CLK_SD3H		37
+#define R8A774A1_CLK_SD3		38
+#define R8A774A1_CLK_SSP2		39
+#define R8A774A1_CLK_SSP1		40
+#define R8A774A1_CLK_SSPRS		41
+#define R8A774A1_CLK_RPC		42
+#define R8A774A1_CLK_RPCD2		43
+#define R8A774A1_CLK_MSO		44
+#define R8A774A1_CLK_CANFD		45
+#define R8A774A1_CLK_HDMI		46
+#define R8A774A1_CLK_CSI0		47
+#define R8A774A1_CLK_CSIREF		48
+#define R8A774A1_CLK_CP			49
+#define R8A774A1_CLK_CPEX		50
+#define R8A774A1_CLK_R			51
+#define R8A774A1_CLK_OSC		52
+
+#endif /* __DT_BINDINGS_CLOCK_R8A774A1_CPG_MSSR_H__ */
diff --git a/include/dt-bindings/power/r8a774a1-sysc.h b/include/dt-bindings/power/r8a774a1-sysc.h
new file mode 100644
index 0000000..d84ea0e
--- /dev/null
+++ b/include/dt-bindings/power/r8a774a1-sysc.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 Renesas Electronics Corp.
+ */
+#ifndef __DT_BINDINGS_POWER_R8A774A1_SYSC_H__
+#define __DT_BINDINGS_POWER_R8A774A1_SYSC_H__
+
+/*
+ * These power domain indices match the numbers of the interrupt bits
+ * representing the power areas in the various Interrupt Registers
+ * (e.g. SYSCISR, Interrupt Status Register)
+ */
+
+#define R8A774A1_PD_CA57_CPU0		 0
+#define R8A774A1_PD_CA57_CPU1		 1
+#define R8A774A1_PD_CA53_CPU0		 5
+#define R8A774A1_PD_CA53_CPU1		 6
+#define R8A774A1_PD_CA53_CPU2		 7
+#define R8A774A1_PD_CA53_CPU3		 8
+#define R8A774A1_PD_CA57_SCU		12
+#define R8A774A1_PD_CR7			13
+#define R8A774A1_PD_A3VC		14
+#define R8A774A1_PD_3DG_A		17
+#define R8A774A1_PD_3DG_B		18
+#define R8A774A1_PD_CA53_SCU		21
+#define R8A774A1_PD_A3IR		24
+#define R8A774A1_PD_A2VC0		25
+#define R8A774A1_PD_A2VC1		26
+
+/* Always-on power area */
+#define R8A774A1_PD_ALWAYS_ON		32
+
+#endif /* __DT_BINDINGS_POWER_R8A774A1_SYSC_H__ */
diff --git a/include/env_internal.h b/include/env_internal.h
index e89fbdb..6655043 100644
--- a/include/env_internal.h
+++ b/include/env_internal.h
@@ -211,6 +211,17 @@
 
 extern struct hsearch_data env_htab;
 
+/**
+ * env_get_location()- Provide the best location for the U-Boot environment
+ *
+ * It is a weak function allowing board to overidde the environment location
+ *
+ * @op: operations performed on the environment
+ * @prio: priority between the multiple environments, 0 being the
+ *        highest priority
+ * @return  an enum env_location value on success, or -ve error code.
+ */
+enum env_location env_get_location(enum env_operation op, int prio);
 #endif /* DO_DEPS_ONLY */
 
 #endif /* _ENV_INTERNAL_H_ */
diff --git a/include/fdtdec.h b/include/fdtdec.h
index abd6d42..760b392 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -909,26 +909,6 @@
 				 struct display_timing *config);
 
 /**
- * fdtdec_setup_mem_size_base_fdt() - decode and setup gd->ram_size and
- * gd->ram_start
- *
- * Decode the /memory 'reg' property to determine the size and start of the
- * first memory bank, populate the global data with the size and start of the
- * first bank of memory.
- *
- * This function should be called from a boards dram_init(). This helper
- * function allows for boards to query the device tree for DRAM size and start
- * address instead of hard coding the value in the case where the memory size
- * and start address cannot be detected automatically.
- *
- * @param blob		FDT blob
- *
- * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or
- * invalid
- */
-int fdtdec_setup_mem_size_base_fdt(const void *blob);
-
-/**
  * fdtdec_setup_mem_size_base() - decode and setup gd->ram_size and
  * gd->ram_start
  *
@@ -947,25 +927,6 @@
 int fdtdec_setup_mem_size_base(void);
 
 /**
- * fdtdec_setup_memory_banksize_fdt() - decode and populate gd->bd->bi_dram
- *
- * Decode the /memory 'reg' property to determine the address and size of the
- * memory banks. Use this data to populate the global data board info with the
- * phys address and size of memory banks.
- *
- * This function should be called from a boards dram_init_banksize(). This
- * helper function allows for boards to query the device tree for memory bank
- * information instead of hard coding the information in cases where it cannot
- * be detected automatically.
- *
- * @param blob		FDT blob
- *
- * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or
- * invalid
- */
-int fdtdec_setup_memory_banksize_fdt(const void *blob);
-
-/**
  * fdtdec_setup_memory_banksize() - decode and populate gd->bd->bi_dram
  *
  * Decode the /memory 'reg' property to determine the address and size of the
diff --git a/include/soc.h b/include/soc.h
new file mode 100644
index 0000000..a55eb1b
--- /dev/null
+++ b/include/soc.h
@@ -0,0 +1,145 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2020 - Texas Instruments Incorporated - http://www.ti.com/
+ *	Dave Gerlach <d-gerlach@ti.com>
+ */
+
+#ifndef __SOC_H
+#define __SOC_H
+
+#define SOC_MAX_STR_SIZE	128
+
+/**
+ * struct soc_attr - Contains SoC identify information to be used in
+ *		     SoC matching. An array of these structs
+ *		     representing different SoCs can be passed to
+ *		     soc_device_match and the struct matching the SoC
+ *		     in use will be returned.
+ *
+ * @family   - Name of SoC family that can include multiple related SoC
+ *	       variants. Example: am33
+ * @machine  - Name of a specific SoC. Example: am3352
+ * @revision - Name of a specific SoC revision. Example: SR1.1
+ * @data     - A pointer to user data for the SoC variant
+ */
+struct soc_attr {
+	const char *family;
+	const char *machine;
+	const char *revision;
+	const void *data;
+};
+
+struct soc_ops {
+	/**
+	 * get_machine() - Get machine name of an SOC
+	 *
+	 * @dev:	Device to check (UCLASS_SOC)
+	 * @buf:	Buffer to place string
+	 * @size:	Size of string space
+	 * @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
+	 */
+	int (*get_machine)(struct udevice *dev, char *buf, int size);
+
+	/**
+	 * get_revision() - Get revision name of a SOC
+	 *
+	 * @dev:	Device to check (UCLASS_SOC)
+	 * @buf:	Buffer to place string
+	 * @size:	Size of string space
+	 * @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
+	 */
+	int (*get_revision)(struct udevice *dev, char *buf, int size);
+
+	/**
+	 * get_family() - Get family name of an SOC
+	 *
+	 * @dev:	Device to check (UCLASS_SOC)
+	 * @buf:	Buffer to place string
+	 * @size:	Size of string space
+	 * @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
+	 */
+	int (*get_family)(struct udevice *dev, char *buf, int size);
+};
+
+#define soc_get_ops(dev)        ((struct soc_ops *)(dev)->driver->ops)
+
+#ifdef CONFIG_SOC_DEVICE
+/**
+ * soc_get() - Return the soc device for the soc in use.
+ * @devp: Pointer to structure to receive the soc device.
+ *
+ * Since there can only be at most one SOC instance, the API can supply a
+ * function that returns the unique device.
+ *
+ * Return: 0 if OK, -ve on error.
+ */
+int soc_get(struct udevice **devp);
+
+/**
+ * soc_get_machine() - Get machine name of an SOC
+ * @dev:	Device to check (UCLASS_SOC)
+ * @buf:	Buffer to place string
+ * @size:	Size of string space
+ *
+ * Return: 0 if OK, -ENOSPC if buffer is too small, other -ve on error
+ */
+int soc_get_machine(struct udevice *dev, char *buf, int size);
+
+/**
+ * soc_get_revision() - Get revision name of an SOC
+ * @dev:	Device to check (UCLASS_SOC)
+ * @buf:	Buffer to place string
+ * @size:	Size of string space
+ *
+ * Return: 0 if OK, -ENOSPC if buffer is too small, other -ve on error
+ */
+int soc_get_revision(struct udevice *dev, char *buf, int size);
+
+/**
+ * soc_get_family() - Get family name of an SOC
+ * @dev:	Device to check (UCLASS_SOC)
+ * @buf:	Buffer to place string
+ * @size:	Size of string space
+ *
+ * Return: 0 if OK, -ENOSPC if buffer is too small, other -ve on error
+ */
+int soc_get_family(struct udevice *dev, char *buf, int size);
+
+/**
+ * soc_device_match() - Return match from an array of soc_attr
+ * @matches:	Array with any combination of family, revision or machine set
+ *
+ * Return: Pointer to struct from matches array with set attributes matching
+ *	   those provided by the soc device, or NULL if no match found.
+ */
+const struct soc_attr *
+soc_device_match(const struct soc_attr *matches);
+
+#else
+static inline int soc_get(struct udevice **devp)
+{
+	return -ENOSYS;
+}
+
+static inline int soc_get_machine(struct udevice *dev, char *buf, int size)
+{
+	return -ENOSYS;
+}
+
+static inline int soc_get_revision(struct udevice *dev, char *buf, int size)
+{
+	return -ENOSYS;
+}
+
+static inline int soc_get_family(struct udevice *dev, char *buf, int size)
+{
+	return -ENOSYS;
+}
+
+static inline const struct soc_attr *
+soc_device_match(const struct soc_attr *matches)
+{
+	return NULL;
+}
+#endif
+#endif /* _SOC_H */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 934944d..78576b5 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1030,18 +1030,18 @@
 	return ret;
 }
 
-int fdtdec_setup_mem_size_base_fdt(const void *blob)
+int fdtdec_setup_mem_size_base(void)
 {
 	int ret, mem;
 	struct fdt_resource res;
 
-	mem = fdt_path_offset(blob, "/memory");
+	mem = fdt_path_offset(gd->fdt_blob, "/memory");
 	if (mem < 0) {
 		debug("%s: Missing /memory node\n", __func__);
 		return -EINVAL;
 	}
 
-	ret = fdt_get_resource(blob, mem, "reg", 0, &res);
+	ret = fdt_get_resource(gd->fdt_blob, mem, "reg", 0, &res);
 	if (ret != 0) {
 		debug("%s: Unable to decode first memory bank\n", __func__);
 		return -EINVAL;
@@ -1055,43 +1055,38 @@
 	return 0;
 }
 
-int fdtdec_setup_mem_size_base(void)
-{
-	return fdtdec_setup_mem_size_base_fdt(gd->fdt_blob);
-}
-
 #if defined(CONFIG_NR_DRAM_BANKS)
 
 static int get_next_memory_node(const void *blob, int mem)
 {
 	do {
-		mem = fdt_node_offset_by_prop_value(blob, mem,
+		mem = fdt_node_offset_by_prop_value(gd->fdt_blob, mem,
 						    "device_type", "memory", 7);
 	} while (!fdtdec_get_is_enabled(blob, mem));
 
 	return mem;
 }
 
-int fdtdec_setup_memory_banksize_fdt(const void *blob)
+int fdtdec_setup_memory_banksize(void)
 {
 	int bank, ret, mem, reg = 0;
 	struct fdt_resource res;
 
-	mem = get_next_memory_node(blob, -1);
+	mem = get_next_memory_node(gd->fdt_blob, -1);
 	if (mem < 0) {
 		debug("%s: Missing /memory node\n", __func__);
 		return -EINVAL;
 	}
 
 	for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
-		ret = fdt_get_resource(blob, mem, "reg", reg++, &res);
+		ret = fdt_get_resource(gd->fdt_blob, mem, "reg", reg++, &res);
 		if (ret == -FDT_ERR_NOTFOUND) {
 			reg = 0;
-			mem = get_next_memory_node(blob, mem);
+			mem = get_next_memory_node(gd->fdt_blob, mem);
 			if (mem == -FDT_ERR_NOTFOUND)
 				break;
 
-			ret = fdt_get_resource(blob, mem, "reg", reg++, &res);
+			ret = fdt_get_resource(gd->fdt_blob, mem, "reg", reg++, &res);
 			if (ret == -FDT_ERR_NOTFOUND)
 				break;
 		}
@@ -1111,12 +1106,6 @@
 
 	return 0;
 }
-
-int fdtdec_setup_memory_banksize(void)
-{
-	return fdtdec_setup_memory_banksize_fdt(gd->fdt_blob);
-
-}
 #endif
 
 #if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index d822abb..eee0e3a 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -4021,7 +4021,6 @@
 CONFIG_TSECV2_1
 CONFIG_TSEC_TBI
 CONFIG_TSEC_TBICR_SETTINGS
-CONFIG_TULIP
 CONFIG_TWL6030_INPUT
 CONFIG_TWL6030_POWER
 CONFIG_TWR
diff --git a/scripts/dtc/pylibfdt/Makefile b/scripts/dtc/pylibfdt/Makefile
index 42342c7..80b6ad2 100644
--- a/scripts/dtc/pylibfdt/Makefile
+++ b/scripts/dtc/pylibfdt/Makefile
@@ -24,6 +24,9 @@
 		$(PYTHON3) $< --quiet build_ext --inplace
 
 $(obj)/_libfdt.so: $(src)/setup.py $(PYLIBFDT_srcs) FORCE
+	@# Remove the library since otherwise Python doesn't seem to regenerate
+	@# the libfdt.py file if it is missing.
+	rm -f $(obj)/_libfdt*.so
 	$(call if_changed,pymod)
 
 always += _libfdt.so
diff --git a/test/dm/Makefile b/test/dm/Makefile
index b03c96d..8391117 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -68,6 +68,7 @@
 obj-$(CONFIG_MISC) += misc.o
 obj-$(CONFIG_DM_SERIAL) += serial.o
 obj-$(CONFIG_CPU) += cpu.o
+obj-$(CONFIG_SOC_DEVICE) += soc.o
 obj-$(CONFIG_SOUND) += sound.o
 obj-$(CONFIG_TEE) += tee.o
 obj-$(CONFIG_VIRTIO_SANDBOX) += virtio.o
diff --git a/test/dm/acpi.c b/test/dm/acpi.c
index b94c4ba..bb8550f 100644
--- a/test/dm/acpi.c
+++ b/test/dm/acpi.c
@@ -190,7 +190,10 @@
 static int dm_test_acpi_create_dmar(struct unit_test_state *uts)
 {
 	struct acpi_dmar dmar;
+	struct udevice *cpu;
 
+	ut_assertok(uclass_first_device(UCLASS_CPU, &cpu));
+	ut_assertnonnull(cpu);
 	ut_assertok(acpi_create_dmar(&dmar, DMAR_INTR_REMAP));
 	ut_asserteq(DMAR_INTR_REMAP, dmar.flags);
 	ut_asserteq(32 - 1, dmar.host_address_width);
diff --git a/test/dm/core.c b/test/dm/core.c
index 6a930ae..d20c484 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -158,7 +158,7 @@
 	for (uclass_find_first_device(UCLASS_TEST, &dev);
 	     dev;
 	     uclass_find_next_device(&dev)) {
-		ut_assert(dev);
+		ut_assertnonnull(dev);
 
 		uc_pdata = dev_get_uclass_platdata(dev);
 		ut_assert(uc_pdata);
@@ -181,7 +181,7 @@
 	for (uclass_find_first_device(UCLASS_TEST, &dev);
 	     dev;
 	     uclass_find_next_device(&dev)) {
-		ut_assert(dev);
+		ut_assertnonnull(dev);
 
 		uc_pdata = dev_get_uclass_platdata(dev);
 		ut_assert(uc_pdata);
@@ -747,11 +747,11 @@
 	     dev;
 	     ret = uclass_find_next_device(&dev)) {
 		ut_assert(!ret);
-		ut_assert(dev);
+		ut_assertnonnull(dev);
 	}
 
 	ut_assertok(uclass_find_first_device(UCLASS_TEST_DUMMY, &dev));
-	ut_assert(!dev);
+	ut_assertnull(dev);
 
 	return 0;
 }
@@ -778,7 +778,7 @@
 	     testdev;
 	     ret = uclass_find_next_device(&testdev)) {
 		ut_assertok(ret);
-		ut_assert(testdev);
+		ut_assertnonnull(testdev);
 
 		findret = uclass_find_device_by_name(UCLASS_TEST_FDT,
 						     testdev->name,
diff --git a/test/dm/devres.c b/test/dm/devres.c
index b5de0cb..5507874 100644
--- a/test/dm/devres.c
+++ b/test/dm/devres.c
@@ -153,6 +153,7 @@
 	 * allocation created in the bind() method.
 	 */
 	ut_assertok(uclass_find_first_device(UCLASS_TEST_DEVRES, &dev));
+	ut_assertnonnull(dev);
 	devres_get_stats(dev, &stats);
 	ut_asserteq(1, stats.allocs);
 	ut_asserteq(TEST_DEVRES_SIZE, stats.total_size);
diff --git a/test/dm/soc.c b/test/dm/soc.c
new file mode 100644
index 0000000..3ad0f56
--- /dev/null
+++ b/test/dm/soc.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for the SOC uclass
+ *
+ * (C) Copyright 2020 - Texas Instruments Incorporated - http://www.ti.com/
+ *	Dave Gerlach <d-gerlach@ti.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <dm/uclass-internal.h>
+#include <soc.h>
+#include <test/ut.h>
+
+struct sb_soc_data {
+	unsigned long param;
+};
+
+static int dm_test_soc(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	char text[128];
+	const struct soc_attr *soc_data;
+	const struct sb_soc_data *match_data;
+
+	static const struct sb_soc_data soc_sandbox1_sr10_data = { 0x91919191 };
+	static const struct sb_soc_data soc_sandbox123_data    = { 0x84848484 };
+
+	static const struct soc_attr sb_soc_devices_full[] = {
+		{
+			.family = "SANDBOX0xx",
+			.machine = "SANDBOX012",
+			.revision = "1.0",
+			.data = NULL,
+		},
+		{
+			.family = "SANDBOX1xx",
+			.machine = "SANDBOX107",
+			.revision = "1.0",
+			.data = NULL,
+		},
+		{
+			.family = "SANDBOX1xx",
+			.machine = "SANDBOX123",
+			.revision = "1.0",
+			.data = &soc_sandbox123_data,
+		},
+		{
+			.family = "SANDBOX1xx",
+			.machine = "SANDBOX131",
+			.revision = "2.0",
+			.data = NULL,
+		},
+		{ /* sentinel */ }
+	};
+
+	static const struct soc_attr sb_soc_devices_partial[] = {
+		{
+			.family = "SANDBOX0xx",
+			.revision = "1.0",
+			.data = NULL,
+		},
+		{
+			.family = "SANDBOX1xx",
+			.revision = "1.0",
+			.data = &soc_sandbox1_sr10_data,
+		},
+		{
+			.family = "SANDBOX1xx",
+			.revision = "2.0",
+			.data = NULL,
+		},
+		{ /* sentinel */ }
+	};
+
+	static const struct soc_attr sb_soc_devices_nomatch[] = {
+		{
+			.family = "SANDBOX0xx",
+			.revision = "1.0",
+			.data = NULL,
+		},
+		{
+			.family = "SANDBOX1xx",
+			.revision = "2.0",
+			.data = NULL,
+		},
+		{ /* sentinel */ }
+	};
+
+	ut_assertok(soc_get(&dev));
+
+	ut_assertok(soc_get_machine(dev, text, sizeof(text)));
+	ut_assertok(strcmp(text, "SANDBOX123"));
+
+	ut_assertok(soc_get_family(dev, text, sizeof(text)));
+	ut_assertok(strcmp(text, "SANDBOX1xx"));
+
+	ut_assertok(soc_get_revision(dev, text, sizeof(text)));
+	ut_asserteq_str(text, "1.0");
+
+	soc_data = soc_device_match(sb_soc_devices_full);
+	ut_assert(soc_data);
+
+	match_data = soc_data->data;
+	ut_asserteq(match_data->param, 0x84848484);
+
+	soc_data = soc_device_match(sb_soc_devices_partial);
+	ut_assert(soc_data);
+
+	match_data = soc_data->data;
+	ut_asserteq(match_data->param, 0x91919191);
+
+	soc_data = soc_device_match(sb_soc_devices_nomatch);
+	ut_asserteq_ptr(soc_data, NULL);
+
+	return 0;
+}
+
+DM_TEST(dm_test_soc, DM_TESTF_SCAN_FDT);
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index 51f2547..8ef7c7a 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -832,10 +832,12 @@
 	struct udevice *back, *dev, *dev2;
 
 	ut_assertok(uclass_find_first_device(UCLASS_PANEL_BACKLIGHT, &back));
+	ut_assertnonnull(back);
 	ut_asserteq(-ENOENT, uclass_find_device_by_phandle(UCLASS_REGULATOR,
 							back, "missing", &dev));
 	ut_assertok(uclass_find_device_by_phandle(UCLASS_REGULATOR, back,
 						  "power-supply", &dev));
+	ut_assertnonnull(dev);
 	ut_asserteq(0, device_active(dev));
 	ut_asserteq_str("ldo1", dev->name);
 	ut_assertok(uclass_get_device_by_phandle(UCLASS_REGULATOR, back,
diff --git a/test/dm/virtio.c b/test/dm/virtio.c
index 4b317d2..4a0c0b2 100644
--- a/test/dm/virtio.c
+++ b/test/dm/virtio.c
@@ -22,9 +22,11 @@
 
 	/* check probe success */
 	ut_assertok(uclass_first_device(UCLASS_VIRTIO, &bus));
+	ut_assertnonnull(bus);
 
 	/* check the child virtio-blk device is bound */
 	ut_assertok(device_find_first_child(bus, &dev));
+	ut_assertnonnull(dev);
 	ut_assertok(strcmp(dev->name, "virtio-blk#0"));
 
 	/* check driver status */
@@ -49,15 +51,18 @@
 
 	/* check probe success */
 	ut_assertok(uclass_first_device(UCLASS_VIRTIO, &bus));
+	ut_assertnonnull(bus);
 
 	/* check the child virtio-blk device is bound */
 	ut_assertok(device_find_first_child(bus, &dev));
+	ut_assertnonnull(dev);
 
 	/*
 	 * fake the virtio device probe by filling in uc_priv->vdev
 	 * which is used by virtio_find_vqs/virtio_del_vqs.
 	 */
 	uc_priv = dev_get_uclass_priv(bus);
+	ut_assertnonnull(uc_priv);
 	uc_priv->vdev = dev;
 
 	/* test virtio_xxx APIs */
@@ -106,9 +111,11 @@
 
 	/* check probe success */
 	ut_assertok(uclass_first_device(UCLASS_VIRTIO, &bus));
+	ut_assertnonnull(bus);
 
 	/* check the child virtio-blk device is bound */
 	ut_assertok(device_find_first_child(bus, &dev));
+	ut_assertnonnull(dev);
 
 	/* set driver status to VIRTIO_CONFIG_S_DRIVER_OK */
 	ut_assertok(virtio_set_status(dev, VIRTIO_CONFIG_S_DRIVER_OK));
diff --git a/test/py/tests/test_env.py b/test/py/tests/test_env.py
index 6ff38f1..a64aaa9 100644
--- a/test/py/tests/test_env.py
+++ b/test/py/tests/test_env.py
@@ -336,3 +336,66 @@
     unset_var(state_test_env, 'foo2')
     unset_var(state_test_env, 'foo3')
     unset_var(state_test_env, 'foo4')
+
+@pytest.mark.buildconfigspec('cmd_nvedit_info')
+def test_env_info(state_test_env):
+
+    """Test 'env info' command with all possible options.
+    """
+    c = state_test_env.u_boot_console
+
+    response = c.run_command('env info')
+    nb_line = 0
+    for l in response.split('\n'):
+        if 'env_valid = ' in l:
+            assert '= invalid' in l or '= valid' in l or '= redundant' in l
+            nb_line += 1
+        elif 'env_ready =' in l or 'env_use_default =' in l:
+            assert '= true' in l or '= false' in l
+            nb_line += 1
+        else:
+            assert true
+    assert nb_line == 3
+
+    response = c.run_command('env info -p -d')
+    assert 'Default environment is used' in response or "Environment was loaded from persistent storage" in response
+    assert 'Environment can be persisted' in response or "Environment cannot be persisted" in response
+
+    response = c.run_command('env info -p -d -q')
+    assert response == ""
+
+    response = c.run_command('env info -p -q')
+    assert response == ""
+
+    response = c.run_command('env info -d -q')
+    assert response == ""
+
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('cmd_nvedit_info')
+@pytest.mark.buildconfigspec('cmd_echo')
+def test_env_info_sandbox(state_test_env):
+
+    """Test 'env info' command result with several options on sandbox
+       with a known ENV configuration: ready & default & persistent
+    """
+    c = state_test_env.u_boot_console
+
+    response = c.run_command('env info')
+    assert 'env_ready = true' in response
+    assert 'env_use_default = true' in response
+
+    response = c.run_command('env info -p -d')
+    assert 'Default environment is used' in response
+    assert 'Environment cannot be persisted' in response
+
+    response = c.run_command('env info -d -q')
+    response = c.run_command('echo $?')
+    assert response == "0"
+
+    response = c.run_command('env info -p -q')
+    response = c.run_command('echo $?')
+    assert response == "1"
+
+    response = c.run_command('env info -d -p -q')
+    response = c.run_command('echo $?')
+    assert response == "1"
diff --git a/test/run b/test/run
index 27331a8..de87e75 100755
--- a/test/run
+++ b/test/run
@@ -48,7 +48,7 @@
 TOOLS_DIR=build-sandbox_spl/tools
 
 run_test "binman" ./tools/binman/binman --toolpath ${TOOLS_DIR} test
-run_test "patman" ./tools/patman/patman --test
+run_test "patman" ./tools/patman/patman test
 
 run_test "buildman" ./tools/buildman/buildman -t ${skip}
 run_test "fdt" ./tools/dtoc/test_fdt -t
diff --git a/tools/binman/README.entries b/tools/binman/README.entries
index 6a816bb..bf8edce 100644
--- a/tools/binman/README.entries
+++ b/tools/binman/README.entries
@@ -42,6 +42,19 @@
 
 
 
+Entry: blob-ext: Entry containing an externally built binary blob
+-----------------------------------------------------------------
+
+Note: This should not be used by itself. It is normally used as a parent
+class by other entry types.
+
+If the file providing this blob is missing, binman can optionally ignore it
+and produce a broken image with a warning.
+
+See 'blob' for Properties / Entry arguments.
+
+
+
 Entry: blob-named-by-arg: A blob entry which gets its filename property from its subclass
 -----------------------------------------------------------------------------------------
 
@@ -297,6 +310,46 @@
 byte value of a region.
 
 
+
+Entry: fit: Entry containing a FIT
+----------------------------------
+
+This calls mkimage to create a FIT (U-Boot Flat Image Tree) based on the
+input provided.
+
+Nodes for the FIT should be written out in the binman configuration just as
+they would be in a file passed to mkimage.
+
+For example, this creates an image containing a FIT with U-Boot SPL:
+
+    binman {
+        fit {
+            description = "Test FIT";
+
+            images {
+                kernel@1 {
+                    description = "SPL";
+                    os = "u-boot";
+                    type = "rkspi";
+                    arch = "arm";
+                    compression = "none";
+                    load = <0>;
+                    entry = <0>;
+
+                    u-boot-spl {
+                    };
+                };
+            };
+        };
+    };
+
+Properties:
+    fit,external-offset: Indicates that the contents of the FIT are external
+        and provides the external offset. This is passsed to mkimage via
+        the -E and -p flags.
+
+
+
 
 Entry: fmap: An entry which contains an Fmap section
 ----------------------------------------------------
@@ -587,6 +640,29 @@
 
 
 
+Entry: mkimage: Entry containing a binary produced by mkimage
+-------------------------------------------------------------
+
+Properties / Entry arguments:
+    - datafile: Filename for -d argument
+    - args: Other arguments to pass
+
+The data passed to mkimage is collected from subnodes of the mkimage node,
+e.g.:
+
+    mkimage {
+        args = "-n test -T imximage";
+
+        u-boot-spl {
+        };
+    };
+
+This calls mkimage to create an imximage with u-boot-spl.bin as the input
+file. The output from mkimage then becomes part of the image produced by
+binman.
+
+
+
 Entry: powerpc-mpc85xx-bootpg-resetvec: PowerPC mpc85xx bootpg + resetvec code for U-Boot
 -----------------------------------------------------------------------------------------
 
diff --git a/tools/binman/cmdline.py b/tools/binman/cmdline.py
index 1e38593..bb4d9d1 100644
--- a/tools/binman/cmdline.py
+++ b/tools/binman/cmdline.py
@@ -53,6 +53,8 @@
             help='Add a path to the list of directories to use for input files')
     build_parser.add_argument('-m', '--map', action='store_true',
         default=False, help='Output a map file for each image')
+    build_parser.add_argument('-M', '--allow-missing', action='store_true',
+        default=False, help='Allow external blobs to be missing')
     build_parser.add_argument('-O', '--outdir', type=str,
         action='store', help='Path to directory to use for intermediate and '
         'output files')
diff --git a/tools/binman/control.py b/tools/binman/control.py
index dc1dd2a..343b0a0 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -387,7 +387,7 @@
 
 
 def ProcessImage(image, update_fdt, write_map, get_contents=True,
-                 allow_resize=True):
+                 allow_resize=True, allow_missing=False):
     """Perform all steps for this image, including checking and # writing it.
 
     This means that errors found with a later image will be reported after
@@ -402,8 +402,13 @@
             the contents is already present
         allow_resize: True to allow entries to change size (this does a re-pack
             of the entries), False to raise an exception
+        allow_missing: Allow blob_ext objects to be missing
+
+    Returns:
+        True if one or more external blobs are missing, False if all are present
     """
     if get_contents:
+        image.SetAllowMissing(allow_missing)
         image.GetEntryContents()
     image.GetEntryOffsets()
 
@@ -448,6 +453,12 @@
     image.BuildImage()
     if write_map:
         image.WriteMap()
+    missing_list = []
+    image.CheckMissing(missing_list)
+    if missing_list:
+        tout.Warning("Image '%s' is missing external blobs and is non-functional: %s" %
+                     (image.name, ' '.join([e.name for e in missing_list])))
+    return bool(missing_list)
 
 
 def Binman(args):
@@ -522,13 +533,17 @@
 
             images = PrepareImagesAndDtbs(dtb_fname, args.image,
                                           args.update_fdt)
+            missing = False
             for image in images.values():
-                ProcessImage(image, args.update_fdt, args.map)
+                missing |= ProcessImage(image, args.update_fdt, args.map,
+                                        allow_missing=args.allow_missing)
 
             # Write the updated FDTs to our output files
             for dtb_item in state.GetAllFdts():
                 tools.WriteFile(dtb_item._fname, dtb_item.GetContents())
 
+            if missing:
+                tout.Warning("Some images are invalid")
         finally:
             tools.FinaliseOutputDir()
     finally:
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index 90ffd27..3434a3f 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -84,6 +84,7 @@
         self.image_pos = None
         self._expand_size = False
         self.compress = 'none'
+        self.missing = False
 
     @staticmethod
     def Lookup(node_path, etype):
@@ -794,3 +795,23 @@
             elif self == entries[-1]:
                 return 'end'
         return 'middle'
+
+    def SetAllowMissing(self, allow_missing):
+        """Set whether a section allows missing external blobs
+
+        Args:
+            allow_missing: True if allowed, False if not allowed
+        """
+        # This is meaningless for anything other than sections
+        pass
+
+    def CheckMissing(self, missing_list):
+        """Check if any entries in this section have missing external blobs
+
+        If there are missing blobs, the entries are added to the list
+
+        Args:
+            missing_list: List of Entry objects to be added to
+        """
+        if self.missing:
+            missing_list.append(self)
diff --git a/tools/binman/etype/_testing.py b/tools/binman/etype/_testing.py
index ed718ee..0800c25 100644
--- a/tools/binman/etype/_testing.py
+++ b/tools/binman/etype/_testing.py
@@ -41,10 +41,10 @@
             data type (generating an error)
     """
     def __init__(self, section, etype, node):
-        Entry.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def ReadNode(self):
-        Entry.ReadNode(self)
+        super().ReadNode()
         self.return_invalid_entry = fdt_util.GetBool(self._node,
                                                      'return-invalid-entry')
         self.return_unknown_contents = fdt_util.GetBool(self._node,
@@ -57,6 +57,8 @@
                                                      'return-contents-once')
         self.bad_update_contents_twice = fdt_util.GetBool(self._node,
                                                     'bad-update-contents-twice')
+        self.return_contents_later = fdt_util.GetBool(self._node,
+                                                     'return-contents-later')
 
         # Set to True when the entry is ready to process the FDT.
         self.process_fdt_ready = False
@@ -83,6 +85,9 @@
     def ObtainContents(self):
         if self.return_unknown_contents or not self.return_contents:
             return False
+        if self.return_contents_later:
+            self.return_contents_later = False
+            return False
         self.data = self.contents
         self.contents_size = len(self.data)
         if self.return_contents_once:
diff --git a/tools/binman/etype/blob.py b/tools/binman/etype/blob.py
index ede7a7a..e507203 100644
--- a/tools/binman/etype/blob.py
+++ b/tools/binman/etype/blob.py
@@ -31,7 +31,7 @@
     data.
     """
     def __init__(self, section, etype, node):
-        Entry.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         self._filename = fdt_util.GetString(self._node, 'filename', self.etype)
         self.compress = fdt_util.GetString(self._node, 'compress', 'none')
 
diff --git a/tools/binman/etype/blob_dtb.py b/tools/binman/etype/blob_dtb.py
index 6c06943..724647a 100644
--- a/tools/binman/etype/blob_dtb.py
+++ b/tools/binman/etype/blob_dtb.py
@@ -20,13 +20,13 @@
         global state
         from binman import state
 
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def ObtainContents(self):
         """Get the device-tree from the list held by the 'state' module"""
         self._filename = self.GetDefaultFilename()
         self._pathname, _ = state.GetFdtContents(self.GetFdtEtype())
-        return Entry_blob.ReadBlobContents(self)
+        return super().ReadBlobContents()
 
     def ProcessContents(self):
         """Re-read the DTB contents so that we get any calculated properties"""
@@ -57,7 +57,7 @@
         return {self.GetFdtEtype(): [self, fname]}
 
     def WriteData(self, data, decomp=True):
-        ok = Entry_blob.WriteData(self, data, decomp)
+        ok = super().WriteData(data, decomp)
 
         # Update the state module, since it has the authoritative record of the
         # device trees used. If we don't do this, then state.GetFdtContents()
diff --git a/tools/binman/etype/blob_ext.py b/tools/binman/etype/blob_ext.py
new file mode 100644
index 0000000..8d64100
--- /dev/null
+++ b/tools/binman/etype/blob_ext.py
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for external blobs, not built by U-Boot
+#
+
+import os
+
+from binman.etype.blob import Entry_blob
+from dtoc import fdt_util
+from patman import tools
+from patman import tout
+
+class Entry_blob_ext(Entry_blob):
+    """Entry containing an externally built binary blob
+
+    Note: This should not be used by itself. It is normally used as a parent
+    class by other entry types.
+
+    If the file providing this blob is missing, binman can optionally ignore it
+    and produce a broken image with a warning.
+
+    See 'blob' for Properties / Entry arguments.
+    """
+    def __init__(self, section, etype, node):
+        Entry_blob.__init__(self, section, etype, node)
+        self.external = True
+
+    def ObtainContents(self):
+        self._filename = self.GetDefaultFilename()
+        self._pathname = tools.GetInputFilename(self._filename,
+                                                self.section.GetAllowMissing())
+        # Allow the file to be missing
+        if not self._pathname:
+            self.SetContents(b'')
+            self.missing = True
+            return True
+        return super().ObtainContents()
diff --git a/tools/binman/etype/blob_named_by_arg.py b/tools/binman/etype/blob_named_by_arg.py
index 3b4593f..e95dabe 100644
--- a/tools/binman/etype/blob_named_by_arg.py
+++ b/tools/binman/etype/blob_named_by_arg.py
@@ -29,6 +29,6 @@
     See cros_ec_rw for an example of this.
     """
     def __init__(self, section, etype, node, blob_fname):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         self._filename, = self.GetEntryArgsOrProps(
             [EntryArg('%s-path' % blob_fname, str)])
diff --git a/tools/binman/etype/cbfs.py b/tools/binman/etype/cbfs.py
index e9aed83..650ab2c 100644
--- a/tools/binman/etype/cbfs.py
+++ b/tools/binman/etype/cbfs.py
@@ -167,7 +167,7 @@
         global state
         from binman import state
 
-        Entry.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         self._cbfs_arg = fdt_util.GetString(node, 'cbfs-arch', 'x86')
         self._cbfs_entries = OrderedDict()
         self._ReadSubnodes()
@@ -204,7 +204,7 @@
         return True
 
     def _ReadSubnodes(self):
-        """Read the subnodes to find out what should go in this IFWI"""
+        """Read the subnodes to find out what should go in this CBFS"""
         for node in self._node.subnodes:
             entry = Entry.Create(self, node)
             entry.ReadNode()
@@ -226,7 +226,7 @@
         Args:
             image_pos: Position of this entry in the image
         """
-        Entry.SetImagePos(self, image_pos)
+        super().SetImagePos(image_pos)
 
         # Now update the entries with info from the CBFS entries
         for entry in self._cbfs_entries.values():
@@ -238,7 +238,7 @@
                 entry.uncomp_size = cfile.memlen
 
     def AddMissingProperties(self):
-        Entry.AddMissingProperties(self)
+        super().AddMissingProperties()
         for entry in self._cbfs_entries.values():
             entry.AddMissingProperties()
             if entry._cbfs_compress:
@@ -250,7 +250,7 @@
 
     def SetCalculatedProperties(self):
         """Set the value of device-tree properties calculated by binman"""
-        Entry.SetCalculatedProperties(self)
+        super().SetCalculatedProperties()
         for entry in self._cbfs_entries.values():
             state.SetInt(entry._node, 'offset', entry.offset)
             state.SetInt(entry._node, 'size', entry.size)
@@ -260,7 +260,7 @@
 
     def ListEntries(self, entries, indent):
         """Override this method to list all files in the section"""
-        Entry.ListEntries(self, entries, indent)
+        super().ListEntries(entries, indent)
         for entry in self._cbfs_entries.values():
             entry.ListEntries(entries, indent + 1)
 
@@ -268,12 +268,12 @@
         return self._cbfs_entries
 
     def ReadData(self, decomp=True):
-        data = Entry.ReadData(self, True)
+        data = super().ReadData(True)
         return data
 
     def ReadChildData(self, child, decomp=True):
         if not self.reader:
-            data = Entry.ReadData(self, True)
+            data = super().ReadData(True)
             self.reader = cbfs_util.CbfsReader(data)
         reader = self.reader
         cfile = reader.files.get(child.name)
diff --git a/tools/binman/etype/cros_ec_rw.py b/tools/binman/etype/cros_ec_rw.py
index 0dbe14b..741372e 100644
--- a/tools/binman/etype/cros_ec_rw.py
+++ b/tools/binman/etype/cros_ec_rw.py
@@ -18,5 +18,5 @@
     updating the EC on startup via software sync.
     """
     def __init__(self, section, etype, node):
-        Entry_blob_named_by_arg.__init__(self, section, etype, node,
-                                         'cros-ec-rw')
+        super().__init__(section, etype, node, 'cros-ec-rw')
+        self.external = True
diff --git a/tools/binman/etype/fdtmap.py b/tools/binman/etype/fdtmap.py
index aa88079..6ca88a1 100644
--- a/tools/binman/etype/fdtmap.py
+++ b/tools/binman/etype/fdtmap.py
@@ -85,7 +85,7 @@
         from binman import state
         from dtoc.fdt import Fdt
 
-        Entry.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def _GetFdtmap(self):
         """Build an FDT map from the entries in the current image
diff --git a/tools/binman/etype/files.py b/tools/binman/etype/files.py
index 10ab585..9adb3af 100644
--- a/tools/binman/etype/files.py
+++ b/tools/binman/etype/files.py
@@ -32,7 +32,7 @@
         global state
         from binman import state
 
-        Entry_section.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         self._pattern = fdt_util.GetString(self._node, 'pattern')
         if not self._pattern:
             self.Raise("Missing 'pattern' property")
diff --git a/tools/binman/etype/fill.py b/tools/binman/etype/fill.py
index 860410e..efb2d13 100644
--- a/tools/binman/etype/fill.py
+++ b/tools/binman/etype/fill.py
@@ -22,10 +22,10 @@
     byte value of a region.
     """
     def __init__(self, section, etype, node):
-        Entry.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def ReadNode(self):
-        Entry.ReadNode(self)
+        super().ReadNode()
         if self.size is None:
             self.Raise("'fill' entry must have a size property")
         self.fill_value = fdt_util.GetByte(self._node, 'fill-byte', 0)
diff --git a/tools/binman/etype/fit.py b/tools/binman/etype/fit.py
new file mode 100644
index 0000000..75712f4
--- /dev/null
+++ b/tools/binman/etype/fit.py
@@ -0,0 +1,164 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for producing a FIT
+#
+
+from collections import defaultdict, OrderedDict
+import libfdt
+
+from binman.entry import Entry
+from dtoc import fdt_util
+from dtoc.fdt import Fdt
+from patman import tools
+
+class Entry_fit(Entry):
+    """Entry containing a FIT
+
+    This calls mkimage to create a FIT (U-Boot Flat Image Tree) based on the
+    input provided.
+
+    Nodes for the FIT should be written out in the binman configuration just as
+    they would be in a file passed to mkimage.
+
+    For example, this creates an image containing a FIT with U-Boot SPL:
+
+        binman {
+            fit {
+                description = "Test FIT";
+
+                images {
+                    kernel@1 {
+                        description = "SPL";
+                        os = "u-boot";
+                        type = "rkspi";
+                        arch = "arm";
+                        compression = "none";
+                        load = <0>;
+                        entry = <0>;
+
+                        u-boot-spl {
+                        };
+                    };
+                };
+            };
+        };
+
+    Properties:
+        fit,external-offset: Indicates that the contents of the FIT are external
+            and provides the external offset. This is passsed to mkimage via
+            the -E and -p flags.
+
+    """
+    def __init__(self, section, etype, node):
+        """
+        Members:
+            _fit: FIT file being built
+            _fit_content: dict:
+                key: relative path to entry Node (from the base of the FIT)
+                value: List of Entry objects comprising the contents of this
+                    node
+        """
+        super().__init__(section, etype, node)
+        self._fit = None
+        self._fit_content = defaultdict(list)
+        self._fit_props = {}
+
+    def ReadNode(self):
+        self._ReadSubnodes()
+        super().ReadNode()
+
+    def _ReadSubnodes(self):
+        def _AddNode(base_node, depth, node):
+            """Add a node to the FIT
+
+            Args:
+                base_node: Base Node of the FIT (with 'description' property)
+                depth: Current node depth (0 is the base node)
+                node: Current node to process
+
+            There are two cases to deal with:
+                - hash and signature nodes which become part of the FIT
+                - binman entries which are used to define the 'data' for each
+                  image
+            """
+            for pname, prop in node.props.items():
+                if pname.startswith('fit,'):
+                    self._fit_props[pname] = prop
+                else:
+                    fsw.property(pname, prop.bytes)
+
+            rel_path = node.path[len(base_node.path):]
+            has_images = depth == 2 and rel_path.startswith('/images/')
+            for subnode in node.subnodes:
+                if has_images and not (subnode.name.startswith('hash') or
+                                       subnode.name.startswith('signature')):
+                    # This is a content node. We collect all of these together
+                    # and put them in the 'data' property. They do not appear
+                    # in the FIT.
+                    entry = Entry.Create(self.section, subnode)
+                    entry.ReadNode()
+                    self._fit_content[rel_path].append(entry)
+                else:
+                    with fsw.add_node(subnode.name):
+                        _AddNode(base_node, depth + 1, subnode)
+
+        # Build a new tree with all nodes and properties starting from the
+        # entry node
+        fsw = libfdt.FdtSw()
+        fsw.finish_reservemap()
+        with fsw.add_node(''):
+            _AddNode(self._node, 0, self._node)
+        fdt = fsw.as_fdt()
+
+        # Pack this new FDT and scan it so we can add the data later
+        fdt.pack()
+        self._fdt = Fdt.FromData(fdt.as_bytearray())
+        self._fdt.Scan()
+
+    def ObtainContents(self):
+        """Obtain the contents of the FIT
+
+        This adds the 'data' properties to the input ITB (Image-tree Binary)
+        then runs mkimage to process it.
+        """
+        data = self._BuildInput(self._fdt)
+        if data == False:
+            return False
+        uniq = self.GetUniqueName()
+        input_fname = tools.GetOutputFilename('%s.itb' % uniq)
+        output_fname = tools.GetOutputFilename('%s.fit' % uniq)
+        tools.WriteFile(input_fname, data)
+        tools.WriteFile(output_fname, data)
+
+        args = []
+        ext_offset = self._fit_props.get('fit,external-offset')
+        if ext_offset is not None:
+            args += ['-E', '-p', '%x' % fdt_util.fdt32_to_cpu(ext_offset.value)]
+        tools.Run('mkimage', '-t', '-F', output_fname, *args)
+
+        self.SetContents(tools.ReadFile(output_fname))
+        return True
+
+    def _BuildInput(self, fdt):
+        """Finish the FIT by adding the 'data' properties to it
+
+        Arguments:
+            fdt: FIT to update
+
+        Returns:
+            New fdt contents (bytes)
+        """
+        for path, entries in self._fit_content.items():
+            node = fdt.GetNode(path)
+            data = b''
+            for entry in entries:
+                if not entry.ObtainContents():
+                    return False
+                data += entry.GetData()
+            node.AddData('data', data)
+
+        fdt.Sync(auto_resize=True)
+        data = fdt.GetContents()
+        return data
diff --git a/tools/binman/etype/fmap.py b/tools/binman/etype/fmap.py
index a43fac3..3e9b815 100644
--- a/tools/binman/etype/fmap.py
+++ b/tools/binman/etype/fmap.py
@@ -32,7 +32,7 @@
     the sub-entries are ignored.
     """
     def __init__(self, section, etype, node):
-        Entry.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def _GetFmap(self):
         """Build an FMAP from the entries in the current image
diff --git a/tools/binman/etype/gbb.py b/tools/binman/etype/gbb.py
index dd10599..41554eb 100644
--- a/tools/binman/etype/gbb.py
+++ b/tools/binman/etype/gbb.py
@@ -54,7 +54,7 @@
     README.chromium for how to obtain the required keys and tools.
     """
     def __init__(self, section, etype, node):
-        Entry.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         self.hardware_id, self.keydir, self.bmpblk = self.GetEntryArgsOrProps(
             [EntryArg('hardware-id', str),
              EntryArg('keydir', str),
diff --git a/tools/binman/etype/image_header.py b/tools/binman/etype/image_header.py
index 176bdeb..2401188 100644
--- a/tools/binman/etype/image_header.py
+++ b/tools/binman/etype/image_header.py
@@ -57,7 +57,7 @@
     first/last in the entry list.
     """
     def __init__(self, section, etype, node):
-        Entry.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         self.location = fdt_util.GetString(self._node, 'location')
 
     def _GetHeader(self):
@@ -101,7 +101,7 @@
                 else:
                     offset = image_size - IMAGE_HEADER_LEN
         offset += self.section.GetStartOffset()
-        return Entry.Pack(self, offset)
+        return super().Pack(offset)
 
     def ProcessContents(self):
         """Write an updated version of the FDT map to this entry
diff --git a/tools/binman/etype/intel_cmc.py b/tools/binman/etype/intel_cmc.py
index 5e6edbe..644fa42 100644
--- a/tools/binman/etype/intel_cmc.py
+++ b/tools/binman/etype/intel_cmc.py
@@ -5,10 +5,9 @@
 # Entry-type module for Intel Chip Microcode binary blob
 #
 
-from binman.entry import Entry
-from binman.etype.blob import Entry_blob
+from binman.etype.blob_ext import Entry_blob_ext
 
-class Entry_intel_cmc(Entry_blob):
+class Entry_intel_cmc(Entry_blob_ext):
     """Entry containing an Intel Chipset Micro Code (CMC) file
 
     Properties / Entry arguments:
@@ -20,4 +19,4 @@
     See README.x86 for information about x86 binary blobs.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
diff --git a/tools/binman/etype/intel_descriptor.py b/tools/binman/etype/intel_descriptor.py
index d4d7a26..7fe88a9 100644
--- a/tools/binman/etype/intel_descriptor.py
+++ b/tools/binman/etype/intel_descriptor.py
@@ -8,7 +8,7 @@
 import struct
 
 from binman.entry import Entry
-from binman.etype.blob import Entry_blob
+from binman.etype.blob_ext import Entry_blob_ext
 
 FD_SIGNATURE   = struct.pack('<L', 0x0ff0a55a)
 MAX_REGIONS    = 5
@@ -25,7 +25,7 @@
         self.limit = ((val & 0x0fff0000) >> 4) | 0xfff
         self.size = self.limit - self.base + 1
 
-class Entry_intel_descriptor(Entry_blob):
+class Entry_intel_descriptor(Entry_blob_ext):
     """Intel flash descriptor block (4KB)
 
     Properties / Entry arguments:
@@ -45,16 +45,22 @@
     See README.x86 for information about x86 binary blobs.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         self._regions = []
 
     def Pack(self, offset):
         """Put this entry at the start of the image"""
         if self.offset is None:
             offset = self.section.GetStartOffset()
-        return Entry_blob.Pack(self, offset)
+        return super().Pack(offset)
 
     def GetOffsets(self):
+        info = {}
+        if self.missing:
+            # Return zero offsets so that these entries get placed somewhere
+            if self.HasSibling('intel-me'):
+                info['intel-me'] = [0, None]
+            return info
         offset = self.data.find(FD_SIGNATURE)
         if offset == -1:
             self.Raise('Cannot find Intel Flash Descriptor (FD) signature')
@@ -66,7 +72,6 @@
 
         # Set the offset for ME (Management Engine) and IFWI (Integrated
         # Firmware Image), for now, since the others are not used.
-        info = {}
         if self.HasSibling('intel-me'):
             info['intel-me'] = [self._regions[REGION_ME].base,
                                 self._regions[REGION_ME].size]
diff --git a/tools/binman/etype/intel_fit.py b/tools/binman/etype/intel_fit.py
index ea482a6..f1a10c5 100644
--- a/tools/binman/etype/intel_fit.py
+++ b/tools/binman/etype/intel_fit.py
@@ -7,9 +7,9 @@
 
 import struct
 
-from binman.etype.blob import Entry_blob
+from binman.etype.blob_ext import Entry_blob_ext
 
-class Entry_intel_fit(Entry_blob):
+class Entry_intel_fit(Entry_blob_ext):
     """Intel Firmware Image Table (FIT)
 
     This entry contains a dummy FIT as required by recent Intel CPUs. The FIT
@@ -19,11 +19,11 @@
     At present binman only supports a basic FIT with no microcode.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def ReadNode(self):
         """Force 16-byte alignment as required by FIT pointer"""
-        Entry_blob.ReadNode(self)
+        super().ReadNode()
         self.align = 16
 
     def ObtainContents(self):
diff --git a/tools/binman/etype/intel_fit_ptr.py b/tools/binman/etype/intel_fit_ptr.py
index df118a6..01f0822 100644
--- a/tools/binman/etype/intel_fit_ptr.py
+++ b/tools/binman/etype/intel_fit_ptr.py
@@ -7,16 +7,16 @@
 
 import struct
 
-from binman.etype.blob import Entry_blob
+from binman.etype.blob_ext import Entry_blob_ext
 
-class Entry_intel_fit_ptr(Entry_blob):
+class Entry_intel_fit_ptr(Entry_blob_ext):
     """Intel Firmware Image Table (FIT) pointer
 
     This entry contains a pointer to the FIT. It is required to be at address
     0xffffffc0 in the image.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         if self.HasSibling('intel-fit') is False:
             self.Raise("'intel-fit-ptr' section must have an 'intel-fit' sibling")
 
@@ -38,4 +38,4 @@
 
     def Pack(self, offset):
         """Special pack method to set the offset to the right place"""
-        return Entry_blob.Pack(self, 0xffffffc0)
+        return super().Pack(0xffffffc0)
diff --git a/tools/binman/etype/intel_fsp.py b/tools/binman/etype/intel_fsp.py
index 7db3d96..2ac012b 100644
--- a/tools/binman/etype/intel_fsp.py
+++ b/tools/binman/etype/intel_fsp.py
@@ -5,10 +5,9 @@
 # Entry-type module for Intel Firmware Support Package binary blob
 #
 
-from binman.entry import Entry
-from binman.etype.blob import Entry_blob
+from binman.etype.blob_ext import Entry_blob_ext
 
-class Entry_intel_fsp(Entry_blob):
+class Entry_intel_fsp(Entry_blob_ext):
     """Entry containing an Intel Firmware Support Package (FSP) file
 
     Properties / Entry arguments:
@@ -24,4 +23,4 @@
     See README.x86 for information about x86 binary blobs.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
diff --git a/tools/binman/etype/intel_fsp_m.py b/tools/binman/etype/intel_fsp_m.py
index 51b4e7e..434b0f1 100644
--- a/tools/binman/etype/intel_fsp_m.py
+++ b/tools/binman/etype/intel_fsp_m.py
@@ -5,10 +5,9 @@
 # Entry-type module for Intel Firmware Support Package binary blob (M section)
 #
 
-from binman.entry import Entry
-from binman.etype.blob import Entry_blob
+from binman.etype.blob_ext import Entry_blob_ext
 
-class Entry_intel_fsp_m(Entry_blob):
+class Entry_intel_fsp_m(Entry_blob_ext):
     """Entry containing Intel Firmware Support Package (FSP) memory init
 
     Properties / Entry arguments:
@@ -24,4 +23,4 @@
     See README.x86 for information about x86 binary blobs.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
diff --git a/tools/binman/etype/intel_fsp_s.py b/tools/binman/etype/intel_fsp_s.py
index b3683e4..564e122 100644
--- a/tools/binman/etype/intel_fsp_s.py
+++ b/tools/binman/etype/intel_fsp_s.py
@@ -5,10 +5,9 @@
 # Entry-type module for Intel Firmware Support Package binary blob (S section)
 #
 
-from binman.entry import Entry
-from binman.etype.blob import Entry_blob
+from binman.etype.blob_ext import Entry_blob_ext
 
-class Entry_intel_fsp_s(Entry_blob):
+class Entry_intel_fsp_s(Entry_blob_ext):
     """Entry containing Intel Firmware Support Package (FSP) silicon init
 
     Properties / Entry arguments:
@@ -24,4 +23,4 @@
     See README.x86 for information about x86 binary blobs.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
diff --git a/tools/binman/etype/intel_fsp_t.py b/tools/binman/etype/intel_fsp_t.py
index 0f196f0..df0c5fb 100644
--- a/tools/binman/etype/intel_fsp_t.py
+++ b/tools/binman/etype/intel_fsp_t.py
@@ -5,10 +5,9 @@
 # Entry-type module for Intel Firmware Support Package binary blob (T section)
 #
 
-from binman.entry import Entry
-from binman.etype.blob import Entry_blob
+from binman.etype.blob_ext import Entry_blob_ext
 
-class Entry_intel_fsp_t(Entry_blob):
+class Entry_intel_fsp_t(Entry_blob_ext):
     """Entry containing Intel Firmware Support Package (FSP) temp ram init
 
     Properties / Entry arguments:
@@ -23,4 +22,4 @@
     See README.x86 for information about x86 binary blobs.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
diff --git a/tools/binman/etype/intel_ifwi.py b/tools/binman/etype/intel_ifwi.py
index 6a96f6b..76b3357 100644
--- a/tools/binman/etype/intel_ifwi.py
+++ b/tools/binman/etype/intel_ifwi.py
@@ -8,11 +8,11 @@
 from collections import OrderedDict
 
 from binman.entry import Entry
-from binman.etype.blob import Entry_blob
+from binman.etype.blob_ext import Entry_blob_ext
 from dtoc import fdt_util
 from patman import tools
 
-class Entry_intel_ifwi(Entry_blob):
+class Entry_intel_ifwi(Entry_blob_ext):
     """Entry containing an Intel Integrated Firmware Image (IFWI) file
 
     Properties / Entry arguments:
@@ -45,13 +45,13 @@
     See README.x86 for information about x86 binary blobs.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         self._convert_fit = fdt_util.GetBool(self._node, 'convert-fit')
         self._ifwi_entries = OrderedDict()
 
     def ReadNode(self):
         self._ReadSubnodes()
-        Entry_blob.ReadNode(self)
+        super().ReadNode()
 
     def _BuildIfwi(self):
         """Build the contents of the IFWI and write it to the 'data' property"""
@@ -84,7 +84,7 @@
         return True
 
     def ObtainContents(self):
-        """Get the contects for the IFWI
+        """Get the contents for the IFWI
 
         Unfortunately we cannot create anything from scratch here, as Intel has
         tools which create precursor binaries with lots of data and settings,
@@ -97,13 +97,21 @@
         After that we delete the OBBP sub-partition and add each of the files
         that we want in the IFWI file, one for each sub-entry of the IWFI node.
         """
-        self._pathname = tools.GetInputFilename(self._filename)
+        self._pathname = tools.GetInputFilename(self._filename,
+                                                self.section.GetAllowMissing())
+        # Allow the file to be missing
+        if not self._pathname:
+            self.SetContents(b'')
+            self.missing = True
+            return True
         for entry in self._ifwi_entries.values():
             if not entry.ObtainContents():
                 return False
         return self._BuildIfwi()
 
     def ProcessContents(self):
+        if self.missing:
+            return True
         orig_data = self.data
         self._BuildIfwi()
         same = orig_data == self.data
@@ -121,5 +129,6 @@
 
     def WriteSymbols(self, section):
         """Write symbol values into binary files for access at run time"""
-        for entry in self._ifwi_entries.values():
-            entry.WriteSymbols(self)
+        if not self.missing:
+            for entry in self._ifwi_entries.values():
+                entry.WriteSymbols(self)
diff --git a/tools/binman/etype/intel_me.py b/tools/binman/etype/intel_me.py
index 41c9c6b..a6fe542 100644
--- a/tools/binman/etype/intel_me.py
+++ b/tools/binman/etype/intel_me.py
@@ -5,10 +5,9 @@
 # Entry-type module for Intel Management Engine binary blob
 #
 
-from binman.entry import Entry
-from binman.etype.blob import Entry_blob
+from binman.etype.blob_ext import Entry_blob_ext
 
-class Entry_intel_me(Entry_blob):
+class Entry_intel_me(Entry_blob_ext):
     """Entry containing an Intel Management Engine (ME) file
 
     Properties / Entry arguments:
@@ -16,7 +15,7 @@
 
     This file contains code used by the SoC that is required to make it work.
     The Management Engine is like a background task that runs things that are
-    not clearly documented, but may include keyboard, deplay and network
+    not clearly documented, but may include keyboard, display and network
     access. For platform that use ME it is not possible to disable it. U-Boot
     does not directly execute code in the ME binary.
 
@@ -27,4 +26,4 @@
     See README.x86 for information about x86 binary blobs.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
diff --git a/tools/binman/etype/intel_mrc.py b/tools/binman/etype/intel_mrc.py
index 854a4dd..ccbb046 100644
--- a/tools/binman/etype/intel_mrc.py
+++ b/tools/binman/etype/intel_mrc.py
@@ -5,10 +5,9 @@
 # Entry-type module for Intel Memory Reference Code binary blob
 #
 
-from binman.entry import Entry
-from binman.etype.blob import Entry_blob
+from binman.etype.blob_ext import Entry_blob_ext
 
-class Entry_intel_mrc(Entry_blob):
+class Entry_intel_mrc(Entry_blob_ext):
     """Entry containing an Intel Memory Reference Code (MRC) file
 
     Properties / Entry arguments:
@@ -21,7 +20,7 @@
     See README.x86 for information about x86 binary blobs.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'mrc.bin'
diff --git a/tools/binman/etype/intel_refcode.py b/tools/binman/etype/intel_refcode.py
index a1059f7..5ead08b 100644
--- a/tools/binman/etype/intel_refcode.py
+++ b/tools/binman/etype/intel_refcode.py
@@ -5,10 +5,9 @@
 # Entry-type module for Intel Memory Reference Code binary blob
 #
 
-from binman.entry import Entry
-from binman.etype.blob import Entry_blob
+from binman.etype.blob_ext import Entry_blob_ext
 
-class Entry_intel_refcode(Entry_blob):
+class Entry_intel_refcode(Entry_blob_ext):
     """Entry containing an Intel Reference Code file
 
     Properties / Entry arguments:
@@ -21,7 +20,7 @@
     See README.x86 for information about x86 binary blobs.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'refcode.bin'
diff --git a/tools/binman/etype/intel_vbt.py b/tools/binman/etype/intel_vbt.py
index 4d465ad..2a98c12 100644
--- a/tools/binman/etype/intel_vbt.py
+++ b/tools/binman/etype/intel_vbt.py
@@ -4,10 +4,9 @@
 # Entry-type module for Intel Video BIOS Table binary blob
 #
 
-from binman.entry import Entry
-from binman.etype.blob import Entry_blob
+from binman.etype.blob_ext import Entry_blob_ext
 
-class Entry_intel_vbt(Entry_blob):
+class Entry_intel_vbt(Entry_blob_ext):
     """Entry containing an Intel Video BIOS Table (VBT) file
 
     Properties / Entry arguments:
@@ -19,4 +18,4 @@
     See README.x86 for information about Intel binary blobs.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
diff --git a/tools/binman/etype/intel_vga.py b/tools/binman/etype/intel_vga.py
index 04cd72f..a103f1c 100644
--- a/tools/binman/etype/intel_vga.py
+++ b/tools/binman/etype/intel_vga.py
@@ -5,10 +5,9 @@
 # Entry-type module for x86 VGA ROM binary blob
 #
 
-from binman.entry import Entry
-from binman.etype.blob import Entry_blob
+from binman.etype.blob_ext import Entry_blob_ext
 
-class Entry_intel_vga(Entry_blob):
+class Entry_intel_vga(Entry_blob_ext):
     """Entry containing an Intel Video Graphics Adaptor (VGA) file
 
     Properties / Entry arguments:
@@ -22,4 +21,4 @@
     See README.x86 for information about Intel binary blobs.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
diff --git a/tools/binman/etype/mkimage.py b/tools/binman/etype/mkimage.py
new file mode 100644
index 0000000..8fddc88
--- /dev/null
+++ b/tools/binman/etype/mkimage.py
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for producing an image using mkimage
+#
+
+from collections import OrderedDict
+
+from binman.entry import Entry
+from dtoc import fdt_util
+from patman import tools
+
+class Entry_mkimage(Entry):
+    """Entry containing a binary produced by mkimage
+
+    Properties / Entry arguments:
+        - datafile: Filename for -d argument
+        - args: Other arguments to pass
+
+    The data passed to mkimage is collected from subnodes of the mkimage node,
+    e.g.:
+
+        mkimage {
+            args = "-n test -T imximage";
+
+            u-boot-spl {
+            };
+        };
+
+    This calls mkimage to create an imximage with u-boot-spl.bin as the input
+    file. The output from mkimage then becomes part of the image produced by
+    binman.
+    """
+    def __init__(self, section, etype, node):
+        super().__init__(section, etype, node)
+        self._args = fdt_util.GetString(self._node, 'args').split(' ')
+        self._mkimage_entries = OrderedDict()
+        self._ReadSubnodes()
+
+    def ObtainContents(self):
+        data = b''
+        for entry in self._mkimage_entries.values():
+            # First get the input data and put it in a file. If not available,
+            # try later.
+            if not entry.ObtainContents():
+                return False
+            data += entry.GetData()
+        uniq = self.GetUniqueName()
+        input_fname = tools.GetOutputFilename('mkimage.%s' % uniq)
+        tools.WriteFile(input_fname, data)
+        output_fname = tools.GetOutputFilename('mkimage-out.%s' % uniq)
+        tools.Run('mkimage', '-d', input_fname, *self._args, output_fname)
+        self.SetContents(tools.ReadFile(output_fname))
+        return True
+
+    def _ReadSubnodes(self):
+        """Read the subnodes to find out what should go in this image"""
+        for node in self._node.subnodes:
+            entry = Entry.Create(self, node)
+            entry.ReadNode()
+            self._mkimage_entries[entry.name] = entry
diff --git a/tools/binman/etype/powerpc_mpc85xx_bootpg_resetvec.py b/tools/binman/etype/powerpc_mpc85xx_bootpg_resetvec.py
index cefd425..3a92fa3 100644
--- a/tools/binman/etype/powerpc_mpc85xx_bootpg_resetvec.py
+++ b/tools/binman/etype/powerpc_mpc85xx_bootpg_resetvec.py
@@ -4,7 +4,6 @@
 # Entry-type module for the PowerPC mpc85xx bootpg and resetvec code for U-Boot
 #
 
-from binman.entry import Entry
 from binman.etype.blob import Entry_blob
 
 class Entry_powerpc_mpc85xx_bootpg_resetvec(Entry_blob):
@@ -13,13 +12,13 @@
     Properties / Entry arguments:
         - filename: Filename of u-boot-br.bin (default 'u-boot-br.bin')
 
-    This enrty is valid for PowerPC mpc85xx cpus. This entry holds
+    This entry is valid for PowerPC mpc85xx cpus. This entry holds
     'bootpg + resetvec' code for PowerPC mpc85xx CPUs which needs to be
     placed at offset 'RESET_VECTOR_ADDRESS - 0xffc'.
     """
 
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'u-boot-br.bin'
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index 91b8e0c..73c5553 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -34,6 +34,11 @@
         name-prefix: Adds a prefix to the name of every entry in the section
             when writing out the map
 
+    Properties:
+        _allow_missing: True if this section permits external blobs to be
+            missing their contents. The second will produce an image but of
+            course it will not work.
+
     Since a section is also an entry, it inherits all the properies of entries
     too.
 
@@ -43,16 +48,18 @@
     """
     def __init__(self, section, etype, node, test=False):
         if not test:
-            Entry.__init__(self, section, etype, node)
+            super().__init__(section, etype, node)
         self._entries = OrderedDict()
         self._pad_byte = 0
         self._sort = False
         self._skip_at_start = None
         self._end_4gb = False
+        self._allow_missing = False
+        self.missing = False
 
     def ReadNode(self):
         """Read properties from the image node"""
-        Entry.ReadNode(self)
+        super().ReadNode()
         self._pad_byte = fdt_util.GetInt(self._node, 'pad-byte', 0)
         self._sort = fdt_util.GetBool(self._node, 'sort-by-offset')
         self._end_4gb = fdt_util.GetBool(self._node, 'end-at-4gb')
@@ -126,13 +133,13 @@
         a section containing a list of files. Process these entries so that
         this information is added to the device tree.
         """
-        Entry.ExpandEntries(self)
+        super().ExpandEntries()
         for entry in self._entries.values():
             entry.ExpandEntries()
 
     def AddMissingProperties(self):
         """Add new properties to the device tree as needed for this entry"""
-        Entry.AddMissingProperties(self)
+        super().AddMissingProperties()
         for entry in self._entries.values():
             entry.AddMissingProperties()
 
@@ -168,14 +175,14 @@
 
     def ResetForPack(self):
         """Reset offset/size fields so that packing can be done again"""
-        Entry.ResetForPack(self)
+        super().ResetForPack()
         for entry in self._entries.values():
             entry.ResetForPack()
 
     def Pack(self, offset):
         """Pack all entries into the section"""
         self._PackEntries()
-        return Entry.Pack(self, offset)
+        return super().Pack(offset)
 
     def _PackEntries(self):
         """Pack all entries into the image"""
@@ -219,7 +226,7 @@
                             "at %#x (%d)" %
                             (entry.offset, entry.offset, self._skip_at_start,
                              self._skip_at_start))
-            if entry.offset < offset:
+            if entry.offset < offset and entry.size:
                 entry.Raise("Offset %#x (%d) overlaps with previous entry '%s' "
                             "ending at %#x (%d)" %
                             (entry.offset, entry.offset, prev_name, offset, offset))
@@ -232,12 +239,12 @@
             entry.WriteSymbols(self)
 
     def SetCalculatedProperties(self):
-        Entry.SetCalculatedProperties(self)
+        super().SetCalculatedProperties()
         for entry in self._entries.values():
             entry.SetCalculatedProperties()
 
     def SetImagePos(self, image_pos):
-        Entry.SetImagePos(self, image_pos)
+        super().SetImagePos(image_pos)
         for entry in self._entries.values():
             entry.SetImagePos(image_pos + self.offset)
 
@@ -435,8 +442,8 @@
         if not entry:
             self._Raise("Unable to set offset/size for unknown entry '%s'" %
                         name)
-        entry.SetOffsetSize(self._skip_at_start + offset if offset else None,
-                            size)
+        entry.SetOffsetSize(self._skip_at_start + offset if offset is not None
+                            else None, size)
 
     def GetEntryOffsets(self):
         """Handle entries that want to set the offset/size of other entries
@@ -535,3 +542,32 @@
 
     def WriteChildData(self, child):
         return True
+
+    def SetAllowMissing(self, allow_missing):
+        """Set whether a section allows missing external blobs
+
+        Args:
+            allow_missing: True if allowed, False if not allowed
+        """
+        self._allow_missing = allow_missing
+        for entry in self._entries.values():
+            entry.SetAllowMissing(allow_missing)
+
+    def GetAllowMissing(self):
+        """Get whether a section allows missing external blobs
+
+        Returns:
+            True if allowed, False if not allowed
+        """
+        return self._allow_missing
+
+    def CheckMissing(self, missing_list):
+        """Check if any entries in this section have missing external blobs
+
+        If there are missing blobs, the entries are added to the list
+
+        Args:
+            missing_list: List of Entry objects to be added to
+        """
+        for entry in self._entries.values():
+            entry.CheckMissing(missing_list)
diff --git a/tools/binman/etype/text.py b/tools/binman/etype/text.py
index 3577135..a69c2a4 100644
--- a/tools/binman/etype/text.py
+++ b/tools/binman/etype/text.py
@@ -57,7 +57,7 @@
     by setting the size of the entry to something larger than the text.
     """
     def __init__(self, section, etype, node):
-        Entry.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         value = fdt_util.GetString(self._node, 'text')
         if value:
             value = tools.ToBytes(value)
diff --git a/tools/binman/etype/u_boot.py b/tools/binman/etype/u_boot.py
index ab1019b..4767197 100644
--- a/tools/binman/etype/u_boot.py
+++ b/tools/binman/etype/u_boot.py
@@ -26,7 +26,7 @@
     in the binman README for more information.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'u-boot.bin'
diff --git a/tools/binman/etype/u_boot_dtb.py b/tools/binman/etype/u_boot_dtb.py
index e983500..65e7129 100644
--- a/tools/binman/etype/u_boot_dtb.py
+++ b/tools/binman/etype/u_boot_dtb.py
@@ -22,7 +22,7 @@
     binman to know which entries contain a device tree.
     """
     def __init__(self, section, etype, node):
-        Entry_blob_dtb.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'u-boot.dtb'
diff --git a/tools/binman/etype/u_boot_dtb_with_ucode.py b/tools/binman/etype/u_boot_dtb_with_ucode.py
index aec1455..66a9db5 100644
--- a/tools/binman/etype/u_boot_dtb_with_ucode.py
+++ b/tools/binman/etype/u_boot_dtb_with_ucode.py
@@ -28,7 +28,7 @@
         global state
         from binman import state
 
-        Entry_blob_dtb.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         self.ucode_data = b''
         self.collate = False
         self.ucode_offset = None
@@ -78,7 +78,7 @@
 
     def ObtainContents(self):
         # Call the base class just in case it does something important.
-        Entry_blob_dtb.ObtainContents(self)
+        super().ObtainContents()
         if self.ucode and not self.collate:
             for node in self.ucode.subnodes:
                 data_prop = node.props.get('data')
diff --git a/tools/binman/etype/u_boot_elf.py b/tools/binman/etype/u_boot_elf.py
index 5f906e5..6614a75 100644
--- a/tools/binman/etype/u_boot_elf.py
+++ b/tools/binman/etype/u_boot_elf.py
@@ -21,7 +21,7 @@
     relocated to any address for execution.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         self._strip = fdt_util.GetBool(self._node, 'strip')
 
     def ReadBlobContents(self):
@@ -31,7 +31,7 @@
             tools.WriteFile(out_fname, tools.ReadFile(self._pathname))
             tools.Run('strip', out_fname)
             self._pathname = out_fname
-        Entry_blob.ReadBlobContents(self)
+        super().ReadBlobContents()
         return True
 
     def GetDefaultFilename(self):
diff --git a/tools/binman/etype/u_boot_img.py b/tools/binman/etype/u_boot_img.py
index 50cc71d..8a739d8 100644
--- a/tools/binman/etype/u_boot_img.py
+++ b/tools/binman/etype/u_boot_img.py
@@ -21,7 +21,7 @@
     applications.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'u-boot.img'
diff --git a/tools/binman/etype/u_boot_nodtb.py b/tools/binman/etype/u_boot_nodtb.py
index e8c0e1a..e84df49 100644
--- a/tools/binman/etype/u_boot_nodtb.py
+++ b/tools/binman/etype/u_boot_nodtb.py
@@ -21,7 +21,7 @@
     U-Boot and the device tree).
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'u-boot-nodtb.bin'
diff --git a/tools/binman/etype/u_boot_spl.py b/tools/binman/etype/u_boot_spl.py
index a6fddbe..d66e461 100644
--- a/tools/binman/etype/u_boot_spl.py
+++ b/tools/binman/etype/u_boot_spl.py
@@ -32,7 +32,7 @@
     binman uses that to look up symbols to write into the SPL binary.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         self.elf_fname = 'spl/u-boot-spl'
 
     def GetDefaultFilename(self):
diff --git a/tools/binman/etype/u_boot_spl_bss_pad.py b/tools/binman/etype/u_boot_spl_bss_pad.py
index a6a177a..596b2be 100644
--- a/tools/binman/etype/u_boot_spl_bss_pad.py
+++ b/tools/binman/etype/u_boot_spl_bss_pad.py
@@ -31,7 +31,7 @@
     binman uses that to look up the BSS address.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def ObtainContents(self):
         fname = tools.GetInputFilename('spl/u-boot-spl')
diff --git a/tools/binman/etype/u_boot_spl_dtb.py b/tools/binman/etype/u_boot_spl_dtb.py
index a0761ee..eefc4a4 100644
--- a/tools/binman/etype/u_boot_spl_dtb.py
+++ b/tools/binman/etype/u_boot_spl_dtb.py
@@ -19,7 +19,7 @@
     to activate.
     """
     def __init__(self, section, etype, node):
-        Entry_blob_dtb.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'spl/u-boot-spl.dtb'
diff --git a/tools/binman/etype/u_boot_spl_elf.py b/tools/binman/etype/u_boot_spl_elf.py
index f99f74a..7f1236b 100644
--- a/tools/binman/etype/u_boot_spl_elf.py
+++ b/tools/binman/etype/u_boot_spl_elf.py
@@ -18,7 +18,7 @@
     be relocated to any address for execution.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'spl/u-boot-spl'
diff --git a/tools/binman/etype/u_boot_spl_nodtb.py b/tools/binman/etype/u_boot_spl_nodtb.py
index 072b915..6f45293 100644
--- a/tools/binman/etype/u_boot_spl_nodtb.py
+++ b/tools/binman/etype/u_boot_spl_nodtb.py
@@ -22,7 +22,7 @@
     both SPL and the device tree).
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'spl/u-boot-spl-nodtb.bin'
diff --git a/tools/binman/etype/u_boot_spl_with_ucode_ptr.py b/tools/binman/etype/u_boot_spl_with_ucode_ptr.py
index b1543a5..72739a5 100644
--- a/tools/binman/etype/u_boot_spl_with_ucode_ptr.py
+++ b/tools/binman/etype/u_boot_spl_with_ucode_ptr.py
@@ -18,7 +18,7 @@
     process.
     """
     def __init__(self, section, etype, node):
-        Entry_u_boot_with_ucode_ptr.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         self.elf_fname = 'spl/u-boot-spl'
 
     def GetDefaultFilename(self):
diff --git a/tools/binman/etype/u_boot_tpl.py b/tools/binman/etype/u_boot_tpl.py
index 6562457..02287ab 100644
--- a/tools/binman/etype/u_boot_tpl.py
+++ b/tools/binman/etype/u_boot_tpl.py
@@ -32,7 +32,7 @@
     binman uses that to look up symbols to write into the TPL binary.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         self.elf_fname = 'tpl/u-boot-tpl'
 
     def GetDefaultFilename(self):
diff --git a/tools/binman/etype/u_boot_tpl_dtb.py b/tools/binman/etype/u_boot_tpl_dtb.py
index 890155f..2ff1d7c 100644
--- a/tools/binman/etype/u_boot_tpl_dtb.py
+++ b/tools/binman/etype/u_boot_tpl_dtb.py
@@ -19,7 +19,7 @@
     to activate.
     """
     def __init__(self, section, etype, node):
-        Entry_blob_dtb.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'tpl/u-boot-tpl.dtb'
diff --git a/tools/binman/etype/u_boot_tpl_dtb_with_ucode.py b/tools/binman/etype/u_boot_tpl_dtb_with_ucode.py
index ca1bf85..066f18d 100644
--- a/tools/binman/etype/u_boot_tpl_dtb_with_ucode.py
+++ b/tools/binman/etype/u_boot_tpl_dtb_with_ucode.py
@@ -16,7 +16,7 @@
     process.
     """
     def __init__(self, section, etype, node):
-        Entry_u_boot_dtb_with_ucode.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'tpl/u-boot-tpl.dtb'
diff --git a/tools/binman/etype/u_boot_tpl_elf.py b/tools/binman/etype/u_boot_tpl_elf.py
index 7fa8e96..3f24d3a 100644
--- a/tools/binman/etype/u_boot_tpl_elf.py
+++ b/tools/binman/etype/u_boot_tpl_elf.py
@@ -18,7 +18,7 @@
     be relocated to any address for execution.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'tpl/u-boot-tpl'
diff --git a/tools/binman/etype/u_boot_tpl_with_ucode_ptr.py b/tools/binman/etype/u_boot_tpl_with_ucode_ptr.py
index 7f7fab7..c7f3f9d 100644
--- a/tools/binman/etype/u_boot_tpl_with_ucode_ptr.py
+++ b/tools/binman/etype/u_boot_tpl_with_ucode_ptr.py
@@ -20,7 +20,7 @@
     process.
     """
     def __init__(self, section, etype, node):
-        Entry_u_boot_with_ucode_ptr.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         self.elf_fname = 'tpl/u-boot-tpl'
 
     def GetDefaultFilename(self):
diff --git a/tools/binman/etype/u_boot_ucode.py b/tools/binman/etype/u_boot_ucode.py
index d9e1a60..4462293 100644
--- a/tools/binman/etype/u_boot_ucode.py
+++ b/tools/binman/etype/u_boot_ucode.py
@@ -58,7 +58,7 @@
             contents of this entry.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def ObtainContents(self):
         # If the section does not need microcode, there is nothing to do
diff --git a/tools/binman/etype/u_boot_with_ucode_ptr.py b/tools/binman/etype/u_boot_with_ucode_ptr.py
index 06047b6..92d2fc6 100644
--- a/tools/binman/etype/u_boot_with_ucode_ptr.py
+++ b/tools/binman/etype/u_boot_with_ucode_ptr.py
@@ -29,7 +29,7 @@
     complicated. Otherwise it is the same as the u_boot entry.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         self.elf_fname = 'u-boot'
         self.target_offset = None
 
diff --git a/tools/binman/etype/vblock.py b/tools/binman/etype/vblock.py
index 5753de7..f734fba 100644
--- a/tools/binman/etype/vblock.py
+++ b/tools/binman/etype/vblock.py
@@ -36,7 +36,7 @@
     and kernel are genuine.
     """
     def __init__(self, section, etype, node):
-        Entry.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
         self.content = fdt_util.GetPhandleList(self._node, 'content')
         if not self.content:
             self.Raise("Vblock must have a 'content' property")
diff --git a/tools/binman/etype/x86_reset16.py b/tools/binman/etype/x86_reset16.py
index ad864e5..5d49f16 100644
--- a/tools/binman/etype/x86_reset16.py
+++ b/tools/binman/etype/x86_reset16.py
@@ -23,7 +23,7 @@
     For 64-bit U-Boot, the 'x86_reset16_spl' entry type is used instead.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'u-boot-x86-reset16.bin'
diff --git a/tools/binman/etype/x86_reset16_spl.py b/tools/binman/etype/x86_reset16_spl.py
index 9a663f0..775b906 100644
--- a/tools/binman/etype/x86_reset16_spl.py
+++ b/tools/binman/etype/x86_reset16_spl.py
@@ -23,7 +23,7 @@
     For 32-bit U-Boot, the 'x86_reset_spl' entry type is used instead.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'spl/u-boot-x86-reset16-spl.bin'
diff --git a/tools/binman/etype/x86_reset16_tpl.py b/tools/binman/etype/x86_reset16_tpl.py
index 864508f..52d3f48 100644
--- a/tools/binman/etype/x86_reset16_tpl.py
+++ b/tools/binman/etype/x86_reset16_tpl.py
@@ -23,7 +23,7 @@
     For 32-bit U-Boot, the 'x86_reset_tpl' entry type is used instead.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'tpl/u-boot-x86-reset16-tpl.bin'
diff --git a/tools/binman/etype/x86_start16.py b/tools/binman/etype/x86_start16.py
index d8345f6..18fdd95 100644
--- a/tools/binman/etype/x86_start16.py
+++ b/tools/binman/etype/x86_start16.py
@@ -25,7 +25,7 @@
     For 64-bit U-Boot, the 'x86_start16_spl' entry type is used instead.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'u-boot-x86-start16.bin'
diff --git a/tools/binman/etype/x86_start16_spl.py b/tools/binman/etype/x86_start16_spl.py
index ad520d3..ac8e90f 100644
--- a/tools/binman/etype/x86_start16_spl.py
+++ b/tools/binman/etype/x86_start16_spl.py
@@ -25,7 +25,7 @@
     For 32-bit U-Boot, the 'x86-start16' entry type is used instead.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'spl/u-boot-x86-start16-spl.bin'
diff --git a/tools/binman/etype/x86_start16_tpl.py b/tools/binman/etype/x86_start16_tpl.py
index ccc8727..72d4608 100644
--- a/tools/binman/etype/x86_start16_tpl.py
+++ b/tools/binman/etype/x86_start16_tpl.py
@@ -26,7 +26,7 @@
     may be used instead.
     """
     def __init__(self, section, etype, node):
-        Entry_blob.__init__(self, section, etype, node)
+        super().__init__(section, etype, node)
 
     def GetDefaultFilename(self):
         return 'tpl/u-boot-x86-start16-tpl.bin'
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 5e24920..bf7f59f 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -6,10 +6,12 @@
 #
 #    python -m unittest func_test.TestFunctional.testHelp
 
+import collections
 import gzip
 import hashlib
 from optparse import OptionParser
 import os
+import re
 import shutil
 import struct
 import sys
@@ -160,8 +162,7 @@
             tools.ReadFile(cls.ElfTestFile('u_boot_ucode_ptr')))
 
         # Intel flash descriptor file
-        with open(cls.TestFile('descriptor.bin'), 'rb') as fd:
-            TestFunctional._MakeInputFile('descriptor.bin', fd.read())
+        cls._SetupDescriptor()
 
         shutil.copytree(cls.TestFile('files'),
                         os.path.join(cls._indir, 'files'))
@@ -285,7 +286,7 @@
 
     def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
                     entry_args=None, images=None, use_real_dtb=False,
-                    verbosity=None):
+                    verbosity=None, allow_missing=False):
         """Run binman with a given test file
 
         Args:
@@ -319,6 +320,8 @@
         if entry_args:
             for arg, value in entry_args.items():
                 args.append('-a%s=%s' % (arg, value))
+        if allow_missing:
+            args.append('-M')
         if images:
             for image in images:
                 args += ['-i', image]
@@ -506,6 +509,11 @@
             tools.ReadFile(cls.ElfTestFile(src_fname)))
 
     @classmethod
+    def _SetupDescriptor(cls):
+        with open(cls.TestFile('descriptor.bin'), 'rb') as fd:
+            TestFunctional._MakeInputFile('descriptor.bin', fd.read())
+
+    @classmethod
     def TestFile(cls, fname):
         return os.path.join(cls._binman_dir, 'test', fname)
 
@@ -931,11 +939,14 @@
 
     def testPackX86RomMeNoDesc(self):
         """Test that an invalid Intel descriptor entry is detected"""
-        TestFunctional._MakeInputFile('descriptor.bin', b'')
-        with self.assertRaises(ValueError) as e:
-            self._DoTestFile('031_x86_rom_me.dts')
-        self.assertIn("Node '/binman/intel-descriptor': Cannot find Intel Flash Descriptor (FD) signature",
-                      str(e.exception))
+        try:
+            TestFunctional._MakeInputFile('descriptor-empty.bin', b'')
+            with self.assertRaises(ValueError) as e:
+                self._DoTestFile('163_x86_rom_me_empty.dts')
+            self.assertIn("Node '/binman/intel-descriptor': Cannot find Intel Flash Descriptor (FD) signature",
+                          str(e.exception))
+        finally:
+            self._SetupDescriptor()
 
     def testPackX86RomBadDesc(self):
         """Test that the Intel requires a descriptor entry"""
@@ -3230,7 +3241,7 @@
         with test_util.capture_sys_output() as (stdout, stderr):
             control.ReplaceEntries(updated_fname, None, outdir, [])
         self.assertIn("Skipping entry '/u-boot' from missing file",
-                      stdout.getvalue())
+                      stderr.getvalue())
 
     def testReplaceCmdMap(self):
         """Test replacing a file fron an image on the command line"""
@@ -3357,6 +3368,115 @@
         data = self._DoReadFile('154_intel_fsp_t.dts')
         self.assertEqual(FSP_T_DATA, data[:len(FSP_T_DATA)])
 
+    def testMkimage(self):
+        """Test using mkimage to build an image"""
+        data = self._DoReadFile('156_mkimage.dts')
+
+        # Just check that the data appears in the file somewhere
+        self.assertIn(U_BOOT_SPL_DATA, data)
+
+    def testExtblob(self):
+        """Test an image with an external blob"""
+        data = self._DoReadFile('157_blob_ext.dts')
+        self.assertEqual(REFCODE_DATA, data)
+
+    def testExtblobMissing(self):
+        """Test an image with a missing external blob"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('158_blob_ext_missing.dts')
+        self.assertIn("Filename 'missing-file' not found in input path",
+                      str(e.exception))
+
+    def testExtblobMissingOk(self):
+        """Test an image with an missing external blob that is allowed"""
+        with test_util.capture_sys_output() as (stdout, stderr):
+            self._DoTestFile('158_blob_ext_missing.dts', allow_missing=True)
+        err = stderr.getvalue()
+        self.assertRegex(err, "Image 'main-section'.*missing.*: blob-ext")
+
+    def testExtblobMissingOkSect(self):
+        """Test an image with an missing external blob that is allowed"""
+        with test_util.capture_sys_output() as (stdout, stderr):
+            self._DoTestFile('159_blob_ext_missing_sect.dts',
+                             allow_missing=True)
+        err = stderr.getvalue()
+        self.assertRegex(err, "Image 'main-section'.*missing.*: "
+                         "blob-ext blob-ext2")
+
+    def testPackX86RomMeMissingDesc(self):
+        """Test that an missing Intel descriptor entry is allowed"""
+        with test_util.capture_sys_output() as (stdout, stderr):
+            self._DoTestFile('164_x86_rom_me_missing.dts', allow_missing=True)
+        err = stderr.getvalue()
+        self.assertRegex(err,
+                         "Image 'main-section'.*missing.*: intel-descriptor")
+
+    def testPackX86RomMissingIfwi(self):
+        """Test that an x86 ROM with Integrated Firmware Image can be created"""
+        self._SetupIfwi('fitimage.bin')
+        pathname = os.path.join(self._indir, 'fitimage.bin')
+        os.remove(pathname)
+        with test_util.capture_sys_output() as (stdout, stderr):
+            self._DoTestFile('111_x86_rom_ifwi.dts', allow_missing=True)
+        err = stderr.getvalue()
+        self.assertRegex(err, "Image 'main-section'.*missing.*: intel-ifwi")
+
+    def testPackOverlap(self):
+        """Test that zero-size overlapping regions are ignored"""
+        self._DoTestFile('160_pack_overlap_zero.dts')
+
+    def testSimpleFit(self):
+        """Test an image with a FIT inside"""
+        data = self._DoReadFile('161_fit.dts')
+        self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
+        self.assertEqual(U_BOOT_NODTB_DATA, data[-len(U_BOOT_NODTB_DATA):])
+        fit_data = data[len(U_BOOT_DATA):-len(U_BOOT_NODTB_DATA)]
+
+        # The data should be inside the FIT
+        dtb = fdt.Fdt.FromData(fit_data)
+        dtb.Scan()
+        fnode = dtb.GetNode('/images/kernel')
+        self.assertIn('data', fnode.props)
+
+        fname = os.path.join(self._indir, 'fit_data.fit')
+        tools.WriteFile(fname, fit_data)
+        out = tools.Run('dumpimage', '-l', fname)
+
+        # Check a few features to make sure the plumbing works. We don't need
+        # to test the operation of mkimage or dumpimage here. First convert the
+        # output into a dict where the keys are the fields printed by dumpimage
+        # and the values are a list of values for each field
+        lines = out.splitlines()
+
+        # Converts "Compression:  gzip compressed" into two groups:
+        # 'Compression' and 'gzip compressed'
+        re_line = re.compile(r'^ *([^:]*)(?:: *(.*))?$')
+        vals = collections.defaultdict(list)
+        for line in lines:
+            mat = re_line.match(line)
+            vals[mat.group(1)].append(mat.group(2))
+
+        self.assertEquals('FIT description: test-desc', lines[0])
+        self.assertIn('Created:', lines[1])
+        self.assertIn('Image 0 (kernel)', vals)
+        self.assertIn('Hash value', vals)
+        data_sizes = vals.get('Data Size')
+        self.assertIsNotNone(data_sizes)
+        self.assertEqual(2, len(data_sizes))
+        # Format is "4 Bytes = 0.00 KiB = 0.00 MiB" so take the first word
+        self.assertEqual(len(U_BOOT_DATA), int(data_sizes[0].split()[0]))
+        self.assertEqual(len(U_BOOT_SPL_DTB_DATA), int(data_sizes[1].split()[0]))
+
+    def testFitExternal(self):
+        """Test an image with an FIT"""
+        data = self._DoReadFile('162_fit_external.dts')
+        fit_data = data[len(U_BOOT_DATA):-2]  # _testing is 2 bytes
+
+        # The data should be outside the FIT
+        dtb = fdt.Fdt.FromData(fit_data)
+        dtb.Scan()
+        fnode = dtb.GetNode('/images/kernel')
+        self.assertNotIn('data', fnode.props)
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/image.py b/tools/binman/image.py
index 523b274..a8772c3 100644
--- a/tools/binman/image.py
+++ b/tools/binman/image.py
@@ -45,7 +45,7 @@
             we create a section manually.
     """
     def __init__(self, name, node, copy_to_orig=True, test=False):
-        section.Entry_section.__init__(self, None, 'section', node, test=test)
+        super().__init__(None, 'section', node, test=test)
         self.copy_to_orig = copy_to_orig
         self.name = 'main-section'
         self.image_name = name
@@ -57,7 +57,7 @@
             self.ReadNode()
 
     def ReadNode(self):
-        section.Entry_section.ReadNode(self)
+        super().ReadNode()
         filename = fdt_util.GetString(self._node, 'filename')
         if filename:
             self._filename = filename
@@ -116,11 +116,11 @@
 
     def PackEntries(self):
         """Pack all entries into the image"""
-        section.Entry_section.Pack(self, 0)
+        super().Pack(0)
 
     def SetImagePos(self):
         # This first section in the image so it starts at 0
-        section.Entry_section.SetImagePos(self, 0)
+        super().SetImagePos(0)
 
     def ProcessEntryContents(self):
         """Call the ProcessContents() method for each entry
@@ -139,7 +139,7 @@
 
     def WriteSymbols(self):
         """Write symbol values into binary files for access at run time"""
-        section.Entry_section.WriteSymbols(self, self)
+        super().WriteSymbols(self)
 
     def BuildImage(self):
         """Write the image to a file"""
@@ -161,7 +161,7 @@
         with open(fname, 'w') as fd:
             print('%8s  %8s  %8s  %s' % ('ImagePos', 'Offset', 'Size', 'Name'),
                   file=fd)
-            section.Entry_section.WriteMap(self, fd, 0)
+            super().WriteMap(fd, 0)
         return fname
 
     def BuildEntryList(self):
diff --git a/tools/binman/main.py b/tools/binman/main.py
index efa7fa8..e543a7d 100755
--- a/tools/binman/main.py
+++ b/tools/binman/main.py
@@ -26,6 +26,7 @@
 
 # Bring in the libfdt module
 sys.path.insert(2, 'scripts/dtc/pylibfdt')
+sys.path.insert(2, os.path.join(our_path, '../../scripts/dtc/pylibfdt'))
 sys.path.insert(2, os.path.join(our_path,
                 '../../build-sandbox_spl/scripts/dtc/pylibfdt'))
 
@@ -88,14 +89,18 @@
                 for item in glob_list
                 if include_testing or '_testing' not in item])
 
-def RunTestCoverage():
+def RunTestCoverage(toolpath):
     """Run the tests and check that we get 100% coverage"""
     glob_list = GetEntryModules(False)
     all_set = set([os.path.splitext(os.path.basename(item))[0]
                    for item in glob_list if '_testing' not in item])
+    extra_args = ''
+    if toolpath:
+        for path in toolpath:
+            extra_args += ' --toolpath %s' % path
     test_util.RunTestCoverage('tools/binman/binman', None,
             ['*test*', '*main.py', 'tools/patman/*', 'tools/dtoc/*'],
-            args.build_dir, all_set)
+            args.build_dir, all_set, extra_args or None)
 
 def RunBinman(args):
     """Main entry point to binman once arguments are parsed
@@ -108,9 +113,14 @@
     if not args.debug:
         sys.tracebacklimit = 0
 
+    # Provide a default toolpath in the hope of finding a mkimage built from
+    # current source
+    if not args.toolpath:
+        args.toolpath = ['./tools', 'build-sandbox/tools']
+
     if args.cmd == 'test':
         if args.test_coverage:
-            RunTestCoverage()
+            RunTestCoverage(args.toolpath)
         else:
             ret_code = RunTests(args.debug, args.verbosity, args.processes,
                                 args.test_preserve_dirs, args.tests,
@@ -123,7 +133,7 @@
         try:
             ret_code = control.Binman(args)
         except Exception as e:
-            print('binman: %s' % e)
+            print('binman: %s' % e, file=sys.stderr)
             if args.debug:
                 print()
                 traceback.print_exc()
diff --git a/tools/binman/test/156_mkimage.dts b/tools/binman/test/156_mkimage.dts
new file mode 100644
index 0000000..933b131
--- /dev/null
+++ b/tools/binman/test/156_mkimage.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		size = <0x80>;
+
+		mkimage {
+			args = "-n test -T script";
+
+			u-boot-spl {
+			};
+
+			_testing {
+				return-contents-later;
+			};
+		};
+	};
+};
diff --git a/tools/binman/test/157_blob_ext.dts b/tools/binman/test/157_blob_ext.dts
new file mode 100644
index 0000000..8afdd53
--- /dev/null
+++ b/tools/binman/test/157_blob_ext.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		blob-ext {
+			filename = "refcode.bin";
+		};
+	};
+};
diff --git a/tools/binman/test/158_blob_ext_missing.dts b/tools/binman/test/158_blob_ext_missing.dts
new file mode 100644
index 0000000..d315e55
--- /dev/null
+++ b/tools/binman/test/158_blob_ext_missing.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		size = <0x80>;
+
+		blob-ext {
+			filename = "missing-file";
+		};
+	};
+};
diff --git a/tools/binman/test/159_blob_ext_missing_sect.dts b/tools/binman/test/159_blob_ext_missing_sect.dts
new file mode 100644
index 0000000..5f14c54
--- /dev/null
+++ b/tools/binman/test/159_blob_ext_missing_sect.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		size = <0x80>;
+
+		section {
+			blob-ext {
+				filename = "missing-file";
+			};
+		};
+
+		blob-ext2 {
+			type = "blob-ext";
+			filename = "missing-file2";
+		};
+	};
+};
diff --git a/tools/binman/test/160_pack_overlap_zero.dts b/tools/binman/test/160_pack_overlap_zero.dts
new file mode 100644
index 0000000..731aa1c
--- /dev/null
+++ b/tools/binman/test/160_pack_overlap_zero.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		u-boot {
+		};
+
+		fill {
+			size = <0>;
+			offset = <3>;
+		};
+	};
+};
diff --git a/tools/binman/test/161_fit.dts b/tools/binman/test/161_fit.dts
new file mode 100644
index 0000000..c52d760
--- /dev/null
+++ b/tools/binman/test/161_fit.dts
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		u-boot {
+		};
+		fit {
+			description = "test-desc";
+			#address-cells = <1>;
+
+			images {
+				kernel {
+					description = "Vanilla Linux kernel";
+					type = "kernel";
+					arch = "ppc";
+					os = "linux";
+					compression = "gzip";
+					load = <00000000>;
+					entry = <00000000>;
+					hash-1 {
+						algo = "crc32";
+					};
+					hash-2 {
+						algo = "sha1";
+					};
+					u-boot {
+					};
+				};
+				fdt-1 {
+					description = "Flattened Device Tree blob";
+					type = "flat_dt";
+					arch = "ppc";
+					compression = "none";
+					hash-1 {
+						algo = "crc32";
+					};
+					hash-2 {
+						algo = "sha1";
+					};
+					u-boot-spl-dtb {
+					};
+				};
+			};
+
+			configurations {
+				default = "conf-1";
+				conf-1 {
+					description = "Boot Linux kernel with FDT blob";
+					kernel = "kernel";
+					fdt = "fdt-1";
+				};
+			};
+		};
+		u-boot-nodtb {
+		};
+	};
+};
diff --git a/tools/binman/test/162_fit_external.dts b/tools/binman/test/162_fit_external.dts
new file mode 100644
index 0000000..19518e0
--- /dev/null
+++ b/tools/binman/test/162_fit_external.dts
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		u-boot {
+		};
+		fit {
+			fit,external-offset = <0>;
+			description = "test-desc";
+			#address-cells = <1>;
+
+			images {
+				kernel {
+					description = "Vanilla Linux kernel";
+					type = "kernel";
+					arch = "ppc";
+					os = "linux";
+					compression = "gzip";
+					load = <00000000>;
+					entry = <00000000>;
+					hash-1 {
+						algo = "crc32";
+					};
+					hash-2 {
+						algo = "sha1";
+					};
+					u-boot {
+					};
+				};
+				fdt-1 {
+					description = "Flattened Device Tree blob";
+					type = "flat_dt";
+					arch = "ppc";
+					compression = "none";
+					hash-1 {
+						algo = "crc32";
+					};
+					hash-2 {
+						algo = "sha1";
+					};
+					_testing {
+						return-contents-later;
+					};
+				};
+			};
+
+			configurations {
+				default = "conf-1";
+				conf-1 {
+					description = "Boot Linux kernel with FDT blob";
+					kernel = "kernel";
+					fdt = "fdt-1";
+				};
+			};
+		};
+		u-boot-nodtb {
+		};
+	};
+};
diff --git a/tools/binman/test/163_x86_rom_me_empty.dts b/tools/binman/test/163_x86_rom_me_empty.dts
new file mode 100644
index 0000000..9349d2d
--- /dev/null
+++ b/tools/binman/test/163_x86_rom_me_empty.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		sort-by-offset;
+		end-at-4gb;
+		size = <0x800000>;
+		intel-descriptor {
+			filename = "descriptor-empty.bin";
+		};
+
+		intel-me {
+			filename = "me.bin";
+			offset-unset;
+		};
+	};
+};
diff --git a/tools/binman/test/164_x86_rom_me_missing.dts b/tools/binman/test/164_x86_rom_me_missing.dts
new file mode 100644
index 0000000..dce3be5
--- /dev/null
+++ b/tools/binman/test/164_x86_rom_me_missing.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		sort-by-offset;
+		end-at-4gb;
+		size = <0x800000>;
+		intel-descriptor {
+			filename = "descriptor-missing.bin";
+		};
+
+		intel-me {
+			filename = "me.bin";
+			offset-unset;
+		};
+	};
+};
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
index 188490b..d058c59 100644
--- a/tools/dtoc/fdt.py
+++ b/tools/dtoc/fdt.py
@@ -207,7 +207,8 @@
             if auto_resize:
                 while fdt_obj.setprop(node.Offset(), self.name, self.bytes,
                                     (libfdt.NOSPACE,)) == -libfdt.NOSPACE:
-                    fdt_obj.resize(fdt_obj.totalsize() + 1024)
+                    fdt_obj.resize(fdt_obj.totalsize() + 1024 +
+                                   len(self.bytes))
                     fdt_obj.setprop(node.Offset(), self.name, self.bytes)
             else:
                 fdt_obj.setprop(node.Offset(), self.name, self.bytes)
@@ -410,6 +411,18 @@
             val = val.encode('utf-8')
         self._CheckProp(prop_name).props[prop_name].SetData(val + b'\0')
 
+    def AddData(self, prop_name, val):
+        """Add a new property to a node
+
+        The device tree is marked dirty so that the value will be written to
+        the blob on the next sync.
+
+        Args:
+            prop_name: Name of property to add
+            val: Bytes value of property
+        """
+        self.props[prop_name] = Prop(self, None, prop_name, val)
+
     def AddString(self, prop_name, val):
         """Add a new string property to a node
 
@@ -422,7 +435,7 @@
         """
         if sys.version_info[0] >= 3:  # pragma: no cover
             val = bytes(val, 'utf-8')
-        self.props[prop_name] = Prop(self, None, prop_name, val + b'\0')
+        self.AddData(prop_name, val + b'\0')
 
     def AddSubnode(self, name):
         """Add a new subnode to the node
diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py
index 375e906..b4f9b7f 100755
--- a/tools/dtoc/test_fdt.py
+++ b/tools/dtoc/test_fdt.py
@@ -417,6 +417,10 @@
         self.node.SetData('empty', b'123')
         self.assertEqual(b'123', prop.bytes)
 
+        # Trying adding a lot of data at once
+        self.node.AddData('data', tools.GetBytes(65, 20000))
+        self.dtb.Sync(auto_resize=True)
+
     def testFromData(self):
         dtb2 = fdt.Fdt.FromData(self.dtb.GetContents())
         self.assertEqual(dtb2.GetContents(), self.dtb.GetContents())
diff --git a/tools/fit_image.c b/tools/fit_image.c
index a082d93..df310b5 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -53,7 +53,7 @@
 	}
 
 	/* for first image creation, add a timestamp at offset 0 i.e., root  */
-	if (params->datafile) {
+	if (params->datafile || params->reset_timestamp) {
 		time_t time = imagetool_get_source_date(params->cmdname,
 							sbuf.st_mtime);
 		ret = fit_set_timestamp(ptr, 0, time);
diff --git a/tools/imagetool.h b/tools/imagetool.h
index f54809c..acbc48e 100644
--- a/tools/imagetool.h
+++ b/tools/imagetool.h
@@ -81,6 +81,7 @@
 	unsigned int external_offset;	/* Add padding to external data */
 	int bl_len;		/* Block length in byte for external data */
 	const char *engine_id;	/* Engine to use for signing */
+	bool reset_timestamp;	/* Reset the timestamp on an existing image */
 };
 
 /*
diff --git a/tools/mkimage.c b/tools/mkimage.c
index 7cb666d..43078d0 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -145,7 +145,7 @@
 	int opt;
 
 	while ((opt = getopt(argc, argv,
-			     "a:A:b:B:c:C:d:D:e:Ef:Fk:i:K:ln:N:p:O:rR:qsT:vVx")) != -1) {
+		   "a:A:b:B:c:C:d:D:e:Ef:Fk:i:K:ln:N:p:O:rR:qstT:vVx")) != -1) {
 		switch (opt) {
 		case 'a':
 			params.addr = strtoull(optarg, &ptr, 16);
@@ -269,6 +269,9 @@
 		case 's':
 			params.skipcpy = 1;
 			break;
+		case 't':
+			params.reset_timestamp = 1;
+			break;
 		case 'T':
 			if (strcmp(optarg, "list") == 0) {
 				show_valid_options(IH_TYPE);
diff --git a/tools/patman/checkpatch.py b/tools/patman/checkpatch.py
index 07c3e27..263bac3 100644
--- a/tools/patman/checkpatch.py
+++ b/tools/patman/checkpatch.py
@@ -41,6 +41,12 @@
 def CheckPatch(fname, verbose=False, show_types=False):
     """Run checkpatch.pl on a file.
 
+    Args:
+        fname: Filename to check
+        verbose: True to print out every line of the checkpatch output as it is
+            parsed
+        show_types: Tell checkpatch to show the type (number) of each message
+
     Returns:
         namedtuple containing:
             ok: False=failure, True=ok
diff --git a/tools/patman/commit.py b/tools/patman/commit.py
index 48d0529..8d583c4 100644
--- a/tools/patman/commit.py
+++ b/tools/patman/commit.py
@@ -2,6 +2,7 @@
 # Copyright (c) 2011 The Chromium OS Authors.
 #
 
+import collections
 import re
 
 # Separates a tag: at the beginning of the subject from the rest of it
@@ -23,6 +24,9 @@
         notes: List of lines in the commit (not series) notes
         change_id: the Change-Id: tag that was stripped from this commit
             and can be used to generate the Message-Id.
+        rtags: Response tags (e.g. Reviewed-by) collected by the commit, dict:
+            key: rtag type (e.g. 'Reviewed-by')
+            value: Set of people who gave that rtag, each a name/email string
     """
     def __init__(self, hash):
         self.hash = hash
@@ -33,6 +37,7 @@
         self.signoff_set = set()
         self.notes = []
         self.change_id = None
+        self.rtags = collections.defaultdict(set)
 
     def AddChange(self, version, info):
         """Add a new change line to the change list for a version.
@@ -88,3 +93,12 @@
           return False
         self.signoff_set.add(signoff)
         return True
+
+    def AddRtag(self, rtag_type, who):
+        """Add a response tag to a commit
+
+        Args:
+            key: rtag type (e.g. 'Reviewed-by')
+            who: Person who gave that rtag, e.g. 'Fred Bloggs <fred@bloggs.org>'
+        """
+        self.rtags[rtag_type].add(who)
diff --git a/tools/patman/control.py b/tools/patman/control.py
new file mode 100644
index 0000000..67e8f39
--- /dev/null
+++ b/tools/patman/control.py
@@ -0,0 +1,178 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2020 Google LLC
+#
+"""Handles the main control logic of patman
+
+This module provides various functions called by the main program to implement
+the features of patman.
+"""
+
+import os
+import sys
+
+from patman import checkpatch
+from patman import gitutil
+from patman import patchstream
+from patman import terminal
+
+def setup():
+    """Do required setup before doing anything"""
+    gitutil.Setup()
+
+def prepare_patches(col, branch, count, start, end, ignore_binary):
+    """Figure out what patches to generate, then generate them
+
+    The patch files are written to the current directory, e.g. 0001_xxx.patch
+    0002_yyy.patch
+
+    Args:
+        col (terminal.Color): Colour output object
+        branch (str): Branch to create patches from (None = current)
+        count (int): Number of patches to produce, or -1 to produce patches for
+            the current branch back to the upstream commit
+        start (int): Start partch to use (0=first / top of branch)
+        end (int): End patch to use (0=last one in series, 1=one before that,
+            etc.)
+        ignore_binary (bool): Don't generate patches for binary files
+
+    Returns:
+        Tuple:
+            Series object for this series (set of patches)
+            Filename of the cover letter as a string (None if none)
+            patch_files: List of patch filenames, each a string, e.g.
+                ['0001_xxx.patch', '0002_yyy.patch']
+    """
+    if count == -1:
+        # Work out how many patches to send if we can
+        count = (gitutil.CountCommitsToBranch(branch) - start)
+
+    if not count:
+        str = 'No commits found to process - please use -c flag, or run:\n' \
+              '  git branch --set-upstream-to remote/branch'
+        sys.exit(col.Color(col.RED, str))
+
+    # Read the metadata from the commits
+    to_do = count - end
+    series = patchstream.GetMetaData(branch, start, to_do)
+    cover_fname, patch_files = gitutil.CreatePatches(
+        branch, start, to_do, ignore_binary, series)
+
+    # Fix up the patch files to our liking, and insert the cover letter
+    patchstream.FixPatches(series, patch_files)
+    if cover_fname and series.get('cover'):
+        patchstream.InsertCoverLetter(cover_fname, series, to_do)
+    return series, cover_fname, patch_files
+
+def check_patches(series, patch_files, run_checkpatch, verbose):
+    """Run some checks on a set of patches
+
+    This santiy-checks the patman tags like Series-version and runs the patches
+    through checkpatch
+
+    Args:
+        series (Series): Series object for this series (set of patches)
+        patch_files (list): List of patch filenames, each a string, e.g.
+            ['0001_xxx.patch', '0002_yyy.patch']
+        run_checkpatch (bool): True to run checkpatch.pl
+        verbose (bool): True to print out every line of the checkpatch output as
+            it is parsed
+
+    Returns:
+        bool: True if the patches had no errors, False if they did
+    """
+    # Do a few checks on the series
+    series.DoChecks()
+
+    # Check the patches, and run them through 'git am' just to be sure
+    if run_checkpatch:
+        ok = checkpatch.CheckPatches(verbose, patch_files)
+    else:
+        ok = True
+    return ok
+
+
+def email_patches(col, series, cover_fname, patch_files, process_tags, its_a_go,
+                  ignore_bad_tags, add_maintainers, limit, dry_run, in_reply_to,
+                  thread, smtp_server):
+    """Email patches to the recipients
+
+    This emails out the patches and cover letter using 'git send-email'. Each
+    patch is copied to recipients identified by the patch tag and output from
+    the get_maintainer.pl script. The cover letter is copied to all recipients
+    of any patch.
+
+    To make this work a CC file is created holding the recipients for each patch
+    and the cover letter. See the main program 'cc_cmd' for this logic.
+
+    Args:
+        col (terminal.Color): Colour output object
+        series (Series): Series object for this series (set of patches)
+        cover_fname (str): Filename of the cover letter as a string (None if
+            none)
+        patch_files (list): List of patch filenames, each a string, e.g.
+            ['0001_xxx.patch', '0002_yyy.patch']
+        process_tags (bool): True to process subject tags in each patch, e.g.
+            for 'dm: spi: Add SPI support' this would be 'dm' and 'spi'. The
+            tags are looked up in the configured sendemail.aliasesfile and also
+            in ~/.patman (see README)
+        its_a_go (bool): True if we are going to actually send the patches,
+            False if the patches have errors and will not be sent unless
+            @ignore_errors
+        ignore_bad_tags (bool): True to just print a warning for unknown tags,
+            False to halt with an error
+        add_maintainers (bool): Run the get_maintainer.pl script for each patch
+        limit (int): Limit on the number of people that can be cc'd on a single
+            patch or the cover letter (None if no limit)
+        dry_run (bool): Don't actually email the patches, just print out what
+            would be sent
+        in_reply_to (str): If not None we'll pass this to git as --in-reply-to.
+            Should be a message ID that this is in reply to.
+        thread (bool): True to add --thread to git send-email (make all patches
+            reply to cover-letter or first patch in series)
+        smtp_server (str): SMTP server to use to send patches (None for default)
+    """
+    cc_file = series.MakeCcFile(process_tags, cover_fname, not ignore_bad_tags,
+                                add_maintainers, limit)
+
+    # Email the patches out (giving the user time to check / cancel)
+    cmd = ''
+    if its_a_go:
+        cmd = gitutil.EmailPatches(
+            series, cover_fname, patch_files, dry_run, not ignore_bad_tags,
+            cc_file, in_reply_to=in_reply_to, thread=thread,
+            smtp_server=smtp_server)
+    else:
+        print(col.Color(col.RED, "Not sending emails due to errors/warnings"))
+
+    # For a dry run, just show our actions as a sanity check
+    if dry_run:
+        series.ShowActions(patch_files, cmd, process_tags)
+        if not its_a_go:
+            print(col.Color(col.RED, "Email would not be sent"))
+
+    os.remove(cc_file)
+
+def send(args):
+    """Create, check and send patches by email
+
+    Args:
+        args (argparse.Namespace): Arguments to patman
+    """
+    setup()
+    col = terminal.Color()
+    series, cover_fname, patch_files = prepare_patches(
+        col, args.branch, args.count, args.start, args.end,
+        args.ignore_binary)
+    ok = check_patches(series, patch_files, args.check_patch,
+                       args.verbose)
+
+    ok = ok and gitutil.CheckSuppressCCConfig()
+
+    its_a_go = ok or args.ignore_errors
+    if its_a_go:
+        email_patches(
+            col, series, cover_fname, patch_files, args.process_tags,
+            its_a_go, args.ignore_bad_tags, args.add_maintainers,
+            args.limit, args.dry_run, args.in_reply_to, args.thread,
+            args.smtp_server)
diff --git a/tools/patman/func_test.py b/tools/patman/func_test.py
index dc30078..810af9c 100644
--- a/tools/patman/func_test.py
+++ b/tools/patman/func_test.py
@@ -14,15 +14,23 @@
 
 from io import StringIO
 
+from patman import control
 from patman import gitutil
 from patman import patchstream
 from patman import settings
+from patman import terminal
 from patman import tools
+from patman.test_util import capture_sys_output
 
+try:
+    import pygit2
+    HAVE_PYGIT2= True
+except ModuleNotFoundError:
+    HAVE_PYGIT2 = False
+
 
 @contextlib.contextmanager
 def capture():
-    import sys
     oldout,olderr = sys.stdout, sys.stderr
     try:
         out=[StringIO(), StringIO()]
@@ -37,6 +45,8 @@
 class TestFunctional(unittest.TestCase):
     def setUp(self):
         self.tmpdir = tempfile.mkdtemp(prefix='patman.')
+        self.gitdir = os.path.join(self.tmpdir, 'git')
+        self.repo = None
 
     def tearDown(self):
         shutil.rmtree(self.tmpdir)
@@ -286,3 +296,160 @@
             if expected:
                 expected = expected.splitlines()
                 self.assertEqual(expected, lines[start:(start+len(expected))])
+
+    def make_commit_with_file(self, subject, body, fname, text):
+        """Create a file and add it to the git repo with a new commit
+
+        Args:
+            subject (str): Subject for the commit
+            body (str): Body text of the commit
+            fname (str): Filename of file to create
+            text (str): Text to put into the file
+        """
+        path = os.path.join(self.gitdir, fname)
+        tools.WriteFile(path, text, binary=False)
+        index = self.repo.index
+        index.add(fname)
+        author =  pygit2.Signature('Test user', 'test@email.com')
+        committer = author
+        tree = index.write_tree()
+        message = subject + '\n' + body
+        self.repo.create_commit('HEAD', author, committer, message, tree,
+                                [self.repo.head.target])
+
+    def make_git_tree(self):
+        """Make a simple git tree suitable for testing
+
+        It has three branches:
+            'base' has two commits: PCI, main
+            'first' has base as upstream and two more commits: I2C, SPI
+            'second' has base as upstream and three more: video, serial, bootm
+
+        Returns:
+            pygit2 repository
+        """
+        repo = pygit2.init_repository(self.gitdir)
+        self.repo = repo
+        new_tree = repo.TreeBuilder().write()
+
+        author = pygit2.Signature('Test user', 'test@email.com')
+        committer = author
+        commit = repo.create_commit('HEAD', author, committer,
+                                         'Created master', new_tree, [])
+
+        self.make_commit_with_file('Initial commit', '''
+Add a README
+
+''', 'README', '''This is the README file
+describing this project
+in very little detail''')
+
+        self.make_commit_with_file('pci: PCI implementation', '''
+Here is a basic PCI implementation
+
+''', 'pci.c', '''This is a file
+it has some contents
+and some more things''')
+        self.make_commit_with_file('main: Main program', '''
+Hello here is the second commit.
+''', 'main.c', '''This is the main file
+there is very little here
+but we can always add more later
+if we want to
+
+Series-to: u-boot
+Series-cc: Barry Crump <bcrump@whataroa.nz>
+''')
+        base_target = repo.revparse_single('HEAD')
+        self.make_commit_with_file('i2c: I2C things', '''
+This has some stuff to do with I2C
+''', 'i2c.c', '''And this is the file contents
+with some I2C-related things in it''')
+        self.make_commit_with_file('spi: SPI fixes', '''
+SPI needs some fixes
+and here they are
+''', 'spi.c', '''Some fixes for SPI in this
+file to make SPI work
+better than before''')
+        first_target = repo.revparse_single('HEAD')
+
+        target = repo.revparse_single('HEAD~2')
+        repo.reset(target.oid, pygit2.GIT_CHECKOUT_FORCE)
+        self.make_commit_with_file('video: Some video improvements', '''
+Fix up the video so that
+it looks more purple. Purple is
+a very nice colour.
+''', 'video.c', '''More purple here
+Purple and purple
+Even more purple
+Could not be any more purple''')
+        self.make_commit_with_file('serial: Add a serial driver', '''
+Here is the serial driver
+for my chip.
+
+Cover-letter:
+Series for my board
+This series implements support
+for my glorious board.
+END
+''', 'serial.c', '''The code for the
+serial driver is here''')
+        self.make_commit_with_file('bootm: Make it boot', '''
+This makes my board boot
+with a fix to the bootm
+command
+''', 'bootm.c', '''Fix up the bootm
+command to make the code as
+complicated as possible''')
+        second_target = repo.revparse_single('HEAD')
+
+        repo.branches.local.create('first', first_target)
+        repo.config.set_multivar('branch.first.remote', '', '.')
+        repo.config.set_multivar('branch.first.merge', '', 'refs/heads/base')
+
+        repo.branches.local.create('second', second_target)
+        repo.config.set_multivar('branch.second.remote', '', '.')
+        repo.config.set_multivar('branch.second.merge', '', 'refs/heads/base')
+
+        repo.branches.local.create('base', base_target)
+        return repo
+
+    @unittest.skipIf(not HAVE_PYGIT2, 'Missing python3-pygit2')
+    def testBranch(self):
+        """Test creating patches from a branch"""
+        repo = self.make_git_tree()
+        target = repo.lookup_reference('refs/heads/first')
+        self.repo.checkout(target, strategy=pygit2.GIT_CHECKOUT_FORCE)
+        control.setup()
+        try:
+            orig_dir = os.getcwd()
+            os.chdir(self.gitdir)
+
+            # Check that it can detect the current branch
+            self.assertEqual(2, gitutil.CountCommitsToBranch(None))
+            col = terminal.Color()
+            with capture_sys_output() as _:
+                _, cover_fname, patch_files = control.prepare_patches(
+                    col, branch=None, count=-1, start=0, end=0,
+                    ignore_binary=False)
+            self.assertIsNone(cover_fname)
+            self.assertEqual(2, len(patch_files))
+
+            # Check that it can detect a different branch
+            self.assertEqual(3, gitutil.CountCommitsToBranch('second'))
+            with capture_sys_output() as _:
+                _, cover_fname, patch_files = control.prepare_patches(
+                    col, branch='second', count=-1, start=0, end=0,
+                    ignore_binary=False)
+            self.assertIsNotNone(cover_fname)
+            self.assertEqual(3, len(patch_files))
+
+            # Check that it can skip patches at the end
+            with capture_sys_output() as _:
+                _, cover_fname, patch_files = control.prepare_patches(
+                    col, branch='second', count=-1, start=0, end=1,
+                    ignore_binary=False)
+            self.assertIsNotNone(cover_fname)
+            self.assertEqual(2, len(patch_files))
+        finally:
+            os.chdir(orig_dir)
diff --git a/tools/patman/gitutil.py b/tools/patman/gitutil.py
index 5189840..192d8e6 100644
--- a/tools/patman/gitutil.py
+++ b/tools/patman/gitutil.py
@@ -49,17 +49,24 @@
     cmd.append('--')
     return cmd
 
-def CountCommitsToBranch():
+def CountCommitsToBranch(branch):
     """Returns number of commits between HEAD and the tracking branch.
 
     This looks back to the tracking branch and works out the number of commits
     since then.
 
+    Args:
+        branch: Branch to count from (None for current branch)
+
     Return:
         Number of patches that exist on top of the branch
     """
-    pipe = [LogCmd('@{upstream}..', oneline=True),
-            ['wc', '-l']]
+    if branch:
+        us, msg = GetUpstream('.git', branch)
+        rev_range = '%s..%s' % (us, branch)
+    else:
+        rev_range = '@{upstream}..'
+    pipe = [LogCmd(rev_range, oneline=True), ['wc', '-l']]
     stdout = command.RunPipe(pipe, capture=True, oneline=True).stdout
     patch_count = int(stdout)
     return patch_count
@@ -252,17 +259,20 @@
     if result.return_code != 0:
         raise OSError('git fetch: %s' % result.stderr)
 
-def CreatePatches(start, count, ignore_binary, series):
+def CreatePatches(branch, start, count, ignore_binary, series):
     """Create a series of patches from the top of the current branch.
 
     The patch files are written to the current directory using
     git format-patch.
 
     Args:
+        branch: Branch to create patches from (None for current branch)
         start: Commit to start from: 0=HEAD, 1=next one, etc.
         count: number of commits to include
+        ignore_binary: Don't generate patches for binary files
+        series: Series object for this series (set of patches)
     Return:
-        Filename of cover letter
+        Filename of cover letter (None if none)
         List of filenames of patch files
     """
     if series.get('version'):
@@ -275,7 +285,8 @@
     prefix = series.GetPatchPrefix()
     if prefix:
         cmd += ['--subject-prefix=%s' % prefix]
-    cmd += ['HEAD~%d..HEAD~%d' % (start + count, start)]
+    brname = branch or 'HEAD'
+    cmd += ['%s~%d..%s~%d' % (brname, start + count, brname, start)]
 
     stdout = command.RunList(cmd)
     files = stdout.splitlines()
@@ -333,6 +344,31 @@
         return ['%s %s%s%s' % (tag, quote, email, quote) for email in result]
     return result
 
+def CheckSuppressCCConfig():
+    """Check if sendemail.suppresscc is configured correctly.
+
+    Returns:
+        True if the option is configured correctly, False otherwise.
+    """
+    suppresscc = command.OutputOneLine('git', 'config', 'sendemail.suppresscc',
+                                       raise_on_error=False)
+
+    # Other settings should be fine.
+    if suppresscc == 'all' or suppresscc == 'cccmd':
+        col = terminal.Color()
+
+        print((col.Color(col.RED, "error") +
+            ": git config sendemail.suppresscc set to %s\n"  % (suppresscc)) +
+            "  patman needs --cc-cmd to be run to set the cc list.\n" +
+            "  Please run:\n" +
+            "    git config --unset sendemail.suppresscc\n" +
+            "  Or read the man page:\n" +
+            "    git send-email --help\n" +
+            "  and set an option that runs --cc-cmd\n")
+        return False
+
+    return True
+
 def EmailPatches(series, cover_fname, args, dry_run, raise_on_error, cc_fname,
         self_only=False, alias=None, in_reply_to=None, thread=False,
         smtp_server=None):
diff --git a/tools/patman/main.py b/tools/patman/main.py
index 28a9a26..b960008 100755
--- a/tools/patman/main.py
+++ b/tools/patman/main.py
@@ -6,10 +6,11 @@
 
 """See README for more information"""
 
-from optparse import OptionParser
+from argparse import ArgumentParser
 import os
 import re
 import sys
+import traceback
 import unittest
 
 if __name__ == "__main__":
@@ -18,76 +19,93 @@
     sys.path.append(os.path.join(our_path, '..'))
 
 # Our modules
-from patman import checkpatch
 from patman import command
+from patman import control
 from patman import gitutil
-from patman import patchstream
 from patman import project
 from patman import settings
 from patman import terminal
+from patman import test_util
 from patman import test_checkpatch
 
+def AddCommonArgs(parser):
+    parser.add_argument('-b', '--branch', type=str,
+        help="Branch to process (by default, the current branch)")
+    parser.add_argument('-c', '--count', dest='count', type=int,
+        default=-1, help='Automatically create patches from top n commits')
+    parser.add_argument('-e', '--end', type=int, default=0,
+        help='Commits to skip at end of patch list')
+    parser.add_argument('-D', '--debug', action='store_true',
+        help='Enabling debugging (provides a full traceback on error)')
+    parser.add_argument('-s', '--start', dest='start', type=int,
+        default=0, help='Commit to start creating patches from (0 = HEAD)')
 
-parser = OptionParser()
-parser.add_option('-H', '--full-help', action='store_true', dest='full_help',
+epilog = '''Create patches from commits in a branch, check them and email them
+as specified by tags you place in the commits. Use -n to do a dry run first.'''
+
+parser = ArgumentParser(epilog=epilog)
+subparsers = parser.add_subparsers(dest='cmd')
+send = subparsers.add_parser('send')
+send.add_argument('-H', '--full-help', action='store_true', dest='full_help',
        default=False, help='Display the README file')
-parser.add_option('-c', '--count', dest='count', type='int',
-       default=-1, help='Automatically create patches from top n commits')
-parser.add_option('-i', '--ignore-errors', action='store_true',
+send.add_argument('-i', '--ignore-errors', action='store_true',
        dest='ignore_errors', default=False,
        help='Send patches email even if patch errors are found')
-parser.add_option('-l', '--limit-cc', dest='limit', type='int',
-       default=None, help='Limit the cc list to LIMIT entries [default: %default]')
-parser.add_option('-m', '--no-maintainers', action='store_false',
+send.add_argument('-l', '--limit-cc', dest='limit', type=int, default=None,
+       help='Limit the cc list to LIMIT entries [default: %(default)s]')
+send.add_argument('-m', '--no-maintainers', action='store_false',
        dest='add_maintainers', default=True,
        help="Don't cc the file maintainers automatically")
-parser.add_option('-n', '--dry-run', action='store_true', dest='dry_run',
+send.add_argument('-n', '--dry-run', action='store_true', dest='dry_run',
        default=False, help="Do a dry run (create but don't email patches)")
-parser.add_option('-p', '--project', default=project.DetectProject(),
+send.add_argument('-p', '--project', default=project.DetectProject(),
                   help="Project name; affects default option values and "
-                  "aliases [default: %default]")
-parser.add_option('-r', '--in-reply-to', type='string', action='store',
+                  "aliases [default: %(default)s]")
+send.add_argument('-r', '--in-reply-to', type=str, action='store',
                   help="Message ID that this series is in reply to")
-parser.add_option('-s', '--start', dest='start', type='int',
-       default=0, help='Commit to start creating patches from (0 = HEAD)')
-parser.add_option('-t', '--ignore-bad-tags', action='store_true',
+send.add_argument('-t', '--ignore-bad-tags', action='store_true',
                   default=False, help='Ignore bad tags / aliases')
-parser.add_option('-v', '--verbose', action='store_true', dest='verbose',
+send.add_argument('-v', '--verbose', action='store_true', dest='verbose',
        default=False, help='Verbose output of errors and warnings')
-parser.add_option('-T', '--thread', action='store_true', dest='thread',
+send.add_argument('-T', '--thread', action='store_true', dest='thread',
                   default=False, help='Create patches as a single thread')
-parser.add_option('--cc-cmd', dest='cc_cmd', type='string', action='store',
+send.add_argument('--cc-cmd', dest='cc_cmd', type=str, action='store',
        default=None, help='Output cc list for patch file (used by git)')
-parser.add_option('--no-binary', action='store_true', dest='ignore_binary',
+send.add_argument('--no-binary', action='store_true', dest='ignore_binary',
                   default=False,
                   help="Do not output contents of changes in binary files")
-parser.add_option('--no-check', action='store_false', dest='check_patch',
+send.add_argument('--no-check', action='store_false', dest='check_patch',
                   default=True,
                   help="Don't check for patch compliance")
-parser.add_option('--no-tags', action='store_false', dest='process_tags',
+send.add_argument('--no-tags', action='store_false', dest='process_tags',
                   default=True, help="Don't process subject tags as aliases")
-parser.add_option('--smtp-server', type='str',
+send.add_argument('--smtp-server', type=str,
                   help="Specify the SMTP server to 'git send-email'")
-parser.add_option('--test', action='store_true', dest='test',
-                  default=False, help='run tests')
-
-parser.usage += """
+AddCommonArgs(send)
 
-Create patches from commits in a branch, check them and email them as
-specified by tags you place in the commits. Use -n to do a dry run first."""
+send.add_argument('patchfiles', nargs='*')
 
+test_parser = subparsers.add_parser('test', help='Run tests')
+AddCommonArgs(test_parser)
 
 # Parse options twice: first to get the project and second to handle
 # defaults properly (which depends on project).
-(options, args) = parser.parse_args()
-settings.Setup(gitutil, parser, options.project, '')
-(options, args) = parser.parse_args()
+argv = sys.argv[1:]
+if len(argv) < 1 or argv[0].startswith('-'):
+    argv = ['send'] + argv
+args = parser.parse_args(argv)
+if hasattr(args, 'project'):
+    settings.Setup(gitutil, send, args.project, '')
+    args = parser.parse_args(argv)
 
 if __name__ != "__main__":
     pass
 
+if not args.debug:
+    sys.tracebacklimit = 0
+
 # Run our meagre tests
-elif options.test:
+if args.cmd == 'test':
     import doctest
     from patman import func_test
 
@@ -101,87 +119,31 @@
         suite = doctest.DocTestSuite(module)
         suite.run(result)
 
-    # TODO: Surely we can just 'print' result?
-    print(result)
-    for test, err in result.errors:
-        print(err)
-    for test, err in result.failures:
-        print(err)
-
-# Called from git with a patch filename as argument
-# Printout a list of additional CC recipients for this patch
-elif options.cc_cmd:
-    fd = open(options.cc_cmd, 'r')
-    re_line = re.compile('(\S*) (.*)')
-    for line in fd.readlines():
-        match = re_line.match(line)
-        if match and match.group(1) == args[0]:
-            for cc in match.group(2).split('\0'):
-                cc = cc.strip()
-                if cc:
-                    print(cc)
-    fd.close()
-
-elif options.full_help:
-    pager = os.getenv('PAGER')
-    if not pager:
-        pager = 'more'
-    fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
-                         'README')
-    command.Run(pager, fname)
+    sys.exit(test_util.ReportResult('patman', None, result))
 
 # Process commits, produce patches files, check them, email them
-else:
-    gitutil.Setup()
-
-    if options.count == -1:
-        # Work out how many patches to send if we can
-        options.count = gitutil.CountCommitsToBranch() - options.start
-
-    col = terminal.Color()
-    if not options.count:
-        str = 'No commits found to process - please use -c flag'
-        sys.exit(col.Color(col.RED, str))
+elif args.cmd == 'send':
+    # Called from git with a patch filename as argument
+    # Printout a list of additional CC recipients for this patch
+    if args.cc_cmd:
+        fd = open(args.cc_cmd, 'r')
+        re_line = re.compile('(\S*) (.*)')
+        for line in fd.readlines():
+            match = re_line.match(line)
+            if match and match.group(1) == args.patchfiles[0]:
+                for cc in match.group(2).split('\0'):
+                    cc = cc.strip()
+                    if cc:
+                        print(cc)
+        fd.close()
 
-    # Read the metadata from the commits
-    if options.count:
-        series = patchstream.GetMetaData(options.start, options.count)
-        cover_fname, args = gitutil.CreatePatches(options.start, options.count,
-                options.ignore_binary, series)
+    elif args.full_help:
+        pager = os.getenv('PAGER')
+        if not pager:
+            pager = 'more'
+        fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
+                             'README')
+        command.Run(pager, fname)
 
-    # Fix up the patch files to our liking, and insert the cover letter
-    patchstream.FixPatches(series, args)
-    if cover_fname and series.get('cover'):
-        patchstream.InsertCoverLetter(cover_fname, series, options.count)
-
-    # Do a few checks on the series
-    series.DoChecks()
-
-    # Check the patches, and run them through 'git am' just to be sure
-    if options.check_patch:
-        ok = checkpatch.CheckPatches(options.verbose, args)
     else:
-        ok = True
-
-    cc_file = series.MakeCcFile(options.process_tags, cover_fname,
-                                not options.ignore_bad_tags,
-                                options.add_maintainers, options.limit)
-
-    # Email the patches out (giving the user time to check / cancel)
-    cmd = ''
-    its_a_go = ok or options.ignore_errors
-    if its_a_go:
-        cmd = gitutil.EmailPatches(series, cover_fname, args,
-                options.dry_run, not options.ignore_bad_tags, cc_file,
-                in_reply_to=options.in_reply_to, thread=options.thread,
-                smtp_server=options.smtp_server)
-    else:
-        print(col.Color(col.RED, "Not sending emails due to errors/warnings"))
-
-    # For a dry run, just show our actions as a sanity check
-    if options.dry_run:
-        series.ShowActions(args, cmd, options.process_tags)
-        if not its_a_go:
-            print(col.Color(col.RED, "Email would not be sent"))
-
-    os.remove(cc_file)
+        control.send(args)
diff --git a/tools/patman/patchstream.py b/tools/patman/patchstream.py
index 4fe465e..ba0a13f 100644
--- a/tools/patman/patchstream.py
+++ b/tools/patman/patchstream.py
@@ -37,7 +37,7 @@
 re_commit_tag = re.compile('^Commit-([a-z-]*): *(.*)')
 
 # Commit tags that we want to collect and keep
-re_tag = re.compile('^(Tested-by|Acked-by|Reviewed-by|Patch-cc): (.*)')
+re_tag = re.compile('^(Tested-by|Acked-by|Reviewed-by|Patch-cc|Fixes): (.*)')
 
 # The start of a new commit in the git log
 re_commit = re.compile('^commit ([0-9a-f]*)$')
@@ -112,6 +112,15 @@
             self.in_section = 'commit-' + name
             self.skip_blank = False
 
+    def AddCommitRtag(self, rtag_type, who):
+        """Add a response tag to the current commit
+
+        Args:
+            key: rtag type (e.g. 'Reviewed-by')
+            who: Person who gave that rtag, e.g. 'Fred Bloggs <fred@bloggs.org>'
+        """
+        self.commit.AddRtag(rtag_type, who)
+
     def CloseCommit(self):
         """Save the current commit into our commit list, and reset our state"""
         if self.commit and self.is_log:
@@ -260,6 +269,10 @@
             else:
                 self.section.append(line)
 
+        # If we are not in a section, it is an unexpected END
+        elif line == 'END':
+                raise ValueError("'END' wihout section")
+
         # Detect the commit subject
         elif not is_blank and self.state == STATE_PATCH_SUBJECT:
             self.commit.subject = line
@@ -338,6 +351,9 @@
             elif name == 'changes':
                 self.in_change = 'Commit'
                 self.change_version = self.ParseVersion(value, line)
+            else:
+                self.warn.append('Line %d: Ignoring Commit-%s' %
+                    (self.linenum, name))
 
         # Detect the start of a new commit
         elif commit_match:
@@ -346,12 +362,14 @@
 
         # Detect tags in the commit message
         elif tag_match:
+            rtag_type, who = tag_match.groups()
+            self.AddCommitRtag(rtag_type, who)
             # Remove Tested-by self, since few will take much notice
-            if (tag_match.group(1) == 'Tested-by' and
-                    tag_match.group(2).find(os.getenv('USER') + '@') != -1):
+            if (rtag_type == 'Tested-by' and
+                    who.find(os.getenv('USER') + '@') != -1):
                 self.warn.append("Ignoring %s" % line)
-            elif tag_match.group(1) == 'Patch-cc':
-                self.commit.AddCc(tag_match.group(2).split(','))
+            elif rtag_type == 'Patch-cc':
+                self.commit.AddCc(who.split(','))
             else:
                 out = [line]
 
@@ -512,17 +530,19 @@
     ps.Finalize()
     return series
 
-def GetMetaData(start, count):
+def GetMetaData(branch, start, count):
     """Reads out patch series metadata from the commits
 
     This does a 'git log' on the relevant commits and pulls out the tags we
     are interested in.
 
     Args:
-        start: Commit to start from: 0=HEAD, 1=next one, etc.
+        branch: Branch to use (None for current branch)
+        start: Commit to start from: 0=branch HEAD, 1=next one, etc.
         count: Number of commits to list
     """
-    return GetMetaDataForList('HEAD~%d' % start, None, count)
+    return GetMetaDataForList('%s~%d' % (branch if branch else 'HEAD', start),
+                              None, count)
 
 def GetMetaDataForTest(text):
     """Process metadata from a file containing a git log. Used for tests
diff --git a/tools/patman/series.py b/tools/patman/series.py
index b7eef37..9f885c8 100644
--- a/tools/patman/series.py
+++ b/tools/patman/series.py
@@ -244,7 +244,7 @@
             add_maintainers: Either:
                 True/False to call the get_maintainers to CC maintainers
                 List of maintainers to include (for testing)
-            limit: Limit the length of the Cc list
+            limit: Limit the length of the Cc list (None if no limit)
         Return:
             Filename of temp file created
         """
diff --git a/tools/patman/settings.py b/tools/patman/settings.py
index 635561a..732bd40 100644
--- a/tools/patman/settings.py
+++ b/tools/patman/settings.py
@@ -233,17 +233,19 @@
         config: An instance of _ProjectConfigParser that we will query
             for settings.
     """
-    defaults = parser.get_default_values()
+    defaults = parser.parse_known_args()[0]
+    defaults = vars(defaults)
     for name, val in config.items('settings'):
-        if hasattr(defaults, name):
-            default_val = getattr(defaults, name)
+        if name in defaults:
+            default_val = defaults[name]
             if isinstance(default_val, bool):
                 val = config.getboolean('settings', name)
             elif isinstance(default_val, int):
                 val = config.getint('settings', name)
-            parser.set_default(name, val)
+            defaults[name] = val
         else:
             print("WARNING: Unknown setting %s" % name)
+        parser.set_defaults(**defaults)
 
 def _ReadAliasFile(fname):
     """Read in the U-Boot git alias file if it exists.
diff --git a/tools/patman/terminal.py b/tools/patman/terminal.py
index c709438..60dbce3 100644
--- a/tools/patman/terminal.py
+++ b/tools/patman/terminal.py
@@ -122,7 +122,7 @@
     return out
 
 
-def Print(text='', newline=True, colour=None, limit_to_line=False):
+def Print(text='', newline=True, colour=None, limit_to_line=False, bright=True):
     """Handle a line of output to the terminal.
 
     In test mode this is recorded in a list. Otherwise it is output to the
@@ -140,7 +140,7 @@
     else:
         if colour:
             col = Color()
-            text = col.Color(colour, text)
+            text = col.Color(colour, text, bright=bright)
         if newline:
             print(text)
             last_print_len = None
diff --git a/tools/patman/test_util.py b/tools/patman/test_util.py
index aac58fb..4e26175 100644
--- a/tools/patman/test_util.py
+++ b/tools/patman/test_util.py
@@ -16,12 +16,14 @@
 
 use_concurrent = True
 try:
-    from concurrencytest import ConcurrentTestSuite, fork_for_tests
+    from concurrencytest.concurrencytest import ConcurrentTestSuite
+    from concurrencytest.concurrencytest import fork_for_tests
 except:
     use_concurrent = False
 
 
-def RunTestCoverage(prog, filter_fname, exclude_list, build_dir, required=None):
+def RunTestCoverage(prog, filter_fname, exclude_list, build_dir, required=None,
+                    extra_args=None):
     """Run tests and check that we get 100% coverage
 
     Args:
@@ -34,6 +36,8 @@
             calculation
         build_dir: Build directory, used to locate libfdt.py
         required: List of modules which must be in the coverage report
+        extra_args (str): Extra arguments to pass to the tool before the -t/test
+            arg
 
     Raises:
         ValueError if the code coverage is not 100%
@@ -47,13 +51,14 @@
         glob_list = []
     glob_list += exclude_list
     glob_list += ['*libfdt.py', '*site-packages*', '*dist-packages*']
-    test_cmd = 'test' if 'binman' in prog else '-t'
+    glob_list += ['*concurrencytest*']
+    test_cmd = 'test' if 'binman' in prog or 'patman' in prog else '-t'
     prefix = ''
     if build_dir:
         prefix = 'PYTHONPATH=$PYTHONPATH:%s/sandbox_spl/tools ' % build_dir
     cmd = ('%spython3-coverage run '
-           '--omit "%s" %s %s -P1' % (prefix, ','.join(glob_list),
-                                      prog, test_cmd))
+           '--omit "%s" %s %s %s -P1' % (prefix, ','.join(glob_list),
+                                         prog, extra_args or '', test_cmd))
     os.system(cmd)
     stdout = command.Output('python3-coverage', 'report')
     lines = stdout.splitlines()
@@ -123,12 +128,12 @@
     for test, err in result.failures:
         print(err, result.failures)
     if result.skipped:
-        print('%d binman test%s SKIPPED:' %
-              (len(result.skipped), 's' if len(result.skipped) > 1 else ''))
+        print('%d %s test%s SKIPPED:' % (len(result.skipped), toolname,
+            's' if len(result.skipped) > 1 else ''))
         for skip_info in result.skipped:
             print('%s: %s' % (skip_info[0], skip_info[1]))
     if result.errors or result.failures:
-        print('binman tests FAILED')
+        print('%s tests FAILED' % toolname)
         return 1
     return 0
 
diff --git a/tools/patman/tools.py b/tools/patman/tools.py
index b50370d..d41115a 100644
--- a/tools/patman/tools.py
+++ b/tools/patman/tools.py
@@ -114,14 +114,16 @@
     indir = dirname
     tout.Debug("Using input directories %s" % indir)
 
-def GetInputFilename(fname):
+def GetInputFilename(fname, allow_missing=False):
     """Return a filename for use as input.
 
     Args:
         fname: Filename to use for new file
+        allow_missing: True if the filename can be missing
 
     Returns:
-        The full path of the filename, within the input directory
+        The full path of the filename, within the input directory, or
+        None on error
     """
     if not indir or fname[:1] == '/':
         return fname
@@ -130,6 +132,8 @@
         if os.path.exists(pathname):
             return pathname
 
+    if allow_missing:
+        return None
     raise ValueError("Filename '%s' not found in input path (%s) (cwd='%s')" %
                      (fname, ','.join(indir), os.getcwd()))
 
@@ -270,7 +274,7 @@
                    #(fname, len(data), len(data)))
     return data
 
-def WriteFile(fname, data):
+def WriteFile(fname, data, binary=True):
     """Write data into a file.
 
     Args:
@@ -279,7 +283,7 @@
     """
     #self._out.Info("Write file '%s' size %d (%#0x)" %
                    #(fname, len(data), len(data)))
-    with open(Filename(fname), 'wb') as fd:
+    with open(Filename(fname), binary and 'wb' or 'w') as fd:
         fd.write(data)
 
 def GetBytes(byte, size):
diff --git a/tools/patman/tout.py b/tools/patman/tout.py
index c7e3272..3330526 100644
--- a/tools/patman/tout.py
+++ b/tools/patman/tout.py
@@ -83,7 +83,10 @@
         ClearProgress()
         if color:
             msg = _color.Color(color, msg)
-        print(msg)
+        if level < NOTICE:
+            print(msg, file=sys.stderr)
+        else:
+            print(msg)
 
 def DoOutput(level, msg):
     """Output a message to the terminal.
@@ -168,6 +171,7 @@
 
     # TODO(sjg): Move this into Chromite libraries when we have them
     stdout_is_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()
+    stderr_is_tty = hasattr(sys.stderr, 'isatty') and sys.stderr.isatty()
 
 def Uninit():
     ClearProgress()