Merge branch '2019-10-11-ti-imports'

- Various improvements to dra7xx, keystone 3, am65x SoCs
- Platform updates
- remoteproc improvements
diff --git a/arch/arm/dts/am335x-guardian.dts b/arch/arm/dts/am335x-guardian.dts
index f3f022c..5ed2133 100644
--- a/arch/arm/dts/am335x-guardian.dts
+++ b/arch/arm/dts/am335x-guardian.dts
@@ -32,12 +32,19 @@
 	gpio_keys {
 		compatible = "gpio-keys";
 		pinctrl-names = "default";
-		pinctrl-0 = <&gpio_keys_pins>;
+		pinctrl-0 = <&guardian_button_pins>;
 
-		button21 {
+		select-button {
+			label = "guardian-select-button";
+			linux,code = <KEY_5>;
+			gpios = <&gpio1 31 GPIO_ACTIVE_LOW>;
+			wakeup-source;
+		};
+
+		power-button {
 			label = "guardian-power-button";
 			linux,code = <KEY_POWER>;
-			gpios = <&gpio2 21 0>;
+			gpios = <&gpio2 21 GPIO_ACTIVE_LOW>;
 			wakeup-source;
 		};
 	};
@@ -45,19 +52,12 @@
 	leds {
 		compatible = "gpio-leds";
 		pinctrl-names = "default";
-		pinctrl-0 = <&leds_pins>;
-
-		led1 {
-			label = "green:heartbeat";
-			gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>;
-			linux,default-trigger = "heartbeat";
-			default-state = "off";
-		};
+		pinctrl-0 = <&guardian_led_pins>;
 
-		led2 {
-			label = "green:mmc0";
+		life-led {
+			label = "guardian:life-led";
 			gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
-			linux,default-trigger = "mmc0";
+			linux,default-trigger = "heartbeat";
 			default-state = "off";
 		};
 	};
@@ -140,22 +140,25 @@
 		gpmc,device-width = <1>;
 		gpmc,sync-clk-ps = <0>;
 		gpmc,cs-on-ns = <0>;
-		gpmc,cs-rd-off-ns = <44>;
-		gpmc,cs-wr-off-ns = <44>;
-		gpmc,adv-on-ns = <6>;
-		gpmc,adv-rd-off-ns = <34>;
-		gpmc,adv-wr-off-ns = <44>;
+		gpmc,cs-rd-off-ns = <30>;
+		gpmc,cs-wr-off-ns = <30>;
+		gpmc,adv-on-ns = <0>;
+		gpmc,adv-rd-off-ns = <30>;
+		gpmc,adv-wr-off-ns = <30>;
 		gpmc,we-on-ns = <0>;
-		gpmc,we-off-ns = <40>;
-		gpmc,oe-on-ns = <0>;
-		gpmc,oe-off-ns = <54>;
-		gpmc,access-ns = <64>;
-		gpmc,rd-cycle-ns = <82>;
-		gpmc,wr-cycle-ns = <82>;
+		gpmc,we-off-ns = <15>;
+		gpmc,oe-on-ns = <1>;
+		gpmc,oe-off-ns = <15>;
+		gpmc,access-ns = <30>;
+		gpmc,rd-cycle-ns = <30>;
+		gpmc,wr-cycle-ns = <30>;
+		gpmc,wait-on-read = "true";
+		gpmc,wait-on-write = "true";
 		gpmc,bus-turnaround-ns = <0>;
 		gpmc,cycle2cycle-delay-ns = <0>;
 		gpmc,clk-activation-ns = <0>;
-		gpmc,wr-access-ns = <40>;
+		gpmc,wait-monitoring-ns = <0>;
+		gpmc,wr-access-ns = <0>;
 		gpmc,wr-data-mux-bus-ns = <0>;
 
 		/*
@@ -199,18 +202,8 @@
 		};
 
 		partition@6 {
-			label = "u-boot-env";
-			reg = <0x300000 0x40000>;
-		};
-
-		partition@7 {
-			label = "u-boot-env.backup1";
-			reg = <0x340000 0x40000>;
-		};
-
-		partition@8 {
 			label = "UBI";
-			reg = <0x380000 0x1fc80000>;
+			reg = <0x300000 0x1fd00000>;
 		};
 	};
 };
@@ -326,6 +319,12 @@
 	status = "okay";
 };
 
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_pins>;
+	status = "okay";
+};
+
 &usb {
 	status = "okay";
 };
@@ -354,7 +353,7 @@
 
 &am33xx_pinmux {
 	pinctrl-names = "default";
-	pinctrl-0 = <&clkout2_pin &gpio_pins>;
+	pinctrl-0 = <&clkout2_pin &guardian_interface_pins>;
 
 	clkout2_pin: pinmux_clkout2_pin {
 		pinctrl-single,pins = <
@@ -368,16 +367,25 @@
 		>;
 	};
 
-	gpio_keys_pins: pinmux_gpio_keys_pins {
+	guardian_button_pins: pinmux_gpio_keys_pins {
 		pinctrl-single,pins = <
 			AM33XX_IOPAD(0x940, PIN_INPUT | MUX_MODE7)
+			AM33XX_IOPAD(0x884, PIN_INPUT | MUX_MODE7)
 		>;
 	};
 
-	gpio_pins: pinmux_gpio_pins {
+	guardian_interface_pins: pinmux_guardian_interface_pins {
 		pinctrl-single,pins = <
-			AM33XX_IOPAD(0x928, PIN_OUTPUT | MUX_MODE7)
-			AM33XX_IOPAD(0x990, PIN_OUTPUT | MUX_MODE7)
+			AM33XX_IOPAD(0x928, PIN_OUTPUT          | MUX_MODE7)
+			AM33XX_IOPAD(0x990, PIN_OUTPUT          | MUX_MODE7)
+			AM33XX_IOPAD(0x9ac, PIN_OUTPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x980, PIN_INPUT           | MUX_MODE7)
+			AM33XX_IOPAD(0x984, PIN_INPUT           | MUX_MODE7)
+			AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLUP   | MUX_MODE7)
+			AM33XX_IOPAD(0x90c, PIN_OUTPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x944, PIN_OUTPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x91c, PIN_INPUT           | MUX_MODE7)
+			AM33XX_IOPAD(0x918, PIN_OUTPUT_PULLDOWN | MUX_MODE7)
 		>;
 	};
 
@@ -452,10 +460,9 @@
 		>;
 	};
 
-	leds_pins: pinmux_leds_pins {
+	guardian_led_pins: pinmux_leds_pins {
 		pinctrl-single,pins = <
 			AM33XX_IOPAD(0x868, PIN_OUTPUT | MUX_MODE7)
-			AM33XX_IOPAD(0x86c, PIN_OUTPUT | MUX_MODE7)
 		>;
 	};
 
@@ -487,6 +494,13 @@
 		>;
 	};
 
+	uart2_pins: pinmux_uart2_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE1)
+			AM33XX_IOPAD(0x930, PIN_OUTPUT_PULLDOWN | MUX_MODE1)
+		>;
+	};
+
 	nandflash_pins: pinmux_nandflash_pins {
 		pinctrl-single,pins = <
 			AM33XX_IOPAD(0x800, PIN_INPUT | MUX_MODE0)
diff --git a/arch/arm/dts/am335x-icev2-u-boot.dtsi b/arch/arm/dts/am335x-icev2-u-boot.dtsi
new file mode 100644
index 0000000..cc9569a
--- /dev/null
+++ b/arch/arm/dts/am335x-icev2-u-boot.dtsi
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ */
+/ {
+	xtal25mhz: xtal25mhz {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+};
+
+&i2c0 {
+	cdce913: cdce913@65 {
+		compatible = "ti,cdce913";
+		reg = <0x65>;
+		clocks = <&xtal25mhz>;
+		#clock-cells = <1>;
+		xtal-load-pf = <0>;
+	};
+};
diff --git a/arch/arm/dts/am437x-idk-evm-u-boot.dtsi b/arch/arm/dts/am437x-idk-evm-u-boot.dtsi
index 3aa9195..50fe09c 100644
--- a/arch/arm/dts/am437x-idk-evm-u-boot.dtsi
+++ b/arch/arm/dts/am437x-idk-evm-u-boot.dtsi
@@ -9,6 +9,12 @@
 	ocp {
 		u-boot,dm-spl;
 	};
+
+	xtal25mhz: xtal25mhz {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
 };
 
 &uart0 {
@@ -17,6 +23,14 @@
 
 &i2c0 {
 	u-boot,dm-spl;
+
+	cdce913: cdce913@65 {
+		compatible = "ti,cdce913";
+		reg = <0x65>;
+		clocks = <&xtal25mhz>;
+		#clock-cells = <1>;
+		xtal-load-pf = <0>;
+	};
 };
 
 &mmc1 {
diff --git a/arch/arm/dts/am571x-idk-u-boot.dtsi b/arch/arm/dts/am571x-idk-u-boot.dtsi
new file mode 100644
index 0000000..6519920
--- /dev/null
+++ b/arch/arm/dts/am571x-idk-u-boot.dtsi
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ */
+#include "am57xx-idk-common-u-boot.dtsi"
diff --git a/arch/arm/dts/am572x-idk-u-boot.dtsi b/arch/arm/dts/am572x-idk-u-boot.dtsi
new file mode 100644
index 0000000..6519920
--- /dev/null
+++ b/arch/arm/dts/am572x-idk-u-boot.dtsi
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ */
+#include "am57xx-idk-common-u-boot.dtsi"
diff --git a/arch/arm/dts/am574x-idk-u-boot.dtsi b/arch/arm/dts/am574x-idk-u-boot.dtsi
new file mode 100644
index 0000000..6519920
--- /dev/null
+++ b/arch/arm/dts/am574x-idk-u-boot.dtsi
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ */
+#include "am57xx-idk-common-u-boot.dtsi"
diff --git a/arch/arm/dts/am57xx-idk-common-u-boot.dtsi b/arch/arm/dts/am57xx-idk-common-u-boot.dtsi
new file mode 100644
index 0000000..b07aea0
--- /dev/null
+++ b/arch/arm/dts/am57xx-idk-common-u-boot.dtsi
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ */
+#include "omap5-u-boot.dtsi"
+
+/ {
+	xtal25mhz: xtal25mhz {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+};
+
+&i2c1 {
+	cdce913: cdce913@65 {
+		compatible = "ti,cdce913";
+		reg = <0x65>;
+		clocks = <&xtal25mhz>;
+		#clock-cells = <1>;
+		xtal-load-pf = <0>;
+	};
+};
diff --git a/arch/arm/dts/k3-am65-mcu.dtsi b/arch/arm/dts/k3-am65-mcu.dtsi
index c9bfd9b..c42e755 100644
--- a/arch/arm/dts/k3-am65-mcu.dtsi
+++ b/arch/arm/dts/k3-am65-mcu.dtsi
@@ -2,7 +2,7 @@
 /*
  * Device Tree Source for AM6 SoC Family MCU Domain peripherals
  *
- * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2016-2019 Texas Instruments Incorporated - http://www.ti.com/
  */
 
 &cbass_mcu {
@@ -26,4 +26,42 @@
 		clocks = <&k3_clks 114 1>;
 		power-domains = <&k3_pds 114 TI_SCI_PD_EXCLUSIVE>;
 	};
+
+	mcu_r5fss0: r5fss@41000000 {
+		compatible = "ti,am654-r5fss";
+		lockstep-mode = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x41000000 0x00 0x41000000 0x20000>,
+			 <0x41400000 0x00 0x41400000 0x20000>;
+		power-domains = <&k3_pds 129 TI_SCI_PD_EXCLUSIVE>;
+
+		mcu_r5fss0_core0: r5f@41000000 {
+			compatible = "ti,am654-r5f";
+			reg = <0x41000000 0x00008000>,
+			      <0x41010000 0x00008000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <159>;
+			ti,sci-proc-ids = <0x01 0xFF>;
+			resets = <&k3_reset 159 1>;
+			atcm-enable = <1>;
+			btcm-enable = <1>;
+			loczrama = <1>;
+		};
+
+		mcu_r5fss0_core1: r5f@41400000 {
+			compatible = "ti,am654-r5f";
+			reg = <0x41400000 0x00008000>,
+			      <0x41410000 0x00008000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <245>;
+			ti,sci-proc-ids = <0x02 0xFF>;
+			resets = <&k3_reset 245 1>;
+			atcm-enable = <1>;
+			btcm-enable = <1>;
+			loczrama = <1>;
+		};
+	};
 };
diff --git a/arch/arm/dts/k3-am654-base-board.dts b/arch/arm/dts/k3-am654-base-board.dts
index e73b9aa..573ead0 100644
--- a/arch/arm/dts/k3-am654-base-board.dts
+++ b/arch/arm/dts/k3-am654-base-board.dts
@@ -17,6 +17,11 @@
 		bootargs = "earlycon=ns16550a,mmio32,0x02800000";
 	};
 
+	aliases {
+		remoteproc0 = &mcu_r5fss0_core0;
+		remoteproc1 = &mcu_r5fss0_core1;
+	};
+
 	memory@80000000 {
 		device_type = "memory";
 		/* 4G RAM */
diff --git a/arch/arm/dts/k3-am654-r5-base-board.dts b/arch/arm/dts/k3-am654-r5-base-board.dts
index 7ed307f..e31ed4f 100644
--- a/arch/arm/dts/k3-am654-r5-base-board.dts
+++ b/arch/arm/dts/k3-am654-r5-base-board.dts
@@ -16,6 +16,7 @@
 
 	aliases {
 		serial0 = &wkup_uart0;
+		serial1 = &mcu_uart0;
 		serial2 = &main_uart0;
 	};
 
@@ -118,6 +119,14 @@
 	status = "okay";
 };
 
+&mcu_uart0 {
+	u-boot,dm-spl;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_uart0_pins_default>;
+	clock-frequency = <48000000>;
+	status = "okay";
+};
+
 &main_uart0 {
 	power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
 };
@@ -141,6 +150,16 @@
 		u-boot,dm-spl;
 	};
 
+	mcu_uart0_pins_default: mcu_uart0_pins_default {
+		pinctrl-single,pins = <
+			AM65X_WKUP_IOPAD(0x0044, PIN_INPUT, 4)	/* (P4) MCU_OSPI1_D1.MCU_UART0_RXD */
+			AM65X_WKUP_IOPAD(0x0048, PIN_OUTPUT, 4)	/* (P5) MCU_OSPI1_D2.MCU_UART0_TXD */
+			AM65X_WKUP_IOPAD(0x004C, PIN_INPUT, 4)	/* (P1) MCU_OSPI1_D3.MCU_UART0_CTSn */
+			AM65X_WKUP_IOPAD(0x0054, PIN_OUTPUT, 4)	/* (N3) MCU_OSPI1_CSn1.MCU_UART0_RTSn */
+		>;
+		u-boot,dm-spl;
+	};
+
 	wkup_i2c0_pins_default: wkup-i2c0-pins-default {
 		pinctrl-single,pins = <
 			AM65X_WKUP_IOPAD(0x00e0, PIN_INPUT, 0) /* (AC7) WKUP_I2C0_SCL */
diff --git a/arch/arm/dts/k3-j721e-common-proc-board.dts b/arch/arm/dts/k3-j721e-common-proc-board.dts
index b5b8c3c..c978cab 100644
--- a/arch/arm/dts/k3-j721e-common-proc-board.dts
+++ b/arch/arm/dts/k3-j721e-common-proc-board.dts
@@ -12,6 +12,18 @@
 		stdout-path = "serial2:115200n8";
 		bootargs = "console=ttyS2,115200n8 earlycon=ns16550a,mmio32,0x02800000";
 	};
+
+	aliases {
+		remoteproc0 = &mcu_r5fss0_core0;
+		remoteproc1 = &mcu_r5fss0_core1;
+		remoteproc2 = &main_r5fss0_core0;
+		remoteproc3 = &main_r5fss0_core1;
+		remoteproc4 = &main_r5fss1_core0;
+		remoteproc5 = &main_r5fss1_core1;
+		remoteproc6 = &c66_0;
+		remoteproc7 = &c66_1;
+		remoteproc8 = &c71_0;
+	};
 };
 
 &wkup_uart0 {
@@ -19,6 +31,10 @@
 	status = "disabled";
 };
 
+&main_uart0 {
+	power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
+};
+
 &main_uart3 {
 	/* UART not brought out */
 	status = "disabled";
diff --git a/arch/arm/dts/k3-j721e-main.dtsi b/arch/arm/dts/k3-j721e-main.dtsi
index 3445784..6bd59ba 100644
--- a/arch/arm/dts/k3-j721e-main.dtsi
+++ b/arch/arm/dts/k3-j721e-main.dtsi
@@ -228,4 +228,115 @@
 		ti,trm-icp = <0x8>;
 		dma-coherent;
 	};
+
+	main_r5fss0: r5fss@5c00000 {
+		compatible = "ti,j721e-r5fss";
+		lockstep-mode = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x5c00000 0x00 0x5c00000 0x20000>,
+			 <0x5d00000 0x00 0x5d00000 0x20000>;
+		power-domains = <&k3_pds 243 TI_SCI_PD_EXCLUSIVE>;
+
+		main_r5fss0_core0: r5f@5c00000 {
+			compatible = "ti,j721e-r5f";
+			reg = <0x5c00000 0x00008000>,
+			      <0x5c10000 0x00008000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <245>;
+			ti,sci-proc-ids = <0x06 0xFF>;
+			resets = <&k3_reset 245 1>;
+			atcm-enable = <1>;
+			btcm-enable = <1>;
+			loczrama = <1>;
+		};
+
+		main_r5fss0_core1: r5f@5d00000 {
+			compatible = "ti,j721e-r5f";
+			reg = <0x5d00000 0x00008000>,
+			      <0x5d10000 0x00008000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <246>;
+			ti,sci-proc-ids = <0x07 0xFF>;
+			resets = <&k3_reset 246 1>;
+			atcm-enable = <1>;
+			btcm-enable = <1>;
+			loczrama = <1>;
+		};
+	};
+
+	main_r5fss1: r5fss@5e00000 {
+		compatible = "ti,j721e-r5fss";
+		lockstep-mode = <1>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x5e00000 0x00 0x5e00000 0x20000>,
+			 <0x5f00000 0x00 0x5f00000 0x20000>;
+		power-domains = <&k3_pds 244 TI_SCI_PD_EXCLUSIVE>;
+
+		main_r5fss1_core0: r5f@5e00000 {
+			compatible = "ti,j721e-r5f";
+			reg = <0x5e00000 0x00008000>,
+			      <0x5e10000 0x00008000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <247>;
+			ti,sci-proc-ids = <0x08 0xFF>;
+			resets = <&k3_reset 247 1>;
+			atcm-enable = <1>;
+			btcm-enable = <1>;
+			loczrama = <1>;
+		};
+
+		main_r5fss1_core1: r5f@5f00000 {
+			compatible = "ti,j721e-r5f";
+			reg = <0x5f00000 0x00008000>,
+			      <0x5f10000 0x00008000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <248>;
+			ti,sci-proc-ids = <0x09 0xFF>;
+			resets = <&k3_reset 248 1>;
+			atcm-enable = <1>;
+			btcm-enable = <1>;
+			loczrama = <1>;
+		};
+	};
+
+	c66_0: dsp@4d80800000 {
+		compatible = "ti,j721e-c66-dsp";
+		reg = <0x4d 0x80800000 0x00 0x00048000>,
+		      <0x4d 0x80e00000 0x00 0x00008000>,
+		      <0x4d 0x80f00000 0x00 0x00008000>;
+		reg-names = "l2sram", "l1pram", "l1dram";
+		ti,sci = <&dmsc>;
+		ti,sci-dev-id = <142>;
+		ti,sci-proc-ids = <0x03 0xFF>;
+		resets = <&k3_reset 142 1>;
+	};
+
+	c66_1: dsp@4d81800000 {
+		compatible = "ti,j721e-c66-dsp";
+		reg = <0x4d 0x81800000 0x00 0x00048000>,
+		      <0x4d 0x81e00000 0x00 0x00008000>,
+		      <0x4d 0x81f00000 0x00 0x00008000>;
+		reg-names = "l2sram", "l1pram", "l1dram";
+		ti,sci = <&dmsc>;
+		ti,sci-dev-id = <143>;
+		ti,sci-proc-ids = <0x04 0xFF>;
+		resets = <&k3_reset 143 1>;
+	};
+
+	c71_0: dsp@64800000 {
+		compatible = "ti,j721e-c71-dsp";
+		reg = <0x00 0x64800000 0x00 0x00080000>,
+		      <0x00 0x64e00000 0x00 0x0000c000>;
+		reg-names = "l2sram", "l1dram";
+		ti,sci = <&dmsc>;
+		ti,sci-dev-id = <15>;
+		ti,sci-proc-ids = <0x30 0xFF>;
+		resets = <&k3_reset 15 1>;
+	};
 };
diff --git a/arch/arm/dts/k3-j721e-mcu-wakeup.dtsi b/arch/arm/dts/k3-j721e-mcu-wakeup.dtsi
index 1175fa9..b958b5b 100644
--- a/arch/arm/dts/k3-j721e-mcu-wakeup.dtsi
+++ b/arch/arm/dts/k3-j721e-mcu-wakeup.dtsi
@@ -69,4 +69,42 @@
 		clocks = <&k3_clks 149 0>;
 		clock-names = "fclk";
 	};
+
+	mcu_r5fss0: r5fss@41000000 {
+		compatible = "ti,j721e-r5fss";
+		lockstep-mode = <1>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x41000000 0x00 0x41000000 0x20000>,
+			 <0x41400000 0x00 0x41400000 0x20000>;
+		power-domains = <&k3_pds 249 TI_SCI_PD_EXCLUSIVE>;
+
+		mcu_r5fss0_core0: r5f@41000000 {
+			compatible = "ti,j721e-r5f";
+			reg = <0x41000000 0x00008000>,
+			      <0x41010000 0x00008000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <250>;
+			ti,sci-proc-ids = <0x01 0xFF>;
+			resets = <&k3_reset 250 1>;
+			atcm-enable = <1>;
+			btcm-enable = <1>;
+			loczrama = <1>;
+		};
+
+		mcu_r5fss0_core1: r5f@41400000 {
+			compatible = "ti,j721e-r5f";
+			reg = <0x41400000 0x00008000>,
+			      <0x41410000 0x00008000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <251>;
+			ti,sci-proc-ids = <0x02 0xFF>;
+			resets = <&k3_reset 251 1>;
+			atcm-enable = <1>;
+			btcm-enable = <1>;
+			loczrama = <1>;
+		};
+	};
 };
diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig
index de1c1cc..5583241 100644
--- a/arch/arm/mach-k3/Kconfig
+++ b/arch/arm/mach-k3/Kconfig
@@ -66,6 +66,27 @@
 	int
 	default 16
 
+config K3_EARLY_CONS
+	bool "Activate to allow for an early console during SPL"
+	depends on SPL
+	help
+	  Turn this option on to enable an early console functionality in SPL
+	  before the main console is being brought up. This can be useful in
+	  situations where the main console is dependent on System Firmware
+	  (SYSFW) being up and running, which is usually not the case during
+	  the very early stages of boot. Using this early console functionality
+	  will allow for an alternate serial port to be used to support things
+	  like UART-based boot and early diagnostic messages until the main
+	  console is ready to get activated.
+
+config K3_EARLY_CONS_IDX
+	depends on K3_EARLY_CONS
+	int "Index of serial device to use for SPL early console"
+	default 1
+	help
+	  Use this option to set the index of the serial device to be used
+	  for the early console during SPL execution.
+
 config K3_LOAD_SYSFW
 	bool
 	depends on SPL
diff --git a/arch/arm/mach-k3/arm64-mmu.c b/arch/arm/mach-k3/arm64-mmu.c
index 82778d2..7f908ee 100644
--- a/arch/arm/mach-k3/arm64-mmu.c
+++ b/arch/arm/mach-k3/arm64-mmu.c
@@ -14,7 +14,7 @@
 
 #ifdef CONFIG_SOC_K3_AM6
 /* NR_DRAM_BANKS + 32bit IO + 64bit IO + terminator */
-#define NR_MMU_REGIONS	(CONFIG_NR_DRAM_BANKS + 3)
+#define NR_MMU_REGIONS	(CONFIG_NR_DRAM_BANKS + 5)
 
 /* ToDo: Add 64bit IO */
 struct mm_region am654_mem_map[NR_MMU_REGIONS] = {
@@ -28,7 +28,19 @@
 	}, {
 		.virt = 0x80000000UL,
 		.phys = 0x80000000UL,
-		.size = 0x80000000UL,
+		.size = 0x20000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	}, {
+		.virt = 0xa0000000UL,
+		.phys = 0xa0000000UL,
+		.size = 0x02100000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) |
+			 PTE_BLOCK_INNER_SHARE
+	}, {
+		.virt = 0xa2100000UL,
+		.phys = 0xa2100000UL,
+		.size = 0x5df00000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_INNER_SHARE
 	}, {
@@ -68,13 +80,13 @@
 	}, {
 		.virt = 0xa0000000UL,
 		.phys = 0xa0000000UL,
-		.size = 0x0bc00000UL,
+		.size = 0x1bc00000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) |
 			 PTE_BLOCK_NON_SHARE
 	}, {
-		.virt = 0xabc00000UL,
-		.phys = 0xabc00000UL,
-		.size = 0x54400000UL,
+		.virt = 0xbbc00000UL,
+		.phys = 0xbbc00000UL,
+		.size = 0x44400000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_INNER_SHARE
 	}, {
diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c
index c16afc6..f8274b3 100644
--- a/arch/arm/mach-k3/common.c
+++ b/arch/arm/mach-k3/common.c
@@ -14,19 +14,48 @@
 #include <linux/soc/ti/ti_sci_protocol.h>
 #include <fdt_support.h>
 #include <asm/arch/sys_proto.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
 
 struct ti_sci_handle *get_ti_sci_handle(void)
 {
 	struct udevice *dev;
 	int ret;
 
-	ret = uclass_get_device(UCLASS_FIRMWARE, 0, &dev);
+	ret = uclass_get_device_by_driver(UCLASS_FIRMWARE,
+					  DM_GET_DRIVER(ti_sci), &dev);
 	if (ret)
 		panic("Failed to get SYSFW (%d)\n", ret);
 
 	return (struct ti_sci_handle *)ti_sci_get_handle_from_sysfw(dev);
 }
 
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_K3_EARLY_CONS
+int early_console_init(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	gd->baudrate = CONFIG_BAUDRATE;
+
+	ret = uclass_get_device_by_seq(UCLASS_SERIAL, CONFIG_K3_EARLY_CONS_IDX,
+				       &dev);
+	if (ret) {
+		printf("Error getting serial dev for early console! (%d)\n",
+		       ret);
+		return ret;
+	}
+
+	gd->cur_serial_dev = dev;
+	gd->flags |= GD_FLG_SERIAL_READY;
+	gd->have_console = 1;
+
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_SYS_K3_SPL_ATF
 void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
 {
@@ -162,5 +191,45 @@
 #ifndef CONFIG_SYSRESET
 void reset_cpu(ulong ignored)
 {
+}
+#endif
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+	u32 soc, rev;
+	char *name;
+
+	soc = (readl(CTRLMMR_WKUP_JTAG_DEVICE_ID) &
+		DEVICE_ID_FAMILY_MASK) >> DEVICE_ID_FAMILY_SHIFT;
+	rev = (readl(CTRLMMR_WKUP_JTAG_ID) &
+		JTAG_ID_VARIANT_MASK) >> JTAG_ID_VARIANT_SHIFT;
+
+	printf("SoC:   ");
+	switch (soc) {
+	case AM654:
+		name = "AM654";
+		break;
+	case J721E:
+		name = "J721E";
+		break;
+	default:
+		name = "Unknown Silicon";
+	};
+
+	printf("%s PG ", 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);
+
+	return 0;
 }
 #endif
diff --git a/arch/arm/mach-k3/common.h b/arch/arm/mach-k3/common.h
index ac7e80d..8f9a023 100644
--- a/arch/arm/mach-k3/common.h
+++ b/arch/arm/mach-k3/common.h
@@ -8,4 +8,11 @@
 
 #include <asm/armv7_mpu.h>
 
+#define AM654	2
+#define J721E	4
+
+#define REV_PG1_0	0
+#define REV_PG2_0	1
+
 void setup_k3_mpu_regions(void);
+int early_console_init(void);
diff --git a/arch/arm/mach-k3/include/mach/hardware.h b/arch/arm/mach-k3/include/mach/hardware.h
index 4e62982..d670d5a 100644
--- a/arch/arm/mach-k3/include/mach/hardware.h
+++ b/arch/arm/mach-k3/include/mach/hardware.h
@@ -13,4 +13,22 @@
 #ifdef CONFIG_SOC_K3_J721E
 #include "j721e_hardware.h"
 #endif
+
+/* Assuming these addresses and definitions stay common across K3 devices */
+#define CTRLMMR_WKUP_JTAG_DEVICE_ID	0x43000018
+#define DEVICE_ID_FAMILY_SHIFT	26
+#define DEVICE_ID_FAMILY_MASK	(0x3f << 26)
+#define DEVICE_ID_BASE_SHIFT	11
+#define DEVICE_ID_BASE_MASK	(0x1fff << 11)
+#define DEVICE_ID_SPEED_SHIFT	6
+#define DEVICE_ID_SPEED_MASK	(0x1f << 6)
+#define DEVICE_ID_TEMP_SHIFT	3
+#define DEVICE_ID_TEMP_MASK	(0x7 << 3)
+
+#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
+#define JTAG_ID_PARTNO_MASK	(0x7ff << 1)
+
 #endif /* _ASM_ARCH_HARDWARE_H_ */
diff --git a/arch/arm/mach-k3/sysfw-loader.c b/arch/arm/mach-k3/sysfw-loader.c
index 7a482bd..5903bbe 100644
--- a/arch/arm/mach-k3/sysfw-loader.c
+++ b/arch/arm/mach-k3/sysfw-loader.c
@@ -12,6 +12,9 @@
 #include <remoteproc.h>
 #include <linux/soc/ti/ti_sci_protocol.h>
 #include <asm/arch/sys_proto.h>
+#include "common.h"
+
+DECLARE_GLOBAL_DATA_PTR;
 
 /* Name of the FIT image nodes for SYSFW and its config data */
 #define SYSFW_FIRMWARE			"sysfw.bin"
@@ -213,6 +216,24 @@
 #else
 				   0);
 #endif
+		break;
+#endif
+#if CONFIG_IS_ENABLED(YMODEM_SUPPORT)
+	case BOOT_DEVICE_UART:
+#ifdef CONFIG_K3_EARLY_CONS
+		/*
+		 * Establish a serial console if not yet available as required
+		 * for UART-based boot. For this use the early console feature
+		 * that allows setting up a UART for use before SYSFW has been
+		 * brought up. Note that the associated UART module's clocks
+		 * must have gotten enabled by the ROM bootcode which will be
+		 * the case when continuing to boot serially from the same
+		 * UART that the ROM loaded the initial bootloader from.
+		 */
+		if (!gd->have_console)
+			early_console_init();
+#endif
+		ret = spl_ymodem_load_image(&spl_image, &bootdev);
 		break;
 #endif
 	default:
diff --git a/arch/arm/mach-omap2/am33xx/Kconfig b/arch/arm/mach-omap2/am33xx/Kconfig
index 7f6b344..39d9c28 100644
--- a/arch/arm/mach-omap2/am33xx/Kconfig
+++ b/arch/arm/mach-omap2/am33xx/Kconfig
@@ -89,6 +89,7 @@
 
 config TARGET_AM335X_GUARDIAN
 	bool "Support am335x based guardian board from bosch"
+	select BOARD_LATE_INIT
 	select DM
 	select DM_SERIAL
 	select DM_GPIO
diff --git a/arch/arm/mach-omap2/emif-common.c b/arch/arm/mach-omap2/emif-common.c
index b384343..290f9dc 100644
--- a/arch/arm/mach-omap2/emif-common.c
+++ b/arch/arm/mach-omap2/emif-common.c
@@ -348,52 +348,63 @@
 static void dra7_enable_ecc(u32 base, const struct emif_regs *regs)
 {
 	struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
-	u32 rgn, size;
+	u32 rgn, rgn_start, size, ctrl_reg;
 
 	/* ECC available only on dra76x EMIF1 */
 	if ((base != EMIF1_BASE) || !is_dra76x())
 		return;
 
 	if (regs->emif_ecc_ctrl_reg & EMIF_ECC_CTRL_REG_ECC_EN_MASK) {
+		/* Disable high-order interleaving */
+		clrbits_le32(MA_PRIORITY, MA_HIMEM_INTERLEAVE_UN_MASK);
+
+#ifdef CONFIG_DRA7XX
+		/* Clear the status flags and other history */
+		writel(readl(&emif->emif_1b_ecc_err_cnt),
+		       &emif->emif_1b_ecc_err_cnt);
+		writel(0xffffffff, &emif->emif_1b_ecc_err_dist_1);
+		writel(0x2, &emif->emif_1b_ecc_err_addr_log);
+		writel(0x1, &emif->emif_2b_ecc_err_addr_log);
+		writel(EMIF_INT_WR_ECC_ERR_SYS_MASK |
+		       EMIF_INT_TWOBIT_ECC_ERR_SYS_MASK |
+		       EMIF_INT_ONEBIT_ECC_ERR_SYS_MASK,
+		       &emif->emif_irqstatus_sys);
+#endif
 		writel(regs->emif_ecc_address_range_1,
 		       &emif->emif_ecc_address_range_1);
 		writel(regs->emif_ecc_address_range_2,
 		       &emif->emif_ecc_address_range_2);
-		writel(regs->emif_ecc_ctrl_reg, &emif->emif_ecc_ctrl_reg);
+
+		/* Disable RMW and ECC verification for read accesses */
+		ctrl_reg = (regs->emif_ecc_ctrl_reg &
+			    ~EMIF_ECC_REG_RMW_EN_MASK) |
+			   EMIF_ECC_CTRL_REG_ECC_VERIFY_DIS_MASK;
+		writel(ctrl_reg, &emif->emif_ecc_ctrl_reg);
 
 		/* Set region1 memory with 0 */
-		rgn = ((regs->emif_ecc_address_range_1 &
-			EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16) +
-		       CONFIG_SYS_SDRAM_BASE;
+		rgn_start = (regs->emif_ecc_address_range_1 &
+			     EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16;
+		rgn = rgn_start + CONFIG_SYS_SDRAM_BASE;
 		size = (regs->emif_ecc_address_range_1 &
-			EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0x10000;
+			EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0x10000 - rgn_start;
 
 		if (regs->emif_ecc_ctrl_reg &
 		    EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK)
 			dra7_reset_ddr_data(rgn, size);
 
 		/* Set region2 memory with 0 */
-		rgn = ((regs->emif_ecc_address_range_2 &
-			EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16) +
-		       CONFIG_SYS_SDRAM_BASE;
+		rgn_start = (regs->emif_ecc_address_range_2 &
+			     EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16;
+		rgn = rgn_start + CONFIG_SYS_SDRAM_BASE;
 		size = (regs->emif_ecc_address_range_2 &
-			EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0x10000;
+			EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0x10000 - rgn_start;
 
 		if (regs->emif_ecc_ctrl_reg &
 		    EMIF_ECC_REG_ECC_ADDR_RGN_2_EN_MASK)
 			dra7_reset_ddr_data(rgn, size);
 
-#ifdef CONFIG_DRA7XX
-		/* Clear the status flags and other history */
-		writel(readl(&emif->emif_1b_ecc_err_cnt),
-		       &emif->emif_1b_ecc_err_cnt);
-		writel(0xffffffff, &emif->emif_1b_ecc_err_dist_1);
-		writel(0x1, &emif->emif_2b_ecc_err_addr_log);
-		writel(EMIF_INT_WR_ECC_ERR_SYS_MASK |
-		       EMIF_INT_TWOBIT_ECC_ERR_SYS_MASK |
-		       EMIF_INT_ONEBIT_ECC_ERR_SYS_MASK,
-		       &emif->emif_irqstatus_sys);
-#endif
+		/* Default value enables RMW and ECC verification */
+		writel(regs->emif_ecc_ctrl_reg, &emif->emif_ecc_ctrl_reg);
 	}
 }
 
diff --git a/arch/arm/mach-omap2/omap5/dra7xx_iodelay.c b/arch/arm/mach-omap2/omap5/dra7xx_iodelay.c
index e2abb7d..9eda57c 100644
--- a/arch/arm/mach-omap2/omap5/dra7xx_iodelay.c
+++ b/arch/arm/mach-omap2/omap5/dra7xx_iodelay.c
@@ -202,8 +202,9 @@
 		return;
 	}
 
-	if (!ret)
-		ret = isolate_io(DEISOLATE_IO);
+	/* Deisolate IO if it is already isolated */
+	if (readl((*ctrl)->ctrl_core_sma_sw_0) & CTRL_ISOLATE_MASK)
+		isolate_io(DEISOLATE_IO);
 
 	/* lock IODELAY CONFIG registers */
 	writel(CFG_IODELAY_LOCK_KEY, (*ctrl)->iodelay_config_base +
@@ -240,6 +241,12 @@
 		debug("IODELAY: IO delay recalibration successfully completed\n");
 	}
 
+	/* If there is an error during iodelay recalibration, SoC is in a bad
+	 * state. Do not progress any further.
+	 */
+	if (ret)
+		hang();
+
 	return;
 }
 
diff --git a/board/bosch/guardian/board.c b/board/bosch/guardian/board.c
index ec0c4a17..072aa4e 100644
--- a/board/bosch/guardian/board.c
+++ b/board/bosch/guardian/board.c
@@ -172,6 +172,8 @@
 
 int board_init(void)
 {
+	save_omap_boot_params();
+
 #if defined(CONFIG_HW_WATCHDOG)
 	hw_watchdog_init();
 #endif
@@ -183,3 +185,54 @@
 #endif
 	return 0;
 }
+
+#ifdef CONFIG_BOARD_LATE_INIT
+static void set_bootmode_env(void)
+{
+	char *boot_device_name = NULL;
+	char *boot_mode_gpio = "gpio@44e07000_14";
+	int   ret;
+	int   value;
+
+	struct gpio_desc boot_mode_desc;
+
+	switch (gd->arch.omap_boot_device) {
+	case BOOT_DEVICE_NAND:
+		boot_device_name = "nand";
+		break;
+	case BOOT_DEVICE_USBETH:
+		boot_device_name = "usbeth";
+		break;
+	default:
+		break;
+	}
+
+	if (boot_device_name)
+		env_set("boot_device", boot_device_name);
+
+	ret = dm_gpio_lookup_name(boot_mode_gpio, &boot_mode_desc);
+	if (ret) {
+		printf("%s is not found\n", boot_mode_gpio);
+		goto err;
+	}
+
+	ret = dm_gpio_request(&boot_mode_desc, "setup_bootmode_env");
+	if (ret && ret != -EBUSY) {
+		printf("requesting gpio: %s failed\n", boot_mode_gpio);
+		goto err;
+	}
+
+	value = dm_gpio_get_value(&boot_mode_desc);
+	value ? env_set("swi_status", "0") : env_set("swi_status", "1");
+	return;
+
+err:
+	env_set("swi_status", "err");
+}
+
+int board_late_init(void)
+{
+	set_bootmode_env();
+	return 0;
+}
+#endif /* CONFIG_BOARD_LATE_INIT */
diff --git a/board/bosch/guardian/mux.c b/board/bosch/guardian/mux.c
index 708c3e7..20a1f25 100644
--- a/board/bosch/guardian/mux.c
+++ b/board/bosch/guardian/mux.c
@@ -26,27 +26,19 @@
 	{-1},
 };
 
-static struct module_pin_mux adc_voltages_en[] = {
-	{OFFSET(mcasp0_ahclkx), (MODE(7) | PULLUP_EN)},
+static struct module_pin_mux guardian_interfaces_pin_mux[] = {
+	{OFFSET(mcasp0_ahclkx), (MODE(7) | PULLDOWN_EN)},
+	{OFFSET(mcasp0_aclkx),  (MODE(7) | PULLUP_EN)},
+	{OFFSET(mii1_txd0),     (MODE(7) | PULLUP_EN)},
+	{OFFSET(uart1_rxd),     (MODE(7) | RXACTIVE | PULLUDDIS)},
+	{OFFSET(uart1_txd),     (MODE(7) | PULLUDDIS)},
+	{OFFSET(mii1_crs),      (MODE(7) | PULLDOWN_EN)},
+	{OFFSET(rmii1_refclk),  (MODE(7) | PULLDOWN_EN)},
+	{OFFSET(mii1_txd3),     (MODE(7) | PULLUDDIS)},
+	{OFFSET(mii1_rxdv),     (MODE(7) | PULLDOWN_EN)},
 	{-1},
 };
 
-static struct module_pin_mux asp_power_en[] = {
-	{OFFSET(mcasp0_aclkx), (MODE(7) | PULLUP_EN)},
-	{-1},
-};
-
-static struct module_pin_mux switch_off_3v6_pin_mux[] = {
-	{OFFSET(mii1_txd0), (MODE(7) | PULLUP_EN)},
-	/*
-	 * The uart1 lines are made floating inputs, based on the Guardian
-	 * A2 Sample Power Supply Schematics
-	 */
-	{OFFSET(uart1_rxd), (MODE(7) | PULLUDDIS)},
-	{OFFSET(uart1_txd), (MODE(7) | PULLUDDIS)},
-	{-1},
-};
-
 #ifdef CONFIG_NAND
 static struct module_pin_mux nand_pin_mux[] = {
 	{OFFSET(gpmc_ad0),      (MODE(0) | PULLUDDIS | RXACTIVE)},
@@ -93,7 +85,5 @@
 #ifdef CONFIG_NAND
 	configure_module_pin_mux(nand_pin_mux);
 #endif
-	configure_module_pin_mux(adc_voltages_en);
-	configure_module_pin_mux(asp_power_en);
-	configure_module_pin_mux(switch_off_3v6_pin_mux);
+	configure_module_pin_mux(guardian_interfaces_pin_mux);
 }
diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c
index 7eaa6cd..499c872 100644
--- a/board/ti/am335x/board.c
+++ b/board/ti/am335x/board.c
@@ -791,6 +791,7 @@
 #ifdef CONFIG_BOARD_LATE_INIT
 int board_late_init(void)
 {
+	struct udevice *dev;
 #if !defined(CONFIG_SPL_BUILD)
 	uint8_t mac_addr[6];
 	uint32_t mac_hi, mac_lo;
@@ -871,6 +872,9 @@
 			env_set("serial#", board_serial);
 	}
 
+	/* Just probe the potentially supported cdce913 device */
+	uclass_get_device(UCLASS_CLK, 0, &dev);
+
 	return 0;
 }
 #endif
diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c
index 2e09cc2..f5ecf87 100644
--- a/board/ti/am43xx/board.c
+++ b/board/ti/am43xx/board.c
@@ -720,6 +720,7 @@
 
 int board_late_init(void)
 {
+	struct udevice *dev;
 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
 	set_board_info_env(NULL);
 
@@ -737,6 +738,10 @@
 	if (device_okay("/ocp/omap_dwc3@483c0000"))
 		enable_usb_clocks(1);
 #endif
+
+	/* Just probe the potentially supported cdce913 device */
+	uclass_get_device(UCLASS_CLK, 0, &dev);
+
 	return 0;
 }
 #endif
diff --git a/board/ti/am57xx/board.c b/board/ti/am57xx/board.c
index f78e6c2..237a834 100644
--- a/board/ti/am57xx/board.c
+++ b/board/ti/am57xx/board.c
@@ -30,6 +30,7 @@
 #include <dwc3-omap-uboot.h>
 #include <ti-usb-phy-uboot.h>
 #include <mmc.h>
+#include <dm/uclass.h>
 
 #include "../common/board_detect.h"
 #include "mux_data.h"
@@ -689,6 +690,7 @@
 {
 	setup_board_eeprom_env();
 	u8 val;
+	struct udevice *dev;
 
 	/*
 	 * DEV_CTRL.DEV_ON = 1 please - else palmas switches off in 8 seconds
@@ -720,6 +722,9 @@
 
 	am57x_idk_lcd_detect();
 
+	/* Just probe the potentially supported cdce913 device */
+	uclass_get_device(UCLASS_CLK, 0, &dev);
+
 #if !defined(CONFIG_SPL_BUILD)
 	board_ti_set_ethaddr(2);
 #endif
diff --git a/board/ti/am65x/README b/board/ti/am65x/README
index 16384e0..2e3fd9c 100644
--- a/board/ti/am65x/README
+++ b/board/ti/am65x/README
@@ -261,3 +261,35 @@
 => setenv mmcdev 0
 => setenv bootpart 0
 => boot
+
+UART:
+-----
+ROM supports booting from MCU_UART0 via X-Modem protocol. The entire UART-based
+boot process up to U-Boot (proper) prompt goes through different stages and uses
+different UART peripherals as follows:
+
+  WHO     | Loading WHAT  |  HW Module  |  Protocol
+----------+---------------+-------------+------------
+Boot ROM  |  tiboot3.bin  |  MCU_UART0  |  X-Modem(*)
+R5 SPL    |  sysfw.itb    |  MCU_UART0  |  Y-Modem(*)
+R5 SPL    |  tispl.bin    |  MAIN_UART0 |  Y-Modem
+A53 SPL   |  u-boot.img   |  MAIN_UART0 |  Y-Modem
+
+(*) Note that in addition to X/Y-Modem related protocol timeouts the DMSC
+    watchdog timeout of 3min (typ.) needs to be observed until System Firmware
+    is fully loaded (from sysfw.itb) and started.
+
+Example bash script sequence for running on a Linux host PC feeding all boot
+artifacts needed to the device:
+
+MCU_DEV=/dev/ttyUSB1
+MAIN_DEV=/dev/ttyUSB0
+
+stty -F $MCU_DEV 115200 cs8 -cstopb -parenb
+stty -F $MAIN_DEV 115200 cs8 -cstopb -parenb
+
+sb --xmodem tiboot3.bin > $MCU_DEV < $MCU_DEV
+sb --ymodem sysfw.itb > $MCU_DEV < $MCU_DEV
+sb --ymodem tispl.bin > $MAIN_DEV < $MAIN_DEV
+sleep 1
+sb --xmodem u-boot.img > $MAIN_DEV < $MAIN_DEV
diff --git a/board/ti/am65x/evm.c b/board/ti/am65x/evm.c
index ad333ad..544f872 100644
--- a/board/ti/am65x/evm.c
+++ b/board/ti/am65x/evm.c
@@ -127,6 +127,19 @@
 	return ret;
 }
 
+int checkboard(void)
+{
+	struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
+
+	if (do_board_detect())
+		/* EEPROM not populated */
+		printf("Board: %s rev %s\n", "AM6-COMPROCEVM", "E3");
+	else
+		printf("Board: %s rev %s\n", ep->name, ep->version);
+
+	return 0;
+}
+
 static void setup_board_eeprom_env(void)
 {
 	char *name = "am65x";
@@ -272,7 +285,7 @@
 		if (strncmp(ep.name, cards[i].card_name, sizeof(ep.name)))
 			continue;
 
-		printf("detected %s\n", cards[i].card_name);
+		printf("Detected: %s rev %s\n", ep.name, ep.version);
 
 		/*
 		 * Populate any MAC addresses from daughtercard into the U-Boot
diff --git a/board/ti/j721e/README b/board/ti/j721e/README
new file mode 100644
index 0000000..5be7d09
--- /dev/null
+++ b/board/ti/j721e/README
@@ -0,0 +1,227 @@
+Introduction:
+-------------
+The J721e family of SoCs are part of K3 Multicore SoC architecture platform
+targeting automotive applications. They are designed as a low power, high
+performance and highly integrated device architecture, adding significant
+enhancement on processing power, graphics capability, video and imaging
+processing, virtualization and coherent memory support.
+
+The device is partitioned into three functional domains, each containing
+specific processing cores and peripherals:
+1. Wake-up (WKUP) domain:
+	- Device Management and Security Controller (DMSC)
+2. Microcontroller (MCU) domain:
+	- Dual Core ARM Cortex-R5F processor
+3. MAIN domain:
+	- Dual core 64-bit ARM Cortex-A72
+	- 2 x Dual cortex ARM Cortex-R5 subsystem
+	- 2 x C66x Digital signal processor sub system
+	- C71x Digital signal processor sub-system with MMA.
+
+More info can be found in TRM: http://www.ti.com/lit/pdf/spruil1
+
+Boot Flow:
+----------
+Boot flow is similar to that of AM65x SoC and extending it with remoteproc
+support. Below is the pictorial representation of boot flow:
+
++------------------------------------------------------------------------+-----------------------+
+|        DMSC            |      MCU R5           |        A72            |  MAIN R5/C66x/C7x     |
++------------------------------------------------------------------------+-----------------------+
+|    +--------+          |                       |                       |                       |
+|    |  Reset |          |                       |                       |                       |
+|    +--------+          |                       |                       |                       |
+|         :              |                       |                       |                       |
+|    +--------+          |   +-----------+       |                       |                       |
+|    | *ROM*  |----------|-->| Reset rls |       |                       |                       |
+|    +--------+          |   +-----------+       |                       |                       |
+|    |        |          |         :             |                       |                       |
+|    |  ROM   |          |         :             |                       |                       |
+|    |services|          |         :             |                       |                       |
+|    |        |          |   +-------------+     |                       |                       |
+|    |        |          |   |  *R5 ROM*   |     |                       |                       |
+|    |        |          |   +-------------+     |                       |                       |
+|    |        |<---------|---|Load and auth|     |                       |                       |
+|    |        |          |   | tiboot3.bin |     |                       |                       |
+|    |        |          |   +-------------+     |                       |                       |
+|    |        |          |         :             |                       |                       |
+|    |        |          |         :             |                       |                       |
+|    |        |          |         :             |                       |                       |
+|    |        |          |   +-------------+     |                       |                       |
+|    |        |          |   |  *R5 SPL*   |     |                       |                       |
+|    |        |          |   +-------------+     |                       |                       |
+|    |        |          |   |    Load     |     |                       |                       |
+|    |        |          |   |  sysfw.itb  |     |                       |                       |
+|    | Start  |          |   +-------------+     |                       |                       |
+|    | System |<---------|---|    Start    |     |                       |                       |
+|    |Firmware|          |   |    SYSFW    |     |                       |                       |
+|    +--------+          |   +-------------+     |                       |                       |
+|        :               |   |             |     |                       |                       |
+|    +---------+         |   |   Load      |     |                       |                       |
+|    | *SYSFW* |         |   |   system    |     |                       |                       |
+|    +---------+         |   | Config data |     |                       |                       |
+|    |         |<--------|---|             |     |                       |                       |
+|    |         |         |   +-------------+     |                       |                       |
+|    |         |         |   |    DDR      |     |                       |                       |
+|    |         |         |   |   config    |     |                       |                       |
+|    |         |         |   +-------------+     |                       |                       |
+|    |         |         |   |    Load     |     |                       |                       |
+|    |         |         |   |  tispl.bin  |     |                       |                       |
+|    |         |         |   +-------------+     |                       |                       |
+|    |         |         |   |   Load R5   |     |                       |                       |
+|    |         |         |   |   firmware  |     |                       |                       |
+|    |         |         |   +-------------+     |                       |                       |
+|    |         |<--------|---| Start A72   |     |                       |                       |
+|    |         |         |   | and jump to |     |                       |                       |
+|    |         |         |   | next image  |     |                       |                       |
+|    |         |         |   +-------------+     |                       |                       |
+|    |         |         |                       |     +-----------+     |                       |
+|    |         |---------|-----------------------|---->| Reset rls |     |                       |
+|    |         |         |                       |     +-----------+     |                       |
+|    |  DMSC   |         |                       |          :            |                       |
+|    |Services |         |                       |     +-----------+     |                       |
+|    |         |<--------|-----------------------|---->|*ATF/OPTEE*|     |                       |
+|    |         |         |                       |     +-----------+     |                       |
+|    |         |         |                       |          :            |                       |
+|    |         |         |                       |     +-----------+     |                       |
+|    |         |<--------|-----------------------|---->| *A72 SPL* |     |                       |
+|    |         |         |                       |     +-----------+     |                       |
+|    |         |         |                       |     |   Load    |     |                       |
+|    |         |         |                       |     | u-boot.img|     |                       |
+|    |         |         |                       |     +-----------+     |                       |
+|    |         |         |                       |          :            |                       |
+|    |         |         |                       |     +-----------+     |                       |
+|    |         |<--------|-----------------------|---->| *U-Boot*  |     |                       |
+|    |         |         |                       |     +-----------+     |                       |
+|    |         |         |                       |     |  prompt   |     |                       |
+|    |         |         |                       |     +-----------+     |                       |
+|    |         |         |                       |     |  Load R5  |     |                       |
+|    |         |         |                       |     |  Firmware |     |                       |
+|    |         |         |                       |     +-----------+     |                       |
+|    |         |<--------|-----------------------|-----|  Start R5 |     |      +-----------+    |
+|    |         |---------|-----------------------|-----+-----------+-----|----->| R5 starts |    |
+|    |         |         |                       |     |  Load C6  |     |      +-----------+    |
+|    |         |         |                       |     |  Firmware |     |                       |
+|    |         |         |                       |     +-----------+     |                       |
+|    |         |<--------|-----------------------|-----|  Start C6 |     |      +-----------+    |
+|    |         |---------|-----------------------|-----+-----------+-----|----->| C6 starts |    |
+|    |         |         |                       |     |  Load C7  |     |      +-----------+    |
+|    |         |         |                       |     |  Firmware |     |                       |
+|    |         |         |                       |     +-----------+     |                       |
+|    |         |<--------|-----------------------|-----|  Start C7 |     |      +-----------+    |
+|    |         |---------|-----------------------|-----+-----------+-----|----->| C7 starts |    |
+|    +---------+         |                       |                       |      +-----------+    |
+|                        |                       |                       |                       |
++------------------------------------------------------------------------+-----------------------+
+
+- Here DMSC acts as master and provides all the critical services. R5/A72
+requests DMSC to get these services done as shown in the above diagram.
+
+Sources:
+--------
+1. SYSFW:
+	Tree: git://git.ti.com/processor-firmware/system-firmware-image-gen.git
+	Branch: master
+
+2. ATF:
+	Tree: https://github.com/ARM-software/arm-trusted-firmware.git
+	Branch: master
+
+3. OPTEE:
+	Tree: https://github.com/OP-TEE/optee_os.git
+	Branch: master
+
+4. U-Boot:
+	Tree: https://gitlab.denx.de/u-boot/u-boot
+	Branch: master
+
+Build procedure:
+----------------
+1. SYSFW:
+$ make CROSS_COMPILE=arm-linux-gnueabihf-
+
+2. ATF:
+$ make CROSS_COMPILE=aarch64-linux-gnu- ARCH=aarch64 PLAT=k3 TARGET_BOARD=generic SPD=opteed
+
+3. OPTEE:
+$ make PLATFORM=k3-j721e CFG_ARM64_core=y
+
+4. U-Boot:
+
+4.1. R5:
+$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- j721e_evm_r5_defconfig O=/tmp/r5
+$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=/tmp/r5
+
+4.2. A72:
+$ make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- j721e_evm_a72_defconfig O=/tmp/a72
+$ make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- ATF=<path to ATF dir>/build/k3/generic/release/bl31.bin TEE=<path to OPTEE OS dir>/out/arm-plat-k3/core/tee-pager.bin O=/tmp/a72
+
+Target Images
+--------------
+Copy the below images to an SD card and boot:
+- sysfw.itb from step 1
+- tiboot3.bin from step 4.1
+- tispl.bin, u-boot.img from 4.2
+
+Image formats:
+--------------
+
+- tiboot3.bin:
+                +-----------------------+
+                |        X.509          |
+                |      Certificate      |
+                | +-------------------+ |
+                | |                   | |
+                | |        R5         | |
+                | |   u-boot-spl.bin  | |
+                | |                   | |
+                | +-------------------+ |
+                | |                   | |
+                | |     FIT header    | |
+                | | +---------------+ | |
+                | | |               | | |
+                | | |   DTB 1...N   | | |
+                | | +---------------+ | |
+                | +-------------------+ |
+                +-----------------------+
+
+- tispl.bin
+                +-----------------------+
+                |                       |
+                |       FIT HEADER      |
+                | +-------------------+ |
+                | |                   | |
+                | |      A72 ATF      | |
+                | +-------------------+ |
+                | |                   | |
+                | |     A72 OPTEE     | |
+                | +-------------------+ |
+                | |                   | |
+                | |      A72 SPL      | |
+                | +-------------------+ |
+                | |                   | |
+                | |   SPL DTB 1...N   | |
+                | +-------------------+ |
+                +-----------------------+
+
+- sysfw.itb
+                +-----------------------+
+                |                       |
+                |       FIT HEADER      |
+                | +-------------------+ |
+                | |                   | |
+                | |     sysfw.bin     | |
+                | +-------------------+ |
+                | |                   | |
+                | |    board config   | |
+                | +-------------------+ |
+                | |                   | |
+                | |     PM config     | |
+                | +-------------------+ |
+                | |                   | |
+                | |     RM config     | |
+                | +-------------------+ |
+                | |                   | |
+                | |    Secure config  | |
+                | +-------------------+ |
+                +-----------------------+
diff --git a/cmd/ti/ddr3.c b/cmd/ti/ddr3.c
index b82cbe1..448a7f5 100644
--- a/cmd/ti/ddr3.c
+++ b/cmd/ti/ddr3.c
@@ -202,10 +202,6 @@
 	writel(val2, addr);
 
 	val3 = readl(addr);
-	printf("\tECC test: addr 0x%x, read data 0x%x, written data 0x%x, err pattern: 0x%x, read after write data 0x%x\n",
-	       addr, val1, val2, ecc_err, val3);
-
-	puts("\tECC test: Enabling DDR ECC ...\n");
 #ifdef CONFIG_ARCH_KEYSTONE
 	ecc_ctrl = ECC_START_ADDR1 | (ECC_END_ADDR1 << 16);
 	writel(ecc_ctrl, EMIF1_BASE + KS2_DDR3_ECC_ADDR_RANGE1_OFFSET);
@@ -214,6 +210,11 @@
 	writel(ecc_ctrl, &emif->emif_ecc_ctrl_reg);
 #endif
 
+	printf("\tECC test: addr 0x%x, read data 0x%x, written data 0x%x, err pattern: 0x%x, read after write data 0x%x\n",
+	       addr, val1, val2, ecc_err, val3);
+
+	puts("\tECC test: Enabled DDR ECC ...\n");
+
 	val1 = readl(addr);
 	printf("\tECC test: addr 0x%x, read data 0x%x\n", addr, val1);
 
@@ -242,8 +243,8 @@
 	if (ecc_ctrl & EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK) {
 		start_addr = ((range & EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16)
 				+ CONFIG_SYS_SDRAM_BASE;
-		end_addr = start_addr + (range & EMIF_ECC_REG_ECC_END_ADDR_MASK)
-				+ 0xFFFF;
+		end_addr = (range & EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0xFFFF +
+				CONFIG_SYS_SDRAM_BASE;
 		if ((addr >= start_addr) && (addr <= end_addr))
 			/* addr within ecc address range 1 */
 			return 1;
@@ -254,8 +255,8 @@
 		range = readl(&emif->emif_ecc_address_range_2);
 		start_addr = ((range & EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16)
 				+ CONFIG_SYS_SDRAM_BASE;
-		end_addr = start_addr + (range & EMIF_ECC_REG_ECC_END_ADDR_MASK)
-				+ 0xFFFF;
+		end_addr = (range & EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0xFFFF +
+				CONFIG_SYS_SDRAM_BASE;
 		if ((addr >= start_addr) && (addr <= end_addr))
 			/* addr within ecc address range 2 */
 			return 1;
diff --git a/common/spl/spl_ymodem.c b/common/spl/spl_ymodem.c
index 20f4260..c02c056 100644
--- a/common/spl/spl_ymodem.c
+++ b/common/spl/spl_ymodem.c
@@ -44,7 +44,8 @@
 	while (info->image_read < offset) {
 		res = xyzModem_stream_read(buf, BUF_SIZE, &err);
 		if (res <= 0)
-			return res;
+			break;
+
 		info->image_read += res;
 	}
 
@@ -57,7 +58,7 @@
 	while (info->image_read < offset + size) {
 		res = xyzModem_stream_read(buf, BUF_SIZE, &err);
 		if (res <= 0)
-			return res;
+			break;
 
 		memcpy(addr, buf, res);
 		info->image_read += res;
@@ -67,8 +68,8 @@
 	return size;
 }
 
-static int spl_ymodem_load_image(struct spl_image_info *spl_image,
-				 struct spl_boot_device *bootdev)
+int spl_ymodem_load_image(struct spl_image_info *spl_image,
+			  struct spl_boot_device *bootdev)
 {
 	ulong size = 0;
 	int err;
diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig
index 2aa9b65..93a28b2 100644
--- a/configs/am335x_evm_defconfig
+++ b/configs/am335x_evm_defconfig
@@ -77,3 +77,5 @@
 CONFIG_RSA=y
 CONFIG_LZO=y
 # CONFIG_OF_LIBFDT_OVERLAY is not set
+CONFIG_CLK=y
+CONFIG_CLK_CDCE9XX=y
diff --git a/configs/am335x_guardian_defconfig b/configs/am335x_guardian_defconfig
index 3cada51..3ce3241 100644
--- a/configs/am335x_guardian_defconfig
+++ b/configs/am335x_guardian_defconfig
@@ -6,11 +6,10 @@
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_AM33XX=y
 CONFIG_TARGET_AM335X_GUARDIAN=y
-CONFIG_SPL_MMC_SUPPORT=y
+# CONFIG_SPL_MMC_SUPPORT is not set
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
 CONFIG_ENV_SIZE=0x040000
-CONFIG_ENV_OFFSET=0x300000
 CONFIG_SPL=y
 CONFIG_BOOTSTAGE_STASH_ADDR=0x0
 CONFIG_SPL_LIBDISK_SUPPORT=y
@@ -21,6 +20,7 @@
 CONFIG_ARCH_MISC_INIT=y
 # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
 CONFIG_SPL_SEPARATE_BSS=y
+# CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR is not set
 CONFIG_SPL_ENV_SUPPORT=y
 CONFIG_SPL_ETH_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
@@ -30,8 +30,8 @@
 CONFIG_SPL_POWER_SUPPORT=y
 CONFIG_SPL_USB_GADGET=y
 CONFIG_SPL_USB_ETHER=y
-CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_YMODEM_SUPPORT=y
+# CONFIG_SPL_WATCHDOG_SUPPORT is not set
+# CONFIG_SPL_YMODEM_SUPPORT is not set
 CONFIG_AUTOBOOT_KEYED=y
 CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n"
 CONFIG_AUTOBOOT_DELAY_STR="d"
@@ -43,14 +43,14 @@
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_GPT=y
 CONFIG_CMD_I2C=y
-CONFIG_CMD_MMC=y
+# CONFIG_CMD_MMC is not set
 CONFIG_CMD_MTD=y
 CONFIG_CMD_NAND=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_MTDPARTS=y
-CONFIG_MTDPARTS_DEFAULT="mtdparts=nand.0:256k(SPL),256k(SPL.backup1),256k(SPL.backup2),256k(SPL.backup3),1m(u-boot),1m(u-boot.backup1),256k(u-boot-env),256k(u-boot-env.backup1),-(UBI)"
+CONFIG_MTDPARTS_DEFAULT="mtdparts=nand.0:256k(SPL),256k(SPL.backup1),256k(SPL.backup2),256k(SPL.backup3),1m(u-boot),1m(u-boot.backup1),-(UBI)"
 CONFIG_CMD_UBI=y
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_ISO_PARTITION is not set
@@ -58,14 +58,17 @@
 CONFIG_OF_CONTROL=y
 CONFIG_SPL_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="am335x-guardian"
-CONFIG_ENV_IS_IN_NAND=y
+CONFIG_OF_SEPARATE=y
+CONFIG_ENV_IS_NOWHERE=y
 CONFIG_SPL_ENV_IS_NOWHERE=y
 CONFIG_SPL_DM=y
+CONFIG_SPL_DM_USB=y
 CONFIG_BOOTCOUNT_LIMIT=y
 CONFIG_BOOTCOUNT_ENV=y
 CONFIG_MISC=y
-CONFIG_DM_MMC=y
-CONFIG_MMC_OMAP_HS=y
+# CONFIG_DM_MMC is not set
+# CONFIG_MMC is not set
+# CONFIG_MMC_OMAP_HS is not set
 CONFIG_MTD=y
 CONFIG_NAND=y
 CONFIG_SYS_NAND_U_BOOT_LOCATIONS=y
@@ -78,15 +81,19 @@
 CONFIG_NOP_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_SINGLE=y
+# CONFIG_WATCHDOG is not set
+CONFIG_SPL_WDT=y
 CONFIG_USB=y
 CONFIG_DM_USB_GADGET=y
 CONFIG_SPL_DM_USB_GADGET=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_MUSB_TI=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
 CONFIG_USB_GADGET_VENDOR_NUM=0x0451
 CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
 CONFIG_USB_ETHER=y
+# CONFIG_USB_STORAGE is not set
 CONFIG_FAT_WRITE=y
diff --git a/configs/am43xx_evm_defconfig b/configs/am43xx_evm_defconfig
index 7c74047..5e3e01c 100644
--- a/configs/am43xx_evm_defconfig
+++ b/configs/am43xx_evm_defconfig
@@ -18,6 +18,7 @@
 CONFIG_SPL_NET_SUPPORT=y
 CONFIG_SPL_NET_VCI_STRING="AM43xx U-Boot SPL"
 CONFIG_SPL_OS_BOOT=y
+CONFIG_SPL_USB_HOST_SUPPORT=y
 CONFIG_SPL_USB_GADGET=y
 CONFIG_SPL_USB_ETHER=y
 CONFIG_CMD_SPL=y
@@ -78,3 +79,5 @@
 CONFIG_USB_GADGET_PRODUCT_NUM=0xbd00
 CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_USB_ETHER=y
+CONFIG_CLK=y
+CONFIG_CLK_CDCE9XX=y
diff --git a/configs/am57xx_evm_defconfig b/configs/am57xx_evm_defconfig
index 3b613e1..e2f558c 100644
--- a/configs/am57xx_evm_defconfig
+++ b/configs/am57xx_evm_defconfig
@@ -98,3 +98,5 @@
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
 CONFIG_USB_GADGET_VENDOR_NUM=0x0451
 CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
+CONFIG_CLK=y
+CONFIG_CLK_CDCE9XX=y
diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig
index e5b127c..c60978c 100644
--- a/configs/am65x_evm_a53_defconfig
+++ b/configs/am65x_evm_a53_defconfig
@@ -12,13 +12,13 @@
 CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FS_FAT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
+# CONFIG_PSCI_RESET is not set
 CONFIG_SPL_TEXT_BASE=0x80080000
 CONFIG_DISTRO_DEFAULTS=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_OF_BOARD_SETUP=y
-CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern"
-# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run boot_rprocs; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern"
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SEPARATE_BSS=y
@@ -35,6 +35,7 @@
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_PCI=y
+CONFIG_CMD_REMOTEPROC=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_TIME=y
 # CONFIG_ISO_PARTITION is not set
@@ -83,6 +84,7 @@
 CONFIG_PINCTRL_SINGLE=y
 CONFIG_POWER_DOMAIN=y
 CONFIG_TI_SCI_POWER_DOMAIN=y
+CONFIG_REMOTEPROC_TI_K3_R5F=y
 CONFIG_DM_RESET=y
 CONFIG_RESET_TI_SCI=y
 CONFIG_DM_SERIAL=y
diff --git a/configs/am65x_evm_r5_defconfig b/configs/am65x_evm_r5_defconfig
index 077aa37..d0619e9 100644
--- a/configs/am65x_evm_r5_defconfig
+++ b/configs/am65x_evm_r5_defconfig
@@ -5,6 +5,7 @@
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_SYS_MALLOC_F_LEN=0x55000
 CONFIG_SOC_K3_AM6=y
+CONFIG_K3_EARLY_CONS=y
 CONFIG_TARGET_AM654_R5_EVM=y
 CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
diff --git a/configs/am65x_hs_evm_a53_defconfig b/configs/am65x_hs_evm_a53_defconfig
index e9fceea..caee953 100644
--- a/configs/am65x_hs_evm_a53_defconfig
+++ b/configs/am65x_hs_evm_a53_defconfig
@@ -21,7 +21,6 @@
 CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_fit_${boot}; run get_overlaystring; run run_fit"
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SEPARATE_BSS=y
diff --git a/configs/j721e_evm_a72_defconfig b/configs/j721e_evm_a72_defconfig
index 5cb933d..6729e03 100644
--- a/configs/j721e_evm_a72_defconfig
+++ b/configs/j721e_evm_a72_defconfig
@@ -14,12 +14,12 @@
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
+# CONFIG_PSCI_RESET is not set
 CONFIG_SPL_TEXT_BASE=0x80080000
 CONFIG_DISTRO_DEFAULTS=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_LOAD_FIT=y
-CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern"
-# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run boot_rprocs; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern"
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SEPARATE_BSS=y
@@ -34,6 +34,7 @@
 CONFIG_CMD_ASKENV=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_MMC=y
+CONFIG_CMD_REMOTEPROC=y
 CONFIG_CMD_SF=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_TIME=y
@@ -72,6 +73,8 @@
 CONFIG_PINCTRL_SINGLE=y
 CONFIG_POWER_DOMAIN=y
 CONFIG_TI_SCI_POWER_DOMAIN=y
+CONFIG_REMOTEPROC_TI_K3_DSP=y
+CONFIG_REMOTEPROC_TI_K3_R5F=y
 CONFIG_DM_RESET=y
 CONFIG_RESET_TI_SCI=y
 CONFIG_DM_SERIAL=y
diff --git a/doc/device-tree-bindings/clock/ti,cdce9xx.txt b/doc/device-tree-bindings/clock/ti,cdce9xx.txt
new file mode 100644
index 0000000..0d01f2d
--- /dev/null
+++ b/doc/device-tree-bindings/clock/ti,cdce9xx.txt
@@ -0,0 +1,49 @@
+Binding for TI CDCE913/925/937/949 programmable I2C clock synthesizers.
+
+Reference
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] http://www.ti.com/product/cdce913
+[3] http://www.ti.com/product/cdce925
+[4] http://www.ti.com/product/cdce937
+[5] http://www.ti.com/product/cdce949
+
+The driver provides clock sources for each output Y1 through Y5.
+
+Required properties:
+ - compatible: Shall be one of the following:
+	- "ti,cdce913": 1-PLL, 3 Outputs
+	- "ti,cdce925": 2-PLL, 5 Outputs
+	- "ti,cdce937": 3-PLL, 7 Outputs
+	- "ti,cdce949": 4-PLL, 9 Outputs
+ - reg: I2C device address.
+ - clocks: Points to a fixed parent clock that provides the input frequency.
+ - #clock-cells: From common clock bindings: Shall be 1.
+
+Optional properties:
+ - xtal-load-pf: Crystal load-capacitor value to fine-tune performance on a
+                 board, or to compensate for external influences.
+
+For all PLL1, PLL2, ... an optional child node can be used to specify spread
+spectrum clocking parameters for a board.
+  - spread-spectrum: SSC mode as defined in the data sheet.
+  - spread-spectrum-center: Use "centered" mode instead of "max" mode. When
+    present, the clock runs at the requested frequency on average. Otherwise
+    the requested frequency is the maximum value of the SCC range.
+
+
+Example:
+
+	clockgen: cdce925pw@64 {
+		compatible = "cdce925";
+		reg = <0x64>;
+		clocks = <&xtal_27Mhz>;
+		#clock-cells = <1>;
+		xtal-load-pf = <5>;
+		/* PLL options to get SSC 1% centered */
+		PLL2 {
+			spread-spectrum = <4>;
+			spread-spectrum-center;
+		};
+	};
diff --git a/doc/device-tree-bindings/remoteproc/ti,k3-dsp-rproc.txt b/doc/device-tree-bindings/remoteproc/ti,k3-dsp-rproc.txt
new file mode 100644
index 0000000..80ab7a4
--- /dev/null
+++ b/doc/device-tree-bindings/remoteproc/ti,k3-dsp-rproc.txt
@@ -0,0 +1,101 @@
+TI K3 DSP devices
+=================
+
+The TI K3 family of SoCs usually have one or more TI DSP Core sub-systems that
+are used to offload some of the processor-intensive tasks or algorithms, for
+achieving various system level goals.
+
+These processor sub-systems usually contain additional sub-modules like L1
+and/or L2 caches/SRAMs, an Interrupt Controller, an external memory controller,
+a dedicated local power/sleep controller etc. The DSP processor cores in the
+K3 SoCs is usually either a TMS320C66x CorePac processor or a TMS320C71x CorePac
+processor.
+
+DSP Device Node:
+================
+Each DSP Core sub-system is represented as a single DT node. Each node has a
+number of required or optional properties that enable the OS running on the
+host processor (Arm CorePac) to perform the device management of the remote
+processor and to communicate with the remote processor.
+
+Required properties:
+--------------------
+The following are the mandatory properties:
+
+- compatible:		Should be one of the following,
+			    "ti,j721e-c66-dsp" for C66x DSPs on K3 J721E SoCs
+			    "ti,j721e-c71-dsp" for C71x DSPs on K3 J721E SoCs
+
+- reg:			Should contain an entry for each value in 'reg-names'.
+			Each entry should have the memory region's start address
+			and the size of the region, the representation matching
+			the parent node's '#address-cells' and '#size-cells' values.
+
+- reg-names:		Should contain strings with the following names, each
+			representing a specific internal memory region (if
+			present), and should be defined in this order,
+			     "l2sram", "l1pram", "l1dram"
+			NOTE: C71x DSPs do not have a "l1pram" memory.
+
+- ti,sci:		Should be a phandle to the TI-SCI System Controller node
+
+- ti,sci-dev-id:	Should contain the TI-SCI device id corresponding to the
+			DSP Core. Please refer to the corresponding System
+			Controller documentation for valid values for the DSP
+			cores.
+
+- ti,sci-proc-ids:	Should contain 2 integer values. The first cell should
+			contain the TI-SCI processor id for the DSP core device
+			and the second cell should contain the TI-SCI host id to
+			which the processor control ownership should be
+			transferred to.
+
+- resets:		Should contain the phandle to the reset controller node
+			managing the resets for this device, and a reset
+			specifier. Please refer to the following reset bindings
+			for the reset argument specifier,
+			Documentation/devicetree/bindings/reset/ti,sci-reset.txt
+
+Example:
+---------
+
+1. J721E SoC
+	/* J721E remoteproc alias */
+	aliases {
+		rproc6 = &c66_0;
+		rproc8 = &c71_0;
+	};
+
+	cbass_main: interconnect@100000 {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0x00 0x64800000 0x00 0x64800000 0x00 0x00800000>, /* C71_0 */
+			 <0x4d 0x80800000 0x4d 0x80800000 0x00 0x00800000>, /* C66_0 */
+			 <0x4d 0x81800000 0x4d 0x81800000 0x00 0x00800000>; /* C66_1 */
+
+		/* J721E C66_0 DSP node */
+		c66_0: dsp@4d80800000 {
+			compatible = "ti,j721e-c66-dsp";
+			reg = <0x4d 0x80800000 0x00 0x00048000>,
+			      <0x4d 0x80e00000 0x00 0x00008000>,
+			      <0x4d 0x80f00000 0x00 0x00008000>;
+			reg-names = "l2sram", "l1pram", "l1dram";
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <142>;
+			ti,sci-proc-ids = <0x03 0xFF>;
+			resets = <&k3_reset 142 1>;
+		};
+
+		/* J721E C71_0 DSP node */
+		c71_0: dsp@64800000 {
+			compatible = "ti,j721e-c71-dsp";
+			reg = <0x00 0x64800000 0x00 0x00080000>,
+			      <0x00 0x64e00000 0x00 0x0000c000>;
+			reg-names = "l2sram", "l1dram";
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <15>;
+			ti,sci-proc-ids = <0x30 0xFF>;
+			resets = <&k3_reset 15 1>;
+		};
+	};
diff --git a/doc/device-tree-bindings/remoteproc/ti,k3-r5f-rproc.txt b/doc/device-tree-bindings/remoteproc/ti,k3-r5f-rproc.txt
new file mode 100644
index 0000000..c2fa6e8
--- /dev/null
+++ b/doc/device-tree-bindings/remoteproc/ti,k3-r5f-rproc.txt
@@ -0,0 +1,164 @@
+TI K3 R5F processor subsystems
+==============================
+
+The TI K3 family of SoCs usually have one or more dual-core Arm Cortex
+R5F processor subsystems/clusters (R5FSS). The dual core cluster can be
+used either in a LockStep mode providing safety/fault tolerance features
+or in a Split mode providing two individual compute cores for doubling
+the compute capacity. These are used together with other processors
+present on the SoC to achieve various system level goals.
+
+R5F Sub-System Device Node:
+===========================
+Each Dual-Core R5F sub-system is represented as a single DTS node representing
+the cluster, with a pair of child DT nodes representing the individual R5F
+cores. Each node has a number of required or optional properties that enable
+the OS running on the host processor to perform the device management of the
+remote processor and to communicate with the remote processor.
+
+Required properties:
+--------------------
+The following are the mandatory properties:
+
+- compatible:		Should be one of the following,
+			    "ti,am654-r5fss" for R5F clusters/subsystems on
+			                       K3 AM65x SoCs
+			    "ti,j721e-r5fss" for R5F clusters/subsystems on
+			                       K3 J721E SoCs
+- power-domains:	Should contain a phandle to a PM domain provider node
+			and an args specifier containing the R5FSS device id
+			value. This property is as per the binding,
+			Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
+- #address-cells:	Should be 1
+- #size-cells:		Should be 1
+- ranges:		Standard ranges definition providing translations for
+			R5F TCM address spaces
+
+Optional properties:
+--------------------
+- lockstep-mode:	Configuration Mode for the Dual R5F cores within the R5F
+			cluster. Should be either a value of 1 (LockStep mode) or
+			0 (Split mode), default is LockStep mode if omitted.
+
+
+R5F Processor Child Nodes:
+==========================
+The R5F Sub-System device node should define two R5F child nodes, each node
+representing a TI instantiation of the Arm Cortex R5F core. There are some
+specific integration differences for the IP like the usage of a Region Address
+Translator (RAT) for translating the larger SoC bus addresses into a 32-bit
+address space for the processor.
+
+Required properties:
+--------------------
+The following are the mandatory properties:
+
+- compatible:		Should be one of the following,
+			    "ti,am654-r5f" for the R5F cores in K3 AM65x SoCs
+			    "ti,j721e-r5f" for the R5F cores in K3 J721E SOCs
+- reg:			Should contain an entry for each value in 'reg-names'.
+			Each entry should have the memory region's start address
+			and the size of the region, the representation matching
+			the parent node's '#address-cells' and '#size-cells' values.
+- reg-names:		Should contain strings with the following names, each
+			representing a specific internal memory region, and
+			should be defined in this order,
+			     "atcm", "btcm"
+- ti,sci:		Should be a phandle to the TI-SCI System Controller node
+- ti,sci-dev-id:	Should contain the TI-SCI device id corresponding to the
+			R5F Core. Please refer to the corresponding System
+			Controller documentation for valid values for the R5F
+			cores.
+- ti,sci-proc-ids:	Should contain 2 integer values. The first cell should
+			contain the TI-SCI processor id for the R5F core device
+			and the second cell should contain the TI-SCI host id to
+			which the processor control ownership should be
+			transferred to.
+- resets:		Should contain the phandle to the reset controller node
+			managing the resets for this device, and a reset
+			specifier. Please refer to the following reset bindings
+			for the reset argument specifier,
+			Documentation/devicetree/bindings/reset/ti,sci-reset.txt
+			    for AM65x and J721E SoCs
+
+Optional properties:
+--------------------
+The following properties are optional properties for each of the R5F cores:
+
+- atcm-enable:		R5F core configuration mode dictating if ATCM should be
+			enabled. Should be either a value of 1 (enabled) or
+			0 (disabled), default is disabled if omitted. R5F view
+			of ATCM dictated by loczrama property.
+- btcm-enable:		R5F core configuration mode dictating if BTCM should be
+			enabled. Should be either a value of 1 (enabled) or
+			0 (disabled), default is enabled if omitted. R5F view
+			of BTCM dictated by loczrama property.
+- loczrama:		R5F core configuration mode dictating which TCM should
+			appear at address 0 (from core's view). Should be either
+			a value of 1 (ATCM at 0x0) or 0 (BTCM at 0x0), default
+			value is 1 if omitted.
+
+Example:
+--------
+1. AM654 SoC
+	/* AM65x remoteproc alias */
+	aliases {
+		remoteproc0 = &mcu_r5fss0_core0;
+	};
+
+	cbass_main: interconnect@100000 {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0x00 0x41000000 0x00 0x41000000 0x00 0x00020000>,
+			 <0x00 0x41400000 0x00 0x41400000 0x00 0x00020000>,
+			 <0x00 0x41c00000 0x00 0x41c00000 0x00 0x00080000>;
+
+		cbass_mcu: interconnect@28380000 {
+			compatible = "simple-bus";
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x00 0x41000000 0x00 0x41000000 0x00 0x00020000>, /* MCU R5F Core0 */
+				 <0x00 0x41400000 0x00 0x41400000 0x00 0x00020000>, /* MCU R5F Core1 */
+				 <0x00 0x41c00000 0x00 0x41c00000 0x00 0x00080000>; /* MCU SRAM */
+
+			/* AM65x MCU R5FSS node */
+			mcu_r5fss0: r5fss@41000000 {
+				compatible = "ti,am654-r5fss";
+				power-domains = <&k3_pds 129>;
+				lockstep-mode = <1>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0x41000000 0x00 0x41000000 0x20000>,
+					 <0x41400000 0x00 0x41400000 0x20000>;
+
+				mcu_r5f0: r5f@41000000 {
+					compatible = "ti,am654-r5f";
+					reg = <0x41000000 0x00008000>,
+					      <0x41010000 0x00008000>;
+					reg-names = "atcm", "btcm";
+					ti,sci = <&dmsc>;
+					ti,sci-dev-id = <159>;
+					ti,sci-proc-ids = <0x01 0xFF>;
+					resets = <&k3_reset 159 1>;
+					atcm-enable = <1>;
+					btcm-enable = <1>;
+					loczrama = <1>;
+				};
+
+				mcu_r5f1: r5f@41400000 {
+					compatible = "ti,am654-r5f";
+					reg = <0x41400000 0x00008000>,
+					      <0x41410000 0x00008000>;
+					reg-names = "atcm", "btcm";
+					ti,sci = <&dmsc>;
+					ti,sci-dev-id = <245>;
+					ti,sci-proc-ids = <0x02 0xFF>;
+					resets = <&k3_reset 245 1>;
+					atcm-enable = <1>;
+					btcm-enable = <1>;
+					loczrama = <1>;
+				};
+			};
+		};
+	};
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 0035f0a..16d4237 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -134,6 +134,13 @@
 	  Enable the STM32 clock (RCC) driver. Enable support for
 	  manipulating STM32MP1's on-SoC clocks.
 
+config CLK_CDCE9XX
+	bool "Enable CDCD9XX clock driver"
+	depends on CLK
+	help
+	   Enable the clock synthesizer driver for CDCE913/925/937/949
+	   series of chips.
+
 source "drivers/clk/analogbits/Kconfig"
 source "drivers/clk/at91/Kconfig"
 source "drivers/clk/exynos/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d7cea3b..8de6777 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -44,3 +44,4 @@
 obj-$(CONFIG_STM32H7) += clk_stm32h7.o
 obj-$(CONFIG_CLK_TI_SCI) += clk-ti-sci.o
 obj-$(CONFIG_CLK_VERSAL) += clk_versal.o
+obj-$(CONFIG_CLK_CDCE9XX) += clk-cdce9xx.o
diff --git a/drivers/clk/clk-cdce9xx.c b/drivers/clk/clk-cdce9xx.c
new file mode 100644
index 0000000..5d1489a
--- /dev/null
+++ b/drivers/clk/clk-cdce9xx.c
@@ -0,0 +1,254 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Texas Instruments CDCE913/925/937/949 clock synthesizer driver
+ *
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ *	Tero Kristo <t-kristo@ti.com>
+ *
+ * Based on Linux kernel clk-cdce925.c.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <clk-uclass.h>
+#include <i2c.h>
+
+#define MAX_NUMBER_OF_PLLS		4
+#define MAX_NUMER_OF_OUTPUTS		9
+
+#define CDCE9XX_REG_GLOBAL1		0x01
+#define CDCE9XX_REG_Y1SPIPDIVH		0x02
+#define CDCE9XX_REG_PDIV1L		0x03
+#define CDCE9XX_REG_XCSEL		0x05
+
+#define CDCE9XX_PDIV1_H_MASK		0x3
+
+#define CDCE9XX_REG_PDIV(clk)		(0x16 + (((clk) - 1) & 1) + \
+					 ((clk) - 1) / 2 * 0x10)
+
+#define CDCE9XX_PDIV_MASK		0x7f
+
+#define CDCE9XX_BYTE_TRANSFER		BIT(7)
+
+struct cdce9xx_chip_info {
+	int num_plls;
+	int num_outputs;
+};
+
+struct cdce9xx_clk_data {
+	struct udevice *i2c;
+	struct cdce9xx_chip_info *chip;
+	u32 xtal_rate;
+};
+
+static const struct cdce9xx_chip_info cdce913_chip_info = {
+	.num_plls = 1, .num_outputs = 3,
+};
+
+static const struct cdce9xx_chip_info cdce925_chip_info = {
+	.num_plls = 2, .num_outputs = 5,
+};
+
+static const struct cdce9xx_chip_info cdce937_chip_info = {
+	.num_plls = 3, .num_outputs = 7,
+};
+
+static const struct cdce9xx_chip_info cdce949_chip_info = {
+	.num_plls = 4, .num_outputs = 9,
+};
+
+static int cdce9xx_reg_read(struct udevice *dev, u8 addr, u8 *buf)
+{
+	struct cdce9xx_clk_data *data = dev_get_priv(dev);
+	int ret;
+
+	ret = dm_i2c_read(data->i2c, addr | CDCE9XX_BYTE_TRANSFER, buf, 1);
+	if (ret)
+		dev_err(dev, "%s: failed for addr:%x, ret:%d\n", __func__,
+			addr, ret);
+
+	return ret;
+}
+
+static int cdce9xx_reg_write(struct udevice *dev, u8 addr, u8 val)
+{
+	struct cdce9xx_clk_data *data = dev_get_priv(dev);
+	int ret;
+
+	ret = dm_i2c_write(data->i2c, addr | CDCE9XX_BYTE_TRANSFER, &val, 1);
+	if (ret)
+		dev_err(dev, "%s: failed for addr:%x, ret:%d\n", __func__,
+			addr, ret);
+
+	return ret;
+}
+
+static int cdce9xx_clk_of_xlate(struct clk *clk,
+				struct ofnode_phandle_args *args)
+{
+	struct cdce9xx_clk_data *data = dev_get_priv(clk->dev);
+
+	if (args->args_count != 1)
+		return -EINVAL;
+
+	if (args->args[0] > data->chip->num_outputs)
+		return -EINVAL;
+
+	clk->id = args->args[0];
+
+	return 0;
+}
+
+static int cdce9xx_clk_probe(struct udevice *dev)
+{
+	struct cdce9xx_clk_data *data = dev_get_priv(dev);
+	struct cdce9xx_chip_info *chip = (void *)dev_get_driver_data(dev);
+	int ret;
+	u32 val;
+	struct clk clk;
+
+	val = (u32)dev_read_addr_ptr(dev);
+
+	ret = i2c_get_chip(dev->parent, val, 1, &data->i2c);
+	if (ret) {
+		dev_err(dev, "I2C probe failed.\n");
+		return ret;
+	}
+
+	data->chip = chip;
+
+	ret = clk_get_by_index(dev, 0, &clk);
+	data->xtal_rate = clk_get_rate(&clk);
+
+	val = dev_read_u32_default(dev, "xtal-load-pf", -1);
+	if (val >= 0)
+		cdce9xx_reg_write(dev, CDCE9XX_REG_XCSEL, val << 3);
+
+	return 0;
+}
+
+static u16 cdce9xx_clk_get_pdiv(struct clk *clk)
+{
+	u8 val;
+	u16 pdiv;
+	int ret;
+
+	if (clk->id == 0) {
+		ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_Y1SPIPDIVH, &val);
+		if (ret)
+			return 0;
+
+		pdiv = (val & CDCE9XX_PDIV1_H_MASK) << 8;
+
+		ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_PDIV1L, &val);
+		if (ret)
+			return 0;
+
+		pdiv |= val;
+	} else {
+		ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_PDIV(clk->id),
+				       &val);
+		if (ret)
+			return 0;
+
+		pdiv = val & CDCE9XX_PDIV_MASK;
+	}
+
+	return pdiv;
+}
+
+static u32 cdce9xx_clk_get_parent_rate(struct clk *clk)
+{
+	struct cdce9xx_clk_data *data = dev_get_priv(clk->dev);
+
+	return data->xtal_rate;
+}
+
+static ulong cdce9xx_clk_get_rate(struct clk *clk)
+{
+	u32 parent_rate;
+	u16 pdiv;
+
+	parent_rate = cdce9xx_clk_get_parent_rate(clk);
+
+	pdiv = cdce9xx_clk_get_pdiv(clk);
+
+	return parent_rate / pdiv;
+}
+
+static ulong cdce9xx_clk_set_rate(struct clk *clk, ulong rate)
+{
+	u32 parent_rate;
+	int pdiv;
+	u32 diff;
+	u8 val;
+	int ret;
+
+	parent_rate = cdce9xx_clk_get_parent_rate(clk);
+
+	pdiv = parent_rate / rate;
+
+	diff = rate - parent_rate / pdiv;
+
+	if (rate - parent_rate / (pdiv + 1) < diff)
+		pdiv++;
+
+	if (clk->id == 0) {
+		ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_Y1SPIPDIVH, &val);
+		if (ret)
+			return ret;
+
+		val &= ~CDCE9XX_PDIV1_H_MASK;
+
+		val |= (pdiv >> 8);
+
+		ret = cdce9xx_reg_write(clk->dev, CDCE9XX_REG_Y1SPIPDIVH, val);
+		if (ret)
+			return ret;
+
+		ret = cdce9xx_reg_write(clk->dev, CDCE9XX_REG_PDIV1L,
+					(pdiv & 0xff));
+		if (ret)
+			return ret;
+	} else {
+		ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_PDIV(clk->id),
+				       &val);
+		if (ret)
+			return ret;
+
+		val &= ~CDCE9XX_PDIV_MASK;
+
+		val |= pdiv;
+
+		ret = cdce9xx_reg_write(clk->dev, CDCE9XX_REG_PDIV(clk->id),
+					val);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct udevice_id cdce9xx_clk_of_match[] = {
+	{ .compatible = "ti,cdce913", .data = (u32)&cdce913_chip_info },
+	{ .compatible = "ti,cdce925", .data = (u32)&cdce925_chip_info },
+	{ .compatible = "ti,cdce937", .data = (u32)&cdce937_chip_info },
+	{ .compatible = "ti,cdce949", .data = (u32)&cdce949_chip_info },
+	{ /* sentinel */ },
+};
+
+static const struct clk_ops cdce9xx_clk_ops = {
+	.of_xlate = cdce9xx_clk_of_xlate,
+	.get_rate = cdce9xx_clk_get_rate,
+	.set_rate = cdce9xx_clk_set_rate,
+};
+
+U_BOOT_DRIVER(cdce9xx_clk) = {
+	.name = "cdce9xx-clk",
+	.id = UCLASS_CLK,
+	.of_match = cdce9xx_clk_of_match,
+	.probe = cdce9xx_clk_probe,
+	.priv_auto_alloc_size = sizeof(struct cdce9xx_clk_data),
+	.ops = &cdce9xx_clk_ops,
+};
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 84f0f0f..ce66c72 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -568,6 +568,17 @@
 	return -ENODEV;
 }
 
+int device_get_child_count(struct udevice *parent)
+{
+	struct udevice *dev;
+	int count = 0;
+
+	list_for_each_entry(dev, &parent->child_head, sibling_node)
+		count++;
+
+	return count;
+}
+
 int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq,
 			     bool find_req_seq, struct udevice **devp)
 {
diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index 1793a3f..7cd5516 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -219,23 +219,10 @@
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
 	struct sdhci_host *host = dev_get_priv(dev);
 	struct mmc_config *cfg = &plat->cfg;
-	struct power_domain sdhci_pwrdmn;
 	struct clk clk;
 	unsigned long clock;
 	int ret;
 
-	ret = power_domain_get_by_index(dev, &sdhci_pwrdmn, 0);
-	if (!ret) {
-		ret = power_domain_on(&sdhci_pwrdmn);
-		if (ret) {
-			dev_err(dev, "Power domain on failed (%d)\n", ret);
-			return ret;
-		}
-	} else if (ret != -ENOENT && ret != -ENODEV && ret != -ENOSYS) {
-		dev_err(dev, "failed to get power domain (%d)\n", ret);
-		return ret;
-	}
-
 	ret = clk_get_by_index(dev, 0, &clk);
 	if (ret) {
 		dev_err(dev, "failed to get clock\n");
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index f54a245..7c2e480 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -52,6 +52,26 @@
 	  on various TI K3 family of SoCs through the remote processor
 	  framework.
 
+config REMOTEPROC_TI_K3_DSP
+	bool "TI K3 C66 and C71 remoteproc support"
+	select REMOTEPROC
+	depends on ARCH_K3
+	depends on TI_SCI_PROTOCOL
+	help
+	  Say y here to support TI's C66/C71 remote processor subsystems
+	  on various TI K3 family of SoCs through the remote processor
+	  framework.
+
+config REMOTEPROC_TI_K3_R5F
+	bool "TI K3 R5F remoteproc support"
+	select REMOTEPROC
+	depends on ARCH_K3
+	depends on TI_SCI_PROTOCOL
+	help
+	  Say y here to support TI's R5F remote processor subsystems
+	  on various TI K3 family of SoCs through the remote processor
+	  framework.
+
 config REMOTEPROC_TI_POWER
 	bool "Support for TI Power processor"
 	select REMOTEPROC
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 271ba55..69ae7bd 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -11,4 +11,6 @@
 obj-$(CONFIG_REMOTEPROC_SANDBOX) += sandbox_testproc.o
 obj-$(CONFIG_REMOTEPROC_STM32_COPRO) += stm32_copro.o
 obj-$(CONFIG_REMOTEPROC_TI_K3_ARM64) += ti_k3_arm64_rproc.o
+obj-$(CONFIG_REMOTEPROC_TI_K3_DSP) += ti_k3_dsp_rproc.o
+obj-$(CONFIG_REMOTEPROC_TI_K3_R5F) += ti_k3_r5f_rproc.o
 obj-$(CONFIG_REMOTEPROC_TI_POWER) += ti_power_proc.o
diff --git a/drivers/remoteproc/rproc-elf-loader.c b/drivers/remoteproc/rproc-elf-loader.c
index 67937a7..b38a226 100644
--- a/drivers/remoteproc/rproc-elf-loader.c
+++ b/drivers/remoteproc/rproc-elf-loader.c
@@ -64,13 +64,90 @@
 	return 0;
 }
 
-/* A very simple elf loader, assumes the image is valid */
-int rproc_elf32_load_image(struct udevice *dev, unsigned long addr)
+/* Basic function to verify ELF64 image format */
+int rproc_elf64_sanity_check(ulong addr, ulong size)
+{
+	Elf64_Ehdr *ehdr = (Elf64_Ehdr *)addr;
+	char class;
+
+	if (!addr) {
+		pr_debug("Invalid fw address?\n");
+		return -EFAULT;
+	}
+
+	if (size < sizeof(Elf64_Ehdr)) {
+		pr_debug("Image is too small\n");
+		return -ENOSPC;
+	}
+
+	class = ehdr->e_ident[EI_CLASS];
+
+	if (!IS_ELF(*ehdr) || ehdr->e_type != ET_EXEC || class != ELFCLASS64) {
+		pr_debug("Not an executable ELF64 image\n");
+		return -EPROTONOSUPPORT;
+	}
+
+	/* We assume the firmware has the same endianness as the host */
+# ifdef __LITTLE_ENDIAN
+	if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
+# else /* BIG ENDIAN */
+	if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) {
+# endif
+		pr_debug("Unsupported firmware endianness\n");
+		return -EILSEQ;
+	}
+
+	if (size < ehdr->e_shoff + sizeof(Elf64_Shdr)) {
+		pr_debug("Image is too small\n");
+		return -ENOSPC;
+	}
+
+	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
+		pr_debug("Image is corrupted (bad magic)\n");
+		return -EBADF;
+	}
+
+	if (ehdr->e_phnum == 0) {
+		pr_debug("No loadable segments\n");
+		return -ENOEXEC;
+	}
+
+	if (ehdr->e_phoff > size) {
+		pr_debug("Firmware size is too small\n");
+		return -ENOSPC;
+	}
+
+	return 0;
+}
+
+/* Basic function to verify ELF image format */
+int rproc_elf_sanity_check(ulong addr, ulong size)
+{
+	Elf32_Ehdr *ehdr = (Elf32_Ehdr *)addr;
+
+	if (!addr) {
+		dev_err(dev, "Invalid firmware address\n");
+		return -EFAULT;
+	}
+
+	if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
+		return rproc_elf64_sanity_check(addr, size);
+	else
+		return rproc_elf32_sanity_check(addr, size);
+}
+
+int rproc_elf32_load_image(struct udevice *dev, unsigned long addr, ulong size)
 {
 	Elf32_Ehdr *ehdr; /* Elf header structure pointer */
 	Elf32_Phdr *phdr; /* Program header structure pointer */
 	const struct dm_rproc_ops *ops;
-	unsigned int i;
+	unsigned int i, ret;
+
+	ret =  rproc_elf32_sanity_check(addr, size);
+	if (ret) {
+		dev_err(dev, "Invalid ELF32 Image %d\n", ret);
+		return ret;
+	}
 
 	ehdr = (Elf32_Ehdr *)addr;
 	phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
@@ -86,7 +163,8 @@
 			continue;
 
 		if (ops->device_to_virt)
-			dst = ops->device_to_virt(dev, (ulong)dst);
+			dst = ops->device_to_virt(dev, (ulong)dst,
+						  phdr->p_memsz);
 
 		dev_dbg(dev, "Loading phdr %i to 0x%p (%i bytes)\n",
 			i, dst, phdr->p_filesz);
@@ -104,3 +182,96 @@
 
 	return 0;
 }
+
+int rproc_elf64_load_image(struct udevice *dev, ulong addr, ulong size)
+{
+	const struct dm_rproc_ops *ops = rproc_get_ops(dev);
+	u64 da, memsz, filesz, offset;
+	Elf64_Ehdr *ehdr;
+	Elf64_Phdr *phdr;
+	int i, ret = 0;
+	void *ptr;
+
+	dev_dbg(dev, "%s: addr = 0x%lx size = 0x%lx\n", __func__, addr, size);
+
+	if (rproc_elf64_sanity_check(addr, size))
+		return -EINVAL;
+
+	ehdr = (Elf64_Ehdr *)addr;
+	phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);
+
+	/* go through the available ELF segments */
+	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
+		da = phdr->p_paddr;
+		memsz = phdr->p_memsz;
+		filesz = phdr->p_filesz;
+		offset = phdr->p_offset;
+
+		if (phdr->p_type != PT_LOAD)
+			continue;
+
+		dev_dbg(dev, "%s:phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n",
+			__func__, phdr->p_type, da, memsz, filesz);
+
+		ptr = (void *)(uintptr_t)da;
+		if (ops->device_to_virt) {
+			ptr = ops->device_to_virt(dev, da, phdr->p_memsz);
+			if (!ptr) {
+				dev_err(dev, "bad da 0x%llx mem 0x%llx\n", da,
+					memsz);
+				ret = -EINVAL;
+				break;
+			}
+		}
+
+		if (filesz)
+			memcpy(ptr, (void *)addr + offset, filesz);
+		if (filesz != memsz)
+			memset(ptr + filesz, 0x00, memsz - filesz);
+
+		flush_cache(rounddown((ulong)ptr, ARCH_DMA_MINALIGN),
+			    roundup((ulong)ptr + filesz, ARCH_DMA_MINALIGN) -
+			    rounddown((ulong)ptr, ARCH_DMA_MINALIGN));
+	}
+
+	return ret;
+}
+
+int rproc_elf_load_image(struct udevice *dev, ulong addr, ulong size)
+{
+	Elf32_Ehdr *ehdr = (Elf32_Ehdr *)addr;
+
+	if (!addr) {
+		dev_err(dev, "Invalid firmware address\n");
+		return -EFAULT;
+	}
+
+	if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
+		return rproc_elf64_load_image(dev, addr, size);
+	else
+		return rproc_elf32_load_image(dev, addr, size);
+}
+
+static ulong rproc_elf32_get_boot_addr(ulong addr)
+{
+	Elf32_Ehdr *ehdr = (Elf32_Ehdr *)addr;
+
+	return ehdr->e_entry;
+}
+
+static ulong rproc_elf64_get_boot_addr(ulong addr)
+{
+	Elf64_Ehdr *ehdr = (Elf64_Ehdr *)addr;
+
+	return ehdr->e_entry;
+}
+
+ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr)
+{
+	Elf32_Ehdr *ehdr = (Elf32_Ehdr *)addr;
+
+	if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
+		return rproc_elf64_get_boot_addr(addr);
+	else
+		return rproc_elf32_get_boot_addr(addr);
+}
diff --git a/drivers/remoteproc/sandbox_testproc.c b/drivers/remoteproc/sandbox_testproc.c
index 5f35119..eeee49c 100644
--- a/drivers/remoteproc/sandbox_testproc.c
+++ b/drivers/remoteproc/sandbox_testproc.c
@@ -306,9 +306,11 @@
  * sandbox_testproc_device_to_virt() - Convert device address to virtual address
  * @dev:	device to operate upon
  * @da:		device address
+ * @size:	Size of the memory region @da is pointing to
  * @return converted virtual address
  */
-static void *sandbox_testproc_device_to_virt(struct udevice *dev, ulong da)
+static void *sandbox_testproc_device_to_virt(struct udevice *dev, ulong da,
+					     ulong size)
 {
 	u64 paddr;
 
diff --git a/drivers/remoteproc/stm32_copro.c b/drivers/remoteproc/stm32_copro.c
index ad941f6..40bba37 100644
--- a/drivers/remoteproc/stm32_copro.c
+++ b/drivers/remoteproc/stm32_copro.c
@@ -107,11 +107,13 @@
  * stm32_copro_device_to_virt() - Convert device address to virtual address
  * @dev:	corresponding STM32 remote processor device
  * @da:		device address
+ * @size:	Size of the memory region @da is pointing to
  * @return converted virtual address
  */
-static void *stm32_copro_device_to_virt(struct udevice *dev, ulong da)
+static void *stm32_copro_device_to_virt(struct udevice *dev, ulong da,
+					ulong size)
 {
-	fdt32_t in_addr = cpu_to_be32(da);
+	fdt32_t in_addr = cpu_to_be32(da), end_addr;
 	u64 paddr;
 
 	paddr = dev_translate_dma_address(dev, &in_addr);
@@ -120,6 +122,12 @@
 		return NULL;
 	}
 
+	end_addr = cpu_to_be32(da + size - 1);
+	if (dev_translate_dma_address(dev, &end_addr) == OF_BAD_ADDR) {
+		dev_err(dev, "Unable to convert address %ld\n", da + size - 1);
+		return NULL;
+	}
+
 	return phys_to_virt(paddr);
 }
 
@@ -147,14 +155,7 @@
 		return ret;
 	}
 
-	/* Support only ELF32 image */
-	ret = rproc_elf32_sanity_check(addr, size);
-	if (ret) {
-		dev_err(dev, "Invalid ELF32 image (%d)\n", ret);
-		return ret;
-	}
-
-	return rproc_elf32_load_image(dev, addr);
+	return rproc_elf32_load_image(dev, addr, size);
 }
 
 /**
diff --git a/drivers/remoteproc/ti_k3_dsp_rproc.c b/drivers/remoteproc/ti_k3_dsp_rproc.c
new file mode 100644
index 0000000..c5dc6b2
--- /dev/null
+++ b/drivers/remoteproc/ti_k3_dsp_rproc.c
@@ -0,0 +1,354 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Texas Instruments' K3 DSP Remoteproc driver
+ *
+ * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/
+ *	Lokesh Vutla <lokeshvutla@ti.com>
+ *
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <remoteproc.h>
+#include <errno.h>
+#include <clk.h>
+#include <reset.h>
+#include <asm/io.h>
+#include <power-domain.h>
+#include <linux/soc/ti/ti_sci_protocol.h>
+#include "ti_sci_proc.h"
+
+#define KEYSTONE_RPROC_LOCAL_ADDRESS_MASK	(SZ_16M - 1)
+
+/**
+ * struct k3_dsp_mem - internal memory structure
+ * @cpu_addr: MPU virtual address of the memory region
+ * @bus_addr: Bus address used to access the memory region
+ * @dev_addr: Device address from remoteproc view
+ * @size: Size of the memory region
+ */
+struct k3_dsp_mem {
+	void __iomem *cpu_addr;
+	phys_addr_t bus_addr;
+	phys_addr_t dev_addr;
+	size_t size;
+};
+
+/**
+ * struct k3_dsp_privdata - Structure representing Remote processor data.
+ * @rproc_rst:		rproc reset control data
+ * @tsp:		Pointer to TISCI proc contrl handle
+ * @mem:		Array of available memories
+ * @num_mem:		Number of available memories
+ */
+struct k3_dsp_privdata {
+	struct reset_ctl dsp_rst;
+	struct ti_sci_proc tsp;
+	struct k3_dsp_mem *mem;
+	int num_mems;
+};
+
+/**
+ * k3_dsp_load() - Load up the Remote processor image
+ * @dev:	rproc device pointer
+ * @addr:	Address at which image is available
+ * @size:	size of the image
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+static int k3_dsp_load(struct udevice *dev, ulong addr, ulong size)
+{
+	struct k3_dsp_privdata *dsp = dev_get_priv(dev);
+	u32 boot_vector;
+	int ret;
+
+	dev_dbg(dev, "%s addr = 0x%lx, size = 0x%lx\n", __func__, addr, size);
+	ret = ti_sci_proc_request(&dsp->tsp);
+	if (ret)
+		return ret;
+
+	ret = rproc_elf_load_image(dev, addr, size);
+	if (ret < 0) {
+		dev_err(dev, "Loading elf failed %d\n", ret);
+		goto proc_release;
+	}
+
+	boot_vector = rproc_elf_get_boot_addr(dev, addr);
+
+	dev_dbg(dev, "%s: Boot vector = 0x%x\n", __func__, boot_vector);
+
+	ret = ti_sci_proc_set_config(&dsp->tsp, boot_vector, 0, 0);
+proc_release:
+	ti_sci_proc_release(&dsp->tsp);
+	return ret;
+}
+
+/**
+ * k3_dsp_start() - Start the remote processor
+ * @dev:	rproc device pointer
+ *
+ * Return: 0 if all went ok, else return appropriate error
+ */
+static int k3_dsp_start(struct udevice *dev)
+{
+	struct k3_dsp_privdata *dsp = dev_get_priv(dev);
+	int ret;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	ret = ti_sci_proc_request(&dsp->tsp);
+	if (ret)
+		return ret;
+	/*
+	 * Setting the right clock frequency would have taken care by
+	 * assigned-clock-rates during the device probe. So no need to
+	 * set the frequency again here.
+	 */
+	ret = ti_sci_proc_power_domain_on(&dsp->tsp);
+	if (ret)
+		goto proc_release;
+
+	ret = reset_deassert(&dsp->dsp_rst);
+
+proc_release:
+	ti_sci_proc_release(&dsp->tsp);
+
+	return ret;
+}
+
+static int k3_dsp_stop(struct udevice *dev)
+{
+	struct k3_dsp_privdata *dsp = dev_get_priv(dev);
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	ti_sci_proc_request(&dsp->tsp);
+	reset_assert(&dsp->dsp_rst);
+	ti_sci_proc_power_domain_off(&dsp->tsp);
+	ti_sci_proc_release(&dsp->tsp);
+
+	return 0;
+}
+
+/**
+ * k3_dsp_init() - Initialize the remote processor
+ * @dev:	rproc device pointer
+ *
+ * Return: 0 if all went ok, else return appropriate error
+ */
+static int k3_dsp_init(struct udevice *dev)
+{
+	dev_dbg(dev, "%s\n", __func__);
+
+	return 0;
+}
+
+static int k3_dsp_reset(struct udevice *dev)
+{
+	dev_dbg(dev, "%s\n", __func__);
+
+	return 0;
+}
+
+static void *k3_dsp_da_to_va(struct udevice *dev, ulong da, ulong len)
+{
+	struct k3_dsp_privdata *dsp = dev_get_priv(dev);
+	phys_addr_t bus_addr, dev_addr;
+	void __iomem *va = NULL;
+	size_t size;
+	u32 offset;
+	int i;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	if (len <= 0)
+		return NULL;
+
+	for (i = 0; i < dsp->num_mems; i++) {
+		bus_addr = dsp->mem[i].bus_addr;
+		dev_addr = dsp->mem[i].dev_addr;
+		size = dsp->mem[i].size;
+
+		if (da >= dev_addr && ((da + len) <= (dev_addr + size))) {
+			offset = da - dev_addr;
+			va = dsp->mem[i].cpu_addr + offset;
+			return (__force void *)va;
+		}
+
+		if (da >= bus_addr && (da + len) <= (bus_addr + size)) {
+			offset = da - bus_addr;
+			va = dsp->mem[i].cpu_addr + offset;
+			return (__force void *)va;
+		}
+	}
+
+	/* Assume it is DDR region and return da */
+	return map_physmem(da, len, MAP_NOCACHE);
+}
+
+static const struct dm_rproc_ops k3_dsp_ops = {
+	.init = k3_dsp_init,
+	.load = k3_dsp_load,
+	.start = k3_dsp_start,
+	.stop = k3_dsp_stop,
+	.reset = k3_dsp_reset,
+	.device_to_virt = k3_dsp_da_to_va,
+};
+
+static int ti_sci_proc_of_to_priv(struct udevice *dev, struct ti_sci_proc *tsp)
+{
+	u32 ids[2];
+	int ret;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	tsp->sci = ti_sci_get_by_phandle(dev, "ti,sci");
+	if (IS_ERR(tsp->sci)) {
+		dev_err(dev, "ti_sci get failed: %ld\n", PTR_ERR(tsp->sci));
+		return PTR_ERR(tsp->sci);
+	}
+
+	ret = dev_read_u32_array(dev, "ti,sci-proc-ids", ids, 2);
+	if (ret) {
+		dev_err(dev, "Proc IDs not populated %d\n", ret);
+		return ret;
+	}
+
+	tsp->ops = &tsp->sci->ops.proc_ops;
+	tsp->proc_id = ids[0];
+	tsp->host_id = ids[1];
+	tsp->dev_id = dev_read_u32_default(dev, "ti,sci-dev-id",
+					   TI_SCI_RESOURCE_NULL);
+	if (tsp->dev_id == TI_SCI_RESOURCE_NULL) {
+		dev_err(dev, "Device ID not populated %d\n", ret);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int k3_dsp_of_get_memories(struct udevice *dev)
+{
+	static const char * const mem_names[] = {"l2sram", "l1pram", "l1dram"};
+	struct k3_dsp_privdata *dsp = dev_get_priv(dev);
+	int i;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	dsp->num_mems = ARRAY_SIZE(mem_names);
+	dsp->mem = calloc(dsp->num_mems, sizeof(*dsp->mem));
+	if (!dsp->mem)
+		return -ENOMEM;
+
+	for (i = 0; i < dsp->num_mems; i++) {
+		/* C71 cores only have a L1P Cache, there are no L1P SRAMs */
+		if (device_is_compatible(dev, "ti,j721e-c71-dsp") &&
+		    !strcmp(mem_names[i], "l1pram")) {
+			dsp->mem[i].bus_addr = FDT_ADDR_T_NONE;
+			dsp->mem[i].dev_addr = FDT_ADDR_T_NONE;
+			dsp->mem[i].cpu_addr = NULL;
+			dsp->mem[i].size = 0;
+			continue;
+		}
+
+		dsp->mem[i].bus_addr = dev_read_addr_size_name(dev, mem_names[i],
+					  (fdt_addr_t *)&dsp->mem[i].size);
+		if (dsp->mem[i].bus_addr == FDT_ADDR_T_NONE) {
+			dev_err(dev, "%s bus address not found\n", mem_names[i]);
+			return -EINVAL;
+		}
+		dsp->mem[i].cpu_addr = map_physmem(dsp->mem[i].bus_addr,
+						   dsp->mem[i].size,
+						   MAP_NOCACHE);
+		dsp->mem[i].dev_addr = dsp->mem[i].bus_addr &
+					KEYSTONE_RPROC_LOCAL_ADDRESS_MASK;
+
+		dev_dbg(dev, "memory %8s: bus addr %pa size 0x%zx va %p da %pa\n",
+			mem_names[i], &dsp->mem[i].bus_addr,
+			dsp->mem[i].size, dsp->mem[i].cpu_addr,
+			&dsp->mem[i].dev_addr);
+	}
+
+	return 0;
+}
+
+/**
+ * k3_of_to_priv() - generate private data from device tree
+ * @dev:	corresponding k3 dsp processor device
+ * @dsp:	pointer to driver specific private data
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+static int k3_dsp_of_to_priv(struct udevice *dev, struct k3_dsp_privdata *dsp)
+{
+	int ret;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	ret = reset_get_by_index(dev, 0, &dsp->dsp_rst);
+	if (ret) {
+		dev_err(dev, "reset_get() failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = ti_sci_proc_of_to_priv(dev, &dsp->tsp);
+	if (ret)
+		return ret;
+
+	ret =  k3_dsp_of_get_memories(dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+/**
+ * k3_dsp_probe() - Basic probe
+ * @dev:	corresponding k3 remote processor device
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+static int k3_dsp_probe(struct udevice *dev)
+{
+	struct k3_dsp_privdata *dsp;
+	int ret;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	dsp = dev_get_priv(dev);
+
+	ret = k3_dsp_of_to_priv(dev, dsp);
+	if (ret) {
+		dev_dbg(dev, "%s: Probe failed with error %d\n", __func__, ret);
+		return ret;
+	}
+
+	dev_dbg(dev, "Remoteproc successfully probed\n");
+
+	return 0;
+}
+
+static int k3_dsp_remove(struct udevice *dev)
+{
+	struct k3_dsp_privdata *dsp = dev_get_priv(dev);
+
+	free(dsp->mem);
+
+	return 0;
+}
+
+static const struct udevice_id k3_dsp_ids[] = {
+	{ .compatible = "ti,j721e-c66-dsp"},
+	{ .compatible = "ti,j721e-c71-dsp"},
+	{}
+};
+
+U_BOOT_DRIVER(k3_dsp) = {
+	.name = "k3_dsp",
+	.of_match = k3_dsp_ids,
+	.id = UCLASS_REMOTEPROC,
+	.ops = &k3_dsp_ops,
+	.probe = k3_dsp_probe,
+	.remove = k3_dsp_remove,
+	.priv_auto_alloc_size = sizeof(struct k3_dsp_privdata),
+};
diff --git a/drivers/remoteproc/ti_k3_r5f_rproc.c b/drivers/remoteproc/ti_k3_r5f_rproc.c
new file mode 100644
index 0000000..ae1e4b9
--- /dev/null
+++ b/drivers/remoteproc/ti_k3_r5f_rproc.c
@@ -0,0 +1,816 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Texas Instruments' K3 R5 Remoteproc driver
+ *
+ * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/
+ *	Lokesh Vutla <lokeshvutla@ti.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <remoteproc.h>
+#include <errno.h>
+#include <clk.h>
+#include <reset.h>
+#include <asm/io.h>
+#include <linux/kernel.h>
+#include <linux/soc/ti/ti_sci_protocol.h>
+#include "ti_sci_proc.h"
+
+/*
+ * R5F's view of this address can either be for ATCM or BTCM with the other
+ * at address 0x0 based on loczrama signal.
+ */
+#define K3_R5_TCM_DEV_ADDR	0x41010000
+
+/* R5 TI-SCI Processor Configuration Flags */
+#define PROC_BOOT_CFG_FLAG_R5_DBG_EN			0x00000001
+#define PROC_BOOT_CFG_FLAG_R5_DBG_NIDEN			0x00000002
+#define PROC_BOOT_CFG_FLAG_R5_LOCKSTEP			0x00000100
+#define PROC_BOOT_CFG_FLAG_R5_TEINIT			0x00000200
+#define PROC_BOOT_CFG_FLAG_R5_NMFI_EN			0x00000400
+#define PROC_BOOT_CFG_FLAG_R5_TCM_RSTBASE		0x00000800
+#define PROC_BOOT_CFG_FLAG_R5_BTCM_EN			0x00001000
+#define PROC_BOOT_CFG_FLAG_R5_ATCM_EN			0x00002000
+#define PROC_BOOT_CFG_FLAG_GEN_IGN_BOOTVECTOR		0x10000000
+
+/* R5 TI-SCI Processor Control Flags */
+#define PROC_BOOT_CTRL_FLAG_R5_CORE_HALT		0x00000001
+
+/* R5 TI-SCI Processor Status Flags */
+#define PROC_BOOT_STATUS_FLAG_R5_WFE			0x00000001
+#define PROC_BOOT_STATUS_FLAG_R5_WFI			0x00000002
+#define PROC_BOOT_STATUS_FLAG_R5_CLK_GATED		0x00000004
+#define PROC_BOOT_STATUS_FLAG_R5_LOCKSTEP_PERMITTED	0x00000100
+
+#define NR_CORES	2
+
+enum cluster_mode {
+	CLUSTER_MODE_SPLIT = 0,
+	CLUSTER_MODE_LOCKSTEP,
+};
+
+/**
+ * struct k3_r5_mem - internal memory structure
+ * @cpu_addr: MPU virtual address of the memory region
+ * @bus_addr: Bus address used to access the memory region
+ * @dev_addr: Device address from remoteproc view
+ * @size: Size of the memory region
+ */
+struct k3_r5f_mem {
+	void __iomem *cpu_addr;
+	phys_addr_t bus_addr;
+	u32 dev_addr;
+	size_t size;
+};
+
+/**
+ * struct k3_r5f_core - K3 R5 core structure
+ * @dev: cached device pointer
+ * @cluster: pointer to the parent cluster.
+ * @reset: reset control handle
+ * @tsp: TI-SCI processor control handle
+ * @mem: Array of available internal memories
+ * @num_mem: Number of available memories
+ * @atcm_enable: flag to control ATCM enablement
+ * @btcm_enable: flag to control BTCM enablement
+ * @loczrama: flag to dictate which TCM is at device address 0x0
+ * @in_use: flag to tell if the core is already in use.
+ */
+struct k3_r5f_core {
+	struct udevice *dev;
+	struct k3_r5f_cluster *cluster;
+	struct reset_ctl reset;
+	struct ti_sci_proc tsp;
+	struct k3_r5f_mem *mem;
+	int num_mems;
+	u32 atcm_enable;
+	u32 btcm_enable;
+	u32 loczrama;
+	bool in_use;
+};
+
+/**
+ * struct k3_r5f_cluster - K3 R5F Cluster structure
+ * @mode: Mode to configure the Cluster - Split or LockStep
+ * @cores: Array of pointers to R5 cores within the cluster
+ */
+struct k3_r5f_cluster {
+	enum cluster_mode mode;
+	struct k3_r5f_core *cores[NR_CORES];
+};
+
+static bool is_primary_core(struct k3_r5f_core *core)
+{
+	return core == core->cluster->cores[0];
+}
+
+static int k3_r5f_proc_request(struct k3_r5f_core *core)
+{
+	struct k3_r5f_cluster *cluster = core->cluster;
+	int i, ret;
+
+	if (cluster->mode == CLUSTER_MODE_LOCKSTEP) {
+		for (i = 0; i < NR_CORES; i++) {
+			ret = ti_sci_proc_request(&cluster->cores[i]->tsp);
+			if (ret)
+				goto proc_release;
+		}
+	} else {
+		ret = ti_sci_proc_request(&core->tsp);
+	}
+
+	return 0;
+
+proc_release:
+	while (i >= 0) {
+		ti_sci_proc_release(&cluster->cores[i]->tsp);
+		i--;
+	}
+	return ret;
+}
+
+static void k3_r5f_proc_release(struct k3_r5f_core *core)
+{
+	struct k3_r5f_cluster *cluster = core->cluster;
+	int i;
+
+	if (cluster->mode == CLUSTER_MODE_LOCKSTEP)
+		for (i = 0; i < NR_CORES; i++)
+			ti_sci_proc_release(&cluster->cores[i]->tsp);
+	else
+		ti_sci_proc_release(&core->tsp);
+}
+
+static int k3_r5f_lockstep_release(struct k3_r5f_cluster *cluster)
+{
+	int ret, c;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	for (c = NR_CORES - 1; c >= 0; c--) {
+		ret = ti_sci_proc_power_domain_on(&cluster->cores[c]->tsp);
+		if (ret)
+			goto unroll_module_reset;
+	}
+
+	/* deassert local reset on all applicable cores */
+	for (c = NR_CORES - 1; c >= 0; c--) {
+		ret = reset_deassert(&cluster->cores[c]->reset);
+		if (ret)
+			goto unroll_local_reset;
+	}
+
+	return 0;
+
+unroll_local_reset:
+	while (c < NR_CORES) {
+		reset_assert(&cluster->cores[c]->reset);
+		c++;
+	}
+	c = 0;
+unroll_module_reset:
+	while (c < NR_CORES) {
+		ti_sci_proc_power_domain_off(&cluster->cores[c]->tsp);
+		c++;
+	}
+
+	return ret;
+}
+
+static int k3_r5f_split_release(struct k3_r5f_core *core)
+{
+	int ret;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	ret = ti_sci_proc_power_domain_on(&core->tsp);
+	if (ret) {
+		dev_err(core->dev, "module-reset deassert failed, ret = %d\n",
+			ret);
+		return ret;
+	}
+
+	ret = reset_deassert(&core->reset);
+	if (ret) {
+		dev_err(core->dev, "local-reset deassert failed, ret = %d\n",
+			ret);
+		if (ti_sci_proc_power_domain_off(&core->tsp))
+			dev_warn(core->dev, "module-reset assert back failed\n");
+	}
+
+	return ret;
+}
+
+static int k3_r5f_prepare(struct udevice *dev)
+{
+	struct k3_r5f_core *core = dev_get_priv(dev);
+	struct k3_r5f_cluster *cluster = core->cluster;
+	int ret = 0;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	if (cluster->mode == CLUSTER_MODE_LOCKSTEP)
+		ret = k3_r5f_lockstep_release(cluster);
+	else
+		ret = k3_r5f_split_release(core);
+
+	if (ret)
+		dev_err(dev, "Unable to enable cores for TCM loading %d\n",
+			ret);
+
+	return ret;
+}
+
+static int k3_r5f_core_sanity_check(struct k3_r5f_core *core)
+{
+	struct k3_r5f_cluster *cluster = core->cluster;
+
+	if (core->in_use) {
+		dev_err(dev, "Invalid op: Trying to load/start on already running core %d\n",
+			core->tsp.proc_id);
+		return -EINVAL;
+	}
+
+	if (cluster->mode == CLUSTER_MODE_LOCKSTEP && !cluster->cores[1]) {
+		printf("Secondary core is not probed in this cluster\n");
+		return -EAGAIN;
+	}
+
+	if (cluster->mode == CLUSTER_MODE_LOCKSTEP && !is_primary_core(core)) {
+		dev_err(dev, "Invalid op: Trying to start secondary core %d in lockstep mode\n",
+			core->tsp.proc_id);
+		return -EINVAL;
+	}
+
+	if (cluster->mode == CLUSTER_MODE_SPLIT && !is_primary_core(core)) {
+		if (!core->cluster->cores[0]->in_use) {
+			dev_err(dev, "Invalid seq: Enable primary core before loading secondary core\n");
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * k3_r5f_load() - Load up the Remote processor image
+ * @dev:	rproc device pointer
+ * @addr:	Address at which image is available
+ * @size:	size of the image
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+static int k3_r5f_load(struct udevice *dev, ulong addr, ulong size)
+{
+	struct k3_r5f_core *core = dev_get_priv(dev);
+	u32 boot_vector;
+	int ret;
+
+	dev_dbg(dev, "%s addr = 0x%lx, size = 0x%lx\n", __func__, addr, size);
+
+	ret = k3_r5f_core_sanity_check(core);
+	if (ret)
+		return ret;
+
+	ret = k3_r5f_proc_request(core);
+	if (ret)
+		return ret;
+
+	ret = k3_r5f_prepare(dev);
+	if (ret) {
+		dev_err(dev, "R5f prepare failed for core %d\n",
+			core->tsp.proc_id);
+		goto proc_release;
+	}
+
+	/* Zero out TCMs so that ECC can be effective on all TCM addresses */
+	if (core->atcm_enable)
+		memset(core->mem[0].cpu_addr, 0x00, core->mem[0].size);
+	if (core->btcm_enable)
+		memset(core->mem[1].cpu_addr, 0x00, core->mem[1].size);
+
+	ret = rproc_elf_load_image(dev, addr, size);
+	if (ret < 0) {
+		dev_err(dev, "Loading elf failedi %d\n", ret);
+		goto proc_release;
+	}
+
+	boot_vector = rproc_elf_get_boot_addr(dev, addr);
+
+	dev_dbg(dev, "%s: Boot vector = 0x%x\n", __func__, boot_vector);
+
+	ret = ti_sci_proc_set_config(&core->tsp, boot_vector, 0, 0);
+
+proc_release:
+	k3_r5f_proc_release(core);
+
+	return ret;
+}
+
+static int k3_r5f_core_halt(struct k3_r5f_core *core)
+{
+	int ret;
+
+	ret = ti_sci_proc_set_control(&core->tsp,
+				      PROC_BOOT_CTRL_FLAG_R5_CORE_HALT, 0);
+	if (ret)
+		dev_err(core->dev, "Core %d failed to stop\n",
+			core->tsp.proc_id);
+
+	return ret;
+}
+
+static int k3_r5f_core_run(struct k3_r5f_core *core)
+{
+	int ret;
+
+	ret = ti_sci_proc_set_control(&core->tsp,
+				      0, PROC_BOOT_CTRL_FLAG_R5_CORE_HALT);
+	if (ret) {
+		dev_err(core->dev, "Core %d failed to start\n",
+			core->tsp.proc_id);
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * k3_r5f_start() - Start the remote processor
+ * @dev:	rproc device pointer
+ *
+ * Return: 0 if all went ok, else return appropriate error
+ */
+static int k3_r5f_start(struct udevice *dev)
+{
+	struct k3_r5f_core *core = dev_get_priv(dev);
+	struct k3_r5f_cluster *cluster = core->cluster;
+	int ret, c;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	ret = k3_r5f_core_sanity_check(core);
+	if (ret)
+		return ret;
+
+	ret = k3_r5f_proc_request(core);
+	if (ret)
+		return ret;
+
+	if (cluster->mode == CLUSTER_MODE_LOCKSTEP) {
+		if (is_primary_core(core)) {
+			for (c = NR_CORES - 1; c >= 0; c--) {
+				ret = k3_r5f_core_run(cluster->cores[c]);
+				if (ret)
+					goto unroll_core_run;
+			}
+		} else {
+			dev_err(dev, "Invalid op: Trying to start secondary core %d in lockstep mode\n",
+				core->tsp.proc_id);
+			ret = -EINVAL;
+			goto proc_release;
+		}
+	} else {
+		ret = k3_r5f_core_run(core);
+		if (ret)
+			goto proc_release;
+	}
+
+	core->in_use = true;
+
+	k3_r5f_proc_release(core);
+	return 0;
+
+unroll_core_run:
+	while (c < NR_CORES) {
+		k3_r5f_core_halt(cluster->cores[c]);
+		c++;
+	}
+proc_release:
+	k3_r5f_proc_release(core);
+
+	return ret;
+}
+
+static int k3_r5f_split_reset(struct k3_r5f_core *core)
+{
+	int ret;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	if (reset_assert(&core->reset))
+		ret = -EINVAL;
+
+	if (ti_sci_proc_power_domain_off(&core->tsp))
+		ret = -EINVAL;
+
+	return ret;
+}
+
+static int k3_r5f_lockstep_reset(struct k3_r5f_cluster *cluster)
+{
+	int ret = 0, c;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	for (c = 0; c < NR_CORES; c++)
+		if (reset_assert(&cluster->cores[c]->reset))
+			ret = -EINVAL;
+
+	/* disable PSC modules on all applicable cores */
+	for (c = 0; c < NR_CORES; c++)
+		if (ti_sci_proc_power_domain_off(&cluster->cores[c]->tsp))
+			ret = -EINVAL;
+
+	return ret;
+}
+
+static int k3_r5f_unprepare(struct udevice *dev)
+{
+	struct k3_r5f_core *core = dev_get_priv(dev);
+	struct k3_r5f_cluster *cluster = core->cluster;
+	int ret;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	if (cluster->mode == CLUSTER_MODE_LOCKSTEP) {
+		if (is_primary_core(core))
+			ret = k3_r5f_lockstep_reset(cluster);
+	} else {
+		ret = k3_r5f_split_reset(core);
+	}
+
+	if (ret)
+		dev_warn(dev, "Unable to enable cores for TCM loading %d\n",
+			 ret);
+
+	return 0;
+}
+
+static int k3_r5f_stop(struct udevice *dev)
+{
+	struct k3_r5f_core *core = dev_get_priv(dev);
+	struct k3_r5f_cluster *cluster = core->cluster;
+	int c, ret;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	ret = k3_r5f_proc_request(core);
+	if (ret)
+		return ret;
+
+	core->in_use = false;
+
+	if (cluster->mode == CLUSTER_MODE_LOCKSTEP) {
+		if (is_primary_core(core)) {
+			for (c = 0; c < NR_CORES; c++)
+				k3_r5f_core_halt(cluster->cores[c]);
+		} else {
+			dev_err(dev, "Invalid op: Trying to stop secondary core in lockstep mode\n");
+			ret = -EINVAL;
+			goto proc_release;
+		}
+	} else {
+		k3_r5f_core_halt(core);
+	}
+
+	ret = k3_r5f_unprepare(dev);
+proc_release:
+	k3_r5f_proc_release(core);
+	return ret;
+}
+
+static void *k3_r5f_da_to_va(struct udevice *dev, ulong da, ulong size)
+{
+	struct k3_r5f_core *core = dev_get_priv(dev);
+	void __iomem *va = NULL;
+	phys_addr_t bus_addr;
+	u32 dev_addr, offset;
+	ulong mem_size;
+	int i;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	if (size <= 0)
+		return NULL;
+
+	for (i = 0; i < core->num_mems; i++) {
+		bus_addr = core->mem[i].bus_addr;
+		dev_addr = core->mem[i].dev_addr;
+		mem_size = core->mem[i].size;
+
+		if (da >= bus_addr && (da + size) <= (bus_addr + mem_size)) {
+			offset = da - bus_addr;
+			va = core->mem[i].cpu_addr + offset;
+			return (__force void *)va;
+		}
+
+		if (da >= dev_addr && (da + size) <= (dev_addr + mem_size)) {
+			offset = da - dev_addr;
+			va = core->mem[i].cpu_addr + offset;
+			return (__force void *)va;
+		}
+	}
+
+	/* Assume it is DDR region and return da */
+	return map_physmem(da, size, MAP_NOCACHE);
+}
+
+static int k3_r5f_init(struct udevice *dev)
+{
+	return 0;
+}
+
+static int k3_r5f_reset(struct udevice *dev)
+{
+	return 0;
+}
+
+static const struct dm_rproc_ops k3_r5f_rproc_ops = {
+	.init = k3_r5f_init,
+	.reset = k3_r5f_reset,
+	.start = k3_r5f_start,
+	.stop = k3_r5f_stop,
+	.load = k3_r5f_load,
+	.device_to_virt = k3_r5f_da_to_va,
+};
+
+static int k3_r5f_rproc_configure(struct k3_r5f_core *core)
+{
+	struct k3_r5f_cluster *cluster = core->cluster;
+	u32 set_cfg = 0, clr_cfg = 0, cfg, ctrl, sts;
+	u64 boot_vec = 0;
+	int ret;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	ret = ti_sci_proc_request(&core->tsp);
+	if (ret < 0)
+		return ret;
+
+	/* Do not touch boot vector now. Load will take care of it. */
+	clr_cfg |= PROC_BOOT_CFG_FLAG_GEN_IGN_BOOTVECTOR;
+
+	ret = ti_sci_proc_get_status(&core->tsp, &boot_vec, &cfg, &ctrl, &sts);
+	if (ret)
+		goto out;
+
+	/* Sanity check for Lockstep mode */
+	if (cluster->mode && is_primary_core(core) &&
+	    !(sts & PROC_BOOT_STATUS_FLAG_R5_LOCKSTEP_PERMITTED)) {
+		dev_err(core->dev, "LockStep mode not permitted on this device\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Primary core only configuration */
+	if (is_primary_core(core)) {
+		/* always enable ARM mode */
+		clr_cfg |= PROC_BOOT_CFG_FLAG_R5_TEINIT;
+		if (cluster->mode == CLUSTER_MODE_LOCKSTEP)
+			set_cfg |= PROC_BOOT_CFG_FLAG_R5_LOCKSTEP;
+		else
+			clr_cfg |= PROC_BOOT_CFG_FLAG_R5_LOCKSTEP;
+	}
+
+	if (core->atcm_enable)
+		set_cfg |= PROC_BOOT_CFG_FLAG_R5_ATCM_EN;
+	else
+		clr_cfg |= PROC_BOOT_CFG_FLAG_R5_ATCM_EN;
+
+	if (core->btcm_enable)
+		set_cfg |= PROC_BOOT_CFG_FLAG_R5_BTCM_EN;
+	else
+		clr_cfg |= PROC_BOOT_CFG_FLAG_R5_BTCM_EN;
+
+	if (core->loczrama)
+		set_cfg |= PROC_BOOT_CFG_FLAG_R5_TCM_RSTBASE;
+	else
+		clr_cfg |= PROC_BOOT_CFG_FLAG_R5_TCM_RSTBASE;
+
+	ret = k3_r5f_core_halt(core);
+	if (ret)
+		goto out;
+
+	ret = ti_sci_proc_set_config(&core->tsp, boot_vec, set_cfg, clr_cfg);
+out:
+	ti_sci_proc_release(&core->tsp);
+	return ret;
+}
+
+static int ti_sci_proc_of_to_priv(struct udevice *dev, struct ti_sci_proc *tsp)
+{
+	u32 ids[2];
+	int ret;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	tsp->sci = ti_sci_get_by_phandle(dev, "ti,sci");
+	if (IS_ERR(tsp->sci)) {
+		dev_err(dev, "ti_sci get failed: %ld\n", PTR_ERR(tsp->sci));
+		return PTR_ERR(tsp->sci);
+	}
+
+	ret = dev_read_u32_array(dev, "ti,sci-proc-ids", ids, 2);
+	if (ret) {
+		dev_err(dev, "Proc IDs not populated %d\n", ret);
+		return ret;
+	}
+
+	tsp->ops = &tsp->sci->ops.proc_ops;
+	tsp->proc_id = ids[0];
+	tsp->host_id = ids[1];
+	tsp->dev_id = dev_read_u32_default(dev, "ti,sci-dev-id",
+					   TI_SCI_RESOURCE_NULL);
+	if (tsp->dev_id == TI_SCI_RESOURCE_NULL) {
+		dev_err(dev, "Device ID not populated %d\n", ret);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int k3_r5f_of_to_priv(struct k3_r5f_core *core)
+{
+	int ret;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	core->atcm_enable = dev_read_u32_default(core->dev, "atcm-enable", 0);
+	core->btcm_enable = dev_read_u32_default(core->dev, "btcm-enable", 1);
+	core->loczrama = dev_read_u32_default(core->dev, "loczrama", 1);
+
+	ret = ti_sci_proc_of_to_priv(core->dev, &core->tsp);
+	if (ret)
+		return ret;
+
+	ret = reset_get_by_index(core->dev, 0, &core->reset);
+	if (ret) {
+		dev_err(core->dev, "Reset lines not available: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int k3_r5f_core_of_get_memories(struct k3_r5f_core *core)
+{
+	static const char * const mem_names[] = {"atcm", "btcm"};
+	struct udevice *dev = core->dev;
+	int i;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	core->num_mems = ARRAY_SIZE(mem_names);
+	core->mem = calloc(core->num_mems, sizeof(*core->mem));
+	if (!core->mem)
+		return -ENOMEM;
+
+	for (i = 0; i < core->num_mems; i++) {
+		core->mem[i].bus_addr = dev_read_addr_size_name(dev,
+								mem_names[i],
+					(fdt_addr_t *)&core->mem[i].size);
+		if (core->mem[i].bus_addr == FDT_ADDR_T_NONE) {
+			dev_err(dev, "%s bus address not found\n",
+				mem_names[i]);
+			return -EINVAL;
+		}
+		core->mem[i].cpu_addr = map_physmem(core->mem[i].bus_addr,
+						    core->mem[i].size,
+						    MAP_NOCACHE);
+		if (!strcmp(mem_names[i], "atcm")) {
+			core->mem[i].dev_addr = core->loczrama ?
+							0 : K3_R5_TCM_DEV_ADDR;
+		} else {
+			core->mem[i].dev_addr = core->loczrama ?
+							K3_R5_TCM_DEV_ADDR : 0;
+		}
+
+		dev_dbg(dev, "memory %8s: bus addr %pa size 0x%zx va %p da 0x%x\n",
+			mem_names[i], &core->mem[i].bus_addr,
+			core->mem[i].size, core->mem[i].cpu_addr,
+			core->mem[i].dev_addr);
+	}
+
+	return 0;
+}
+
+/**
+ * k3_r5f_probe() - Basic probe
+ * @dev:	corresponding k3 remote processor device
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+static int k3_r5f_probe(struct udevice *dev)
+{
+	struct k3_r5f_cluster *cluster = dev_get_priv(dev->parent);
+	struct k3_r5f_core *core = dev_get_priv(dev);
+	bool r_state;
+	int ret;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	core->dev = dev;
+	ret = k3_r5f_of_to_priv(core);
+	if (ret)
+		return ret;
+
+	core->cluster = cluster;
+	/* Assume Primary core gets probed first */
+	if (!cluster->cores[0])
+		cluster->cores[0] = core;
+	else
+		cluster->cores[1] = core;
+
+	ret = k3_r5f_core_of_get_memories(core);
+	if (ret) {
+		dev_err(dev, "Rproc getting internal memories failed\n");
+		return ret;
+	}
+
+	ret = core->tsp.sci->ops.dev_ops.is_on(core->tsp.sci, core->tsp.dev_id,
+					       &r_state, &core->in_use);
+	if (ret)
+		return ret;
+
+	if (core->in_use) {
+		dev_info(dev, "Core %d is already in use. No rproc commands work\n",
+			 core->tsp.proc_id);
+		return 0;
+	}
+
+	/* Make sure Local reset is asserted. Redundant? */
+	reset_assert(&core->reset);
+
+	ret = k3_r5f_rproc_configure(core);
+	if (ret) {
+		dev_err(dev, "rproc configure failed %d\n", ret);
+		return ret;
+	}
+
+	dev_dbg(dev, "Remoteproc successfully probed\n");
+
+	return 0;
+}
+
+static int k3_r5f_remove(struct udevice *dev)
+{
+	struct k3_r5f_core *core = dev_get_priv(dev);
+
+	free(core->mem);
+
+	ti_sci_proc_release(&core->tsp);
+
+	return 0;
+}
+
+static const struct udevice_id k3_r5f_rproc_ids[] = {
+	{ .compatible = "ti,am654-r5f"},
+	{ .compatible = "ti,j721e-r5f"},
+	{}
+};
+
+U_BOOT_DRIVER(k3_r5f_rproc) = {
+	.name = "k3_r5f_rproc",
+	.of_match = k3_r5f_rproc_ids,
+	.id = UCLASS_REMOTEPROC,
+	.ops = &k3_r5f_rproc_ops,
+	.probe = k3_r5f_probe,
+	.remove = k3_r5f_remove,
+	.priv_auto_alloc_size = sizeof(struct k3_r5f_core),
+};
+
+static int k3_r5f_cluster_probe(struct udevice *dev)
+{
+	struct k3_r5f_cluster *cluster = dev_get_priv(dev);
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	cluster->mode = dev_read_u32_default(dev, "lockstep-mode",
+					     CLUSTER_MODE_LOCKSTEP);
+
+	if (device_get_child_count(dev) != 2) {
+		dev_err(dev, "Invalid number of R5 cores");
+		return -EINVAL;
+	}
+
+	dev_dbg(dev, "%s: Cluster successfully probed in %s mode\n",
+		__func__, cluster->mode ? "lockstep" : "split");
+
+	return 0;
+}
+
+static const struct udevice_id k3_r5fss_ids[] = {
+	{ .compatible = "ti,am654-r5fss"},
+	{ .compatible = "ti,j721e-r5fss"},
+	{}
+};
+
+U_BOOT_DRIVER(k3_r5fss) = {
+	.name = "k3_r5fss",
+	.of_match = k3_r5fss_ids,
+	.id = UCLASS_MISC,
+	.probe = k3_r5f_cluster_probe,
+	.priv_auto_alloc_size = sizeof(struct k3_r5f_cluster),
+};
diff --git a/drivers/remoteproc/ti_sci_proc.h b/drivers/remoteproc/ti_sci_proc.h
index ccfc39e..f8299d1 100644
--- a/drivers/remoteproc/ti_sci_proc.h
+++ b/drivers/remoteproc/ti_sci_proc.h
@@ -19,12 +19,14 @@
  * @proc_id: processor id for the consumer remoteproc device
  * @host_id: host id to pass the control over for this consumer remoteproc
  *	     device
+ * @dev_id: Device ID as identified by system controller.
  */
 struct ti_sci_proc {
 	const struct ti_sci_handle *sci;
 	const struct ti_sci_proc_ops *ops;
 	u8 proc_id;
 	u8 host_id;
+	u16 dev_id;
 };
 
 static inline int ti_sci_proc_request(struct ti_sci_proc *tsp)
@@ -118,4 +120,29 @@
 	return ret;
 }
 
+static inline int ti_sci_proc_power_domain_on(struct ti_sci_proc *tsp)
+{
+	int ret;
+
+	debug("%s: dev_id = %d\n", __func__, tsp->dev_id);
+
+	ret = tsp->sci->ops.dev_ops.get_device_exclusive(tsp->sci, tsp->dev_id);
+	if (ret)
+		pr_err("Power-domain on failed for dev = %d\n", tsp->dev_id);
+
+	return ret;
+}
+
+static inline int ti_sci_proc_power_domain_off(struct ti_sci_proc *tsp)
+{
+	int ret;
+
+	debug("%s: dev_id = %d\n", __func__, tsp->dev_id);
+
+	ret = tsp->sci->ops.dev_ops.put_device(tsp->sci, tsp->dev_id);
+	if (ret)
+		pr_err("Power-domain off failed for dev = %d\n", tsp->dev_id);
+
+	return ret;
+}
 #endif /* REMOTEPROC_TI_SCI_PROC_H */
diff --git a/include/configs/am335x_guardian.h b/include/configs/am335x_guardian.h
index 8bde198..b45b8d2 100644
--- a/include/configs/am335x_guardian.h
+++ b/include/configs/am335x_guardian.h
@@ -16,10 +16,14 @@
 #define CONFIG_TIMESTAMP
 #endif
 
+#define CONFIG_SYS_BOOTM_LEN		(16 << 20)
+
 /* Clock Defines */
 #define V_OSCK				24000000  /* Clock output from T2 */
 #define V_SCLK				(V_OSCK)
 
+#define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+
 #ifndef CONFIG_SPL_BUILD
 
 #define MEM_LAYOUT_ENV_SETTINGS \
@@ -30,7 +34,6 @@
 	"ramdisk_addr_r=0x88080000\0" \
 
 #define BOOT_TARGET_DEVICES(func) \
-	func(MMC, mmc, 0) \
 	func(UBIFS, ubifs, 0) \
 	func(PXE, pxe, na) \
 	func(DHCP, dhcp, na)
@@ -44,11 +47,12 @@
 	MEM_LAYOUT_ENV_SETTINGS \
 	BOOTENV \
 	"bootlimit=3\0" \
+	"bootubivol=rootfs\0" \
 	"altbootcmd=" \
 		"setenv boot_config \"extlinux-rollback.conf\"; " \
 		"run distro_bootcmd\0"
 
-#endif /* CONFIG_SPL_BUILD */
+#endif /* ! CONFIG_SPL_BUILD */
 
 /* NS16550 Configuration */
 #define CONFIG_SYS_NS16550_COM1		0x44e09000	/* UART0 */
@@ -65,9 +69,6 @@
 #define CONFIG_SYS_BOOTCOUNT_LE
 
 #ifdef CONFIG_NAND
-#define CONFIG_ENV_OFFSET		0x300000
-#define CONFIG_ENV_OFFSET_REDUND	0x340000
-#define CONFIG_ENV_SIZE			0x040000
 
 #define CONFIG_SYS_NAND_5_ADDR_CYCLE
 #define CONFIG_SYS_NAND_PAGE_COUNT      (CONFIG_SYS_NAND_BLOCK_SIZE / \
diff --git a/include/configs/am65x_evm.h b/include/configs/am65x_evm.h
index 0249a20..1149d55 100644
--- a/include/configs/am65x_evm.h
+++ b/include/configs/am65x_evm.h
@@ -12,6 +12,7 @@
 #include <linux/sizes.h>
 #include <config_distro_bootcmd.h>
 #include <environment/ti/mmc.h>
+#include <environment/ti/k3_rproc.h>
 
 #define CONFIG_ENV_SIZE			(128 << 10)
 
@@ -98,12 +99,20 @@
 		"${bootdir}/${name_fit}\0"				\
 	"partitions=" PARTS_DEFAULT
 
+#ifdef DEFAULT_RPROCS
+#undef DEFAULT_RPROCS
+#endif
+#define DEFAULT_RPROCS	""						\
+		"0 /lib/firmware/am65x-mcu-r5f0_0-fw "			\
+		"1 /lib/firmware/am65x-mcu-r5f0_1-fw "
+
 /* Incorporate settings into the U-Boot environment */
 #define CONFIG_EXTRA_ENV_SETTINGS					\
 	DEFAULT_MMC_TI_ARGS						\
 	DEFAULT_FIT_TI_ARGS						\
 	EXTRA_ENV_AM65X_BOARD_SETTINGS					\
-	EXTRA_ENV_AM65X_BOARD_SETTINGS_MMC
+	EXTRA_ENV_AM65X_BOARD_SETTINGS_MMC				\
+	EXTRA_ENV_RPROC_SETTINGS
 
 /* MMC ENV related defines */
 #ifdef CONFIG_ENV_IS_IN_MMC
diff --git a/include/configs/j721e_evm.h b/include/configs/j721e_evm.h
index 5fe77ef..dbe226b 100644
--- a/include/configs/j721e_evm.h
+++ b/include/configs/j721e_evm.h
@@ -12,6 +12,7 @@
 #include <linux/sizes.h>
 #include <config_distro_bootcmd.h>
 #include <environment/ti/mmc.h>
+#include <environment/ti/k3_rproc.h>
 
 #define CONFIG_ENV_SIZE			(128 << 10)
 
@@ -87,11 +88,22 @@
 	"get_kern_mmc=load mmc ${bootpart} ${loadaddr} "		\
 		"${bootdir}/${name_kern}\0"
 
+#ifdef DEFAULT_RPROCS
+#undef DEFAULT_RPROCS
+#endif
+#define DEFAULT_RPROCS	""						\
+		"3 /lib/firmware/j7-main-r5f0_1-fw "			\
+		"4 /lib/firmware/j7-main-r5f1_0-fw "			\
+		"6 /lib/firmware/j7-c66_0-fw "				\
+		"7 /lib/firmware/j7-c66_1-fw "				\
+		"8 /lib/firmware/j7-c71_0-fw "
+
 /* Incorporate settings into the U-Boot environment */
 #define CONFIG_EXTRA_ENV_SETTINGS					\
 	DEFAULT_MMC_TI_ARGS						\
 	EXTRA_ENV_J721E_BOARD_SETTINGS					\
-	EXTRA_ENV_J721E_BOARD_SETTINGS_MMC
+	EXTRA_ENV_J721E_BOARD_SETTINGS_MMC				\
+	EXTRA_ENV_RPROC_SETTINGS
 
 /* Now for the remaining common defines */
 #include <configs/ti_armv7_common.h>
diff --git a/include/configs/tao3530.h b/include/configs/tao3530.h
index c34e785..7a54fe3 100644
--- a/include/configs/tao3530.h
+++ b/include/configs/tao3530.h
@@ -114,7 +114,7 @@
 		"bootm ${loadaddr}\0" \
 
 #define CONFIG_BOOTCOMMAND \
-	"if mmc rescan ${mmcdev}; then " \
+	"mmc dev ${mmcdev}; if mmc rescan; then " \
 		"if run loadbootscript; then " \
 			"run bootscript; " \
 		"else " \
diff --git a/include/configs/ti_armv7_common.h b/include/configs/ti_armv7_common.h
index 2de6bc2..6d15304 100644
--- a/include/configs/ti_armv7_common.h
+++ b/include/configs/ti_armv7_common.h
@@ -60,7 +60,7 @@
 		"do;" \
 		"setenv overlaystring ${overlaystring}'#'${overlay};" \
 		"done;\0" \
-	"run_fit=bootm ${loadaddr}#${fdtfile}${overlaystring}\0" \
+	"run_fit=bootm ${addr_fit}#${fdtfile}${overlaystring}\0" \
 	"loadfit=run args_mmc; run run_fit;\0" \
 
 /*
diff --git a/include/dm/device.h b/include/dm/device.h
index d121042..defda0a 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -405,6 +405,15 @@
 int device_get_child(struct udevice *parent, int index, struct udevice **devp);
 
 /**
+ * device_get_child_count() - Get the available child count of a device
+ *
+ * Returns the number of children to a device.
+ *
+ * @parent:	Parent device to check
+ */
+int device_get_child_count(struct udevice *parent);
+
+/**
  * device_find_child_by_seq() - Find a child device based on a sequence
  *
  * This searches for a device with the given seq or req_seq.
diff --git a/include/environment/ti/k3_rproc.h b/include/environment/ti/k3_rproc.h
new file mode 100644
index 0000000..3418cb4
--- /dev/null
+++ b/include/environment/ti/k3_rproc.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * rproc environment variable definitions for various TI K3 SoCs.
+ */
+
+#ifndef __TI_RPROC_H
+#define __TI_RPROC_H
+
+/*
+ * should contain a list of <rproc_id fw_name> tuplies,
+ * override in board config files with the actual list
+ */
+#define DEFAULT_RPROCS ""
+
+#ifdef CONFIG_CMD_REMOTEPROC
+#define EXTRA_ENV_RPROC_SETTINGS					\
+	"dorprocboot=0\0"						\
+	"boot_rprocs="							\
+		"if test ${dorprocboot} -eq 1 && test ${boot} = mmc; then "\
+			"rproc init;"					\
+			"run boot_rprocs_mmc;"				\
+		"fi;\0"							\
+	"rproc_load_and_boot_one="					\
+		"if load mmc ${bootpart} $loadaddr ${rproc_fw}; then "	\
+			"if rproc load ${rproc_id} ${loadaddr} ${filesize}; then "\
+				"rproc start ${rproc_id};"		\
+			"fi;"						\
+		"fi\0"							\
+	"boot_rprocs_mmc="						\
+		"env set rproc_id;"					\
+		"env set rproc_fw;"					\
+		"for i in ${rproc_fw_binaries} ; do "			\
+			"if test -z \"${rproc_id}\" ; then "		\
+				"env set rproc_id $i;"			\
+			"else "						\
+				"env set rproc_fw $i;"			\
+				"run rproc_load_and_boot_one;"		\
+				"env set rproc_id;"			\
+				"env set rproc_fw;"			\
+			"fi;"						\
+		"done\0"						\
+	"rproc_fw_binaries="						\
+		DEFAULT_RPROCS						\
+		"\0"
+#else
+#define EXTRA_ENV_RPROC_SETTINGS					\
+	"boot_rprocs= \0"
+#endif /* CONFIG_CMD_REMOTEPROC */
+
+#endif /* __TI_RPROC_H */
diff --git a/include/remoteproc.h b/include/remoteproc.h
index 4987194..046cd9e 100644
--- a/include/remoteproc.h
+++ b/include/remoteproc.h
@@ -122,9 +122,10 @@
 	 *
 	 * @dev:	Remote proc device
 	 * @da:		Device address
+	 * @size:	Size of the memory region @da is pointing to
 	 * @return virtual address.
 	 */
-	void * (*device_to_virt)(struct udevice *dev, ulong da);
+	void * (*device_to_virt)(struct udevice *dev, ulong da, ulong size);
 };
 
 /* Accessor */
@@ -214,12 +215,68 @@
 int rproc_elf32_sanity_check(ulong addr, ulong size);
 
 /**
+ * rproc_elf64_sanity_check() - Verify if an image is a valid ELF32 one
+ *
+ * Check if a valid ELF64 image exists at the given memory location. Verify
+ * basic ELF64 format requirements like magic number and sections size.
+ *
+ * @addr:	address of the image to verify
+ * @size:	size of the image
+ * @return 0 if the image looks good, else appropriate error value.
+ */
+int rproc_elf64_sanity_check(ulong addr, ulong size);
+
+/**
+ * rproc_elf_sanity_check() - Verify if an image is a valid ELF one
+ *
+ * Check if a valid ELF image exists at the given memory location. Auto
+ * detects ELF32/ELF64 and verifies basic ELF64/ELF32 format requirements
+ * like magic number and sections size.
+ *
+ * @addr:	address of the image to verify
+ * @size:	size of the image
+ * @return 0 if the image looks good, else appropriate error value.
+ */
+int rproc_elf_sanity_check(ulong addr, ulong size);
+
+/**
  * rproc_elf32_load_image() - load an ELF32 image
  * @dev:	device loading the ELF32 image
  * @addr:	valid ELF32 image address
+ * @size:	size of the image
  * @return 0 if the image is successfully loaded, else appropriate error value.
  */
-int rproc_elf32_load_image(struct udevice *dev, unsigned long addr);
+int rproc_elf32_load_image(struct udevice *dev, unsigned long addr, ulong size);
+
+/**
+ * rproc_elf64_load_image() - load an ELF64 image
+ * @dev:	device loading the ELF64 image
+ * @addr:	valid ELF64 image address
+ * @size:	size of the image
+ * @return 0 if the image is successfully loaded, else appropriate error value.
+ */
+int rproc_elf64_load_image(struct udevice *dev, ulong addr, ulong size);
+
+/**
+ * rproc_elf_load_image() - load an ELF image
+ * @dev:	device loading the ELF image
+ * @addr:	valid ELF image address
+ * @size:	size of the image
+ *
+ * Auto detects if the image is ELF32 or ELF64 image and load accordingly.
+ * @return 0 if the image is successfully loaded, else appropriate error value.
+ */
+int rproc_elf_load_image(struct udevice *dev, unsigned long addr, ulong size);
+
+/**
+ * rproc_elf_get_boot_addr() - Get rproc's boot address.
+ * @dev:	device loading the ELF image
+ * @addr:	valid ELF image address
+ *
+ * This function returns the entry point address of the ELF
+ * image.
+ */
+ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr);
 #else
 static inline int rproc_init(void) { return -ENOSYS; }
 static inline int rproc_dev_init(int id) { return -ENOSYS; }
@@ -232,8 +289,21 @@
 static inline int rproc_is_running(int id) { return -ENOSYS; }
 static inline int rproc_elf32_sanity_check(ulong addr,
 					   ulong size) { return -ENOSYS; }
+static inline int rproc_elf64_sanity_check(ulong addr,
+					   ulong size) { return -ENOSYS; }
+static inline int rproc_elf_sanity_check(ulong addr,
+					 ulong size) { return -ENOSYS; }
 static inline int rproc_elf32_load_image(struct udevice *dev,
-					 unsigned long addr) { return -ENOSYS; }
+					 unsigned long addr, ulong size)
+{ return -ENOSYS; }
+static inline int rproc_elf64_load_image(struct udevice *dev, ulong addr,
+					 ulong size)
+{ return -ENOSYS; }
+static inline int rproc_elf_load_image(struct udevice *dev, ulong addr,
+				       ulong size)
+{ return -ENOSYS; }
+static inline ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr)
+{ return 0; }
 #endif
 
 #endif	/* _RPROC_H_ */
diff --git a/include/spl.h b/include/spl.h
index 4359636..b5387ef 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -434,6 +434,9 @@
 		 int raw_part,
 		 unsigned long raw_sect);
 
+int spl_ymodem_load_image(struct spl_image_info *spl_image,
+			  struct spl_boot_device *bootdev);
+
 /**
  * spl_invoke_atf - boot using an ARM trusted firmware image
  */
diff --git a/test/dm/bus.c b/test/dm/bus.c
index 93f3acd..1ad45ad 100644
--- a/test/dm/bus.c
+++ b/test/dm/bus.c
@@ -8,6 +8,7 @@
 #include <os.h>
 #endif
 #include <dm.h>
+#include <dm/device.h>
 #include <dm/device-internal.h>
 #include <dm/test.h>
 #include <dm/uclass-internal.h>
@@ -371,7 +372,6 @@
 {
 	struct dm_test_parent_platdata *plat;
 	struct udevice *bus, *dev;
-	int child_count;
 
 	/* Check that the bus has no children */
 	ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
@@ -380,7 +380,7 @@
 
 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
 
-	for (device_find_first_child(bus, &dev), child_count = 0;
+	for (device_find_first_child(bus, &dev);
 	     dev;
 	     device_find_next_child(&dev)) {
 		/* Check that platform data is allocated */
@@ -399,22 +399,20 @@
 		ut_asserteq_ptr(plat, dev_get_parent_platdata(dev));
 		ut_asserteq(1, plat->count);
 		ut_assertok(device_probe(dev));
-		child_count++;
 	}
-	ut_asserteq(3, child_count);
+	ut_asserteq(3, device_get_child_count(bus));
 
 	/* Removing the bus should also have no effect (it is still bound) */
 	device_remove(bus, DM_REMOVE_NORMAL);
-	for (device_find_first_child(bus, &dev), child_count = 0;
+	for (device_find_first_child(bus, &dev);
 	     dev;
 	     device_find_next_child(&dev)) {
 		/* Check that platform data is allocated */
 		plat = dev_get_parent_platdata(dev);
 		ut_assert(plat != NULL);
 		ut_asserteq(1, plat->count);
-		child_count++;
 	}
-	ut_asserteq(3, child_count);
+	ut_asserteq(3, device_get_child_count(bus));
 
 	/* Unbind all the children */
 	do {
@@ -425,16 +423,15 @@
 
 	/* Now the child platdata should be removed and re-added */
 	device_probe(bus);
-	for (device_find_first_child(bus, &dev), child_count = 0;
+	for (device_find_first_child(bus, &dev);
 	     dev;
 	     device_find_next_child(&dev)) {
 		/* Check that platform data is allocated */
 		plat = dev_get_parent_platdata(dev);
 		ut_assert(plat != NULL);
 		ut_asserteq(0, plat->count);
-		child_count++;
 	}
-	ut_asserteq(3, child_count);
+	ut_asserteq(3, device_get_child_count(bus));
 
 	return 0;
 }
@@ -480,19 +477,17 @@
 {
 	struct dm_test_parent_platdata *plat;
 	struct udevice *bus, *dev;
-	int child_count;
 
 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
-	for (device_find_first_child(bus, &dev), child_count = 0;
+	for (device_find_first_child(bus, &dev);
 	     dev;
 	     device_find_next_child(&dev)) {
 		/* Check that platform data is allocated */
 		plat = dev_get_parent_platdata(dev);
 		ut_assert(plat != NULL);
 		ut_asserteq(1, plat->bind_flag);
-		child_count++;
 	}
-	ut_asserteq(3, child_count);
+	ut_asserteq(3, device_get_child_count(bus));
 
 	return 0;
 }
@@ -503,19 +498,17 @@
 {
 	struct dm_test_parent_platdata *plat;
 	struct udevice *bus, *dev;
-	int child_count;
 
 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
-	for (device_find_first_child(bus, &dev), child_count = 0;
+	for (device_find_first_child(bus, &dev);
 	     dev;
 	     device_find_next_child(&dev)) {
 		/* Check that platform data is allocated */
 		plat = dev_get_parent_platdata(dev);
 		ut_assert(plat != NULL);
 		ut_asserteq(2, plat->uclass_bind_flag);
-		child_count++;
 	}
-	ut_asserteq(3, child_count);
+	ut_asserteq(3, device_get_child_count(bus));
 
 	return 0;
 }
@@ -529,14 +522,13 @@
 static int dm_test_bus_child_pre_probe_uclass(struct unit_test_state *uts)
 {
 	struct udevice *bus, *dev;
-	int child_count;
 
 	/*
 	 * See testfdt_drv_probe() which effectively checks that the uclass
 	 * flag is set before that method is called
 	 */
 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
-	for (device_find_first_child(bus, &dev), child_count = 0;
+	for (device_find_first_child(bus, &dev);
 	     dev;
 	     device_find_next_child(&dev)) {
 		struct dm_test_priv *priv = dev_get_priv(dev);
@@ -549,9 +541,8 @@
 		ut_assert(priv != NULL);
 		ut_asserteq(1, priv->uclass_flag);
 		ut_asserteq(1, priv->uclass_total);
-		child_count++;
 	}
-	ut_asserteq(3, child_count);
+	ut_asserteq(3, device_get_child_count(bus));
 
 	return 0;
 }
@@ -565,14 +556,13 @@
 static int dm_test_bus_child_post_probe_uclass(struct unit_test_state *uts)
 {
 	struct udevice *bus, *dev;
-	int child_count;
 
 	/*
 	 * See testfdt_drv_probe() which effectively initializes that
 	 * the uclass postp flag is set to a value
 	 */
 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
-	for (device_find_first_child(bus, &dev), child_count = 0;
+	for (device_find_first_child(bus, &dev);
 	     dev;
 	     device_find_next_child(&dev)) {
 		struct dm_test_priv *priv = dev_get_priv(dev);
@@ -584,9 +574,8 @@
 		priv = dev_get_priv(dev);
 		ut_assert(priv != NULL);
 		ut_asserteq(0, priv->uclass_postp);
-		child_count++;
 	}
-	ut_asserteq(3, child_count);
+	ut_asserteq(3, device_get_child_count(bus));
 
 	return 0;
 }
diff --git a/test/dm/remoteproc.c b/test/dm/remoteproc.c
index a2c4be7..1d9a9b3 100644
--- a/test/dm/remoteproc.c
+++ b/test/dm/remoteproc.c
@@ -171,12 +171,11 @@
 	ut_assertnonnull(loaded_firmware);
 	memset(loaded_firmware, 0, loaded_firmware_size);
 
-	/* Verify valid ELF format */
-	ut_assertok(rproc_elf32_sanity_check((ulong)valid_elf32, size));
-
 	/* Load firmware in loaded_firmware, and verify it */
-	ut_assertok(rproc_elf32_load_image(dev, (unsigned long)valid_elf32));
+	ut_assertok(rproc_elf32_load_image(dev, (ulong)valid_elf32, size));
 	ut_assertok(memcmp(loaded_firmware, valid_elf32, loaded_firmware_size));
+	ut_asserteq(rproc_elf_get_boot_addr(dev, (unsigned long)valid_elf32),
+		    0x08000000);
 	unmap_physmem(loaded_firmware, MAP_NOCACHE);
 
 	/* Invalid ELF Magic */